aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Headers/x86gprintrin.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Headers/x86gprintrin.h')
-rw-r--r--clang/lib/Headers/x86gprintrin.h28
1 files changed, 23 insertions, 5 deletions
diff --git a/clang/lib/Headers/x86gprintrin.h b/clang/lib/Headers/x86gprintrin.h
index 01e741f1eb61..2c2fbb97c9ac 100644
--- a/clang/lib/Headers/x86gprintrin.h
+++ b/clang/lib/Headers/x86gprintrin.h
@@ -25,11 +25,29 @@
#include <crc32intrin.h>
#endif
-#define __SSC_MARK(Tag) \
- __asm__ __volatile__("mov {%%ebx, %%eax|eax, ebx}; " \
- "mov {%0, %%ebx|ebx, %0}; " \
+#if defined(__i386__)
+#define __FULLBX "ebx"
+#define __TMPGPR "eax"
+#else
+// When in 64-bit target, the 32-bit operands generate a 32-bit result,
+// zero-extended to a 64-bit result in the destination general-purpose,
+// It means "mov x %ebx" will clobber the higher 32 bits of rbx, so we
+// should preserve the 64-bit register rbx.
+#define __FULLBX "rbx"
+#define __TMPGPR "rax"
+#endif
+
+#define __MOVEGPR(__r1, __r2) "mov {%%"__r1 ", %%"__r2 "|"__r2 ", "__r1"};"
+
+#define __SAVE_GPRBX __MOVEGPR(__FULLBX, __TMPGPR)
+#define __RESTORE_GPRBX __MOVEGPR(__TMPGPR, __FULLBX)
+
+#define __SSC_MARK(__Tag) \
+ __asm__ __volatile__( __SAVE_GPRBX \
+ "mov {%0, %%ebx|ebx, %0}; " \
".byte 0x64, 0x67, 0x90; " \
- "mov {%%eax, %%ebx|ebx, eax};" ::"i"(Tag) \
- : "%eax");
+ __RESTORE_GPRBX \
+ ::"i"(__Tag) \
+ : __TMPGPR );
#endif /* __X86GPRINTRIN_H */