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