libgo: use inline assembly in favor of call to _xgetbv()
[official-gcc.git] / libgo / go / internal / cpu / cpu_gccgo.c
blob1d5b492a7877f762e1bc3c920c490a9a3819b60d
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 #include <stdint.h>
7 #if defined(__i386__) || defined(__x86_64__)
8 #include <cpuid.h>
9 #include <x86intrin.h>
10 #endif
12 #include "runtime.h"
14 #if defined(__i386__) || defined(__x86_64__)
16 struct cpuid_ret {
17 uint32_t eax;
18 uint32_t ebx;
19 uint32_t ecx;
20 uint32_t edx;
23 struct cpuid_ret cpuid(uint32_t, uint32_t)
24 __asm__(GOSYM_PREFIX "internal_cpu.cpuid")
25 __attribute__((no_split_stack));
27 struct cpuid_ret cpuid(uint32_t eaxArg, uint32_t ecxArg) {
28 unsigned int eax = 0;
29 unsigned int ebx = 0;
30 unsigned int ecx = 0;
31 unsigned int edx = 0;
32 struct cpuid_ret ret;
34 __get_cpuid_count(eaxArg, ecxArg, &eax, &ebx, &ecx, &edx);
35 ret.eax = (uint32_t)(eax);
36 ret.ebx = (uint32_t)(ebx);
37 ret.ecx = (uint32_t)(ecx);
38 ret.edx = (uint32_t)(edx);
39 return ret;
42 struct xgetbv_ret {
43 uint32_t eax;
44 uint32_t edx;
47 struct xgetbv_ret xgetbv(void)
48 __asm__(GOSYM_PREFIX "internal_cpu.xgetbv")
49 __attribute__((no_split_stack));
51 #pragma GCC push_options
52 #pragma GCC target("xsave")
54 struct xgetbv_ret xgetbv(void) {
55 struct xgetbv_ret ret;
57 // At some point, use call to _xgetbv() instead:
59 // long long r = _xgetbv(0);
60 // ret.eax = r & 0xffffffff;
61 // ret.edx = r >> 32;
63 unsigned int __eax, __edx, __xcr_no = 0;
64 __asm__ ("xgetbv" : "=a" (__eax), "=d" (__edx) : "c" (__xcr_no));
65 ret.eax = __eax;
66 ret.edx = __edx;
67 return ret;
70 #pragma GCC pop_options
72 #endif /* defined(__i386__) || defined(__x86_64__) */