r218173 - Fix bugs in cpuid.h.

Akira Hatanaka ahatanaka at apple.com
Fri Sep 19 18:31:09 PDT 2014


Author: ahatanak
Date: Fri Sep 19 20:31:09 2014
New Revision: 218173

URL: http://llvm.org/viewvc/llvm-project?rev=218173&view=rev
Log:
Fix bugs in cpuid.h.

This commit makes two changes:

- Remove the push and pop instructions that were saving and restoring %ebx
  before and after cpuid in 32-bit pic mode. We were doing this to ensure we
  don't lose the GOT address in pic register %ebx, but this isn't necessary
  because the GOT address is kept in a virtual register.

- In 64-bit mode, preserve base register %rbx around cpuid.

This fixes PR20311 and rdar://problem/17686779.

Added:
    cfe/trunk/test/Headers/cpuid.c
Modified:
    cfe/trunk/lib/Headers/cpuid.h

Modified: cfe/trunk/lib/Headers/cpuid.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/cpuid.h?rev=218173&r1=218172&r2=218173&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/cpuid.h (original)
+++ cfe/trunk/lib/Headers/cpuid.h Fri Sep 19 20:31:09 2014
@@ -92,31 +92,29 @@
 #define bit_SMEP        0x00000080
 #define bit_ENH_MOVSB   0x00000200
 
-/* PIC on i386 uses %ebx, so preserve it. */
 #if __i386__
 #define __cpuid(__level, __eax, __ebx, __ecx, __edx) \
-    __asm("  pushl  %%ebx\n" \
+    __asm("cpuid" : "=a"(__eax), "=b" (__ebx), "=c"(__ecx), "=d"(__edx) \
+                  : "0"(__level))
+
+#define __cpuid_count(__level, __count, __eax, __ebx, __ecx, __edx) \
+    __asm("cpuid" : "=a"(__eax), "=b" (__ebx), "=c"(__ecx), "=d"(__edx) \
+                  : "0"(__level), "2"(__count))
+#else
+/* x86-64 uses %rbx as the base register, so preserve it. */
+#define __cpuid(__level, __eax, __ebx, __ecx, __edx) \
+    __asm("  xchgq  %%rbx,%q1\n" \
           "  cpuid\n" \
-          "  mov    %%ebx,%1\n" \
-          "  popl   %%ebx" \
+          "  xchgq  %%rbx,%q1" \
         : "=a"(__eax), "=r" (__ebx), "=c"(__ecx), "=d"(__edx) \
         : "0"(__level))
 
 #define __cpuid_count(__level, __count, __eax, __ebx, __ecx, __edx) \
-    __asm("  pushl  %%ebx\n" \
+    __asm("  xchgq  %%rbx,%q1\n" \
           "  cpuid\n" \
-          "  mov    %%ebx,%1\n" \
-          "  popl   %%ebx" \
+          "  xchgq  %%rbx,%q1" \
         : "=a"(__eax), "=r" (__ebx), "=c"(__ecx), "=d"(__edx) \
         : "0"(__level), "2"(__count))
-#else
-#define __cpuid(__level, __eax, __ebx, __ecx, __edx) \
-    __asm("cpuid" : "=a"(__eax), "=b" (__ebx), "=c"(__ecx), "=d"(__edx) \
-                  : "0"(__level))
-
-#define __cpuid_count(__level, __count, __eax, __ebx, __ecx, __edx) \
-    __asm("cpuid" : "=a"(__eax), "=b" (__ebx), "=c"(__ecx), "=d"(__edx) \
-                  : "0"(__level), "2"(__count))
 #endif
 
 static __inline int __get_cpuid (unsigned int __level, unsigned int *__eax,

Added: cfe/trunk/test/Headers/cpuid.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Headers/cpuid.c?rev=218173&view=auto
==============================================================================
--- cfe/trunk/test/Headers/cpuid.c (added)
+++ cfe/trunk/test/Headers/cpuid.c Fri Sep 19 20:31:09 2014
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-64
+// RUN: %clang_cc1 %s -ffreestanding -triple i386 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-32
+
+#include <cpuid.h>
+
+// CHECK-64: {{.*}} call { i32, i32, i32, i32 } asm "  xchgq  %rbx,${1:q}\0A cpuid\0A xchgq %rbx,${1:q}", "={ax},=r,={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}})
+// CHECK-64: {{.*}} call { i32, i32, i32, i32 } asm "  xchgq  %rbx,${1:q}\0A  cpuid\0A  xchgq  %rbx,${1:q}", "={ax},=r,={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}}, i32 %{{[a-z0-9]+}})
+
+// CHECK-32: {{.*}} call { i32, i32, i32, i32 } asm "cpuid", "={ax},={bx},={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}})
+// CHECK-32: {{.*}} call { i32, i32, i32, i32 } asm "cpuid", "={ax},={bx},={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}}, i32 %{{[a-z0-9]+}})
+
+unsigned eax0, ebx0, ecx0, edx0;
+unsigned eax1, ebx1, ecx1, edx1;
+
+void test_cpuid(unsigned level, unsigned count) {
+  __cpuid(level, eax1, ebx1, ecx1, edx1);
+  __cpuid_count(level, count, eax0, ebx0, ecx0, edx0);
+}





More information about the cfe-commits mailing list