github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/platform/cpuid_amd64.go (about)

     1  //go:build amd64 && !tinygo
     2  
     3  package platform
     4  
     5  // CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods
     6  var CpuFeatures CpuFeatureFlags = loadCpuFeatureFlags()
     7  
     8  // cpuFeatureFlags implements CpuFeatureFlags interface
     9  type cpuFeatureFlags struct {
    10  	flags      uint64
    11  	extraFlags uint64
    12  }
    13  
    14  // cpuid exposes the CPUID instruction to the Go layer (https://www.amd.com/system/files/TechDocs/25481.pdf)
    15  // implemented in impl_amd64.s
    16  func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)
    17  
    18  // cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap
    19  func cpuidAsBitmap(arg1, arg2 uint32) uint64 {
    20  	_ /* eax */, _ /* ebx */, ecx, edx := cpuid(arg1, arg2)
    21  	return (uint64(edx) << 32) | uint64(ecx)
    22  }
    23  
    24  // loadStandardRange load flags from the standard range, panics otherwise
    25  func loadStandardRange(id uint32) uint64 {
    26  	// ensure that the id is in the valid range, returned by cpuid(0,0)
    27  	maxRange, _, _, _ := cpuid(0, 0)
    28  	if id > maxRange {
    29  		panic("cannot query standard CPU flags")
    30  	}
    31  	return cpuidAsBitmap(id, 0)
    32  }
    33  
    34  // loadStandardRange load flags from the extended range, panics otherwise
    35  func loadExtendedRange(id uint32) uint64 {
    36  	// ensure that the id is in the valid range, returned by cpuid(0x80000000,0)
    37  	maxRange, _, _, _ := cpuid(0x80000000, 0)
    38  	if id > maxRange {
    39  		panic("cannot query extended CPU flags")
    40  	}
    41  	return cpuidAsBitmap(id, 0)
    42  }
    43  
    44  func loadCpuFeatureFlags() CpuFeatureFlags {
    45  	return &cpuFeatureFlags{
    46  		flags:      loadStandardRange(1),
    47  		extraFlags: loadExtendedRange(0x80000001),
    48  	}
    49  }
    50  
    51  // Has implements the same method on the CpuFeatureFlags interface
    52  func (f *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool {
    53  	return (f.flags & uint64(cpuFeature)) != 0
    54  }
    55  
    56  // HasExtra implements the same method on the CpuFeatureFlags interface
    57  func (f *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool {
    58  	return (f.extraFlags & uint64(cpuFeature)) != 0
    59  }