[PATCH] D70101: [X86] Fix the implementation of __readcr3/__writecr3 to work in 64-bit mode

Craig Topper via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 11 15:14:44 PST 2019


craig.topper created this revision.
craig.topper added reviewers: rnk, thakis.

We need to use a 64-bit type in 64-bit mode so a 64-bit register will get used in the generated assembly. I've also changed the constraints to just use "r" intead of "q". "q" forces to a only an a/b/c/d register in 32-bit mode, but I see no reason that would matter here. Still not sure why in 32-bit mode one uses long and the other uses int, but I'm just going to leave that alone.

Fixes Nico's note in PR19301 over 4 years ago.


https://reviews.llvm.org/D70101

Files:
  clang/lib/Headers/intrin.h
  clang/test/Headers/ms-intrin.cpp


Index: clang/test/Headers/ms-intrin.cpp
===================================================================
--- clang/test/Headers/ms-intrin.cpp
+++ clang/test/Headers/ms-intrin.cpp
@@ -56,12 +56,8 @@
   __nop();
   __readmsr(0);
 
-  // FIXME: Call these in 64-bit too once the intrinsics have been fixed to
-  // work there, PR19301
-#ifndef _M_X64
   __readcr3();
   __writecr3(0);
-#endif
 
 #ifdef _M_ARM
   __dmb(_ARM_BARRIER_ISHST);
Index: clang/lib/Headers/intrin.h
===================================================================
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -94,8 +94,13 @@
 void __outwordstring(unsigned short, unsigned short *, unsigned long);
 unsigned long __readcr0(void);
 unsigned long __readcr2(void);
+#ifdef __x86_64__
+static __inline__
+unsigned __int64 __readcr3(void);
+#else
 static __inline__
 unsigned long __readcr3(void);
+#endif
 unsigned long __readcr4(void);
 unsigned long __readcr8(void);
 unsigned int __readdr(unsigned int);
@@ -131,8 +136,13 @@
 void __vmx_vmptrst(unsigned __int64 *);
 void __wbinvd(void);
 void __writecr0(unsigned int);
+#ifdef __x86_64__
+static __inline__
+void __writecr3(unsigned __int64);
+#else
 static __inline__
 void __writecr3(unsigned int);
+#endif
 void __writecr4(unsigned int);
 void __writecr8(unsigned int);
 void __writedr(unsigned int, unsigned int);
@@ -565,17 +575,31 @@
   __asm__ ("rdmsr" : "=d"(__edx), "=a"(__eax) : "c"(__register));
   return (((unsigned __int64)__edx) << 32) | (unsigned __int64)__eax;
 }
+#endif
+
+#ifdef __x86_64__
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
+__readcr3(void) {
+  unsigned __int64 __cr3_val;
+  __asm__ __volatile__ ("mov %%cr3, %0" : "=r"(__cr3_val) : : "memory");
+  return __cr3_val;
+}
 
+static __inline__ void __DEFAULT_FN_ATTRS
+__writecr3(unsigned __int64 __cr3_val) {
+  __asm__ ("mov %0, %%cr3" : : "r"(__cr3_val) : "memory");
+}
+#else
 static __inline__ unsigned long __DEFAULT_FN_ATTRS
 __readcr3(void) {
   unsigned long __cr3_val;
-  __asm__ __volatile__ ("mov %%cr3, %0" : "=q"(__cr3_val) : : "memory");
+  __asm__ __volatile__ ("mov %%cr3, %0" : "=r"(__cr3_val) : : "memory");
   return __cr3_val;
 }
 
 static __inline__ void __DEFAULT_FN_ATTRS
 __writecr3(unsigned int __cr3_val) {
-  __asm__ ("mov %0, %%cr3" : : "q"(__cr3_val) : "memory");
+  __asm__ ("mov %0, %%cr3" : : "r"(__cr3_val) : "memory");
 }
 #endif
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70101.228773.patch
Type: text/x-patch
Size: 2404 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191111/2224217e/attachment.bin>


More information about the llvm-commits mailing list