github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/platform/cpuid_amd64.go (about)

     1  package platform
     2  
     3  const (
     4  	// CpuFeatureSSE3 is the flag to query CpuFeatureFlags.Has for SSEv3 capabilities
     5  	CpuFeatureSSE3 = uint64(1)
     6  	// CpuFeatureSSE4_1 is the flag to query CpuFeatureFlags.Has for SSEv4.1 capabilities
     7  	CpuFeatureSSE4_1 = uint64(1) << 19
     8  	// CpuFeatureSSE4_2 is the flag to query CpuFeatureFlags.Has for SSEv4.2 capabilities
     9  	CpuFeatureSSE4_2 = uint64(1) << 20
    10  )
    11  
    12  const (
    13  	// CpuExtraFeatureABM is the flag to query CpuFeatureFlags.HasExtra for Advanced Bit Manipulation capabilities (e.g. LZCNT)
    14  	CpuExtraFeatureABM = uint64(1) << 5
    15  )
    16  
    17  // CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods
    18  var CpuFeatures CpuFeatureFlags = loadCpuFeatureFlags()
    19  
    20  // CpuFeatureFlags exposes methods for querying CPU capabilities
    21  type CpuFeatureFlags interface {
    22  	// Has returns true when the specified flag (represented as uint64) is supported
    23  	Has(cpuFeature uint64) bool
    24  	// HasExtra returns true when the specified extraFlag (represented as uint64) is supported
    25  	HasExtra(cpuFeature uint64) bool
    26  }
    27  
    28  // cpuFeatureFlags implements CpuFeatureFlags interface
    29  type cpuFeatureFlags struct {
    30  	flags      uint64
    31  	extraFlags uint64
    32  }
    33  
    34  // cpuid exposes the CPUID instruction to the Go layer (https://www.amd.com/system/files/TechDocs/25481.pdf)
    35  // implemented in impl_amd64.s
    36  func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)
    37  
    38  // cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap
    39  func cpuidAsBitmap(arg1, arg2 uint32) uint64 {
    40  	_ /* eax */, _ /* ebx */, ecx, edx := cpuid(arg1, arg2)
    41  	return (uint64(edx) << 32) | uint64(ecx)
    42  }
    43  
    44  // loadStandardRange load flags from the standard range, panics otherwise
    45  func loadStandardRange(id uint32) uint64 {
    46  	// ensure that the id is in the valid range, returned by cpuid(0,0)
    47  	maxRange, _, _, _ := cpuid(0, 0)
    48  	if id > maxRange {
    49  		panic("cannot query standard CPU flags")
    50  	}
    51  	return cpuidAsBitmap(id, 0)
    52  }
    53  
    54  // loadStandardRange load flags from the extended range, panics otherwise
    55  func loadExtendedRange(id uint32) uint64 {
    56  	// ensure that the id is in the valid range, returned by cpuid(0x80000000,0)
    57  	maxRange, _, _, _ := cpuid(0x80000000, 0)
    58  	if id > maxRange {
    59  		panic("cannot query extended CPU flags")
    60  	}
    61  	return cpuidAsBitmap(id, 0)
    62  }
    63  
    64  func loadCpuFeatureFlags() CpuFeatureFlags {
    65  	return &cpuFeatureFlags{
    66  		flags:      loadStandardRange(1),
    67  		extraFlags: loadExtendedRange(0x80000001),
    68  	}
    69  }
    70  
    71  // Has implements the same method on the CpuFeatureFlags interface
    72  func (f *cpuFeatureFlags) Has(cpuFeature uint64) bool {
    73  	return (f.flags & cpuFeature) != 0
    74  }
    75  
    76  // HasExtra implements the same method on the CpuFeatureFlags interface
    77  func (f *cpuFeatureFlags) HasExtra(cpuFeature uint64) bool {
    78  	return (f.extraFlags & cpuFeature) != 0
    79  }