Files
wazero/internal/platform/cpuid_amd64.go
2024-05-28 17:44:05 +09:00

80 lines
2.4 KiB
Go

//go:build amd64 && !tinygo
package platform
// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods.
var CpuFeatures = loadCpuFeatureFlags()
// 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 CpuFeature) bool {
return (f.flags & uint64(cpuFeature)) != 0
}
// HasExtra implements the same method on the CpuFeatureFlags interface.
func (f *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool {
return (f.extraFlags & uint64(cpuFeature)) != 0
}
// Raw implements the same method on the CpuFeatureFlags interface.
func (f *cpuFeatureFlags) Raw() uint64 {
// Below, we only set the first 4 bits for the features we care about,
// instead of setting all the unnecessary bits obtained from the CPUID instruction.
var ret uint64
if f.Has(CpuFeatureAmd64SSE3) {
ret = 1 << 0
}
if f.Has(CpuFeatureAmd64SSE4_1) {
ret |= 1 << 1
}
if f.Has(CpuFeatureAmd64SSE4_2) {
ret |= 1 << 2
}
if f.HasExtra(CpuExtraFeatureAmd64ABM) {
ret |= 1 << 3
}
return ret
}