...

Source file src/pkg/internal/cpu/cpu_x86.go

     1	// Copyright 2017 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.
     4	
     5	// +build 386 amd64 amd64p32
     6	
     7	package cpu
     8	
     9	const CacheLinePadSize = 64
    10	
    11	// cpuid is implemented in cpu_x86.s.
    12	func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
    13	
    14	// xgetbv with ecx = 0 is implemented in cpu_x86.s.
    15	func xgetbv() (eax, edx uint32)
    16	
    17	const (
    18		// edx bits
    19		cpuid_SSE2 = 1 << 26
    20	
    21		// ecx bits
    22		cpuid_SSE3      = 1 << 0
    23		cpuid_PCLMULQDQ = 1 << 1
    24		cpuid_SSSE3     = 1 << 9
    25		cpuid_FMA       = 1 << 12
    26		cpuid_SSE41     = 1 << 19
    27		cpuid_SSE42     = 1 << 20
    28		cpuid_POPCNT    = 1 << 23
    29		cpuid_AES       = 1 << 25
    30		cpuid_OSXSAVE   = 1 << 27
    31		cpuid_AVX       = 1 << 28
    32	
    33		// ebx bits
    34		cpuid_BMI1 = 1 << 3
    35		cpuid_AVX2 = 1 << 5
    36		cpuid_BMI2 = 1 << 8
    37		cpuid_ERMS = 1 << 9
    38		cpuid_ADX  = 1 << 19
    39	)
    40	
    41	func doinit() {
    42		options = []option{
    43			{Name: "adx", Feature: &X86.HasADX},
    44			{Name: "aes", Feature: &X86.HasAES},
    45			{Name: "avx", Feature: &X86.HasAVX},
    46			{Name: "avx2", Feature: &X86.HasAVX2},
    47			{Name: "bmi1", Feature: &X86.HasBMI1},
    48			{Name: "bmi2", Feature: &X86.HasBMI2},
    49			{Name: "erms", Feature: &X86.HasERMS},
    50			{Name: "fma", Feature: &X86.HasFMA},
    51			{Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ},
    52			{Name: "popcnt", Feature: &X86.HasPOPCNT},
    53			{Name: "sse3", Feature: &X86.HasSSE3},
    54			{Name: "sse41", Feature: &X86.HasSSE41},
    55			{Name: "sse42", Feature: &X86.HasSSE42},
    56			{Name: "ssse3", Feature: &X86.HasSSSE3},
    57	
    58			// These capabilities should always be enabled on amd64(p32):
    59			{Name: "sse2", Feature: &X86.HasSSE2, Required: GOARCH == "amd64" || GOARCH == "amd64p32"},
    60		}
    61	
    62		maxID, _, _, _ := cpuid(0, 0)
    63	
    64		if maxID < 1 {
    65			return
    66		}
    67	
    68		_, _, ecx1, edx1 := cpuid(1, 0)
    69		X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
    70	
    71		X86.HasSSE3 = isSet(ecx1, cpuid_SSE3)
    72		X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ)
    73		X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3)
    74		X86.HasFMA = isSet(ecx1, cpuid_FMA)
    75		X86.HasSSE41 = isSet(ecx1, cpuid_SSE41)
    76		X86.HasSSE42 = isSet(ecx1, cpuid_SSE42)
    77		X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT)
    78		X86.HasAES = isSet(ecx1, cpuid_AES)
    79		X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE)
    80	
    81		osSupportsAVX := false
    82		// For XGETBV, OSXSAVE bit is required and sufficient.
    83		if X86.HasOSXSAVE {
    84			eax, _ := xgetbv()
    85			// Check if XMM and YMM registers have OS support.
    86			osSupportsAVX = isSet(eax, 1<<1) && isSet(eax, 1<<2)
    87		}
    88	
    89		X86.HasAVX = isSet(ecx1, cpuid_AVX) && osSupportsAVX
    90	
    91		if maxID < 7 {
    92			return
    93		}
    94	
    95		_, ebx7, _, _ := cpuid(7, 0)
    96		X86.HasBMI1 = isSet(ebx7, cpuid_BMI1)
    97		X86.HasAVX2 = isSet(ebx7, cpuid_AVX2) && osSupportsAVX
    98		X86.HasBMI2 = isSet(ebx7, cpuid_BMI2)
    99		X86.HasERMS = isSet(ebx7, cpuid_ERMS)
   100		X86.HasADX = isSet(ebx7, cpuid_ADX)
   101	}
   102	
   103	func isSet(hwc uint32, value uint32) bool {
   104		return hwc&value != 0
   105	}
   106	

View as plain text