mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Part 1: CL 199499 (GOOS nacl)
Part 2: CL 200077 (amd64p32 files, toolchain)
Part 3: stuff that arguably should've been part of Part 2, but I forgot
one of my grep patterns when splitting the original CL up into
two parts.
This one might also have interesting stuff to resurrect for any future
x32 ABI support.
Updates #30439
Change-Id: I2b4143374a253a003666f3c69e776b7e456bdb9c
Reviewed-on: https://go-review.googlesource.com/c/go/+/200318
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
105 lines
2.7 KiB
Go
105 lines
2.7 KiB
Go
// Copyright 2017 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.
|
|
|
|
// +build 386 amd64
|
|
|
|
package cpu
|
|
|
|
const CacheLinePadSize = 64
|
|
|
|
// cpuid is implemented in cpu_x86.s.
|
|
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
|
|
|
|
// xgetbv with ecx = 0 is implemented in cpu_x86.s.
|
|
func xgetbv() (eax, edx uint32)
|
|
|
|
const (
|
|
// edx bits
|
|
cpuid_SSE2 = 1 << 26
|
|
|
|
// ecx bits
|
|
cpuid_SSE3 = 1 << 0
|
|
cpuid_PCLMULQDQ = 1 << 1
|
|
cpuid_SSSE3 = 1 << 9
|
|
cpuid_FMA = 1 << 12
|
|
cpuid_SSE41 = 1 << 19
|
|
cpuid_SSE42 = 1 << 20
|
|
cpuid_POPCNT = 1 << 23
|
|
cpuid_AES = 1 << 25
|
|
cpuid_OSXSAVE = 1 << 27
|
|
cpuid_AVX = 1 << 28
|
|
|
|
// ebx bits
|
|
cpuid_BMI1 = 1 << 3
|
|
cpuid_AVX2 = 1 << 5
|
|
cpuid_BMI2 = 1 << 8
|
|
cpuid_ERMS = 1 << 9
|
|
cpuid_ADX = 1 << 19
|
|
)
|
|
|
|
func doinit() {
|
|
options = []option{
|
|
{Name: "adx", Feature: &X86.HasADX},
|
|
{Name: "aes", Feature: &X86.HasAES},
|
|
{Name: "avx", Feature: &X86.HasAVX},
|
|
{Name: "avx2", Feature: &X86.HasAVX2},
|
|
{Name: "bmi1", Feature: &X86.HasBMI1},
|
|
{Name: "bmi2", Feature: &X86.HasBMI2},
|
|
{Name: "erms", Feature: &X86.HasERMS},
|
|
{Name: "fma", Feature: &X86.HasFMA},
|
|
{Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ},
|
|
{Name: "popcnt", Feature: &X86.HasPOPCNT},
|
|
{Name: "sse3", Feature: &X86.HasSSE3},
|
|
{Name: "sse41", Feature: &X86.HasSSE41},
|
|
{Name: "sse42", Feature: &X86.HasSSE42},
|
|
{Name: "ssse3", Feature: &X86.HasSSSE3},
|
|
|
|
// These capabilities should always be enabled on amd64:
|
|
{Name: "sse2", Feature: &X86.HasSSE2, Required: GOARCH == "amd64"},
|
|
}
|
|
|
|
maxID, _, _, _ := cpuid(0, 0)
|
|
|
|
if maxID < 1 {
|
|
return
|
|
}
|
|
|
|
_, _, 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)
|
|
X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE)
|
|
|
|
osSupportsAVX := false
|
|
// For XGETBV, OSXSAVE bit is required and sufficient.
|
|
if X86.HasOSXSAVE {
|
|
eax, _ := xgetbv()
|
|
// Check if XMM and YMM registers have OS support.
|
|
osSupportsAVX = isSet(eax, 1<<1) && isSet(eax, 1<<2)
|
|
}
|
|
|
|
X86.HasAVX = isSet(ecx1, cpuid_AVX) && osSupportsAVX
|
|
|
|
if maxID < 7 {
|
|
return
|
|
}
|
|
|
|
_, ebx7, _, _ := cpuid(7, 0)
|
|
X86.HasBMI1 = isSet(ebx7, cpuid_BMI1)
|
|
X86.HasAVX2 = isSet(ebx7, cpuid_AVX2) && osSupportsAVX
|
|
X86.HasBMI2 = isSet(ebx7, cpuid_BMI2)
|
|
X86.HasERMS = isSet(ebx7, cpuid_ERMS)
|
|
X86.HasADX = isSet(ebx7, cpuid_ADX)
|
|
}
|
|
|
|
func isSet(hwc uint32, value uint32) bool {
|
|
return hwc&value != 0
|
|
}
|