// [AsmJit] // Complete x86/x64 JIT and Remote Assembler for C++. // // [License] // Zlib - See LICENSE.md file in the package. // [Guard] #ifndef _ASMJIT_BASE_CPUINFO_H #define _ASMJIT_BASE_CPUINFO_H // [Dependencies] #include "../base/arch.h" // [Api-Begin] #include "../asmjit_apibegin.h" namespace asmjit { //! \addtogroup asmjit_base //! \{ // ============================================================================ // [asmjit::CpuFeatures] // ============================================================================ class CpuFeatures { public: typedef uintptr_t BitWord; enum { kMaxFeatures = 128, kBitWordSize = static_cast(sizeof(BitWord)) * 8, kNumBitWords = kMaxFeatures / kBitWordSize }; // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- ASMJIT_INLINE CpuFeatures() noexcept { reset(); } ASMJIT_INLINE CpuFeatures(const CpuFeatures& other) noexcept = default; // -------------------------------------------------------------------------- // [Init / Reset] // -------------------------------------------------------------------------- ASMJIT_INLINE void init(const CpuFeatures& other) noexcept { ::memcpy(this, &other, sizeof(*this)); } ASMJIT_INLINE void reset() noexcept { ::memset(this, 0, sizeof(*this)); } // -------------------------------------------------------------------------- // [Ops] // -------------------------------------------------------------------------- //! Get all features as `BitWord` array. ASMJIT_INLINE BitWord* getBits() noexcept { return _bits; } //! Get all features as `BitWord` array (const). ASMJIT_INLINE const BitWord* getBits() const noexcept { return _bits; } //! Get if feature `feature` is present. ASMJIT_INLINE bool has(uint32_t feature) const noexcept { ASMJIT_ASSERT(feature < kMaxFeatures); uint32_t idx = feature / kBitWordSize; uint32_t bit = feature % kBitWordSize; return static_cast((_bits[idx] >> bit) & 0x1); } //! Get if all features as defined by `other` are present. ASMJIT_INLINE bool hasAll(const CpuFeatures& other) const noexcept { for (uint32_t i = 0; i < kNumBitWords; i++) if ((_bits[i] & other._bits[i]) != other._bits[i]) return false; return true; } //! Add a CPU `feature`. ASMJIT_INLINE CpuFeatures& add(uint32_t feature) noexcept { ASMJIT_ASSERT(feature < kMaxFeatures); uint32_t idx = feature / kBitWordSize; uint32_t bit = feature % kBitWordSize; _bits[idx] |= static_cast(1) << bit; return *this; } //! Remove a CPU `feature`. ASMJIT_INLINE CpuFeatures& remove(uint32_t feature) noexcept { ASMJIT_ASSERT(feature < kMaxFeatures); uint32_t idx = feature / kBitWordSize; uint32_t bit = feature % kBitWordSize; _bits[idx] &= ~(static_cast(1) << bit); return *this; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- BitWord _bits[kNumBitWords]; }; // ============================================================================ // [asmjit::CpuInfo] // ============================================================================ //! CPU information. class CpuInfo { public: //! CPU vendor ID. ASMJIT_ENUM(Vendor) { kVendorNone = 0, //!< Generic or unknown. kVendorIntel = 1, //!< Intel vendor. kVendorAMD = 2, //!< AMD vendor. kVendorVIA = 3 //!< VIA vendor. }; //! ARM/ARM64 CPU features. ASMJIT_ENUM(ArmFeatures) { kArmFeatureV6 = 1, //!< ARMv6 instruction set. kArmFeatureV7, //!< ARMv7 instruction set. kArmFeatureV8, //!< ARMv8 instruction set. kArmFeatureTHUMB, //!< CPU provides THUMB v1 instruction set (THUMB mode). kArmFeatureTHUMB2, //!< CPU provides THUMB v2 instruction set (THUMB mode). kArmFeatureVFPv2, //!< CPU provides VFPv2 instruction set. kArmFeatureVFPv3, //!< CPU provides VFPv3 instruction set. kArmFeatureVFPv4, //!< CPU provides VFPv4 instruction set. kArmFeatureVFP_D32, //!< CPU provides 32 VFP-D (64-bit) registers. kArmFeatureEDSP, //!< CPU provides EDSP extensions. kArmFeatureASIMD, //!< CPU provides 'Advanced SIMD'. kArmFeatureIDIVA, //!< CPU provides hardware SDIV and UDIV (ARM mode). kArmFeatureIDIVT, //!< CPU provides hardware SDIV and UDIV (THUMB mode). kArmFeatureAES, //!< CPU provides AES instructions (ARM64 only). kArmFeatureCRC32, //!< CPU provides CRC32 instructions. kArmFeaturePMULL, //!< CPU provides PMULL instructions (ARM64 only). kArmFeatureSHA1, //!< CPU provides SHA1 instructions. kArmFeatureSHA256, //!< CPU provides SHA256 instructions. kArmFeatureAtomics64, //!< CPU provides 64-bit load/store atomics (ARM64 only). kArmFeaturesCount //!< Count of ARM/ARM64 CPU features. }; //! X86/X64 CPU features. ASMJIT_ENUM(X86Features) { kX86FeatureI486 = 1, //!< CPU is at least I486. kX86FeatureNX, //!< CPU has Not-Execute-Bit. kX86FeatureMT, //!< CPU has multi-threading. kX86FeatureALTMOVCR8, //!< CPU supports `LOCK MOV CR8` (AMD CPUs). kX86FeatureCMOV, //!< CPU has CMOV. kX86FeatureCMPXCHG8B, //!< CPU has CMPXCHG8B. kX86FeatureCMPXCHG16B, //!< CPU has CMPXCHG16B (x64). kX86FeatureMSR, //!< CPU has RDMSR/WRMSR. kX86FeatureRDTSC, //!< CPU has RDTSC. kX86FeatureRDTSCP, //!< CPU has RDTSCP. kX86FeatureCLFLUSH, //!< CPU has CLFUSH. kX86FeatureCLFLUSHOPT, //!< CPU has CLFUSHOPT. kX86FeatureCLWB, //!< CPU has CLWB. kX86FeatureCLZERO, //!< CPU has CLZERO. kX86FeaturePCOMMIT, //!< CPU has PCOMMIT. kX86FeaturePREFETCHW, //!< CPU has PREFETCHW. kX86FeaturePREFETCHWT1, //!< CPU has PREFETCHWT1. kX86FeatureLAHFSAHF, //!< CPU has LAHF/SAHF. kX86FeatureFXSR, //!< CPU has FXSAVE/FXRSTOR. kX86FeatureFXSROPT, //!< CPU has FXSAVE/FXRSTOR (optimized). kX86FeatureMMX, //!< CPU has MMX. kX86FeatureMMX2, //!< CPU has extended MMX. kX86Feature3DNOW, //!< CPU has 3DNOW. kX86Feature3DNOW2, //!< CPU has 3DNOW2 (enhanced). kX86FeatureGEODE, //!< CPU has GEODE extensions (few additions to 3DNOW). kX86FeatureSSE, //!< CPU has SSE. kX86FeatureSSE2, //!< CPU has SSE2. kX86FeatureSSE3, //!< CPU has SSE3. kX86FeatureSSSE3, //!< CPU has SSSE3. kX86FeatureSSE4A, //!< CPU has SSE4.A. kX86FeatureSSE4_1, //!< CPU has SSE4.1. kX86FeatureSSE4_2, //!< CPU has SSE4.2. kX86FeatureMSSE, //!< CPU has Misaligned SSE (MSSE). kX86FeatureMONITOR, //!< CPU has MONITOR and MWAIT. kX86FeatureMOVBE, //!< CPU has MOVBE. kX86FeaturePOPCNT, //!< CPU has POPCNT. kX86FeatureLZCNT, //!< CPU has LZCNT. kX86FeatureAESNI, //!< CPU has AESNI. kX86FeaturePCLMULQDQ, //!< CPU has PCLMULQDQ. kX86FeatureRDRAND, //!< CPU has RDRAND. kX86FeatureRDSEED, //!< CPU has RDSEED. kX86FeatureSMAP, //!< CPU has SMAP (supervisor-mode access prevention). kX86FeatureSMEP, //!< CPU has SMEP (supervisor-mode execution prevention). kX86FeatureSHA, //!< CPU has SHA-1 and SHA-256. kX86FeatureXSAVE, //!< CPU has XSAVE support (XSAVE/XRSTOR, XSETBV/XGETBV, and XCR). kX86FeatureXSAVEC, //!< CPU has XSAVEC support (XSAVEC). kX86FeatureXSAVES, //!< CPU has XSAVES support (XSAVES/XRSTORS). kX86FeatureXSAVEOPT, //!< CPU has XSAVEOPT support (XSAVEOPT/XSAVEOPT64). kX86FeatureOSXSAVE, //!< CPU has XSAVE enabled by OS. kX86FeatureAVX, //!< CPU has AVX. kX86FeatureAVX2, //!< CPU has AVX2. kX86FeatureF16C, //!< CPU has F16C. kX86FeatureFMA, //!< CPU has FMA. kX86FeatureFMA4, //!< CPU has FMA4. kX86FeatureXOP, //!< CPU has XOP. kX86FeatureBMI, //!< CPU has BMI (bit manipulation instructions #1). kX86FeatureBMI2, //!< CPU has BMI2 (bit manipulation instructions #2). kX86FeatureADX, //!< CPU has ADX (multi-precision add-carry instruction extensions). kX86FeatureTBM, //!< CPU has TBM (trailing bit manipulation). kX86FeatureMPX, //!< CPU has MPX (memory protection extensions). kX86FeatureHLE, //!< CPU has HLE. kX86FeatureRTM, //!< CPU has RTM. kX86FeatureTSX, //!< CPU has TSX. kX86FeatureERMS, //!< CPU has ERMS (enhanced REP MOVSB/STOSB). kX86FeatureFSGSBASE, //!< CPU has FSGSBASE. kX86FeatureAVX512_F, //!< CPU has AVX512-F (foundation). kX86FeatureAVX512_CDI, //!< CPU has AVX512-CDI (conflict detection). kX86FeatureAVX512_PFI, //!< CPU has AVX512-PFI (prefetch instructions). kX86FeatureAVX512_ERI, //!< CPU has AVX512-ERI (exponential and reciprocal). kX86FeatureAVX512_DQ, //!< CPU has AVX512-DQ (DWORD/QWORD). kX86FeatureAVX512_BW, //!< CPU has AVX512-BW (BYTE/WORD). kX86FeatureAVX512_VL, //!< CPU has AVX512-VL (vector length extensions). kX86FeatureAVX512_IFMA, //!< CPU has AVX512-IFMA (integer fused-multiply-add using 52-bit precision). kX86FeatureAVX512_VBMI, //!< CPU has AVX512-VBMI (vector byte manipulation). kX86FeatureAVX512_VPOPCNTDQ, //!< CPU has AVX512-VPOPCNTDQ (VPOPCNT[D|Q] instructions). kX86FeatureAVX512_4VNNIW, //!< CPU has AVX512-VNNIW (vector NN instructions word variable precision). kX86FeatureAVX512_4FMAPS, //!< CPU has AVX512-FMAPS (FMA packed single). kX86FeaturesCount //!< Count of X86/X64 CPU features. }; // -------------------------------------------------------------------------- // [ArmInfo] // -------------------------------------------------------------------------- struct ArmData { }; // -------------------------------------------------------------------------- // [X86Info] // -------------------------------------------------------------------------- struct X86Data { uint32_t _processorType; //!< Processor type. uint32_t _brandIndex; //!< Brand index. uint32_t _flushCacheLineSize; //!< Flush cache line size (in bytes). uint32_t _maxLogicalProcessors; //!< Maximum number of addressable IDs for logical processors. }; // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- ASMJIT_INLINE CpuInfo() noexcept { reset(); } ASMJIT_INLINE CpuInfo(const CpuInfo& other) noexcept = default; // -------------------------------------------------------------------------- // [Init / Reset] // -------------------------------------------------------------------------- //! Initialize CpuInfo to the given architecture, see \ArchInfo. ASMJIT_INLINE void initArch(uint32_t archType, uint32_t archMode = 0) noexcept { _archInfo.init(archType, archMode); } ASMJIT_INLINE void init(const CpuInfo& other) noexcept { ::memcpy(this, &other, sizeof(*this)); } ASMJIT_INLINE void reset() noexcept { ::memset(this, 0, sizeof(*this)); } // -------------------------------------------------------------------------- // [Detect] // -------------------------------------------------------------------------- ASMJIT_API void detect() noexcept; // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! Get generic architecture information. ASMJIT_INLINE const ArchInfo& getArchInfo() const noexcept { return _archInfo; } //! Get CPU architecture type, see \ArchInfo::Type. ASMJIT_INLINE uint32_t getArchType() const noexcept { return _archInfo.getType(); } //! Get CPU architecture sub-type, see \ArchInfo::SubType. ASMJIT_INLINE uint32_t getArchSubType() const noexcept { return _archInfo.getSubType(); } //! Get CPU vendor ID. ASMJIT_INLINE uint32_t getVendorId() const noexcept { return _vendorId; } //! Get CPU family ID. ASMJIT_INLINE uint32_t getFamily() const noexcept { return _family; } //! Get CPU model ID. ASMJIT_INLINE uint32_t getModel() const noexcept { return _model; } //! Get CPU stepping. ASMJIT_INLINE uint32_t getStepping() const noexcept { return _stepping; } //! Get number of hardware threads available. ASMJIT_INLINE uint32_t getHwThreadsCount() const noexcept { return _hwThreadsCount; } //! Get all CPU features. ASMJIT_INLINE const CpuFeatures& getFeatures() const noexcept { return _features; } //! Get whether CPU has a `feature`. ASMJIT_INLINE bool hasFeature(uint32_t feature) const noexcept { return _features.has(feature); } //! Add a CPU `feature`. ASMJIT_INLINE CpuInfo& addFeature(uint32_t feature) noexcept { _features.add(feature); return *this; } //! Get CPU vendor string. ASMJIT_INLINE const char* getVendorString() const noexcept { return _vendorString; } //! Get CPU brand string. ASMJIT_INLINE const char* getBrandString() const noexcept { return _brandString; } // -------------------------------------------------------------------------- // [Accessors - ARM] // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- // [Accessors - X86] // -------------------------------------------------------------------------- //! Get processor type. ASMJIT_INLINE uint32_t getX86ProcessorType() const noexcept { return _x86Data._processorType; } //! Get brand index. ASMJIT_INLINE uint32_t getX86BrandIndex() const noexcept { return _x86Data._brandIndex; } //! Get flush cache line size. ASMJIT_INLINE uint32_t getX86FlushCacheLineSize() const noexcept { return _x86Data._flushCacheLineSize; } //! Get maximum logical processors count. ASMJIT_INLINE uint32_t getX86MaxLogicalProcessors() const noexcept { return _x86Data._maxLogicalProcessors; } // -------------------------------------------------------------------------- // [Statics] // -------------------------------------------------------------------------- //! Get the host CPU information. ASMJIT_API static const CpuInfo& getHost() noexcept; // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- ArchInfo _archInfo; //!< CPU architecture information. uint32_t _vendorId; //!< CPU vendor id, see \ref Vendor. uint32_t _family; //!< CPU family ID. uint32_t _model; //!< CPU model ID. uint32_t _stepping; //!< CPU stepping. uint32_t _hwThreadsCount; //!< Number of hardware threads. CpuFeatures _features; //!< CPU features. char _vendorString[16]; //!< CPU vendor string. char _brandString[64]; //!< CPU brand string. // Architecture specific data. union { ArmData _armData; X86Data _x86Data; }; }; //! \} } // asmjit namespace // [Api-End] #include "../asmjit_apiend.h" // [Guard] #endif // _ASMJIT_BASE_CPUINFO_H