mirror of git://gcc.gnu.org/git/gcc.git
73 lines
1.6 KiB
C
73 lines
1.6 KiB
C
// Copyright 2018 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
#include <stdint.h>
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
|
#include <cpuid.h>
|
|
#include <x86intrin.h>
|
|
#endif
|
|
|
|
#include "runtime.h"
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
|
|
|
struct cpuid_ret {
|
|
uint32_t eax;
|
|
uint32_t ebx;
|
|
uint32_t ecx;
|
|
uint32_t edx;
|
|
};
|
|
|
|
struct cpuid_ret cpuid(uint32_t, uint32_t)
|
|
__asm__(GOSYM_PREFIX "internal..z2fcpu.cpuid")
|
|
__attribute__((no_split_stack));
|
|
|
|
struct cpuid_ret cpuid(uint32_t eaxArg, uint32_t ecxArg) {
|
|
unsigned int eax = 0;
|
|
unsigned int ebx = 0;
|
|
unsigned int ecx = 0;
|
|
unsigned int edx = 0;
|
|
struct cpuid_ret ret;
|
|
|
|
__get_cpuid_count(eaxArg, ecxArg, &eax, &ebx, &ecx, &edx);
|
|
ret.eax = (uint32_t)(eax);
|
|
ret.ebx = (uint32_t)(ebx);
|
|
ret.ecx = (uint32_t)(ecx);
|
|
ret.edx = (uint32_t)(edx);
|
|
return ret;
|
|
}
|
|
|
|
struct xgetbv_ret {
|
|
uint32_t eax;
|
|
uint32_t edx;
|
|
};
|
|
|
|
struct xgetbv_ret xgetbv(void)
|
|
__asm__(GOSYM_PREFIX "internal..z2fcpu.xgetbv")
|
|
__attribute__((no_split_stack));
|
|
|
|
#pragma GCC push_options
|
|
#pragma GCC target("xsave")
|
|
|
|
struct xgetbv_ret xgetbv(void) {
|
|
struct xgetbv_ret ret;
|
|
|
|
// At some point, use call to _xgetbv() instead:
|
|
//
|
|
// long long r = _xgetbv(0);
|
|
// ret.eax = r & 0xffffffff;
|
|
// ret.edx = r >> 32;
|
|
//
|
|
unsigned int __eax, __edx, __xcr_no = 0;
|
|
__asm__ ("xgetbv" : "=a" (__eax), "=d" (__edx) : "c" (__xcr_no));
|
|
ret.eax = __eax;
|
|
ret.edx = __edx;
|
|
return ret;
|
|
}
|
|
|
|
#pragma GCC pop_options
|
|
|
|
#endif /* defined(__i386__) || defined(__x86_64__) */
|