Commit 5a6c5809 authored by Martin Möhrmann's avatar Martin Möhrmann

runtime: refactor cpu feature detection for 386 & amd64

Changes all cpu features to be detected and stored in bools in rt0_go.

Updates: #15403

Change-Id: I5a9961cdec789b331d09c44d86beb53833d5dc3e
Reviewed-on: https://go-review.googlesource.com/41950
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIlya Tocar <ilya.tocar@intel.com>
Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 1f85d3ad
......@@ -283,9 +283,9 @@ func alginit() {
// Install aes hash algorithm if we have the instructions we need
if (GOARCH == "386" || GOARCH == "amd64") &&
GOOS != "nacl" &&
cpuid_ecx&(1<<25) != 0 && // aes (aesenc)
cpuid_ecx&(1<<9) != 0 && // sse3 (pshufb)
cpuid_ecx&(1<<19) != 0 { // sse4.1 (pinsr{d,q})
support_aes && // AESENC
support_ssse3 && // PSHUFB
support_sse41 { // PINSR{D,Q}
useAeshash = true
algarray[alg_MEM32].hash = aeshash32
algarray[alg_MEM64].hash = aeshash64
......
......@@ -75,24 +75,81 @@ notintel:
MOVL $1, AX
CPUID
MOVL CX, DI // Move to global variable clobbers CX when generating PIC
MOVL AX, runtime·cpuid_eax(SB)
MOVL AX, runtime·processorVersionInfo(SB)
MOVL DI, runtime·cpuid_ecx(SB)
MOVL DX, runtime·cpuid_edx(SB)
// Check for MMX support
TESTL $(1<<23), DX // MMX
JZ bad_proc
TESTL $(1<<23), DX // MMX
JZ bad_proc
TESTL $(1<<26), DX // SSE2
SETNE runtime·support_sse2(SB)
TESTL $(1<<9), DI // SSSE3
SETNE runtime·support_ssse3(SB)
TESTL $(1<<19), DI // SSE4.1
SETNE runtime·support_sse41(SB)
TESTL $(1<<20), DI // SSE4.2
SETNE runtime·support_sse42(SB)
TESTL $(1<<23), DI // POPCNT
SETNE runtime·support_popcnt(SB)
TESTL $(1<<25), DI // AES
SETNE runtime·support_aes(SB)
TESTL $(1<<27), DI // OSXSAVE
SETNE runtime·support_osxsave(SB)
// If OS support for XMM and YMM is not present
// support_avx will be set back to false later.
TESTL $(1<<28), DI // AVX
SETNE runtime·support_avx(SB)
eax7:
// Load EAX=7/ECX=0 cpuid flags
CMPL SI, $7
JLT nocpuinfo
JLT osavx
MOVL $7, AX
MOVL $0, CX
CPUID
MOVL BX, runtime·cpuid_ebx7(SB)
nocpuinfo:
TESTL $(1<<3), BX // BMI1
SETNE runtime·support_bmi1(SB)
// If OS support for XMM and YMM is not present
// support_avx2 will be set back to false later.
TESTL $(1<<5), BX
SETNE runtime·support_avx2(SB)
TESTL $(1<<8), BX // BMI2
SETNE runtime·support_bmi2(SB)
TESTL $(1<<9), BX // ERMS
SETNE runtime·support_erms(SB)
osavx:
// nacl does not support XGETBV to test
// for XMM and YMM OS support.
#ifndef GOOS_nacl
CMPB runtime·support_osxsave(SB), $1
JNE noavx
MOVL $0, CX
// For XGETBV, OSXSAVE bit is required and sufficient
XGETBV
ANDL $6, AX
CMPL AX, $6 // Check for OS support of XMM and YMM registers.
JE nocpuinfo
#endif
noavx:
MOVB $0, runtime·support_avx(SB)
MOVB $0, runtime·support_avx2(SB)
nocpuinfo:
// if there is an _cgo_init, call it to let it
// initialize and to set up GS. if not,
// we set up GS ourselves.
......@@ -803,8 +860,8 @@ TEXT runtime·getcallerpc(SB),NOSPLIT,$4-8
// func cputicks() int64
TEXT runtime·cputicks(SB),NOSPLIT,$0-8
TESTL $0x4000000, runtime·cpuid_edx(SB) // no sse2, no mfence
JEQ done
CMPB runtime·support_sse2(SB), $1
JNE done
CMPB runtime·lfenceBeforeRdtsc(SB), $1
JNE mfence
BYTE $0x0f; BYTE $0xae; BYTE $0xe8 // LFENCE
......@@ -1311,8 +1368,8 @@ TEXT runtime·memeqbody(SB),NOSPLIT,$0-0
hugeloop:
CMPL BX, $64
JB bigloop
TESTL $0x4000000, runtime·cpuid_edx(SB) // check for sse2
JE bigloop
CMPB runtime·support_sse2(SB), $1
JNE bigloop
MOVOU (SI), X0
MOVOU (DI), X1
MOVOU 16(SI), X2
......@@ -1455,8 +1512,8 @@ TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
JEQ allsame
CMPL BP, $4
JB small
TESTL $0x4000000, runtime·cpuid_edx(SB) // check for sse2
JE mediumloop
CMPB runtime·support_sse2(SB), $1
JNE mediumloop
largeloop:
CMPL BP, $16
JB mediumloop
......
......@@ -26,10 +26,10 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
MOVQ SP, (g_stack+stack_hi)(DI)
// find out information about the processor we're on
MOVQ $0, AX
MOVL $0, AX
CPUID
MOVQ AX, SI
CMPQ AX, $0
MOVL AX, SI
CMPL AX, $0
JE nocpuinfo
// Figure out how to serialize RDTSC.
......@@ -46,62 +46,75 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
notintel:
// Load EAX=1 cpuid flags
MOVQ $1, AX
MOVL $1, AX
CPUID
MOVL AX, runtime·cpuid_eax(SB)
MOVL AX, runtime·processorVersionInfo(SB)
MOVL CX, runtime·cpuid_ecx(SB)
MOVL DX, runtime·cpuid_edx(SB)
TESTL $(1<<26), DX // SSE2
SETNE runtime·support_sse2(SB)
TESTL $(1<<9), CX // SSSE3
SETNE runtime·support_ssse3(SB)
TESTL $(1<<19), CX // SSE4.1
SETNE runtime·support_sse41(SB)
TESTL $(1<<20), CX // SSE4.2
SETNE runtime·support_sse42(SB)
TESTL $(1<<23), CX // POPCNT
SETNE runtime·support_popcnt(SB)
TESTL $(1<<25), CX // AES
SETNE runtime·support_aes(SB)
TESTL $(1<<27), CX // OSXSAVE
SETNE runtime·support_osxsave(SB)
// If OS support for XMM and YMM is not present
// support_avx will be set back to false later.
TESTL $(1<<28), CX // AVX
SETNE runtime·support_avx(SB)
eax7:
// Load EAX=7/ECX=0 cpuid flags
CMPQ SI, $7
JLT no7
CMPL SI, $7
JLT osavx
MOVL $7, AX
MOVL $0, CX
CPUID
MOVL BX, runtime·cpuid_ebx7(SB)
no7:
// Detect AVX and AVX2 as per 14.7.1 Detection of AVX2 chapter of [1]
// [1] 64-ia-32-architectures-software-developer-manual-325462.pdf
// http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
MOVL runtime·cpuid_ecx(SB), CX
ANDL $0x18000000, CX // check for OSXSAVE and AVX bits
CMPL CX, $0x18000000
JNE noavx
MOVL $0, CX
TESTL $(1<<3), BX // BMI1
SETNE runtime·support_bmi1(SB)
// If OS support for XMM and YMM is not present
// support_avx2 will be set back to false later.
TESTL $(1<<5), BX
SETNE runtime·support_avx2(SB)
TESTL $(1<<8), BX // BMI2
SETNE runtime·support_bmi2(SB)
TESTL $(1<<9), BX // ERMS
SETNE runtime·support_erms(SB)
osavx:
CMPB runtime·support_osxsave(SB), $1
JNE noavx
MOVL $0, CX
// For XGETBV, OSXSAVE bit is required and sufficient
XGETBV
ANDL $6, AX
CMPL AX, $6 // Check for OS support of YMM registers
JNE noavx
MOVB $1, runtime·support_avx(SB)
TESTL $(1<<5), runtime·cpuid_ebx7(SB) // check for AVX2 bit
JEQ noavx2
MOVB $1, runtime·support_avx2(SB)
JMP testbmi1
ANDL $6, AX
CMPL AX, $6 // Check for OS support of XMM and YMM registers.
JE nocpuinfo
noavx:
MOVB $0, runtime·support_avx(SB)
noavx2:
MOVB $0, runtime·support_avx2(SB)
testbmi1:
// Detect BMI1 and BMI2 extensions as per
// 5.1.16.1 Detection of VEX-encoded GPR Instructions,
// LZCNT and TZCNT, PREFETCHW chapter of [1]
MOVB $0, runtime·support_bmi1(SB)
TESTL $(1<<3), runtime·cpuid_ebx7(SB) // check for BMI1 bit
JEQ testbmi2
MOVB $1, runtime·support_bmi1(SB)
testbmi2:
MOVB $0, runtime·support_bmi2(SB)
TESTL $(1<<8), runtime·cpuid_ebx7(SB) // check for BMI2 bit
JEQ testpopcnt
MOVB $1, runtime·support_bmi2(SB)
testpopcnt:
MOVB $0, runtime·support_popcnt(SB)
TESTL $(1<<23), runtime·cpuid_ecx(SB) // check for POPCNT bit
JEQ nocpuinfo
MOVB $1, runtime·support_popcnt(SB)
nocpuinfo:
MOVB $0, runtime·support_avx(SB)
MOVB $0, runtime·support_avx2(SB)
nocpuinfo:
// if there is an _cgo_init, call it.
MOVQ _cgo_init(SB), AX
TESTQ AX, AX
......@@ -1942,9 +1955,8 @@ success_avx2:
VZEROUPPER
JMP success
sse42:
MOVL runtime·cpuid_ecx(SB), CX
ANDL $0x100000, CX
JZ no_sse42
CMPB runtime·support_sse42(SB), $1
JNE no_sse42
CMPQ AX, $12
// PCMPESTRI is slower than normal compare,
// so using it makes sense only if we advance 4+ bytes per compare
......
......@@ -28,9 +28,9 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
MOVL SP, (g_stack+stack_hi)(DI)
// find out information about the processor we're on
MOVQ $0, AX
MOVL $0, AX
CPUID
CMPQ AX, $0
CMPL AX, $0
JE nocpuinfo
CMPL BX, $0x756E6547 // "Genu"
......@@ -42,13 +42,81 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
MOVB $1, runtime·isIntel(SB)
notintel:
MOVQ $1, AX
// Load EAX=1 cpuid flags
MOVL $1, AX
CPUID
MOVL AX, runtime·cpuid_eax(SB)
MOVL AX, runtime·processorVersionInfo(SB)
MOVL CX, runtime·cpuid_ecx(SB)
MOVL DX, runtime·cpuid_edx(SB)
nocpuinfo:
TESTL $(1<<26), DX // SSE2
SETNE runtime·support_sse2(SB)
TESTL $(1<<9), CX // SSSE3
SETNE runtime·support_ssse3(SB)
TESTL $(1<<19), CX // SSE4.1
SETNE runtime·support_sse41(SB)
TESTL $(1<<20), CX // SSE4.2
SETNE runtime·support_sse42(SB)
TESTL $(1<<23), CX // POPCNT
SETNE runtime·support_popcnt(SB)
TESTL $(1<<25), CX // AES
SETNE runtime·support_aes(SB)
TESTL $(1<<27), CX // OSXSAVE
SETNE runtime·support_osxsave(SB)
// If OS support for XMM and YMM is not present
// support_avx will be set back to false later.
TESTL $(1<<28), CX // AVX
SETNE runtime·support_avx(SB)
eax7:
// Load EAX=7/ECX=0 cpuid flags
CMPL SI, $7
JLT osavx
MOVL $7, AX
MOVL $0, CX
CPUID
MOVL BX, runtime·cpuid_ebx7(SB)
TESTL $(1<<3), BX // BMI1
SETNE runtime·support_bmi1(SB)
// If OS support for XMM and YMM is not present
// support_avx2 will be set back to false later.
TESTL $(1<<5), BX
SETNE runtime·support_avx2(SB)
TESTL $(1<<8), BX // BMI2
SETNE runtime·support_bmi2(SB)
TESTL $(1<<9), BX // ERMS
SETNE runtime·support_erms(SB)
osavx:
// nacl does not support XGETBV to test
// for XMM and YMM OS support.
#ifndef GOOS_nacl
CMPB runtime·support_osxsave(SB), $1
JNE noavx
MOVL $0, CX
// For XGETBV, OSXSAVE bit is required and sufficient
XGETBV
ANDL $6, AX
CMPL AX, $6 // Check for OS support of XMM and YMM registers.
JE nocpuinfo
#endif
noavx:
MOVB $0, runtime·support_avx(SB)
MOVB $0, runtime·support_avx2(SB)
nocpuinfo:
needtls:
LEAL runtime·m0+m_tls(SB), DI
CALL runtime·settls(SB)
......
......@@ -8,13 +8,13 @@ var useAVXmemmove bool
func init() {
// Let's remove stepping and reserved fields
processorVersionInfo := cpuid_eax & 0x0FFF3FF0
processor := processorVersionInfo & 0x0FFF3FF0
isIntelBridgeFamily := isIntel &&
(processorVersionInfo == 0x206A0 ||
processorVersionInfo == 0x206D0 ||
processorVersionInfo == 0x306A0 ||
processorVersionInfo == 0x306E0)
processor == 0x206A0 ||
processor == 0x206D0 ||
processor == 0x306A0 ||
processor == 0x306E0
useAVXmemmove = support_avx && !isIntelBridgeFamily
}
......@@ -27,8 +27,8 @@ tail:
JBE _5through8
CMPL BX, $16
JBE _9through16
TESTL $0x4000000, runtime·cpuid_edx(SB) // check for sse2
JEQ nosse2
CMPB runtime·support_sse2(SB), $1
JNE nosse2
PXOR X0, X0
CMPL BX, $32
JBE _17through32
......
......@@ -49,8 +49,8 @@ tail:
JBE move_5through8
CMPL BX, $16
JBE move_9through16
TESTL $0x4000000, runtime·cpuid_edx(SB) // check for sse2
JEQ nosse2
CMPB runtime·support_sse2(SB), $1
JNE nosse2
CMPL BX, $32
JBE move_17through32
CMPL BX, $64
......@@ -71,8 +71,8 @@ nosse2:
*/
forward:
// If REP MOVSB isn't fast, don't use it
TESTL $(1<<9), runtime·cpuid_ebx7(SB) // erms, aka enhanced REP MOVSB/STOSB
JEQ fwdBy4
CMPB runtime·support_erms(SB), $1 // enhanced REP MOVSB/STOSB
JNE fwdBy4
// Check alignment
MOVL SI, AX
......
......@@ -81,8 +81,8 @@ forward:
JLS move_256through2048
// If REP MOVSB isn't fast, don't use it
TESTL $(1<<9), runtime·cpuid_ebx7(SB) // erms, aka enhanced REP MOVSB/STOSB
JEQ fwdBy8
CMPB runtime·support_erms(SB), $1 // enhanced REP MOVSB/STOSB
JNE fwdBy8
// Check alignment
MOVL SI, AX
......
......@@ -728,17 +728,29 @@ var (
// Information about what cpu features are available.
// Set on startup in asm_{386,amd64,amd64p32}.s.
cpuid_eax uint32
cpuid_ecx uint32
cpuid_edx uint32
cpuid_ebx7 uint32 // not set on amd64p32
isIntel bool
lfenceBeforeRdtsc bool
support_avx bool
support_avx2 bool
support_bmi1 bool
support_bmi2 bool
support_popcnt bool
// Packages outside the runtime should not use these
// as they are not an external api.
processorVersionInfo uint32
isIntel bool
lfenceBeforeRdtsc bool
support_aes bool
support_avx bool
support_avx2 bool
support_bmi1 bool
support_bmi2 bool
support_erms bool
support_osxsave bool
support_popcnt bool
support_sse2 bool
support_sse41 bool
support_sse42 bool
support_ssse3 bool
// TODO(moehrmann) delete below variables once external
// packages have their dependencies on these removed.
cpuid_ecx uint32
cpuid_edx uint32
cpuid_ebx7 uint32 // not set on amd64p32
goarm uint8 // set by cmd/link on arm systems
framepointer_enabled bool // set by cmd/link
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment