// 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 #if defined(__i386__) || defined(__x86_64__) #include #include #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__) */