cpu: use xgetbv intrinsic
Fixes golang/go#53302
Change-Id: I698ef44f90e2ec538ae4a057134c22c102a87ff8
Reviewed-on: https://go-review.googlesource.com/c/sys/+/411635
Auto-Submit: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@google.com>
diff --git a/cpu/cpu_gccgo_x86.c b/cpu/cpu_gccgo_x86.c
index e363c7d..a4605e6 100644
--- a/cpu/cpu_gccgo_x86.c
+++ b/cpu/cpu_gccgo_x86.c
@@ -7,6 +7,7 @@
#include <cpuid.h>
#include <stdint.h>
+#include <x86intrin.h>
// Need to wrap __get_cpuid_count because it's declared as static.
int
@@ -17,27 +18,21 @@
return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx);
}
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#pragma GCC push_options
+#pragma GCC target("xsave")
+#pragma clang attribute push (__attribute__((target("xsave"))), apply_to=function)
+
// xgetbv reads the contents of an XCR (Extended Control Register)
// specified in the ECX register into registers EDX:EAX.
// Currently, the only supported value for XCR is 0.
-//
-// TODO: Replace with a better alternative:
-//
-// #include <xsaveintrin.h>
-//
-// #pragma GCC target("xsave")
-//
-// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) {
-// unsigned long long x = _xgetbv(0);
-// *eax = x & 0xffffffff;
-// *edx = (x >> 32) & 0xffffffff;
-// }
-//
-// Note that _xgetbv is defined starting with GCC 8.
void
gccgoXgetbv(uint32_t *eax, uint32_t *edx)
{
- __asm(" xorl %%ecx, %%ecx\n"
- " xgetbv"
- : "=a"(*eax), "=d"(*edx));
+ uint64_t v = _xgetbv(0);
+ *eax = v & 0xffffffff;
+ *edx = v >> 32;
}
+
+#pragma clang attribute pop
+#pragma GCC pop_options