On Tue, May 21, 2019 at 12:20 AM tedheadster <tedheads...@gmail.com> wrote: > > On Mon, May 20, 2019 at 2:57 PM Uros Bizjak <ubiz...@gmail.com> wrote: > > > > On Mon, May 20, 2019 at 6:12 PM tedheadster <tedheads...@gmail.com> wrote: > > > Did you instead mean "zeroing %EBX and %ECX regs should be enough"? > > > > Ah, yes. This is what I meant to say. The patch clears %ebx and %ecx. > > > > Uros, > your patch worked on real 32-bit hardware. The assembly output is > nearly identical to mine, with merely a re-ordering when setting the > %eax, %ebx, and %ecx registers.
Attached patch fixes the core of the problem. We can change __cpuid itself to use zeroing, unless we can prove that we use constant argument, different than 1. __cpuid is mostly used with constant argument, so constant propagation does its job. As an example: --cut here-- #include "cpuid.h" int main () { unsigned int eax, ebx, ecx, edx; if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) __builtin_abort (); printf ("%#x, %#x, %#x, %#x\n", eax, ebx, ecx, edx); return 0; } --cut here-- results in: 2f: 31 f6 xor %esi,%esi 31: 89 f0 mov %esi,%eax 33: 0f a2 cpuid 35: 85 c0 test %eax,%eax 37: 0f 84 fc ff ff ff je 39 <main+0x39> 3d: 83 ec 0c sub $0xc,%esp 40: 89 f3 mov %esi,%ebx 42: 89 f1 mov %esi,%ecx 44: b8 01 00 00 00 mov $0x1,%eax 49: 0f a2 cpuid Uros.
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h index 8ddd425c8b7e..1d6ef335e76d 100644 --- a/gcc/config/i386/cpuid.h +++ b/gcc/config/i386/cpuid.h @@ -187,10 +187,27 @@ #define signature_VORTEX_ecx 0x436f5320 #define signature_VORTEX_edx 0x36387865 +#ifndef __x86_64__ +/* At least one cpu (Winchip 2) does not set %ebx and %ecx + for cpuid leaf 1. Forcibly zero the two registers before + calling cpuid as a precaution. */ +#define __cpuid(level, a, b, c, d) \ + do { \ + if (__builtin_constant_p (level) && (level) != 1) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)); \ + else \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level), "1" (0), "2" (0)); \ + } while (0) +#else #define __cpuid(level, a, b, c, d) \ __asm__ ("cpuid\n\t" \ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ : "0" (level)) +#endif #define __cpuid_count(level, count, a, b, c, d) \ __asm__ ("cpuid\n\t" \