80 lines
2.7 KiB
Go
80 lines
2.7 KiB
Go
package platform
|
|
|
|
const (
|
|
// CpuFeatureSSE3 is the flag to query CpuFeatureFlags.Has for SSEv3 capabilities
|
|
CpuFeatureSSE3 = uint64(1)
|
|
// CpuFeatureSSE4_1 is the flag to query CpuFeatureFlags.Has for SSEv4.1 capabilities
|
|
CpuFeatureSSE4_1 = uint64(1) << 19
|
|
// CpuFeatureSSE4_2 is the flag to query CpuFeatureFlags.Has for SSEv4.2 capabilities
|
|
CpuFeatureSSE4_2 = uint64(1) << 20
|
|
)
|
|
|
|
const (
|
|
// CpuExtraFeatureABM is the flag to query CpuFeatureFlags.HasExtra for Advanced Bit Manipulation capabilities (e.g. LZCNT)
|
|
CpuExtraFeatureABM = uint64(1) << 5
|
|
)
|
|
|
|
// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods
|
|
var CpuFeatures CpuFeatureFlags = loadCpuFeatureFlags()
|
|
|
|
// CpuFeatureFlags exposes methods for querying CPU capabilities
|
|
type CpuFeatureFlags interface {
|
|
// Has returns true when the specified flag (represented as uint64) is supported
|
|
Has(cpuFeature uint64) bool
|
|
// HasExtra returns true when the specified extraFlag (represented as uint64) is supported
|
|
HasExtra(cpuFeature uint64) bool
|
|
}
|
|
|
|
// cpuFeatureFlags implements CpuFeatureFlags interface
|
|
type cpuFeatureFlags struct {
|
|
flags uint64
|
|
extraFlags uint64
|
|
}
|
|
|
|
// cpuid exposes the CPUID instruction to the Go layer (https://www.amd.com/system/files/TechDocs/25481.pdf)
|
|
// implemented in impl_amd64.s
|
|
func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)
|
|
|
|
// cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap
|
|
func cpuidAsBitmap(arg1, arg2 uint32) uint64 {
|
|
_ /* eax */, _ /* ebx */, ecx, edx := cpuid(arg1, arg2)
|
|
return (uint64(edx) << 32) | uint64(ecx)
|
|
}
|
|
|
|
// loadStandardRange load flags from the standard range, panics otherwise
|
|
func loadStandardRange(id uint32) uint64 {
|
|
// ensure that the id is in the valid range, returned by cpuid(0,0)
|
|
maxRange, _, _, _ := cpuid(0, 0)
|
|
if id > maxRange {
|
|
panic("cannot query standard CPU flags")
|
|
}
|
|
return cpuidAsBitmap(id, 0)
|
|
}
|
|
|
|
// loadStandardRange load flags from the extended range, panics otherwise
|
|
func loadExtendedRange(id uint32) uint64 {
|
|
// ensure that the id is in the valid range, returned by cpuid(0x80000000,0)
|
|
maxRange, _, _, _ := cpuid(0x80000000, 0)
|
|
if id > maxRange {
|
|
panic("cannot query extended CPU flags")
|
|
}
|
|
return cpuidAsBitmap(id, 0)
|
|
}
|
|
|
|
func loadCpuFeatureFlags() CpuFeatureFlags {
|
|
return &cpuFeatureFlags{
|
|
flags: loadStandardRange(1),
|
|
extraFlags: loadExtendedRange(0x80000001),
|
|
}
|
|
}
|
|
|
|
// Has implements the same method on the CpuFeatureFlags interface
|
|
func (f *cpuFeatureFlags) Has(cpuFeature uint64) bool {
|
|
return (f.flags & cpuFeature) != 0
|
|
}
|
|
|
|
// HasExtra implements the same method on the CpuFeatureFlags interface
|
|
func (f *cpuFeatureFlags) HasExtra(cpuFeature uint64) bool {
|
|
return (f.extraFlags & cpuFeature) != 0
|
|
}
|