aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/internal/cpu/cpu_x86.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/internal/cpu/cpu_x86.go')
-rw-r--r--libgo/go/internal/cpu/cpu_x86.go60
1 files changed, 59 insertions, 1 deletions
diff --git a/libgo/go/internal/cpu/cpu_x86.go b/libgo/go/internal/cpu/cpu_x86.go
index eceeb44..62853a1 100644
--- a/libgo/go/internal/cpu/cpu_x86.go
+++ b/libgo/go/internal/cpu/cpu_x86.go
@@ -36,6 +36,8 @@ const (
cpuid_ADX = 1 << 19
)
+var maxExtendedFunctionInformation uint32
+
func doinit() {
options = []option{
{Name: "adx", Feature: &X86.HasADX},
@@ -63,19 +65,30 @@ func doinit() {
return
}
+ maxExtendedFunctionInformation, _, _, _ = cpuid(0x80000000, 0)
+
_, _, ecx1, edx1 := cpuid(1, 0)
X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
X86.HasSSE3 = isSet(ecx1, cpuid_SSE3)
X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ)
X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3)
- X86.HasFMA = isSet(ecx1, cpuid_FMA)
X86.HasSSE41 = isSet(ecx1, cpuid_SSE41)
X86.HasSSE42 = isSet(ecx1, cpuid_SSE42)
X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT)
X86.HasAES = isSet(ecx1, cpuid_AES)
+
+ // OSXSAVE can be false when using older Operating Systems
+ // or when explicitly disabled on newer Operating Systems by
+ // e.g. setting the xsavedisable boot option on Windows 10.
X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE)
+ // The FMA instruction set extension only has VEX prefixed instructions.
+ // VEX prefixed instructions require OSXSAVE to be enabled.
+ // See Intel 64 and IA-32 Architecture Software Developer’s Manual Volume 2
+ // Section 2.4 "AVX and SSE Instruction Exception Specification"
+ X86.HasFMA = isSet(ecx1, cpuid_FMA) && X86.HasOSXSAVE
+
osSupportsAVX := false
// For XGETBV, OSXSAVE bit is required and sufficient.
if X86.HasOSXSAVE {
@@ -101,3 +114,48 @@ func doinit() {
func isSet(hwc uint32, value uint32) bool {
return hwc&value != 0
}
+
+// Name returns the CPU name given by the vendor.
+// If the CPU name can not be determined an
+// empty string is returned.
+func Name() string {
+ if maxExtendedFunctionInformation < 0x80000004 {
+ return ""
+ }
+
+ data := make([]byte, 0, 3*4*4)
+
+ var eax, ebx, ecx, edx uint32
+ eax, ebx, ecx, edx = cpuid(0x80000002, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+ eax, ebx, ecx, edx = cpuid(0x80000003, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+ eax, ebx, ecx, edx = cpuid(0x80000004, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+
+ // Trim leading spaces.
+ for len(data) > 0 && data[0] == ' ' {
+ data = data[1:]
+ }
+
+ // Trim tail after and including the first null byte.
+ for i, c := range data {
+ if c == '\x00' {
+ data = data[:i]
+ break
+ }
+ }
+
+ return string(data)
+}
+
+func appendBytes(b []byte, args ...uint32) []byte {
+ for _, arg := range args {
+ b = append(b,
+ byte((arg >> 0)),
+ byte((arg >> 8)),
+ byte((arg >> 16)),
+ byte((arg >> 24)))
+ }
+ return b
+}