summaryrefslogtreecommitdiff
path: root/erts/emulator/asmjit/core/cpuinfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/asmjit/core/cpuinfo.h')
-rw-r--r--erts/emulator/asmjit/core/cpuinfo.h755
1 files changed, 707 insertions, 48 deletions
diff --git a/erts/emulator/asmjit/core/cpuinfo.h b/erts/emulator/asmjit/core/cpuinfo.h
index 83bb8c1a83..974fb3ed42 100644
--- a/erts/emulator/asmjit/core/cpuinfo.h
+++ b/erts/emulator/asmjit/core/cpuinfo.h
@@ -1,52 +1,679 @@
-// AsmJit - Machine code generation for C++
+// This file is part of AsmJit project <https://asmjit.com>
//
-// * Official AsmJit Home Page: https://asmjit.com
-// * Official Github Repository: https://github.com/asmjit/asmjit
-//
-// Copyright (c) 2008-2020 The AsmJit Authors
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
+// See asmjit.h or LICENSE.md for license and copyright information
+// SPDX-License-Identifier: Zlib
#ifndef ASMJIT_CORE_CPUINFO_H_INCLUDED
#define ASMJIT_CORE_CPUINFO_H_INCLUDED
#include "../core/archtraits.h"
-#include "../core/features.h"
+#include "../core/environment.h"
#include "../core/globals.h"
#include "../core/string.h"
+#include "../core/support.h"
ASMJIT_BEGIN_NAMESPACE
//! \addtogroup asmjit_core
//! \{
-// ============================================================================
-// [asmjit::CpuInfo]
-// ============================================================================
+//! CPU features information.
+//!
+//! Each feature is represented by a single bit in an embedded bit array.
+class CpuFeatures {
+public:
+ //! A word that is used to represents feature bits.
+ typedef Support::BitWord BitWord;
+ //! Iterator that can iterate all CPU features set.
+ typedef Support::BitVectorIterator<BitWord> Iterator;
+
+ //! \name Constants
+ //! \{
+
+ //! \cond INTERNAL
+ enum : uint32_t {
+ kMaxFeatures = 256,
+ kNumBitWords = kMaxFeatures / Support::kBitWordSizeInBits
+ };
+ //! \endcond
+
+ //! \}
+
+ //! \name Data
+ //! \{
+
+ //! CPU features data.
+ struct Data {
+ //! \name Members
+ //! \{
+
+ //! Data bits.
+ Support::Array<BitWord, kNumBitWords> _bits;
+
+ //! \}
+
+ //! \name Overloaded Operators
+ //! \{
+
+ inline bool operator==(const Data& other) noexcept { return eq(other); }
+ inline bool operator!=(const Data& other) noexcept { return !eq(other); }
+
+ //! \}
+
+ //! \name Accessors
+ //! \{
+
+ //! Returns true if there are no features set.
+ inline bool empty() const noexcept { return _bits.aggregate<Support::Or>(0) == 0; }
+
+ //! Returns all features as array of bitwords (see \ref Support::BitWord).
+ inline BitWord* bits() noexcept { return _bits.data(); }
+ //! Returns all features as array of bitwords (const).
+ inline const BitWord* bits() const noexcept { return _bits.data(); }
+
+ //! Returns the number of BitWords returned by \ref bits().
+ inline size_t bitWordCount() const noexcept { return kNumBitWords; }
+
+ //! Returns \ref Support::BitVectorIterator, that can be used to iterate over all features efficiently.
+ inline Iterator iterator() const noexcept { return Iterator(_bits.data(), kNumBitWords); }
+
+ //! Tests whether the feature `featureId` is present.
+ template<typename FeatureId>
+ ASMJIT_FORCE_INLINE bool has(const FeatureId& featureId) const noexcept {
+ ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures);
+
+ uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits;
+ uint32_t bit = uint32_t(featureId) % Support::kBitWordSizeInBits;
+
+ return bool((_bits[idx] >> bit) & 0x1);
+ }
+
+ //! Tests whether all features as defined by `other` are present.
+ ASMJIT_FORCE_INLINE bool hasAll(const Data& other) const noexcept {
+ for (uint32_t i = 0; i < kNumBitWords; i++)
+ if ((_bits[i] & other._bits[i]) != other._bits[i])
+ return false;
+ return true;
+ }
+
+ //! \}
+
+ //! \name Manipulation
+ //! \{
+
+ inline void reset() noexcept { _bits.fill(0); }
+
+ //! Adds the given CPU `featureId` to the list of features.
+ template<typename FeatureId>
+ ASMJIT_FORCE_INLINE void add(const FeatureId& featureId) noexcept {
+ ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures);
+
+ uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits;
+ uint32_t bit = uint32_t(featureId) % Support::kBitWordSizeInBits;
+
+ _bits[idx] |= BitWord(1) << bit;
+ }
+
+ template<typename FeatureId, typename... Args>
+ ASMJIT_FORCE_INLINE void add(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
+ add(featureId);
+ add(std::forward<Args>(otherFeatureIds)...);
+ }
+
+ template<typename FeatureId>
+ ASMJIT_FORCE_INLINE void addIf(bool condition, const FeatureId& featureId) noexcept {
+ ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures);
+
+ uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits;
+ uint32_t bit = uint32_t(featureId) % Support::kBitWordSizeInBits;
+
+ _bits[idx] |= BitWord(condition) << bit;
+ }
+
+ template<typename FeatureId, typename... Args>
+ ASMJIT_FORCE_INLINE void addIf(bool condition, const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
+ addIf(condition, featureId);
+ addIf(condition, std::forward<Args>(otherFeatureIds)...);
+ }
+
+ //! Removes the given CPU `featureId` from the list of features.
+ template<typename FeatureId>
+ ASMJIT_FORCE_INLINE void remove(const FeatureId& featureId) noexcept {
+ ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures);
+
+ uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits;
+ uint32_t bit = uint32_t(featureId) % Support::kBitWordSizeInBits;
+
+ _bits[idx] &= ~(BitWord(1) << bit);
+ }
+
+ template<typename FeatureId, typename... Args>
+ ASMJIT_FORCE_INLINE void remove(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
+ remove(featureId);
+ remove(std::forward<Args>(otherFeatureIds)...);
+ }
+
+ //! Tests whether this CPU features data matches `other`.
+ ASMJIT_FORCE_INLINE bool eq(const Data& other) const noexcept { return _bits == other._bits; }
+
+ //! \}
+
+ };
+
+ //! X86 specific features data.
+ struct X86 : public Data {
+ //! X86 CPU feature identifiers.
+ enum Id : uint8_t {
+ // @EnumValuesBegin{"enum": "CpuFeatures::X86"}@
+ kNone, //!< No feature (never set, used internally).
+
+ kMT, //!< CPU has multi-threading capabilities.
+ kNX, //!< CPU has Not-Execute-Bit aka DEP (data-execution prevention).
+ k3DNOW, //!< CPU has 3DNOW (3DNOW base instructions) [AMD].
+ k3DNOW2, //!< CPU has 3DNOW2 (enhanced 3DNOW) [AMD].
+ kADX, //!< CPU has ADX (multi-precision add-carry instruction extensions).
+ kAESNI, //!< CPU has AESNI (AES encode/decode instructions).
+ kALTMOVCR8, //!< CPU has LOCK MOV R<->CR0 (supports `MOV R<->CR8` via `LOCK MOV R<->CR0` in 32-bit mode) [AMD].
+ kAMX_BF16, //!< CPU has AMX_BF16 (advanced matrix extensions - BF16 instructions).
+ kAMX_INT8, //!< CPU has AMX_INT8 (advanced matrix extensions - INT8 instructions).
+ kAMX_TILE, //!< CPU has AMX_TILE (advanced matrix extensions).
+ kAVX, //!< CPU has AVX (advanced vector extensions).
+ kAVX2, //!< CPU has AVX2 (advanced vector extensions 2).
+ kAVX512_4FMAPS, //!< CPU has AVX512_FMAPS (FMA packed single).
+ kAVX512_4VNNIW, //!< CPU has AVX512_VNNIW (vector NN instructions word variable precision).
+ kAVX512_BF16, //!< CPU has AVX512_BF16 (BFLOAT16 support instruction).
+ kAVX512_BITALG, //!< CPU has AVX512_BITALG (VPOPCNT[B|W], VPSHUFBITQMB).
+ kAVX512_BW, //!< CPU has AVX512_BW (packed BYTE|WORD).
+ kAVX512_CDI, //!< CPU has AVX512_CDI (conflict detection).
+ kAVX512_DQ, //!< CPU has AVX512_DQ (packed DWORD|QWORD).
+ kAVX512_ERI, //!< CPU has AVX512_ERI (exponential and reciprocal).
+ kAVX512_F, //!< CPU has AVX512_F (AVX512 foundation).
+ kAVX512_FP16, //!< CPU has AVX512_FP16 (FP16 extensions).
+ kAVX512_IFMA, //!< CPU has AVX512_IFMA (integer fused-multiply-add using 52-bit precision).
+ kAVX512_PFI, //!< CPU has AVX512_PFI (prefetch instructions).
+ kAVX512_VBMI, //!< CPU has AVX512_VBMI (vector byte manipulation).
+ kAVX512_VBMI2, //!< CPU has AVX512_VBMI2 (vector byte manipulation 2).
+ kAVX512_VL, //!< CPU has AVX512_VL (vector length extensions).
+ kAVX512_VNNI, //!< CPU has AVX512_VNNI (vector neural network instructions).
+ kAVX512_VP2INTERSECT, //!< CPU has AVX512_VP2INTERSECT
+ kAVX512_VPOPCNTDQ, //!< CPU has AVX512_VPOPCNTDQ (VPOPCNT[D|Q] instructions).
+ kAVX_VNNI, //!< CPU has AVX_VNNI (VEX encoding of vpdpbusd/vpdpbusds/vpdpwssd/vpdpwssds).
+ kBMI, //!< CPU has BMI (bit manipulation instructions #1).
+ kBMI2, //!< CPU has BMI2 (bit manipulation instructions #2).
+ kCET_IBT, //!< CPU has CET-IBT (indirect branch tracking).
+ kCET_SS, //!< CPU has CET-SS.
+ kCLDEMOTE, //!< CPU has CLDEMOTE (cache line demote).
+ kCLFLUSH, //!< CPU has CLFUSH (Cache Line flush).
+ kCLFLUSHOPT, //!< CPU has CLFUSHOPT (Cache Line flush - optimized).
+ kCLWB, //!< CPU has CLWB.
+ kCLZERO, //!< CPU has CLZERO.
+ kCMOV, //!< CPU has CMOV (CMOV and FCMOV instructions).
+ kCMPXCHG16B, //!< CPU has CMPXCHG16B (compare-exchange 16 bytes) [X86_64].
+ kCMPXCHG8B, //!< CPU has CMPXCHG8B (compare-exchange 8 bytes).
+ kENCLV, //!< CPU has ENCLV.
+ kENQCMD, //!< CPU has ENQCMD (enqueue stores).
+ kERMS, //!< CPU has ERMS (enhanced REP MOVSB/STOSB).
+ kF16C, //!< CPU has F16C.
+ kFMA, //!< CPU has FMA (fused-multiply-add 3 operand form).
+ kFMA4, //!< CPU has FMA4 (fused-multiply-add 4 operand form).
+ kFPU, //!< CPU has FPU (FPU support).
+ kFSGSBASE, //!< CPU has FSGSBASE.
+ kFXSR, //!< CPU has FXSR (FXSAVE/FXRSTOR instructions).
+ kFXSROPT, //!< CPU has FXSROTP (FXSAVE/FXRSTOR is optimized).
+ kGEODE, //!< CPU has GEODE extensions (3DNOW additions).
+ kGFNI, //!< CPU has GFNI (Galois field instructions).
+ kHLE, //!< CPU has HLE.
+ kHRESET, //!< CPU has HRESET.
+ kI486, //!< CPU has I486 features (I486+ support).
+ kLAHFSAHF, //!< CPU has LAHF/SAHF (LAHF/SAHF in 64-bit mode) [X86_64].
+ kLWP, //!< CPU has LWP (lightweight profiling) [AMD].
+ kLZCNT, //!< CPU has LZCNT (LZCNT instruction).
+ kMCOMMIT, //!< CPU has MCOMMIT (MCOMMIT instruction).
+ kMMX, //!< CPU has MMX (MMX base instructions).
+ kMMX2, //!< CPU has MMX2 (MMX extensions or MMX2).
+ kMONITOR, //!< CPU has MONITOR (MONITOR/MWAIT instructions).
+ kMONITORX, //!< CPU has MONITORX (MONITORX/MWAITX instructions).
+ kMOVBE, //!< CPU has MOVBE (move with byte-order swap).
+ kMOVDIR64B, //!< CPU has MOVDIR64B (move 64 bytes as direct store).
+ kMOVDIRI, //!< CPU has MOVDIRI (move dword/qword as direct store).
+ kMPX, //!< CPU has MPX (memory protection extensions).
+ kMSR, //!< CPU has MSR (RDMSR/WRMSR instructions).
+ kMSSE, //!< CPU has MSSE (misaligned SSE support).
+ kOSXSAVE, //!< CPU has OSXSAVE (XSAVE enabled by OS).
+ kOSPKE, //!< CPU has OSPKE (PKE enabled by OS).
+ kPCLMULQDQ, //!< CPU has PCLMULQDQ (packed carry-less multiplication).
+ kPCONFIG, //!< CPU has PCONFIG (PCONFIG instruction).
+ kPOPCNT, //!< CPU has POPCNT (POPCNT instruction).
+ kPREFETCHW, //!< CPU has PREFETCHW.
+ kPREFETCHWT1, //!< CPU has PREFETCHWT1.
+ kPTWRITE, //!< CPU has PTWRITE.
+ kRDPID, //!< CPU has RDPID.
+ kRDPRU, //!< CPU has RDPRU.
+ kRDRAND, //!< CPU has RDRAND.
+ kRDSEED, //!< CPU has RDSEED.
+ kRDTSC, //!< CPU has RDTSC.
+ kRDTSCP, //!< CPU has RDTSCP.
+ kRTM, //!< CPU has RTM.
+ kSERIALIZE, //!< CPU has SERIALIZE.
+ kSHA, //!< CPU has SHA (SHA-1 and SHA-256 instructions).
+ kSKINIT, //!< CPU has SKINIT (SKINIT/STGI instructions) [AMD].
+ kSMAP, //!< CPU has SMAP (supervisor-mode access prevention).
+ kSMEP, //!< CPU has SMEP (supervisor-mode execution prevention).
+ kSMX, //!< CPU has SMX (safer mode extensions).
+ kSNP, //!< CPU has SNP.
+ kSSE, //!< CPU has SSE.
+ kSSE2, //!< CPU has SSE2.
+ kSSE3, //!< CPU has SSE3.
+ kSSE4_1, //!< CPU has SSE4.1.
+ kSSE4_2, //!< CPU has SSE4.2.
+ kSSE4A, //!< CPU has SSE4A [AMD].
+ kSSSE3, //!< CPU has SSSE3.
+ kSVM, //!< CPU has SVM (virtualization) [AMD].
+ kTBM, //!< CPU has TBM (trailing bit manipulation) [AMD].
+ kTSX, //!< CPU has TSX.
+ kTSXLDTRK, //!< CPU has TSXLDTRK.
+ kUINTR, //!< CPU has UINTR (user interrupts).
+ kVAES, //!< CPU has VAES (vector AES 256|512 bit support).
+ kVMX, //!< CPU has VMX (virtualization) [INTEL].
+ kVPCLMULQDQ, //!< CPU has VPCLMULQDQ (vector PCLMULQDQ 256|512-bit support).
+ kWAITPKG, //!< CPU has WAITPKG (UMONITOR, UMWAIT, TPAUSE).
+ kWBNOINVD, //!< CPU has WBNOINVD.
+ kXOP, //!< CPU has XOP (XOP instructions) [AMD].
+ kXSAVE, //!< CPU has XSAVE.
+ kXSAVEC, //!< CPU has XSAVEC.
+ kXSAVEOPT, //!< CPU has XSAVEOPT.
+ kXSAVES, //!< CPU has XSAVES.
+ // @EnumValuesEnd@
+
+ kMaxValue = kXSAVES
+ };
+
+ #define ASMJIT_X86_FEATURE(FEATURE) \
+ inline bool has##FEATURE() const noexcept { return has(X86::k##FEATURE); }
+
+ ASMJIT_X86_FEATURE(MT)
+ ASMJIT_X86_FEATURE(NX)
+ ASMJIT_X86_FEATURE(3DNOW)
+ ASMJIT_X86_FEATURE(3DNOW2)
+ ASMJIT_X86_FEATURE(ADX)
+ ASMJIT_X86_FEATURE(AESNI)
+ ASMJIT_X86_FEATURE(ALTMOVCR8)
+ ASMJIT_X86_FEATURE(AMX_BF16)
+ ASMJIT_X86_FEATURE(AMX_INT8)
+ ASMJIT_X86_FEATURE(AMX_TILE)
+ ASMJIT_X86_FEATURE(AVX)
+ ASMJIT_X86_FEATURE(AVX2)
+ ASMJIT_X86_FEATURE(AVX512_4FMAPS)
+ ASMJIT_X86_FEATURE(AVX512_4VNNIW)
+ ASMJIT_X86_FEATURE(AVX512_BF16)
+ ASMJIT_X86_FEATURE(AVX512_BITALG)
+ ASMJIT_X86_FEATURE(AVX512_BW)
+ ASMJIT_X86_FEATURE(AVX512_CDI)
+ ASMJIT_X86_FEATURE(AVX512_DQ)
+ ASMJIT_X86_FEATURE(AVX512_ERI)
+ ASMJIT_X86_FEATURE(AVX512_F)
+ ASMJIT_X86_FEATURE(AVX512_FP16)
+ ASMJIT_X86_FEATURE(AVX512_IFMA)
+ ASMJIT_X86_FEATURE(AVX512_PFI)
+ ASMJIT_X86_FEATURE(AVX512_VBMI)
+ ASMJIT_X86_FEATURE(AVX512_VBMI2)
+ ASMJIT_X86_FEATURE(AVX512_VL)
+ ASMJIT_X86_FEATURE(AVX512_VNNI)
+ ASMJIT_X86_FEATURE(AVX512_VP2INTERSECT)
+ ASMJIT_X86_FEATURE(AVX512_VPOPCNTDQ)
+ ASMJIT_X86_FEATURE(AVX_VNNI)
+ ASMJIT_X86_FEATURE(BMI)
+ ASMJIT_X86_FEATURE(BMI2)
+ ASMJIT_X86_FEATURE(CET_IBT)
+ ASMJIT_X86_FEATURE(CET_SS)
+ ASMJIT_X86_FEATURE(CLDEMOTE)
+ ASMJIT_X86_FEATURE(CLFLUSH)
+ ASMJIT_X86_FEATURE(CLFLUSHOPT)
+ ASMJIT_X86_FEATURE(CLWB)
+ ASMJIT_X86_FEATURE(CLZERO)
+ ASMJIT_X86_FEATURE(CMOV)
+ ASMJIT_X86_FEATURE(CMPXCHG16B)
+ ASMJIT_X86_FEATURE(CMPXCHG8B)
+ ASMJIT_X86_FEATURE(ENCLV)
+ ASMJIT_X86_FEATURE(ENQCMD)
+ ASMJIT_X86_FEATURE(ERMS)
+ ASMJIT_X86_FEATURE(F16C)
+ ASMJIT_X86_FEATURE(FMA)
+ ASMJIT_X86_FEATURE(FMA4)
+ ASMJIT_X86_FEATURE(FPU)
+ ASMJIT_X86_FEATURE(FSGSBASE)
+ ASMJIT_X86_FEATURE(FXSR)
+ ASMJIT_X86_FEATURE(FXSROPT)
+ ASMJIT_X86_FEATURE(GEODE)
+ ASMJIT_X86_FEATURE(GFNI)
+ ASMJIT_X86_FEATURE(HLE)
+ ASMJIT_X86_FEATURE(HRESET)
+ ASMJIT_X86_FEATURE(I486)
+ ASMJIT_X86_FEATURE(LAHFSAHF)
+ ASMJIT_X86_FEATURE(LWP)
+ ASMJIT_X86_FEATURE(LZCNT)
+ ASMJIT_X86_FEATURE(MCOMMIT)
+ ASMJIT_X86_FEATURE(MMX)
+ ASMJIT_X86_FEATURE(MMX2)
+ ASMJIT_X86_FEATURE(MONITOR)
+ ASMJIT_X86_FEATURE(MONITORX)
+ ASMJIT_X86_FEATURE(MOVBE)
+ ASMJIT_X86_FEATURE(MOVDIR64B)
+ ASMJIT_X86_FEATURE(MOVDIRI)
+ ASMJIT_X86_FEATURE(MPX)
+ ASMJIT_X86_FEATURE(MSR)
+ ASMJIT_X86_FEATURE(MSSE)
+ ASMJIT_X86_FEATURE(OSXSAVE)
+ ASMJIT_X86_FEATURE(OSPKE)
+ ASMJIT_X86_FEATURE(PCLMULQDQ)
+ ASMJIT_X86_FEATURE(PCONFIG)
+ ASMJIT_X86_FEATURE(POPCNT)
+ ASMJIT_X86_FEATURE(PREFETCHW)
+ ASMJIT_X86_FEATURE(PREFETCHWT1)
+ ASMJIT_X86_FEATURE(PTWRITE)
+ ASMJIT_X86_FEATURE(RDPID)
+ ASMJIT_X86_FEATURE(RDPRU)
+ ASMJIT_X86_FEATURE(RDRAND)
+ ASMJIT_X86_FEATURE(RDSEED)
+ ASMJIT_X86_FEATURE(RDTSC)
+ ASMJIT_X86_FEATURE(RDTSCP)
+ ASMJIT_X86_FEATURE(RTM)
+ ASMJIT_X86_FEATURE(SERIALIZE)
+ ASMJIT_X86_FEATURE(SHA)
+ ASMJIT_X86_FEATURE(SKINIT)
+ ASMJIT_X86_FEATURE(SMAP)
+ ASMJIT_X86_FEATURE(SMEP)
+ ASMJIT_X86_FEATURE(SMX)
+ ASMJIT_X86_FEATURE(SNP)
+ ASMJIT_X86_FEATURE(SSE)
+ ASMJIT_X86_FEATURE(SSE2)
+ ASMJIT_X86_FEATURE(SSE3)
+ ASMJIT_X86_FEATURE(SSE4_1)
+ ASMJIT_X86_FEATURE(SSE4_2)
+ ASMJIT_X86_FEATURE(SSE4A)
+ ASMJIT_X86_FEATURE(SSSE3)
+ ASMJIT_X86_FEATURE(SVM)
+ ASMJIT_X86_FEATURE(TBM)
+ ASMJIT_X86_FEATURE(TSX)
+ ASMJIT_X86_FEATURE(TSXLDTRK)
+ ASMJIT_X86_FEATURE(UINTR)
+ ASMJIT_X86_FEATURE(VAES)
+ ASMJIT_X86_FEATURE(VMX)
+ ASMJIT_X86_FEATURE(VPCLMULQDQ)
+ ASMJIT_X86_FEATURE(WAITPKG)
+ ASMJIT_X86_FEATURE(WBNOINVD)
+ ASMJIT_X86_FEATURE(XOP)
+ ASMJIT_X86_FEATURE(XSAVE)
+ ASMJIT_X86_FEATURE(XSAVEC)
+ ASMJIT_X86_FEATURE(XSAVEOPT)
+ ASMJIT_X86_FEATURE(XSAVES)
+
+ #undef ASMJIT_X86_FEATURE
+ };
+
+ //! ARM specific features data.
+ struct ARM : public Data {
+ //! ARM CPU feature identifiers.
+ enum Id : uint8_t {
+ // @EnumValuesBegin{"enum": "CpuFeatures::ARM"}@
+ kNone = 0, //!< No feature (never set, used internally).
+ kTHUMB, //!< THUMB v1 ISA.
+ kTHUMBv2, //!< THUMB v2 ISA.
+
+ kARMv6, //!< ARMv6 ISA.
+ kARMv7, //!< ARMv7 ISA.
+ kARMv8a, //!< ARMv8-A ISA.
+ kARMv8_1a, //!< ARMv8.1-A ISA.
+ kARMv8_2a, //!< ARMv8.2-A ISA.
+ kARMv8_3a, //!< ARMv8.3-A ISA.
+ kARMv8_4a, //!< ARMv8.4-A ISA.
+ kARMv8_5a, //!< ARMv8.5-A ISA.
+ kARMv8_6a, //!< ARMv8.6-A ISA.
+ kARMv8_7a, //!< ARMv8.6-A ISA.
+
+ kVFPv2, //!< CPU has VFPv2 instruction set.
+ kVFPv3, //!< CPU has VFPv3 instruction set.
+ kVFPv4, //!< CPU has VFPv4 instruction set.
+ kVFP_D32, //!< CPU has 32 VFP-D (64-bit) registers.
+
+ kAES, //!< CPU has AES (AArch64 only).
+ kALTNZCV, //!< CPU has ALTNZCV (AArch64 only).
+ kASIMD, //!< CPU has Advanced SIMD (NEON on ARM/THUMB).
+ kBF16, //!< CPU has BF16 (AArch64 only).
+ kBTI, //!< CPU has BTI (branch target identification).
+ kCPUID, //!< CPU has accessible CPUID register (ID_AA64ZFR0_EL1).
+ kCRC32, //!< CPU has CRC32 .
+ kDGH, //!< CPU has DGH (AArch64 only).
+ kDIT, //!< CPU has data independent timing instructions (DIT).
+ kDOTPROD, //!< CPU has DOTPROD (SDOT/UDOT).
+ kEDSP, //!< CPU has EDSP (ARM/THUMB only).
+ kFCMA, //!< CPU has FCMA (FCADD/FCMLA).
+ kFJCVTZS, //!< CPU has FJCVTZS (AArch64 only).
+ kFLAGM, //!< CPU has FLAGM (AArch64 only).
+ kFP16CONV, //!< CPU has FP16 (half-float) conversion.
+ kFP16FML, //!< CPU has FMLAL{2}/FMLSL{2}
+ kFP16FULL, //!< CPU has full support for FP16.
+ kFRINT, //!< CPU has FRINT[32|64][X|Z] (AArch64 only).
+ kI8MM, //!< CPU has I8MM (AArch64 only).
+ kIDIVA, //!< CPU has hardware SDIV and UDIV (ARM mode).
+ kIDIVT, //!< CPU has hardware SDIV and UDIV (THUMB mode).
+ kLSE, //!< CPU has large system extensions (LSE) (AArch64 only).
+ kMTE, //!< CPU has MTE (AArch64 only).
+ kRCPC_IMMO, //!< CPU has RCPC_IMMO (AArch64 only).
+ kRDM, //!< CPU has RDM (AArch64 only).
+ kPMU, //!< CPU has PMU (AArch64 only).
+ kPMULL, //!< CPU has PMULL (AArch64 only).
+ kRNG, //!< CPU has random number generation (RNG).
+ kSB, //!< CPU has speculative barrier SB (AArch64 only).
+ kSHA1, //!< CPU has SHA1.
+ kSHA2, //!< CPU has SHA2.
+ kSHA3, //!< CPU has SHA3.
+ kSHA512, //!< CPU has SHA512.
+ kSM3, //!< CPU has SM3.
+ kSM4, //!< CPU has SM4.
+ kSSBS, //!< CPU has SSBS.
+ kSVE, //!< CPU has SVE (AArch64 only).
+ kSVE_BF16, //!< CPU has SVE-BF16 (AArch64 only).
+ kSVE_F32MM, //!< CPU has SVE-F32MM (AArch64 only).
+ kSVE_F64MM, //!< CPU has SVE-F64MM (AArch64 only).
+ kSVE_I8MM, //!< CPU has SVE-I8MM (AArch64 only).
+ kSVE_PMULL, //!< CPU has SVE-PMULL (AArch64 only).
+ kSVE2, //!< CPU has SVE2 (AArch64 only).
+ kSVE2_AES, //!< CPU has SVE2-AES (AArch64 only).
+ kSVE2_BITPERM, //!< CPU has SVE2-BITPERM (AArch64 only).
+ kSVE2_SHA3, //!< CPU has SVE2-SHA3 (AArch64 only).
+ kSVE2_SM4, //!< CPU has SVE2-SM4 (AArch64 only).
+ kTME, //!< CPU has transactional memory extensions (TME).
+ // @EnumValuesEnd@
+
+ kMaxValue = kTME
+ };
+
+ #define ASMJIT_ARM_FEATURE(FEATURE) \
+ inline bool has##FEATURE() const noexcept { return has(ARM::k##FEATURE); }
+
+ ASMJIT_ARM_FEATURE(THUMB)
+ ASMJIT_ARM_FEATURE(THUMBv2)
+
+ ASMJIT_ARM_FEATURE(ARMv6)
+ ASMJIT_ARM_FEATURE(ARMv7)
+ ASMJIT_ARM_FEATURE(ARMv8a)
+ ASMJIT_ARM_FEATURE(ARMv8_1a)
+ ASMJIT_ARM_FEATURE(ARMv8_2a)
+ ASMJIT_ARM_FEATURE(ARMv8_3a)
+ ASMJIT_ARM_FEATURE(ARMv8_4a)
+ ASMJIT_ARM_FEATURE(ARMv8_5a)
+ ASMJIT_ARM_FEATURE(ARMv8_6a)
+ ASMJIT_ARM_FEATURE(ARMv8_7a)
+
+ ASMJIT_ARM_FEATURE(VFPv2)
+ ASMJIT_ARM_FEATURE(VFPv3)
+ ASMJIT_ARM_FEATURE(VFPv4)
+ ASMJIT_ARM_FEATURE(VFP_D32)
+
+ ASMJIT_ARM_FEATURE(AES)
+ ASMJIT_ARM_FEATURE(ALTNZCV)
+ ASMJIT_ARM_FEATURE(ASIMD)
+ ASMJIT_ARM_FEATURE(BF16)
+ ASMJIT_ARM_FEATURE(BTI)
+ ASMJIT_ARM_FEATURE(CPUID)
+ ASMJIT_ARM_FEATURE(CRC32)
+ ASMJIT_ARM_FEATURE(DGH)
+ ASMJIT_ARM_FEATURE(DIT)
+ ASMJIT_ARM_FEATURE(DOTPROD)
+ ASMJIT_ARM_FEATURE(EDSP)
+ ASMJIT_ARM_FEATURE(FCMA)
+ ASMJIT_ARM_FEATURE(FLAGM)
+ ASMJIT_ARM_FEATURE(FP16CONV)
+ ASMJIT_ARM_FEATURE(FP16FML)
+ ASMJIT_ARM_FEATURE(FP16FULL)
+ ASMJIT_ARM_FEATURE(FRINT)
+ ASMJIT_ARM_FEATURE(IDIVA)
+ ASMJIT_ARM_FEATURE(IDIVT)
+ ASMJIT_ARM_FEATURE(LSE)
+ ASMJIT_ARM_FEATURE(MTE)
+ ASMJIT_ARM_FEATURE(FJCVTZS)
+ ASMJIT_ARM_FEATURE(I8MM)
+ ASMJIT_ARM_FEATURE(RCPC_IMMO)
+ ASMJIT_ARM_FEATURE(RDM)
+ ASMJIT_ARM_FEATURE(PMU)
+ ASMJIT_ARM_FEATURE(PMULL)
+ ASMJIT_ARM_FEATURE(RNG)
+ ASMJIT_ARM_FEATURE(SB)
+ ASMJIT_ARM_FEATURE(SHA1)
+ ASMJIT_ARM_FEATURE(SHA2)
+ ASMJIT_ARM_FEATURE(SHA3)
+ ASMJIT_ARM_FEATURE(SHA512)
+ ASMJIT_ARM_FEATURE(SM3)
+ ASMJIT_ARM_FEATURE(SM4)
+ ASMJIT_ARM_FEATURE(SSBS)
+ ASMJIT_ARM_FEATURE(SVE)
+ ASMJIT_ARM_FEATURE(SVE_BF16)
+ ASMJIT_ARM_FEATURE(SVE_F32MM)
+ ASMJIT_ARM_FEATURE(SVE_F64MM)
+ ASMJIT_ARM_FEATURE(SVE_I8MM)
+ ASMJIT_ARM_FEATURE(SVE_PMULL)
+ ASMJIT_ARM_FEATURE(SVE2)
+ ASMJIT_ARM_FEATURE(SVE2_AES)
+ ASMJIT_ARM_FEATURE(SVE2_BITPERM)
+ ASMJIT_ARM_FEATURE(SVE2_SHA3)
+ ASMJIT_ARM_FEATURE(SVE2_SM4)
+ ASMJIT_ARM_FEATURE(TME)
+
+ #undef ASMJIT_ARM_FEATURE
+ };
+
+ static_assert(uint32_t(X86::kMaxValue) < kMaxFeatures, "The number of X86 CPU features cannot exceed CpuFeatures::kMaxFeatures");
+ static_assert(uint32_t(ARM::kMaxValue) < kMaxFeatures, "The number of ARM CPU features cannot exceed CpuFeatures::kMaxFeatures");
+
+ //! \}
+
+ //! \name Members
+ //! \{
+
+ Data _data {};
+
+ //! \}
+
+ //! \name Construction & Destruction
+ //! \{
+
+ inline CpuFeatures() noexcept {}
+ inline CpuFeatures(const CpuFeatures& other) noexcept = default;
+ inline explicit CpuFeatures(Globals::NoInit_) noexcept {}
+
+ //! \}
+
+ //! \name Overloaded Operators
+ //! \{
+
+ inline CpuFeatures& operator=(const CpuFeatures& other) noexcept = default;
+
+ inline bool operator==(const CpuFeatures& other) noexcept { return eq(other); }
+ inline bool operator!=(const CpuFeatures& other) noexcept { return !eq(other); }
+
+ //! \}
+
+ //! \name Accessors
+ //! \{
+
+ //! Returns true if there are no features set.
+ inline bool empty() const noexcept { return _data.empty(); }
+
+ //! Casts this base class into a derived type `T`.
+ template<typename T = Data>
+ inline T& data() noexcept { return static_cast<T&>(_data); }
+
+ //! Casts this base class into a derived type `T` (const).
+ template<typename T = Data>
+ inline const T& data() const noexcept { return static_cast<const T&>(_data); }
+
+ //! Returns CpuFeatures::Data as \ref CpuFeatures::X86.
+ inline X86& x86() noexcept { return data<X86>(); }
+ //! Returns CpuFeatures::Data as \ref CpuFeatures::X86 (const).
+ inline const X86& x86() const noexcept { return data<X86>(); }
+
+ //! Returns CpuFeatures::Data as \ref CpuFeatures::ARM.
+ inline ARM& arm() noexcept { return data<ARM>(); }
+ //! Returns CpuFeatures::Data as \ref CpuFeatures::ARM (const).
+ inline const ARM& arm() const noexcept { return data<ARM>(); }
+
+ //! Returns all features as array of bitwords (see \ref Support::BitWord).
+ inline BitWord* bits() noexcept { return _data.bits(); }
+ //! Returns all features as array of bitwords (const).
+ inline const BitWord* bits() const noexcept { return _data.bits(); }
+ //! Returns the number of BitWords returned by \ref bits().
+ inline size_t bitWordCount() const noexcept { return _data.bitWordCount(); }
+
+ //! Returns \ref Support::BitVectorIterator, that can be used to iterate over all features efficiently.
+ inline Iterator iterator() const noexcept { return _data.iterator(); }
+
+ //! Tests whether the feature `featureId` is present.
+ template<typename FeatureId>
+ inline bool has(const FeatureId& featureId) const noexcept { return _data.has(featureId); }
+
+ //! Tests whether all features as defined by `other` are present.
+ inline bool hasAll(const CpuFeatures& other) const noexcept { return _data.hasAll(other._data); }
+
+ //! \}
+
+ //! \name Manipulation
+ //! \{
+
+ inline void reset() noexcept { _data.reset(); }
+
+ //! Adds the given CPU `featureId` to the list of features.
+ template<typename... Args>
+ inline void add(Args&&... args) noexcept { return _data.add(std::forward<Args>(args)...); }
+
+ //! Adds the given CPU `featureId` to the list of features if `condition` is true.
+ template<typename... Args>
+ inline void addIf(bool condition, Args&&... args) noexcept { return _data.addIf(condition, std::forward<Args>(args)...); }
+
+ //! Removes the given CPU `featureId` from the list of features.
+ template<typename... Args>
+ inline void remove(Args&&... args) noexcept { return _data.remove(std::forward<Args>(args)...); }
+
+ //! Tests whether this CPU features matches `other`.
+ inline bool eq(const CpuFeatures& other) const noexcept { return _data.eq(other._data); }
+
+ //! \}
+};
//! CPU information.
class CpuInfo {
public:
+ //! \name Members
+ //! \{
+
//! Architecture.
- uint8_t _arch;
+ Arch _arch;
//! Sub-architecture.
- uint8_t _subArch;
+ SubArch _subArch;
+ //! True if the CPU was detected, false if the detection failed or it's not available.
+ bool _wasDetected;
//! Reserved for future use.
- uint16_t _reserved;
+ uint8_t _reserved;
//! CPU family ID.
uint32_t _familyId;
//! CPU model ID.
@@ -69,7 +696,9 @@ public:
//! CPU brand string.
FixedString<64> _brand;
//! CPU features.
- BaseFeatures _features;
+ CpuFeatures _features;
+
+ //! \}
//! \name Construction & Destruction
//! \{
@@ -83,10 +712,10 @@ public:
//! Returns the host CPU information.
ASMJIT_API static const CpuInfo& host() noexcept;
- //! Initializes CpuInfo to the given architecture, see \ref Environment.
- inline void initArch(uint32_t arch, uint32_t subArch = 0u) noexcept {
- _arch = uint8_t(arch);
- _subArch = uint8_t(subArch);
+ //! Initializes CpuInfo architecture and sub-architecture members to `arch` and `subArch`, respectively.
+ inline void initArch(Arch arch, SubArch subArch = SubArch::kUnknown) noexcept {
+ _arch = arch;
+ _subArch = subArch;
}
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
@@ -103,46 +732,76 @@ public:
//! \name Accessors
//! \{
- //! Returns the CPU architecture id, see \ref Environment::Arch.
- inline uint32_t arch() const noexcept { return _arch; }
- //! Returns the CPU architecture sub-id, see \ref Environment::SubArch.
- inline uint32_t subArch() const noexcept { return _subArch; }
+ //! Returns the CPU architecture this information relates to.
+ inline Arch arch() const noexcept { return _arch; }
+
+ //! Returns the CPU sub-architecture this information relates to.
+ inline SubArch subArch() const noexcept { return _subArch; }
+
+ //! Returns whether the CPU was detected successfully.
+ //!
+ //! If the returned value is false it means that AsmJit either failed to detect the CPU or it doesn't have
+ //! implementation targeting the host architecture and operating system.
+ inline bool wasDetected() const noexcept { return _wasDetected; }
//! Returns the CPU family ID.
+ //!
+ //! Family identifier matches the FamilyId read by using CPUID on X86 architecture.
inline uint32_t familyId() const noexcept { return _familyId; }
+
//! Returns the CPU model ID.
+ //!
+ //! Family identifier matches the ModelId read by using CPUID on X86 architecture.
+
inline uint32_t modelId() const noexcept { return _modelId; }
//! Returns the CPU brand id.
+ //!
+ //! Family identifier matches the BrandId read by using CPUID on X86 architecture.
inline uint32_t brandId() const noexcept { return _brandId; }
+
//! Returns the CPU stepping.
+ //!
+ //! Family identifier matches the Stepping information read by using CPUID on X86 architecture.
inline uint32_t stepping() const noexcept { return _stepping; }
+
//! Returns the processor type.
+ //!
+ //! Family identifier matches the ProcessorType read by using CPUID on X86 architecture.
inline uint32_t processorType() const noexcept { return _processorType; }
- //! Returns the number of maximum logical processors.
+
+ //! Returns the maximum number of logical processors.
inline uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; }
//! Returns the size of a cache line flush.
inline uint32_t cacheLineSize() const noexcept { return _cacheLineSize; }
+
//! Returns number of hardware threads available.
inline uint32_t hwThreadCount() const noexcept { return _hwThreadCount; }
- //! Returns the CPU vendor.
+ //! Returns a CPU vendor string.
inline const char* vendor() const noexcept { return _vendor.str; }
- //! Tests whether the CPU vendor is equal to `s`.
+ //! Tests whether the CPU vendor string is equal to `s`.
inline bool isVendor(const char* s) const noexcept { return _vendor.eq(s); }
- //! Returns the CPU brand string.
+ //! Returns a CPU brand string.
inline const char* brand() const noexcept { return _brand.str; }
- //! Returns all CPU features as `BaseFeatures`, cast to your arch-specific class
- //! if needed.
- template<typename T = BaseFeatures>
- inline const T& features() const noexcept { return _features.as<T>(); }
+ //! Returns CPU features.
+ inline CpuFeatures& features() noexcept { return _features; }
+ //! Returns CPU features (const).
+ inline const CpuFeatures& features() const noexcept { return _features; }
//! Tests whether the CPU has the given `feature`.
- inline bool hasFeature(uint32_t featureId) const noexcept { return _features.has(featureId); }
- //! Adds the given CPU `feature` to the list of this CpuInfo features.
- inline CpuInfo& addFeature(uint32_t featureId) noexcept { _features.add(featureId); return *this; }
+ template<typename FeatureId>
+ inline bool hasFeature(const FeatureId& featureId) const noexcept { return _features.has(featureId); }
+
+ //! Adds the given CPU `featureId` to the list of features.
+ template<typename... Args>
+ inline void addFeature(Args&&... args) noexcept { return _features.add(std::forward<Args>(args)...); }
+
+ //! Removes the given CPU `featureId` from the list of features.
+ template<typename... Args>
+ inline void removeFeature(Args&&... args) noexcept { return _features.remove(std::forward<Args>(args)...); }
//! \}
};