CPUID Patch for IDT Winchip
Uros Bizjak
ubizjak@gmail.com
Tue May 21 07:46:00 GMT 2019
On Tue, May 21, 2019 at 12:20 AM tedheadster <tedheadster@gmail.com> wrote:
>
> On Mon, May 20, 2019 at 2:57 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Mon, May 20, 2019 at 6:12 PM tedheadster <tedheadster@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.
-------------- next part --------------
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" \
More information about the Gcc-patches
mailing list