diff options
Diffstat (limited to '3rdparty/asmjit/src')
139 files changed, 20096 insertions, 12205 deletions
diff --git a/3rdparty/asmjit/src/asmjit/a64.h b/3rdparty/asmjit/src/asmjit/a64.h index ea4d304f058..e849eb3a8ca 100644 --- a/3rdparty/asmjit/src/asmjit/a64.h +++ b/3rdparty/asmjit/src/asmjit/a64.h @@ -18,25 +18,24 @@ //! ### Supported Instructions //! //! - Emitters: -//! - \ref a64::EmitterExplicitT - Provides all instructions that use explicit -//! operands, provides also utility functions. The member functions provided -//! are part of all ARM/AArch64 emitters. +//! - \ref a64::EmitterExplicitT - Provides all instructions that use explicit operands, provides also utility +//! functions. The member functions provided are part of all AArch64 emitters. //! //! - Instruction representation: //! - \ref a64::Inst::Id - instruction identifiers. //! //! ### Register Operands //! -//! - \ref arm::Reg - Base class for any AArch32/AArch64 register. -//! - \ref arm::Gp - General purpose register: -//! - \ref arm::GpW - 32-bit register. -//! - \ref arm::GpX - 64-bit register. -//! - \ref arm::Vec - Vector (SIMD) register: -//! - \ref arm::VecB - 8-bit SIMD register (AArch64 only). -//! - \ref arm::VecH - 16-bit SIMD register (AArch64 only). -//! - \ref arm::VecS - 32-bit SIMD register. -//! - \ref arm::VecD - 64-bit SIMD register. -//! - \ref arm::VecV - 128-bit SIMD register. +//! - \ref arm::Reg - Base class of all AArch32/AArch64 registers. +//! - \ref a64::Gp - General purpose register (AArch64): +//! - \ref a64::GpW - 32-bit general purpose register (AArch64). +//! - \ref a64::GpX - 64-bit general purpose register (AArch64). +//! - \ref a64::Vec - Vector (SIMD) register: +//! - \ref a64::VecB - 8-bit SIMD register. +//! - \ref a64::VecH - 16-bit SIMD register. +//! - \ref a64::VecS - 32-bit SIMD register. +//! - \ref a64::VecD - 64-bit SIMD register. +//! - \ref a64::VecV - 128-bit SIMD register. //! //! ### Memory Operands //! @@ -46,7 +45,7 @@ //! ### Other //! //! - \ref arm::Shift - Shift operation and value. -//! - \ref a64::Utils - Utilities that can help during code generation for AArch64. +//! - \ref arm::Utils - Utilities that can help during code generation for AArch32 and AArch64. #include "./arm.h" #include "./arm/a64assembler.h" @@ -56,7 +55,6 @@ #include "./arm/a64globals.h" #include "./arm/a64instdb.h" #include "./arm/a64operand.h" -#include "./arm/a64utils.h" #endif // ASMJIT_A64_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/arm.h b/3rdparty/asmjit/src/asmjit/arm.h index 57ffa815b8c..e4a3e3d3ac5 100644 --- a/3rdparty/asmjit/src/asmjit/arm.h +++ b/3rdparty/asmjit/src/asmjit/arm.h @@ -11,11 +11,19 @@ //! ### Namespaces //! //! - \ref arm - arm namespace provides common functionality for both AArch32 and AArch64 backends. +//! - \ref a32 - a32 namespace provides support for AArch32 architecture. In addition it includes +//! \ref arm namespace, so you can only use a single namespace when targeting AArch32 architecture. //! - \ref a64 - a64 namespace provides support for AArch64 architecture. In addition it includes //! \ref arm namespace, so you can only use a single namespace when targeting AArch64 architecture. //! //! ### Emitters //! +//! - AArch32 +//! - \ref a32::Assembler - AArch32 assembler (must read, provides examples). +//! - \ref a32::Builder - AArch32 builder. +//! - \ref a32::Compiler - AArch32 compiler. +//! - \ref a32::Emitter - AArch32 emitter (abstract). +//! //! - AArch64 //! - \ref a64::Assembler - AArch64 assembler (must read, provides examples). //! - \ref a64::Builder - AArch64 builder. @@ -24,6 +32,13 @@ //! //! ### Supported Instructions //! +//! - AArch32: +//! - Emitters: +//! - \ref a32::EmitterExplicitT - Provides all instructions that use explicit operands, provides also +//! utility functions. The member functions provided are part of all AArch32 emitters. +//! - Instruction representation: +//! - \ref a32::Inst::Id - instruction identifiers. +//! //! - AArch64: //! - Emitters: //! - \ref a64::EmitterExplicitT - Provides all instructions that use explicit operands, provides also @@ -33,16 +48,22 @@ //! //! ### Register Operands //! -//! - \ref arm::Reg - Base class for any AArch32/AArch64 register. -//! - \ref arm::Gp - General purpose register: -//! - \ref arm::GpW - 32-bit register. -//! - \ref arm::GpX - 64-bit register. -//! - \ref arm::Vec - Vector (SIMD) register: -//! - \ref arm::VecB - 8-bit SIMD register (AArch64 only). -//! - \ref arm::VecH - 16-bit SIMD register (AArch64 only). -//! - \ref arm::VecS - 32-bit SIMD register. -//! - \ref arm::VecD - 64-bit SIMD register. -//! - \ref arm::VecV - 128-bit SIMD register. +//! - \ref arm::Reg - Base class of all AArch32/AArch64 registers. +//! - \ref a32::Gp - 32-bit general purpose register used by AArch32: +//! - \ref a64::Gp - 32-bit or 64-bit general purpose register used by AArch64: +//! - \ref a64::GpW - 32-bit register (AArch64). +//! - \ref a64::GpX - 64-bit register (AArch64). +//! - \ref arm::BaseVec - Base vector (SIMD) register. +//! - \ref a32::Vec - Vector (SIMD) register (AArch32): +//! - \ref a32::VecS - 32-bit SIMD register (AArch32). +//! - \ref a32::VecD - 64-bit SIMD register (AArch32). +//! - \ref a32::VecV - 128-bit SIMD register (AArch32). +//! - \ref a64::Vec - Vector (SIMD) register (AArch64): +//! - \ref a64::VecB - 8-bit SIMD register (AArch64). +//! - \ref a64::VecH - 16-bit SIMD register (AArch64). +//! - \ref a64::VecS - 32-bit SIMD register (AArch64). +//! - \ref a64::VecD - 64-bit SIMD register (AArch64). +//! - \ref a64::VecV - 128-bit SIMD register (AArch64). //! //! ### Memory Operands //! @@ -53,10 +74,11 @@ //! //! - \ref arm::Shift - Shift operation and value (both AArch32 and AArch64). //! - \ref arm::DataType - Data type that is part of an instruction in AArch32 mode. -//! - \ref a64::Utils - Utilities that can help during code generation for AArch64. +//! - \ref arm::Utils - Utilities that can help during code generation for AArch32 and AArch64. #include "./core.h" #include "./arm/armglobals.h" #include "./arm/armoperand.h" +#include "./arm/armutils.h" #endif // ASMJIT_ARM_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/arm/a64archtraits_p.h b/3rdparty/asmjit/src/asmjit/arm/a64archtraits_p.h index 87559c71d5a..4b5bde68a9e 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64archtraits_p.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64archtraits_p.h @@ -9,6 +9,7 @@ #include "../core/archtraits.h" #include "../core/misc_p.h" #include "../core/type.h" +#include "../arm/a64globals.h" #include "../arm/a64operand.h" ASMJIT_BEGIN_SUB_NAMESPACE(a64) @@ -24,7 +25,7 @@ static const constexpr ArchTraits a64ArchTraits = { // Reserved. { 0, 0, 0 }, - // HW stack alignment (AArch64 requires stack aligned to 64 bytes). + // HW stack alignment (AArch64 requires stack aligned to 16 bytes at HW level). 16, // Min/max stack offset - byte addressing is the worst, VecQ addressing the best. @@ -39,12 +40,12 @@ static const constexpr ArchTraits a64ArchTraits = { }}, // RegInfo. - #define V(index) OperandSignature{arm::RegTraits<RegType(index)>::kSignature} + #define V(index) OperandSignature{RegTraits<RegType(index)>::kSignature} {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, #undef V // RegTypeToTypeId. - #define V(index) TypeId(arm::RegTraits<RegType(index)>::kTypeId) + #define V(index) TypeId(RegTraits<RegType(index)>::kTypeId) {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, #undef V diff --git a/3rdparty/asmjit/src/asmjit/arm/a64assembler.cpp b/3rdparty/asmjit/src/asmjit/arm/a64assembler.cpp index 485f05f491f..32514b9bad9 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64assembler.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64assembler.cpp @@ -14,19 +14,23 @@ #include "../core/misc_p.h" #include "../core/support.h" #include "../arm/armformatter_p.h" +#include "../arm/armutils.h" #include "../arm/a64assembler.h" #include "../arm/a64emithelper_p.h" #include "../arm/a64instdb_p.h" -#include "../arm/a64utils.h" ASMJIT_BEGIN_SUB_NAMESPACE(a64) +// a64::Assembler - Utils +// ====================== + +static ASMJIT_FORCE_INLINE constexpr uint32_t diff(RegType a, RegType b) noexcept { return uint32_t(a) - uint32_t(b); } +static ASMJIT_FORCE_INLINE constexpr uint32_t diff(VecElementType elementType, VecElementType baseType) noexcept { return uint32_t(elementType) - uint32_t(baseType); } + // a64::Assembler - Cond // ===================== -static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept { - return (uint32_t(cond) - 2u) & 0xFu; -} +static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept { return (uint32_t(cond) - 2u) & 0xFu; } // a64::Assembler - Bits // ===================== @@ -49,8 +53,19 @@ static constexpr uint32_t kWX = InstDB::kWX; static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; #undef VALUE -static inline constexpr uint32_t diff(RegType a, RegType b) noexcept { - return uint32_t(a) - uint32_t(b); +// a64::Assembler - ExtendOpToRegType +// ================================== + +static inline RegType extendOptionToRegType(uint32_t option) noexcept { + uint32_t pred = (uint32_t(RegType::kARM_GpW) << (0x0 * 4)) | // 0b000 - UXTB. + (uint32_t(RegType::kARM_GpW) << (0x1 * 4)) | // 0b001 - UXTH. + (uint32_t(RegType::kARM_GpW) << (0x2 * 4)) | // 0b010 - UXTW. + (uint32_t(RegType::kARM_GpX) << (0x3 * 4)) | // 0b011 - UXTX|LSL. + (uint32_t(RegType::kARM_GpW) << (0x4 * 4)) | // 0b100 - SXTB. + (uint32_t(RegType::kARM_GpW) << (0x5 * 4)) | // 0b101 - SXTH. + (uint32_t(RegType::kARM_GpW) << (0x6 * 4)) | // 0b110 - SXTW. + (uint32_t(RegType::kARM_GpX) << (0x7 * 4)) ; // 0b111 - SXTX. + return RegType((pred >> (option * 4u)) & 0xFu); } // asmjit::a64::Assembler - SizeOp @@ -118,25 +133,25 @@ struct SizeOpTable { }; #define VALUE_BIN(x) { \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00Q : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : SizeOp::kInvalid \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00Q : SizeOp::kInvalid \ } #define VALUE_ANY(x) { \ - x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00S : \ - x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k01S : \ - x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k10S : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k11S : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01Q : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10Q : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11S : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11Q : SizeOp::kInvalid \ + x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00S : \ + x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k01S : \ + x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k10S : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k11S : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kH )) ? SizeOp::k01 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kH )) ? SizeOp::k01Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kS )) ? SizeOp::k10 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kS )) ? SizeOp::k10Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kD )) ? SizeOp::k11S : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kD )) ? SizeOp::k11Q : SizeOp::kInvalid \ } static const SizeOpTable sizeOpTable[SizeOpTable::kCount] = { @@ -254,16 +269,16 @@ static const Operand_& significantSimdOp(const Operand_& o0, const Operand_& o1, return !(instFlags & InstDB::kInstFlagLong) ? o0 : o1; } -static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, uint32_t elementType) noexcept { +static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, VecElementType elementType) noexcept { // Instruction data or Assembler is wrong if this triggers an assertion failure. ASMJIT_ASSERT(vecOpType < InstDB::kVO_Count); // ElementType uses 3 bits in the operand signature, it should never overflow. - ASMJIT_ASSERT(elementType <= 0x7u); + ASMJIT_ASSERT(uint32_t(elementType) <= 0x7u); const SizeOpMap& map = sizeOpMap[vecOpType]; const SizeOpTable& table = sizeOpTable[map.tableId]; - size_t index = (Support::min<uint32_t>(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | elementType; + size_t index = (Support::min<uint32_t>(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | uint32_t(elementType); SizeOp op = table.array[index]; SizeOp modifiedOp { uint8_t(op.value & map.sizeOpMask) }; @@ -398,14 +413,6 @@ static inline bool encodeLMH(uint32_t sizeField, uint32_t elementIndex, LMHImm* return elementIndex <= maxElementIndex; } -// [.......A|B.......|.......C|D.......|.......E|F.......|.......G|H.......] -static inline uint32_t encodeImm64ByteMaskToImm8(uint64_t imm) noexcept { - return uint32_t(((imm >> (7 - 0)) & 0b00000011) | // [.......G|H.......] - ((imm >> (23 - 2)) & 0b00001100) | // [.......E|F.......] - ((imm >> (39 - 4)) & 0b00110000) | // [.......C|D.......] - ((imm >> (55 - 6)) & 0b11000000)); // [.......A|B.......] -} - // a64::Assembler - Opcode // ======================= @@ -475,7 +482,7 @@ static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const } static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, uint32_t instFlags) noexcept { - return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature() && o2.signature() == o3.signature();; + return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature() && o2.signature() == o3.signature(); } // Memory must be either: @@ -545,7 +552,7 @@ static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint else { // Vector operation [HSD]. uint32_t q = diff(reg.type(), RegType::kARM_VecD); - uint32_t sz = reg.elementType() - Vec::kElementTypeH; + uint32_t sz = diff(reg.elementType(), VecElementType::kH); if (q > 1u || sz > 2u || !Support::bitTest(szBits[vHf].sizeMask, sz)) return false; @@ -698,25 +705,25 @@ static const Support::Array<uint8_t, 32> commonHiRegIdOfType = {{ #undef V static inline bool checkValidRegs(const Operand_& o0) noexcept { - return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])); + return bool(unsigned(o0.id() < 31) | unsigned(o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])); } static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1) noexcept { - return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & - ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) ; + return bool((unsigned(o0.id() < 31) | unsigned(o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & + (unsigned(o1.id() < 31) | unsigned(o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()]))); } static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { - return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & - ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) & - ((o2.id() < 31) | (o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) ; + return bool((unsigned(o0.id() < 31) | unsigned(o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & + (unsigned(o1.id() < 31) | unsigned(o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) & + (unsigned(o2.id() < 31) | unsigned(o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()]))); } static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { - return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & - ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) & - ((o2.id() < 31) | (o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) & - ((o3.id() < 31) | (o3.id() == commonHiRegIdOfType[o3.as<Reg>().type()])) ; + return bool((unsigned(o0.id() < 31) | unsigned(o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & + (unsigned(o1.id() < 31) | unsigned(o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) & + (unsigned(o2.id() < 31) | unsigned(o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) & + (unsigned(o3.id() < 31) | unsigned(o3.id() == commonHiRegIdOfType[o3.as<Reg>().type()]))); } // a64::Assembler - Construction & Destruction @@ -724,8 +731,6 @@ static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -811,7 +816,7 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co Operand_ opArray[Globals::kMaxOpCount]; EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); + err = _funcs.validate(BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); if (ASMJIT_UNLIKELY(err)) goto Failed; } @@ -1238,9 +1243,6 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co } if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - if (!checkSignature(o1, o2)) - goto InvalidInstruction; - uint32_t opSize = x ? 64 : 32; uint64_t shift = 0; uint32_t sType = uint32_t(ShiftOp::kLSL); @@ -1257,11 +1259,17 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co if (sType <= uint32_t(ShiftOp::kASR)) { bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP(); if (!hasSP) { - if (!checkGpId(o0, o1, kZR)) + if (!checkSignature(o1, o2)) { + goto InvalidInstruction; + } + + if (!checkGpId(o0, o1, kZR)) { goto InvalidPhysId; + } - if (shift >= opSize) + if (shift >= opSize) { goto InvalidImmediate; + } opcode.reset(uint32_t(opData.shiftedOp) << 21); opcode.addImm(x, 31); @@ -1274,8 +1282,10 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co } // SP register can only be used with LSL or Extend. - if (sType != uint32_t(ShiftOp::kLSL)) + if (sType != uint32_t(ShiftOp::kLSL)) { goto InvalidImmediate; + } + sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW); } @@ -1283,8 +1293,9 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co opcode.reset(uint32_t(opData.extendedOp) << 21); sType -= uint32_t(ShiftOp::kUXTB); - if (sType > 7 || shift > 4) + if (sType > 7 || shift > 4) { goto InvalidImmediate; + } if (!(opcode.get() & B(29))) { // ADD|SUB (extend) - ZR is not allowed. @@ -1297,6 +1308,11 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co goto InvalidPhysId; } + // Validate whether the register operands match extend option. + if (o2.as<Reg>().type() != extendOptionToRegType(sType) || o1.as<Reg>().type() < o2.as<Reg>().type()) { + goto InvalidInstruction; + } + opcode.addImm(x, 31); opcode.addReg(o2, 16); opcode.addImm(sType, 13); @@ -1422,9 +1438,6 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co } if (isign4 == ENC_OPS2(Reg, Reg) || isign4 == ENC_OPS3(Reg, Reg, Imm)) { - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - uint32_t opSize = x ? 64 : 32; uint32_t sType = 0; uint64_t shift = 0; @@ -1439,8 +1452,13 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co // Shift operation - LSL, LSR, ASR. if (sType <= uint32_t(ShiftOp::kASR)) { if (!hasSP) { - if (shift >= opSize) + if (!checkSignature(o0, o1)) { + goto InvalidInstruction; + } + + if (shift >= opSize) { goto InvalidImmediate; + } opcode.reset(uint32_t(opData.shiftedOp) << 21); opcode.addImm(x, 31); @@ -1461,8 +1479,14 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX. sType -= uint32_t(ShiftOp::kUXTB); - if (sType > 7 || shift > 4) + if (sType > 7 || shift > 4) { goto InvalidImmediate; + } + + // Validate whether the register operands match extend option. + if (o1.as<Reg>().type() != extendOptionToRegType(sType) || o0.as<Reg>().type() < o1.as<Reg>().type()) { + goto InvalidInstruction; + } opcode.reset(uint32_t(opData.extendedOp) << 21); opcode.addImm(x, 31); @@ -2250,6 +2274,86 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co } // ------------------------------------------------------------------------ + // [Base - Prefetch] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBasePrfm: { + const InstDB::EncodingData::BasePrfm& opData = InstDB::EncodingData::basePrfm[encodingIndex]; + + if (isign4 == ENC_OPS2(Imm, Mem)) { + const Mem& m = o1.as<Mem>(); + rmRel = &m; + + uint32_t immShift = 3u; + + if (o0.as<Imm>().valueAs<uint64_t>() > 0x1Fu) + goto InvalidImmediate; + + if (!armCheckMemBaseIndexRel(m)) + goto InvalidAddress; + + int64_t offset = m.offset(); + uint32_t prfop = o0.as<Imm>().valueAs<uint32_t>(); + + if (m.hasBaseReg()) { + // [Base {Offset | Index}] + if (m.hasIndex()) { + uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; + if (opt == 0xFF) + goto InvalidAddress; + + uint32_t shift = m.shift(); + uint32_t s = shift != 0; + + if (s && shift != immShift) + goto InvalidAddressScale; + + opcode.reset(uint32_t(opData.registerOp) << 21); + opcode.addImm(opt, 13); + opcode.addImm(s, 12); + opcode |= B(11); + opcode.addImm(prfop, 0); + goto EmitOp_MemBaseIndex_Rn5_Rm16; + } + + if (!Support::isInt32(offset)) + goto InvalidDisplacement; + + int32_t offset32 = int32_t(offset); + + if (m.isPreOrPost()) + goto InvalidAddress; + + uint32_t imm12 = uint32_t(offset32) >> immShift; + + if (Support::isUInt12(imm12) && (imm12 << immShift) == uint32_t(offset32)) { + opcode.reset(uint32_t(opData.sOffsetOp) << 22); + opcode.addImm(imm12, 10); + opcode.addImm(prfop, 0); + goto EmitOp_MemBase_Rn5; + } + + if (Support::isInt9(offset32)) { + opcode.reset(uint32_t(opData.uOffsetOp) << 21); + opcode.addImm(uint32_t(offset32) & 0x1FFu, 12); + opcode.addImm(prfop, 0); + goto EmitOp_MemBase_Rn5; + } + + goto InvalidAddress; + } + else { + opcode.reset(uint32_t(opData.literalOp) << 24); + opcode.addImm(prfop, 0); + offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); + goto EmitOp_Rel; + } + } + + break; + } + + // ------------------------------------------------------------------------ // [Base - Load / Store] // ------------------------------------------------------------------------ @@ -2280,7 +2384,7 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co if (m.hasBaseReg()) { // [Base {Offset | Index}] if (m.hasIndex()) { - uint32_t opt = armShiftOpToLdStOptMap[m.predicate()]; + uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; if (opt == 0xFF) goto InvalidAddress; @@ -2698,7 +2802,7 @@ Case_BaseLdurStur: // hD, vS.{4|8}h (16-bit) // sD, vS.4s (32-bit) uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); - uint32_t elementSz = o1.as<Vec>().elementType() - Vec::kElementTypeH; + uint32_t elementSz = diff(o1.as<Vec>().elementType(), VecElementType::kH); // Size greater than 1 means 64-bit elements, not supported. if ((sz | elementSz) > 1 || sz != elementSz) @@ -2820,7 +2924,7 @@ Case_BaseLdurStur: if (q > 1) goto InvalidInstruction; - uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB; + uint32_t sz = diff(o0.as<Vec>().elementType(), VecElementType::kB); if (sz == 0 || sz > 3) goto InvalidInstruction; @@ -2912,7 +3016,7 @@ Case_BaseLdurStur: if (q > 1) goto InvalidInstruction; - uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB; + uint32_t sz = diff(o0.as<Vec>().elementType(), VecElementType::kB); if (sz == 0 || sz > 3) goto InvalidInstruction; @@ -3094,11 +3198,11 @@ Case_BaseLdurStur: if (uint32_t(opcode.hasQ()) != q) goto InvalidInstruction; - if (rL.isVecS4() && rN.elementType() == Vec::kElementTypeH && !opData.isCvtxn()) { + if (rL.isVecS4() && rN.elementType() == VecElementType::kH && !opData.isCvtxn()) { goto EmitOp_Rd0_Rn5; } - if (rL.isVecD2() && rN.elementType() == Vec::kElementTypeS) { + if (rL.isVecD2() && rN.elementType() == VecElementType::kS) { opcode |= B(22); goto EmitOp_Rd0_Rn5; } @@ -3209,8 +3313,8 @@ Case_BaseLdurStur: } if (uint32_t(o0.as<Reg>().type()) != uint32_t(o1.as<Reg>().type()) + qIsOptional || - o0.as<Vec>().elementType() != opData.tA || - o1.as<Vec>().elementType() != opData.tB) + uint32_t(o0.as<Vec>().elementType()) != opData.tA || + uint32_t(o1.as<Vec>().elementType()) != opData.tB) goto InvalidInstruction; if (!o2.as<Vec>().hasElementIndex()) { @@ -3222,7 +3326,7 @@ Case_BaseLdurStur: goto EmitOp_Rd0_Rn5_Rm16; } else { - if (o2.as<Vec>().elementType() != opData.tElement) + if (uint32_t(o2.as<Vec>().elementType()) != opData.tElement) goto InvalidInstruction; if (o2.as<Reg>().id() > 15) @@ -3372,7 +3476,7 @@ Case_BaseLdurStur: } else { uint32_t q = diff(o0.as<Vec>().type(), RegType::kARM_VecD); - uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH; + uint32_t sz = diff(o0.as<Vec>().elementType(), VecElementType::kH); if (q > 1 || sz > 2) goto InvalidInstruction; @@ -3426,7 +3530,7 @@ Case_BaseLdurStur: if (q > 1) goto InvalidInstruction; - uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH; + uint32_t sz = diff(o0.as<Vec>().elementType(), VecElementType::kH); if (sz > 2) goto InvalidInstruction; @@ -3450,7 +3554,7 @@ Case_BaseLdurStur: if (isign4 == ENC_OPS2(Reg, Reg)) { // The first destination operand is scalar, which matches element-type of source vectors. uint32_t L = (instFlags & InstDB::kInstFlagLong) != 0; - if (diff(o0.as<Vec>().type(), RegType::kARM_VecB) != o1.as<Vec>().elementType() - Vec::kElementTypeB + L) + if (diff(o0.as<Vec>().type(), RegType::kARM_VecB) != diff(o1.as<Vec>().elementType(), VecElementType::kB) + L) goto InvalidInstruction; SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType()); @@ -3550,7 +3654,7 @@ Case_BaseLdurStur: if (!sizeOp.isValid()) goto InvalidInstruction; - if (!checkSignature(o0, o1) || !o0.as<Reg>().isVecV() || o0.as<Vec>().elementType() != o2.as<Vec>().elementType() + 1) + if (!checkSignature(o0, o1) || !o0.as<Reg>().isVecV() || uint32_t(o0.as<Vec>().elementType()) != uint32_t(o2.as<Vec>().elementType()) + 1u) goto InvalidInstruction; opcode.reset(opData.opcode()); @@ -3753,7 +3857,7 @@ Case_BaseLdurStur: goto InvalidImmediate; } else if (imm) { - shift = Support::ctz(imm) & 0x7u; + shift = Support::ctz(imm) & ~0x7u; imm >>= shift; if (imm > 0xFFu || shift > maxShift) @@ -3835,9 +3939,9 @@ Case_BaseLdurStur: if (o0.as<Reg>().type() != o1.as<Reg>().type() || o1.as<Reg>().type() != o2.as<Reg>().type()) goto InvalidInstruction; - if (o0.as<Vec>().elementType() != opData.tA || - o1.as<Vec>().elementType() != opData.tB || - o2.as<Vec>().elementType() != opData.tB) + if (uint32_t(o0.as<Vec>().elementType()) != opData.tA || + uint32_t(o1.as<Vec>().elementType()) != opData.tB || + uint32_t(o2.as<Vec>().elementType()) != opData.tB) goto InvalidInstruction; opcode.reset(uint32_t(opData.vectorOp) << 10); @@ -3851,9 +3955,9 @@ Case_BaseLdurStur: if (o0.as<Reg>().type() != o1.as<Reg>().type() || !o2.as<Reg>().isVecV()) goto InvalidInstruction; - if (o0.as<Vec>().elementType() != opData.tA || - o1.as<Vec>().elementType() != opData.tB || - o2.as<Vec>().elementType() != opData.tElement) + if (uint32_t(o0.as<Vec>().elementType()) != opData.tA || + uint32_t(o1.as<Vec>().elementType()) != opData.tB || + uint32_t(o2.as<Vec>().elementType()) != opData.tElement) goto InvalidInstruction; uint32_t elementIndex = o2.as<Vec>().elementIndex(); @@ -3879,13 +3983,13 @@ Case_BaseLdurStur: case InstDB::kEncodingSimdDup: SimdDup: { if (isign4 == ENC_OPS2(Reg, Reg)) { // Truth table of valid encodings of `Q:1|ElementType:3` - uint32_t kValidEncodings = B(Vec::kElementTypeB + 0) | - B(Vec::kElementTypeH + 0) | - B(Vec::kElementTypeS + 0) | - B(Vec::kElementTypeB + 8) | - B(Vec::kElementTypeH + 8) | - B(Vec::kElementTypeS + 8) | - B(Vec::kElementTypeD + 8) ; + uint32_t kValidEncodings = B(uint32_t(VecElementType::kB) + 0) | + B(uint32_t(VecElementType::kH) + 0) | + B(uint32_t(VecElementType::kS) + 0) | + B(uint32_t(VecElementType::kB) + 8) | + B(uint32_t(VecElementType::kH) + 8) | + B(uint32_t(VecElementType::kS) + 8) | + B(uint32_t(VecElementType::kD) + 8) ; uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); @@ -3894,7 +3998,7 @@ Case_BaseLdurStur: // // NOTE: This is only scalar for `dup d, x` case, otherwise the value // would be duplicated across all vector elements (1, 2, 4, 8, or 16). - uint32_t elementType = o0.as<Vec>().elementType(); + uint32_t elementType = uint32_t(o0.as<Vec>().elementType()); if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) goto InvalidInstruction; @@ -3915,7 +4019,7 @@ Case_BaseLdurStur: // DUP - Vec (scalar) <- Vec[N]. uint32_t lsbIndex = diff(o0.as<Reg>().type(), RegType::kARM_VecB); - if (lsbIndex != o1.as<Vec>().elementType() - Vec::kElementTypeB || lsbIndex > 3) + if (lsbIndex != diff(o1.as<Vec>().elementType(), VecElementType::kB) || lsbIndex > 3) goto InvalidInstruction; uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; @@ -3928,7 +4032,7 @@ Case_BaseLdurStur: } else { // DUP - Vec (all) <- Vec[N]. - uint32_t elementType = o0.as<Vec>().elementType(); + uint32_t elementType = uint32_t(o0.as<Vec>().elementType()); if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) goto InvalidInstruction; @@ -3953,7 +4057,7 @@ Case_BaseLdurStur: if (!o0.as<Vec>().hasElementIndex()) goto InvalidInstruction; - uint32_t elementType = o0.as<Vec>().elementType(); + uint32_t elementType = uint32_t(o0.as<Vec>().elementType()); uint32_t dstIndex = o0.as<Vec>().elementIndex(); uint32_t lsbIndex = elementType - 1u; @@ -4056,7 +4160,7 @@ Case_BaseLdurStur: goto InvalidImmediate; if (Utils::isByteMaskImm8(imm64)) { - imm8 = encodeImm64ByteMaskToImm8(imm64); + imm8 = Utils::encodeImm64ByteMaskToImm8(imm64); } else { // Change from D to S and from 64-bit imm to 32-bit imm if this @@ -4122,7 +4226,6 @@ Case_BaseLdurStur: if (inverted) { imm8 = ~imm8 & 0xFFu; - inverted = 0; } cmode = B(3) | B(2) | B(1); @@ -4155,7 +4258,6 @@ Case_BaseLdurStur: case 3: if (inverted) { imm8 = ~imm8 & 0xFFu; - inverted = 0; } op = 1; @@ -4443,7 +4545,7 @@ Case_BaseLdurStur: if (m.hasBaseReg()) { // [Base {Offset | Index}] if (m.hasIndex()) { - uint32_t opt = armShiftOpToLdStOptMap[m.predicate()]; + uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; if (opt == 0xFFu) goto InvalidAddress; @@ -4667,7 +4769,7 @@ Case_SimdLdurStur: uint32_t q = 0; uint32_t rm = 0; uint32_t rn = m.baseId(); - uint32_t sz = v.elementType() - Vec::kElementTypeB; + uint32_t sz = diff(v.elementType(), VecElementType::kB); uint32_t opcSsize = sz; uint32_t offsetPossibility = 0; @@ -4997,9 +5099,7 @@ EmitDone: #endif } - resetExtraReg(); - resetInstOptions(); - resetInlineComment(); + resetState(); writer.done(this); return kErrorOk; @@ -5025,9 +5125,7 @@ Failed: #ifndef ASMJIT_NO_LOGGING return EmitterUtils::logInstructionFailed(this, err, instId, options, o0, o1, o2, opExt); #else - resetExtraReg(); - resetInstOptions(); - resetInlineComment(); + resetState(); return reportError(err); #endif } @@ -5103,6 +5201,10 @@ Error Assembler::align(AlignMode alignMode, uint32_t alignment) { Error Assembler::onAttach(CodeHolder* code) noexcept { ASMJIT_PROPAGATE(Base::onAttach(code)); + + _instructionAlignment = uint8_t(4); + assignEmitterFuncs(this); + return kErrorOk; } diff --git a/3rdparty/asmjit/src/asmjit/arm/a64assembler.h b/3rdparty/asmjit/src/asmjit/arm/a64assembler.h index f1ac72b8d56..319321576d8 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64assembler.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64assembler.h @@ -23,22 +23,11 @@ class ASMJIT_VIRTAPI Assembler public: typedef BaseAssembler Base; - //! \name Construction / Destruction + //! \name Construction & Destruction //! \{ ASMJIT_API Assembler(CodeHolder* code = nullptr) noexcept; - ASMJIT_API virtual ~Assembler() noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Gets whether the current ARM mode is THUMB (alternative to 32-bit ARM encoding). - inline bool isInThumbMode() const noexcept { return _environment.isArchThumb(); } - - //! Gets the current code alignment of the current mode (ARM vs THUMB). - inline uint32_t codeAlignment() const noexcept { return isInThumbMode() ? 2 : 4; } + ASMJIT_API ~Assembler() noexcept override; //! \} diff --git a/3rdparty/asmjit/src/asmjit/arm/a64builder.cpp b/3rdparty/asmjit/src/asmjit/arm/a64builder.cpp index 3a52b2a578c..d29b0a498b9 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64builder.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64builder.cpp @@ -17,8 +17,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() { _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -28,13 +26,19 @@ Builder::~Builder() noexcept {} // ===================== Error Builder::onAttach(CodeHolder* code) noexcept { - return Base::onAttach(code); + ASMJIT_PROPAGATE(Base::onAttach(code)); + + _instructionAlignment = uint8_t(4); + assignEmitterFuncs(this); + + return kErrorOk; } Error Builder::onDetach(CodeHolder* code) noexcept { return Base::onDetach(code); } + // a64::Builder - Finalize // ======================= diff --git a/3rdparty/asmjit/src/asmjit/arm/a64builder.h b/3rdparty/asmjit/src/asmjit/arm/a64builder.h index adc99aafc8c..cab1083172b 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64builder.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64builder.h @@ -29,7 +29,7 @@ public: //! \{ ASMJIT_API explicit Builder(CodeHolder* code = nullptr) noexcept; - ASMJIT_API virtual ~Builder() noexcept; + ASMJIT_API ~Builder() noexcept override; //! \} diff --git a/3rdparty/asmjit/src/asmjit/arm/a64compiler.cpp b/3rdparty/asmjit/src/asmjit/arm/a64compiler.cpp index d6c4ed28ff2..765fd4b9dee 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64compiler.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64compiler.cpp @@ -18,8 +18,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() { _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -37,6 +35,9 @@ Error Compiler::onAttach(CodeHolder* code) noexcept { return err; } + _instructionAlignment = uint8_t(4); + assignEmitterFuncs(this); + return kErrorOk; } diff --git a/3rdparty/asmjit/src/asmjit/arm/a64compiler.h b/3rdparty/asmjit/src/asmjit/arm/a64compiler.h index bed408a98fd..64f82f62538 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64compiler.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64compiler.h @@ -3,8 +3,8 @@ // See asmjit.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib -#ifndef ASMJIT_ARM_ARMCOMPILER_H_INCLUDED -#define ASMJIT_ARM_ARMCOMPILER_H_INCLUDED +#ifndef ASMJIT_ARM_A64COMPILER_H_INCLUDED +#define ASMJIT_ARM_A64COMPILER_H_INCLUDED #include "../core/api-config.h" #ifndef ASMJIT_NO_COMPILER @@ -30,7 +30,7 @@ public: //! \{ ASMJIT_API explicit Compiler(CodeHolder* code = nullptr) noexcept; - ASMJIT_API virtual ~Compiler() noexcept; + ASMJIT_API ~Compiler() noexcept override; //! \} @@ -39,74 +39,81 @@ public: //! \cond INTERNAL template<typename RegT, typename Type> - inline RegT _newRegInternal(const Type& type) { + ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type) { RegT reg(Globals::NoInit); _newReg(®, type, nullptr); return reg; } - template<typename RegT, typename Type, typename... Args> - inline RegT _newRegInternal(const Type& type, const char* s, Args&&... args) { + template<typename RegT, typename Type> + ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s) { #ifndef ASMJIT_NO_LOGGING RegT reg(Globals::NoInit); - if (sizeof...(Args) == 0) - _newReg(®, type, s); - else - _newRegFmt(®, type, s, std::forward<Args>(args)...); + _newReg(®, type, s); return reg; #else - DebugUtils::unused(std::forward<Args>(args)...); + DebugUtils::unused(s); + return _newRegInternal<RegT>(type); +#endif + } + + template<typename RegT, typename Type, typename... Args> + ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s, Args&&... args) { +#ifndef ASMJIT_NO_LOGGING RegT reg(Globals::NoInit); - _newReg(®, type, nullptr); + _newRegFmt(®, type, s, std::forward<Args>(args)...); return reg; +#else + DebugUtils::unused(s, std::forward<Args>(args)...); + return _newRegInternal<RegT>(type); #endif } //! \endcond template<typename RegT, typename... Args> - inline RegT newSimilarReg(const RegT& ref, Args&&... args) { + ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref, Args&&... args) { return _newRegInternal<RegT>(ref, std::forward<Args>(args)...); } template<typename... Args> - inline Reg newReg(TypeId typeId, Args&&... args) { return _newRegInternal<Reg>(typeId, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Reg newReg(TypeId typeId, Args&&... args) { return _newRegInternal<Reg>(typeId, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newGp(TypeId typeId, Args&&... args) { return _newRegInternal<Gp>(typeId, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newGp(TypeId typeId, Args&&... args) { return _newRegInternal<Gp>(typeId, std::forward<Args>(args)...); } template<typename... Args> - inline Vec newVec(TypeId typeId, Args&&... args) { return _newRegInternal<Vec>(typeId, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Vec newVec(TypeId typeId, Args&&... args) { return _newRegInternal<Vec>(typeId, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt32, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt32, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newUInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newUInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt64, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt64, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newUInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newUInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kIntPtr, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kIntPtr, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newUIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newUIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newGpw(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newGpw(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newGpx(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newGpx(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); } template<typename... Args> - inline Gp newGpz(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Gp newGpz(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); } template<typename... Args> - inline Vec newVecS(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat32, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Vec newVecS(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat32, std::forward<Args>(args)...); } template<typename... Args> - inline Vec newVecD(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat64, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Vec newVecD(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat64, std::forward<Args>(args)...); } template<typename... Args> - inline Vec newVecQ(Args&&... args) { return _newRegInternal<Vec>(TypeId::kUInt8x16, std::forward<Args>(args)...); } + ASMJIT_INLINE_NODEBUG Vec newVecQ(Args&&... args) { return _newRegInternal<Vec>(TypeId::kUInt8x16, std::forward<Args>(args)...); } //! \} @@ -114,7 +121,7 @@ public: //! \{ //! Creates a new memory chunk allocated on the current function's stack. - inline Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) { + ASMJIT_INLINE_NODEBUG Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) { Mem m(Globals::NoInit); _newStack(&m, size, alignment, name); return m; @@ -126,38 +133,38 @@ public: //! \{ //! Put data to a constant-pool and get a memory reference to it. - inline Mem newConst(ConstPoolScope scope, const void* data, size_t size) { + ASMJIT_INLINE_NODEBUG Mem newConst(ConstPoolScope scope, const void* data, size_t size) { Mem m(Globals::NoInit); _newConst(&m, scope, data, size); return m; } //! Put a BYTE `val` to a constant-pool (8 bits). - inline Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); } + ASMJIT_INLINE_NODEBUG Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); } //! Put a HWORD `val` to a constant-pool (16 bits). - inline Mem newHWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } + ASMJIT_INLINE_NODEBUG Mem newHWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a WORD `val` to a constant-pool (32 bits). - inline Mem newWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } + ASMJIT_INLINE_NODEBUG Mem newWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a DWORD `val` to a constant-pool (64 bits). - inline Mem newDWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } + ASMJIT_INLINE_NODEBUG Mem newDWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a WORD `val` to a constant-pool. - inline Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); } + ASMJIT_INLINE_NODEBUG Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a WORD `val` to a constant-pool. - inline Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } + ASMJIT_INLINE_NODEBUG Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a DWORD `val` to a constant-pool. - inline Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); } + ASMJIT_INLINE_NODEBUG Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a DWORD `val` to a constant-pool. - inline Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } + ASMJIT_INLINE_NODEBUG Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a QWORD `val` to a constant-pool. - inline Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); } + ASMJIT_INLINE_NODEBUG Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a QWORD `val` to a constant-pool. - inline Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } + ASMJIT_INLINE_NODEBUG Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a SP-FP `val` to a constant-pool. - inline Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); } + ASMJIT_INLINE_NODEBUG Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); } //! Put a DP-FP `val` to a constant-pool. - inline Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); } + ASMJIT_INLINE_NODEBUG Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); } //! \} @@ -165,7 +172,7 @@ public: //! \{ //! Force the compiler to not follow the conditional or unconditional jump. - inline Compiler& unfollow() noexcept { _instOptions |= InstOptions::kUnfollow; return *this; } + ASMJIT_INLINE_NODEBUG Compiler& unfollow() noexcept { _instOptions |= InstOptions::kUnfollow; return *this; } //! \} @@ -177,7 +184,7 @@ public: //! \note At the moment this instruction is only useful to load a stack allocated address into a GP register //! for further use. It makes very little sense to use it for anything else. The semantics of this instruction //! is the same as X86 `LEA` (load effective address) instruction. - inline Error loadAddressOf(const Gp& o0, const Mem& o1) { return _emitter()->_emitI(Inst::kIdAdr, o0, o1); } + ASMJIT_INLINE_NODEBUG Error loadAddressOf(const Gp& o0, const Mem& o1) { return _emitter()->_emitI(Inst::kIdAdr, o0, o1); } //! \} @@ -185,7 +192,7 @@ public: //! \{ //! Invoke a function call without `target` type enforcement. - inline Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) { + ASMJIT_INLINE_NODEBUG Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) { return addInvokeNode(out, Inst::kIdBlr, target, signature); } @@ -194,22 +201,22 @@ public: //! Creates a new \ref InvokeNode, initializes all the necessary members to match the given function `signature`, //! adds the node to the compiler, and stores its pointer to `out`. The operation is atomic, if anything fails //! nullptr is stored in `out` and error code is returned. - inline Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload - inline Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload - inline Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload - inline Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload - inline Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); } //! Return. - inline Error ret() { return addRet(Operand(), Operand()); } + ASMJIT_INLINE_NODEBUG Error ret() { return addRet(Operand(), Operand()); } //! \overload - inline Error ret(const BaseReg& o0) { return addRet(o0, Operand()); } + ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0) { return addRet(o0, Operand()); } //! \overload - inline Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); } + ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); } //! \} @@ -219,7 +226,7 @@ public: using EmitterExplicitT<Compiler>::br; //! Adds a jump to the given `target` with the provided jump `annotation`. - inline Error br(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdBr, target, annotation); } + ASMJIT_INLINE_NODEBUG Error br(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdBr, target, annotation); } //! \} @@ -244,4 +251,4 @@ public: ASMJIT_END_SUB_NAMESPACE #endif // !ASMJIT_NO_COMPILER -#endif // ASMJIT_ARM_ARMCOMPILER_H_INCLUDED +#endif // ASMJIT_ARM_A64COMPILER_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/arm/a64emithelper.cpp b/3rdparty/asmjit/src/asmjit/arm/a64emithelper.cpp index 1e8da619a6b..0cf098250a3 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64emithelper.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64emithelper.cpp @@ -169,7 +169,7 @@ Error EmitHelper::emitArgMove( if (TypeUtils::isInt(dstTypeId)) { if (TypeUtils::isInt(srcTypeId)) { - uint32_t x = dstSize == 8; + uint32_t x = uint32_t(dstSize == 8); dst.setSignature(OperandSignature{x ? uint32_t(GpX::kSignature) : uint32_t(GpW::kSignature)}); _emitter->setInlineComment(comment); @@ -186,7 +186,7 @@ Error EmitHelper::emitArgMove( case TypeId::kInt16: instId = Inst::kIdLdrsh; break; case TypeId::kUInt16: instId = Inst::kIdLdrh; break; case TypeId::kInt32: instId = x ? Inst::kIdLdrsw : Inst::kIdLdr; break; - case TypeId::kUInt32: instId = Inst::kIdLdr; x = 0; break; + case TypeId::kUInt32: instId = Inst::kIdLdr; break; case TypeId::kInt64: instId = Inst::kIdLdr; break; case TypeId::kUInt64: instId = Inst::kIdLdr; break; default: @@ -312,6 +312,12 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { { Inst::kIdStr_v, Inst::kIdStp_v } }}; + // Emit: 'bti' (indirect branch protection). + if (frame.hasIndirectBranchProtection()) { + // TODO: The instruction is not available at the moment (would be ABI break). + // ASMJIT_PROPAGATE(emitter->bti()); + } + uint32_t adjustInitialOffset = pei.sizeTotal; for (RegGroup group : Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kVec>{}) { @@ -339,7 +345,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { else ASMJIT_PROPAGATE(emitter->emit(insts.pairInstId, regs[0], regs[1], mem)); - mem.resetToFixedOffset(); + mem.resetOffsetMode(); if (i == 0 && frame.hasPreservedFP()) { ASMJIT_PROPAGATE(emitter->mov(x29, sp)); @@ -421,7 +427,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) { else ASMJIT_PROPAGATE(emitter->emit(insts.pairInstId, regs[0], regs[1], mem)); - mem.resetToFixedOffset(); + mem.resetOffsetMode(); } } diff --git a/3rdparty/asmjit/src/asmjit/arm/a64emithelper_p.h b/3rdparty/asmjit/src/asmjit/arm/a64emithelper_p.h index b1ba1a92960..6e10f9eaabe 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64emithelper_p.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64emithelper_p.h @@ -3,8 +3,8 @@ // See asmjit.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib -#ifndef ASMJIT_ARM_ARMEMITHELPER_P_H_INCLUDED -#define ASMJIT_ARM_ARMEMITHELPER_P_H_INCLUDED +#ifndef ASMJIT_ARM_A64EMITHELPER_P_H_INCLUDED +#define ASMJIT_ARM_A64EMITHELPER_P_H_INCLUDED #include "../core/api-config.h" @@ -21,7 +21,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) class EmitHelper : public BaseEmitHelper { public: - inline explicit EmitHelper(BaseEmitter* emitter = nullptr) noexcept + ASMJIT_INLINE_NODEBUG explicit EmitHelper(BaseEmitter* emitter = nullptr) noexcept : BaseEmitHelper(emitter) {} Error emitRegMove( @@ -47,4 +47,4 @@ void assignEmitterFuncs(BaseEmitter* emitter); ASMJIT_END_SUB_NAMESPACE -#endif // ASMJIT_ARM_ARMEMITHELPER_P_H_INCLUDED +#endif // ASMJIT_ARM_A64EMITHELPER_P_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/arm/a64emitter.h b/3rdparty/asmjit/src/asmjit/arm/a64emitter.h index 54354eaca84..15c91e0ba4a 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64emitter.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64emitter.h @@ -11,6 +11,14 @@ #include "../arm/a64instdb.h" #include "../arm/a64operand.h" +// MSVC targeting AArch64 defines a lot of macros without underscores clashing +// with AArch64 instruction names. We have to workaround until it's fixed in SDK. +#if defined(_MSC_VER) && defined(mvn) + #define ASMJIT_RESTORE_MSVC_AARCH64_MACROS + #pragma push_macro("mvn") + #undef mvn +#endif + ASMJIT_BEGIN_SUB_NAMESPACE(a64) #define ASMJIT_INST_0x(NAME, ID) \ @@ -63,7 +71,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) //! ARM emitter. //! //! NOTE: This class cannot be instantiated, you can only cast to it and use it as emitter that emits to either -//! \ref Assembler, \ref Builder, or \ref Compiler (use withcaution with \ref Compiler as it expects virtual +//! \ref Assembler, \ref Builder, or \ref Compiler (use with caution with \ref Compiler as it expects virtual //! registers to be used). template<typename This> struct EmitterExplicitT { @@ -71,22 +79,22 @@ struct EmitterExplicitT { // These two are unfortunately reported by the sanitizer. We know what we do, however, the sanitizer doesn't. // I have tried to use reinterpret_cast instead, but that would generate bad code when compiled by MSC. - ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline This* _emitter() noexcept { return static_cast<This*>(this); } - ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline const This* _emitter() const noexcept { return static_cast<const This*>(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF ASMJIT_INLINE_NODEBUG This* _emitter() noexcept { return static_cast<This*>(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF ASMJIT_INLINE_NODEBUG const This* _emitter() const noexcept { return static_cast<const This*>(this); } //! \endcond - // -------------------------------------------------------------------------- - // [Options] - // -------------------------------------------------------------------------- -protected: - inline This& _addInstOptions(InstOptions options) noexcept { - static_cast<This*>(this)->addInstOptions(options); - return *static_cast<This*>(this); - } + //! \name Native Registers + //! \{ + + //! Returns either 32-bit or 64-bit GP register of the given `id` depending on the emitter's architecture. + inline Gp gpz(uint32_t id) const noexcept { return Gp(_emitter()->_gpSignature, id); } + //! Clones the given `reg` to either 32-bit or 64-bit GP register depending on the emitter's architecture. + inline Gp gpz(const Gp& reg) const noexcept { return Gp(_emitter()->_gpSignature, reg.id()); } + + //! \} -public: //! \name General Purpose Instructions //! \{ @@ -517,6 +525,8 @@ public: ASMJIT_INST_2x(ldxrb, Ldxrb, Gp, Mem) ASMJIT_INST_2x(ldxrh, Ldxrh, Gp, Mem) + ASMJIT_INST_2x(prfm, Prfm, Imm, Mem) + ASMJIT_INST_2x(stadd, Stadd, Gp, Mem) ASMJIT_INST_2x(staddb, Staddb, Gp, Mem) ASMJIT_INST_2x(staddh, Staddh, Gp, Mem) @@ -1111,14 +1121,14 @@ public: //! \} - //! \name FJCVTZS Instruction (ARMv8.3-A) + //! \name JSCVT Instruction (ARMv8.3-A) //! \{ ASMJIT_INST_2x(fjcvtzs, Fjcvtzs_v, Gp, Vec); //! \} - //! \name FP16FML Instructions (ARMv8.4-A, optional in ARMv8.2-A) + //! \name FHM Instructions //! \{ ASMJIT_INST_3x(fmlal, Fmlal_v, Vec, Vec, Vec); @@ -1225,4 +1235,9 @@ class Emitter : public BaseEmitter, public EmitterExplicitT<Emitter> { ASMJIT_END_SUB_NAMESPACE +// Restore undefined MSVC AArch64 macros. +#if defined(ASMJIT_RESTORE_MSVC_AARCH64_MACROS) + #pragma pop_macro("mvn") +#endif + #endif // ASMJIT_ARM_A64EMITTER_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/arm/a64formatter.cpp b/3rdparty/asmjit/src/asmjit/arm/a64formatter.cpp index bccb68b99b0..94ef3ee59e9 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64formatter.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64formatter.cpp @@ -4,7 +4,7 @@ // SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" -#ifndef ASMJIT_NO_LOGGING +#if !defined(ASMJIT_NO_AARCH64) && !defined(ASMJIT_NO_LOGGING) #include "../core/misc_p.h" #include "../core/support.h" @@ -19,243 +19,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) -// a64::FormatterInternal - Format Register -// ======================================== - -ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister( - String& sb, - FormatFlags flags, - const BaseEmitter* emitter, - Arch arch, - RegType regType, - uint32_t rId, - uint32_t elementType, - uint32_t elementIndex) noexcept { - - DebugUtils::unused(flags); - DebugUtils::unused(arch); - - static const char bhsdq[] = "bhsdq"; - - bool virtRegFormatted = false; - -#ifndef ASMJIT_NO_COMPILER - if (Operand::isVirtId(rId)) { - if (emitter && emitter->isCompiler()) { - const BaseCompiler* cc = static_cast<const BaseCompiler*>(emitter); - if (cc->isVirtIdValid(rId)) { - VirtReg* vReg = cc->virtRegById(rId); - ASMJIT_ASSERT(vReg != nullptr); - - const char* name = vReg->name(); - if (name && name[0] != '\0') - ASMJIT_PROPAGATE(sb.append(name)); - else - ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(rId)))); - - virtRegFormatted = true; - } - } - } -#else - DebugUtils::unused(emitter, flags); -#endif - - if (!virtRegFormatted) { - char letter = '\0'; - switch (regType) { - case RegType::kARM_GpW: - if (rId == Gp::kIdZr) - return sb.append("wzr"); - if (rId == Gp::kIdSp) - return sb.append("wsp"); - - letter = 'w'; - break; - - case RegType::kARM_GpX: - if (rId == Gp::kIdZr) - return sb.append("xzr"); - if (rId == Gp::kIdSp) - return sb.append("sp"); - - letter = 'x'; - break; - - case RegType::kARM_VecB: - case RegType::kARM_VecH: - case RegType::kARM_VecS: - case RegType::kARM_VecD: - case RegType::kARM_VecV: - letter = bhsdq[uint32_t(regType) - uint32_t(RegType::kARM_VecB)]; - if (elementType) - letter = 'v'; - break; - - default: - ASMJIT_PROPAGATE(sb.appendFormat("<Reg-%u>?$u", uint32_t(regType), rId)); - break; - } - - if (letter) - ASMJIT_PROPAGATE(sb.appendFormat("%c%u", letter, rId)); - } - - if (elementType) { - char elementLetter = '\0'; - uint32_t elementCount = 0; - - switch (elementType) { - case Vec::kElementTypeB: - elementLetter = 'b'; - elementCount = 16; - break; - - case Vec::kElementTypeH: - elementLetter = 'h'; - elementCount = 8; - break; - - case Vec::kElementTypeS: - elementLetter = 's'; - elementCount = 4; - break; - - case Vec::kElementTypeD: - elementLetter = 'd'; - elementCount = 2; - break; - - default: - return sb.append(".<Unknown>"); - } - - if (elementLetter) { - if (elementIndex == 0xFFFFFFFFu) { - if (regType == RegType::kARM_VecD) - elementCount /= 2u; - ASMJIT_PROPAGATE(sb.appendFormat(".%u%c", elementCount, elementLetter)); - } - else { - ASMJIT_PROPAGATE(sb.appendFormat(".%c[%u]", elementLetter, elementIndex)); - } - } - } - - return kErrorOk; -} - -// a64::FormatterInternal - Format Operand -// ======================================= - -ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( - String& sb, - FormatFlags flags, - const BaseEmitter* emitter, - Arch arch, - const Operand_& op) noexcept { - - if (op.isReg()) { - const BaseReg& reg = op.as<BaseReg>(); - - uint32_t elementType = op.as<Vec>().elementType(); - uint32_t elementIndex = op.as<Vec>().elementIndex(); - - if (!op.as<Vec>().hasElementIndex()) - elementIndex = 0xFFFFFFFFu; - - return formatRegister(sb, flags, emitter, arch, reg.type(), reg.id(), elementType, elementIndex); - } - - if (op.isMem()) { - const Mem& m = op.as<Mem>(); - ASMJIT_PROPAGATE(sb.append('[')); - - if (m.hasBase()) { - if (m.hasBaseLabel()) { - ASMJIT_PROPAGATE(Formatter::formatLabel(sb, flags, emitter, m.baseId())); - } - else { - FormatFlags modifiedFlags = flags; - if (m.isRegHome()) { - ASMJIT_PROPAGATE(sb.append('&')); - modifiedFlags &= ~FormatFlags::kRegCasts; - } - ASMJIT_PROPAGATE(formatRegister(sb, modifiedFlags, emitter, arch, m.baseType(), m.baseId())); - } - } - else { - // ARM really requires base. - if (m.hasIndex() || m.hasOffset()) { - ASMJIT_PROPAGATE(sb.append("<None>")); - } - } - - // The post index makes it look like there was another operand, but it's - // still the part of AsmJit's `arm::Mem` operand so it's consistent with - // other architectures. - if (m.isPostIndex()) - ASMJIT_PROPAGATE(sb.append(']')); - - if (m.hasIndex()) { - ASMJIT_PROPAGATE(sb.append(", ")); - ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, m.indexType(), m.indexId())); - } - - if (m.hasOffset()) { - ASMJIT_PROPAGATE(sb.append(", ")); - - int64_t off = int64_t(m.offset()); - uint32_t base = 10; - - if (Support::test(flags, FormatFlags::kHexOffsets) && uint64_t(off) > 9) - base = 16; - - if (base == 10) { - ASMJIT_PROPAGATE(sb.appendInt(off, base)); - } - else { - ASMJIT_PROPAGATE(sb.append("0x")); - ASMJIT_PROPAGATE(sb.appendUInt(uint64_t(off), base)); - } - } - - if (m.hasShift()) { - ASMJIT_PROPAGATE(sb.append(' ')); - if (!m.isPreOrPost()) - ASMJIT_PROPAGATE(formatShiftOp(sb, (ShiftOp)m.predicate())); - ASMJIT_PROPAGATE(sb.appendFormat(" %u", m.shift())); - } - - if (!m.isPostIndex()) - ASMJIT_PROPAGATE(sb.append(']')); - - if (m.isPreIndex()) - ASMJIT_PROPAGATE(sb.append('!')); - - return kErrorOk; - } - - if (op.isImm()) { - const Imm& i = op.as<Imm>(); - int64_t val = i.value(); - - if (Support::test(flags, FormatFlags::kHexImms) && uint64_t(val) > 9) { - ASMJIT_PROPAGATE(sb.append("0x")); - return sb.appendUInt(uint64_t(val), 16); - } - else { - return sb.appendInt(val, 10); - } - } - - if (op.isLabel()) { - return Formatter::formatLabel(sb, flags, emitter, op.id()); - } - - return sb.append("<None>"); -} - // a64::FormatterInternal - Format Instruction // =========================================== @@ -266,12 +29,10 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept { - DebugUtils::unused(arch); - // Format instruction options and instruction mnemonic. InstId instId = inst.realId(); - if (instId < Inst::_kIdCount) - ASMJIT_PROPAGATE(InstInternal::instIdToString(arch, instId, sb)); + if (instId != Inst::kIdNone && instId < Inst::_kIdCount) + ASMJIT_PROPAGATE(InstInternal::instIdToString(instId, sb)); else ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); @@ -295,4 +56,4 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( ASMJIT_END_SUB_NAMESPACE -#endif // !ASMJIT_NO_LOGGING +#endif // !ASMJIT_NO_AARCH64 && !ASMJIT_NO_LOGGING diff --git a/3rdparty/asmjit/src/asmjit/arm/a64formatter_p.h b/3rdparty/asmjit/src/asmjit/arm/a64formatter_p.h index bd7a1440cb0..d0adde3ce0d 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64formatter_p.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64formatter_p.h @@ -24,23 +24,6 @@ namespace FormatterInternal { using namespace arm::FormatterInternal; -Error ASMJIT_CDECL formatRegister( - String& sb, - FormatFlags flags, - const BaseEmitter* emitter, - Arch arch, - RegType regType, - uint32_t regId, - uint32_t elementType = 0, - uint32_t elementIndex = 0xFFFFFFFFu) noexcept; - -Error ASMJIT_CDECL formatOperand( - String& sb, - FormatFlags flags, - const BaseEmitter* emitter, - Arch arch, - const Operand_& op) noexcept; - Error ASMJIT_CDECL formatInstruction( String& sb, FormatFlags flags, diff --git a/3rdparty/asmjit/src/asmjit/arm/a64func.cpp b/3rdparty/asmjit/src/asmjit/arm/a64func.cpp index 55e3f2e71ec..a33a2f2d9d7 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64func.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64func.cpp @@ -13,7 +13,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) namespace FuncInternal { -static inline bool shouldThreatAsCDecl(CallConvId ccId) noexcept { +static inline bool shouldTreatAsCDecl(CallConvId ccId) noexcept { return ccId == CallConvId::kCDecl || ccId == CallConvId::kStdCall || ccId == CallConvId::kFastCall || @@ -41,18 +41,19 @@ static RegType regTypeFromFpOrVecTypeId(TypeId typeId) noexcept { ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept { cc.setArch(environment.arch()); + cc.setStrategy(environment.isDarwin() ? CallConvStrategy::kAArch64Apple : CallConvStrategy::kDefault); cc.setSaveRestoreRegSize(RegGroup::kGp, 8); cc.setSaveRestoreRegSize(RegGroup::kVec, 8); cc.setSaveRestoreAlignment(RegGroup::kGp, 16); cc.setSaveRestoreAlignment(RegGroup::kVec, 16); - cc.setSaveRestoreAlignment(RegGroup::kExtraVirt2, 1); + cc.setSaveRestoreAlignment(RegGroup::kMask, 1); cc.setSaveRestoreAlignment(RegGroup::kExtraVirt3, 1); cc.setPassedOrder(RegGroup::kGp, 0, 1, 2, 3, 4, 5, 6, 7); cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7); cc.setNaturalStackAlignment(16); - if (shouldThreatAsCDecl(ccId)) { + if (shouldTreatAsCDecl(ccId)) { // ARM doesn't have that many calling conventions as we can find in X86 world, treat most conventions as __cdecl. cc.setId(CallConvId::kCDecl); cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(Gp::kIdOs, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30)); @@ -68,7 +69,7 @@ ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Enviro return kErrorOk; } -ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept { +ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& signature) noexcept { DebugUtils::unused(signature); const CallConv& cc = func.callConv(); @@ -77,6 +78,13 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si uint32_t i; uint32_t argCount = func.argCount(); + // Minimum stack size of a single argument passed via stack. The standard AArch64 calling convention + // specifies 8 bytes, so each function argument would occupy at least 8 bytes even if it needs less. + // However, Apple has decided to not follow this rule and function argument can occupy less, for + // example two consecutive 32-bit arguments would occupy 8 bytes total, instead of 16 as specified + // by ARM. + uint32_t minStackArgSize = cc.strategy() == CallConvStrategy::kAArch64Apple ? 4u : 8u; + if (func.hasRet()) { for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { TypeId typeId = func._rets[valueIndex].typeId(); @@ -119,7 +127,8 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si } switch (cc.strategy()) { - case CallConvStrategy::kDefault: { + case CallConvStrategy::kDefault: + case CallConvStrategy::kAArch64Apple: { uint32_t gpzPos = 0; uint32_t vecPos = 0; @@ -140,7 +149,9 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si gpzPos++; } else { - uint32_t size = Support::max<uint32_t>(TypeUtils::sizeOf(typeId), registerSize); + uint32_t size = Support::max<uint32_t>(TypeUtils::sizeOf(typeId), minStackArgSize); + if (size >= 8) + stackOffset = Support::alignUp(stackOffset, 8); arg.assignStackOffset(int32_t(stackOffset)); stackOffset += size; } @@ -164,7 +175,9 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si vecPos++; } else { - uint32_t size = TypeUtils::sizeOf(typeId); + uint32_t size = Support::max<uint32_t>(TypeUtils::sizeOf(typeId), minStackArgSize); + if (size >= 8) + stackOffset = Support::alignUp(stackOffset, 8); arg.assignStackOffset(int32_t(stackOffset)); stackOffset += size; } @@ -178,7 +191,7 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si return DebugUtils::errored(kErrorInvalidState); } - func._argStackSize = stackOffset; + func._argStackSize = Support::alignUp(stackOffset, 8u); return kErrorOk; } diff --git a/3rdparty/asmjit/src/asmjit/arm/a64func_p.h b/3rdparty/asmjit/src/asmjit/arm/a64func_p.h index 9f531fc5a23..7f2221c7059 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64func_p.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64func_p.h @@ -21,7 +21,7 @@ namespace FuncInternal { Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept; //! Initialize `FuncDetail` (AArch64 specific). -Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept; +Error initFuncDetail(FuncDetail& func, const FuncSignature& signature) noexcept; } // {FuncInternal} diff --git a/3rdparty/asmjit/src/asmjit/arm/a64globals.h b/3rdparty/asmjit/src/asmjit/arm/a64globals.h index 2b6b6f0ce91..720b6f151ce 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64globals.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64globals.h @@ -15,16 +15,13 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) -// a64 uses everything from arm namespace and adds into it. -using namespace arm; - //! \addtogroup asmjit_a64 //! \{ //! AArch64 instruction. //! //! \note Only used to hold ARM-specific enumerations and static functions. -struct Inst { +namespace Inst { //! Instruction id. enum Id : uint32_t { // ${InstId:Begin} @@ -293,6 +290,7 @@ struct Inst { kIdPacdza, //!< Instruction 'pacdza'. kIdPacdzb, //!< Instruction 'pacdzb'. kIdPacga, //!< Instruction 'pacga'. + kIdPrfm, //!< Instruction 'prfm'. kIdPssbb, //!< Instruction 'pssbb'. kIdRbit, //!< Instruction 'rbit'. kIdRet, //!< Instruction 'ret'. @@ -797,14 +795,14 @@ struct Inst { }; //! Tests whether the `instId` is defined (counts also Inst::kIdNone, which must be zero). - static inline bool isDefinedId(InstId instId) noexcept { return (instId & uint32_t(InstIdParts::kRealId)) < _kIdCount; } + static ASMJIT_INLINE_NODEBUG bool isDefinedId(InstId instId) noexcept { return (instId & uint32_t(InstIdParts::kRealId)) < _kIdCount; } }; namespace Predicate { //! Address translate options (AT). namespace AT { - static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); } @@ -862,7 +860,7 @@ namespace DB { //! Data cache maintenance options. namespace DC { - static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); } @@ -901,7 +899,7 @@ namespace DC { //! Instruction cache maintenance options. namespace IC { - static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); } @@ -955,7 +953,7 @@ namespace PSB { } namespace TLBI { - static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); } @@ -1054,7 +1052,7 @@ namespace TSB { //! Processor state access through MSR. namespace PState { //! Encodes a pstate from `op0` and `op1`. - static inline constexpr uint32_t encode(uint32_t op0, uint32_t op1) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op0, uint32_t op1) noexcept { return (op0 << 3) | (op1 << 0); } @@ -1083,17 +1081,17 @@ namespace SysReg { }; //! Encodes a system register from `op0`, `op1`, `cRn`, `cRm`, and `op2` fields. - static inline constexpr uint32_t encode(uint32_t op0, uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op0, uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { return (op0 << 14) | (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); } //! Encodes a system register from `fields`. - static inline constexpr uint32_t encode(const Fields& fields) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(const Fields& fields) noexcept { return encode(fields.op0, fields.op1, fields.cRn, fields.cRm, fields.op2); } //! Decodes a system register to \ref Fields. - static inline constexpr Fields decode(uint32_t id) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr Fields decode(uint32_t id) noexcept { return Fields { uint8_t((id >> 14) & 0x3u), uint8_t((id >> 11) & 0x7u), @@ -1417,9 +1415,12 @@ namespace SysReg { kID_AA64DFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0101, 0b001), // RO kID_AA64ISAR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0110, 0b000), // RO kID_AA64ISAR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0110, 0b001), // RO + kID_AA64ISAR2_EL1 = encode(0b11, 0b000, 0b0000, 0b0110, 0b010), // RO kID_AA64MMFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0111, 0b000), // RO kID_AA64MMFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0111, 0b001), // RO kID_AA64MMFR2_EL1 = encode(0b11, 0b000, 0b0000, 0b0111, 0b010), // RO + kID_AA64MMFR3_EL1 = encode(0b11, 0b000, 0b0000, 0b0111, 0b011), // RO + kID_AA64MMFR4_EL1 = encode(0b11, 0b000, 0b0000, 0b0111, 0b100), // RO kID_AA64PFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0100, 0b000), // RO kID_AA64PFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0100, 0b001), // RO kID_AA64ZFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0100, 0b100), // RO diff --git a/3rdparty/asmjit/src/asmjit/arm/a64instapi.cpp b/3rdparty/asmjit/src/asmjit/arm/a64instapi.cpp index d933d4bd7f7..023be05573e 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64instapi.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64instapi.cpp @@ -8,71 +8,29 @@ #include "../core/cpuinfo.h" #include "../core/misc_p.h" -#include "../core/support.h" +#include "../core/support_p.h" #include "../arm/a64instapi_p.h" #include "../arm/a64instdb_p.h" #include "../arm/a64operand.h" ASMJIT_BEGIN_SUB_NAMESPACE(a64) +namespace InstInternal { + // a64::InstInternal - Text // ======================== #ifndef ASMJIT_NO_TEXT -Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noexcept { +Error instIdToString(InstId instId, String& output) noexcept { uint32_t realId = instId & uint32_t(InstIdParts::kRealId); - DebugUtils::unused(arch); - if (ASMJIT_UNLIKELY(!Inst::isDefinedId(realId))) return DebugUtils::errored(kErrorInvalidInstruction); - const InstDB::InstInfo& info = InstDB::infoById(realId); - return output.append(InstDB::_nameData + info._nameDataIndex); + return InstNameUtils::decode(output, InstDB::_instNameIndexTable[realId], InstDB::_instNameStringTable); } -InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept { - DebugUtils::unused(arch); - - if (ASMJIT_UNLIKELY(!s)) - return Inst::kIdNone; - - if (len == SIZE_MAX) - len = strlen(s); - - if (ASMJIT_UNLIKELY(len == 0 || len > InstDB::kMaxNameSize)) - return Inst::kIdNone; - - uint32_t prefix = uint32_t(s[0]) - 'a'; - if (ASMJIT_UNLIKELY(prefix > 'z' - 'a')) - return Inst::kIdNone; - - uint32_t index = InstDB::instNameIndex[prefix].start; - if (ASMJIT_UNLIKELY(!index)) - return Inst::kIdNone; - - const char* nameData = InstDB::_nameData; - const InstDB::InstInfo* table = InstDB::_instInfoTable; - - const InstDB::InstInfo* base = table + index; - const InstDB::InstInfo* end = table + InstDB::instNameIndex[prefix].end; - - for (size_t lim = (size_t)(end - base); lim != 0; lim >>= 1) { - const InstDB::InstInfo* cur = base + (lim >> 1); - int result = Support::cmpInstName(nameData + cur[0]._nameDataIndex, s, len); - - if (result < 0) { - base = cur + 1; - lim--; - continue; - } - - if (result > 0) - continue; - - return uint32_t((size_t)(cur - table)); - } - - return Inst::kIdNone; +InstId stringToInstId(const char* s, size_t len) noexcept { + return InstNameUtils::find(s, len, InstDB::instNameIndex, InstDB::_instNameIndexTable, InstDB::_instNameStringTable); } #endif // !ASMJIT_NO_TEXT @@ -80,9 +38,9 @@ InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexce // ============================ #ifndef ASMJIT_NO_VALIDATION -ASMJIT_FAVOR_SIZE Error InstInternal::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { +ASMJIT_FAVOR_SIZE Error validate(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { // TODO: - DebugUtils::unused(arch, inst, operands, opCount, validationFlags); + DebugUtils::unused(inst, operands, opCount, validationFlags); return kErrorOk; } #endif // !ASMJIT_NO_VALIDATION @@ -126,13 +84,7 @@ static const InstRWInfoData instRWInfoData[] = { static const uint8_t elementTypeSize[8] = { 0, 1, 2, 4, 8, 4, 4, 0 }; -Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { - // Unused in Release configuration as the assert is not compiled in. - DebugUtils::unused(arch); - - // Only called when `arch` matches X86 family. - ASMJIT_ASSERT(Environment::isFamilyARM(arch)); - +Error queryRWInfo(const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { // Get the instruction data. uint32_t realId = inst.id() & uint32_t(InstIdParts::kRealId); @@ -185,11 +137,13 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* if (memOp.hasBase()) { op.addOpFlags(OpRWFlags::kMemBaseRead); + if ((memOp.hasIndex() || memOp.hasOffset()) && memOp.isPreOrPost()) { + op.addOpFlags(OpRWFlags::kMemBaseWrite); + } } if (memOp.hasIndex()) { op.addOpFlags(OpRWFlags::kMemIndexRead); - op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexWrite : OpRWFlags::kNone); } } } @@ -222,10 +176,10 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* if (srcOp.isReg()) { if (srcOp.as<Vec>().hasElementIndex()) { // Only part of the vector is accessed if element index [] is used. - uint32_t elementType = srcOp.as<Vec>().elementType(); + VecElementType elementType = srcOp.as<Vec>().elementType(); uint32_t elementIndex = srcOp.as<Vec>().elementIndex(); - uint32_t elementSize = elementTypeSize[elementType]; + uint32_t elementSize = elementTypeSize[size_t(elementType)]; uint64_t accessMask = uint64_t(Support::lsbMask<uint32_t>(elementSize)) << (elementIndex * elementSize); op._readByteMask &= accessMask; @@ -239,11 +193,13 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* if (memOp.hasBase()) { op.addOpFlags(OpRWFlags::kMemBaseRead); + if ((memOp.hasIndex() || memOp.hasOffset()) && memOp.isPreOrPost()) { + op.addOpFlags(OpRWFlags::kMemBaseWrite); + } } if (memOp.hasIndex()) { op.addOpFlags(OpRWFlags::kMemIndexRead); - op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexWrite : OpRWFlags::kNone); } } } @@ -257,13 +213,15 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* // ================================= #ifndef ASMJIT_NO_INTROSPECTION -Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { +Error queryFeatures(const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { // TODO: [ARM] QueryFeatures not implemented yet. - DebugUtils::unused(arch, inst, operands, opCount, out); + DebugUtils::unused(inst, operands, opCount, out); return kErrorOk; } #endif // !ASMJIT_NO_INTROSPECTION +} // {InstInternal} + // a64::InstInternal - Unit // ======================== diff --git a/3rdparty/asmjit/src/asmjit/arm/a64instapi_p.h b/3rdparty/asmjit/src/asmjit/arm/a64instapi_p.h index 320a3e881d9..535e4bd71f8 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64instapi_p.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64instapi_p.h @@ -18,17 +18,17 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) namespace InstInternal { #ifndef ASMJIT_NO_TEXT -Error ASMJIT_CDECL instIdToString(Arch arch, InstId instId, String& output) noexcept; -InstId ASMJIT_CDECL stringToInstId(Arch arch, const char* s, size_t len) noexcept; +Error ASMJIT_CDECL instIdToString(InstId instId, String& output) noexcept; +InstId ASMJIT_CDECL stringToInstId(const char* s, size_t len) noexcept; #endif // !ASMJIT_NO_TEXT #ifndef ASMJIT_NO_VALIDATION -Error ASMJIT_CDECL validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; +Error ASMJIT_CDECL validate(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; #endif // !ASMJIT_NO_VALIDATION #ifndef ASMJIT_NO_INTROSPECTION -Error ASMJIT_CDECL queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; -Error ASMJIT_CDECL queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; +Error ASMJIT_CDECL queryRWInfo(const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; +Error ASMJIT_CDECL queryFeatures(const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; #endif // !ASMJIT_NO_INTROSPECTION } // {InstInternal} diff --git a/3rdparty/asmjit/src/asmjit/arm/a64instdb.cpp b/3rdparty/asmjit/src/asmjit/arm/a64instdb.cpp index 64709b5db03..bc6646e895e 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64instdb.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64instdb.cpp @@ -18,20 +18,11 @@ namespace InstDB { // a64::InstDB - InstInfoTable // =========================== -// Don't store `_nameDataIndex` if instruction names are disabled. Since some -// APIs can use `_nameDataIndex` it's much safer if it's zero if it's not used. -#if defined(ASMJIT_NO_TEXT) - #define NAME_DATA_INDEX(x) 0 -#else - #define NAME_DATA_INDEX(x) x -#endif - // Defines an ARM/AArch64 instruction. -#define INST(id, opcodeEncoding, opcodeData, rwInfoIndex, flags, opcodeDataIndex, nameDataIndex) { \ +#define INST(id, opcodeEncoding, opcodeData, rwInfoIndex, flags, opcodeDataIndex) { \ uint32_t(kEncoding##opcodeEncoding), \ uint32_t(opcodeDataIndex), \ 0, \ - uint32_t(NAME_DATA_INDEX(nameDataIndex)), \ uint16_t(rwInfoIndex), \ uint16_t(flags) \ } @@ -63,774 +54,775 @@ IRG: Insert Random Tag. INST_(Irg , BaseRRR , (0b1001101011000000000100, kX , kSP, kX , kSP, kX , kZR, true) , kRWI_W , 0 , 0 , 1 ), // #1 */ const InstInfo _instInfoTable[] = { - // +------------------+---------------------+--------------------------------------------------------------------------------------+-----------+---------------------------+----+-----+ - // | Instruction Id | Encoding | Opcode Data | RW Info | Instruction Flags |DatX|NameX| - // +------------------+---------------------+--------------------------------------------------------------------------------------+-----------+---------------------------+----+-----+ + // +------------------+---------------------+--------------------------------------------------------------------------------------+-----------+---------------------------+----+ + // | Instruction Id | Encoding | Opcode Data | RW Info | Instruction Flags |DatX| + // +------------------+---------------------+--------------------------------------------------------------------------------------+-----------+---------------------------+----+ // ${InstInfo:Begin} - INST(None , None , (_) , 0 , 0 , 0 , 0 ), // #0 - INST(Adc , BaseRRR , (0b0001101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 0 , 1 ), // #1 - INST(Adcs , BaseRRR , (0b0011101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 1 , 5 ), // #2 - INST(Add , BaseAddSub , (0b0001011000, 0b0001011001, 0b0010001) , kRWI_W , 0 , 0 , 978 ), // #3 - INST(Addg , BaseRRII , (0b1001000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10) , kRWI_W , 0 , 0 , 10 ), // #4 - INST(Adds , BaseAddSub , (0b0101011000, 0b0101011001, 0b0110001) , kRWI_W , 0 , 1 , 15 ), // #5 - INST(Adr , BaseAdr , (0b0001000000000000000000, OffsetType::kAArch64_ADR) , kRWI_W , 0 , 0 , 25 ), // #6 - INST(Adrp , BaseAdr , (0b1001000000000000000000, OffsetType::kAArch64_ADRP) , kRWI_W , 0 , 1 , 29 ), // #7 - INST(And , BaseLogical , (0b0001010000, 0b00100100, 0) , kRWI_W , 0 , 0 , 57 ), // #8 - INST(Ands , BaseLogical , (0b1101010000, 0b11100100, 0) , kRWI_W , 0 , 1 , 61 ), // #9 - INST(Asr , BaseShift , (0b0001101011000000001010, 0b0001001100000000011111, 0) , kRWI_W , 0 , 0 , 66 ), // #10 - INST(Asrv , BaseShift , (0b0001101011000000001010, 0b0000000000000000000000, 0) , kRWI_W , 0 , 1 , 70 ), // #11 - INST(At , BaseAtDcIcTlbi , (0b00011111110000, 0b00001111000000, true) , kRWI_RX , 0 , 0 , 75 ), // #12 - INST(Autda , BaseRR , (0b11011010110000010001100000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 0 , 78 ), // #13 - INST(Autdza , BaseR , (0b11011010110000010011101111100000, kX, kZR, 0) , kRWI_X , 0 , 0 , 90 ), // #14 - INST(Autdb , BaseRR , (0b11011010110000010001110000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 1 , 84 ), // #15 - INST(Autdzb , BaseR , (0b11011010110000010011111111100000, kX, kZR, 0) , kRWI_X , 0 , 1 , 97 ), // #16 - INST(Autia , BaseRR , (0b11011010110000010001000000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 2 , 104 ), // #17 - INST(Autia1716 , BaseOp , (0b11010101000000110010000110011111) , 0 , 0 , 0 , 110 ), // #18 - INST(Autiasp , BaseOp , (0b11010101000000110010001110111111) , 0 , 0 , 1 , 120 ), // #19 - INST(Autiaz , BaseOp , (0b11010101000000110010001110011111) , 0 , 0 , 2 , 128 ), // #20 - INST(Autib , BaseRR , (0b11011010110000010001010000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 3 , 135 ), // #21 - INST(Autib1716 , BaseOp , (0b11010101000000110010000111011111) , 0 , 0 , 3 , 141 ), // #22 - INST(Autibsp , BaseOp , (0b11010101000000110010001111111111) , 0 , 0 , 4 , 151 ), // #23 - INST(Autibz , BaseOp , (0b11010101000000110010001111011111) , 0 , 0 , 5 , 159 ), // #24 - INST(Autiza , BaseR , (0b11011010110000010011001111100000, kX, kZR, 0) , kRWI_X , 0 , 2 , 166 ), // #25 - INST(Autizb , BaseR , (0b11011010110000010011011111100000, kX, kZR, 0) , kRWI_X , 0 , 3 , 173 ), // #26 - INST(Axflag , BaseOp , (0b11010101000000000100000001011111) , 0 , 0 , 6 , 180 ), // #27 - INST(B , BaseBranchRel , (0b00010100000000000000000000000000) , 0 , F(Cond) , 0 , 1738), // #28 - INST(Bfc , BaseBfc , (0b00110011000000000000001111100000) , kRWI_X , 0 , 0 , 192 ), // #29 - INST(Bfi , BaseBfi , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 , 223 ), // #30 - INST(Bfm , BaseBfm , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 , 2514), // #31 - INST(Bfxil , BaseBfx , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 , 250 ), // #32 - INST(Bic , BaseLogical , (0b0001010001, 0b00100100, 1) , kRWI_W , 0 , 2 , 256 ), // #33 - INST(Bics , BaseLogical , (0b1101010001, 0b11100100, 1) , kRWI_W , 0 , 3 , 260 ), // #34 - INST(Bl , BaseBranchRel , (0b10010100000000000000000000000000) , 0 , 0 , 1 , 2831), // #35 - INST(Blr , BaseBranchReg , (0b11010110001111110000000000000000) , kRWI_R , 0 , 0 , 269 ), // #36 - INST(Br , BaseBranchReg , (0b11010110000111110000000000000000) , kRWI_R , 0 , 1 , 273 ), // #37 - INST(Brk , BaseOpImm , (0b11010100001000000000000000000000, 16, 5) , 0 , 0 , 0 , 276 ), // #38 - INST(Cas , BaseAtomicOp , (0b1000100010100000011111, kWX, 30, 0) , kRWI_XRX , 0 , 0 , 284 ), // #39 - INST(Casa , BaseAtomicOp , (0b1000100011100000011111, kWX, 30, 1) , kRWI_XRX , 0 , 1 , 288 ), // #40 - INST(Casab , BaseAtomicOp , (0b0000100011100000011111, kW , 0 , 1) , kRWI_XRX , 0 , 2 , 293 ), // #41 - INST(Casah , BaseAtomicOp , (0b0100100011100000011111, kW , 0 , 1) , kRWI_XRX , 0 , 3 , 299 ), // #42 - INST(Casal , BaseAtomicOp , (0b1000100011100000111111, kWX, 30, 1) , kRWI_XRX , 0 , 4 , 305 ), // #43 - INST(Casalb , BaseAtomicOp , (0b0000100011100000111111, kW , 0 , 1) , kRWI_XRX , 0 , 5 , 311 ), // #44 - INST(Casalh , BaseAtomicOp , (0b0100100011100000111111, kW , 0 , 1) , kRWI_XRX , 0 , 6 , 318 ), // #45 - INST(Casb , BaseAtomicOp , (0b0000100010100000011111, kW , 0 , 0) , kRWI_XRX , 0 , 7 , 325 ), // #46 - INST(Cash , BaseAtomicOp , (0b0100100010100000011111, kW , 0 , 0) , kRWI_XRX , 0 , 8 , 330 ), // #47 - INST(Casl , BaseAtomicOp , (0b1000100010100000111111, kWX, 30, 0) , kRWI_XRX , 0 , 9 , 335 ), // #48 - INST(Caslb , BaseAtomicOp , (0b0000100010100000111111, kW , 0 , 0) , kRWI_XRX , 0 , 10 , 340 ), // #49 - INST(Caslh , BaseAtomicOp , (0b0100100010100000111111, kW , 0 , 0) , kRWI_XRX , 0 , 11 , 346 ), // #50 - INST(Casp , BaseAtomicCasp , (0b0000100000100000011111, kWX, 30) , kRWI_XXRRX, 0 , 0 , 352 ), // #51 - INST(Caspa , BaseAtomicCasp , (0b0000100001100000011111, kWX, 30) , kRWI_XXRRX, 0 , 1 , 357 ), // #52 - INST(Caspal , BaseAtomicCasp , (0b0000100001100000111111, kWX, 30) , kRWI_XXRRX, 0 , 2 , 363 ), // #53 - INST(Caspl , BaseAtomicCasp , (0b0000100000100000111111, kWX, 30) , kRWI_XXRRX, 0 , 3 , 370 ), // #54 - INST(Cbnz , BaseBranchCmp , (0b00110101000000000000000000000000) , kRWI_R , 0 , 0 , 376 ), // #55 - INST(Cbz , BaseBranchCmp , (0b00110100000000000000000000000000) , kRWI_R , 0 , 1 , 381 ), // #56 - INST(Ccmn , BaseCCmp , (0b00111010010000000000000000000000) , kRWI_R , 0 , 0 , 385 ), // #57 - INST(Ccmp , BaseCCmp , (0b01111010010000000000000000000000) , kRWI_R , 0 , 1 , 650 ), // #58 - INST(Cfinv , BaseOp , (0b11010101000000000100000000011111) , 0 , 0 , 7 , 390 ), // #59 - INST(Cinc , BaseCInc , (0b00011010100000000000010000000000) , kRWI_W , 0 , 0 , 396 ), // #60 - INST(Cinv , BaseCInc , (0b01011010100000000000000000000000) , kRWI_W , 0 , 1 , 401 ), // #61 - INST(Clrex , BaseOpImm , (0b11010101000000110011000001011111, 4, 8) , 0 , 0 , 1 , 406 ), // #62 - INST(Cls , BaseRR , (0b01011010110000000001010000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 4 , 412 ), // #63 - INST(Clz , BaseRR , (0b01011010110000000001000000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 5 , 416 ), // #64 - INST(Cmn , BaseCmpCmn , (0b0101011000, 0b0101011001, 0b0110001) , kRWI_R , 0 , 0 , 386 ), // #65 - INST(Cmp , BaseCmpCmn , (0b1101011000, 0b1101011001, 0b1110001) , kRWI_R , 0 , 1 , 651 ), // #66 - INST(Cmpp , BaseRR , (0b10111010110000000000000000011111, kX, kSP, 5, kX, kSP, 16, true) , kRWI_R , 0 , 6 , 430 ), // #67 - INST(Cneg , BaseCInc , (0b01011010100000000000010000000000) , kRWI_W , 0 , 2 , 441 ), // #68 - INST(Crc32b , BaseRRR , (0b0001101011000000010000, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 2 , 450 ), // #69 - INST(Crc32cb , BaseRRR , (0b0001101011000000010100, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 3 , 457 ), // #70 - INST(Crc32ch , BaseRRR , (0b0001101011000000010101, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 4 , 465 ), // #71 - INST(Crc32cw , BaseRRR , (0b0001101011000000010110, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 5 , 473 ), // #72 - INST(Crc32cx , BaseRRR , (0b1001101011000000010111, kW, kZR, kW, kZR, kX, kZR, false) , kRWI_W , 0 , 6 , 481 ), // #73 - INST(Crc32h , BaseRRR , (0b0001101011000000010001, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 7 , 489 ), // #74 - INST(Crc32w , BaseRRR , (0b0001101011000000010010, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 8 , 496 ), // #75 - INST(Crc32x , BaseRRR , (0b1001101011000000010011, kW, kZR, kW, kZR, kX, kZR, false) , kRWI_W , 0 , 9 , 503 ), // #76 - INST(Csdb , BaseOp , (0b11010101000000110010001010011111) , 0 , 0 , 8 , 510 ), // #77 - INST(Csel , BaseCSel , (0b00011010100000000000000000000000) , kRWI_W , 0 , 0 , 710 ), // #78 - INST(Cset , BaseCSet , (0b00011010100111110000011111100000) , kRWI_W , 0 , 0 , 515 ), // #79 - INST(Csetm , BaseCSet , (0b01011010100111110000001111100000) , kRWI_W , 0 , 1 , 520 ), // #80 - INST(Csinc , BaseCSel , (0b00011010100000000000010000000000) , kRWI_W , 0 , 1 , 526 ), // #81 - INST(Csinv , BaseCSel , (0b01011010100000000000000000000000) , kRWI_W , 0 , 2 , 532 ), // #82 - INST(Csneg , BaseCSel , (0b01011010100000000000010000000000) , kRWI_W , 0 , 3 , 538 ), // #83 - INST(Dc , BaseAtDcIcTlbi , (0b00011110000000, 0b00001110000000, true) , kRWI_RX , 0 , 1 , 2 ), // #84 - INST(Dcps1 , BaseOpImm , (0b11010100101000000000000000000001, 16, 5) , 0 , 0 , 2 , 544 ), // #85 - INST(Dcps2 , BaseOpImm , (0b11010100101000000000000000000010, 16, 5) , 0 , 0 , 3 , 550 ), // #86 - INST(Dcps3 , BaseOpImm , (0b11010100101000000000000000000011, 16, 5) , 0 , 0 , 4 , 556 ), // #87 - INST(Dgh , BaseOp , (0b11010101000000110010000011011111) , 0 , 0 , 9 , 562 ), // #88 - INST(Dmb , BaseOpImm , (0b11010101000000110011000010111111, 4, 8) , 0 , 0 , 5 , 566 ), // #89 - INST(Drps , BaseOp , (0b11010110101111110000001111100000) , 0 , 0 , 10 , 570 ), // #90 - INST(Dsb , BaseOpImm , (0b11010101000000110011000010011111, 4, 8) , 0 , 0 , 6 , 575 ), // #91 - INST(Eon , BaseLogical , (0b1001010001, 0b10100100, 1) , kRWI_W , 0 , 4 , 583 ), // #92 - INST(Eor , BaseLogical , (0b1001010000, 0b10100100, 0) , kRWI_W , 0 , 5 , 1418), // #93 - INST(Esb , BaseOp , (0b11010101000000110010001000011111) , 0 , 0 , 11 , 597 ), // #94 - INST(Extr , BaseExtract , (0b00010011100000000000000000000000) , kRWI_W , 0 , 0 , 605 ), // #95 - INST(Eret , BaseOp , (0b11010110100111110000001111100000) , 0 , 0 , 12 , 592 ), // #96 - INST(Gmi , BaseRRR , (0b1001101011000000000101, kX , kZR, kX , kSP, kX , kZR, true) , kRWI_W , 0 , 10 , 1128), // #97 - INST(Hint , BaseOpImm , (0b11010101000000110010000000011111, 7, 5) , 0 , 0 , 7 , 1132), // #98 - INST(Hlt , BaseOpImm , (0b11010100010000000000000000000000, 16, 5) , 0 , 0 , 8 , 1137), // #99 - INST(Hvc , BaseOpImm , (0b11010100000000000000000000000010, 16, 5) , 0 , 0 , 9 , 1141), // #100 - INST(Ic , BaseAtDcIcTlbi , (0b00011110000000, 0b00001110000000, false) , kRWI_RX , 0 , 2 , 257 ), // #101 - INST(Isb , BaseOpImm , (0b11010101000000110011000011011111, 4, 8) , 0 , 0 , 10 , 1149), // #102 - INST(Ldadd , BaseAtomicOp , (0b1011100000100000000000, kWX, 30, 0) , kRWI_WRX , 0 , 12 , 1189), // #103 - INST(Ldadda , BaseAtomicOp , (0b1011100010100000000000, kWX, 30, 1) , kRWI_WRX , 0 , 13 , 1195), // #104 - INST(Ldaddab , BaseAtomicOp , (0b0011100010100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 14 , 1202), // #105 - INST(Ldaddah , BaseAtomicOp , (0b0111100010100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 15 , 1210), // #106 - INST(Ldaddal , BaseAtomicOp , (0b1011100011100000000000, kWX, 30, 1) , kRWI_WRX , 0 , 16 , 1218), // #107 - INST(Ldaddalb , BaseAtomicOp , (0b0011100011100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 17 , 1226), // #108 - INST(Ldaddalh , BaseAtomicOp , (0b0111100011100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 18 , 1235), // #109 - INST(Ldaddb , BaseAtomicOp , (0b0011100000100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 19 , 1244), // #110 - INST(Ldaddh , BaseAtomicOp , (0b0111100000100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 20 , 1251), // #111 - INST(Ldaddl , BaseAtomicOp , (0b1011100001100000000000, kWX, 30, 0) , kRWI_WRX , 0 , 21 , 1258), // #112 - INST(Ldaddlb , BaseAtomicOp , (0b0011100001100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 22 , 1265), // #113 - INST(Ldaddlh , BaseAtomicOp , (0b0111100001100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 23 , 1273), // #114 - INST(Ldar , BaseRM_NoImm , (0b1000100011011111111111, kWX, kZR, 30) , kRWI_W , 0 , 0 , 1281), // #115 - INST(Ldarb , BaseRM_NoImm , (0b0000100011011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 1 , 1286), // #116 - INST(Ldarh , BaseRM_NoImm , (0b0100100011011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 2 , 1292), // #117 - INST(Ldaxp , BaseLdxp , (0b1000100001111111100000, kWX, 30) , kRWI_WW , 0 , 0 , 1298), // #118 - INST(Ldaxr , BaseRM_NoImm , (0b1000100001011111111111, kWX, kZR, 30) , kRWI_W , 0 , 3 , 1304), // #119 - INST(Ldaxrb , BaseRM_NoImm , (0b0000100001011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 4 , 1310), // #120 - INST(Ldaxrh , BaseRM_NoImm , (0b0100100001011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 5 , 1317), // #121 - INST(Ldclr , BaseAtomicOp , (0b1011100000100000000100, kWX, 30, 0) , kRWI_WRX , 0 , 24 , 1324), // #122 - INST(Ldclra , BaseAtomicOp , (0b1011100010100000000100, kWX, 30, 1) , kRWI_WRX , 0 , 25 , 1330), // #123 - INST(Ldclrab , BaseAtomicOp , (0b0011100010100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 26 , 1337), // #124 - INST(Ldclrah , BaseAtomicOp , (0b0111100010100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 27 , 1345), // #125 - INST(Ldclral , BaseAtomicOp , (0b1011100011100000000100, kWX, 30, 1) , kRWI_WRX , 0 , 28 , 1353), // #126 - INST(Ldclralb , BaseAtomicOp , (0b0011100011100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 29 , 1361), // #127 - INST(Ldclralh , BaseAtomicOp , (0b0111100011100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 30 , 1370), // #128 - INST(Ldclrb , BaseAtomicOp , (0b0011100000100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 31 , 1379), // #129 - INST(Ldclrh , BaseAtomicOp , (0b0111100000100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 32 , 1386), // #130 - INST(Ldclrl , BaseAtomicOp , (0b1011100001100000000100, kWX, 30, 0) , kRWI_WRX , 0 , 33 , 1393), // #131 - INST(Ldclrlb , BaseAtomicOp , (0b0011100001100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 34 , 1400), // #132 - INST(Ldclrlh , BaseAtomicOp , (0b0111100001100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 35 , 1408), // #133 - INST(Ldeor , BaseAtomicOp , (0b1011100000100000001000, kWX, 30, 0) , kRWI_WRX , 0 , 36 , 1416), // #134 - INST(Ldeora , BaseAtomicOp , (0b1011100010100000001000, kWX, 30, 1) , kRWI_WRX , 0 , 37 , 1422), // #135 - INST(Ldeorab , BaseAtomicOp , (0b0011100010100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 38 , 1429), // #136 - INST(Ldeorah , BaseAtomicOp , (0b0111100010100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 39 , 1437), // #137 - INST(Ldeoral , BaseAtomicOp , (0b1011100011100000001000, kWX, 30, 1) , kRWI_WRX , 0 , 40 , 1445), // #138 - INST(Ldeoralb , BaseAtomicOp , (0b0011100011100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 41 , 1453), // #139 - INST(Ldeoralh , BaseAtomicOp , (0b0111100011100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 42 , 1462), // #140 - INST(Ldeorb , BaseAtomicOp , (0b0011100000100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 43 , 1471), // #141 - INST(Ldeorh , BaseAtomicOp , (0b0111100000100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 44 , 1478), // #142 - INST(Ldeorl , BaseAtomicOp , (0b1011100001100000001000, kWX, 30, 0) , kRWI_WRX , 0 , 45 , 1485), // #143 - INST(Ldeorlb , BaseAtomicOp , (0b0011100001100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 46 , 1492), // #144 - INST(Ldeorlh , BaseAtomicOp , (0b0111100001100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 47 , 1500), // #145 - INST(Ldg , BaseRM_SImm9 , (0b1101100101100000000000, 0b0000000000000000000000, kX , kZR, 0, 4) , kRWI_W , 0 , 0 , 1508), // #146 - INST(Ldgm , BaseRM_NoImm , (0b1101100111100000000000, kX , kZR, 0 ) , kRWI_W , 0 , 6 , 1512), // #147 - INST(Ldlar , BaseRM_NoImm , (0b1000100011011111011111, kWX, kZR, 30) , kRWI_W , 0 , 7 , 1517), // #148 - INST(Ldlarb , BaseRM_NoImm , (0b0000100011011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 8 , 1523), // #149 - INST(Ldlarh , BaseRM_NoImm , (0b0100100011011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 9 , 1530), // #150 - INST(Ldnp , BaseLdpStp , (0b0010100001, 0 , kWX, 31, 2) , kRWI_WW , 0 , 0 , 1537), // #151 - INST(Ldp , BaseLdpStp , (0b0010100101, 0b0010100011, kWX, 31, 2) , kRWI_W , 0 , 1 , 1542), // #152 - INST(Ldpsw , BaseLdpStp , (0b0110100101, 0b0110100011, kX , 0 , 2) , kRWI_WW , 0 , 2 , 1546), // #153 - INST(Ldr , BaseLdSt , (0b1011100101, 0b10111000010, 0b10111000011, 0b00011000, kWX, 30, 2, Inst::kIdLdur) , kRWI_W , 0 , 0 , 1552), // #154 - INST(Ldraa , BaseRM_SImm10 , (0b1111100000100000000001, kX , kZR, 0, 3) , kRWI_W , 0 , 0 , 1556), // #155 - INST(Ldrab , BaseRM_SImm10 , (0b1111100010100000000001, kX , kZR, 0, 3) , kRWI_W , 0 , 1 , 1562), // #156 - INST(Ldrb , BaseLdSt , (0b0011100101, 0b00111000010, 0b00111000011, 0 , kW , 0 , 0, Inst::kIdLdurb) , kRWI_W , 0 , 1 , 1568), // #157 - INST(Ldrh , BaseLdSt , (0b0111100101, 0b01111000010, 0b01111000011, 0 , kW , 0 , 1, Inst::kIdLdurh) , kRWI_W , 0 , 2 , 1573), // #158 - INST(Ldrsb , BaseLdSt , (0b0011100111, 0b00111000100, 0b00111000101, 0 , kWX, 22, 0, Inst::kIdLdursb) , kRWI_W , 0 , 3 , 1578), // #159 - INST(Ldrsh , BaseLdSt , (0b0111100110, 0b01111000100, 0b01111000101, 0 , kWX, 22, 1, Inst::kIdLdursh) , kRWI_W , 0 , 4 , 1584), // #160 - INST(Ldrsw , BaseLdSt , (0b1011100110, 0b10111000100, 0b10111000101, 0b10011000, kX , 0 , 2, Inst::kIdLdursw) , kRWI_W , 0 , 5 , 1590), // #161 - INST(Ldset , BaseAtomicOp , (0b1011100000100000001100, kWX, 30, 0) , kRWI_WRX , 0 , 48 , 1596), // #162 - INST(Ldseta , BaseAtomicOp , (0b1011100010100000001100, kWX, 30, 1) , kRWI_WRX , 0 , 49 , 1602), // #163 - INST(Ldsetab , BaseAtomicOp , (0b0011100010100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 50 , 1609), // #164 - INST(Ldsetah , BaseAtomicOp , (0b0111100010100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 51 , 1617), // #165 - INST(Ldsetal , BaseAtomicOp , (0b1011100011100000001100, kWX, 30, 1) , kRWI_WRX , 0 , 52 , 1625), // #166 - INST(Ldsetalb , BaseAtomicOp , (0b0011100011100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 53 , 1633), // #167 - INST(Ldsetalh , BaseAtomicOp , (0b0111100011100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 54 , 1642), // #168 - INST(Ldsetb , BaseAtomicOp , (0b0011100000100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 55 , 1651), // #169 - INST(Ldseth , BaseAtomicOp , (0b0111100000100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 56 , 1658), // #170 - INST(Ldsetl , BaseAtomicOp , (0b1011100001100000001100, kWX, 30, 0) , kRWI_WRX , 0 , 57 , 1665), // #171 - INST(Ldsetlb , BaseAtomicOp , (0b0011100001100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 58 , 1672), // #172 - INST(Ldsetlh , BaseAtomicOp , (0b0111100001100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 59 , 1680), // #173 - INST(Ldsmax , BaseAtomicOp , (0b1011100000100000010000, kWX, 30, 0) , kRWI_WRX , 0 , 60 , 1688), // #174 - INST(Ldsmaxa , BaseAtomicOp , (0b1011100010100000010000, kWX, 30, 1) , kRWI_WRX , 0 , 61 , 1695), // #175 - INST(Ldsmaxab , BaseAtomicOp , (0b0011100010100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 62 , 1703), // #176 - INST(Ldsmaxah , BaseAtomicOp , (0b0111100010100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 63 , 1712), // #177 - INST(Ldsmaxal , BaseAtomicOp , (0b1011100011100000010000, kWX, 30, 1) , kRWI_WRX , 0 , 64 , 1721), // #178 - INST(Ldsmaxalb , BaseAtomicOp , (0b0011100011100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 65 , 1730), // #179 - INST(Ldsmaxalh , BaseAtomicOp , (0b0111100011100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 66 , 1740), // #180 - INST(Ldsmaxb , BaseAtomicOp , (0b0011100000100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 67 , 1750), // #181 - INST(Ldsmaxh , BaseAtomicOp , (0b0111100000100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 68 , 1758), // #182 - INST(Ldsmaxl , BaseAtomicOp , (0b1011100001100000010000, kWX, 30, 0) , kRWI_WRX , 0 , 69 , 1766), // #183 - INST(Ldsmaxlb , BaseAtomicOp , (0b0011100001100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 70 , 1774), // #184 - INST(Ldsmaxlh , BaseAtomicOp , (0b0111100001100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 71 , 1783), // #185 - INST(Ldsmin , BaseAtomicOp , (0b1011100000100000010100, kWX, 30, 0) , kRWI_WRX , 0 , 72 , 1792), // #186 - INST(Ldsmina , BaseAtomicOp , (0b1011100010100000010100, kWX, 30, 1) , kRWI_WRX , 0 , 73 , 1799), // #187 - INST(Ldsminab , BaseAtomicOp , (0b0011100010100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 74 , 1807), // #188 - INST(Ldsminah , BaseAtomicOp , (0b0111100010100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 75 , 1816), // #189 - INST(Ldsminal , BaseAtomicOp , (0b1011100011100000010100, kWX, 30, 1) , kRWI_WRX , 0 , 76 , 1825), // #190 - INST(Ldsminalb , BaseAtomicOp , (0b0011100011100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 77 , 1834), // #191 - INST(Ldsminalh , BaseAtomicOp , (0b0111100011100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 78 , 1844), // #192 - INST(Ldsminb , BaseAtomicOp , (0b0011100000100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 79 , 1854), // #193 - INST(Ldsminh , BaseAtomicOp , (0b0111100000100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 80 , 1862), // #194 - INST(Ldsminl , BaseAtomicOp , (0b1011100001100000010100, kWX, 30, 0) , kRWI_WRX , 0 , 81 , 1870), // #195 - INST(Ldsminlb , BaseAtomicOp , (0b0011100001100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 82 , 1878), // #196 - INST(Ldsminlh , BaseAtomicOp , (0b0111100001100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 83 , 1887), // #197 - INST(Ldtr , BaseRM_SImm9 , (0b1011100001000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_W , 0 , 1 , 1896), // #198 - INST(Ldtrb , BaseRM_SImm9 , (0b0011100001000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 2 , 1901), // #199 - INST(Ldtrh , BaseRM_SImm9 , (0b0111100001000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 3 , 1907), // #200 - INST(Ldtrsb , BaseRM_SImm9 , (0b0011100011000000000010, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 4 , 1913), // #201 - INST(Ldtrsh , BaseRM_SImm9 , (0b0111100011000000000010, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 5 , 1920), // #202 - INST(Ldtrsw , BaseRM_SImm9 , (0b1011100010000000000010, 0b0000000000000000000000, kX , kZR, 0 , 0) , kRWI_W , 0 , 6 , 1927), // #203 - INST(Ldumax , BaseAtomicOp , (0b1011100000100000011000, kWX, 30, 0) , kRWI_WRX , 0 , 84 , 1934), // #204 - INST(Ldumaxa , BaseAtomicOp , (0b1011100010100000011000, kWX, 30, 1) , kRWI_WRX , 0 , 85 , 1941), // #205 - INST(Ldumaxab , BaseAtomicOp , (0b0011100010100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 86 , 1949), // #206 - INST(Ldumaxah , BaseAtomicOp , (0b0111100010100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 87 , 1958), // #207 - INST(Ldumaxal , BaseAtomicOp , (0b1011100011100000011000, kWX, 30, 1) , kRWI_WRX , 0 , 88 , 1967), // #208 - INST(Ldumaxalb , BaseAtomicOp , (0b0011100011100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 89 , 1976), // #209 - INST(Ldumaxalh , BaseAtomicOp , (0b0111100011100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 90 , 1986), // #210 - INST(Ldumaxb , BaseAtomicOp , (0b0011100000100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 91 , 1996), // #211 - INST(Ldumaxh , BaseAtomicOp , (0b0111100000100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 92 , 2004), // #212 - INST(Ldumaxl , BaseAtomicOp , (0b1011100001100000011000, kWX, 30, 0) , kRWI_WRX , 0 , 93 , 2012), // #213 - INST(Ldumaxlb , BaseAtomicOp , (0b0011100001100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 94 , 2020), // #214 - INST(Ldumaxlh , BaseAtomicOp , (0b0111100001100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 95 , 2029), // #215 - INST(Ldumin , BaseAtomicOp , (0b1011100000100000011100, kWX, 30, 0) , kRWI_WRX , 0 , 96 , 2038), // #216 - INST(Ldumina , BaseAtomicOp , (0b1011100010100000011100, kWX, 30, 1) , kRWI_WRX , 0 , 97 , 2045), // #217 - INST(Lduminab , BaseAtomicOp , (0b0011100010100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 98 , 2053), // #218 - INST(Lduminah , BaseAtomicOp , (0b0111100010100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 99 , 2062), // #219 - INST(Lduminal , BaseAtomicOp , (0b1011100011100000011100, kWX, 30, 1) , kRWI_WRX , 0 , 100, 2071), // #220 - INST(Lduminalb , BaseAtomicOp , (0b0011100011100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 101, 2080), // #221 - INST(Lduminalh , BaseAtomicOp , (0b0111100011100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 102, 2090), // #222 - INST(Lduminb , BaseAtomicOp , (0b0011100000100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 103, 2100), // #223 - INST(Lduminh , BaseAtomicOp , (0b0111100000100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 104, 2108), // #224 - INST(Lduminl , BaseAtomicOp , (0b1011100001100000011100, kWX, 30, 0) , kRWI_WRX , 0 , 105, 2116), // #225 - INST(Lduminlb , BaseAtomicOp , (0b0011100001100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 106, 2124), // #226 - INST(Lduminlh , BaseAtomicOp , (0b0111100001100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 107, 2133), // #227 - INST(Ldur , BaseRM_SImm9 , (0b1011100001000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_W , 0 , 7 , 2142), // #228 - INST(Ldurb , BaseRM_SImm9 , (0b0011100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 8 , 2147), // #229 - INST(Ldurh , BaseRM_SImm9 , (0b0111100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 9 , 2153), // #230 - INST(Ldursb , BaseRM_SImm9 , (0b0011100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 10 , 2159), // #231 - INST(Ldursh , BaseRM_SImm9 , (0b0111100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 11 , 2166), // #232 - INST(Ldursw , BaseRM_SImm9 , (0b1011100010000000000000, 0b0000000000000000000000, kWX, kZR, 0 , 0) , kRWI_W , 0 , 12 , 2173), // #233 - INST(Ldxp , BaseLdxp , (0b1000100001111111000000, kWX, 30) , kRWI_WW , 0 , 1 , 2180), // #234 - INST(Ldxr , BaseRM_NoImm , (0b1000100001011111011111, kWX, kZR, 30) , kRWI_W , 0 , 10 , 2185), // #235 - INST(Ldxrb , BaseRM_NoImm , (0b0000100001011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 11 , 2190), // #236 - INST(Ldxrh , BaseRM_NoImm , (0b0100100001011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 12 , 2196), // #237 - INST(Lsl , BaseShift , (0b0001101011000000001000, 0b0101001100000000000000, 0) , kRWI_W , 0 , 2 , 2880), // #238 - INST(Lslv , BaseShift , (0b0001101011000000001000, 0b0000000000000000000000, 0) , kRWI_W , 0 , 3 , 2202), // #239 - INST(Lsr , BaseShift , (0b0001101011000000001001, 0b0101001100000000011111, 0) , kRWI_W , 0 , 4 , 2207), // #240 - INST(Lsrv , BaseShift , (0b0001101011000000001001, 0b0000000000000000000000, 0) , kRWI_W , 0 , 5 , 2211), // #241 - INST(Madd , BaseRRRR , (0b0001101100000000000000, kWX, kZR, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 0 , 977 ), // #242 - INST(Mneg , BaseRRR , (0b0001101100000000111111, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 11 , 2216), // #243 - INST(Mov , BaseMov , (_) , kRWI_W , 0 , 0 , 949 ), // #244 - INST(Movk , BaseMovKNZ , (0b01110010100000000000000000000000) , kRWI_X , 0 , 0 , 2226), // #245 - INST(Movn , BaseMovKNZ , (0b00010010100000000000000000000000) , kRWI_W , 0 , 1 , 2231), // #246 - INST(Movz , BaseMovKNZ , (0b01010010100000000000000000000000) , kRWI_W , 0 , 2 , 2236), // #247 - INST(Mrs , BaseMrs , (_) , kRWI_W , 0 , 0 , 2241), // #248 - INST(Msr , BaseMsr , (_) , kRWI_W , 0 , 0 , 2245), // #249 - INST(Msub , BaseRRRR , (0b0001101100000000100000, kWX, kZR, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 1 , 984 ), // #250 - INST(Mul , BaseRRR , (0b0001101100000000011111, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 12 , 991 ), // #251 - INST(Mvn , BaseMvnNeg , (0b00101010001000000000001111100000) , kRWI_W , 0 , 0 , 2249), // #252 - INST(Neg , BaseMvnNeg , (0b01001011000000000000001111100000) , kRWI_W , 0 , 1 , 540 ), // #253 - INST(Negs , BaseMvnNeg , (0b01101011000000000000001111100000) , kRWI_W , 0 , 2 , 2258), // #254 - INST(Ngc , BaseRR , (0b01011010000000000000001111100000, kWX, kZR, 0, kWX, kZR, 16, true) , kRWI_W , 0 , 7 , 2263), // #255 - INST(Ngcs , BaseRR , (0b01111010000000000000001111100000, kWX, kZR, 0, kWX, kZR, 16, true) , kRWI_W , 0 , 8 , 2267), // #256 - INST(Nop , BaseOp , (0b11010101000000110010000000011111) , 0 , 0 , 13 , 2272), // #257 - INST(Orn , BaseLogical , (0b0101010001, 0b01100100, 1) , kRWI_W , 0 , 6 , 2280), // #258 - INST(Orr , BaseLogical , (0b0101010000, 0b01100100, 0) , kRWI_W , 0 , 7 , 2284), // #259 - INST(Pacda , BaseRR , (0b11011010110000010000100000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 9 , 2288), // #260 - INST(Pacdb , BaseRR , (0b11011010110000010000110000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 10 , 2294), // #261 - INST(Pacdza , BaseR , (0b11011010110000010010101111100000, kX, kZR, 0) , kRWI_X , 0 , 4 , 2300), // #262 - INST(Pacdzb , BaseR , (0b11011010110000010010111111100000, kX, kZR, 0) , kRWI_X , 0 , 5 , 2307), // #263 - INST(Pacga , BaseRRR , (0b1001101011000000001100, kX, kZR, kX, kZR, kX, kSP, false) , kRWI_W , 0 , 13 , 2314), // #264 - INST(Pssbb , BaseOp , (0b11010101000000110011010010011111) , 0 , 0 , 14 , 2338), // #265 - INST(Rbit , BaseRR , (0b01011010110000000000000000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 11 , 2364), // #266 - INST(Ret , BaseBranchReg , (0b11010110010111110000000000000000) , kRWI_R , 0 , 2 , 593 ), // #267 - INST(Rev , BaseRev , (_) , kRWI_W , 0 , 0 , 2369), // #268 - INST(Rev16 , BaseRR , (0b01011010110000000000010000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 12 , 2373), // #269 - INST(Rev32 , BaseRR , (0b11011010110000000000100000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 13 , 2379), // #270 - INST(Rev64 , BaseRR , (0b11011010110000000000110000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 14 , 2385), // #271 - INST(Ror , BaseShift , (0b0001101011000000001011, 0b0001001110000000000000, 1) , kRWI_W , 0 , 6 , 2391), // #272 - INST(Rorv , BaseShift , (0b0001101011000000001011, 0b0000000000000000000000, 1) , kRWI_W , 0 , 7 , 2395), // #273 - INST(Sbc , BaseRRR , (0b0101101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 14 , 2498), // #274 - INST(Sbcs , BaseRRR , (0b0111101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 15 , 2502), // #275 - INST(Sbfiz , BaseBfi , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 , 2507), // #276 - INST(Sbfm , BaseBfm , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 , 2513), // #277 - INST(Sbfx , BaseBfx , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 , 2518), // #278 - INST(Sdiv , BaseRRR , (0b0001101011000000000011, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 16 , 2529), // #279 - INST(Setf8 , BaseR , (0b00111010000000000000100000001101, kW, kZR, 5) , 0 , 0 , 6 , 2541), // #280 - INST(Setf16 , BaseR , (0b00111010000000000100100000001101, kW, kZR, 5) , 0 , 0 , 7 , 2534), // #281 - INST(Sev , BaseOp , (0b11010101000000110010000010011111) , 0 , 0 , 15 , 2547), // #282 - INST(Sevl , BaseOp , (0b11010101000000110010000010111111) , 0 , 0 , 16 , 2551), // #283 - INST(Smaddl , BaseRRRR , (0b1001101100100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 2 , 2758), // #284 - INST(Smc , BaseOpImm , (0b11010100000000000000000000000011, 16, 5) , 0 , 0 , 11 , 53 ), // #285 - INST(Smnegl , BaseRRR , (0b1001101100100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 17 , 2815), // #286 - INST(Smsubl , BaseRRRR , (0b1001101100100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 3 , 2827), // #287 - INST(Smulh , BaseRRR , (0b1001101101000000011111, kX , kZR, kX , kZR, kX , kZR, true) , kRWI_W , 0 , 18 , 2834), // #288 - INST(Smull , BaseRRR , (0b1001101100100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 19 , 2840), // #289 - INST(Ssbb , BaseOp , (0b11010101000000110011000010011111) , 0 , 0 , 17 , 2339), // #290 - INST(St2g , BaseRM_SImm9 , (0b1101100110100000000010, 0b1101100110100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 13 , 3164), // #291 - INST(Stadd , BaseAtomicSt , (0b1011100000100000000000, kWX, 30) , kRWI_RX , 0 , 0 , 3177), // #292 - INST(Staddl , BaseAtomicSt , (0b1011100001100000000000, kWX, 30) , kRWI_RX , 0 , 1 , 3197), // #293 - INST(Staddb , BaseAtomicSt , (0b0011100000100000000000, kW , 0 ) , kRWI_RX , 0 , 2 , 3183), // #294 - INST(Staddlb , BaseAtomicSt , (0b0011100001100000000000, kW , 0 ) , kRWI_RX , 0 , 3 , 3204), // #295 - INST(Staddh , BaseAtomicSt , (0b0111100000100000000000, kW , 0 ) , kRWI_RX , 0 , 4 , 3190), // #296 - INST(Staddlh , BaseAtomicSt , (0b0111100001100000000000, kW , 0 ) , kRWI_RX , 0 , 5 , 3212), // #297 - INST(Stclr , BaseAtomicSt , (0b1011100000100000000100, kWX, 30) , kRWI_RX , 0 , 6 , 3220), // #298 - INST(Stclrl , BaseAtomicSt , (0b1011100001100000000100, kWX, 30) , kRWI_RX , 0 , 7 , 3240), // #299 - INST(Stclrb , BaseAtomicSt , (0b0011100000100000000100, kW , 0 ) , kRWI_RX , 0 , 8 , 3226), // #300 - INST(Stclrlb , BaseAtomicSt , (0b0011100001100000000100, kW , 0 ) , kRWI_RX , 0 , 9 , 3247), // #301 - INST(Stclrh , BaseAtomicSt , (0b0111100000100000000100, kW , 0 ) , kRWI_RX , 0 , 10 , 3233), // #302 - INST(Stclrlh , BaseAtomicSt , (0b0111100001100000000100, kW , 0 ) , kRWI_RX , 0 , 11 , 3255), // #303 - INST(Steor , BaseAtomicSt , (0b1011100000100000001000, kWX, 30) , kRWI_RX , 0 , 12 , 3263), // #304 - INST(Steorl , BaseAtomicSt , (0b1011100001100000001000, kWX, 30) , kRWI_RX , 0 , 13 , 3283), // #305 - INST(Steorb , BaseAtomicSt , (0b0011100000100000001000, kW , 0 ) , kRWI_RX , 0 , 14 , 3269), // #306 - INST(Steorlb , BaseAtomicSt , (0b0011100001100000001000, kW , 0 ) , kRWI_RX , 0 , 15 , 3290), // #307 - INST(Steorh , BaseAtomicSt , (0b0111100000100000001000, kW , 0 ) , kRWI_RX , 0 , 16 , 3276), // #308 - INST(Steorlh , BaseAtomicSt , (0b0111100001100000001000, kW , 0 ) , kRWI_RX , 0 , 17 , 3298), // #309 - INST(Stg , BaseRM_SImm9 , (0b1101100100100000000010, 0b1101100100100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 14 , 3306), // #310 - INST(Stgm , BaseRM_NoImm , (0b1101100110100000000000, kX , kZR, 0 ) , kRWI_RW , 0 , 13 , 3310), // #311 - INST(Stgp , BaseLdpStp , (0b0110100100, 0b0110100010, kX, 0, 4) , kRWI_RRW , 0 , 3 , 3315), // #312 - INST(Stllr , BaseRM_NoImm , (0b1000100010011111011111, kWX, kZR, 30) , kRWI_RW , 0 , 14 , 3320), // #313 - INST(Stllrb , BaseRM_NoImm , (0b0000100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 15 , 3326), // #314 - INST(Stllrh , BaseRM_NoImm , (0b0100100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 16 , 3333), // #315 - INST(Stlr , BaseRM_NoImm , (0b1000100010011111111111, kWX, kZR, 30) , kRWI_RW , 0 , 17 , 3340), // #316 - INST(Stlrb , BaseRM_NoImm , (0b0000100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 18 , 3345), // #317 - INST(Stlrh , BaseRM_NoImm , (0b0100100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 19 , 3351), // #318 - INST(Stlxp , BaseStxp , (0b1000100000100000100000, kWX, 30) , kRWI_WRRX , 0 , 0 , 3357), // #319 - INST(Stlxr , BaseAtomicOp , (0b1000100000000000111111, kWX, 30, 1) , kRWI_WRX , 0 , 108, 3363), // #320 - INST(Stlxrb , BaseAtomicOp , (0b0000100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 109, 3369), // #321 - INST(Stlxrh , BaseAtomicOp , (0b0100100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 110, 3376), // #322 - INST(Stnp , BaseLdpStp , (0b0010100000, 0 , kWX, 31, 2) , kRWI_RRW , 0 , 4 , 3383), // #323 - INST(Stp , BaseLdpStp , (0b0010100100, 0b0010100010, kWX, 31, 2) , kRWI_RRW , 0 , 5 , 3388), // #324 - INST(Str , BaseLdSt , (0b1011100100, 0b10111000000, 0b10111000001, 0 , kWX, 30, 2, Inst::kIdStur) , kRWI_RW , 0 , 6 , 3392), // #325 - INST(Strb , BaseLdSt , (0b0011100100, 0b00111000000, 0b00111000001, 0 , kW , 30, 0, Inst::kIdSturb) , kRWI_RW , 0 , 7 , 3396), // #326 - INST(Strh , BaseLdSt , (0b0111100100, 0b01111000000, 0b01111000001, 0 , kWX, 30, 1, Inst::kIdSturh) , kRWI_RW , 0 , 8 , 3401), // #327 - INST(Stset , BaseAtomicSt , (0b1011100000100000001100, kWX, 30) , kRWI_RX , 0 , 18 , 3406), // #328 - INST(Stsetl , BaseAtomicSt , (0b1011100001100000001100, kWX, 30) , kRWI_RX , 0 , 19 , 3426), // #329 - INST(Stsetb , BaseAtomicSt , (0b0011100000100000001100, kW , 0 ) , kRWI_RX , 0 , 20 , 3412), // #330 - INST(Stsetlb , BaseAtomicSt , (0b0011100001100000001100, kW , 0 ) , kRWI_RX , 0 , 21 , 3433), // #331 - INST(Stseth , BaseAtomicSt , (0b0111100000100000001100, kW , 0 ) , kRWI_RX , 0 , 22 , 3419), // #332 - INST(Stsetlh , BaseAtomicSt , (0b0111100001100000001100, kW , 0 ) , kRWI_RX , 0 , 23 , 3441), // #333 - INST(Stsmax , BaseAtomicSt , (0b1011100000100000010000, kWX, 30) , kRWI_RX , 0 , 24 , 3449), // #334 - INST(Stsmaxl , BaseAtomicSt , (0b1011100001100000010000, kWX, 30) , kRWI_RX , 0 , 25 , 3472), // #335 - INST(Stsmaxb , BaseAtomicSt , (0b0011100000100000010000, kW , 0 ) , kRWI_RX , 0 , 26 , 3456), // #336 - INST(Stsmaxlb , BaseAtomicSt , (0b0011100001100000010000, kW , 0 ) , kRWI_RX , 0 , 27 , 3480), // #337 - INST(Stsmaxh , BaseAtomicSt , (0b0111100000100000010000, kW , 0 ) , kRWI_RX , 0 , 28 , 3464), // #338 - INST(Stsmaxlh , BaseAtomicSt , (0b0111100001100000010000, kW , 0 ) , kRWI_RX , 0 , 29 , 3489), // #339 - INST(Stsmin , BaseAtomicSt , (0b1011100000100000010100, kWX, 30) , kRWI_RX , 0 , 30 , 3498), // #340 - INST(Stsminl , BaseAtomicSt , (0b1011100001100000010100, kWX, 30) , kRWI_RX , 0 , 31 , 3521), // #341 - INST(Stsminb , BaseAtomicSt , (0b0011100000100000010100, kW , 0 ) , kRWI_RX , 0 , 32 , 3505), // #342 - INST(Stsminlb , BaseAtomicSt , (0b0011100001100000010100, kW , 0 ) , kRWI_RX , 0 , 33 , 3529), // #343 - INST(Stsminh , BaseAtomicSt , (0b0111100000100000010100, kW , 0 ) , kRWI_RX , 0 , 34 , 3513), // #344 - INST(Stsminlh , BaseAtomicSt , (0b0111100001100000010100, kW , 0 ) , kRWI_RX , 0 , 35 , 3538), // #345 - INST(Sttr , BaseRM_SImm9 , (0b1011100000000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 15 , 3547), // #346 - INST(Sttrb , BaseRM_SImm9 , (0b0011100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 16 , 3552), // #347 - INST(Sttrh , BaseRM_SImm9 , (0b0111100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 17 , 3558), // #348 - INST(Stumax , BaseAtomicSt , (0b1011100000100000011000, kWX, 30) , kRWI_RX , 0 , 36 , 3564), // #349 - INST(Stumaxl , BaseAtomicSt , (0b1011100001100000011000, kWX, 30) , kRWI_RX , 0 , 37 , 3587), // #350 - INST(Stumaxb , BaseAtomicSt , (0b0011100000100000011000, kW , 0 ) , kRWI_RX , 0 , 38 , 3571), // #351 - INST(Stumaxlb , BaseAtomicSt , (0b0011100001100000011000, kW , 0 ) , kRWI_RX , 0 , 39 , 3595), // #352 - INST(Stumaxh , BaseAtomicSt , (0b0111100000100000011000, kW , 0 ) , kRWI_RX , 0 , 40 , 3579), // #353 - INST(Stumaxlh , BaseAtomicSt , (0b0111100001100000011000, kW , 0 ) , kRWI_RX , 0 , 41 , 3604), // #354 - INST(Stumin , BaseAtomicSt , (0b1011100000100000011100, kWX, 30) , kRWI_RX , 0 , 42 , 3613), // #355 - INST(Stuminl , BaseAtomicSt , (0b1011100001100000011100, kWX, 30) , kRWI_RX , 0 , 43 , 3636), // #356 - INST(Stuminb , BaseAtomicSt , (0b0011100000100000011100, kW , 0 ) , kRWI_RX , 0 , 44 , 3620), // #357 - INST(Stuminlb , BaseAtomicSt , (0b0011100001100000011100, kW , 0 ) , kRWI_RX , 0 , 45 , 3644), // #358 - INST(Stuminh , BaseAtomicSt , (0b0111100000100000011100, kW , 0 ) , kRWI_RX , 0 , 46 , 3628), // #359 - INST(Stuminlh , BaseAtomicSt , (0b0111100001100000011100, kW , 0 ) , kRWI_RX , 0 , 47 , 3653), // #360 - INST(Stur , BaseRM_SImm9 , (0b1011100000000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 18 , 3662), // #361 - INST(Sturb , BaseRM_SImm9 , (0b0011100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 19 , 3667), // #362 - INST(Sturh , BaseRM_SImm9 , (0b0111100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 20 , 3673), // #363 - INST(Stxp , BaseStxp , (0b1000100000100000000000, kWX, 30) , kRWI_WRRW , 0 , 1 , 3679), // #364 - INST(Stxr , BaseStx , (0b1000100000000000011111, kWX, 30) , kRWI_WRW , 0 , 0 , 3684), // #365 - INST(Stxrb , BaseStx , (0b0000100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 1 , 3689), // #366 - INST(Stxrh , BaseStx , (0b0100100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 2 , 3695), // #367 - INST(Stz2g , BaseRM_SImm9 , (0b1101100111100000000010, 0b1101100111100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 21 , 3701), // #368 - INST(Stzg , BaseRM_SImm9 , (0b1101100101100000000010, 0b1101100101100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 22 , 3707), // #369 - INST(Stzgm , BaseRM_NoImm , (0b1101100100100000000000, kX , kZR, 0) , kRWI_RW , 0 , 20 , 3712), // #370 - INST(Sub , BaseAddSub , (0b1001011000, 0b1001011001, 0b1010001) , kRWI_X , 0 , 2 , 985 ), // #371 - INST(Subg , BaseRRII , (0b1101000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10) , kRWI_W , 0 , 1 , 3718), // #372 - INST(Subp , BaseRRR , (0b1001101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 20 , 3723), // #373 - INST(Subps , BaseRRR , (0b1011101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 21 , 3728), // #374 - INST(Subs , BaseAddSub , (0b1101011000, 0b1101011001, 0b1110001) , kRWI_X , 0 , 3 , 3734), // #375 - INST(Svc , BaseOpImm , (0b11010100000000000000000000000001, 16, 5) , 0 , 0 , 12 , 3752), // #376 - INST(Swp , BaseAtomicOp , (0b1011100000100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 111, 3756), // #377 - INST(Swpa , BaseAtomicOp , (0b1011100010100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 112, 3760), // #378 - INST(Swpab , BaseAtomicOp , (0b0011100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 113, 3765), // #379 - INST(Swpah , BaseAtomicOp , (0b0111100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 114, 3771), // #380 - INST(Swpal , BaseAtomicOp , (0b1011100011100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 115, 3777), // #381 - INST(Swpalb , BaseAtomicOp , (0b0011100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 116, 3783), // #382 - INST(Swpalh , BaseAtomicOp , (0b0111100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 117, 3790), // #383 - INST(Swpb , BaseAtomicOp , (0b0011100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 118, 3797), // #384 - INST(Swph , BaseAtomicOp , (0b0111100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 119, 3802), // #385 - INST(Swpl , BaseAtomicOp , (0b1011100001100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 120, 3807), // #386 - INST(Swplb , BaseAtomicOp , (0b0011100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 121, 3812), // #387 - INST(Swplh , BaseAtomicOp , (0b0111100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 122, 3818), // #388 - INST(Sxtb , BaseExtend , (0b0001001100000000000111, kWX, 0) , kRWI_W , 0 , 0 , 3824), // #389 - INST(Sxth , BaseExtend , (0b0001001100000000001111, kWX, 0) , kRWI_W , 0 , 1 , 3829), // #390 - INST(Sxtw , BaseExtend , (0b1001001101000000011111, kX , 0) , kRWI_W , 0 , 2 , 3845), // #391 - INST(Sys , BaseSys , (_) , kRWI_W , 0 , 0 , 3850), // #392 - INST(Tlbi , BaseAtDcIcTlbi , (0b00011110000000, 0b00010000000000, false) , kRWI_RX , 0 , 3 , 3871), // #393 - INST(Tst , BaseTst , (0b1101010000, 0b111001000) , kRWI_R , 0 , 0 , 437 ), // #394 - INST(Tbnz , BaseBranchTst , (0b00110111000000000000000000000000) , kRWI_R , 0 , 0 , 3858), // #395 - INST(Tbz , BaseBranchTst , (0b00110110000000000000000000000000) , kRWI_R , 0 , 1 , 3867), // #396 - INST(Ubfiz , BaseBfi , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 , 3969), // #397 - INST(Ubfm , BaseBfm , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 , 3975), // #398 - INST(Ubfx , BaseBfx , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 , 3980), // #399 - INST(Udf , BaseOpImm , (0b00000000000000000000000000000000, 16, 0) , 0 , 0 , 13 , 3991), // #400 - INST(Udiv , BaseRRR , (0b0001101011000000000010, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 22 , 3995), // #401 - INST(Umaddl , BaseRRRR , (0b1001101110100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 4 , 4012), // #402 - INST(Umnegl , BaseRRR , (0b1001101110100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 23 , 4075), // #403 - INST(Umull , BaseRRR , (0b1001101110100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 24 , 4100), // #404 - INST(Umulh , BaseRRR , (0b1001101111000000011111, kX , kZR, kX , kZR, kX , kZR, false) , kRWI_W , 0 , 25 , 4094), // #405 - INST(Umsubl , BaseRRRR , (0b1001101110100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 5 , 4087), // #406 - INST(Uxtb , BaseExtend , (0b0101001100000000000111, kW, 1) , kRWI_W , 0 , 3 , 4291), // #407 - INST(Uxth , BaseExtend , (0b0101001100000000001111, kW, 1) , kRWI_W , 0 , 4 , 4296), // #408 - INST(Wfe , BaseOp , (0b11010101000000110010000001011111) , 0 , 0 , 18 , 4322), // #409 - INST(Wfi , BaseOp , (0b11010101000000110010000001111111) , 0 , 0 , 19 , 4326), // #410 - INST(Xaflag , BaseOp , (0b11010101000000000100000000111111) , 0 , 0 , 20 , 4330), // #411 - INST(Xpacd , BaseR , (0b11011010110000010100011111100000, kX, kZR, 0) , kRWI_X , 0 , 8 , 4341), // #412 - INST(Xpaci , BaseR , (0b11011010110000010100001111100000, kX, kZR, 0) , kRWI_X , 0 , 9 , 4347), // #413 - INST(Xpaclri , BaseOp , (0b11010101000000110010000011111111) , kRWI_X , 0 , 21 , 4353), // #414 - INST(Yield , BaseOp , (0b11010101000000110010000000111111) , 0 , 0 , 22 , 4361), // #415 - INST(Abs_v , ISimdVV , (0b0000111000100000101110, kVO_V_Any) , kRWI_W , 0 , 0 , 2855), // #416 - INST(Add_v , ISimdVVV , (0b0000111000100000100001, kVO_V_Any) , kRWI_W , 0 , 0 , 978 ), // #417 - INST(Addhn_v , ISimdVVV , (0b0000111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 1 , 2345), // #418 - INST(Addhn2_v , ISimdVVV , (0b0100111000100000010000, kVO_V_B16H8S4) , kRWI_W , F(Narrow) , 2 , 2352), // #419 - INST(Addp_v , ISimdPair , (0b0101111000110001101110, 0b0000111000100000101111, kVO_V_Any) , kRWI_W , F(Pair) , 0 , 638 ), // #420 - INST(Addv_v , ISimdSV , (0b0000111000110001101110, kVO_V_BH_4S) , kRWI_W , 0 , 0 , 20 ), // #421 - INST(Aesd_v , ISimdVVx , (0b0100111000101000010110, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 0 , 34 ), // #422 - INST(Aese_v , ISimdVVx , (0b0100111000101000010010, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 1 , 39 ), // #423 - INST(Aesimc_v , ISimdVVx , (0b0100111000101000011110, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 2 , 44 ), // #424 - INST(Aesmc_v , ISimdVVx , (0b0100111000101000011010, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 3 , 51 ), // #425 - INST(And_v , ISimdVVV , (0b0000111000100000000111, kVO_V_B) , kRWI_W , 0 , 3 , 57 ), // #426 - INST(Bcax_v , ISimdVVVV , (0b1100111000100000000000, kVO_V_B16) , kRWI_W , 0 , 0 , 187 ), // #427 - INST(Bfcvt_v , ISimdVVx , (0b0001111001100011010000, kOp_H, kOp_S) , kRWI_W , 0 , 4 , 196 ), // #428 - INST(Bfcvtn_v , ISimdVVx , (0b0000111010100001011010, kOp_V4H, kOp_V4S) , kRWI_W , F(Narrow) , 5 , 202 ), // #429 - INST(Bfcvtn2_v , ISimdVVx , (0b0100111010100001011010, kOp_V8H, kOp_V4S) , kRWI_W , F(Narrow) , 6 , 209 ), // #430 - INST(Bfdot_v , SimdDot , (0b0010111001000000111111, 0b0000111101000000111100, kET_S, kET_H, kET_2H) , kRWI_X , 0 , 0 , 217 ), // #431 - INST(Bfmlalb_v , SimdFmlal , (0b0010111011000000111111, 0b0000111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 0 , 227 ), // #432 - INST(Bfmlalt_v , SimdFmlal , (0b0110111011000000111111, 0b0100111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 1 , 235 ), // #433 - INST(Bfmmla_v , ISimdVVVx , (0b0110111001000000111011, kOp_V4S, kOp_V8H, kOp_V8H) , kRWI_X , F(Long) , 0 , 243 ), // #434 - INST(Bic_v , SimdBicOrr , (0b0000111001100000000111, 0b0010111100000000000001) , kRWI_W , 0 , 0 , 256 ), // #435 - INST(Bif_v , ISimdVVV , (0b0010111011100000000111, kVO_V_B) , kRWI_X , 0 , 4 , 265 ), // #436 - INST(Bit_v , ISimdVVV , (0b0010111010100000000111, kVO_V_B) , kRWI_X , 0 , 5 , 2365), // #437 - INST(Bsl_v , ISimdVVV , (0b0010111001100000000111, kVO_V_B) , kRWI_X , 0 , 6 , 280 ), // #438 - INST(Cls_v , ISimdVV , (0b0000111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 1 , 412 ), // #439 - INST(Clz_v , ISimdVV , (0b0010111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 2 , 416 ), // #440 - INST(Cmeq_v , SimdCmp , (0b0010111000100000100011, 0b0000111000100000100110, kVO_V_Any) , kRWI_W , 0 , 0 , 663 ), // #441 - INST(Cmge_v , SimdCmp , (0b0000111000100000001111, 0b0010111000100000100010, kVO_V_Any) , kRWI_W , 0 , 1 , 669 ), // #442 - INST(Cmgt_v , SimdCmp , (0b0000111000100000001101, 0b0000111000100000100010, kVO_V_Any) , kRWI_W , 0 , 2 , 675 ), // #443 - INST(Cmhi_v , SimdCmp , (0b0010111000100000001101, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 3 , 420 ), // #444 - INST(Cmhs_v , SimdCmp , (0b0010111000100000001111, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 4 , 425 ), // #445 - INST(Cmle_v , SimdCmp , (0b0000000000000000000000, 0b0010111000100000100110, kVO_V_Any) , kRWI_W , 0 , 5 , 687 ), // #446 - INST(Cmlt_v , SimdCmp , (0b0000000000000000000000, 0b0000111000100000101010, kVO_V_Any) , kRWI_W , 0 , 6 , 693 ), // #447 - INST(Cmtst_v , ISimdVVV , (0b0000111000100000100011, kVO_V_Any) , kRWI_W , 0 , 7 , 435 ), // #448 - INST(Cnt_v , ISimdVV , (0b0000111000100000010110, kVO_V_B) , kRWI_W , 0 , 3 , 446 ), // #449 - INST(Dup_v , SimdDup , (_) , kRWI_W , 0 , 0 , 579 ), // #450 - INST(Eor_v , ISimdVVV , (0b0010111000100000000111, kVO_V_B) , kRWI_W , 0 , 8 , 1418), // #451 - INST(Eor3_v , ISimdVVVV , (0b1100111000000000000000, kVO_V_B16) , kRWI_W , 0 , 1 , 587 ), // #452 - INST(Ext_v , ISimdVVVI , (0b0010111000000000000000, kVO_V_B, 4, 11, 1) , kRWI_W , 0 , 0 , 601 ), // #453 - INST(Fabd_v , FSimdVVV , (0b0111111010100000110101, kHF_C, 0b0010111010100000110101, kHF_C) , kRWI_W , 0 , 0 , 610 ), // #454 - INST(Fabs_v , FSimdVV , (0b0001111000100000110000, kHF_A, 0b0000111010100000111110, kHF_B) , kRWI_W , 0 , 0 , 615 ), // #455 - INST(Facge_v , FSimdVVV , (0b0111111000100000111011, kHF_C, 0b0010111000100000111011, kHF_C) , kRWI_W , 0 , 1 , 620 ), // #456 - INST(Facgt_v , FSimdVVV , (0b0111111010100000111011, kHF_C, 0b0010111010100000111011, kHF_C) , kRWI_W , 0 , 2 , 626 ), // #457 - INST(Fadd_v , FSimdVVV , (0b0001111000100000001010, kHF_A, 0b0000111000100000110101, kHF_C) , kRWI_W , 0 , 3 , 632 ), // #458 - INST(Faddp_v , FSimdPair , (0b0111111000110000110110, 0b0010111000100000110101) , kRWI_W , 0 , 0 , 637 ), // #459 - INST(Fcadd_v , SimdFcadd , (0b0010111000000000111001) , kRWI_W , 0 , 0 , 643 ), // #460 - INST(Fccmp_v , SimdFccmpFccmpe , (0b00011110001000000000010000000000) , kRWI_R , 0 , 0 , 649 ), // #461 - INST(Fccmpe_v , SimdFccmpFccmpe , (0b00011110001000000000010000010000) , kRWI_R , 0 , 1 , 655 ), // #462 - INST(Fcmeq_v , SimdFcm , (0b0000111000100000111001, kHF_C, 0b0000111010100000110110) , kRWI_W , 0 , 0 , 662 ), // #463 - INST(Fcmge_v , SimdFcm , (0b0010111000100000111001, kHF_C, 0b0010111010100000110010) , kRWI_W , 0 , 1 , 668 ), // #464 - INST(Fcmgt_v , SimdFcm , (0b0010111010100000111001, kHF_C, 0b0000111010100000110010) , kRWI_W , 0 , 2 , 674 ), // #465 - INST(Fcmla_v , SimdFcmla , (0b0010111000000000110001, 0b0010111100000000000100) , kRWI_X , 0 , 0 , 680 ), // #466 - INST(Fcmle_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0010111010100000110110) , kRWI_W , 0 , 3 , 686 ), // #467 - INST(Fcmlt_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0000111010100000111010) , kRWI_W , 0 , 4 , 692 ), // #468 - INST(Fcmp_v , SimdFcmpFcmpe , (0b00011110001000000010000000000000) , kRWI_R , 0 , 0 , 698 ), // #469 - INST(Fcmpe_v , SimdFcmpFcmpe , (0b00011110001000000010000000010000) , kRWI_R , 0 , 1 , 703 ), // #470 - INST(Fcsel_v , SimdFcsel , (_) , kRWI_W , 0 , 0 , 709 ), // #471 - INST(Fcvt_v , SimdFcvt , (_) , kRWI_W , 0 , 0 , 197 ), // #472 - INST(Fcvtas_v , SimdFcvtSV , (0b0000111000100001110010, 0b0000000000000000000000, 0b0001111000100100000000, 1) , kRWI_W , 0 , 0 , 715 ), // #473 - INST(Fcvtau_v , SimdFcvtSV , (0b0010111000100001110010, 0b0000000000000000000000, 0b0001111000100101000000, 1) , kRWI_W , 0 , 1 , 722 ), // #474 - INST(Fcvtl_v , SimdFcvtLN , (0b0000111000100001011110, 0, 0) , kRWI_W , F(Long) , 0 , 729 ), // #475 - INST(Fcvtl2_v , SimdFcvtLN , (0b0100111000100001011110, 0, 0) , kRWI_W , F(Long) , 1 , 735 ), // #476 - INST(Fcvtms_v , SimdFcvtSV , (0b0000111000100001101110, 0b0000000000000000000000, 0b0001111000110000000000, 1) , kRWI_W , 0 , 2 , 742 ), // #477 - INST(Fcvtmu_v , SimdFcvtSV , (0b0010111000100001101110, 0b0000000000000000000000, 0b0001111000110001000000, 1) , kRWI_W , 0 , 3 , 749 ), // #478 - INST(Fcvtn_v , SimdFcvtLN , (0b0000111000100001011010, 0, 0) , kRWI_W , F(Narrow) , 2 , 203 ), // #479 - INST(Fcvtn2_v , SimdFcvtLN , (0b0100111000100001011010, 0, 0) , kRWI_X , F(Narrow) , 3 , 210 ), // #480 - INST(Fcvtns_v , SimdFcvtSV , (0b0000111000100001101010, 0b0000000000000000000000, 0b0001111000100000000000, 1) , kRWI_W , 0 , 4 , 756 ), // #481 - INST(Fcvtnu_v , SimdFcvtSV , (0b0010111000100001101010, 0b0000000000000000000000, 0b0001111000100001000000, 1) , kRWI_W , 0 , 5 , 763 ), // #482 - INST(Fcvtps_v , SimdFcvtSV , (0b0000111010100001101010, 0b0000000000000000000000, 0b0001111000101000000000, 1) , kRWI_W , 0 , 6 , 770 ), // #483 - INST(Fcvtpu_v , SimdFcvtSV , (0b0010111010100001101010, 0b0000000000000000000000, 0b0001111000101001000000, 1) , kRWI_W , 0 , 7 , 777 ), // #484 - INST(Fcvtxn_v , SimdFcvtLN , (0b0010111000100001011010, 1, 1) , kRWI_W , F(Narrow) , 4 , 784 ), // #485 - INST(Fcvtxn2_v , SimdFcvtLN , (0b0110111000100001011010, 1, 0) , kRWI_X , F(Narrow) , 5 , 791 ), // #486 - INST(Fcvtzs_v , SimdFcvtSV , (0b0000111010100001101110, 0b0000111100000000111111, 0b0001111000111000000000, 1) , kRWI_W , 0 , 8 , 799 ), // #487 - INST(Fcvtzu_v , SimdFcvtSV , (0b0010111010100001101110, 0b0010111100000000111111, 0b0001111000111001000000, 1) , kRWI_W , 0 , 9 , 806 ), // #488 - INST(Fdiv_v , FSimdVVV , (0b0001111000100000000110, kHF_A, 0b0010111000100000111111, kHF_C) , kRWI_W , 0 , 4 , 813 ), // #489 - INST(Fjcvtzs_v , ISimdVVx , (0b0001111001111110000000, kOp_GpW, kOp_D) , kRWI_W , 0 , 7 , 818 ), // #490 - INST(Fmadd_v , FSimdVVVV , (0b0001111100000000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 0 , 826 ), // #491 - INST(Fmax_v , FSimdVVV , (0b0001111000100000010010, kHF_A, 0b0000111000100000111101, kHF_C) , kRWI_W , 0 , 5 , 832 ), // #492 - INST(Fmaxnm_v , FSimdVVV , (0b0001111000100000011010, kHF_A, 0b0000111000100000110001, kHF_C) , kRWI_W , 0 , 6 , 837 ), // #493 - INST(Fmaxnmp_v , FSimdPair , (0b0111111000110000110010, 0b0010111000100000110001) , kRWI_W , 0 , 1 , 844 ), // #494 - INST(Fmaxnmv_v , FSimdSV , (0b0010111000110000110010) , kRWI_W , 0 , 0 , 852 ), // #495 - INST(Fmaxp_v , FSimdPair , (0b0111111000110000111110, 0b0010111000100000111101) , kRWI_W , 0 , 2 , 860 ), // #496 - INST(Fmaxv_v , FSimdSV , (0b0010111000110000111110) , kRWI_W , 0 , 1 , 866 ), // #497 - INST(Fmin_v , FSimdVVV , (0b0001111000100000010110, kHF_A, 0b0000111010100000111101, kHF_C) , kRWI_W , 0 , 7 , 872 ), // #498 - INST(Fminnm_v , FSimdVVV , (0b0001111000100000011110, kHF_A, 0b0000111010100000110001, kHF_C) , kRWI_W , 0 , 8 , 877 ), // #499 - INST(Fminnmp_v , FSimdPair , (0b0111111010110000110010, 0b0010111010100000110001) , kRWI_W , 0 , 3 , 884 ), // #500 - INST(Fminnmv_v , FSimdSV , (0b0010111010110000110010) , kRWI_W , 0 , 2 , 892 ), // #501 - INST(Fminp_v , FSimdPair , (0b0111111010110000111110, 0b0010111010100000111101) , kRWI_W , 0 , 4 , 900 ), // #502 - INST(Fminv_v , FSimdSV , (0b0010111010110000111110) , kRWI_W , 0 , 3 , 906 ), // #503 - INST(Fmla_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111000100000110011, 0b0000111110000000000100) , kRWI_X , F(VH0_15) , 0 , 912 ), // #504 - INST(Fmlal_v , SimdFmlal , (0b0000111000100000111011, 0b0000111110000000000000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 2 , 917 ), // #505 - INST(Fmlal2_v , SimdFmlal , (0b0010111000100000110011, 0b0010111110000000100000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 3 , 923 ), // #506 - INST(Fmls_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111010100000110011, 0b0000111110000000010100) , kRWI_X , F(VH0_15) , 1 , 930 ), // #507 - INST(Fmlsl_v , SimdFmlal , (0b0000111010100000111011, 0b0000111110000000010000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 4 , 935 ), // #508 - INST(Fmlsl2_v , SimdFmlal , (0b0010111010100000110011, 0b0010111110000000110000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 5 , 941 ), // #509 - INST(Fmov_v , SimdFmov , (_) , kRWI_W , 0 , 0 , 948 ), // #510 - INST(Fmsub_v , FSimdVVVV , (0b0001111100000000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 1 , 953 ), // #511 - INST(Fmul_v , FSimdVVVe , (0b0001111000100000000010, kHF_A, 0b0010111000100000110111, 0b0000111110000000100100) , kRWI_W , F(VH0_15) , 2 , 959 ), // #512 - INST(Fmulx_v , FSimdVVVe , (0b0101111000100000110111, kHF_C, 0b0000111000100000110111, 0b0010111110000000100100) , kRWI_W , F(VH0_15) , 3 , 964 ), // #513 - INST(Fneg_v , FSimdVV , (0b0001111000100001010000, kHF_A, 0b0010111010100000111110, kHF_B) , kRWI_W , 0 , 1 , 970 ), // #514 - INST(Fnmadd_v , FSimdVVVV , (0b0001111100100000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 2 , 975 ), // #515 - INST(Fnmsub_v , FSimdVVVV , (0b0001111100100000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 , 982 ), // #516 - INST(Fnmul_v , FSimdVVV , (0b0001111000100000100010, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 9 , 989 ), // #517 - INST(Frecpe_v , FSimdVV , (0b0101111010100001110110, kHF_B, 0b0000111010100001110110, kHF_B) , kRWI_W , 0 , 2 , 995 ), // #518 - INST(Frecps_v , FSimdVVV , (0b0101111000100000111111, kHF_C, 0b0000111000100000111111, kHF_C) , kRWI_W , 0 , 10 , 1002), // #519 - INST(Frecpx_v , FSimdVV , (0b0101111010100001111110, kHF_B, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 , 1009), // #520 - INST(Frint32x_v , FSimdVV , (0b0001111000101000110000, kHF_N, 0b0010111000100001111010, kHF_N) , kRWI_W , 0 , 4 , 1016), // #521 - INST(Frint32z_v , FSimdVV , (0b0001111000101000010000, kHF_N, 0b0000111000100001111010, kHF_N) , kRWI_W , 0 , 5 , 1025), // #522 - INST(Frint64x_v , FSimdVV , (0b0001111000101001110000, kHF_N, 0b0010111000100001111110, kHF_N) , kRWI_W , 0 , 6 , 1034), // #523 - INST(Frint64z_v , FSimdVV , (0b0001111000101001010000, kHF_N, 0b0000111000100001111110, kHF_N) , kRWI_W , 0 , 7 , 1043), // #524 - INST(Frinta_v , FSimdVV , (0b0001111000100110010000, kHF_A, 0b0010111000100001100010, kHF_B) , kRWI_W , 0 , 8 , 1052), // #525 - INST(Frinti_v , FSimdVV , (0b0001111000100111110000, kHF_A, 0b0010111010100001100110, kHF_B) , kRWI_W , 0 , 9 , 1059), // #526 - INST(Frintm_v , FSimdVV , (0b0001111000100101010000, kHF_A, 0b0000111000100001100110, kHF_B) , kRWI_W , 0 , 10 , 1066), // #527 - INST(Frintn_v , FSimdVV , (0b0001111000100100010000, kHF_A, 0b0000111000100001100010, kHF_B) , kRWI_W , 0 , 11 , 1073), // #528 - INST(Frintp_v , FSimdVV , (0b0001111000100100110000, kHF_A, 0b0000111010100001100010, kHF_B) , kRWI_W , 0 , 12 , 1080), // #529 - INST(Frintx_v , FSimdVV , (0b0001111000100111010000, kHF_A, 0b0010111000100001100110, kHF_B) , kRWI_W , 0 , 13 , 1087), // #530 - INST(Frintz_v , FSimdVV , (0b0001111000100101110000, kHF_A, 0b0000111010100001100110, kHF_B) , kRWI_W , 0 , 14 , 1094), // #531 - INST(Frsqrte_v , FSimdVV , (0b0111111010100001110110, kHF_B, 0b0010111010100001110110, kHF_B) , kRWI_W , 0 , 15 , 1101), // #532 - INST(Frsqrts_v , FSimdVVV , (0b0101111010100000111111, kHF_C, 0b0000111010100000111111, kHF_C) , kRWI_W , 0 , 11 , 1109), // #533 - INST(Fsqrt_v , FSimdVV , (0b0001111000100001110000, kHF_A, 0b0010111010100001111110, kHF_B) , kRWI_W , 0 , 16 , 1117), // #534 - INST(Fsub_v , FSimdVVV , (0b0001111000100000001110, kHF_A, 0b0000111010100000110101, kHF_C) , kRWI_W , 0 , 12 , 1123), // #535 - INST(Ins_v , SimdIns , (_) , kRWI_X , 0 , 0 , 1145), // #536 - INST(Ld1_v , SimdLdNStN , (0b0000110101000000000000, 0b0000110001000000001000, 1, 0) , kRWI_LDn , F(Consecutive) , 0 , 1153), // #537 - INST(Ld1r_v , SimdLdNStN , (0b0000110101000000110000, 0b0000000000000000000000, 1, 1) , kRWI_LDn , F(Consecutive) , 1 , 1157), // #538 - INST(Ld2_v , SimdLdNStN , (0b0000110101100000000000, 0b0000110001000000100000, 2, 0) , kRWI_LDn , F(Consecutive) , 2 , 1162), // #539 - INST(Ld2r_v , SimdLdNStN , (0b0000110101100000110000, 0b0000000000000000000000, 2, 1) , kRWI_LDn , F(Consecutive) , 3 , 1166), // #540 - INST(Ld3_v , SimdLdNStN , (0b0000110101000000001000, 0b0000110001000000010000, 3, 0) , kRWI_LDn , F(Consecutive) , 4 , 1171), // #541 - INST(Ld3r_v , SimdLdNStN , (0b0000110101000000111000, 0b0000000000000000000000, 3, 1) , kRWI_LDn , F(Consecutive) , 5 , 1175), // #542 - INST(Ld4_v , SimdLdNStN , (0b0000110101100000001000, 0b0000110001000000000000, 4, 0) , kRWI_LDn , F(Consecutive) , 6 , 1180), // #543 - INST(Ld4r_v , SimdLdNStN , (0b0000110101100000111000, 0b0000000000000000000000, 4, 1) , kRWI_LDn , F(Consecutive) , 7 , 1184), // #544 - INST(Ldnp_v , SimdLdpStp , (0b0010110001, 0b0000000000) , kRWI_WW , 0 , 0 , 1537), // #545 - INST(Ldp_v , SimdLdpStp , (0b0010110101, 0b0010110011) , kRWI_WW , 0 , 1 , 1542), // #546 - INST(Ldr_v , SimdLdSt , (0b0011110101, 0b00111100010, 0b00111100011, 0b00011100, Inst::kIdLdur_v) , kRWI_W , 0 , 0 , 1552), // #547 - INST(Ldur_v , SimdLdurStur , (0b0011110001000000000000) , kRWI_W , 0 , 0 , 2142), // #548 - INST(Mla_v , ISimdVVVe , (0b0000111000100000100101, kVO_V_BHS, 0b0010111100000000000000, kVO_V_HS) , kRWI_X , F(VH0_15) , 0 , 246 ), // #549 - INST(Mls_v , ISimdVVVe , (0b0010111000100000100101, kVO_V_BHS, 0b0010111100000000010000, kVO_V_HS) , kRWI_X , F(VH0_15) , 1 , 931 ), // #550 - INST(Mov_v , SimdMov , (_) , kRWI_W , 0 , 0 , 949 ), // #551 - INST(Movi_v , SimdMoviMvni , (0b0000111100000000000001, 0) , kRWI_W , 0 , 0 , 2221), // #552 - INST(Mul_v , ISimdVVVe , (0b0000111000100000100111, kVO_V_BHS, 0b0000111100000000100000, kVO_V_HS) , kRWI_W , F(VH0_15) , 2 , 991 ), // #553 - INST(Mvn_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 4 , 2249), // #554 - INST(Mvni_v , SimdMoviMvni , (0b0000111100000000000001, 1) , kRWI_W , 0 , 1 , 2253), // #555 - INST(Neg_v , ISimdVV , (0b0010111000100000101110, kVO_V_Any) , kRWI_W , 0 , 5 , 540 ), // #556 - INST(Not_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 6 , 2276), // #557 - INST(Orn_v , ISimdVVV , (0b0000111011100000000111, kVO_V_B) , kRWI_W , 0 , 9 , 2280), // #558 - INST(Orr_v , SimdBicOrr , (0b0000111010100000000111, 0b0000111100000000000001) , kRWI_W , 0 , 1 , 2284), // #559 - INST(Pmul_v , ISimdVVV , (0b0010111000100000100111, kVO_V_B) , kRWI_W , 0 , 10 , 2320), // #560 - INST(Pmull_v , ISimdVVV , (0b0000111000100000111000, kVO_V_B8D1) , kRWI_W , F(Long) , 11 , 2325), // #561 - INST(Pmull2_v , ISimdVVV , (0b0100111000100000111000, kVO_V_B16D2) , kRWI_W , F(Long) , 12 , 2331), // #562 - INST(Raddhn_v , ISimdVVV , (0b0010111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 13 , 2344), // #563 - INST(Raddhn2_v , ISimdVVV , (0b0110111000100000010000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 , 2351), // #564 - INST(Rax1_v , ISimdVVV , (0b1100111001100000100011, kVO_V_D2) , kRWI_W , 0 , 15 , 2359), // #565 - INST(Rbit_v , ISimdVV , (0b0010111001100000010110, kVO_V_B) , kRWI_W , 0 , 7 , 2364), // #566 - INST(Rev16_v , ISimdVV , (0b0000111000100000000110, kVO_V_B) , kRWI_W , 0 , 8 , 2373), // #567 - INST(Rev32_v , ISimdVV , (0b0010111000100000000010, kVO_V_BH) , kRWI_W , 0 , 9 , 2379), // #568 - INST(Rev64_v , ISimdVV , (0b0000111000100000000010, kVO_V_BHS) , kRWI_W , 0 , 10 , 2385), // #569 - INST(Rshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100011, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 0 , 2960), // #570 - INST(Rshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 1 , 2968), // #571 - INST(Rsubhn_v , ISimdVVV , (0b0010111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 16 , 2400), // #572 - INST(Rsubhn2_v , ISimdVVV , (0b0110111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 17 , 2407), // #573 - INST(Saba_v , ISimdVVV , (0b0000111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 18 , 2415), // #574 - INST(Sabal_v , ISimdVVV , (0b0000111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 19 , 2420), // #575 - INST(Sabal2_v , ISimdVVV , (0b0100111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 20 , 2426), // #576 - INST(Sabd_v , ISimdVVV , (0b0000111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 21 , 2433), // #577 - INST(Sabdl_v , ISimdVVV , (0b0000111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 , 2438), // #578 - INST(Sabdl2_v , ISimdVVV , (0b0100111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 , 2444), // #579 - INST(Sadalp_v , ISimdVV , (0b0000111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 11 , 2451), // #580 - INST(Saddl_v , ISimdVVV , (0b0000111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 24 , 2458), // #581 - INST(Saddl2_v , ISimdVVV , (0b0100111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 25 , 2464), // #582 - INST(Saddlp_v , ISimdVV , (0b0000111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 12 , 2471), // #583 - INST(Saddlv_v , ISimdSV , (0b0000111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 1 , 2478), // #584 - INST(Saddw_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 0 , 2485), // #585 - INST(Saddw2_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 1 , 2491), // #586 - INST(Scvtf_v , SimdFcvtSV , (0b0000111000100001110110, 0b0000111100000000111001, 0b0001111000100010000000, 0) , kRWI_W , 0 , 10 , 2523), // #587 - INST(Sdot_v , SimdDot , (0b0000111010000000100101, 0b0000111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 1 , 4218), // #588 - INST(Sha1c_v , ISimdVVVx , (0b0101111000000000000000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 1 , 2556), // #589 - INST(Sha1h_v , ISimdVVx , (0b0101111000101000000010, kOp_S, kOp_S) , kRWI_W , 0 , 8 , 2562), // #590 - INST(Sha1m_v , ISimdVVVx , (0b0101111000000000001000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 2 , 2568), // #591 - INST(Sha1p_v , ISimdVVVx , (0b0101111000000000000100, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 3 , 2574), // #592 - INST(Sha1su0_v , ISimdVVVx , (0b0101111000000000001100, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 4 , 2580), // #593 - INST(Sha1su1_v , ISimdVVx , (0b0101111000101000000110, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 9 , 2588), // #594 - INST(Sha256h_v , ISimdVVVx , (0b0101111000000000010000, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 5 , 2596), // #595 - INST(Sha256h2_v , ISimdVVVx , (0b0101111000000000010100, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 6 , 2604), // #596 - INST(Sha256su0_v , ISimdVVx , (0b0101111000101000001010, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 10 , 2613), // #597 - INST(Sha256su1_v , ISimdVVVx , (0b0101111000000000011000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 7 , 2623), // #598 - INST(Sha512h_v , ISimdVVVx , (0b1100111001100000100000, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 8 , 2633), // #599 - INST(Sha512h2_v , ISimdVVVx , (0b1100111001100000100001, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 9 , 2641), // #600 - INST(Sha512su0_v , ISimdVVx , (0b1100111011000000100000, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 11 , 2650), // #601 - INST(Sha512su1_v , ISimdVVVx , (0b1100111001100000100010, kOp_V2D, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 10 , 2660), // #602 - INST(Shadd_v , ISimdVVV , (0b0000111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 26 , 2670), // #603 - INST(Shl_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000010101, 0, kVO_V_Any) , kRWI_W , 0 , 2 , 2954), // #604 - INST(Shll_v , SimdShiftES , (0b0010111000100001001110, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 , 3108), // #605 - INST(Shll2_v , SimdShiftES , (0b0110111000100001001110, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 , 3114), // #606 - INST(Shrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100001, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 3 , 2961), // #607 - INST(Shrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 4 , 2969), // #608 - INST(Shsub_v , ISimdVVV , (0b0000111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 27 , 2676), // #609 - INST(Sli_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010101, 0, kVO_V_Any) , kRWI_X , 0 , 5 , 2682), // #610 - INST(Sm3partw1_v , ISimdVVVx , (0b1100111001100000110000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 11 , 2686), // #611 - INST(Sm3partw2_v , ISimdVVVx , (0b1100111001100000110001, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 , 2696), // #612 - INST(Sm3ss1_v , ISimdVVVVx , (0b1100111001000000000000, kOp_V4S, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_W , 0 , 0 , 2706), // #613 - INST(Sm3tt1a_v , SimdSm3tt , (0b1100111001000000100000) , kRWI_X , 0 , 0 , 2713), // #614 - INST(Sm3tt1b_v , SimdSm3tt , (0b1100111001000000100001) , kRWI_X , 0 , 1 , 2721), // #615 - INST(Sm3tt2a_v , SimdSm3tt , (0b1100111001000000100010) , kRWI_X , 0 , 2 , 2729), // #616 - INST(Sm3tt2b_v , SimdSm3tt , (0b1100111001000000100011) , kRWI_X , 0 , 3 , 2737), // #617 - INST(Sm4e_v , ISimdVVx , (0b1100111011000000100001, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 , 2745), // #618 - INST(Sm4ekey_v , ISimdVVVx , (0b1100111001100000110010, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 13 , 2750), // #619 - INST(Smax_v , ISimdVVV , (0b0000111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 28 , 1690), // #620 - INST(Smaxp_v , ISimdVVV , (0b0000111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 29 , 2765), // #621 - INST(Smaxv_v , ISimdSV , (0b0000111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 2 , 2771), // #622 - INST(Smin_v , ISimdVVV , (0b0000111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 30 , 1794), // #623 - INST(Sminp_v , ISimdVVV , (0b0000111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 31 , 2777), // #624 - INST(Sminv_v , ISimdSV , (0b0000111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 3 , 2783), // #625 - INST(Smlal_v , ISimdVVVe , (0b0000111000100000100000, kVO_V_B8H4S2, 0b0000111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 3 , 2789), // #626 - INST(Smlal2_v , ISimdVVVe , (0b0100111000100000100000, kVO_V_B16H8S4, 0b0100111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 4 , 2795), // #627 - INST(Smlsl_v , ISimdVVVe , (0b0000111000100000101000, kVO_V_B8H4S2, 0b0000111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 5 , 2802), // #628 - INST(Smlsl2_v , ISimdVVVe , (0b0100111000100000101000, kVO_V_B16H8S4, 0b0100111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 6 , 2808), // #629 - INST(Smmla_v , ISimdVVVx , (0b0100111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 14 , 4247), // #630 - INST(Smov_v , SimdSmovUmov , (0b0000111000000000001011, kVO_V_BHS, 1) , kRWI_W , 0 , 0 , 2822), // #631 - INST(Smull_v , ISimdVVVe , (0b0000111000100000110000, kVO_V_B8H4S2, 0b0000111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 7 , 2840), // #632 - INST(Smull2_v , ISimdVVVe , (0b0100111000100000110000, kVO_V_B16H8S4, 0b0100111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 8 , 2846), // #633 - INST(Sqabs_v , ISimdVV , (0b0000111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 13 , 2853), // #634 - INST(Sqadd_v , ISimdVVV , (0b0000111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 32 , 4254), // #635 - INST(Sqdmlal_v , ISimdVVVe , (0b0000111000100000100100, kVO_SV_BHS, 0b0000111100000000001100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 9 , 2859), // #636 - INST(Sqdmlal2_v , ISimdVVVe , (0b0100111000100000100100, kVO_V_B16H8S4, 0b0100111100000000001100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 10 , 2867), // #637 - INST(Sqdmlsl_v , ISimdVVVe , (0b0000111000100000101100, kVO_SV_BHS, 0b0000111100000000011100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 11 , 2876), // #638 - INST(Sqdmlsl2_v , ISimdVVVe , (0b0100111000100000101100, kVO_V_B16H8S4, 0b0100111100000000011100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 12 , 2884), // #639 - INST(Sqdmulh_v , ISimdVVVe , (0b0000111000100000101101, kVO_SV_HS, 0b0000111100000000110000, kVO_SV_HS) , kRWI_W , F(VH0_15) , 13 , 2893), // #640 - INST(Sqdmull_v , ISimdVVVe , (0b0000111000100000110100, kVO_SV_BHS, 0b0000111100000000101100, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 14 , 2901), // #641 - INST(Sqdmull2_v , ISimdVVVe , (0b0100111000100000110100, kVO_V_B16H8S4, 0b0100111100000000101100, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 15 , 2909), // #642 - INST(Sqneg_v , ISimdVV , (0b0010111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 14 , 2918), // #643 - INST(Sqrdmlah_v , ISimdVVVe , (0b0010111000000000100001, kVO_SV_HS, 0b0010111100000000110100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 16 , 2924), // #644 - INST(Sqrdmlsh_v , ISimdVVVe , (0b0010111000000000100011, kVO_SV_HS, 0b0010111100000000111100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 17 , 2933), // #645 - INST(Sqrdmulh_v , ISimdVVVe , (0b0010111000100000101101, kVO_SV_HS, 0b0000111100000000110100, kVO_SV_HS) , kRWI_W , F(VH0_15) , 18 , 2942), // #646 - INST(Sqrshl_v , SimdShift , (0b0000111000100000010111, 0b0000000000000000000000, 1, kVO_SV_Any) , kRWI_W , 0 , 6 , 2951), // #647 - INST(Sqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 7 , 2958), // #648 - INST(Sqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 8 , 2966), // #649 - INST(Sqrshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100011, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 9 , 2975), // #650 - INST(Sqrshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 10 , 2984), // #651 - INST(Sqshl_v , SimdShift , (0b0000111000100000010011, 0b0000111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 11 , 2994), // #652 - INST(Sqshlu_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000011001, 0, kVO_SV_Any) , kRWI_W , 0 , 12 , 3000), // #653 - INST(Sqshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 13 , 3007), // #654 - INST(Sqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 , 3014), // #655 - INST(Sqshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100001, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 , 3022), // #656 - INST(Sqshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 , 3030), // #657 - INST(Sqsub_v , ISimdVVV , (0b0000111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 33 , 3039), // #658 - INST(Sqxtn_v , ISimdVV , (0b0000111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 , 3045), // #659 - INST(Sqxtn2_v , ISimdVV , (0b0100111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 , 3051), // #660 - INST(Sqxtun_v , ISimdVV , (0b0010111000100001001010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 17 , 3058), // #661 - INST(Sqxtun2_v , ISimdVV , (0b0110111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 18 , 3065), // #662 - INST(Srhadd_v , ISimdVVV , (0b0000111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 34 , 3073), // #663 - INST(Sri_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010001, 1, kVO_V_Any) , kRWI_W , 0 , 17 , 3080), // #664 - INST(Srshl_v , SimdShift , (0b0000111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 18 , 3084), // #665 - INST(Srshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 19 , 3090), // #666 - INST(Srsra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 20 , 3096), // #667 - INST(Sshl_v , SimdShift , (0b0000111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 21 , 3102), // #668 - INST(Sshll_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 , 3107), // #669 - INST(Sshll2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 , 3113), // #670 - INST(Sshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 24 , 3120), // #671 - INST(Ssra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 25 , 3125), // #672 - INST(Ssubl_v , ISimdVVV , (0b0000111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 35 , 3130), // #673 - INST(Ssubl2_v , ISimdVVV , (0b0100111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 36 , 3136), // #674 - INST(Ssubw_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 2 , 3143), // #675 - INST(Ssubw2_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B16H8S4) , kRWI_X , 0 , 3 , 3149), // #676 - INST(St1_v , SimdLdNStN , (0b0000110100000000000000, 0b0000110000000000001000, 1, 0) , kRWI_STn , F(Consecutive) , 8 , 3156), // #677 - INST(St2_v , SimdLdNStN , (0b0000110100100000000000, 0b0000110000000000100000, 2, 0) , kRWI_STn , F(Consecutive) , 9 , 3160), // #678 - INST(St3_v , SimdLdNStN , (0b0000110100000000001000, 0b0000110000000000010000, 3, 0) , kRWI_STn , F(Consecutive) , 10 , 3169), // #679 - INST(St4_v , SimdLdNStN , (0b0000110100100000001000, 0b0000110000000000000000, 4, 0) , kRWI_STn , F(Consecutive) , 11 , 3173), // #680 - INST(Stnp_v , SimdLdpStp , (0b0010110000, 0b0000000000) , kRWI_RRW , 0 , 2 , 3383), // #681 - INST(Stp_v , SimdLdpStp , (0b0010110100, 0b0010110010) , kRWI_RRW , 0 , 3 , 3388), // #682 - INST(Str_v , SimdLdSt , (0b0011110100, 0b00111100000, 0b00111100001, 0b00000000, Inst::kIdStur_v) , kRWI_RW , 0 , 1 , 3392), // #683 - INST(Stur_v , SimdLdurStur , (0b0011110000000000000000) , kRWI_RW , 0 , 1 , 3662), // #684 - INST(Sub_v , ISimdVVV , (0b0010111000100000100001, kVO_V_Any) , kRWI_W , 0 , 37 , 985 ), // #685 - INST(Subhn_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 38 , 2401), // #686 - INST(Subhn2_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 39 , 2408), // #687 - INST(Sudot_v , SimdDot , (0b0000000000000000000000, 0b0000111100000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 2 , 3739), // #688 - INST(Suqadd_v , ISimdVV , (0b0000111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 19 , 3745), // #689 - INST(Sxtl_v , SimdSxtlUxtl , (0b0000111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 , 3834), // #690 - INST(Sxtl2_v , SimdSxtlUxtl , (0b0100111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 , 3839), // #691 - INST(Tbl_v , SimdTblTbx , (0b0000111000000000000000) , kRWI_W , 0 , 0 , 3854), // #692 - INST(Tbx_v , SimdTblTbx , (0b0000111000000000000100) , kRWI_W , 0 , 1 , 3863), // #693 - INST(Trn1_v , ISimdVVV , (0b0000111000000000001010, kVO_V_BHS_D2) , kRWI_W , 0 , 40 , 3876), // #694 - INST(Trn2_v , ISimdVVV , (0b0000111000000000011010, kVO_V_BHS_D2) , kRWI_W , 0 , 41 , 3881), // #695 - INST(Uaba_v , ISimdVVV , (0b0010111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 42 , 3886), // #696 - INST(Uabal_v , ISimdVVV , (0b0010111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 43 , 3891), // #697 - INST(Uabal2_v , ISimdVVV , (0b0110111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 44 , 3897), // #698 - INST(Uabd_v , ISimdVVV , (0b0010111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 45 , 3904), // #699 - INST(Uabdl_v , ISimdVVV , (0b0010111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 46 , 3909), // #700 - INST(Uabdl2_v , ISimdVVV , (0b0110111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 47 , 3915), // #701 - INST(Uadalp_v , ISimdVV , (0b0010111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 20 , 3922), // #702 - INST(Uaddl_v , ISimdVVV , (0b0010111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 48 , 3929), // #703 - INST(Uaddl2_v , ISimdVVV , (0b0110111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 49 , 3935), // #704 - INST(Uaddlp_v , ISimdVV , (0b0010111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 21 , 3942), // #705 - INST(Uaddlv_v , ISimdSV , (0b0010111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 4 , 3949), // #706 - INST(Uaddw_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 4 , 3956), // #707 - INST(Uaddw2_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 5 , 3962), // #708 - INST(Ucvtf_v , SimdFcvtSV , (0b0010111000100001110110, 0b0010111100000000111001, 0b0001111000100011000000, 0) , kRWI_W , 0 , 11 , 3985), // #709 - INST(Udot_v , SimdDot , (0b0010111010000000100101, 0b0010111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 3 , 3740), // #710 - INST(Uhadd_v , ISimdVVV , (0b0010111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 50 , 4000), // #711 - INST(Uhsub_v , ISimdVVV , (0b0010111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 51 , 4006), // #712 - INST(Umax_v , ISimdVVV , (0b0010111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 52 , 1936), // #713 - INST(Umaxp_v , ISimdVVV , (0b0010111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 53 , 4019), // #714 - INST(Umaxv_v , ISimdSV , (0b0010111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 5 , 4025), // #715 - INST(Umin_v , ISimdVVV , (0b0010111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 54 , 2040), // #716 - INST(Uminp_v , ISimdVVV , (0b0010111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 55 , 4031), // #717 - INST(Uminv_v , ISimdSV , (0b0010111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 6 , 4037), // #718 - INST(Umlal_v , ISimdVVVe , (0b0010111000100000100000, kVO_V_B8H4S2, 0b0010111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 19 , 4043), // #719 - INST(Umlal2_v , ISimdVVVe , (0b0110111000100000100000, kVO_V_B16H8S4, 0b0010111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 20 , 4049), // #720 - INST(Umlsl_v , ISimdVVVe , (0b0010111000100000101000, kVO_V_B8H4S2, 0b0010111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 21 , 4056), // #721 - INST(Umlsl2_v , ISimdVVVe , (0b0110111000100000101000, kVO_V_B16H8S4, 0b0110111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 22 , 4062), // #722 - INST(Ummla_v , ISimdVVVx , (0b0110111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 15 , 4069), // #723 - INST(Umov_v , SimdSmovUmov , (0b0000111000000000001111, kVO_V_Any, 0) , kRWI_W , 0 , 1 , 4082), // #724 - INST(Umull_v , ISimdVVVe , (0b0010111000100000110000, kVO_V_B8H4S2, 0b0010111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 23 , 4100), // #725 - INST(Umull2_v , ISimdVVVe , (0b0110111000100000110000, kVO_V_B16H8S4, 0b0110111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 24 , 4106), // #726 - INST(Uqadd_v , ISimdVVV , (0b0010111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 56 , 3746), // #727 - INST(Uqrshl_v , SimdShift , (0b0010111000100000010111, 0b0000000000000000000000, 0, kVO_SV_Any) , kRWI_W , 0 , 26 , 4113), // #728 - INST(Uqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 27 , 4120), // #729 - INST(Uqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 , 4128), // #730 - INST(Uqshl_v , SimdShift , (0b0010111000100000010011, 0b0010111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 29 , 4137), // #731 - INST(Uqshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 30 , 4143), // #732 - INST(Uqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 31 , 4150), // #733 - INST(Uqsub_v , ISimdVVV , (0b0010111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 57 , 4158), // #734 - INST(Uqxtn_v , ISimdVV , (0b0010111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 22 , 4164), // #735 - INST(Uqxtn2_v , ISimdVV , (0b0110111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 23 , 4170), // #736 - INST(Urecpe_v , ISimdVV , (0b0000111010100001110010, kVO_V_S) , kRWI_W , 0 , 24 , 4177), // #737 - INST(Urhadd_v , ISimdVVV , (0b0010111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 58 , 4184), // #738 - INST(Urshl_v , SimdShift , (0b0010111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 32 , 4191), // #739 - INST(Urshr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 33 , 4197), // #740 - INST(Ursqrte_v , ISimdVV , (0b0010111010100001110010, kVO_V_S) , kRWI_W , 0 , 25 , 4203), // #741 - INST(Ursra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 34 , 4211), // #742 - INST(Usdot_v , SimdDot , (0b0000111010000000100111, 0b0000111110000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 4 , 4217), // #743 - INST(Ushl_v , SimdShift , (0b0010111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 35 , 4223), // #744 - INST(Ushll_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 36 , 4228), // #745 - INST(Ushll2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 37 , 4234), // #746 - INST(Ushr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 38 , 4241), // #747 - INST(Usmmla_v , ISimdVVVx , (0b0100111010000000101011, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 16 , 4246), // #748 - INST(Usqadd_v , ISimdVV , (0b0010111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 26 , 4253), // #749 - INST(Usra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 39 , 4260), // #750 - INST(Usubl_v , ISimdVVV , (0b0010111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 59 , 4265), // #751 - INST(Usubl2_v , ISimdVVV , (0b0110111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 60 , 4271), // #752 - INST(Usubw_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 6 , 4278), // #753 - INST(Usubw2_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B16H8S4) , kRWI_W , 0 , 7 , 4284), // #754 - INST(Uxtl_v , SimdSxtlUxtl , (0b0010111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 2 , 4301), // #755 - INST(Uxtl2_v , SimdSxtlUxtl , (0b0110111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 3 , 4306), // #756 - INST(Uzp1_v , ISimdVVV , (0b0000111000000000000110, kVO_V_BHS_D2) , kRWI_W , 0 , 61 , 4312), // #757 - INST(Uzp2_v , ISimdVVV , (0b0000111000000000010110, kVO_V_BHS_D2) , kRWI_W , 0 , 62 , 4317), // #758 - INST(Xar_v , ISimdVVVI , (0b1100111001100000100011, kVO_V_D2, 6, 10, 0) , kRWI_W , 0 , 1 , 4337), // #759 - INST(Xtn_v , ISimdVV , (0b0000111000100001001010, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 27 , 3047), // #760 - INST(Xtn2_v , ISimdVV , (0b0100111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 , 3053), // #761 - INST(Zip1_v , ISimdVVV , (0b0000111000000000001110, kVO_V_BHS_D2) , kRWI_W , 0 , 63 , 4367), // #762 - INST(Zip2_v , ISimdVVV , (0b0000111000000000011110, kVO_V_BHS_D2) , kRWI_W , 0 , 64 , 4372) // #763 + INST(None , None , (_) , 0 , 0 , 0 ), // #0 + INST(Adc , BaseRRR , (0b0001101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 0 ), // #1 + INST(Adcs , BaseRRR , (0b0011101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 1 ), // #2 + INST(Add , BaseAddSub , (0b0001011000, 0b0001011001, 0b0010001) , kRWI_W , 0 , 0 ), // #3 + INST(Addg , BaseRRII , (0b1001000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10) , kRWI_W , 0 , 0 ), // #4 + INST(Adds , BaseAddSub , (0b0101011000, 0b0101011001, 0b0110001) , kRWI_W , 0 , 1 ), // #5 + INST(Adr , BaseAdr , (0b0001000000000000000000, OffsetType::kAArch64_ADR) , kRWI_W , 0 , 0 ), // #6 + INST(Adrp , BaseAdr , (0b1001000000000000000000, OffsetType::kAArch64_ADRP) , kRWI_W , 0 , 1 ), // #7 + INST(And , BaseLogical , (0b0001010000, 0b00100100, 0) , kRWI_W , 0 , 0 ), // #8 + INST(Ands , BaseLogical , (0b1101010000, 0b11100100, 0) , kRWI_W , 0 , 1 ), // #9 + INST(Asr , BaseShift , (0b0001101011000000001010, 0b0001001100000000011111, 0) , kRWI_W , 0 , 0 ), // #10 + INST(Asrv , BaseShift , (0b0001101011000000001010, 0b0000000000000000000000, 0) , kRWI_W , 0 , 1 ), // #11 + INST(At , BaseAtDcIcTlbi , (0b00011111110000, 0b00001111000000, true) , kRWI_RX , 0 , 0 ), // #12 + INST(Autda , BaseRR , (0b11011010110000010001100000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 0 ), // #13 + INST(Autdza , BaseR , (0b11011010110000010011101111100000, kX, kZR, 0) , kRWI_X , 0 , 0 ), // #14 + INST(Autdb , BaseRR , (0b11011010110000010001110000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 1 ), // #15 + INST(Autdzb , BaseR , (0b11011010110000010011111111100000, kX, kZR, 0) , kRWI_X , 0 , 1 ), // #16 + INST(Autia , BaseRR , (0b11011010110000010001000000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 2 ), // #17 + INST(Autia1716 , BaseOp , (0b11010101000000110010000110011111) , 0 , 0 , 0 ), // #18 + INST(Autiasp , BaseOp , (0b11010101000000110010001110111111) , 0 , 0 , 1 ), // #19 + INST(Autiaz , BaseOp , (0b11010101000000110010001110011111) , 0 , 0 , 2 ), // #20 + INST(Autib , BaseRR , (0b11011010110000010001010000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 3 ), // #21 + INST(Autib1716 , BaseOp , (0b11010101000000110010000111011111) , 0 , 0 , 3 ), // #22 + INST(Autibsp , BaseOp , (0b11010101000000110010001111111111) , 0 , 0 , 4 ), // #23 + INST(Autibz , BaseOp , (0b11010101000000110010001111011111) , 0 , 0 , 5 ), // #24 + INST(Autiza , BaseR , (0b11011010110000010011001111100000, kX, kZR, 0) , kRWI_X , 0 , 2 ), // #25 + INST(Autizb , BaseR , (0b11011010110000010011011111100000, kX, kZR, 0) , kRWI_X , 0 , 3 ), // #26 + INST(Axflag , BaseOp , (0b11010101000000000100000001011111) , 0 , 0 , 6 ), // #27 + INST(B , BaseBranchRel , (0b00010100000000000000000000000000) , 0 , F(Cond) , 0 ), // #28 + INST(Bfc , BaseBfc , (0b00110011000000000000001111100000) , kRWI_X , 0 , 0 ), // #29 + INST(Bfi , BaseBfi , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 ), // #30 + INST(Bfm , BaseBfm , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 ), // #31 + INST(Bfxil , BaseBfx , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 ), // #32 + INST(Bic , BaseLogical , (0b0001010001, 0b00100100, 1) , kRWI_W , 0 , 2 ), // #33 + INST(Bics , BaseLogical , (0b1101010001, 0b11100100, 1) , kRWI_W , 0 , 3 ), // #34 + INST(Bl , BaseBranchRel , (0b10010100000000000000000000000000) , 0 , 0 , 1 ), // #35 + INST(Blr , BaseBranchReg , (0b11010110001111110000000000000000) , kRWI_R , 0 , 0 ), // #36 + INST(Br , BaseBranchReg , (0b11010110000111110000000000000000) , kRWI_R , 0 , 1 ), // #37 + INST(Brk , BaseOpImm , (0b11010100001000000000000000000000, 16, 5) , 0 , 0 , 0 ), // #38 + INST(Cas , BaseAtomicOp , (0b1000100010100000011111, kWX, 30, 0) , kRWI_XRX , 0 , 0 ), // #39 + INST(Casa , BaseAtomicOp , (0b1000100011100000011111, kWX, 30, 1) , kRWI_XRX , 0 , 1 ), // #40 + INST(Casab , BaseAtomicOp , (0b0000100011100000011111, kW , 0 , 1) , kRWI_XRX , 0 , 2 ), // #41 + INST(Casah , BaseAtomicOp , (0b0100100011100000011111, kW , 0 , 1) , kRWI_XRX , 0 , 3 ), // #42 + INST(Casal , BaseAtomicOp , (0b1000100011100000111111, kWX, 30, 1) , kRWI_XRX , 0 , 4 ), // #43 + INST(Casalb , BaseAtomicOp , (0b0000100011100000111111, kW , 0 , 1) , kRWI_XRX , 0 , 5 ), // #44 + INST(Casalh , BaseAtomicOp , (0b0100100011100000111111, kW , 0 , 1) , kRWI_XRX , 0 , 6 ), // #45 + INST(Casb , BaseAtomicOp , (0b0000100010100000011111, kW , 0 , 0) , kRWI_XRX , 0 , 7 ), // #46 + INST(Cash , BaseAtomicOp , (0b0100100010100000011111, kW , 0 , 0) , kRWI_XRX , 0 , 8 ), // #47 + INST(Casl , BaseAtomicOp , (0b1000100010100000111111, kWX, 30, 0) , kRWI_XRX , 0 , 9 ), // #48 + INST(Caslb , BaseAtomicOp , (0b0000100010100000111111, kW , 0 , 0) , kRWI_XRX , 0 , 10 ), // #49 + INST(Caslh , BaseAtomicOp , (0b0100100010100000111111, kW , 0 , 0) , kRWI_XRX , 0 , 11 ), // #50 + INST(Casp , BaseAtomicCasp , (0b0000100000100000011111, kWX, 30) , kRWI_XXRRX, 0 , 0 ), // #51 + INST(Caspa , BaseAtomicCasp , (0b0000100001100000011111, kWX, 30) , kRWI_XXRRX, 0 , 1 ), // #52 + INST(Caspal , BaseAtomicCasp , (0b0000100001100000111111, kWX, 30) , kRWI_XXRRX, 0 , 2 ), // #53 + INST(Caspl , BaseAtomicCasp , (0b0000100000100000111111, kWX, 30) , kRWI_XXRRX, 0 , 3 ), // #54 + INST(Cbnz , BaseBranchCmp , (0b00110101000000000000000000000000) , kRWI_R , 0 , 0 ), // #55 + INST(Cbz , BaseBranchCmp , (0b00110100000000000000000000000000) , kRWI_R , 0 , 1 ), // #56 + INST(Ccmn , BaseCCmp , (0b00111010010000000000000000000000) , kRWI_R , 0 , 0 ), // #57 + INST(Ccmp , BaseCCmp , (0b01111010010000000000000000000000) , kRWI_R , 0 , 1 ), // #58 + INST(Cfinv , BaseOp , (0b11010101000000000100000000011111) , 0 , 0 , 7 ), // #59 + INST(Cinc , BaseCInc , (0b00011010100000000000010000000000) , kRWI_W , 0 , 0 ), // #60 + INST(Cinv , BaseCInc , (0b01011010100000000000000000000000) , kRWI_W , 0 , 1 ), // #61 + INST(Clrex , BaseOpImm , (0b11010101000000110011000001011111, 4, 8) , 0 , 0 , 1 ), // #62 + INST(Cls , BaseRR , (0b01011010110000000001010000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 4 ), // #63 + INST(Clz , BaseRR , (0b01011010110000000001000000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 5 ), // #64 + INST(Cmn , BaseCmpCmn , (0b0101011000, 0b0101011001, 0b0110001) , kRWI_R , 0 , 0 ), // #65 + INST(Cmp , BaseCmpCmn , (0b1101011000, 0b1101011001, 0b1110001) , kRWI_R , 0 , 1 ), // #66 + INST(Cmpp , BaseRR , (0b10111010110000000000000000011111, kX, kSP, 5, kX, kSP, 16, true) , kRWI_R , 0 , 6 ), // #67 + INST(Cneg , BaseCInc , (0b01011010100000000000010000000000) , kRWI_W , 0 , 2 ), // #68 + INST(Crc32b , BaseRRR , (0b0001101011000000010000, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 2 ), // #69 + INST(Crc32cb , BaseRRR , (0b0001101011000000010100, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 3 ), // #70 + INST(Crc32ch , BaseRRR , (0b0001101011000000010101, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 4 ), // #71 + INST(Crc32cw , BaseRRR , (0b0001101011000000010110, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 5 ), // #72 + INST(Crc32cx , BaseRRR , (0b1001101011000000010111, kW, kZR, kW, kZR, kX, kZR, false) , kRWI_W , 0 , 6 ), // #73 + INST(Crc32h , BaseRRR , (0b0001101011000000010001, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 7 ), // #74 + INST(Crc32w , BaseRRR , (0b0001101011000000010010, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 8 ), // #75 + INST(Crc32x , BaseRRR , (0b1001101011000000010011, kW, kZR, kW, kZR, kX, kZR, false) , kRWI_W , 0 , 9 ), // #76 + INST(Csdb , BaseOp , (0b11010101000000110010001010011111) , 0 , 0 , 8 ), // #77 + INST(Csel , BaseCSel , (0b00011010100000000000000000000000) , kRWI_W , 0 , 0 ), // #78 + INST(Cset , BaseCSet , (0b00011010100111110000011111100000) , kRWI_W , 0 , 0 ), // #79 + INST(Csetm , BaseCSet , (0b01011010100111110000001111100000) , kRWI_W , 0 , 1 ), // #80 + INST(Csinc , BaseCSel , (0b00011010100000000000010000000000) , kRWI_W , 0 , 1 ), // #81 + INST(Csinv , BaseCSel , (0b01011010100000000000000000000000) , kRWI_W , 0 , 2 ), // #82 + INST(Csneg , BaseCSel , (0b01011010100000000000010000000000) , kRWI_W , 0 , 3 ), // #83 + INST(Dc , BaseAtDcIcTlbi , (0b00011110000000, 0b00001110000000, true) , kRWI_RX , 0 , 1 ), // #84 + INST(Dcps1 , BaseOpImm , (0b11010100101000000000000000000001, 16, 5) , 0 , 0 , 2 ), // #85 + INST(Dcps2 , BaseOpImm , (0b11010100101000000000000000000010, 16, 5) , 0 , 0 , 3 ), // #86 + INST(Dcps3 , BaseOpImm , (0b11010100101000000000000000000011, 16, 5) , 0 , 0 , 4 ), // #87 + INST(Dgh , BaseOp , (0b11010101000000110010000011011111) , 0 , 0 , 9 ), // #88 + INST(Dmb , BaseOpImm , (0b11010101000000110011000010111111, 4, 8) , 0 , 0 , 5 ), // #89 + INST(Drps , BaseOp , (0b11010110101111110000001111100000) , 0 , 0 , 10 ), // #90 + INST(Dsb , BaseOpImm , (0b11010101000000110011000010011111, 4, 8) , 0 , 0 , 6 ), // #91 + INST(Eon , BaseLogical , (0b1001010001, 0b10100100, 1) , kRWI_W , 0 , 4 ), // #92 + INST(Eor , BaseLogical , (0b1001010000, 0b10100100, 0) , kRWI_W , 0 , 5 ), // #93 + INST(Esb , BaseOp , (0b11010101000000110010001000011111) , 0 , 0 , 11 ), // #94 + INST(Extr , BaseExtract , (0b00010011100000000000000000000000) , kRWI_W , 0 , 0 ), // #95 + INST(Eret , BaseOp , (0b11010110100111110000001111100000) , 0 , 0 , 12 ), // #96 + INST(Gmi , BaseRRR , (0b1001101011000000000101, kX , kZR, kX , kSP, kX , kZR, true) , kRWI_W , 0 , 10 ), // #97 + INST(Hint , BaseOpImm , (0b11010101000000110010000000011111, 7, 5) , 0 , 0 , 7 ), // #98 + INST(Hlt , BaseOpImm , (0b11010100010000000000000000000000, 16, 5) , 0 , 0 , 8 ), // #99 + INST(Hvc , BaseOpImm , (0b11010100000000000000000000000010, 16, 5) , 0 , 0 , 9 ), // #100 + INST(Ic , BaseAtDcIcTlbi , (0b00011110000000, 0b00001110000000, false) , kRWI_RX , 0 , 2 ), // #101 + INST(Isb , BaseOpImm , (0b11010101000000110011000011011111, 4, 8) , 0 , 0 , 10 ), // #102 + INST(Ldadd , BaseAtomicOp , (0b1011100000100000000000, kWX, 30, 0) , kRWI_WRX , 0 , 12 ), // #103 + INST(Ldadda , BaseAtomicOp , (0b1011100010100000000000, kWX, 30, 1) , kRWI_WRX , 0 , 13 ), // #104 + INST(Ldaddab , BaseAtomicOp , (0b0011100010100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 14 ), // #105 + INST(Ldaddah , BaseAtomicOp , (0b0111100010100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 15 ), // #106 + INST(Ldaddal , BaseAtomicOp , (0b1011100011100000000000, kWX, 30, 1) , kRWI_WRX , 0 , 16 ), // #107 + INST(Ldaddalb , BaseAtomicOp , (0b0011100011100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 17 ), // #108 + INST(Ldaddalh , BaseAtomicOp , (0b0111100011100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 18 ), // #109 + INST(Ldaddb , BaseAtomicOp , (0b0011100000100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 19 ), // #110 + INST(Ldaddh , BaseAtomicOp , (0b0111100000100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 20 ), // #111 + INST(Ldaddl , BaseAtomicOp , (0b1011100001100000000000, kWX, 30, 0) , kRWI_WRX , 0 , 21 ), // #112 + INST(Ldaddlb , BaseAtomicOp , (0b0011100001100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 22 ), // #113 + INST(Ldaddlh , BaseAtomicOp , (0b0111100001100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 23 ), // #114 + INST(Ldar , BaseRM_NoImm , (0b1000100011011111111111, kWX, kZR, 30) , kRWI_W , 0 , 0 ), // #115 + INST(Ldarb , BaseRM_NoImm , (0b0000100011011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 1 ), // #116 + INST(Ldarh , BaseRM_NoImm , (0b0100100011011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 2 ), // #117 + INST(Ldaxp , BaseLdxp , (0b1000100001111111100000, kWX, 30) , kRWI_WW , 0 , 0 ), // #118 + INST(Ldaxr , BaseRM_NoImm , (0b1000100001011111111111, kWX, kZR, 30) , kRWI_W , 0 , 3 ), // #119 + INST(Ldaxrb , BaseRM_NoImm , (0b0000100001011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 4 ), // #120 + INST(Ldaxrh , BaseRM_NoImm , (0b0100100001011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 5 ), // #121 + INST(Ldclr , BaseAtomicOp , (0b1011100000100000000100, kWX, 30, 0) , kRWI_WRX , 0 , 24 ), // #122 + INST(Ldclra , BaseAtomicOp , (0b1011100010100000000100, kWX, 30, 1) , kRWI_WRX , 0 , 25 ), // #123 + INST(Ldclrab , BaseAtomicOp , (0b0011100010100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 26 ), // #124 + INST(Ldclrah , BaseAtomicOp , (0b0111100010100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 27 ), // #125 + INST(Ldclral , BaseAtomicOp , (0b1011100011100000000100, kWX, 30, 1) , kRWI_WRX , 0 , 28 ), // #126 + INST(Ldclralb , BaseAtomicOp , (0b0011100011100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 29 ), // #127 + INST(Ldclralh , BaseAtomicOp , (0b0111100011100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 30 ), // #128 + INST(Ldclrb , BaseAtomicOp , (0b0011100000100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 31 ), // #129 + INST(Ldclrh , BaseAtomicOp , (0b0111100000100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 32 ), // #130 + INST(Ldclrl , BaseAtomicOp , (0b1011100001100000000100, kWX, 30, 0) , kRWI_WRX , 0 , 33 ), // #131 + INST(Ldclrlb , BaseAtomicOp , (0b0011100001100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 34 ), // #132 + INST(Ldclrlh , BaseAtomicOp , (0b0111100001100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 35 ), // #133 + INST(Ldeor , BaseAtomicOp , (0b1011100000100000001000, kWX, 30, 0) , kRWI_WRX , 0 , 36 ), // #134 + INST(Ldeora , BaseAtomicOp , (0b1011100010100000001000, kWX, 30, 1) , kRWI_WRX , 0 , 37 ), // #135 + INST(Ldeorab , BaseAtomicOp , (0b0011100010100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 38 ), // #136 + INST(Ldeorah , BaseAtomicOp , (0b0111100010100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 39 ), // #137 + INST(Ldeoral , BaseAtomicOp , (0b1011100011100000001000, kWX, 30, 1) , kRWI_WRX , 0 , 40 ), // #138 + INST(Ldeoralb , BaseAtomicOp , (0b0011100011100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 41 ), // #139 + INST(Ldeoralh , BaseAtomicOp , (0b0111100011100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 42 ), // #140 + INST(Ldeorb , BaseAtomicOp , (0b0011100000100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 43 ), // #141 + INST(Ldeorh , BaseAtomicOp , (0b0111100000100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 44 ), // #142 + INST(Ldeorl , BaseAtomicOp , (0b1011100001100000001000, kWX, 30, 0) , kRWI_WRX , 0 , 45 ), // #143 + INST(Ldeorlb , BaseAtomicOp , (0b0011100001100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 46 ), // #144 + INST(Ldeorlh , BaseAtomicOp , (0b0111100001100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 47 ), // #145 + INST(Ldg , BaseRM_SImm9 , (0b1101100101100000000000, 0b0000000000000000000000, kX , kZR, 0, 4) , kRWI_W , 0 , 0 ), // #146 + INST(Ldgm , BaseRM_NoImm , (0b1101100111100000000000, kX , kZR, 0 ) , kRWI_W , 0 , 6 ), // #147 + INST(Ldlar , BaseRM_NoImm , (0b1000100011011111011111, kWX, kZR, 30) , kRWI_W , 0 , 7 ), // #148 + INST(Ldlarb , BaseRM_NoImm , (0b0000100011011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 8 ), // #149 + INST(Ldlarh , BaseRM_NoImm , (0b0100100011011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 9 ), // #150 + INST(Ldnp , BaseLdpStp , (0b0010100001, 0 , kWX, 31, 2) , kRWI_WW , 0 , 0 ), // #151 + INST(Ldp , BaseLdpStp , (0b0010100101, 0b0010100011, kWX, 31, 2) , kRWI_WW , 0 , 1 ), // #152 + INST(Ldpsw , BaseLdpStp , (0b0110100101, 0b0110100011, kX , 0 , 2) , kRWI_WW , 0 , 2 ), // #153 + INST(Ldr , BaseLdSt , (0b1011100101, 0b10111000010, 0b10111000011, 0b00011000, kWX, 30, 2, Inst::kIdLdur) , kRWI_W , 0 , 0 ), // #154 + INST(Ldraa , BaseRM_SImm10 , (0b1111100000100000000001, kX , kZR, 0, 3) , kRWI_W , 0 , 0 ), // #155 + INST(Ldrab , BaseRM_SImm10 , (0b1111100010100000000001, kX , kZR, 0, 3) , kRWI_W , 0 , 1 ), // #156 + INST(Ldrb , BaseLdSt , (0b0011100101, 0b00111000010, 0b00111000011, 0 , kW , 0 , 0, Inst::kIdLdurb) , kRWI_W , 0 , 1 ), // #157 + INST(Ldrh , BaseLdSt , (0b0111100101, 0b01111000010, 0b01111000011, 0 , kW , 0 , 1, Inst::kIdLdurh) , kRWI_W , 0 , 2 ), // #158 + INST(Ldrsb , BaseLdSt , (0b0011100111, 0b00111000100, 0b00111000111, 0 , kWX, 22, 0, Inst::kIdLdursb) , kRWI_W , 0 , 3 ), // #159 + INST(Ldrsh , BaseLdSt , (0b0111100111, 0b01111000100, 0b01111000111, 0 , kWX, 22, 1, Inst::kIdLdursh) , kRWI_W , 0 , 4 ), // #160 + INST(Ldrsw , BaseLdSt , (0b1011100110, 0b10111000100, 0b10111000101, 0b10011000, kX , 0 , 2, Inst::kIdLdursw) , kRWI_W , 0 , 5 ), // #161 + INST(Ldset , BaseAtomicOp , (0b1011100000100000001100, kWX, 30, 0) , kRWI_WRX , 0 , 48 ), // #162 + INST(Ldseta , BaseAtomicOp , (0b1011100010100000001100, kWX, 30, 1) , kRWI_WRX , 0 , 49 ), // #163 + INST(Ldsetab , BaseAtomicOp , (0b0011100010100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 50 ), // #164 + INST(Ldsetah , BaseAtomicOp , (0b0111100010100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 51 ), // #165 + INST(Ldsetal , BaseAtomicOp , (0b1011100011100000001100, kWX, 30, 1) , kRWI_WRX , 0 , 52 ), // #166 + INST(Ldsetalb , BaseAtomicOp , (0b0011100011100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 53 ), // #167 + INST(Ldsetalh , BaseAtomicOp , (0b0111100011100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 54 ), // #168 + INST(Ldsetb , BaseAtomicOp , (0b0011100000100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 55 ), // #169 + INST(Ldseth , BaseAtomicOp , (0b0111100000100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 56 ), // #170 + INST(Ldsetl , BaseAtomicOp , (0b1011100001100000001100, kWX, 30, 0) , kRWI_WRX , 0 , 57 ), // #171 + INST(Ldsetlb , BaseAtomicOp , (0b0011100001100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 58 ), // #172 + INST(Ldsetlh , BaseAtomicOp , (0b0111100001100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 59 ), // #173 + INST(Ldsmax , BaseAtomicOp , (0b1011100000100000010000, kWX, 30, 0) , kRWI_WRX , 0 , 60 ), // #174 + INST(Ldsmaxa , BaseAtomicOp , (0b1011100010100000010000, kWX, 30, 1) , kRWI_WRX , 0 , 61 ), // #175 + INST(Ldsmaxab , BaseAtomicOp , (0b0011100010100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 62 ), // #176 + INST(Ldsmaxah , BaseAtomicOp , (0b0111100010100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 63 ), // #177 + INST(Ldsmaxal , BaseAtomicOp , (0b1011100011100000010000, kWX, 30, 1) , kRWI_WRX , 0 , 64 ), // #178 + INST(Ldsmaxalb , BaseAtomicOp , (0b0011100011100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 65 ), // #179 + INST(Ldsmaxalh , BaseAtomicOp , (0b0111100011100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 66 ), // #180 + INST(Ldsmaxb , BaseAtomicOp , (0b0011100000100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 67 ), // #181 + INST(Ldsmaxh , BaseAtomicOp , (0b0111100000100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 68 ), // #182 + INST(Ldsmaxl , BaseAtomicOp , (0b1011100001100000010000, kWX, 30, 0) , kRWI_WRX , 0 , 69 ), // #183 + INST(Ldsmaxlb , BaseAtomicOp , (0b0011100001100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 70 ), // #184 + INST(Ldsmaxlh , BaseAtomicOp , (0b0111100001100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 71 ), // #185 + INST(Ldsmin , BaseAtomicOp , (0b1011100000100000010100, kWX, 30, 0) , kRWI_WRX , 0 , 72 ), // #186 + INST(Ldsmina , BaseAtomicOp , (0b1011100010100000010100, kWX, 30, 1) , kRWI_WRX , 0 , 73 ), // #187 + INST(Ldsminab , BaseAtomicOp , (0b0011100010100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 74 ), // #188 + INST(Ldsminah , BaseAtomicOp , (0b0111100010100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 75 ), // #189 + INST(Ldsminal , BaseAtomicOp , (0b1011100011100000010100, kWX, 30, 1) , kRWI_WRX , 0 , 76 ), // #190 + INST(Ldsminalb , BaseAtomicOp , (0b0011100011100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 77 ), // #191 + INST(Ldsminalh , BaseAtomicOp , (0b0111100011100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 78 ), // #192 + INST(Ldsminb , BaseAtomicOp , (0b0011100000100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 79 ), // #193 + INST(Ldsminh , BaseAtomicOp , (0b0111100000100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 80 ), // #194 + INST(Ldsminl , BaseAtomicOp , (0b1011100001100000010100, kWX, 30, 0) , kRWI_WRX , 0 , 81 ), // #195 + INST(Ldsminlb , BaseAtomicOp , (0b0011100001100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 82 ), // #196 + INST(Ldsminlh , BaseAtomicOp , (0b0111100001100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 83 ), // #197 + INST(Ldtr , BaseRM_SImm9 , (0b1011100001000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_W , 0 , 1 ), // #198 + INST(Ldtrb , BaseRM_SImm9 , (0b0011100001000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 2 ), // #199 + INST(Ldtrh , BaseRM_SImm9 , (0b0111100001000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 3 ), // #200 + INST(Ldtrsb , BaseRM_SImm9 , (0b0011100011000000000010, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 4 ), // #201 + INST(Ldtrsh , BaseRM_SImm9 , (0b0111100011000000000010, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 5 ), // #202 + INST(Ldtrsw , BaseRM_SImm9 , (0b1011100010000000000010, 0b0000000000000000000000, kX , kZR, 0 , 0) , kRWI_W , 0 , 6 ), // #203 + INST(Ldumax , BaseAtomicOp , (0b1011100000100000011000, kWX, 30, 0) , kRWI_WRX , 0 , 84 ), // #204 + INST(Ldumaxa , BaseAtomicOp , (0b1011100010100000011000, kWX, 30, 1) , kRWI_WRX , 0 , 85 ), // #205 + INST(Ldumaxab , BaseAtomicOp , (0b0011100010100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 86 ), // #206 + INST(Ldumaxah , BaseAtomicOp , (0b0111100010100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 87 ), // #207 + INST(Ldumaxal , BaseAtomicOp , (0b1011100011100000011000, kWX, 30, 1) , kRWI_WRX , 0 , 88 ), // #208 + INST(Ldumaxalb , BaseAtomicOp , (0b0011100011100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 89 ), // #209 + INST(Ldumaxalh , BaseAtomicOp , (0b0111100011100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 90 ), // #210 + INST(Ldumaxb , BaseAtomicOp , (0b0011100000100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 91 ), // #211 + INST(Ldumaxh , BaseAtomicOp , (0b0111100000100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 92 ), // #212 + INST(Ldumaxl , BaseAtomicOp , (0b1011100001100000011000, kWX, 30, 0) , kRWI_WRX , 0 , 93 ), // #213 + INST(Ldumaxlb , BaseAtomicOp , (0b0011100001100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 94 ), // #214 + INST(Ldumaxlh , BaseAtomicOp , (0b0111100001100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 95 ), // #215 + INST(Ldumin , BaseAtomicOp , (0b1011100000100000011100, kWX, 30, 0) , kRWI_WRX , 0 , 96 ), // #216 + INST(Ldumina , BaseAtomicOp , (0b1011100010100000011100, kWX, 30, 1) , kRWI_WRX , 0 , 97 ), // #217 + INST(Lduminab , BaseAtomicOp , (0b0011100010100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 98 ), // #218 + INST(Lduminah , BaseAtomicOp , (0b0111100010100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 99 ), // #219 + INST(Lduminal , BaseAtomicOp , (0b1011100011100000011100, kWX, 30, 1) , kRWI_WRX , 0 , 100), // #220 + INST(Lduminalb , BaseAtomicOp , (0b0011100011100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 101), // #221 + INST(Lduminalh , BaseAtomicOp , (0b0111100011100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 102), // #222 + INST(Lduminb , BaseAtomicOp , (0b0011100000100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 103), // #223 + INST(Lduminh , BaseAtomicOp , (0b0111100000100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 104), // #224 + INST(Lduminl , BaseAtomicOp , (0b1011100001100000011100, kWX, 30, 0) , kRWI_WRX , 0 , 105), // #225 + INST(Lduminlb , BaseAtomicOp , (0b0011100001100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 106), // #226 + INST(Lduminlh , BaseAtomicOp , (0b0111100001100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 107), // #227 + INST(Ldur , BaseRM_SImm9 , (0b1011100001000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_W , 0 , 7 ), // #228 + INST(Ldurb , BaseRM_SImm9 , (0b0011100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 8 ), // #229 + INST(Ldurh , BaseRM_SImm9 , (0b0111100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 9 ), // #230 + INST(Ldursb , BaseRM_SImm9 , (0b0011100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 10 ), // #231 + INST(Ldursh , BaseRM_SImm9 , (0b0111100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 11 ), // #232 + INST(Ldursw , BaseRM_SImm9 , (0b1011100010000000000000, 0b0000000000000000000000, kX , kZR, 0 , 0) , kRWI_W , 0 , 12 ), // #233 + INST(Ldxp , BaseLdxp , (0b1000100001111111000000, kWX, 30) , kRWI_WW , 0 , 1 ), // #234 + INST(Ldxr , BaseRM_NoImm , (0b1000100001011111011111, kWX, kZR, 30) , kRWI_W , 0 , 10 ), // #235 + INST(Ldxrb , BaseRM_NoImm , (0b0000100001011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 11 ), // #236 + INST(Ldxrh , BaseRM_NoImm , (0b0100100001011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 12 ), // #237 + INST(Lsl , BaseShift , (0b0001101011000000001000, 0b0101001100000000000000, 0) , kRWI_W , 0 , 2 ), // #238 + INST(Lslv , BaseShift , (0b0001101011000000001000, 0b0000000000000000000000, 0) , kRWI_W , 0 , 3 ), // #239 + INST(Lsr , BaseShift , (0b0001101011000000001001, 0b0101001100000000011111, 0) , kRWI_W , 0 , 4 ), // #240 + INST(Lsrv , BaseShift , (0b0001101011000000001001, 0b0000000000000000000000, 0) , kRWI_W , 0 , 5 ), // #241 + INST(Madd , BaseRRRR , (0b0001101100000000000000, kWX, kZR, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 0 ), // #242 + INST(Mneg , BaseRRR , (0b0001101100000000111111, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 11 ), // #243 + INST(Mov , BaseMov , (_) , kRWI_W , 0 , 0 ), // #244 + INST(Movk , BaseMovKNZ , (0b01110010100000000000000000000000) , kRWI_X , 0 , 0 ), // #245 + INST(Movn , BaseMovKNZ , (0b00010010100000000000000000000000) , kRWI_W , 0 , 1 ), // #246 + INST(Movz , BaseMovKNZ , (0b01010010100000000000000000000000) , kRWI_W , 0 , 2 ), // #247 + INST(Mrs , BaseMrs , (_) , kRWI_W , 0 , 0 ), // #248 + INST(Msr , BaseMsr , (_) , kRWI_W , 0 , 0 ), // #249 + INST(Msub , BaseRRRR , (0b0001101100000000100000, kWX, kZR, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 1 ), // #250 + INST(Mul , BaseRRR , (0b0001101100000000011111, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 12 ), // #251 + INST(Mvn , BaseMvnNeg , (0b00101010001000000000001111100000) , kRWI_W , 0 , 0 ), // #252 + INST(Neg , BaseMvnNeg , (0b01001011000000000000001111100000) , kRWI_W , 0 , 1 ), // #253 + INST(Negs , BaseMvnNeg , (0b01101011000000000000001111100000) , kRWI_W , 0 , 2 ), // #254 + INST(Ngc , BaseRR , (0b01011010000000000000001111100000, kWX, kZR, 0, kWX, kZR, 16, true) , kRWI_W , 0 , 7 ), // #255 + INST(Ngcs , BaseRR , (0b01111010000000000000001111100000, kWX, kZR, 0, kWX, kZR, 16, true) , kRWI_W , 0 , 8 ), // #256 + INST(Nop , BaseOp , (0b11010101000000110010000000011111) , 0 , 0 , 13 ), // #257 + INST(Orn , BaseLogical , (0b0101010001, 0b01100100, 1) , kRWI_W , 0 , 6 ), // #258 + INST(Orr , BaseLogical , (0b0101010000, 0b01100100, 0) , kRWI_W , 0 , 7 ), // #259 + INST(Pacda , BaseRR , (0b11011010110000010000100000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 9 ), // #260 + INST(Pacdb , BaseRR , (0b11011010110000010000110000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 10 ), // #261 + INST(Pacdza , BaseR , (0b11011010110000010010101111100000, kX, kZR, 0) , kRWI_X , 0 , 4 ), // #262 + INST(Pacdzb , BaseR , (0b11011010110000010010111111100000, kX, kZR, 0) , kRWI_X , 0 , 5 ), // #263 + INST(Pacga , BaseRRR , (0b1001101011000000001100, kX, kZR, kX, kZR, kX, kSP, false) , kRWI_W , 0 , 13 ), // #264 + INST(Prfm , BasePrfm , (0b11111000101, 0b1111100110, 0b11111000100, 0b11011000) , kRWI_R , 0 , 0 ), // #265 + INST(Pssbb , BaseOp , (0b11010101000000110011010010011111) , 0 , 0 , 14 ), // #266 + INST(Rbit , BaseRR , (0b01011010110000000000000000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 11 ), // #267 + INST(Ret , BaseBranchReg , (0b11010110010111110000000000000000) , kRWI_R , 0 , 2 ), // #268 + INST(Rev , BaseRev , (_) , kRWI_W , 0 , 0 ), // #269 + INST(Rev16 , BaseRR , (0b01011010110000000000010000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 12 ), // #270 + INST(Rev32 , BaseRR , (0b11011010110000000000100000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 13 ), // #271 + INST(Rev64 , BaseRR , (0b11011010110000000000110000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 14 ), // #272 + INST(Ror , BaseShift , (0b0001101011000000001011, 0b0001001110000000000000, 1) , kRWI_W , 0 , 6 ), // #273 + INST(Rorv , BaseShift , (0b0001101011000000001011, 0b0000000000000000000000, 1) , kRWI_W , 0 , 7 ), // #274 + INST(Sbc , BaseRRR , (0b0101101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 14 ), // #275 + INST(Sbcs , BaseRRR , (0b0111101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 15 ), // #276 + INST(Sbfiz , BaseBfi , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #277 + INST(Sbfm , BaseBfm , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #278 + INST(Sbfx , BaseBfx , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #279 + INST(Sdiv , BaseRRR , (0b0001101011000000000011, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 16 ), // #280 + INST(Setf8 , BaseR , (0b00111010000000000000100000001101, kW, kZR, 5) , 0 , 0 , 6 ), // #281 + INST(Setf16 , BaseR , (0b00111010000000000100100000001101, kW, kZR, 5) , 0 , 0 , 7 ), // #282 + INST(Sev , BaseOp , (0b11010101000000110010000010011111) , 0 , 0 , 15 ), // #283 + INST(Sevl , BaseOp , (0b11010101000000110010000010111111) , 0 , 0 , 16 ), // #284 + INST(Smaddl , BaseRRRR , (0b1001101100100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 2 ), // #285 + INST(Smc , BaseOpImm , (0b11010100000000000000000000000011, 16, 5) , 0 , 0 , 11 ), // #286 + INST(Smnegl , BaseRRR , (0b1001101100100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 17 ), // #287 + INST(Smsubl , BaseRRRR , (0b1001101100100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 3 ), // #288 + INST(Smulh , BaseRRR , (0b1001101101000000011111, kX , kZR, kX , kZR, kX , kZR, true) , kRWI_W , 0 , 18 ), // #289 + INST(Smull , BaseRRR , (0b1001101100100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 19 ), // #290 + INST(Ssbb , BaseOp , (0b11010101000000110011000010011111) , 0 , 0 , 17 ), // #291 + INST(St2g , BaseRM_SImm9 , (0b1101100110100000000010, 0b1101100110100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 13 ), // #292 + INST(Stadd , BaseAtomicSt , (0b1011100000100000000000, kWX, 30) , kRWI_RX , 0 , 0 ), // #293 + INST(Staddl , BaseAtomicSt , (0b1011100001100000000000, kWX, 30) , kRWI_RX , 0 , 1 ), // #294 + INST(Staddb , BaseAtomicSt , (0b0011100000100000000000, kW , 0 ) , kRWI_RX , 0 , 2 ), // #295 + INST(Staddlb , BaseAtomicSt , (0b0011100001100000000000, kW , 0 ) , kRWI_RX , 0 , 3 ), // #296 + INST(Staddh , BaseAtomicSt , (0b0111100000100000000000, kW , 0 ) , kRWI_RX , 0 , 4 ), // #297 + INST(Staddlh , BaseAtomicSt , (0b0111100001100000000000, kW , 0 ) , kRWI_RX , 0 , 5 ), // #298 + INST(Stclr , BaseAtomicSt , (0b1011100000100000000100, kWX, 30) , kRWI_RX , 0 , 6 ), // #299 + INST(Stclrl , BaseAtomicSt , (0b1011100001100000000100, kWX, 30) , kRWI_RX , 0 , 7 ), // #300 + INST(Stclrb , BaseAtomicSt , (0b0011100000100000000100, kW , 0 ) , kRWI_RX , 0 , 8 ), // #301 + INST(Stclrlb , BaseAtomicSt , (0b0011100001100000000100, kW , 0 ) , kRWI_RX , 0 , 9 ), // #302 + INST(Stclrh , BaseAtomicSt , (0b0111100000100000000100, kW , 0 ) , kRWI_RX , 0 , 10 ), // #303 + INST(Stclrlh , BaseAtomicSt , (0b0111100001100000000100, kW , 0 ) , kRWI_RX , 0 , 11 ), // #304 + INST(Steor , BaseAtomicSt , (0b1011100000100000001000, kWX, 30) , kRWI_RX , 0 , 12 ), // #305 + INST(Steorl , BaseAtomicSt , (0b1011100001100000001000, kWX, 30) , kRWI_RX , 0 , 13 ), // #306 + INST(Steorb , BaseAtomicSt , (0b0011100000100000001000, kW , 0 ) , kRWI_RX , 0 , 14 ), // #307 + INST(Steorlb , BaseAtomicSt , (0b0011100001100000001000, kW , 0 ) , kRWI_RX , 0 , 15 ), // #308 + INST(Steorh , BaseAtomicSt , (0b0111100000100000001000, kW , 0 ) , kRWI_RX , 0 , 16 ), // #309 + INST(Steorlh , BaseAtomicSt , (0b0111100001100000001000, kW , 0 ) , kRWI_RX , 0 , 17 ), // #310 + INST(Stg , BaseRM_SImm9 , (0b1101100100100000000010, 0b1101100100100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 14 ), // #311 + INST(Stgm , BaseRM_NoImm , (0b1101100110100000000000, kX , kZR, 0 ) , kRWI_RW , 0 , 13 ), // #312 + INST(Stgp , BaseLdpStp , (0b0110100100, 0b0110100010, kX, 0, 4) , kRWI_RRW , 0 , 3 ), // #313 + INST(Stllr , BaseRM_NoImm , (0b1000100010011111011111, kWX, kZR, 30) , kRWI_RW , 0 , 14 ), // #314 + INST(Stllrb , BaseRM_NoImm , (0b0000100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 15 ), // #315 + INST(Stllrh , BaseRM_NoImm , (0b0100100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 16 ), // #316 + INST(Stlr , BaseRM_NoImm , (0b1000100010011111111111, kWX, kZR, 30) , kRWI_RW , 0 , 17 ), // #317 + INST(Stlrb , BaseRM_NoImm , (0b0000100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 18 ), // #318 + INST(Stlrh , BaseRM_NoImm , (0b0100100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 19 ), // #319 + INST(Stlxp , BaseStxp , (0b1000100000100000100000, kWX, 30) , kRWI_WRRX , 0 , 0 ), // #320 + INST(Stlxr , BaseAtomicOp , (0b1000100000000000111111, kWX, 30, 1) , kRWI_WRX , 0 , 108), // #321 + INST(Stlxrb , BaseAtomicOp , (0b0000100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 109), // #322 + INST(Stlxrh , BaseAtomicOp , (0b0100100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 110), // #323 + INST(Stnp , BaseLdpStp , (0b0010100000, 0 , kWX, 31, 2) , kRWI_RRW , 0 , 4 ), // #324 + INST(Stp , BaseLdpStp , (0b0010100100, 0b0010100010, kWX, 31, 2) , kRWI_RRW , 0 , 5 ), // #325 + INST(Str , BaseLdSt , (0b1011100100, 0b10111000000, 0b10111000001, 0 , kWX, 30, 2, Inst::kIdStur) , kRWI_RW , 0 , 6 ), // #326 + INST(Strb , BaseLdSt , (0b0011100100, 0b00111000000, 0b00111000001, 0 , kW , 30, 0, Inst::kIdSturb) , kRWI_RW , 0 , 7 ), // #327 + INST(Strh , BaseLdSt , (0b0111100100, 0b01111000000, 0b01111000001, 0 , kWX, 30, 1, Inst::kIdSturh) , kRWI_RW , 0 , 8 ), // #328 + INST(Stset , BaseAtomicSt , (0b1011100000100000001100, kWX, 30) , kRWI_RX , 0 , 18 ), // #329 + INST(Stsetl , BaseAtomicSt , (0b1011100001100000001100, kWX, 30) , kRWI_RX , 0 , 19 ), // #330 + INST(Stsetb , BaseAtomicSt , (0b0011100000100000001100, kW , 0 ) , kRWI_RX , 0 , 20 ), // #331 + INST(Stsetlb , BaseAtomicSt , (0b0011100001100000001100, kW , 0 ) , kRWI_RX , 0 , 21 ), // #332 + INST(Stseth , BaseAtomicSt , (0b0111100000100000001100, kW , 0 ) , kRWI_RX , 0 , 22 ), // #333 + INST(Stsetlh , BaseAtomicSt , (0b0111100001100000001100, kW , 0 ) , kRWI_RX , 0 , 23 ), // #334 + INST(Stsmax , BaseAtomicSt , (0b1011100000100000010000, kWX, 30) , kRWI_RX , 0 , 24 ), // #335 + INST(Stsmaxl , BaseAtomicSt , (0b1011100001100000010000, kWX, 30) , kRWI_RX , 0 , 25 ), // #336 + INST(Stsmaxb , BaseAtomicSt , (0b0011100000100000010000, kW , 0 ) , kRWI_RX , 0 , 26 ), // #337 + INST(Stsmaxlb , BaseAtomicSt , (0b0011100001100000010000, kW , 0 ) , kRWI_RX , 0 , 27 ), // #338 + INST(Stsmaxh , BaseAtomicSt , (0b0111100000100000010000, kW , 0 ) , kRWI_RX , 0 , 28 ), // #339 + INST(Stsmaxlh , BaseAtomicSt , (0b0111100001100000010000, kW , 0 ) , kRWI_RX , 0 , 29 ), // #340 + INST(Stsmin , BaseAtomicSt , (0b1011100000100000010100, kWX, 30) , kRWI_RX , 0 , 30 ), // #341 + INST(Stsminl , BaseAtomicSt , (0b1011100001100000010100, kWX, 30) , kRWI_RX , 0 , 31 ), // #342 + INST(Stsminb , BaseAtomicSt , (0b0011100000100000010100, kW , 0 ) , kRWI_RX , 0 , 32 ), // #343 + INST(Stsminlb , BaseAtomicSt , (0b0011100001100000010100, kW , 0 ) , kRWI_RX , 0 , 33 ), // #344 + INST(Stsminh , BaseAtomicSt , (0b0111100000100000010100, kW , 0 ) , kRWI_RX , 0 , 34 ), // #345 + INST(Stsminlh , BaseAtomicSt , (0b0111100001100000010100, kW , 0 ) , kRWI_RX , 0 , 35 ), // #346 + INST(Sttr , BaseRM_SImm9 , (0b1011100000000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 15 ), // #347 + INST(Sttrb , BaseRM_SImm9 , (0b0011100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 16 ), // #348 + INST(Sttrh , BaseRM_SImm9 , (0b0111100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 17 ), // #349 + INST(Stumax , BaseAtomicSt , (0b1011100000100000011000, kWX, 30) , kRWI_RX , 0 , 36 ), // #350 + INST(Stumaxl , BaseAtomicSt , (0b1011100001100000011000, kWX, 30) , kRWI_RX , 0 , 37 ), // #351 + INST(Stumaxb , BaseAtomicSt , (0b0011100000100000011000, kW , 0 ) , kRWI_RX , 0 , 38 ), // #352 + INST(Stumaxlb , BaseAtomicSt , (0b0011100001100000011000, kW , 0 ) , kRWI_RX , 0 , 39 ), // #353 + INST(Stumaxh , BaseAtomicSt , (0b0111100000100000011000, kW , 0 ) , kRWI_RX , 0 , 40 ), // #354 + INST(Stumaxlh , BaseAtomicSt , (0b0111100001100000011000, kW , 0 ) , kRWI_RX , 0 , 41 ), // #355 + INST(Stumin , BaseAtomicSt , (0b1011100000100000011100, kWX, 30) , kRWI_RX , 0 , 42 ), // #356 + INST(Stuminl , BaseAtomicSt , (0b1011100001100000011100, kWX, 30) , kRWI_RX , 0 , 43 ), // #357 + INST(Stuminb , BaseAtomicSt , (0b0011100000100000011100, kW , 0 ) , kRWI_RX , 0 , 44 ), // #358 + INST(Stuminlb , BaseAtomicSt , (0b0011100001100000011100, kW , 0 ) , kRWI_RX , 0 , 45 ), // #359 + INST(Stuminh , BaseAtomicSt , (0b0111100000100000011100, kW , 0 ) , kRWI_RX , 0 , 46 ), // #360 + INST(Stuminlh , BaseAtomicSt , (0b0111100001100000011100, kW , 0 ) , kRWI_RX , 0 , 47 ), // #361 + INST(Stur , BaseRM_SImm9 , (0b1011100000000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 18 ), // #362 + INST(Sturb , BaseRM_SImm9 , (0b0011100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 19 ), // #363 + INST(Sturh , BaseRM_SImm9 , (0b0111100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 20 ), // #364 + INST(Stxp , BaseStxp , (0b1000100000100000000000, kWX, 30) , kRWI_WRRW , 0 , 1 ), // #365 + INST(Stxr , BaseStx , (0b1000100000000000011111, kWX, 30) , kRWI_WRW , 0 , 0 ), // #366 + INST(Stxrb , BaseStx , (0b0000100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 1 ), // #367 + INST(Stxrh , BaseStx , (0b0100100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 2 ), // #368 + INST(Stz2g , BaseRM_SImm9 , (0b1101100111100000000010, 0b1101100111100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 21 ), // #369 + INST(Stzg , BaseRM_SImm9 , (0b1101100101100000000010, 0b1101100101100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 22 ), // #370 + INST(Stzgm , BaseRM_NoImm , (0b1101100100100000000000, kX , kZR, 0) , kRWI_RW , 0 , 20 ), // #371 + INST(Sub , BaseAddSub , (0b1001011000, 0b1001011001, 0b1010001) , kRWI_W , 0 , 2 ), // #372 + INST(Subg , BaseRRII , (0b1101000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10) , kRWI_W , 0 , 1 ), // #373 + INST(Subp , BaseRRR , (0b1001101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 20 ), // #374 + INST(Subps , BaseRRR , (0b1011101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 21 ), // #375 + INST(Subs , BaseAddSub , (0b1101011000, 0b1101011001, 0b1110001) , kRWI_W , 0 , 3 ), // #376 + INST(Svc , BaseOpImm , (0b11010100000000000000000000000001, 16, 5) , 0 , 0 , 12 ), // #377 + INST(Swp , BaseAtomicOp , (0b1011100000100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 111), // #378 + INST(Swpa , BaseAtomicOp , (0b1011100010100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 112), // #379 + INST(Swpab , BaseAtomicOp , (0b0011100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 113), // #380 + INST(Swpah , BaseAtomicOp , (0b0111100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 114), // #381 + INST(Swpal , BaseAtomicOp , (0b1011100011100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 115), // #382 + INST(Swpalb , BaseAtomicOp , (0b0011100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 116), // #383 + INST(Swpalh , BaseAtomicOp , (0b0111100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 117), // #384 + INST(Swpb , BaseAtomicOp , (0b0011100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 118), // #385 + INST(Swph , BaseAtomicOp , (0b0111100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 119), // #386 + INST(Swpl , BaseAtomicOp , (0b1011100001100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 120), // #387 + INST(Swplb , BaseAtomicOp , (0b0011100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 121), // #388 + INST(Swplh , BaseAtomicOp , (0b0111100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 122), // #389 + INST(Sxtb , BaseExtend , (0b0001001100000000000111, kWX, 0) , kRWI_W , 0 , 0 ), // #390 + INST(Sxth , BaseExtend , (0b0001001100000000001111, kWX, 0) , kRWI_W , 0 , 1 ), // #391 + INST(Sxtw , BaseExtend , (0b1001001101000000011111, kX , 0) , kRWI_W , 0 , 2 ), // #392 + INST(Sys , BaseSys , (_) , kRWI_W , 0 , 0 ), // #393 + INST(Tlbi , BaseAtDcIcTlbi , (0b00011110000000, 0b00010000000000, false) , kRWI_RX , 0 , 3 ), // #394 + INST(Tst , BaseTst , (0b1101010000, 0b111001000) , kRWI_R , 0 , 0 ), // #395 + INST(Tbnz , BaseBranchTst , (0b00110111000000000000000000000000) , kRWI_R , 0 , 0 ), // #396 + INST(Tbz , BaseBranchTst , (0b00110110000000000000000000000000) , kRWI_R , 0 , 1 ), // #397 + INST(Ubfiz , BaseBfi , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #398 + INST(Ubfm , BaseBfm , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #399 + INST(Ubfx , BaseBfx , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #400 + INST(Udf , BaseOpImm , (0b00000000000000000000000000000000, 16, 0) , 0 , 0 , 13 ), // #401 + INST(Udiv , BaseRRR , (0b0001101011000000000010, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 22 ), // #402 + INST(Umaddl , BaseRRRR , (0b1001101110100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 4 ), // #403 + INST(Umnegl , BaseRRR , (0b1001101110100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 23 ), // #404 + INST(Umull , BaseRRR , (0b1001101110100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 24 ), // #405 + INST(Umulh , BaseRRR , (0b1001101111000000011111, kX , kZR, kX , kZR, kX , kZR, false) , kRWI_W , 0 , 25 ), // #406 + INST(Umsubl , BaseRRRR , (0b1001101110100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 5 ), // #407 + INST(Uxtb , BaseExtend , (0b0101001100000000000111, kW, 1) , kRWI_W , 0 , 3 ), // #408 + INST(Uxth , BaseExtend , (0b0101001100000000001111, kW, 1) , kRWI_W , 0 , 4 ), // #409 + INST(Wfe , BaseOp , (0b11010101000000110010000001011111) , 0 , 0 , 18 ), // #410 + INST(Wfi , BaseOp , (0b11010101000000110010000001111111) , 0 , 0 , 19 ), // #411 + INST(Xaflag , BaseOp , (0b11010101000000000100000000111111) , 0 , 0 , 20 ), // #412 + INST(Xpacd , BaseR , (0b11011010110000010100011111100000, kX, kZR, 0) , kRWI_X , 0 , 8 ), // #413 + INST(Xpaci , BaseR , (0b11011010110000010100001111100000, kX, kZR, 0) , kRWI_X , 0 , 9 ), // #414 + INST(Xpaclri , BaseOp , (0b11010101000000110010000011111111) , kRWI_X , 0 , 21 ), // #415 + INST(Yield , BaseOp , (0b11010101000000110010000000111111) , 0 , 0 , 22 ), // #416 + INST(Abs_v , ISimdVV , (0b0000111000100000101110, kVO_V_Any) , kRWI_W , 0 , 0 ), // #417 + INST(Add_v , ISimdVVV , (0b0000111000100000100001, kVO_V_Any) , kRWI_W , 0 , 0 ), // #418 + INST(Addhn_v , ISimdVVV , (0b0000111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 1 ), // #419 + INST(Addhn2_v , ISimdVVV , (0b0100111000100000010000, kVO_V_B16H8S4) , kRWI_W , F(Narrow) , 2 ), // #420 + INST(Addp_v , ISimdPair , (0b0101111000110001101110, 0b0000111000100000101111, kVO_V_Any) , kRWI_W , F(Pair) , 0 ), // #421 + INST(Addv_v , ISimdSV , (0b0000111000110001101110, kVO_V_BH_4S) , kRWI_W , 0 , 0 ), // #422 + INST(Aesd_v , ISimdVVx , (0b0100111000101000010110, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 0 ), // #423 + INST(Aese_v , ISimdVVx , (0b0100111000101000010010, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 1 ), // #424 + INST(Aesimc_v , ISimdVVx , (0b0100111000101000011110, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 2 ), // #425 + INST(Aesmc_v , ISimdVVx , (0b0100111000101000011010, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 3 ), // #426 + INST(And_v , ISimdVVV , (0b0000111000100000000111, kVO_V_B) , kRWI_W , 0 , 3 ), // #427 + INST(Bcax_v , ISimdVVVV , (0b1100111000100000000000, kVO_V_B16) , kRWI_W , 0 , 0 ), // #428 + INST(Bfcvt_v , ISimdVVx , (0b0001111001100011010000, kOp_H, kOp_S) , kRWI_W , 0 , 4 ), // #429 + INST(Bfcvtn_v , ISimdVVx , (0b0000111010100001011010, kOp_V4H, kOp_V4S) , kRWI_W , F(Narrow) , 5 ), // #430 + INST(Bfcvtn2_v , ISimdVVx , (0b0100111010100001011010, kOp_V8H, kOp_V4S) , kRWI_W , F(Narrow) , 6 ), // #431 + INST(Bfdot_v , SimdDot , (0b0010111001000000111111, 0b0000111101000000111100, kET_S, kET_H, kET_2H) , kRWI_X , 0 , 0 ), // #432 + INST(Bfmlalb_v , SimdFmlal , (0b0010111011000000111111, 0b0000111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 0 ), // #433 + INST(Bfmlalt_v , SimdFmlal , (0b0110111011000000111111, 0b0100111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 1 ), // #434 + INST(Bfmmla_v , ISimdVVVx , (0b0110111001000000111011, kOp_V4S, kOp_V8H, kOp_V8H) , kRWI_X , F(Long) , 0 ), // #435 + INST(Bic_v , SimdBicOrr , (0b0000111001100000000111, 0b0010111100000000000001) , kRWI_W , 0 , 0 ), // #436 + INST(Bif_v , ISimdVVV , (0b0010111011100000000111, kVO_V_B) , kRWI_X , 0 , 4 ), // #437 + INST(Bit_v , ISimdVVV , (0b0010111010100000000111, kVO_V_B) , kRWI_X , 0 , 5 ), // #438 + INST(Bsl_v , ISimdVVV , (0b0010111001100000000111, kVO_V_B) , kRWI_X , 0 , 6 ), // #439 + INST(Cls_v , ISimdVV , (0b0000111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 1 ), // #440 + INST(Clz_v , ISimdVV , (0b0010111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 2 ), // #441 + INST(Cmeq_v , SimdCmp , (0b0010111000100000100011, 0b0000111000100000100110, kVO_V_Any) , kRWI_W , 0 , 0 ), // #442 + INST(Cmge_v , SimdCmp , (0b0000111000100000001111, 0b0010111000100000100010, kVO_V_Any) , kRWI_W , 0 , 1 ), // #443 + INST(Cmgt_v , SimdCmp , (0b0000111000100000001101, 0b0000111000100000100010, kVO_V_Any) , kRWI_W , 0 , 2 ), // #444 + INST(Cmhi_v , SimdCmp , (0b0010111000100000001101, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 3 ), // #445 + INST(Cmhs_v , SimdCmp , (0b0010111000100000001111, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 4 ), // #446 + INST(Cmle_v , SimdCmp , (0b0000000000000000000000, 0b0010111000100000100110, kVO_V_Any) , kRWI_W , 0 , 5 ), // #447 + INST(Cmlt_v , SimdCmp , (0b0000000000000000000000, 0b0000111000100000101010, kVO_V_Any) , kRWI_W , 0 , 6 ), // #448 + INST(Cmtst_v , ISimdVVV , (0b0000111000100000100011, kVO_V_Any) , kRWI_W , 0 , 7 ), // #449 + INST(Cnt_v , ISimdVV , (0b0000111000100000010110, kVO_V_B) , kRWI_W , 0 , 3 ), // #450 + INST(Dup_v , SimdDup , (_) , kRWI_W , 0 , 0 ), // #451 + INST(Eor_v , ISimdVVV , (0b0010111000100000000111, kVO_V_B) , kRWI_W , 0 , 8 ), // #452 + INST(Eor3_v , ISimdVVVV , (0b1100111000000000000000, kVO_V_B16) , kRWI_W , 0 , 1 ), // #453 + INST(Ext_v , ISimdVVVI , (0b0010111000000000000000, kVO_V_B, 4, 11, 1) , kRWI_W , 0 , 0 ), // #454 + INST(Fabd_v , FSimdVVV , (0b0111111010100000110101, kHF_C, 0b0010111010100000110101, kHF_C) , kRWI_W , 0 , 0 ), // #455 + INST(Fabs_v , FSimdVV , (0b0001111000100000110000, kHF_A, 0b0000111010100000111110, kHF_B) , kRWI_W , 0 , 0 ), // #456 + INST(Facge_v , FSimdVVV , (0b0111111000100000111011, kHF_C, 0b0010111000100000111011, kHF_C) , kRWI_W , 0 , 1 ), // #457 + INST(Facgt_v , FSimdVVV , (0b0111111010100000111011, kHF_C, 0b0010111010100000111011, kHF_C) , kRWI_W , 0 , 2 ), // #458 + INST(Fadd_v , FSimdVVV , (0b0001111000100000001010, kHF_A, 0b0000111000100000110101, kHF_C) , kRWI_W , 0 , 3 ), // #459 + INST(Faddp_v , FSimdPair , (0b0111111000110000110110, 0b0010111000100000110101) , kRWI_W , 0 , 0 ), // #460 + INST(Fcadd_v , SimdFcadd , (0b0010111000000000111001) , kRWI_W , 0 , 0 ), // #461 + INST(Fccmp_v , SimdFccmpFccmpe , (0b00011110001000000000010000000000) , kRWI_R , 0 , 0 ), // #462 + INST(Fccmpe_v , SimdFccmpFccmpe , (0b00011110001000000000010000010000) , kRWI_R , 0 , 1 ), // #463 + INST(Fcmeq_v , SimdFcm , (0b0000111000100000111001, kHF_C, 0b0000111010100000110110) , kRWI_W , 0 , 0 ), // #464 + INST(Fcmge_v , SimdFcm , (0b0010111000100000111001, kHF_C, 0b0010111010100000110010) , kRWI_W , 0 , 1 ), // #465 + INST(Fcmgt_v , SimdFcm , (0b0010111010100000111001, kHF_C, 0b0000111010100000110010) , kRWI_W , 0 , 2 ), // #466 + INST(Fcmla_v , SimdFcmla , (0b0010111000000000110001, 0b0010111100000000000100) , kRWI_X , 0 , 0 ), // #467 + INST(Fcmle_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0010111010100000110110) , kRWI_W , 0 , 3 ), // #468 + INST(Fcmlt_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0000111010100000111010) , kRWI_W , 0 , 4 ), // #469 + INST(Fcmp_v , SimdFcmpFcmpe , (0b00011110001000000010000000000000) , kRWI_R , 0 , 0 ), // #470 + INST(Fcmpe_v , SimdFcmpFcmpe , (0b00011110001000000010000000010000) , kRWI_R , 0 , 1 ), // #471 + INST(Fcsel_v , SimdFcsel , (_) , kRWI_W , 0 , 0 ), // #472 + INST(Fcvt_v , SimdFcvt , (_) , kRWI_W , 0 , 0 ), // #473 + INST(Fcvtas_v , SimdFcvtSV , (0b0000111000100001110010, 0b0000000000000000000000, 0b0001111000100100000000, 1) , kRWI_W , 0 , 0 ), // #474 + INST(Fcvtau_v , SimdFcvtSV , (0b0010111000100001110010, 0b0000000000000000000000, 0b0001111000100101000000, 1) , kRWI_W , 0 , 1 ), // #475 + INST(Fcvtl_v , SimdFcvtLN , (0b0000111000100001011110, 0, 0) , kRWI_W , F(Long) , 0 ), // #476 + INST(Fcvtl2_v , SimdFcvtLN , (0b0100111000100001011110, 0, 0) , kRWI_W , F(Long) , 1 ), // #477 + INST(Fcvtms_v , SimdFcvtSV , (0b0000111000100001101110, 0b0000000000000000000000, 0b0001111000110000000000, 1) , kRWI_W , 0 , 2 ), // #478 + INST(Fcvtmu_v , SimdFcvtSV , (0b0010111000100001101110, 0b0000000000000000000000, 0b0001111000110001000000, 1) , kRWI_W , 0 , 3 ), // #479 + INST(Fcvtn_v , SimdFcvtLN , (0b0000111000100001011010, 0, 0) , kRWI_W , F(Narrow) , 2 ), // #480 + INST(Fcvtn2_v , SimdFcvtLN , (0b0100111000100001011010, 0, 0) , kRWI_X , F(Narrow) , 3 ), // #481 + INST(Fcvtns_v , SimdFcvtSV , (0b0000111000100001101010, 0b0000000000000000000000, 0b0001111000100000000000, 1) , kRWI_W , 0 , 4 ), // #482 + INST(Fcvtnu_v , SimdFcvtSV , (0b0010111000100001101010, 0b0000000000000000000000, 0b0001111000100001000000, 1) , kRWI_W , 0 , 5 ), // #483 + INST(Fcvtps_v , SimdFcvtSV , (0b0000111010100001101010, 0b0000000000000000000000, 0b0001111000101000000000, 1) , kRWI_W , 0 , 6 ), // #484 + INST(Fcvtpu_v , SimdFcvtSV , (0b0010111010100001101010, 0b0000000000000000000000, 0b0001111000101001000000, 1) , kRWI_W , 0 , 7 ), // #485 + INST(Fcvtxn_v , SimdFcvtLN , (0b0010111000100001011010, 1, 1) , kRWI_W , F(Narrow) , 4 ), // #486 + INST(Fcvtxn2_v , SimdFcvtLN , (0b0110111000100001011010, 1, 0) , kRWI_X , F(Narrow) , 5 ), // #487 + INST(Fcvtzs_v , SimdFcvtSV , (0b0000111010100001101110, 0b0000111100000000111111, 0b0001111000111000000000, 1) , kRWI_W , 0 , 8 ), // #488 + INST(Fcvtzu_v , SimdFcvtSV , (0b0010111010100001101110, 0b0010111100000000111111, 0b0001111000111001000000, 1) , kRWI_W , 0 , 9 ), // #489 + INST(Fdiv_v , FSimdVVV , (0b0001111000100000000110, kHF_A, 0b0010111000100000111111, kHF_C) , kRWI_W , 0 , 4 ), // #490 + INST(Fjcvtzs_v , ISimdVVx , (0b0001111001111110000000, kOp_GpW, kOp_D) , kRWI_W , 0 , 7 ), // #491 + INST(Fmadd_v , FSimdVVVV , (0b0001111100000000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 0 ), // #492 + INST(Fmax_v , FSimdVVV , (0b0001111000100000010010, kHF_A, 0b0000111000100000111101, kHF_C) , kRWI_W , 0 , 5 ), // #493 + INST(Fmaxnm_v , FSimdVVV , (0b0001111000100000011010, kHF_A, 0b0000111000100000110001, kHF_C) , kRWI_W , 0 , 6 ), // #494 + INST(Fmaxnmp_v , FSimdPair , (0b0111111000110000110010, 0b0010111000100000110001) , kRWI_W , 0 , 1 ), // #495 + INST(Fmaxnmv_v , FSimdSV , (0b0010111000110000110010) , kRWI_W , 0 , 0 ), // #496 + INST(Fmaxp_v , FSimdPair , (0b0111111000110000111110, 0b0010111000100000111101) , kRWI_W , 0 , 2 ), // #497 + INST(Fmaxv_v , FSimdSV , (0b0010111000110000111110) , kRWI_W , 0 , 1 ), // #498 + INST(Fmin_v , FSimdVVV , (0b0001111000100000010110, kHF_A, 0b0000111010100000111101, kHF_C) , kRWI_W , 0 , 7 ), // #499 + INST(Fminnm_v , FSimdVVV , (0b0001111000100000011110, kHF_A, 0b0000111010100000110001, kHF_C) , kRWI_W , 0 , 8 ), // #500 + INST(Fminnmp_v , FSimdPair , (0b0111111010110000110010, 0b0010111010100000110001) , kRWI_W , 0 , 3 ), // #501 + INST(Fminnmv_v , FSimdSV , (0b0010111010110000110010) , kRWI_W , 0 , 2 ), // #502 + INST(Fminp_v , FSimdPair , (0b0111111010110000111110, 0b0010111010100000111101) , kRWI_W , 0 , 4 ), // #503 + INST(Fminv_v , FSimdSV , (0b0010111010110000111110) , kRWI_W , 0 , 3 ), // #504 + INST(Fmla_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111000100000110011, 0b0000111110000000000100) , kRWI_X , F(VH0_15) , 0 ), // #505 + INST(Fmlal_v , SimdFmlal , (0b0000111000100000111011, 0b0000111110000000000000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 2 ), // #506 + INST(Fmlal2_v , SimdFmlal , (0b0010111000100000110011, 0b0010111110000000100000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 3 ), // #507 + INST(Fmls_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111010100000110011, 0b0000111110000000010100) , kRWI_X , F(VH0_15) , 1 ), // #508 + INST(Fmlsl_v , SimdFmlal , (0b0000111010100000111011, 0b0000111110000000010000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 4 ), // #509 + INST(Fmlsl2_v , SimdFmlal , (0b0010111010100000110011, 0b0010111110000000110000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 5 ), // #510 + INST(Fmov_v , SimdFmov , (_) , kRWI_W , 0 , 0 ), // #511 + INST(Fmsub_v , FSimdVVVV , (0b0001111100000000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 1 ), // #512 + INST(Fmul_v , FSimdVVVe , (0b0001111000100000000010, kHF_A, 0b0010111000100000110111, 0b0000111110000000100100) , kRWI_W , F(VH0_15) , 2 ), // #513 + INST(Fmulx_v , FSimdVVVe , (0b0101111000100000110111, kHF_C, 0b0000111000100000110111, 0b0010111110000000100100) , kRWI_W , F(VH0_15) , 3 ), // #514 + INST(Fneg_v , FSimdVV , (0b0001111000100001010000, kHF_A, 0b0010111010100000111110, kHF_B) , kRWI_W , 0 , 1 ), // #515 + INST(Fnmadd_v , FSimdVVVV , (0b0001111100100000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 2 ), // #516 + INST(Fnmsub_v , FSimdVVVV , (0b0001111100100000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 ), // #517 + INST(Fnmul_v , FSimdVVV , (0b0001111000100000100010, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 9 ), // #518 + INST(Frecpe_v , FSimdVV , (0b0101111010100001110110, kHF_B, 0b0000111010100001110110, kHF_B) , kRWI_W , 0 , 2 ), // #519 + INST(Frecps_v , FSimdVVV , (0b0101111000100000111111, kHF_C, 0b0000111000100000111111, kHF_C) , kRWI_W , 0 , 10 ), // #520 + INST(Frecpx_v , FSimdVV , (0b0101111010100001111110, kHF_B, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 ), // #521 + INST(Frint32x_v , FSimdVV , (0b0001111000101000110000, kHF_N, 0b0010111000100001111010, kHF_N) , kRWI_W , 0 , 4 ), // #522 + INST(Frint32z_v , FSimdVV , (0b0001111000101000010000, kHF_N, 0b0000111000100001111010, kHF_N) , kRWI_W , 0 , 5 ), // #523 + INST(Frint64x_v , FSimdVV , (0b0001111000101001110000, kHF_N, 0b0010111000100001111110, kHF_N) , kRWI_W , 0 , 6 ), // #524 + INST(Frint64z_v , FSimdVV , (0b0001111000101001010000, kHF_N, 0b0000111000100001111110, kHF_N) , kRWI_W , 0 , 7 ), // #525 + INST(Frinta_v , FSimdVV , (0b0001111000100110010000, kHF_A, 0b0010111000100001100010, kHF_B) , kRWI_W , 0 , 8 ), // #526 + INST(Frinti_v , FSimdVV , (0b0001111000100111110000, kHF_A, 0b0010111010100001100110, kHF_B) , kRWI_W , 0 , 9 ), // #527 + INST(Frintm_v , FSimdVV , (0b0001111000100101010000, kHF_A, 0b0000111000100001100110, kHF_B) , kRWI_W , 0 , 10 ), // #528 + INST(Frintn_v , FSimdVV , (0b0001111000100100010000, kHF_A, 0b0000111000100001100010, kHF_B) , kRWI_W , 0 , 11 ), // #529 + INST(Frintp_v , FSimdVV , (0b0001111000100100110000, kHF_A, 0b0000111010100001100010, kHF_B) , kRWI_W , 0 , 12 ), // #530 + INST(Frintx_v , FSimdVV , (0b0001111000100111010000, kHF_A, 0b0010111000100001100110, kHF_B) , kRWI_W , 0 , 13 ), // #531 + INST(Frintz_v , FSimdVV , (0b0001111000100101110000, kHF_A, 0b0000111010100001100110, kHF_B) , kRWI_W , 0 , 14 ), // #532 + INST(Frsqrte_v , FSimdVV , (0b0111111010100001110110, kHF_B, 0b0010111010100001110110, kHF_B) , kRWI_W , 0 , 15 ), // #533 + INST(Frsqrts_v , FSimdVVV , (0b0101111010100000111111, kHF_C, 0b0000111010100000111111, kHF_C) , kRWI_W , 0 , 11 ), // #534 + INST(Fsqrt_v , FSimdVV , (0b0001111000100001110000, kHF_A, 0b0010111010100001111110, kHF_B) , kRWI_W , 0 , 16 ), // #535 + INST(Fsub_v , FSimdVVV , (0b0001111000100000001110, kHF_A, 0b0000111010100000110101, kHF_C) , kRWI_W , 0 , 12 ), // #536 + INST(Ins_v , SimdIns , (_) , kRWI_X , 0 , 0 ), // #537 + INST(Ld1_v , SimdLdNStN , (0b0000110101000000000000, 0b0000110001000000001000, 1, 0) , kRWI_LDn , F(Consecutive) , 0 ), // #538 + INST(Ld1r_v , SimdLdNStN , (0b0000110101000000110000, 0b0000000000000000000000, 1, 1) , kRWI_LDn , F(Consecutive) , 1 ), // #539 + INST(Ld2_v , SimdLdNStN , (0b0000110101100000000000, 0b0000110001000000100000, 2, 0) , kRWI_LDn , F(Consecutive) , 2 ), // #540 + INST(Ld2r_v , SimdLdNStN , (0b0000110101100000110000, 0b0000000000000000000000, 2, 1) , kRWI_LDn , F(Consecutive) , 3 ), // #541 + INST(Ld3_v , SimdLdNStN , (0b0000110101000000001000, 0b0000110001000000010000, 3, 0) , kRWI_LDn , F(Consecutive) , 4 ), // #542 + INST(Ld3r_v , SimdLdNStN , (0b0000110101000000111000, 0b0000000000000000000000, 3, 1) , kRWI_LDn , F(Consecutive) , 5 ), // #543 + INST(Ld4_v , SimdLdNStN , (0b0000110101100000001000, 0b0000110001000000000000, 4, 0) , kRWI_LDn , F(Consecutive) , 6 ), // #544 + INST(Ld4r_v , SimdLdNStN , (0b0000110101100000111000, 0b0000000000000000000000, 4, 1) , kRWI_LDn , F(Consecutive) , 7 ), // #545 + INST(Ldnp_v , SimdLdpStp , (0b0010110001, 0b0000000000) , kRWI_WW , 0 , 0 ), // #546 + INST(Ldp_v , SimdLdpStp , (0b0010110101, 0b0010110011) , kRWI_WW , 0 , 1 ), // #547 + INST(Ldr_v , SimdLdSt , (0b0011110101, 0b00111100010, 0b00111100011, 0b00011100, Inst::kIdLdur_v) , kRWI_W , 0 , 0 ), // #548 + INST(Ldur_v , SimdLdurStur , (0b0011110001000000000000) , kRWI_W , 0 , 0 ), // #549 + INST(Mla_v , ISimdVVVe , (0b0000111000100000100101, kVO_V_BHS, 0b0010111100000000000000, kVO_V_HS) , kRWI_X , F(VH0_15) , 0 ), // #550 + INST(Mls_v , ISimdVVVe , (0b0010111000100000100101, kVO_V_BHS, 0b0010111100000000010000, kVO_V_HS) , kRWI_X , F(VH0_15) , 1 ), // #551 + INST(Mov_v , SimdMov , (_) , kRWI_W , 0 , 0 ), // #552 + INST(Movi_v , SimdMoviMvni , (0b0000111100000000000001, 0) , kRWI_W , 0 , 0 ), // #553 + INST(Mul_v , ISimdVVVe , (0b0000111000100000100111, kVO_V_BHS, 0b0000111100000000100000, kVO_V_HS) , kRWI_W , F(VH0_15) , 2 ), // #554 + INST(Mvn_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 4 ), // #555 + INST(Mvni_v , SimdMoviMvni , (0b0000111100000000000001, 1) , kRWI_W , 0 , 1 ), // #556 + INST(Neg_v , ISimdVV , (0b0010111000100000101110, kVO_V_Any) , kRWI_W , 0 , 5 ), // #557 + INST(Not_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 6 ), // #558 + INST(Orn_v , ISimdVVV , (0b0000111011100000000111, kVO_V_B) , kRWI_W , 0 , 9 ), // #559 + INST(Orr_v , SimdBicOrr , (0b0000111010100000000111, 0b0000111100000000000001) , kRWI_W , 0 , 1 ), // #560 + INST(Pmul_v , ISimdVVV , (0b0010111000100000100111, kVO_V_B) , kRWI_W , 0 , 10 ), // #561 + INST(Pmull_v , ISimdVVV , (0b0000111000100000111000, kVO_V_B8D1) , kRWI_W , F(Long) , 11 ), // #562 + INST(Pmull2_v , ISimdVVV , (0b0100111000100000111000, kVO_V_B16D2) , kRWI_W , F(Long) , 12 ), // #563 + INST(Raddhn_v , ISimdVVV , (0b0010111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 13 ), // #564 + INST(Raddhn2_v , ISimdVVV , (0b0110111000100000010000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 ), // #565 + INST(Rax1_v , ISimdVVV , (0b1100111001100000100011, kVO_V_D2) , kRWI_W , 0 , 15 ), // #566 + INST(Rbit_v , ISimdVV , (0b0010111001100000010110, kVO_V_B) , kRWI_W , 0 , 7 ), // #567 + INST(Rev16_v , ISimdVV , (0b0000111000100000000110, kVO_V_B) , kRWI_W , 0 , 8 ), // #568 + INST(Rev32_v , ISimdVV , (0b0010111000100000000010, kVO_V_BH) , kRWI_W , 0 , 9 ), // #569 + INST(Rev64_v , ISimdVV , (0b0000111000100000000010, kVO_V_BHS) , kRWI_W , 0 , 10 ), // #570 + INST(Rshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100011, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 0 ), // #571 + INST(Rshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 1 ), // #572 + INST(Rsubhn_v , ISimdVVV , (0b0010111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 16 ), // #573 + INST(Rsubhn2_v , ISimdVVV , (0b0110111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 17 ), // #574 + INST(Saba_v , ISimdVVV , (0b0000111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 18 ), // #575 + INST(Sabal_v , ISimdVVV , (0b0000111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 19 ), // #576 + INST(Sabal2_v , ISimdVVV , (0b0100111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 20 ), // #577 + INST(Sabd_v , ISimdVVV , (0b0000111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 21 ), // #578 + INST(Sabdl_v , ISimdVVV , (0b0000111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 ), // #579 + INST(Sabdl2_v , ISimdVVV , (0b0100111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 ), // #580 + INST(Sadalp_v , ISimdVV , (0b0000111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 11 ), // #581 + INST(Saddl_v , ISimdVVV , (0b0000111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 24 ), // #582 + INST(Saddl2_v , ISimdVVV , (0b0100111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 25 ), // #583 + INST(Saddlp_v , ISimdVV , (0b0000111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 12 ), // #584 + INST(Saddlv_v , ISimdSV , (0b0000111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 1 ), // #585 + INST(Saddw_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 0 ), // #586 + INST(Saddw2_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 1 ), // #587 + INST(Scvtf_v , SimdFcvtSV , (0b0000111000100001110110, 0b0000111100000000111001, 0b0001111000100010000000, 0) , kRWI_W , 0 , 10 ), // #588 + INST(Sdot_v , SimdDot , (0b0000111010000000100101, 0b0000111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 1 ), // #589 + INST(Sha1c_v , ISimdVVVx , (0b0101111000000000000000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 1 ), // #590 + INST(Sha1h_v , ISimdVVx , (0b0101111000101000000010, kOp_S, kOp_S) , kRWI_W , 0 , 8 ), // #591 + INST(Sha1m_v , ISimdVVVx , (0b0101111000000000001000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 2 ), // #592 + INST(Sha1p_v , ISimdVVVx , (0b0101111000000000000100, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 3 ), // #593 + INST(Sha1su0_v , ISimdVVVx , (0b0101111000000000001100, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 4 ), // #594 + INST(Sha1su1_v , ISimdVVx , (0b0101111000101000000110, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 9 ), // #595 + INST(Sha256h_v , ISimdVVVx , (0b0101111000000000010000, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 5 ), // #596 + INST(Sha256h2_v , ISimdVVVx , (0b0101111000000000010100, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 6 ), // #597 + INST(Sha256su0_v , ISimdVVx , (0b0101111000101000001010, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 10 ), // #598 + INST(Sha256su1_v , ISimdVVVx , (0b0101111000000000011000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 7 ), // #599 + INST(Sha512h_v , ISimdVVVx , (0b1100111001100000100000, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 8 ), // #600 + INST(Sha512h2_v , ISimdVVVx , (0b1100111001100000100001, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 9 ), // #601 + INST(Sha512su0_v , ISimdVVx , (0b1100111011000000100000, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 11 ), // #602 + INST(Sha512su1_v , ISimdVVVx , (0b1100111001100000100010, kOp_V2D, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 10 ), // #603 + INST(Shadd_v , ISimdVVV , (0b0000111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 26 ), // #604 + INST(Shl_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000010101, 0, kVO_V_Any) , kRWI_W , 0 , 2 ), // #605 + INST(Shll_v , SimdShiftES , (0b0010111000100001001110, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 ), // #606 + INST(Shll2_v , SimdShiftES , (0b0110111000100001001110, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 ), // #607 + INST(Shrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100001, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 3 ), // #608 + INST(Shrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 4 ), // #609 + INST(Shsub_v , ISimdVVV , (0b0000111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 27 ), // #610 + INST(Sli_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010101, 0, kVO_V_Any) , kRWI_X , 0 , 5 ), // #611 + INST(Sm3partw1_v , ISimdVVVx , (0b1100111001100000110000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 11 ), // #612 + INST(Sm3partw2_v , ISimdVVVx , (0b1100111001100000110001, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 ), // #613 + INST(Sm3ss1_v , ISimdVVVVx , (0b1100111001000000000000, kOp_V4S, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_W , 0 , 0 ), // #614 + INST(Sm3tt1a_v , SimdSm3tt , (0b1100111001000000100000) , kRWI_X , 0 , 0 ), // #615 + INST(Sm3tt1b_v , SimdSm3tt , (0b1100111001000000100001) , kRWI_X , 0 , 1 ), // #616 + INST(Sm3tt2a_v , SimdSm3tt , (0b1100111001000000100010) , kRWI_X , 0 , 2 ), // #617 + INST(Sm3tt2b_v , SimdSm3tt , (0b1100111001000000100011) , kRWI_X , 0 , 3 ), // #618 + INST(Sm4e_v , ISimdVVx , (0b1100111011000000100001, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 ), // #619 + INST(Sm4ekey_v , ISimdVVVx , (0b1100111001100000110010, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 13 ), // #620 + INST(Smax_v , ISimdVVV , (0b0000111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 28 ), // #621 + INST(Smaxp_v , ISimdVVV , (0b0000111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 29 ), // #622 + INST(Smaxv_v , ISimdSV , (0b0000111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 2 ), // #623 + INST(Smin_v , ISimdVVV , (0b0000111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 30 ), // #624 + INST(Sminp_v , ISimdVVV , (0b0000111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 31 ), // #625 + INST(Sminv_v , ISimdSV , (0b0000111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 3 ), // #626 + INST(Smlal_v , ISimdVVVe , (0b0000111000100000100000, kVO_V_B8H4S2, 0b0000111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 3 ), // #627 + INST(Smlal2_v , ISimdVVVe , (0b0100111000100000100000, kVO_V_B16H8S4, 0b0100111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 4 ), // #628 + INST(Smlsl_v , ISimdVVVe , (0b0000111000100000101000, kVO_V_B8H4S2, 0b0000111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 5 ), // #629 + INST(Smlsl2_v , ISimdVVVe , (0b0100111000100000101000, kVO_V_B16H8S4, 0b0100111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 6 ), // #630 + INST(Smmla_v , ISimdVVVx , (0b0100111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 14 ), // #631 + INST(Smov_v , SimdSmovUmov , (0b0000111000000000001011, kVO_V_BHS, 1) , kRWI_W , 0 , 0 ), // #632 + INST(Smull_v , ISimdVVVe , (0b0000111000100000110000, kVO_V_B8H4S2, 0b0000111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 7 ), // #633 + INST(Smull2_v , ISimdVVVe , (0b0100111000100000110000, kVO_V_B16H8S4, 0b0100111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 8 ), // #634 + INST(Sqabs_v , ISimdVV , (0b0000111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 13 ), // #635 + INST(Sqadd_v , ISimdVVV , (0b0000111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 32 ), // #636 + INST(Sqdmlal_v , ISimdVVVe , (0b0000111000100000100100, kVO_SV_BHS, 0b0000111100000000001100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 9 ), // #637 + INST(Sqdmlal2_v , ISimdVVVe , (0b0100111000100000100100, kVO_V_B16H8S4, 0b0100111100000000001100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 10 ), // #638 + INST(Sqdmlsl_v , ISimdVVVe , (0b0000111000100000101100, kVO_SV_BHS, 0b0000111100000000011100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 11 ), // #639 + INST(Sqdmlsl2_v , ISimdVVVe , (0b0100111000100000101100, kVO_V_B16H8S4, 0b0100111100000000011100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 12 ), // #640 + INST(Sqdmulh_v , ISimdVVVe , (0b0000111000100000101101, kVO_SV_HS, 0b0000111100000000110000, kVO_SV_HS) , kRWI_W , F(VH0_15) , 13 ), // #641 + INST(Sqdmull_v , ISimdVVVe , (0b0000111000100000110100, kVO_SV_BHS, 0b0000111100000000101100, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 14 ), // #642 + INST(Sqdmull2_v , ISimdVVVe , (0b0100111000100000110100, kVO_V_B16H8S4, 0b0100111100000000101100, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 15 ), // #643 + INST(Sqneg_v , ISimdVV , (0b0010111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 14 ), // #644 + INST(Sqrdmlah_v , ISimdVVVe , (0b0010111000000000100001, kVO_SV_HS, 0b0010111100000000110100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 16 ), // #645 + INST(Sqrdmlsh_v , ISimdVVVe , (0b0010111000000000100011, kVO_SV_HS, 0b0010111100000000111100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 17 ), // #646 + INST(Sqrdmulh_v , ISimdVVVe , (0b0010111000100000101101, kVO_SV_HS, 0b0000111100000000110100, kVO_SV_HS) , kRWI_W , F(VH0_15) , 18 ), // #647 + INST(Sqrshl_v , SimdShift , (0b0000111000100000010111, 0b0000000000000000000000, 1, kVO_SV_Any) , kRWI_W , 0 , 6 ), // #648 + INST(Sqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 7 ), // #649 + INST(Sqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 8 ), // #650 + INST(Sqrshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100011, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 9 ), // #651 + INST(Sqrshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 10 ), // #652 + INST(Sqshl_v , SimdShift , (0b0000111000100000010011, 0b0000111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 11 ), // #653 + INST(Sqshlu_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000011001, 0, kVO_SV_Any) , kRWI_W , 0 , 12 ), // #654 + INST(Sqshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 13 ), // #655 + INST(Sqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 ), // #656 + INST(Sqshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100001, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 ), // #657 + INST(Sqshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 ), // #658 + INST(Sqsub_v , ISimdVVV , (0b0000111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 33 ), // #659 + INST(Sqxtn_v , ISimdVV , (0b0000111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 ), // #660 + INST(Sqxtn2_v , ISimdVV , (0b0100111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 ), // #661 + INST(Sqxtun_v , ISimdVV , (0b0010111000100001001010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 17 ), // #662 + INST(Sqxtun2_v , ISimdVV , (0b0110111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 18 ), // #663 + INST(Srhadd_v , ISimdVVV , (0b0000111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 34 ), // #664 + INST(Sri_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010001, 1, kVO_V_Any) , kRWI_W , 0 , 17 ), // #665 + INST(Srshl_v , SimdShift , (0b0000111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 18 ), // #666 + INST(Srshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 19 ), // #667 + INST(Srsra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 20 ), // #668 + INST(Sshl_v , SimdShift , (0b0000111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 21 ), // #669 + INST(Sshll_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 ), // #670 + INST(Sshll2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 ), // #671 + INST(Sshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 24 ), // #672 + INST(Ssra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 25 ), // #673 + INST(Ssubl_v , ISimdVVV , (0b0000111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 35 ), // #674 + INST(Ssubl2_v , ISimdVVV , (0b0100111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 36 ), // #675 + INST(Ssubw_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 2 ), // #676 + INST(Ssubw2_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B16H8S4) , kRWI_X , 0 , 3 ), // #677 + INST(St1_v , SimdLdNStN , (0b0000110100000000000000, 0b0000110000000000001000, 1, 0) , kRWI_STn , F(Consecutive) , 8 ), // #678 + INST(St2_v , SimdLdNStN , (0b0000110100100000000000, 0b0000110000000000100000, 2, 0) , kRWI_STn , F(Consecutive) , 9 ), // #679 + INST(St3_v , SimdLdNStN , (0b0000110100000000001000, 0b0000110000000000010000, 3, 0) , kRWI_STn , F(Consecutive) , 10 ), // #680 + INST(St4_v , SimdLdNStN , (0b0000110100100000001000, 0b0000110000000000000000, 4, 0) , kRWI_STn , F(Consecutive) , 11 ), // #681 + INST(Stnp_v , SimdLdpStp , (0b0010110000, 0b0000000000) , kRWI_RRW , 0 , 2 ), // #682 + INST(Stp_v , SimdLdpStp , (0b0010110100, 0b0010110010) , kRWI_RRW , 0 , 3 ), // #683 + INST(Str_v , SimdLdSt , (0b0011110100, 0b00111100000, 0b00111100001, 0b00000000, Inst::kIdStur_v) , kRWI_RW , 0 , 1 ), // #684 + INST(Stur_v , SimdLdurStur , (0b0011110000000000000000) , kRWI_RW , 0 , 1 ), // #685 + INST(Sub_v , ISimdVVV , (0b0010111000100000100001, kVO_V_Any) , kRWI_W , 0 , 37 ), // #686 + INST(Subhn_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 38 ), // #687 + INST(Subhn2_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 39 ), // #688 + INST(Sudot_v , SimdDot , (0b0000000000000000000000, 0b0000111100000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 2 ), // #689 + INST(Suqadd_v , ISimdVV , (0b0000111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 19 ), // #690 + INST(Sxtl_v , SimdSxtlUxtl , (0b0000111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 ), // #691 + INST(Sxtl2_v , SimdSxtlUxtl , (0b0100111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 ), // #692 + INST(Tbl_v , SimdTblTbx , (0b0000111000000000000000) , kRWI_W , 0 , 0 ), // #693 + INST(Tbx_v , SimdTblTbx , (0b0000111000000000000100) , kRWI_W , 0 , 1 ), // #694 + INST(Trn1_v , ISimdVVV , (0b0000111000000000001010, kVO_V_BHS_D2) , kRWI_W , 0 , 40 ), // #695 + INST(Trn2_v , ISimdVVV , (0b0000111000000000011010, kVO_V_BHS_D2) , kRWI_W , 0 , 41 ), // #696 + INST(Uaba_v , ISimdVVV , (0b0010111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 42 ), // #697 + INST(Uabal_v , ISimdVVV , (0b0010111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 43 ), // #698 + INST(Uabal2_v , ISimdVVV , (0b0110111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 44 ), // #699 + INST(Uabd_v , ISimdVVV , (0b0010111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 45 ), // #700 + INST(Uabdl_v , ISimdVVV , (0b0010111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 46 ), // #701 + INST(Uabdl2_v , ISimdVVV , (0b0110111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 47 ), // #702 + INST(Uadalp_v , ISimdVV , (0b0010111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 20 ), // #703 + INST(Uaddl_v , ISimdVVV , (0b0010111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 48 ), // #704 + INST(Uaddl2_v , ISimdVVV , (0b0110111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 49 ), // #705 + INST(Uaddlp_v , ISimdVV , (0b0010111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 21 ), // #706 + INST(Uaddlv_v , ISimdSV , (0b0010111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 4 ), // #707 + INST(Uaddw_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 4 ), // #708 + INST(Uaddw2_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 5 ), // #709 + INST(Ucvtf_v , SimdFcvtSV , (0b0010111000100001110110, 0b0010111100000000111001, 0b0001111000100011000000, 0) , kRWI_W , 0 , 11 ), // #710 + INST(Udot_v , SimdDot , (0b0010111010000000100101, 0b0010111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 3 ), // #711 + INST(Uhadd_v , ISimdVVV , (0b0010111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 50 ), // #712 + INST(Uhsub_v , ISimdVVV , (0b0010111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 51 ), // #713 + INST(Umax_v , ISimdVVV , (0b0010111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 52 ), // #714 + INST(Umaxp_v , ISimdVVV , (0b0010111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 53 ), // #715 + INST(Umaxv_v , ISimdSV , (0b0010111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 5 ), // #716 + INST(Umin_v , ISimdVVV , (0b0010111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 54 ), // #717 + INST(Uminp_v , ISimdVVV , (0b0010111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 55 ), // #718 + INST(Uminv_v , ISimdSV , (0b0010111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 6 ), // #719 + INST(Umlal_v , ISimdVVVe , (0b0010111000100000100000, kVO_V_B8H4S2, 0b0010111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 19 ), // #720 + INST(Umlal2_v , ISimdVVVe , (0b0110111000100000100000, kVO_V_B16H8S4, 0b0010111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 20 ), // #721 + INST(Umlsl_v , ISimdVVVe , (0b0010111000100000101000, kVO_V_B8H4S2, 0b0010111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 21 ), // #722 + INST(Umlsl2_v , ISimdVVVe , (0b0110111000100000101000, kVO_V_B16H8S4, 0b0110111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 22 ), // #723 + INST(Ummla_v , ISimdVVVx , (0b0110111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 15 ), // #724 + INST(Umov_v , SimdSmovUmov , (0b0000111000000000001111, kVO_V_Any, 0) , kRWI_W , 0 , 1 ), // #725 + INST(Umull_v , ISimdVVVe , (0b0010111000100000110000, kVO_V_B8H4S2, 0b0010111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 23 ), // #726 + INST(Umull2_v , ISimdVVVe , (0b0110111000100000110000, kVO_V_B16H8S4, 0b0110111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 24 ), // #727 + INST(Uqadd_v , ISimdVVV , (0b0010111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 56 ), // #728 + INST(Uqrshl_v , SimdShift , (0b0010111000100000010111, 0b0000000000000000000000, 0, kVO_SV_Any) , kRWI_W , 0 , 26 ), // #729 + INST(Uqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 27 ), // #730 + INST(Uqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 ), // #731 + INST(Uqshl_v , SimdShift , (0b0010111000100000010011, 0b0010111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 29 ), // #732 + INST(Uqshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 30 ), // #733 + INST(Uqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 31 ), // #734 + INST(Uqsub_v , ISimdVVV , (0b0010111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 57 ), // #735 + INST(Uqxtn_v , ISimdVV , (0b0010111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 22 ), // #736 + INST(Uqxtn2_v , ISimdVV , (0b0110111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 23 ), // #737 + INST(Urecpe_v , ISimdVV , (0b0000111010100001110010, kVO_V_S) , kRWI_W , 0 , 24 ), // #738 + INST(Urhadd_v , ISimdVVV , (0b0010111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 58 ), // #739 + INST(Urshl_v , SimdShift , (0b0010111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 32 ), // #740 + INST(Urshr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 33 ), // #741 + INST(Ursqrte_v , ISimdVV , (0b0010111010100001110010, kVO_V_S) , kRWI_W , 0 , 25 ), // #742 + INST(Ursra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 34 ), // #743 + INST(Usdot_v , SimdDot , (0b0000111010000000100111, 0b0000111110000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 4 ), // #744 + INST(Ushl_v , SimdShift , (0b0010111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 35 ), // #745 + INST(Ushll_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 36 ), // #746 + INST(Ushll2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 37 ), // #747 + INST(Ushr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 38 ), // #748 + INST(Usmmla_v , ISimdVVVx , (0b0100111010000000101011, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 16 ), // #749 + INST(Usqadd_v , ISimdVV , (0b0010111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 26 ), // #750 + INST(Usra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 39 ), // #751 + INST(Usubl_v , ISimdVVV , (0b0010111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 59 ), // #752 + INST(Usubl2_v , ISimdVVV , (0b0110111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 60 ), // #753 + INST(Usubw_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 6 ), // #754 + INST(Usubw2_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B16H8S4) , kRWI_W , 0 , 7 ), // #755 + INST(Uxtl_v , SimdSxtlUxtl , (0b0010111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 2 ), // #756 + INST(Uxtl2_v , SimdSxtlUxtl , (0b0110111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 3 ), // #757 + INST(Uzp1_v , ISimdVVV , (0b0000111000000000000110, kVO_V_BHS_D2) , kRWI_W , 0 , 61 ), // #758 + INST(Uzp2_v , ISimdVVV , (0b0000111000000000010110, kVO_V_BHS_D2) , kRWI_W , 0 , 62 ), // #759 + INST(Xar_v , ISimdVVVI , (0b1100111001100000100011, kVO_V_D2, 6, 10, 0) , kRWI_W , 0 , 1 ), // #760 + INST(Xtn_v , ISimdVV , (0b0000111000100001001010, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 27 ), // #761 + INST(Xtn2_v , ISimdVV , (0b0100111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 ), // #762 + INST(Zip1_v , ISimdVVV , (0b0000111000000000001110, kVO_V_BHS_D2) , kRWI_W , 0 , 63 ), // #763 + INST(Zip2_v , ISimdVVV , (0b0000111000000000011110, kVO_V_BHS_D2) , kRWI_W , 0 , 64 ) // #764 // ${InstInfo:End} }; @@ -1132,8 +1124,8 @@ const BaseLdSt baseLdSt[9] = { { 0b1011100101, 0b10111000010, 0b10111000011, 0b00011000, kWX, 30, 2, Inst::kIdLdur }, // ldr { 0b0011100101, 0b00111000010, 0b00111000011, 0 , kW , 0 , 0, Inst::kIdLdurb }, // ldrb { 0b0111100101, 0b01111000010, 0b01111000011, 0 , kW , 0 , 1, Inst::kIdLdurh }, // ldrh - { 0b0011100111, 0b00111000100, 0b00111000101, 0 , kWX, 22, 0, Inst::kIdLdursb }, // ldrsb - { 0b0111100110, 0b01111000100, 0b01111000101, 0 , kWX, 22, 1, Inst::kIdLdursh }, // ldrsh + { 0b0011100111, 0b00111000100, 0b00111000111, 0 , kWX, 22, 0, Inst::kIdLdursb }, // ldrsb + { 0b0111100111, 0b01111000100, 0b01111000111, 0 , kWX, 22, 1, Inst::kIdLdursh }, // ldrsh { 0b1011100110, 0b10111000100, 0b10111000101, 0b10011000, kX , 0 , 2, Inst::kIdLdursw }, // ldrsw { 0b1011100100, 0b10111000000, 0b10111000001, 0 , kWX, 30, 2, Inst::kIdStur }, // str { 0b0011100100, 0b00111000000, 0b00111000001, 0 , kW , 30, 0, Inst::kIdSturb }, // strb @@ -1220,6 +1212,10 @@ const BaseOpImm baseOpImm[14] = { { 0b00000000000000000000000000000000, 16, 0 } // udf }; +const BasePrfm basePrfm[1] = { + { 0b11111000101, 0b1111100110, 0b11111000100, 0b11011000 } // prfm +}; + const BaseR baseR[10] = { { 0b11011010110000010011101111100000, kX, kZR, 0 }, // autdza { 0b11011010110000010011111111100000, kX, kZR, 0 }, // autdzb @@ -1275,7 +1271,7 @@ const BaseRM_SImm9 baseRM_SImm9[23] = { { 0b0111100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // ldurh { 0b0011100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0 }, // ldursb { 0b0111100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0 }, // ldursh - { 0b1011100010000000000000, 0b0000000000000000000000, kWX, kZR, 0 , 0 }, // ldursw + { 0b1011100010000000000000, 0b0000000000000000000000, kX , kZR, 0 , 0 }, // ldursw { 0b1101100110100000000010, 0b1101100110100000000001, kX, kSP, 0, 4 }, // st2g { 0b1101100100100000000010, 0b1101100100100000000001, kX, kSP, 0, 4 }, // stg { 0b1011100000000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0 }, // sttr @@ -1852,75 +1848,10 @@ const InstDB::CommonInfo InstDB::commonData[] = { // ArmUtil - Id <-> Name // ===================== -#ifndef ASMJIT_DISABLE_TEXT +#ifndef ASMJIT_NO_TEXT // ${NameData:Begin} // ------------------- Automatically generated, do not edit ------------------- -const char InstDB::_nameData[] = - "\0" "adc\0" "adcs\0" "addg\0" "adds\0" "addv\0" "adr\0" "adrp\0" "aesd\0" "aese\0" "aesimc\0" "aesmc\0" "and\0" - "ands\0" "asr\0" "asrv\0" "at\0" "autda\0" "autdb\0" "autdza\0" "autdzb\0" "autia\0" "autia1716\0" "autiasp\0" - "autiaz\0" "autib\0" "autib1716\0" "autibsp\0" "autibz\0" "autiza\0" "autizb\0" "axflag\0" "bcax\0" "bfc\0" "bfcvt\0" - "bfcvtn\0" "bfcvtn2\0" "bfdot\0" "bfi\0" "bfmlalb\0" "bfmlalt\0" "bfmmla\0" "bfxil\0" "bic\0" "bics\0" "bif\0" - "blr\0" "br\0" "brk\0" "bsl\0" "cas\0" "casa\0" "casab\0" "casah\0" "casal\0" "casalb\0" "casalh\0" "casb\0" "cash\0" - "casl\0" "caslb\0" "caslh\0" "casp\0" "caspa\0" "caspal\0" "caspl\0" "cbnz\0" "cbz\0" "ccmn\0" "cfinv\0" "cinc\0" - "cinv\0" "clrex\0" "cls\0" "clz\0" "cmhi\0" "cmhs\0" "cmpp\0" "cmtst\0" "cneg\0" "cnt\0" "crc32b\0" "crc32cb\0" - "crc32ch\0" "crc32cw\0" "crc32cx\0" "crc32h\0" "crc32w\0" "crc32x\0" "csdb\0" "cset\0" "csetm\0" "csinc\0" "csinv\0" - "csneg\0" "dcps1\0" "dcps2\0" "dcps3\0" "dgh\0" "dmb\0" "drps\0" "dsb\0" "dup\0" "eon\0" "eor3\0" "eret\0" "esb\0" - "ext\0" "extr\0" "fabd\0" "fabs\0" "facge\0" "facgt\0" "fadd\0" "faddp\0" "fcadd\0" "fccmp\0" "fccmpe\0" "fcmeq\0" - "fcmge\0" "fcmgt\0" "fcmla\0" "fcmle\0" "fcmlt\0" "fcmp\0" "fcmpe\0" "fcsel\0" "fcvtas\0" "fcvtau\0" "fcvtl\0" - "fcvtl2\0" "fcvtms\0" "fcvtmu\0" "fcvtns\0" "fcvtnu\0" "fcvtps\0" "fcvtpu\0" "fcvtxn\0" "fcvtxn2\0" "fcvtzs\0" - "fcvtzu\0" "fdiv\0" "fjcvtzs\0" "fmadd\0" "fmax\0" "fmaxnm\0" "fmaxnmp\0" "fmaxnmv\0" "fmaxp\0" "fmaxv\0" "fmin\0" - "fminnm\0" "fminnmp\0" "fminnmv\0" "fminp\0" "fminv\0" "fmla\0" "fmlal\0" "fmlal2\0" "fmls\0" "fmlsl\0" "fmlsl2\0" - "fmov\0" "fmsub\0" "fmul\0" "fmulx\0" "fneg\0" "fnmadd\0" "fnmsub\0" "fnmul\0" "frecpe\0" "frecps\0" "frecpx\0" - "frint32x\0" "frint32z\0" "frint64x\0" "frint64z\0" "frinta\0" "frinti\0" "frintm\0" "frintn\0" "frintp\0" "frintx\0" - "frintz\0" "frsqrte\0" "frsqrts\0" "fsqrt\0" "fsub\0" "gmi\0" "hint\0" "hlt\0" "hvc\0" "ins\0" "isb\0" "ld1\0" - "ld1r\0" "ld2\0" "ld2r\0" "ld3\0" "ld3r\0" "ld4\0" "ld4r\0" "ldadd\0" "ldadda\0" "ldaddab\0" "ldaddah\0" "ldaddal\0" - "ldaddalb\0" "ldaddalh\0" "ldaddb\0" "ldaddh\0" "ldaddl\0" "ldaddlb\0" "ldaddlh\0" "ldar\0" "ldarb\0" "ldarh\0" - "ldaxp\0" "ldaxr\0" "ldaxrb\0" "ldaxrh\0" "ldclr\0" "ldclra\0" "ldclrab\0" "ldclrah\0" "ldclral\0" "ldclralb\0" - "ldclralh\0" "ldclrb\0" "ldclrh\0" "ldclrl\0" "ldclrlb\0" "ldclrlh\0" "ldeor\0" "ldeora\0" "ldeorab\0" "ldeorah\0" - "ldeoral\0" "ldeoralb\0" "ldeoralh\0" "ldeorb\0" "ldeorh\0" "ldeorl\0" "ldeorlb\0" "ldeorlh\0" "ldg\0" "ldgm\0" - "ldlar\0" "ldlarb\0" "ldlarh\0" "ldnp\0" "ldp\0" "ldpsw\0" "ldr\0" "ldraa\0" "ldrab\0" "ldrb\0" "ldrh\0" "ldrsb\0" - "ldrsh\0" "ldrsw\0" "ldset\0" "ldseta\0" "ldsetab\0" "ldsetah\0" "ldsetal\0" "ldsetalb\0" "ldsetalh\0" "ldsetb\0" - "ldseth\0" "ldsetl\0" "ldsetlb\0" "ldsetlh\0" "ldsmax\0" "ldsmaxa\0" "ldsmaxab\0" "ldsmaxah\0" "ldsmaxal\0" - "ldsmaxalb\0" "ldsmaxalh\0" "ldsmaxb\0" "ldsmaxh\0" "ldsmaxl\0" "ldsmaxlb\0" "ldsmaxlh\0" "ldsmin\0" "ldsmina\0" - "ldsminab\0" "ldsminah\0" "ldsminal\0" "ldsminalb\0" "ldsminalh\0" "ldsminb\0" "ldsminh\0" "ldsminl\0" "ldsminlb\0" - "ldsminlh\0" "ldtr\0" "ldtrb\0" "ldtrh\0" "ldtrsb\0" "ldtrsh\0" "ldtrsw\0" "ldumax\0" "ldumaxa\0" "ldumaxab\0" - "ldumaxah\0" "ldumaxal\0" "ldumaxalb\0" "ldumaxalh\0" "ldumaxb\0" "ldumaxh\0" "ldumaxl\0" "ldumaxlb\0" "ldumaxlh\0" - "ldumin\0" "ldumina\0" "lduminab\0" "lduminah\0" "lduminal\0" "lduminalb\0" "lduminalh\0" "lduminb\0" "lduminh\0" - "lduminl\0" "lduminlb\0" "lduminlh\0" "ldur\0" "ldurb\0" "ldurh\0" "ldursb\0" "ldursh\0" "ldursw\0" "ldxp\0" "ldxr\0" - "ldxrb\0" "ldxrh\0" "lslv\0" "lsr\0" "lsrv\0" "mneg\0" "movi\0" "movk\0" "movn\0" "movz\0" "mrs\0" "msr\0" "mvn\0" - "mvni\0" "negs\0" "ngc\0" "ngcs\0" "nop\0" "not\0" "orn\0" "orr\0" "pacda\0" "pacdb\0" "pacdza\0" "pacdzb\0" - "pacga\0" "pmul\0" "pmull\0" "pmull2\0" "pssbb\0" "raddhn\0" "raddhn2\0" "rax1\0" "rbit\0" "rev\0" "rev16\0" - "rev32\0" "rev64\0" "ror\0" "rorv\0" "rsubhn\0" "rsubhn2\0" "saba\0" "sabal\0" "sabal2\0" "sabd\0" "sabdl\0" - "sabdl2\0" "sadalp\0" "saddl\0" "saddl2\0" "saddlp\0" "saddlv\0" "saddw\0" "saddw2\0" "sbc\0" "sbcs\0" "sbfiz\0" - "sbfm\0" "sbfx\0" "scvtf\0" "sdiv\0" "setf16\0" "setf8\0" "sev\0" "sevl\0" "sha1c\0" "sha1h\0" "sha1m\0" "sha1p\0" - "sha1su0\0" "sha1su1\0" "sha256h\0" "sha256h2\0" "sha256su0\0" "sha256su1\0" "sha512h\0" "sha512h2\0" "sha512su0\0" - "sha512su1\0" "shadd\0" "shsub\0" "sli\0" "sm3partw1\0" "sm3partw2\0" "sm3ss1\0" "sm3tt1a\0" "sm3tt1b\0" "sm3tt2a\0" - "sm3tt2b\0" "sm4e\0" "sm4ekey\0" "smaddl\0" "smaxp\0" "smaxv\0" "sminp\0" "sminv\0" "smlal\0" "smlal2\0" "smlsl\0" - "smlsl2\0" "smnegl\0" "smov\0" "smsubl\0" "smulh\0" "smull\0" "smull2\0" "sqabs\0" "sqdmlal\0" "sqdmlal2\0" - "sqdmlsl\0" "sqdmlsl2\0" "sqdmulh\0" "sqdmull\0" "sqdmull2\0" "sqneg\0" "sqrdmlah\0" "sqrdmlsh\0" "sqrdmulh\0" - "sqrshl\0" "sqrshrn\0" "sqrshrn2\0" "sqrshrun\0" "sqrshrun2\0" "sqshl\0" "sqshlu\0" "sqshrn\0" "sqshrn2\0" - "sqshrun\0" "sqshrun2\0" "sqsub\0" "sqxtn\0" "sqxtn2\0" "sqxtun\0" "sqxtun2\0" "srhadd\0" "sri\0" "srshl\0" "srshr\0" - "srsra\0" "sshl\0" "sshll\0" "sshll2\0" "sshr\0" "ssra\0" "ssubl\0" "ssubl2\0" "ssubw\0" "ssubw2\0" "st1\0" "st2\0" - "st2g\0" "st3\0" "st4\0" "stadd\0" "staddb\0" "staddh\0" "staddl\0" "staddlb\0" "staddlh\0" "stclr\0" "stclrb\0" - "stclrh\0" "stclrl\0" "stclrlb\0" "stclrlh\0" "steor\0" "steorb\0" "steorh\0" "steorl\0" "steorlb\0" "steorlh\0" - "stg\0" "stgm\0" "stgp\0" "stllr\0" "stllrb\0" "stllrh\0" "stlr\0" "stlrb\0" "stlrh\0" "stlxp\0" "stlxr\0" "stlxrb\0" - "stlxrh\0" "stnp\0" "stp\0" "str\0" "strb\0" "strh\0" "stset\0" "stsetb\0" "stseth\0" "stsetl\0" "stsetlb\0" - "stsetlh\0" "stsmax\0" "stsmaxb\0" "stsmaxh\0" "stsmaxl\0" "stsmaxlb\0" "stsmaxlh\0" "stsmin\0" "stsminb\0" - "stsminh\0" "stsminl\0" "stsminlb\0" "stsminlh\0" "sttr\0" "sttrb\0" "sttrh\0" "stumax\0" "stumaxb\0" "stumaxh\0" - "stumaxl\0" "stumaxlb\0" "stumaxlh\0" "stumin\0" "stuminb\0" "stuminh\0" "stuminl\0" "stuminlb\0" "stuminlh\0" - "stur\0" "sturb\0" "sturh\0" "stxp\0" "stxr\0" "stxrb\0" "stxrh\0" "stz2g\0" "stzg\0" "stzgm\0" "subg\0" "subp\0" - "subps\0" "subs\0" "sudot\0" "suqadd\0" "svc\0" "swp\0" "swpa\0" "swpab\0" "swpah\0" "swpal\0" "swpalb\0" "swpalh\0" - "swpb\0" "swph\0" "swpl\0" "swplb\0" "swplh\0" "sxtb\0" "sxth\0" "sxtl\0" "sxtl2\0" "sxtw\0" "sys\0" "tbl\0" "tbnz\0" - "tbx\0" "tbz\0" "tlbi\0" "trn1\0" "trn2\0" "uaba\0" "uabal\0" "uabal2\0" "uabd\0" "uabdl\0" "uabdl2\0" "uadalp\0" - "uaddl\0" "uaddl2\0" "uaddlp\0" "uaddlv\0" "uaddw\0" "uaddw2\0" "ubfiz\0" "ubfm\0" "ubfx\0" "ucvtf\0" "udf\0" - "udiv\0" "uhadd\0" "uhsub\0" "umaddl\0" "umaxp\0" "umaxv\0" "uminp\0" "uminv\0" "umlal\0" "umlal2\0" "umlsl\0" - "umlsl2\0" "ummla\0" "umnegl\0" "umov\0" "umsubl\0" "umulh\0" "umull\0" "umull2\0" "uqrshl\0" "uqrshrn\0" - "uqrshrn2\0" "uqshl\0" "uqshrn\0" "uqshrn2\0" "uqsub\0" "uqxtn\0" "uqxtn2\0" "urecpe\0" "urhadd\0" "urshl\0" - "urshr\0" "ursqrte\0" "ursra\0" "usdot\0" "ushl\0" "ushll\0" "ushll2\0" "ushr\0" "usmmla\0" "usqadd\0" "usra\0" - "usubl\0" "usubl2\0" "usubw\0" "usubw2\0" "uxtb\0" "uxth\0" "uxtl\0" "uxtl2\0" "uzp1\0" "uzp2\0" "wfe\0" "wfi\0" - "xaflag\0" "xar\0" "xpacd\0" "xpaci\0" "xpaclri\0" "yield\0" "zip1\0" "zip2"; - -const InstDB::InstNameIndex InstDB::instNameIndex[26] = { +const InstNameIndex InstDB::instNameIndex = {{ { Inst::kIdAdc , Inst::kIdAnd_v + 1 }, { Inst::kIdB , Inst::kIdBsl_v + 1 }, { Inst::kIdCas , Inst::kIdCnt_v + 1 }, @@ -1947,10 +1878,785 @@ const InstDB::InstNameIndex InstDB::instNameIndex[26] = { { Inst::kIdXaflag , Inst::kIdXtn2_v + 1 }, { Inst::kIdYield , Inst::kIdYield + 1 }, { Inst::kIdZip1_v , Inst::kIdZip2_v + 1 } +}, uint16_t(9)}; + +const char InstDB::_instNameStringTable[] = + "autia1716autibldsmaxalhldsminalldumaxallduminalsha256su0sha512su1sm3partwsqrshru" + "nldaddalldclralldeoralldsetallbstsmaxstsminstumaxstuminfrint32z64x64zh2sqdmlalsl" + "2sqdmulsqrdmlaulhn2sqshruuqrshrspcrc32cstaddstclrsteorstsetxpaclbfcvtbfmlaltfcvt" + "xfjcvtzfmaxnmfminnmfrsqrraddrsubsha1sm3tt12a2bsm4ekeysqxtuuqshrursqrsetfrev8"; + + +const uint32_t InstDB::_instNameIndexTable[] = { + 0x80000000, // Small ''. + 0x80000C81, // Small 'adc'. + 0x80098C81, // Small 'adcs'. + 0x80001081, // Small 'add'. + 0x80039081, // Small 'addg'. + 0x80099081, // Small 'adds'. + 0x80004881, // Small 'adr'. + 0x80084881, // Small 'adrp'. + 0x800011C1, // Small 'and'. + 0x800991C1, // Small 'ands'. + 0x80004A61, // Small 'asr'. + 0x800B4A61, // Small 'asrv'. + 0x80000281, // Small 'at'. + 0x801252A1, // Small 'autda'. + 0x83A252A1, // Small 'autdza'. + 0x802252A1, // Small 'autdb'. + 0x85A252A1, // Small 'autdzb'. + 0x8014D2A1, // Small 'autia'. + 0x00009000, // Large 'autia1716'. + 0x20BF5000, // Large 'autia|sp'. + 0xB414D2A1, // Small 'autiaz'. + 0x8024D2A1, // Small 'autib'. + 0x40055009, // Large 'autib|1716'. + 0x20BF5009, // Large 'autib|sp'. + 0xB424D2A1, // Small 'autibz'. + 0x83A4D2A1, // Small 'autiza'. + 0x85A4D2A1, // Small 'autizb'. + 0x8E161B01, // Small 'axflag'. + 0x80000002, // Small 'b'. + 0x80000CC2, // Small 'bfc'. + 0x800024C2, // Small 'bfi'. + 0x800034C2, // Small 'bfm'. + 0x80C4E0C2, // Small 'bfxil'. + 0x80000D22, // Small 'bic'. + 0x80098D22, // Small 'bics'. + 0x80000182, // Small 'bl'. + 0x80004982, // Small 'blr'. + 0x80000242, // Small 'br'. + 0x80002E42, // Small 'brk'. + 0x80004C23, // Small 'cas'. + 0x8000CC23, // Small 'casa'. + 0x8020CC23, // Small 'casab'. + 0x8080CC23, // Small 'casah'. + 0x80C0CC23, // Small 'casal'. + 0x84C0CC23, // Small 'casalb'. + 0x90C0CC23, // Small 'casalh'. + 0x80014C23, // Small 'casb'. + 0x80044C23, // Small 'cash'. + 0x80064C23, // Small 'casl'. + 0x80264C23, // Small 'caslb'. + 0x80864C23, // Small 'caslh'. + 0x80084C23, // Small 'casp'. + 0x80184C23, // Small 'caspa'. + 0x98184C23, // Small 'caspal'. + 0x80C84C23, // Small 'caspl'. + 0x800D3843, // Small 'cbnz'. + 0x80006843, // Small 'cbz'. + 0x80073463, // Small 'ccmn'. + 0x80083463, // Small 'ccmp'. + 0x816724C3, // Small 'cfinv'. + 0x8001B923, // Small 'cinc'. + 0x800B3923, // Small 'cinv'. + 0x8182C983, // Small 'clrex'. + 0x80004D83, // Small 'cls'. + 0x80006983, // Small 'clz'. + 0x800039A3, // Small 'cmn'. + 0x800041A3, // Small 'cmp'. + 0x800841A3, // Small 'cmpp'. + 0x800395C3, // Small 'cneg'. + 0x85DF0E43, // Small 'crc32b'. + 0x100D60C1, // Large 'crc32c|b'. + 0x101660C1, // Large 'crc32c|h'. + 0x104860C1, // Large 'crc32c|w'. + 0x101360C1, // Large 'crc32c|x'. + 0x91DF0E43, // Small 'crc32h'. + 0xAFDF0E43, // Small 'crc32w'. + 0xB1DF0E43, // Small 'crc32x'. + 0x80011263, // Small 'csdb'. + 0x80061663, // Small 'csel'. + 0x800A1663, // Small 'cset'. + 0x80DA1663, // Small 'csetm'. + 0x80372663, // Small 'csinc'. + 0x81672663, // Small 'csinv'. + 0x8072BA63, // Small 'csneg'. + 0x80000064, // Small 'dc'. + 0x81C9C064, // Small 'dcps1'. + 0x81D9C064, // Small 'dcps2'. + 0x81E9C064, // Small 'dcps3'. + 0x800020E4, // Small 'dgh'. + 0x800009A4, // Small 'dmb'. + 0x8009C244, // Small 'drps'. + 0x80000A64, // Small 'dsb'. + 0x800039E5, // Small 'eon'. + 0x800049E5, // Small 'eor'. + 0x80000A65, // Small 'esb'. + 0x80095305, // Small 'extr'. + 0x800A1645, // Small 'eret'. + 0x800025A7, // Small 'gmi'. + 0x800A3928, // Small 'hint'. + 0x80005188, // Small 'hlt'. + 0x80000EC8, // Small 'hvc'. + 0x80000069, // Small 'ic'. + 0x80000A69, // Small 'isb'. + 0x8042048C, // Small 'ldadd'. + 0x8242048C, // Small 'ldadda'. + 0x100D6051, // Large 'ldadda|b'. + 0x10166051, // Large 'ldadda|h'. + 0x00007051, // Large 'ldaddal'. + 0x100D7051, // Large 'ldaddal|b'. + 0x10167051, // Large 'ldaddal|h'. + 0x8442048C, // Small 'ldaddb'. + 0x9042048C, // Small 'ldaddh'. + 0x9842048C, // Small 'ldaddl'. + 0x206D5051, // Large 'ldadd|lb'. + 0x20155051, // Large 'ldadd|lh'. + 0x8009048C, // Small 'ldar'. + 0x8029048C, // Small 'ldarb'. + 0x8089048C, // Small 'ldarh'. + 0x810C048C, // Small 'ldaxp'. + 0x812C048C, // Small 'ldaxr'. + 0x852C048C, // Small 'ldaxrb'. + 0x912C048C, // Small 'ldaxrh'. + 0x81260C8C, // Small 'ldclr'. + 0x83260C8C, // Small 'ldclra'. + 0x100D6058, // Large 'ldclra|b'. + 0x10166058, // Large 'ldclra|h'. + 0x00007058, // Large 'ldclral'. + 0x100D7058, // Large 'ldclral|b'. + 0x10167058, // Large 'ldclral|h'. + 0x85260C8C, // Small 'ldclrb'. + 0x91260C8C, // Small 'ldclrh'. + 0x99260C8C, // Small 'ldclrl'. + 0x206D5058, // Large 'ldclr|lb'. + 0x20155058, // Large 'ldclr|lh'. + 0x8127948C, // Small 'ldeor'. + 0x8327948C, // Small 'ldeora'. + 0x100D605F, // Large 'ldeora|b'. + 0x1016605F, // Large 'ldeora|h'. + 0x0000705F, // Large 'ldeoral'. + 0x100D705F, // Large 'ldeoral|b'. + 0x1016705F, // Large 'ldeoral|h'. + 0x8527948C, // Small 'ldeorb'. + 0x9127948C, // Small 'ldeorh'. + 0x9927948C, // Small 'ldeorl'. + 0x206D505F, // Large 'ldeor|lb'. + 0x2015505F, // Large 'ldeor|lh'. + 0x80001C8C, // Small 'ldg'. + 0x80069C8C, // Small 'ldgm'. + 0x8120B08C, // Small 'ldlar'. + 0x8520B08C, // Small 'ldlarb'. + 0x9120B08C, // Small 'ldlarh'. + 0x8008388C, // Small 'ldnp'. + 0x8000408C, // Small 'ldp'. + 0x8179C08C, // Small 'ldpsw'. + 0x8000488C, // Small 'ldr'. + 0x8010C88C, // Small 'ldraa'. + 0x8020C88C, // Small 'ldrab'. + 0x8001488C, // Small 'ldrb'. + 0x8004488C, // Small 'ldrh'. + 0x8029C88C, // Small 'ldrsb'. + 0x8089C88C, // Small 'ldrsh'. + 0x8179C88C, // Small 'ldrsw'. + 0x8142CC8C, // Small 'ldset'. + 0x8342CC8C, // Small 'ldseta'. + 0x100D6066, // Large 'ldseta|b'. + 0x10166066, // Large 'ldseta|h'. + 0x00007066, // Large 'ldsetal'. + 0x100D7066, // Large 'ldsetal|b'. + 0x10167066, // Large 'ldsetal|h'. + 0x8542CC8C, // Small 'ldsetb'. + 0x9142CC8C, // Small 'ldseth'. + 0x9942CC8C, // Small 'ldsetl'. + 0x206D5066, // Large 'ldset|lb'. + 0x20155066, // Large 'ldset|lh'. + 0xB016CC8C, // Small 'ldsmax'. + 0x0000700E, // Large 'ldsmaxa'. + 0x100D700E, // Large 'ldsmaxa|b'. + 0x1016700E, // Large 'ldsmaxa|h'. + 0x0000800E, // Large 'ldsmaxal'. + 0x100D800E, // Large 'ldsmaxal|b'. + 0x1016800E, // Large 'ldsmaxal|h'. + 0x100D600E, // Large 'ldsmax|b'. + 0x1016600E, // Large 'ldsmax|h'. + 0x100E600E, // Large 'ldsmax|l'. + 0x206D600E, // Large 'ldsmax|lb'. + 0x2015600E, // Large 'ldsmax|lh'. + 0x9C96CC8C, // Small 'ldsmin'. + 0x00007017, // Large 'ldsmina'. + 0x100D7017, // Large 'ldsmina|b'. + 0x10167017, // Large 'ldsmina|h'. + 0x00008017, // Large 'ldsminal'. + 0x100D8017, // Large 'ldsminal|b'. + 0x10168017, // Large 'ldsminal|h'. + 0x100D6017, // Large 'ldsmin|b'. + 0x10166017, // Large 'ldsmin|h'. + 0x100E6017, // Large 'ldsmin|l'. + 0x206D6017, // Large 'ldsmin|lb'. + 0x20156017, // Large 'ldsmin|lh'. + 0x8009508C, // Small 'ldtr'. + 0x8029508C, // Small 'ldtrb'. + 0x8089508C, // Small 'ldtrh'. + 0x8539508C, // Small 'ldtrsb'. + 0x9139508C, // Small 'ldtrsh'. + 0xAF39508C, // Small 'ldtrsw'. + 0xB016D48C, // Small 'ldumax'. + 0x0000701F, // Large 'ldumaxa'. + 0x100D701F, // Large 'ldumaxa|b'. + 0x1016701F, // Large 'ldumaxa|h'. + 0x0000801F, // Large 'ldumaxal'. + 0x100D801F, // Large 'ldumaxal|b'. + 0x1016801F, // Large 'ldumaxal|h'. + 0x100D601F, // Large 'ldumax|b'. + 0x1016601F, // Large 'ldumax|h'. + 0x100E601F, // Large 'ldumax|l'. + 0x206D601F, // Large 'ldumax|lb'. + 0x2015601F, // Large 'ldumax|lh'. + 0x9C96D48C, // Small 'ldumin'. + 0x00007027, // Large 'ldumina'. + 0x100D7027, // Large 'ldumina|b'. + 0x10167027, // Large 'ldumina|h'. + 0x00008027, // Large 'lduminal'. + 0x100D8027, // Large 'lduminal|b'. + 0x10168027, // Large 'lduminal|h'. + 0x100D6027, // Large 'ldumin|b'. + 0x10166027, // Large 'ldumin|h'. + 0x100E6027, // Large 'ldumin|l'. + 0x206D6027, // Large 'ldumin|lb'. + 0x20156027, // Large 'ldumin|lh'. + 0x8009548C, // Small 'ldur'. + 0x8029548C, // Small 'ldurb'. + 0x8089548C, // Small 'ldurh'. + 0x8539548C, // Small 'ldursb'. + 0x9139548C, // Small 'ldursh'. + 0xAF39548C, // Small 'ldursw'. + 0x8008608C, // Small 'ldxp'. + 0x8009608C, // Small 'ldxr'. + 0x8029608C, // Small 'ldxrb'. + 0x8089608C, // Small 'ldxrh'. + 0x8000326C, // Small 'lsl'. + 0x800B326C, // Small 'lslv'. + 0x80004A6C, // Small 'lsr'. + 0x800B4A6C, // Small 'lsrv'. + 0x8002102D, // Small 'madd'. + 0x800395CD, // Small 'mneg'. + 0x800059ED, // Small 'mov'. + 0x8005D9ED, // Small 'movk'. + 0x800759ED, // Small 'movn'. + 0x800D59ED, // Small 'movz'. + 0x80004E4D, // Small 'mrs'. + 0x80004A6D, // Small 'msr'. + 0x8001566D, // Small 'msub'. + 0x800032AD, // Small 'mul'. + 0x80003ACD, // Small 'mvn'. + 0x80001CAE, // Small 'neg'. + 0x80099CAE, // Small 'negs'. + 0x80000CEE, // Small 'ngc'. + 0x80098CEE, // Small 'ngcs'. + 0x800041EE, // Small 'nop'. + 0x80003A4F, // Small 'orn'. + 0x80004A4F, // Small 'orr'. + 0x80120C30, // Small 'pacda'. + 0x80220C30, // Small 'pacdb'. + 0x83A20C30, // Small 'pacdza'. + 0x85A20C30, // Small 'pacdzb'. + 0x80138C30, // Small 'pacga'. + 0x80069A50, // Small 'prfm'. + 0x80214E70, // Small 'pssbb'. + 0x800A2452, // Small 'rbit'. + 0x800050B2, // Small 'ret'. + 0x800058B2, // Small 'rev'. + 0x20073138, // Large 'rev|16'. + 0x81DF58B2, // Small 'rev32'. + 0x208F3138, // Large 'rev|64'. + 0x800049F2, // Small 'ror'. + 0x800B49F2, // Small 'rorv'. + 0x80000C53, // Small 'sbc'. + 0x80098C53, // Small 'sbcs'. + 0x81A49853, // Small 'sbfiz'. + 0x80069853, // Small 'sbfm'. + 0x800C1853, // Small 'sbfx'. + 0x800B2493, // Small 'sdiv'. + 0x113B4134, // Large 'setf|8'. + 0x20074134, // Large 'setf|16'. + 0x800058B3, // Small 'sev'. + 0x800658B3, // Small 'sevl'. + 0x984205B3, // Small 'smaddl'. + 0x80000DB3, // Small 'smc'. + 0x9872B9B3, // Small 'smnegl'. + 0x982ACDB3, // Small 'smsubl'. + 0x808655B3, // Small 'smulh'. + 0x80C655B3, // Small 'smull'. + 0x80010A73, // Small 'ssbb'. + 0x8003F693, // Small 'st2g'. + 0x80420693, // Small 'stadd'. + 0x98420693, // Small 'staddl'. + 0x84420693, // Small 'staddb'. + 0x206D50C7, // Large 'stadd|lb'. + 0x90420693, // Small 'staddh'. + 0x201550C7, // Large 'stadd|lh'. + 0x81260E93, // Small 'stclr'. + 0x99260E93, // Small 'stclrl'. + 0x85260E93, // Small 'stclrb'. + 0x206D50CC, // Large 'stclr|lb'. + 0x91260E93, // Small 'stclrh'. + 0x201550CC, // Large 'stclr|lh'. + 0x81279693, // Small 'steor'. + 0x99279693, // Small 'steorl'. + 0x85279693, // Small 'steorb'. + 0x206D50D1, // Large 'steor|lb'. + 0x91279693, // Small 'steorh'. + 0x201550D1, // Large 'steor|lh'. + 0x80001E93, // Small 'stg'. + 0x80069E93, // Small 'stgm'. + 0x80081E93, // Small 'stgp'. + 0x81263293, // Small 'stllr'. + 0x85263293, // Small 'stllrb'. + 0x91263293, // Small 'stllrh'. + 0x80093293, // Small 'stlr'. + 0x80293293, // Small 'stlrb'. + 0x80893293, // Small 'stlrh'. + 0x810C3293, // Small 'stlxp'. + 0x812C3293, // Small 'stlxr'. + 0x852C3293, // Small 'stlxrb'. + 0x912C3293, // Small 'stlxrh'. + 0x80083A93, // Small 'stnp'. + 0x80004293, // Small 'stp'. + 0x80004A93, // Small 'str'. + 0x80014A93, // Small 'strb'. + 0x80044A93, // Small 'strh'. + 0x8142CE93, // Small 'stset'. + 0x9942CE93, // Small 'stsetl'. + 0x8542CE93, // Small 'stsetb'. + 0x206D50D6, // Large 'stset|lb'. + 0x9142CE93, // Small 'stseth'. + 0x201550D6, // Large 'stset|lh'. + 0xB016CE93, // Small 'stsmax'. + 0x100E606F, // Large 'stsmax|l'. + 0x100D606F, // Large 'stsmax|b'. + 0x206D606F, // Large 'stsmax|lb'. + 0x1016606F, // Large 'stsmax|h'. + 0x2015606F, // Large 'stsmax|lh'. + 0x9C96CE93, // Small 'stsmin'. + 0x100E6075, // Large 'stsmin|l'. + 0x100D6075, // Large 'stsmin|b'. + 0x206D6075, // Large 'stsmin|lb'. + 0x10166075, // Large 'stsmin|h'. + 0x20156075, // Large 'stsmin|lh'. + 0x80095293, // Small 'sttr'. + 0x80295293, // Small 'sttrb'. + 0x80895293, // Small 'sttrh'. + 0xB016D693, // Small 'stumax'. + 0x100E607B, // Large 'stumax|l'. + 0x100D607B, // Large 'stumax|b'. + 0x206D607B, // Large 'stumax|lb'. + 0x1016607B, // Large 'stumax|h'. + 0x2015607B, // Large 'stumax|lh'. + 0x9C96D693, // Small 'stumin'. + 0x100E6081, // Large 'stumin|l'. + 0x100D6081, // Large 'stumin|b'. + 0x206D6081, // Large 'stumin|lb'. + 0x10166081, // Large 'stumin|h'. + 0x20156081, // Large 'stumin|lh'. + 0x80095693, // Small 'stur'. + 0x80295693, // Small 'sturb'. + 0x80895693, // Small 'sturh'. + 0x80086293, // Small 'stxp'. + 0x80096293, // Small 'stxr'. + 0x80296293, // Small 'stxrb'. + 0x80896293, // Small 'stxrh'. + 0x807EEA93, // Small 'stz2g'. + 0x8003EA93, // Small 'stzg'. + 0x80D3EA93, // Small 'stzgm'. + 0x80000AB3, // Small 'sub'. + 0x80038AB3, // Small 'subg'. + 0x80080AB3, // Small 'subp'. + 0x81380AB3, // Small 'subps'. + 0x80098AB3, // Small 'subs'. + 0x80000ED3, // Small 'svc'. + 0x800042F3, // Small 'swp'. + 0x8000C2F3, // Small 'swpa'. + 0x8020C2F3, // Small 'swpab'. + 0x8080C2F3, // Small 'swpah'. + 0x80C0C2F3, // Small 'swpal'. + 0x84C0C2F3, // Small 'swpalb'. + 0x90C0C2F3, // Small 'swpalh'. + 0x800142F3, // Small 'swpb'. + 0x800442F3, // Small 'swph'. + 0x800642F3, // Small 'swpl'. + 0x802642F3, // Small 'swplb'. + 0x808642F3, // Small 'swplh'. + 0x80015313, // Small 'sxtb'. + 0x80045313, // Small 'sxth'. + 0x800BD313, // Small 'sxtw'. + 0x80004F33, // Small 'sys'. + 0x80048994, // Small 'tlbi'. + 0x80005274, // Small 'tst'. + 0x800D3854, // Small 'tbnz'. + 0x80006854, // Small 'tbz'. + 0x81A49855, // Small 'ubfiz'. + 0x80069855, // Small 'ubfm'. + 0x800C1855, // Small 'ubfx'. + 0x80001895, // Small 'udf'. + 0x800B2495, // Small 'udiv'. + 0x984205B5, // Small 'umaddl'. + 0x9872B9B5, // Small 'umnegl'. + 0x80C655B5, // Small 'umull'. + 0x808655B5, // Small 'umulh'. + 0x982ACDB5, // Small 'umsubl'. + 0x80015315, // Small 'uxtb'. + 0x80045315, // Small 'uxth'. + 0x800014D7, // Small 'wfe'. + 0x800024D7, // Small 'wfi'. + 0x8E161838, // Small 'xaflag'. + 0x80418618, // Small 'xpacd'. + 0x80918618, // Small 'xpaci'. + 0x208850DB, // Large 'xpacl|ri'. + 0x80461539, // Small 'yield'. + 0x80004C41, // Small 'abs'. + 0x80001081, // Small 'add'. + 0x80E41081, // Small 'addhn'. + 0xBAE41081, // Small 'addhn2'. + 0x80081081, // Small 'addp'. + 0x800B1081, // Small 'addv'. + 0x80024CA1, // Small 'aesd'. + 0x8002CCA1, // Small 'aese'. + 0x86D4CCA1, // Small 'aesimc'. + 0x8036CCA1, // Small 'aesmc'. + 0x800011C1, // Small 'and'. + 0x800C0462, // Small 'bcax'. + 0x814B0CC2, // Small 'bfcvt'. + 0x9D4B0CC2, // Small 'bfcvtn'. + 0x20B150E0, // Large 'bfcvt|n2'. + 0x814790C2, // Small 'bfdot'. + 0x206D50E5, // Large 'bfmla|lb'. + 0x20EA50E5, // Large 'bfmla|lt'. + 0x82C6B4C2, // Small 'bfmmla'. + 0x80000D22, // Small 'bic'. + 0x80001922, // Small 'bif'. + 0x80005122, // Small 'bit'. + 0x80003262, // Small 'bsl'. + 0x80004D83, // Small 'cls'. + 0x80006983, // Small 'clz'. + 0x800895A3, // Small 'cmeq'. + 0x80029DA3, // Small 'cmge'. + 0x800A1DA3, // Small 'cmgt'. + 0x8004A1A3, // Small 'cmhi'. + 0x8009A1A3, // Small 'cmhs'. + 0x8002B1A3, // Small 'cmle'. + 0x800A31A3, // Small 'cmlt'. + 0x8149D1A3, // Small 'cmtst'. + 0x800051C3, // Small 'cnt'. + 0x800042A4, // Small 'dup'. + 0x800049E5, // Small 'eor'. + 0x800F49E5, // Small 'eor3'. + 0x80005305, // Small 'ext'. + 0x80020826, // Small 'fabd'. + 0x80098826, // Small 'fabs'. + 0x80538C26, // Small 'facge'. + 0x81438C26, // Small 'facgt'. + 0x80021026, // Small 'fadd'. + 0x81021026, // Small 'faddp'. + 0x80420466, // Small 'fcadd'. + 0x81068C66, // Small 'fccmp'. + 0x8B068C66, // Small 'fccmpe'. + 0x8112B466, // Small 'fcmeq'. + 0x8053B466, // Small 'fcmge'. + 0x8143B466, // Small 'fcmgt'. + 0x80163466, // Small 'fcmla'. + 0x80563466, // Small 'fcmle'. + 0x81463466, // Small 'fcmlt'. + 0x80083466, // Small 'fcmp'. + 0x80583466, // Small 'fcmpe'. + 0x80C2CC66, // Small 'fcsel'. + 0x800A5866, // Small 'fcvt'. + 0xA61A5866, // Small 'fcvtas'. + 0xAA1A5866, // Small 'fcvtau'. + 0x80CA5866, // Small 'fcvtl'. + 0xBACA5866, // Small 'fcvtl2'. + 0xA6DA5866, // Small 'fcvtms'. + 0xAADA5866, // Small 'fcvtmu'. + 0x80EA5866, // Small 'fcvtn'. + 0xBAEA5866, // Small 'fcvtn2'. + 0xA6EA5866, // Small 'fcvtns'. + 0xAAEA5866, // Small 'fcvtnu'. + 0xA70A5866, // Small 'fcvtps'. + 0xAB0A5866, // Small 'fcvtpu'. + 0x9D8A5866, // Small 'fcvtxn'. + 0x20B150EC, // Large 'fcvtx|n2'. + 0xA7AA5866, // Small 'fcvtzs'. + 0xABAA5866, // Small 'fcvtzu'. + 0x800B2486, // Small 'fdiv'. + 0x101060F1, // Large 'fjcvtz|s'. + 0x804205A6, // Small 'fmadd'. + 0x800C05A6, // Small 'fmax'. + 0x9AEC05A6, // Small 'fmaxnm'. + 0x104460F7, // Large 'fmaxnm|p'. + 0x10E360F7, // Large 'fmaxnm|v'. + 0x810C05A6, // Small 'fmaxp'. + 0x816C05A6, // Small 'fmaxv'. + 0x800725A6, // Small 'fmin'. + 0x9AE725A6, // Small 'fminnm'. + 0x104460FD, // Large 'fminnm|p'. + 0x10E360FD, // Large 'fminnm|v'. + 0x810725A6, // Small 'fminp'. + 0x816725A6, // Small 'fminv'. + 0x8000B1A6, // Small 'fmla'. + 0x80C0B1A6, // Small 'fmlal'. + 0xBAC0B1A6, // Small 'fmlal2'. + 0x8009B1A6, // Small 'fmls'. + 0x80C9B1A6, // Small 'fmlsl'. + 0xBAC9B1A6, // Small 'fmlsl2'. + 0x800B3DA6, // Small 'fmov'. + 0x802ACDA6, // Small 'fmsub'. + 0x800655A6, // Small 'fmul'. + 0x818655A6, // Small 'fmulx'. + 0x800395C6, // Small 'fneg'. + 0x8840B5C6, // Small 'fnmadd'. + 0x8559B5C6, // Small 'fnmsub'. + 0x80CAB5C6, // Small 'fnmul'. + 0x8B019646, // Small 'frecpe'. + 0xA7019646, // Small 'frecps'. + 0xB1019646, // Small 'frecpx'. + 0x10137087, // Large 'frint32|x'. + 0x108E7087, // Large 'frint32|z'. + 0x308F5087, // Large 'frint|64x'. + 0x30925087, // Large 'frint|64z'. + 0x83472646, // Small 'frinta'. + 0x93472646, // Small 'frinti'. + 0x9B472646, // Small 'frintm'. + 0x9D472646, // Small 'frintn'. + 0xA1472646, // Small 'frintp'. + 0xB1472646, // Small 'frintx'. + 0xB5472646, // Small 'frintz'. + 0x20D25103, // Large 'frsqr|te'. + 0x20705103, // Large 'frsqr|ts'. + 0x81494666, // Small 'fsqrt'. + 0x80015666, // Small 'fsub'. + 0x80004DC9, // Small 'ins'. + 0x8000708C, // Small 'ld1'. + 0x8009708C, // Small 'ld1r'. + 0x8000748C, // Small 'ld2'. + 0x8009748C, // Small 'ld2r'. + 0x8000788C, // Small 'ld3'. + 0x8009788C, // Small 'ld3r'. + 0x80007C8C, // Small 'ld4'. + 0x80097C8C, // Small 'ld4r'. + 0x8008388C, // Small 'ldnp'. + 0x8000408C, // Small 'ldp'. + 0x8000488C, // Small 'ldr'. + 0x8009548C, // Small 'ldur'. + 0x8000058D, // Small 'mla'. + 0x80004D8D, // Small 'mls'. + 0x800059ED, // Small 'mov'. + 0x8004D9ED, // Small 'movi'. + 0x800032AD, // Small 'mul'. + 0x80003ACD, // Small 'mvn'. + 0x8004BACD, // Small 'mvni'. + 0x80001CAE, // Small 'neg'. + 0x800051EE, // Small 'not'. + 0x80003A4F, // Small 'orn'. + 0x80004A4F, // Small 'orr'. + 0x800655B0, // Small 'pmul'. + 0x80C655B0, // Small 'pmull'. + 0xBAC655B0, // Small 'pmull2'. + 0x9C821032, // Small 'raddhn'. + 0x30B04108, // Large 'radd|hn2'. + 0x800E6032, // Small 'rax1'. + 0x800A2452, // Small 'rbit'. + 0x20073138, // Large 'rev|16'. + 0x81DF58B2, // Small 'rev32'. + 0x208F3138, // Large 'rev|64'. + 0x80E92272, // Small 'rshrn'. + 0xBAE92272, // Small 'rshrn2'. + 0x9C815672, // Small 'rsubhn'. + 0x30B0410C, // Large 'rsub|hn2'. + 0x80008833, // Small 'saba'. + 0x80C08833, // Small 'sabal'. + 0xBAC08833, // Small 'sabal2'. + 0x80020833, // Small 'sabd'. + 0x80C20833, // Small 'sabdl'. + 0xBAC20833, // Small 'sabdl2'. + 0xA0C09033, // Small 'sadalp'. + 0x80C21033, // Small 'saddl'. + 0xBAC21033, // Small 'saddl2'. + 0xA0C21033, // Small 'saddlp'. + 0xACC21033, // Small 'saddlv'. + 0x81721033, // Small 'saddw'. + 0xBB721033, // Small 'saddw2'. + 0x806A5873, // Small 'scvtf'. + 0x800A3C93, // Small 'sdot'. + 0x803E0513, // Small 'sha1c'. + 0x808E0513, // Small 'sha1h'. + 0x80DE0513, // Small 'sha1m'. + 0x810E0513, // Small 'sha1p'. + 0x30354110, // Large 'sha1|su0'. + 0x303E4110, // Large 'sha1|su1'. + 0x1016602F, // Large 'sha256|h'. + 0x2095602F, // Large 'sha256|h2'. + 0x0000902F, // Large 'sha256su0'. + 0x1005802F, // Large 'sha256su|1'. + 0x10166038, // Large 'sha512|h'. + 0x20956038, // Large 'sha512|h2'. + 0x30356038, // Large 'sha512|su0'. + 0x303E6038, // Large 'sha512|su1'. + 0x80420513, // Small 'shadd'. + 0x80003113, // Small 'shl'. + 0x80063113, // Small 'shll'. + 0x81D63113, // Small 'shll2'. + 0x80074913, // Small 'shrn'. + 0x81D74913, // Small 'shrn2'. + 0x802ACD13, // Small 'shsub'. + 0x80002593, // Small 'sli'. + 0x10058041, // Large 'sm3partw|1'. + 0x10328041, // Large 'sm3partw|2'. + 0xB939F9B3, // Small 'sm3ss1'. + 0x10006114, // Large 'sm3tt1|a'. + 0x100D6114, // Large 'sm3tt1|b'. + 0x211A5114, // Large 'sm3tt|2a'. + 0x211C5114, // Large 'sm3tt|2b'. + 0x8002FDB3, // Small 'sm4e'. + 0x0000711E, // Large 'sm4ekey'. + 0x800C05B3, // Small 'smax'. + 0x810C05B3, // Small 'smaxp'. + 0x816C05B3, // Small 'smaxv'. + 0x800725B3, // Small 'smin'. + 0x810725B3, // Small 'sminp'. + 0x816725B3, // Small 'sminv'. + 0x80C0B1B3, // Small 'smlal'. + 0xBAC0B1B3, // Small 'smlal2'. + 0x80C9B1B3, // Small 'smlsl'. + 0xBAC9B1B3, // Small 'smlsl2'. + 0x801635B3, // Small 'smmla'. + 0x800B3DB3, // Small 'smov'. + 0x80C655B3, // Small 'smull'. + 0xBAC655B3, // Small 'smull2'. + 0x81310633, // Small 'sqabs'. + 0x80420633, // Small 'sqadd'. + 0x00007097, // Large 'sqdmlal'. + 0x10327097, // Large 'sqdmlal|2'. + 0x209E5097, // Large 'sqdml|sl'. + 0x309E5097, // Large 'sqdml|sl2'. + 0x101660A1, // Large 'sqdmul|h'. + 0x100E60A1, // Large 'sqdmul|l'. + 0x209F60A1, // Large 'sqdmul|l2'. + 0x8072BA33, // Small 'sqneg'. + 0x101670A7, // Large 'sqrdmla|h'. + 0x202F60A7, // Large 'sqrdml|sh'. + 0x30AE50A7, // Large 'sqrdm|ulh'. + 0x9889CA33, // Small 'sqrshl'. + 0x101C6049, // Large 'sqrshr|n'. + 0x20B16049, // Large 'sqrshr|n2'. + 0x00008049, // Large 'sqrshrun'. + 0x10328049, // Large 'sqrshrun|2'. + 0x80C44E33, // Small 'sqshl'. + 0xAAC44E33, // Small 'sqshlu'. + 0x9D244E33, // Small 'sqshrn'. + 0x20B150B3, // Large 'sqshr|n2'. + 0x101C60B3, // Large 'sqshru|n'. + 0x20B160B3, // Large 'sqshru|n2'. + 0x802ACE33, // Small 'sqsub'. + 0x80EA6233, // Small 'sqxtn'. + 0xBAEA6233, // Small 'sqxtn2'. + 0x9D5A6233, // Small 'sqxtun'. + 0x20B15125, // Large 'sqxtu|n2'. + 0x8840A253, // Small 'srhadd'. + 0x80002653, // Small 'sri'. + 0x80C44E53, // Small 'srshl'. + 0x81244E53, // Small 'srshr'. + 0x80194E53, // Small 'srsra'. + 0x80062273, // Small 'sshl'. + 0x80C62273, // Small 'sshll'. + 0xBAC62273, // Small 'sshll2'. + 0x80092273, // Small 'sshr'. + 0x8000CA73, // Small 'ssra'. + 0x80C15673, // Small 'ssubl'. + 0xBAC15673, // Small 'ssubl2'. + 0x81715673, // Small 'ssubw'. + 0xBB715673, // Small 'ssubw2'. + 0x80007293, // Small 'st1'. + 0x80007693, // Small 'st2'. + 0x80007A93, // Small 'st3'. + 0x80007E93, // Small 'st4'. + 0x80083A93, // Small 'stnp'. + 0x80004293, // Small 'stp'. + 0x80004A93, // Small 'str'. + 0x80095693, // Small 'stur'. + 0x80000AB3, // Small 'sub'. + 0x80E40AB3, // Small 'subhn'. + 0xBAE40AB3, // Small 'subhn2'. + 0x814792B3, // Small 'sudot'. + 0x8840C6B3, // Small 'suqadd'. + 0x80065313, // Small 'sxtl'. + 0x81D65313, // Small 'sxtl2'. + 0x80003054, // Small 'tbl'. + 0x80006054, // Small 'tbx'. + 0x800E3A54, // Small 'trn1'. + 0x800EBA54, // Small 'trn2'. + 0x80008835, // Small 'uaba'. + 0x80C08835, // Small 'uabal'. + 0xBAC08835, // Small 'uabal2'. + 0x80020835, // Small 'uabd'. + 0x80C20835, // Small 'uabdl'. + 0xBAC20835, // Small 'uabdl2'. + 0xA0C09035, // Small 'uadalp'. + 0x80C21035, // Small 'uaddl'. + 0xBAC21035, // Small 'uaddl2'. + 0xA0C21035, // Small 'uaddlp'. + 0xACC21035, // Small 'uaddlv'. + 0x81721035, // Small 'uaddw'. + 0xBB721035, // Small 'uaddw2'. + 0x806A5875, // Small 'ucvtf'. + 0x800A3C95, // Small 'udot'. + 0x80420515, // Small 'uhadd'. + 0x802ACD15, // Small 'uhsub'. + 0x800C05B5, // Small 'umax'. + 0x810C05B5, // Small 'umaxp'. + 0x816C05B5, // Small 'umaxv'. + 0x800725B5, // Small 'umin'. + 0x810725B5, // Small 'uminp'. + 0x816725B5, // Small 'uminv'. + 0x80C0B1B5, // Small 'umlal'. + 0xBAC0B1B5, // Small 'umlal2'. + 0x80C9B1B5, // Small 'umlsl'. + 0xBAC9B1B5, // Small 'umlsl2'. + 0x801635B5, // Small 'ummla'. + 0x800B3DB5, // Small 'umov'. + 0x80C655B5, // Small 'umull'. + 0xBAC655B5, // Small 'umull2'. + 0x80420635, // Small 'uqadd'. + 0x9889CA35, // Small 'uqrshl'. + 0x101C60B9, // Large 'uqrshr|n'. + 0x20B160B9, // Large 'uqrshr|n2'. + 0x80C44E35, // Small 'uqshl'. + 0x9D244E35, // Small 'uqshrn'. + 0x20B1512A, // Large 'uqshr|n2'. + 0x802ACE35, // Small 'uqsub'. + 0x80EA6235, // Small 'uqxtn'. + 0xBAEA6235, // Small 'uqxtn2'. + 0x8B019655, // Small 'urecpe'. + 0x8840A255, // Small 'urhadd'. + 0x80C44E55, // Small 'urshl'. + 0x81244E55, // Small 'urshr'. + 0x20D2512F, // Large 'ursqr|te'. + 0x80194E55, // Small 'ursra'. + 0x81479275, // Small 'usdot'. + 0x80062275, // Small 'ushl'. + 0x80C62275, // Small 'ushll'. + 0xBAC62275, // Small 'ushll2'. + 0x80092275, // Small 'ushr'. + 0x82C6B675, // Small 'usmmla'. + 0x8840C675, // Small 'usqadd'. + 0x8000CA75, // Small 'usra'. + 0x80C15675, // Small 'usubl'. + 0xBAC15675, // Small 'usubl2'. + 0x81715675, // Small 'usubw'. + 0xBB715675, // Small 'usubw2'. + 0x80065315, // Small 'uxtl'. + 0x81D65315, // Small 'uxtl2'. + 0x800E4355, // Small 'uzp1'. + 0x800EC355, // Small 'uzp2'. + 0x80004838, // Small 'xar'. + 0x80003A98, // Small 'xtn'. + 0x800EBA98, // Small 'xtn2'. + 0x800E413A, // Small 'zip1'. + 0x800EC13A // Small 'zip2'. }; // ---------------------------------------------------------------------------- // ${NameData:End} -#endif +#endif // !ASMJIT_NO_TEXT ASMJIT_END_SUB_NAMESPACE diff --git a/3rdparty/asmjit/src/asmjit/arm/a64instdb.h b/3rdparty/asmjit/src/asmjit/arm/a64instdb.h index 0575d1a2fa6..a03125401ad 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64instdb.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64instdb.h @@ -29,7 +29,7 @@ enum InstFlags : uint32_t { //! SIMD element access of half-words can only be used with v0..15. kInstFlagVH0_15 = 0x00000010u, - //! Instruction may consecutive registers if the number of operands is greater than 2. + //! Instruction uses consecutive registers if the number of operands is greater than 2. kInstFlagConsecutive = 0x00000080u }; @@ -39,9 +39,7 @@ struct InstInfo { uint32_t _encoding : 8; //! Index to data specific to each encoding type. uint32_t _encodingDataIndex : 8; - uint32_t _reserved : 2; - //! Index to \ref _nameData. - uint32_t _nameDataIndex : 14; + uint32_t _reserved : 16; uint16_t _rwInfoIndex; uint16_t _flags; @@ -49,10 +47,10 @@ struct InstInfo { //! \name Accessors //! \{ - inline uint32_t rwInfoIndex() const noexcept { return _rwInfoIndex; } - inline uint32_t flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG uint32_t rwInfoIndex() const noexcept { return _rwInfoIndex; } + ASMJIT_INLINE_NODEBUG uint32_t flags() const noexcept { return _flags; } - inline bool hasFlag(uint32_t flag) const { return (_flags & flag) != 0; } + ASMJIT_INLINE_NODEBUG bool hasFlag(uint32_t flag) const { return (_flags & flag) != 0; } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/arm/a64instdb_p.h b/3rdparty/asmjit/src/asmjit/arm/a64instdb_p.h index eb4f3f83766..5c3da7e1f9f 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64instdb_p.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64instdb_p.h @@ -7,6 +7,7 @@ #define ASMJIT_ARM_A64INSTDB_H_P_INCLUDED #include "../core/codeholder.h" +#include "../core/instdb_p.h" #include "../arm/a64instdb.h" #include "../arm/a64operand.h" @@ -58,14 +59,14 @@ enum RWInfoType : uint32_t { // a64::InstDB - ElementType // ========================= -enum ElementType : uint8_t { - kET_None = Vec::kElementTypeNone, - kET_B = Vec::kElementTypeB, - kET_H = Vec::kElementTypeH, - kET_S = Vec::kElementTypeS, - kET_D = Vec::kElementTypeD, - kET_2H = Vec::kElementTypeH2, - kET_4B = Vec::kElementTypeB4 +enum InstElementType : uint8_t { + kET_None = uint8_t(VecElementType::kNone), + kET_B = uint8_t(VecElementType::kB), + kET_H = uint8_t(VecElementType::kH), + kET_S = uint8_t(VecElementType::kS), + kET_D = uint8_t(VecElementType::kD), + kET_2H = uint8_t(VecElementType::kH2), + kET_4B = uint8_t(VecElementType::kB4) }; // a64::InstDB - GpType @@ -192,6 +193,7 @@ enum EncodingId : uint32_t { kEncodingBaseMvnNeg, kEncodingBaseOp, kEncodingBaseOpImm, + kEncodingBasePrfm, kEncodingBaseR, kEncodingBaseRM_NoImm, kEncodingBaseRM_SImm10, @@ -262,7 +264,7 @@ namespace EncodingData { #define M_OPCODE(field, bits) \ uint32_t _##field : bits; \ - inline constexpr uint32_t field() const noexcept { return uint32_t(_##field) << (32 - bits); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t field() const noexcept { return uint32_t(_##field) << (32 - bits); } struct BaseOp { uint32_t opcode; @@ -412,6 +414,13 @@ struct BaseRM_SImm10 { uint32_t immShift : 4; }; +struct BasePrfm { + uint32_t registerOp : 11; + uint32_t sOffsetOp : 10; + uint32_t uOffsetOp : 11; + uint32_t literalOp; +}; + struct BaseLdSt { uint32_t uOffsetOp : 10; uint32_t prePostOp : 11; @@ -787,6 +796,7 @@ extern const BaseMovKNZ baseMovKNZ[3]; extern const BaseMvnNeg baseMvnNeg[3]; extern const BaseOp baseOp[23]; extern const BaseOpImm baseOpImm[14]; +extern const BasePrfm basePrfm[1]; extern const BaseR baseR[10]; extern const BaseRM_NoImm baseRM_NoImm[21]; extern const BaseRM_SImm10 baseRM_SImm10[2]; @@ -843,26 +853,13 @@ extern const SimdTblTbx simdTblTbx[2]; } // {EncodingData} -// a64::InstDB - InstNameIndex -// =========================== - -// ${NameLimits:Begin} -// ------------------- Automatically generated, do not edit ------------------- -enum : uint32_t { kMaxNameSize = 9 }; -// ---------------------------------------------------------------------------- -// ${NameLimits:End} - -struct InstNameIndex { - uint16_t start; - uint16_t end; -}; - // a64::InstDB - Tables // ==================== #ifndef ASMJIT_NO_TEXT -extern const char _nameData[]; -extern const InstNameIndex instNameIndex[26]; +extern const InstNameIndex instNameIndex; +extern const char _instNameStringTable[]; +extern const uint32_t _instNameIndexTable[]; #endif // !ASMJIT_NO_TEXT } // {InstDB} diff --git a/3rdparty/asmjit/src/asmjit/arm/a64operand.cpp b/3rdparty/asmjit/src/asmjit/arm/a64operand.cpp index 40a4a7952bc..e8c6100fa68 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64operand.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64operand.cpp @@ -17,66 +17,66 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) #if defined(ASMJIT_TEST) UNIT(a64_operand) { INFO("Checking if a64::reg(...) matches built-in IDs"); - EXPECT(w(5) == w5); - EXPECT(x(5) == x5); + EXPECT_EQ(w(5), w5); + EXPECT_EQ(x(5), x5); INFO("Checking Gp register properties"); - EXPECT(Gp().isReg() == true); - EXPECT(w0.isReg() == true); - EXPECT(x0.isReg() == true); - EXPECT(w0.id() == 0); - EXPECT(x0.id() == 0); - EXPECT(wzr.id() == Gp::kIdZr); - EXPECT(xzr.id() == Gp::kIdZr); - EXPECT(wsp.id() == Gp::kIdSp); - EXPECT(sp.id() == Gp::kIdSp); - EXPECT(w0.size() == 4); - EXPECT(x0.size() == 8); - EXPECT(w0.type() == RegType::kARM_GpW); - EXPECT(x0.type() == RegType::kARM_GpX); - EXPECT(w0.group() == RegGroup::kGp); - EXPECT(x0.group() == RegGroup::kGp); + EXPECT_TRUE(Gp().isReg()); + EXPECT_TRUE(w0.isReg()); + EXPECT_TRUE(x0.isReg()); + EXPECT_EQ(w0.id(), 0u); + EXPECT_EQ(x0.id(), 0u); + EXPECT_EQ(wzr.id(), Gp::kIdZr); + EXPECT_EQ(xzr.id(), Gp::kIdZr); + EXPECT_EQ(wsp.id(), Gp::kIdSp); + EXPECT_EQ(sp.id(), Gp::kIdSp); + EXPECT_EQ(w0.size(), 4u); + EXPECT_EQ(x0.size(), 8u); + EXPECT_EQ(w0.type(), RegType::kARM_GpW); + EXPECT_EQ(x0.type(), RegType::kARM_GpX); + EXPECT_EQ(w0.group(), RegGroup::kGp); + EXPECT_EQ(x0.group(), RegGroup::kGp); INFO("Checking Vec register properties"); - EXPECT(v0.type() == RegType::kARM_VecV); - EXPECT(d0.type() == RegType::kARM_VecD); - EXPECT(s0.type() == RegType::kARM_VecS); - EXPECT(h0.type() == RegType::kARM_VecH); - EXPECT(b0.type() == RegType::kARM_VecB); + EXPECT_EQ(v0.type(), RegType::kARM_VecV); + EXPECT_EQ(d0.type(), RegType::kARM_VecD); + EXPECT_EQ(s0.type(), RegType::kARM_VecS); + EXPECT_EQ(h0.type(), RegType::kARM_VecH); + EXPECT_EQ(b0.type(), RegType::kARM_VecB); - EXPECT(v0.group() == RegGroup::kVec); - EXPECT(d0.group() == RegGroup::kVec); - EXPECT(s0.group() == RegGroup::kVec); - EXPECT(h0.group() == RegGroup::kVec); - EXPECT(b0.group() == RegGroup::kVec); + EXPECT_EQ(v0.group(), RegGroup::kVec); + EXPECT_EQ(d0.group(), RegGroup::kVec); + EXPECT_EQ(s0.group(), RegGroup::kVec); + EXPECT_EQ(h0.group(), RegGroup::kVec); + EXPECT_EQ(b0.group(), RegGroup::kVec); INFO("Checking Vec register element[] access"); Vec vd_1 = v15.d(1); - EXPECT(vd_1.type() == RegType::kARM_VecV); - EXPECT(vd_1.group() == RegGroup::kVec); - EXPECT(vd_1.id() == 15); - EXPECT(vd_1.isVecD2()); - EXPECT(vd_1.elementType() == Vec::kElementTypeD); - EXPECT(vd_1.hasElementIndex()); - EXPECT(vd_1.elementIndex() == 1); + EXPECT_EQ(vd_1.type(), RegType::kARM_VecV); + EXPECT_EQ(vd_1.group(), RegGroup::kVec); + EXPECT_EQ(vd_1.id(), 15u); + EXPECT_TRUE(vd_1.isVecD2()); + EXPECT_EQ(vd_1.elementType(), VecElementType::kD); + EXPECT_TRUE(vd_1.hasElementIndex()); + EXPECT_EQ(vd_1.elementIndex(), 1u); Vec vs_3 = v15.s(3); - EXPECT(vs_3.type() == RegType::kARM_VecV); - EXPECT(vs_3.group() == RegGroup::kVec); - EXPECT(vs_3.id() == 15); - EXPECT(vs_3.isVecS4()); - EXPECT(vs_3.elementType() == Vec::kElementTypeS); - EXPECT(vs_3.hasElementIndex()); - EXPECT(vs_3.elementIndex() == 3); + EXPECT_EQ(vs_3.type(), RegType::kARM_VecV); + EXPECT_EQ(vs_3.group(), RegGroup::kVec); + EXPECT_EQ(vs_3.id(), 15u); + EXPECT_TRUE(vs_3.isVecS4()); + EXPECT_EQ(vs_3.elementType(), VecElementType::kS); + EXPECT_TRUE(vs_3.hasElementIndex()); + EXPECT_EQ(vs_3.elementIndex(), 3u); Vec vb_4 = v15.b4(3); - EXPECT(vb_4.type() == RegType::kARM_VecV); - EXPECT(vb_4.group() == RegGroup::kVec); - EXPECT(vb_4.id() == 15); - EXPECT(vb_4.isVecB4x4()); - EXPECT(vb_4.elementType() == Vec::kElementTypeB4); - EXPECT(vb_4.hasElementIndex()); - EXPECT(vb_4.elementIndex() == 3); + EXPECT_EQ(vb_4.type(), RegType::kARM_VecV); + EXPECT_EQ(vb_4.group(), RegGroup::kVec); + EXPECT_EQ(vb_4.id(), 15u); + EXPECT_TRUE(vb_4.isVecB4x4()); + EXPECT_EQ(vb_4.elementType(), VecElementType::kB4); + EXPECT_TRUE(vb_4.hasElementIndex()); + EXPECT_EQ(vb_4.elementIndex(), 3u); } #endif diff --git a/3rdparty/asmjit/src/asmjit/arm/a64operand.h b/3rdparty/asmjit/src/asmjit/arm/a64operand.h index c2d3c179a86..9e233062b69 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64operand.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64operand.h @@ -13,24 +13,304 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) //! \addtogroup asmjit_a64 //! \{ -using arm::Reg; -using arm::Mem; -using arm::Gp; -using arm::GpW; -using arm::GpX; - -using arm::Vec; -using arm::VecB; -using arm::VecH; -using arm::VecS; -using arm::VecD; -using arm::VecV; +class GpW; +class GpX; + +class VecB; +class VecH; +class VecS; +class VecD; +class VecV; + +//! General purpose register (AArch64). +class Gp : public Reg { +public: + ASMJIT_DEFINE_ABSTRACT_REG(Gp, Reg) + + //! Special register id. + enum Id : uint32_t { + //! Register that depends on OS, could be used as TLS offset. + kIdOs = 18, + //! Frame pointer register id. + kIdFp = 29, + //! Link register id. + kIdLr = 30, + //! Stack register id. + kIdSp = 31, + //! Zero register id. + //! + //! Although zero register has the same id as stack register it has a special treatment, because we need to be + //! able to distinguish between these two at API level. Some instructions were designed to be used with SP and + //! some other with ZR - so we need a way to distinguish these two to make sure we emit the right thing. + //! + //! The number 63 is not random, when you perform `id & 31` you would always get 31 for both SP and ZR inputs, + //! which is the identifier used by AArch64 ISA to encode either SP or ZR depending on the instruction. + kIdZr = 63 + }; + + //! Test whether this register is ZR register. + ASMJIT_INLINE_NODEBUG constexpr bool isZR() const noexcept { return id() == kIdZr; } + //! Test whether this register is SP register. + ASMJIT_INLINE_NODEBUG constexpr bool isSP() const noexcept { return id() == kIdSp; } + + //! Cast this register to a 32-bit W register (returns a new operand). + ASMJIT_INLINE_NODEBUG GpW w() const noexcept; + //! \overload + ASMJIT_INLINE_NODEBUG GpW r32() const noexcept; + //! Cast this register to a 64-bit X register (returns a new operand). + ASMJIT_INLINE_NODEBUG GpX x() const noexcept; + //! \overload + ASMJIT_INLINE_NODEBUG GpX r64() const noexcept; +}; + +//! 32-bit general purpose W register (AArch64). +class GpW : public Gp { ASMJIT_DEFINE_FINAL_REG(GpW, Gp, RegTraits<RegType::kARM_GpW>); }; +//! 64-bit general purpose X register (AArch64). +class GpX : public Gp { ASMJIT_DEFINE_FINAL_REG(GpX, Gp, RegTraits<RegType::kARM_GpX>); }; + +#ifndef _DOXYGEN +ASMJIT_INLINE_NODEBUG GpW Gp::w() const noexcept { return GpW(id()); } +ASMJIT_INLINE_NODEBUG GpX Gp::x() const noexcept { return GpX(id()); } +ASMJIT_INLINE_NODEBUG GpW Gp::r32() const noexcept { return GpW(id()); } +ASMJIT_INLINE_NODEBUG GpX Gp::r64() const noexcept { return GpX(id()); } +#endif + +//! Vector element type (AArch64). +enum class VecElementType : uint32_t { + //! No element type specified. + kNone = 0, + //! Byte elements (B8 or B16). + kB, + //! Halfword elements (H4 or H8). + kH, + //! Singleword elements (S2 or S4). + kS, + //! Doubleword elements (D2). + kD, + //! Byte elements grouped by 4 bytes (B4). + //! + //! \note This element-type is only used by few instructions. + kB4, + //! Halfword elements grouped by 2 halfwords (H2). + //! + //! \note This element-type is only used by few instructions. + kH2, + + //! Maximum value of \ref VecElementType + kMaxValue = kH2 +}; + +//! Vector register (AArch64). +class Vec : public BaseVec { +public: + ASMJIT_DEFINE_ABSTRACT_REG(Vec, BaseVec) + + //! \cond + //! Shortcuts. + enum SignatureReg : uint32_t { + kSignatureElementB = uint32_t(VecElementType::kB) << kSignatureRegElementTypeShift, + kSignatureElementH = uint32_t(VecElementType::kH) << kSignatureRegElementTypeShift, + kSignatureElementS = uint32_t(VecElementType::kS) << kSignatureRegElementTypeShift, + kSignatureElementD = uint32_t(VecElementType::kD) << kSignatureRegElementTypeShift, + kSignatureElementB4 = uint32_t(VecElementType::kB4) << kSignatureRegElementTypeShift, + kSignatureElementH2 = uint32_t(VecElementType::kH2) << kSignatureRegElementTypeShift + }; + //! \endcond + + //! Returns whether the register has element type or element index (or both). + ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask | kSignatureRegElementFlagMask>(); } + + //! Returns whether the vector register has associated a vector element type. + ASMJIT_INLINE_NODEBUG constexpr bool hasElementType() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask>(); } + //! Returns vector element type of the register. + ASMJIT_INLINE_NODEBUG constexpr VecElementType elementType() const noexcept { return VecElementType(_signature.getField<kSignatureRegElementTypeMask>()); } + //! Sets vector element type of the register to `elementType`. + ASMJIT_INLINE_NODEBUG void setElementType(VecElementType elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(uint32_t(elementType)); } + //! Resets vector element type to none. + ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecD>::kSignature); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4); + } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { + return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2); + } + + //! Creates a cloned register with element access. + ASMJIT_INLINE_NODEBUG Vec at(uint32_t elementIndex) const noexcept { + return Vec((signature() & ~kSignatureRegElementIndexMask) | (elementIndex << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id()); + } + + //! Cast this register to an 8-bit B register (AArch64 only). + ASMJIT_INLINE_NODEBUG VecB b() const noexcept; + //! Cast this register to a 16-bit H register (AArch64 only). + ASMJIT_INLINE_NODEBUG VecH h() const noexcept; + //! Cast this register to a 32-bit S register. + ASMJIT_INLINE_NODEBUG VecS s() const noexcept; + //! Cast this register to a 64-bit D register. + ASMJIT_INLINE_NODEBUG VecD d() const noexcept; + //! Cast this register to a 128-bit Q register. + ASMJIT_INLINE_NODEBUG VecV q() const noexcept; + //! Cast this register to a 128-bit V register. + ASMJIT_INLINE_NODEBUG VecV v() const noexcept; + + //! Casts this register to b (clone). + ASMJIT_INLINE_NODEBUG Vec v8() const noexcept; + //! Casts this register to h (clone). + ASMJIT_INLINE_NODEBUG Vec v16() const noexcept; + //! Casts this register to s (clone). + ASMJIT_INLINE_NODEBUG Vec v32() const noexcept; + //! Casts this register to d (clone). + ASMJIT_INLINE_NODEBUG Vec v64() const noexcept; + //! Casts this register to q (clone). + ASMJIT_INLINE_NODEBUG Vec v128() const noexcept; + + //! Cast this register to a 128-bit V.B[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV b(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.H[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV h(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.S[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV s(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.D[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV d(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.H2[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV h2(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.B4[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV b4(uint32_t elementIndex) const noexcept; + + //! Cast this register to V.8B. + ASMJIT_INLINE_NODEBUG VecD b8() const noexcept; + //! Cast this register to V.16B. + ASMJIT_INLINE_NODEBUG VecV b16() const noexcept; + //! Cast this register to V.2H. + ASMJIT_INLINE_NODEBUG VecS h2() const noexcept; + //! Cast this register to V.4H. + ASMJIT_INLINE_NODEBUG VecD h4() const noexcept; + //! Cast this register to V.8H. + ASMJIT_INLINE_NODEBUG VecV h8() const noexcept; + //! Cast this register to V.2S. + ASMJIT_INLINE_NODEBUG VecD s2() const noexcept; + //! Cast this register to V.4S. + ASMJIT_INLINE_NODEBUG VecV s4() const noexcept; + //! Cast this register to V.2D. + ASMJIT_INLINE_NODEBUG VecV d2() const noexcept; + + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature _makeElementAccessSignature(VecElementType elementType, uint32_t elementIndex) noexcept { + return OperandSignature{ + uint32_t(RegTraits<RegType::kARM_VecV>::kSignature) | + uint32_t(kSignatureRegElementFlagMask) | + (uint32_t(elementType) << kSignatureRegElementTypeShift) | + (uint32_t(elementIndex << kSignatureRegElementIndexShift))}; + } +}; + +//! 8-bit view (S) of VFP/SIMD register. +class VecB : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecB, Vec, RegTraits<RegType::kARM_VecB>) +}; + +//! 16-bit view (S) of VFP/SIMD register. +class VecH : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits<RegType::kARM_VecH>) +}; + +//! 32-bit view (S) of VFP/SIMD register. +class VecS : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits<RegType::kARM_VecS>) +}; + +//! 64-bit view (D) of VFP/SIMD register. +class VecD : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits<RegType::kARM_VecD>) +}; + +//! 128-bit vector register (Q or V). +class VecV : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits<RegType::kARM_VecV>) +}; + +ASMJIT_INLINE_NODEBUG VecB Vec::b() const noexcept { return VecB(id()); } +ASMJIT_INLINE_NODEBUG VecH Vec::h() const noexcept { return VecH(id()); } +ASMJIT_INLINE_NODEBUG VecS Vec::s() const noexcept { return VecS(id()); } +ASMJIT_INLINE_NODEBUG VecD Vec::d() const noexcept { return VecD(id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::q() const noexcept { return VecV(id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::v() const noexcept { return VecV(id()); } + +ASMJIT_INLINE_NODEBUG Vec Vec::v8() const noexcept { return VecB(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v16() const noexcept { return VecH(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v32() const noexcept { return VecS(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v64() const noexcept { return VecD(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v128() const noexcept { return VecV(id()); } + +ASMJIT_INLINE_NODEBUG VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kB, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kH, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kS, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kD, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kH2, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kB4, elementIndex), id()); } + +ASMJIT_INLINE_NODEBUG VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); } +ASMJIT_INLINE_NODEBUG VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); } +ASMJIT_INLINE_NODEBUG VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); } +ASMJIT_INLINE_NODEBUG VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); } #ifndef _DOXYGEN namespace regs { #endif -using namespace ::asmjit::arm::regs; +//! Creates a 32-bit W register operand. +static ASMJIT_INLINE_NODEBUG constexpr GpW w(uint32_t id) noexcept { return GpW(id); } +//! Creates a 64-bit X register operand. +static ASMJIT_INLINE_NODEBUG constexpr GpX x(uint32_t id) noexcept { return GpX(id); } + +//! Creates a 32-bit S register operand. +static ASMJIT_INLINE_NODEBUG constexpr VecS s(uint32_t id) noexcept { return VecS(id); } +//! Creates a 64-bit D register operand. +static ASMJIT_INLINE_NODEBUG constexpr VecD d(uint32_t id) noexcept { return VecD(id); } +//! Creates a 1282-bit V register operand. +static ASMJIT_INLINE_NODEBUG constexpr VecV v(uint32_t id) noexcept { return VecV(id); } static constexpr GpW w0 = GpW(0); static constexpr GpW w1 = GpW(1); @@ -305,8 +585,94 @@ static constexpr VecV v31 = VecV(31); using namespace regs; #endif +//! \name Shift Operation Construction +//! \{ + +//! Constructs a `UXTB #value` extend and shift (unsigned byte extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift uxtb(uint32_t value) noexcept { return Shift(ShiftOp::kUXTB, value); } +//! Constructs a `UXTH #value` extend and shift (unsigned hword extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift uxth(uint32_t value) noexcept { return Shift(ShiftOp::kUXTH, value); } +//! Constructs a `UXTW #value` extend and shift (unsigned word extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift uxtw(uint32_t value) noexcept { return Shift(ShiftOp::kUXTW, value); } +//! Constructs a `UXTX #value` extend and shift (unsigned dword extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift uxtx(uint32_t value) noexcept { return Shift(ShiftOp::kUXTX, value); } + +//! Constructs a `SXTB #value` extend and shift (signed byte extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift sxtb(uint32_t value) noexcept { return Shift(ShiftOp::kSXTB, value); } +//! Constructs a `SXTH #value` extend and shift (signed hword extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift sxth(uint32_t value) noexcept { return Shift(ShiftOp::kSXTH, value); } +//! Constructs a `SXTW #value` extend and shift (signed word extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift sxtw(uint32_t value) noexcept { return Shift(ShiftOp::kSXTW, value); } +//! Constructs a `SXTX #value` extend and shift (signed dword extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift sxtx(uint32_t value) noexcept { return Shift(ShiftOp::kSXTX, value); } + +//! \} + +//! \name Memory Operand Construction +//! \{ + +//! Creates `[base, offset]` memory operand (offset mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset); +} + +//! Creates `[base, offset]!` memory operand (pre-index mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_pre(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset, OperandSignature::fromValue<Mem::kSignatureMemOffsetModeMask>(OffsetMode::kPreIndex)); +} + +//! Creates `[base], offset` memory operand (post-index mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_post(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset, OperandSignature::fromValue<Mem::kSignatureMemOffsetModeMask>(OffsetMode::kPostIndex)); +} + +//! Creates `[base, index]` memory operand (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index) noexcept { + return Mem(base, index); +} + +//! Creates `[base, index]!` memory operand (pre-index mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_pre(const Gp& base, const Gp& index) noexcept { + return Mem(base, index, OperandSignature::fromValue<Mem::kSignatureMemOffsetModeMask>(OffsetMode::kPreIndex)); +} + +//! Creates `[base], index` memory operand (post-index mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_post(const Gp& base, const Gp& index) noexcept { + return Mem(base, index, OperandSignature::fromValue<Mem::kSignatureMemOffsetModeMask>(OffsetMode::kPostIndex)); +} + +//! Creates `[base, index, SHIFT_OP #shift]` memory operand (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index, const Shift& shift) noexcept { + return Mem(base, index, shift); +} + +//! Creates `[base, offset]` memory operand (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, int32_t offset = 0) noexcept { + return Mem(base, offset); +} + +// TODO: [ARM] PC + offset address. +#if 0 +//! Creates `[PC + offset]` (relative) memory operand. +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const PC& pc, int32_t offset = 0) noexcept { + return Mem(pc, offset); +} +#endif + +//! \} + //! \} ASMJIT_END_SUB_NAMESPACE +//! \cond INTERNAL +ASMJIT_BEGIN_NAMESPACE +ASMJIT_DEFINE_TYPE_ID(a64::GpW, TypeId::kInt32); +ASMJIT_DEFINE_TYPE_ID(a64::GpX, TypeId::kInt64); +ASMJIT_DEFINE_TYPE_ID(a64::VecS, TypeId::kFloat32x1); +ASMJIT_DEFINE_TYPE_ID(a64::VecD, TypeId::kFloat64x1); +ASMJIT_DEFINE_TYPE_ID(a64::VecV, TypeId::kInt32x4); +ASMJIT_END_NAMESPACE +//! \endcond + #endif // ASMJIT_ARM_A64OPERAND_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/arm/a64rapass.cpp b/3rdparty/asmjit/src/asmjit/arm/a64rapass.cpp index aaec1c90f99..b97f259efa0 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64rapass.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/a64rapass.cpp @@ -131,7 +131,7 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstB InstId instId = inst->id(); uint32_t opCount = inst->opCount(); const Operand* opArray = inst->operands(); - ASMJIT_PROPAGATE(InstInternal::queryRWInfo(_arch, inst->baseInst(), opArray, opCount, &rwInfo)); + ASMJIT_PROPAGATE(InstInternal::queryRWInfo(inst->baseInst(), opArray, opCount, &rwInfo)); const InstDB::InstInfo& instInfo = InstDB::infoById(instId); uint32_t singleRegOps = 0; @@ -230,7 +230,7 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstB if (reg.as<Vec>().hasElementIndex()) { // Only the first 0..15 registers can be used if the register uses // element accessor that accesses half-words (h[0..7] elements). - if (instInfo.hasFlag(InstDB::kInstFlagVH0_15) && reg.as<Vec>().elementType() == Vec::kElementTypeH) { + if (instInfo.hasFlag(InstDB::kInstFlagVH0_15) && reg.as<Vec>().elementType() == VecElementType::kH) { if (Support::test(flags, RATiedFlags::kUse)) useId &= 0x0000FFFFu; else @@ -595,14 +595,14 @@ void ARMRAPass::onInit() noexcept { _archTraits = &ArchTraits::byArch(arch); _physRegCount.set(RegGroup::kGp, 32); _physRegCount.set(RegGroup::kVec, 32); - _physRegCount.set(RegGroup::kExtraVirt2, 0); + _physRegCount.set(RegGroup::kMask, 0); _physRegCount.set(RegGroup::kExtraVirt3, 0); _buildPhysIndex(); _availableRegCount = _physRegCount; _availableRegs[RegGroup::kGp] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kGp)); _availableRegs[RegGroup::kVec] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kVec)); - _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt2)); + _availableRegs[RegGroup::kMask] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kMask)); _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt3)); _scratchRegIndexes[0] = uint8_t(27); @@ -612,7 +612,9 @@ void ARMRAPass::onInit() noexcept { // make unavailable all registers that are special and cannot be used in general. bool hasFP = _func->frame().hasPreservedFP(); - if (hasFP) + // Apple ABI requires that the frame-pointer register is not changed by leaf functions and properly updated + // by non-leaf functions. So, let's make this register unavailable as it's just not safe to update it. + if (hasFP || cc()->environment().isDarwin()) makeUnavailable(RegGroup::kGp, Gp::kIdFp); makeUnavailable(RegGroup::kGp, Gp::kIdSp); diff --git a/3rdparty/asmjit/src/asmjit/arm/a64rapass_p.h b/3rdparty/asmjit/src/asmjit/arm/a64rapass_p.h index e1a90ab8df7..73130873f44 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64rapass_p.h +++ b/3rdparty/asmjit/src/asmjit/arm/a64rapass_p.h @@ -37,7 +37,7 @@ public: //! \{ ARMRAPass() noexcept; - virtual ~ARMRAPass() noexcept; + ~ARMRAPass() noexcept override; //! \} @@ -45,10 +45,10 @@ public: //! \{ //! Returns the compiler casted to `arm::Compiler`. - inline Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); } + ASMJIT_INLINE_NODEBUG Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); } //! Returns emit helper. - inline EmitHelper* emitHelper() noexcept { return &_emitHelper; } + ASMJIT_INLINE_NODEBUG EmitHelper* emitHelper() noexcept { return &_emitHelper; } //! \} diff --git a/3rdparty/asmjit/src/asmjit/arm/armformatter.cpp b/3rdparty/asmjit/src/asmjit/arm/armformatter.cpp index 0432043106a..3fe2c6b911c 100644 --- a/3rdparty/asmjit/src/asmjit/arm/armformatter.cpp +++ b/3rdparty/asmjit/src/asmjit/arm/armformatter.cpp @@ -9,7 +9,7 @@ #include "../core/misc_p.h" #include "../core/support.h" #include "../arm/armformatter_p.h" -#include "../arm/armoperand.h" +#include "../arm/a64operand.h" #include "../arm/a64instapi_p.h" #include "../arm/a64instdb_p.h" @@ -26,78 +26,225 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept // @EnumStringBegin{"enum": "CpuFeatures::ARM", "output": "sFeature", "strip": "k"}@ static const char sFeatureString[] = "None\0" - "THUMB\0" - "THUMBv2\0" "ARMv6\0" "ARMv7\0" "ARMv8a\0" - "ARMv8_1a\0" - "ARMv8_2a\0" - "ARMv8_3a\0" - "ARMv8_4a\0" - "ARMv8_5a\0" - "ARMv8_6a\0" - "ARMv8_7a\0" - "VFPv2\0" - "VFPv3\0" - "VFPv4\0" - "VFP_D32\0" + "THUMB\0" + "THUMBv2\0" + "ABLE\0" + "ADERR\0" "AES\0" - "ALTNZCV\0" + "AFP\0" + "AIE\0" + "AMU1\0" + "AMU1_1\0" + "ANERR\0" "ASIMD\0" "BF16\0" + "BRBE\0" "BTI\0" + "BWE\0" + "CCIDX\0" + "CHK\0" + "CLRBHB\0" + "CMOW\0" + "CONSTPACFIELD\0" + "CPA\0" + "CPA2\0" "CPUID\0" "CRC32\0" + "CSSC\0" + "CSV2\0" + "CSV2_3\0" + "CSV3\0" + "D128\0" "DGH\0" "DIT\0" "DOTPROD\0" + "DPB\0" + "DPB2\0" + "EBEP\0" + "EBF16\0" + "ECBHB\0" + "ECV\0" + "EDHSR\0" "EDSP\0" + "FAMINMAX\0" "FCMA\0" - "FJCVTZS\0" + "FGT\0" + "FGT2\0" + "FHM\0" "FLAGM\0" + "FLAGM2\0" + "FMAC\0" + "FP\0" + "FP16\0" "FP16CONV\0" - "FP16FML\0" - "FP16FULL\0" - "FRINT\0" + "FP8\0" + "FP8DOT2\0" + "FP8DOT4\0" + "FP8FMA\0" + "FPMR\0" + "FRINTTS\0" + "GCS\0" + "HACDBS\0" + "HAFDBS\0" + "HAFT\0" + "HDBSS\0" + "HBC\0" + "HCX\0" + "HPDS\0" + "HPDS2\0" "I8MM\0" "IDIVA\0" "IDIVT\0" + "ITE\0" + "JSCVT\0" + "LOR\0" + "LRCPC\0" + "LRCPC2\0" + "LRCPC3\0" + "LS64\0" + "LS64_ACCDATA\0" + "LS64_V\0" "LSE\0" + "LSE128\0" + "LSE2\0" + "LUT\0" + "LVA\0" + "LVA3\0" + "MEC\0" + "MOPS\0" + "MPAM\0" "MTE\0" - "RCPC_IMMO\0" - "RDM\0" + "MTE2\0" + "MTE3\0" + "MTE4\0" + "MTE_ASYM_FAULT\0" + "MTE_ASYNC\0" + "MTE_CANONICAL_TAGS\0" + "MTE_NO_ADDRESS_TAGS\0" + "MTE_PERM_S1\0" + "MTE_STORE_ONLY\0" + "MTE_TAGGED_FAR\0" + "MTPMU\0" + "NMI\0" + "NV\0" + "NV2\0" + "PAN\0" + "PAN2\0" + "PAN3\0" + "PAUTH\0" + "PFAR\0" "PMU\0" "PMULL\0" + "PRFMSLC\0" + "RAS\0" + "RAS1_1\0" + "RAS2\0" + "RASSA2\0" + "RDM\0" + "RME\0" "RNG\0" + "RNG_TRAP\0" + "RPRES\0" + "RPRFM\0" + "S1PIE\0" + "S1POE\0" + "S2PIE\0" + "S2POE\0" "SB\0" + "SCTLR2\0" + "SEBEP\0" + "SEL2\0" "SHA1\0" - "SHA2\0" + "SHA256\0" "SHA3\0" "SHA512\0" "SM3\0" "SM4\0" + "SME\0" + "SME2\0" + "SME2_1\0" + "SME_B16B16\0" + "SME_B16F32\0" + "SME_BI32I32\0" + "SME_F16F16\0" + "SME_F16F32\0" + "SME_F32F32\0" + "SME_F64F64\0" + "SME_F8F16\0" + "SME_F8F32\0" + "SME_FA64\0" + "SME_I16I32\0" + "SME_I16I64\0" + "SME_I8I32\0" + "SME_LUTv2\0" + "SPE\0" + "SPE1_1\0" + "SPE1_2\0" + "SPE1_3\0" + "SPE1_4\0" + "SPE_ALTCLK\0" + "SPE_CRR\0" + "SPE_EFT\0" + "SPE_FDS\0" + "SPE_FPF\0" + "SPE_SME\0" + "SPECRES\0" + "SPECRES2\0" + "SPMU\0" "SSBS\0" + "SSBS2\0" + "SSVE_FP8DOT2\0" + "SSVE_FP8DOT4\0" + "SSVE_FP8FMA\0" "SVE\0" + "SVE2\0" + "SVE2_1\0" + "SVE_AES\0" + "SVE_B16B16\0" "SVE_BF16\0" + "SVE_BITPERM\0" + "SVE_EBF16\0" "SVE_F32MM\0" "SVE_F64MM\0" "SVE_I8MM\0" - "SVE_PMULL\0" - "SVE2\0" - "SVE2_AES\0" - "SVE2_BITPERM\0" - "SVE2_SHA3\0" - "SVE2_SM4\0" + "SVE_PMULL128\0" + "SVE_SHA3\0" + "SVE_SM4\0" + "SYSINSTR128\0" + "SYSREG128\0" + "THE\0" + "TLBIOS\0" + "TLBIRANGE\0" + "TLBIW\0" "TME\0" + "TRF\0" + "UAO\0" + "VFP_D32\0" + "VHE\0" + "VMID16\0" + "WFXT\0" + "XNX\0" + "XS\0" "<Unknown>\0"; static const uint16_t sFeatureIndex[] = { - 0, 5, 11, 19, 25, 31, 38, 47, 56, 65, 74, 83, 92, 101, 107, 113, 119, 127, - 131, 139, 145, 150, 154, 160, 166, 170, 174, 182, 187, 192, 200, 206, 215, - 223, 232, 238, 243, 249, 255, 259, 263, 273, 277, 281, 287, 291, 294, 299, - 304, 309, 316, 320, 324, 329, 333, 342, 352, 362, 371, 381, 386, 395, 408, - 418, 427, 431 + 0, 5, 11, 17, 24, 30, 38, 43, 49, 53, 57, 61, 66, 73, 79, 85, 90, 95, 99, + 103, 109, 113, 120, 125, 139, 143, 148, 154, 160, 165, 170, 177, 182, 187, + 191, 195, 203, 207, 212, 217, 223, 229, 233, 239, 244, 253, 258, 262, 267, + 271, 277, 284, 289, 292, 297, 306, 310, 318, 326, 333, 338, 346, 350, 357, + 364, 369, 375, 379, 383, 388, 394, 399, 405, 411, 415, 421, 425, 431, 438, + 445, 450, 463, 470, 474, 481, 486, 490, 494, 499, 503, 508, 513, 517, 522, + 527, 532, 547, 557, 576, 596, 608, 623, 638, 644, 648, 651, 655, 659, 664, + 669, 675, 680, 684, 690, 698, 702, 709, 714, 721, 725, 729, 733, 742, 748, + 754, 760, 766, 772, 778, 781, 788, 794, 799, 804, 811, 816, 823, 827, 831, + 835, 840, 847, 858, 869, 881, 892, 903, 914, 925, 935, 945, 954, 965, 976, + 986, 996, 1000, 1007, 1014, 1021, 1028, 1039, 1047, 1055, 1063, 1071, 1079, + 1087, 1096, 1101, 1106, 1112, 1125, 1138, 1150, 1154, 1159, 1166, 1174, 1185, + 1194, 1206, 1216, 1226, 1236, 1245, 1258, 1267, 1275, 1287, 1297, 1301, 1308, + 1318, 1324, 1328, 1332, 1336, 1344, 1348, 1355, 1360, 1364, 1367 }; // @EnumStringEnd@ @@ -111,14 +258,14 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatCondCode(String& sb, CondCode c static const char condCodeData[] = "al\0" "na\0" "eq\0" "ne\0" - "cs\0" "cc\0" "mi\0" "pl\0" "vs\0" "vc\0" + "hs\0" "lo\0" "mi\0" "pl\0" "vs\0" "vc\0" "hi\0" "ls\0" "ge\0" "lt\0" "gt\0" "le\0" "<Unknown>"; return sb.append(condCodeData + Support::min<uint32_t>(uint32_t(cc), 16u) * 3); } ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shiftOp) noexcept { - const char* str = "<Unknown>"; + const char* str = nullptr; switch (shiftOp) { case ShiftOp::kLSL: str = "lsl"; break; case ShiftOp::kLSR: str = "lsr"; break; @@ -134,10 +281,308 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shi case ShiftOp::kSXTH: str = "sxth"; break; case ShiftOp::kSXTW: str = "sxtw"; break; case ShiftOp::kSXTX: str = "sxtx"; break; + default: str = "<Unknown>"; break; } return sb.append(str); } +// arm::FormatterInternal - Format Register +// ======================================== + +struct FormatElementData { + char letter; + uint8_t elementCount; + uint8_t onlyIndex; + uint8_t reserved; +}; + +static constexpr FormatElementData formatElementDataTable[9] = { + { '?' , 0 , 0, 0 }, // None + { 'b' , 16, 0, 0 }, // bX or b[index] + { 'h' , 8 , 0, 0 }, // hX or h[index] + { 's' , 4 , 0, 0 }, // sX or s[index] + { 'd' , 2 , 0, 0 }, // dX or d[index] + { 'b' , 4 , 1, 0 }, // ?? or b4[index] + { 'h' , 2 , 1, 0 }, // ?? or h2[index] + { '?' , 0 , 0, 0 }, // invalid (possibly stored in Operand) + { '?' , 0 , 0, 0 } // invalid (never stored in Operand, bug...) +}; + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + RegType regType, + uint32_t rId, + uint32_t elementType, + uint32_t elementIndex) noexcept { + + DebugUtils::unused(flags); + DebugUtils::unused(arch); + + static const char bhsdq[] = "bhsdq"; + + bool virtRegFormatted = false; + +#ifndef ASMJIT_NO_COMPILER + if (Operand::isVirtId(rId)) { + if (emitter && emitter->isCompiler()) { + const BaseCompiler* cc = static_cast<const BaseCompiler*>(emitter); + if (cc->isVirtIdValid(rId)) { + VirtReg* vReg = cc->virtRegById(rId); + ASMJIT_ASSERT(vReg != nullptr); + + const char* name = vReg->name(); + if (name && name[0] != '\0') + ASMJIT_PROPAGATE(sb.append(name)); + else + ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(rId)))); + + virtRegFormatted = true; + } + } + } +#else + DebugUtils::unused(emitter, flags); +#endif + + if (!virtRegFormatted) { + char letter = '\0'; + switch (regType) { + case RegType::kARM_VecB: + case RegType::kARM_VecH: + case RegType::kARM_VecS: + case RegType::kARM_VecD: + case RegType::kARM_VecV: + letter = bhsdq[uint32_t(regType) - uint32_t(RegType::kARM_VecB)]; + if (elementType) + letter = 'v'; + break; + + case RegType::kARM_GpW: + if (Environment::is64Bit(arch)) { + letter = 'w'; + + if (rId == a64::Gp::kIdZr) + return sb.append("wzr", 3); + + if (rId == a64::Gp::kIdSp) + return sb.append("wsp", 3); + } + else { + letter = 'r'; + } + break; + + case RegType::kARM_GpX: + if (Environment::is64Bit(arch)) { + if (rId == a64::Gp::kIdZr) + return sb.append("xzr", 3); + if (rId == a64::Gp::kIdSp) + return sb.append("sp", 2); + + letter = 'x'; + break; + } + + // X registers are undefined in 32-bit mode. + ASMJIT_FALLTHROUGH; + + default: + ASMJIT_PROPAGATE(sb.appendFormat("<Reg-%u>?%u", uint32_t(regType), rId)); + break; + } + + if (letter) + ASMJIT_PROPAGATE(sb.appendFormat("%c%u", letter, rId)); + } + + constexpr uint32_t kElementTypeCount = uint32_t(a64::VecElementType::kMaxValue) + 1; + if (elementType) { + elementType = Support::min(elementType, kElementTypeCount); + + FormatElementData elementData = formatElementDataTable[elementType]; + uint32_t elementCount = elementData.elementCount; + + if (regType == RegType::kARM_VecD) { + elementCount /= 2u; + } + + ASMJIT_PROPAGATE(sb.append('.')); + if (elementCount) { + ASMJIT_PROPAGATE(sb.appendUInt(elementCount)); + } + ASMJIT_PROPAGATE(sb.append(elementData.letter)); + } + + if (elementIndex != 0xFFFFFFFFu) { + ASMJIT_PROPAGATE(sb.appendFormat("[%u]", elementIndex)); + } + + return kErrorOk; +} + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegisterList( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + RegType regType, + uint32_t rMask) noexcept { + + bool first = true; + + ASMJIT_PROPAGATE(sb.append('{')); + while (rMask != 0u) { + uint32_t start = Support::ctz(rMask); + uint32_t count = 0u; + + uint32_t mask = 1u << start; + do { + rMask &= ~mask; + mask <<= 1u; + count++; + } while (rMask & mask); + + if (!first) + ASMJIT_PROPAGATE(sb.append(", ")); + + ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, regType, start, 0, 0xFFFFFFFFu)); + if (count >= 2u) { + ASMJIT_PROPAGATE(sb.append('-')); + ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, regType, start + count - 1, 0, 0xFFFFFFFFu)); + } + + first = false; + } + ASMJIT_PROPAGATE(sb.append('}')); + + return kErrorOk; +} + +// a64::FormatterInternal - Format Operand +// ======================================= + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + const Operand_& op) noexcept { + + if (op.isReg()) { + const BaseReg& reg = op.as<BaseReg>(); + + uint32_t elementType = op._signature.getField<BaseVec::kSignatureRegElementTypeMask>(); + uint32_t elementIndex = op.as<BaseVec>().elementIndex(); + + if (!op.as<BaseVec>().hasElementIndex()) + elementIndex = 0xFFFFFFFFu; + + return formatRegister(sb, flags, emitter, arch, reg.type(), reg.id(), elementType, elementIndex); + } + + if (op.isMem()) { + const Mem& m = op.as<Mem>(); + ASMJIT_PROPAGATE(sb.append('[')); + + if (m.hasBase()) { + if (m.hasBaseLabel()) { + ASMJIT_PROPAGATE(Formatter::formatLabel(sb, flags, emitter, m.baseId())); + } + else { + FormatFlags modifiedFlags = flags; + if (m.isRegHome()) { + ASMJIT_PROPAGATE(sb.append('&')); + modifiedFlags &= ~FormatFlags::kRegCasts; + } + ASMJIT_PROPAGATE(formatRegister(sb, modifiedFlags, emitter, arch, m.baseType(), m.baseId())); + } + } + else { + // ARM really requires base. + if (m.hasIndex() || m.hasOffset()) { + ASMJIT_PROPAGATE(sb.append("<None>")); + } + } + + // The post index makes it look like there was another operand, but it's + // still the part of AsmJit's `arm::Mem` operand so it's consistent with + // other architectures. + if (m.isPostIndex()) + ASMJIT_PROPAGATE(sb.append(']')); + + if (m.hasIndex()) { + ASMJIT_PROPAGATE(sb.append(", ")); + ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, m.indexType(), m.indexId())); + } + + if (m.hasOffset()) { + ASMJIT_PROPAGATE(sb.append(", ")); + + int64_t off = int64_t(m.offset()); + uint32_t base = 10; + + if (Support::test(flags, FormatFlags::kHexOffsets) && uint64_t(off) > 9) + base = 16; + + if (base == 10) { + ASMJIT_PROPAGATE(sb.appendInt(off, base)); + } + else { + ASMJIT_PROPAGATE(sb.append("0x")); + ASMJIT_PROPAGATE(sb.appendUInt(uint64_t(off), base)); + } + } + + if (m.hasShift()) { + ASMJIT_PROPAGATE(sb.append(' ')); + if (!m.isPreOrPost()) + ASMJIT_PROPAGATE(formatShiftOp(sb, m.shiftOp())); + ASMJIT_PROPAGATE(sb.appendFormat(" %u", m.shift())); + } + + if (!m.isPostIndex()) + ASMJIT_PROPAGATE(sb.append(']')); + + if (m.isPreIndex()) + ASMJIT_PROPAGATE(sb.append('!')); + + return kErrorOk; + } + + if (op.isImm()) { + const Imm& i = op.as<Imm>(); + int64_t val = i.value(); + uint32_t predicate = i.predicate(); + + if (predicate) { + ASMJIT_PROPAGATE(formatShiftOp(sb, ShiftOp(predicate))); + ASMJIT_PROPAGATE(sb.append(' ')); + } + + if (Support::test(flags, FormatFlags::kHexImms) && uint64_t(val) > 9) { + ASMJIT_PROPAGATE(sb.append("0x")); + return sb.appendUInt(uint64_t(val), 16); + } + else { + return sb.appendInt(val, 10); + } + } + + if (op.isLabel()) { + return Formatter::formatLabel(sb, flags, emitter, op.id()); + } + + if (op.isRegList()) { + const BaseRegList& regList = op.as<BaseRegList>(); + return formatRegisterList(sb, flags, emitter, arch, regList.type(), regList.list()); + } + + return sb.append("<None>"); +} + ASMJIT_END_SUB_NAMESPACE #endif // !ASMJIT_NO_LOGGING diff --git a/3rdparty/asmjit/src/asmjit/arm/armformatter_p.h b/3rdparty/asmjit/src/asmjit/arm/armformatter_p.h index 582173054a8..20b4812e913 100644 --- a/3rdparty/asmjit/src/asmjit/arm/armformatter_p.h +++ b/3rdparty/asmjit/src/asmjit/arm/armformatter_p.h @@ -33,6 +33,31 @@ Error ASMJIT_CDECL formatShiftOp( String& sb, ShiftOp shiftOp) noexcept; +Error ASMJIT_CDECL formatRegister( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + RegType regType, + uint32_t rId, + uint32_t elementType = 0, + uint32_t elementIndex = 0xFFFFFFFF) noexcept; + +Error ASMJIT_CDECL formatRegisterList( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + RegType regType, + uint32_t rMask) noexcept; + +Error ASMJIT_CDECL formatOperand( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + const Operand_& op) noexcept; + } // {FormatterInternal} //! \} diff --git a/3rdparty/asmjit/src/asmjit/arm/armglobals.h b/3rdparty/asmjit/src/asmjit/arm/armglobals.h index 506646f8068..851f6708601 100644 --- a/3rdparty/asmjit/src/asmjit/arm/armglobals.h +++ b/3rdparty/asmjit/src/asmjit/arm/armglobals.h @@ -14,8 +14,4 @@ //! //! API shared between AArch32 & AArch64 backends. -ASMJIT_BEGIN_SUB_NAMESPACE(arm) - -ASMJIT_END_SUB_NAMESPACE - #endif // ASMJIT_ARM_ARMGLOBALS_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/arm/armoperand.h b/3rdparty/asmjit/src/asmjit/arm/armoperand.h index ede829d9c18..583a3d8c326 100644 --- a/3rdparty/asmjit/src/asmjit/arm/armoperand.h +++ b/3rdparty/asmjit/src/asmjit/arm/armoperand.h @@ -19,18 +19,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(arm) class Reg; class Mem; -class Gp; -class GpW; -class GpX; - -class Vec; -class VecB; -class VecH; -class VecS; -class VecD; -class VecV; - -//! Register traits (ARM/AArch64). +//! Register traits (AArch32/AArch64). //! //! Register traits contains information about a particular register type. It's used by asmjit to setup register //! information on-the-fly and to populate tables that contain register information (this way it's possible to @@ -39,128 +28,106 @@ template<RegType kRegType> struct RegTraits : public BaseRegTraits {}; //! \cond -// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ -// | Reg | Reg-Type | Reg-Group |Sz |Cnt| TypeId | -// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ -ASMJIT_DEFINE_REG_TRAITS(GpW , RegType::kARM_GpW , RegGroup::kGp , 4 , 32, TypeId::kInt32 ); -ASMJIT_DEFINE_REG_TRAITS(GpX , RegType::kARM_GpX , RegGroup::kGp , 8 , 32, TypeId::kInt64 ); -ASMJIT_DEFINE_REG_TRAITS(VecB , RegType::kARM_VecB , RegGroup::kVec , 1 , 32, TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(VecH , RegType::kARM_VecH , RegGroup::kVec , 2 , 32, TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(VecS , RegType::kARM_VecS , RegGroup::kVec , 4 , 32, TypeId::kInt32x1 ); -ASMJIT_DEFINE_REG_TRAITS(VecD , RegType::kARM_VecD , RegGroup::kVec , 8 , 32, TypeId::kInt32x2 ); -ASMJIT_DEFINE_REG_TRAITS(VecV , RegType::kARM_VecV , RegGroup::kVec , 16, 32, TypeId::kInt32x4 ); +// <--------------------+------------------------+------------------------+---+------------------+ +// | Reg-Type | Reg-Group |Sz | TypeId | +// <--------------------+------------------------+------------------------+---+------------------+ +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_GpW , RegGroup::kGp , 4 , TypeId::kInt32 ); // AArch32 & AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_GpX , RegGroup::kGp , 8 , TypeId::kInt64 ); // AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecB , RegGroup::kVec , 1 , TypeId::kVoid ); // AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecH , RegGroup::kVec , 2 , TypeId::kVoid ); // AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecS , RegGroup::kVec , 4 , TypeId::kInt32x1 ); // AArch32 & AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecD , RegGroup::kVec , 8 , TypeId::kInt32x2 ); // AArch32 & AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecQ , RegGroup::kVec , 16, TypeId::kInt32x4 ); // AArch32 & AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_PC , RegGroup::kPC , 8 , TypeId::kInt64 ); // AArch64 //! \endcond -//! Register (ARM). +//! Register operand that can represent AArch32 and AArch64 registers. class Reg : public BaseReg { public: ASMJIT_DEFINE_ABSTRACT_REG(Reg, BaseReg) - //! Gets whether the register is a `R|W` register (32-bit). - inline constexpr bool isGpW() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpW>::kSignature; } + //! Gets whether the register is either `R` or `W` register (32-bit). + ASMJIT_INLINE_NODEBUG constexpr bool isGpR() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpW>::kSignature; } + //! Gets whether the register is either `R` or `W` register (32-bit). + ASMJIT_INLINE_NODEBUG constexpr bool isGpW() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpW>::kSignature; } //! Gets whether the register is an `X` register (64-bit). - inline constexpr bool isGpX() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpX>::kSignature; } + ASMJIT_INLINE_NODEBUG constexpr bool isGpX() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpX>::kSignature; } + //! Gets whether the register is a VEC-B register (8-bit). - inline constexpr bool isVecB() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecB>::kSignature; } + ASMJIT_INLINE_NODEBUG constexpr bool isVecB() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecB>::kSignature; } //! Gets whether the register is a VEC-H register (16-bit). - inline constexpr bool isVecH() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecH>::kSignature; } + ASMJIT_INLINE_NODEBUG constexpr bool isVecH() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecH>::kSignature; } //! Gets whether the register is a VEC-S register (32-bit). - inline constexpr bool isVecS() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecS>::kSignature; } + ASMJIT_INLINE_NODEBUG constexpr bool isVecS() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecS>::kSignature; } //! Gets whether the register is a VEC-D register (64-bit). - inline constexpr bool isVecD() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecD>::kSignature; } + ASMJIT_INLINE_NODEBUG constexpr bool isVecD() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecD>::kSignature; } //! Gets whether the register is a VEC-Q register (128-bit). - inline constexpr bool isVecQ() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; } - + ASMJIT_INLINE_NODEBUG constexpr bool isVecQ() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; } //! Gets whether the register is either VEC-D (64-bit) or VEC-Q (128-bit). - inline constexpr bool isVecDOrQ() const noexcept { return uint32_t(type()) - uint32_t(RegType::kARM_VecD) <= 1u; } - + ASMJIT_INLINE_NODEBUG constexpr bool isVecDOrQ() const noexcept { return uint32_t(type()) - uint32_t(RegType::kARM_VecD) <= 1u; } //! Gets whether the register is a VEC-V register (128-bit). - inline constexpr bool isVecV() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; } + ASMJIT_INLINE_NODEBUG constexpr bool isVecV() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; } + + //! Gets whether the register is an 8-bit vector register or view, alias if \ref isVecB(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec8() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecB>::kSignature; } + //! Gets whether the register is a 16-bit vector register or view, alias if \ref isVecH(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec16() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecH>::kSignature; } + //! Gets whether the register is a 32-bit vector register or view, alias if \ref isVecS(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec32() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecS>::kSignature; } + //! Gets whether the register is a 64-bit vector register or view, alias if \ref isVecD(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec64() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecD>::kSignature; } + //! Gets whether the register is a 128-bit vector register or view, alias if \ref isVecQ(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; } template<RegType kRegType> - inline void setRegT(uint32_t id) noexcept { + ASMJIT_INLINE_NODEBUG void setRegT(uint32_t id) noexcept { setSignature(RegTraits<kRegType>::kSignature); setId(id); } - inline void setTypeAndId(RegType type, uint32_t id) noexcept { + ASMJIT_INLINE_NODEBUG void setTypeAndId(RegType type, uint32_t id) noexcept { setSignature(signatureOf(type)); setId(id); } - static inline RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToGroup(type); } - static inline TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToTypeId(type); } - static inline OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToSignature(type); } + static ASMJIT_INLINE_NODEBUG RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToGroup(type); } + static ASMJIT_INLINE_NODEBUG TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToTypeId(type); } + static ASMJIT_INLINE_NODEBUG OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToSignature(type); } template<RegType kRegType> - static inline RegGroup groupOfT() noexcept { return RegTraits<kRegType>::kGroup; } + static ASMJIT_INLINE_NODEBUG RegGroup groupOfT() noexcept { return RegTraits<kRegType>::kGroup; } template<RegType kRegType> - static inline TypeId typeIdOfT() noexcept { return RegTraits<kRegType>::kTypeId; } + static ASMJIT_INLINE_NODEBUG TypeId typeIdOfT() noexcept { return RegTraits<kRegType>::kTypeId; } template<RegType kRegType> - static inline OperandSignature signatureOfT() noexcept { return RegTraits<kRegType>::kSignature; } - - static inline bool isGpW(const Operand_& op) noexcept { return op.as<Reg>().isGpW(); } - static inline bool isGpX(const Operand_& op) noexcept { return op.as<Reg>().isGpX(); } - static inline bool isVecB(const Operand_& op) noexcept { return op.as<Reg>().isVecB(); } - static inline bool isVecH(const Operand_& op) noexcept { return op.as<Reg>().isVecH(); } - static inline bool isVecS(const Operand_& op) noexcept { return op.as<Reg>().isVecS(); } - static inline bool isVecD(const Operand_& op) noexcept { return op.as<Reg>().isVecD(); } - static inline bool isVecQ(const Operand_& op) noexcept { return op.as<Reg>().isVecQ(); } - static inline bool isVecV(const Operand_& op) noexcept { return op.as<Reg>().isVecV(); } - - static inline bool isGpW(const Operand_& op, uint32_t id) noexcept { return isGpW(op) & (op.id() == id); } - static inline bool isGpX(const Operand_& op, uint32_t id) noexcept { return isGpX(op) & (op.id() == id); } - static inline bool isVecB(const Operand_& op, uint32_t id) noexcept { return isVecB(op) & (op.id() == id); } - static inline bool isVecH(const Operand_& op, uint32_t id) noexcept { return isVecH(op) & (op.id() == id); } - static inline bool isVecS(const Operand_& op, uint32_t id) noexcept { return isVecS(op) & (op.id() == id); } - static inline bool isVecD(const Operand_& op, uint32_t id) noexcept { return isVecD(op) & (op.id() == id); } - static inline bool isVecQ(const Operand_& op, uint32_t id) noexcept { return isVecQ(op) & (op.id() == id); } - static inline bool isVecV(const Operand_& op, uint32_t id) noexcept { return isVecV(op) & (op.id() == id); } -}; - -//! General purpose register (ARM). -class Gp : public Reg { -public: - ASMJIT_DEFINE_ABSTRACT_REG(Gp, Reg) - - //! Special register id. - enum Id : uint32_t { - //! Register that depends on OS, could be used as TLS offset. - kIdOs = 18, - //! Frame pointer. - kIdFp = 29, - //! Link register. - kIdLr = 30, - //! Stack register id. - kIdSp = 31, - //! Zero register id. - //! - //! Although zero register has the same id as stack register it has a special treatment, because we need to be - //! able to distinguish between these two at API level. Some intructions were designed to be used with SP and - //! some other with ZR - so we need a way to distinguish these two to make sure we emit the right thing. - //! - //! The number 63 is not random, when you perform `id & 31` you would always get 31 for both SP and ZR inputs, - //! which is the identifier used by AArch64 ISA to encode either SP or ZR depending on the instruction. - kIdZr = 63 - }; - - inline constexpr bool isZR() const noexcept { return id() == kIdZr; } - inline constexpr bool isSP() const noexcept { return id() == kIdSp; } - - //! Cast this register to a 32-bit R|W. - inline GpW w() const noexcept; - //! Cast this register to a 64-bit X. - inline GpX x() const noexcept; + static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfT() noexcept { return OperandSignature{RegTraits<kRegType>::kSignature}; } + + static ASMJIT_INLINE_NODEBUG bool isGpW(const Operand_& op) noexcept { return op.as<Reg>().isGpW(); } + static ASMJIT_INLINE_NODEBUG bool isGpX(const Operand_& op) noexcept { return op.as<Reg>().isGpX(); } + static ASMJIT_INLINE_NODEBUG bool isVecB(const Operand_& op) noexcept { return op.as<Reg>().isVecB(); } + static ASMJIT_INLINE_NODEBUG bool isVecH(const Operand_& op) noexcept { return op.as<Reg>().isVecH(); } + static ASMJIT_INLINE_NODEBUG bool isVecS(const Operand_& op) noexcept { return op.as<Reg>().isVecS(); } + static ASMJIT_INLINE_NODEBUG bool isVecD(const Operand_& op) noexcept { return op.as<Reg>().isVecD(); } + static ASMJIT_INLINE_NODEBUG bool isVecQ(const Operand_& op) noexcept { return op.as<Reg>().isVecQ(); } + static ASMJIT_INLINE_NODEBUG bool isVecV(const Operand_& op) noexcept { return op.as<Reg>().isVecV(); } + + static ASMJIT_INLINE_NODEBUG bool isGpW(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isGpW(op)) & unsigned(op.id() == id)); } + static ASMJIT_INLINE_NODEBUG bool isGpX(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isGpX(op)) & unsigned(op.id() == id)); } + static ASMJIT_INLINE_NODEBUG bool isVecB(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecB(op)) & unsigned(op.id() == id)); } + static ASMJIT_INLINE_NODEBUG bool isVecH(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecH(op)) & unsigned(op.id() == id)); } + static ASMJIT_INLINE_NODEBUG bool isVecS(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecS(op)) & unsigned(op.id() == id)); } + static ASMJIT_INLINE_NODEBUG bool isVecD(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecD(op)) & unsigned(op.id() == id)); } + static ASMJIT_INLINE_NODEBUG bool isVecQ(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecQ(op)) & unsigned(op.id() == id)); } + static ASMJIT_INLINE_NODEBUG bool isVecV(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecV(op)) & unsigned(op.id() == id)); } }; -//! Vector register (ARM). -class Vec : public Reg { +//! Vector register base - a common base for both AArch32 & AArch64 vector register. +class BaseVec : public Reg { public: - ASMJIT_DEFINE_ABSTRACT_REG(Vec, Reg) + ASMJIT_DEFINE_ABSTRACT_REG(BaseVec, Reg) - //! Additional signature bits used by arm::Vec. + //! Additional signature bits used by a vector register. enum AdditionalBits : uint32_t { // Register element type (3 bits). // |........|........|.XXX....|........| @@ -178,202 +145,21 @@ public: kSignatureRegElementIndexMask = 0x0F << kSignatureRegElementIndexShift }; - //! Element type. - enum ElementType : uint32_t { - //! No element type specified. - kElementTypeNone = 0, - //! Byte elements (B8 or B16). - kElementTypeB, - //! Halfword elements (H4 or H8). - kElementTypeH, - //! Singleword elements (S2 or S4). - kElementTypeS, - //! Doubleword elements (D2). - kElementTypeD, - //! Byte elements grouped by 4 bytes (B4). - //! - //! \note This element-type is only used by few instructions. - kElementTypeB4, - //! Halfword elements grouped by 2 halfwords (H2). - //! - //! \note This element-type is only used by few instructions. - kElementTypeH2, - - //! Count of element types. - kElementTypeCount - }; - - //! \cond - //! Shortcuts. - enum SignatureReg : uint32_t { - kSignatureElementB = kElementTypeB << kSignatureRegElementTypeShift, - kSignatureElementH = kElementTypeH << kSignatureRegElementTypeShift, - kSignatureElementS = kElementTypeS << kSignatureRegElementTypeShift, - kSignatureElementD = kElementTypeD << kSignatureRegElementTypeShift, - kSignatureElementB4 = kElementTypeB4 << kSignatureRegElementTypeShift, - kSignatureElementH2 = kElementTypeH2 << kSignatureRegElementTypeShift - }; - //! \endcond - - //! Returns whether the register has associated an element type. - inline constexpr bool hasElementType() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask>(); } //! Returns whether the register has element index (it's an element index access). - inline constexpr bool hasElementIndex() const noexcept { return _signature.hasField<kSignatureRegElementFlagMask>(); } - //! Returns whether the reggister has element type or element index (or both). - inline constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask | kSignatureRegElementFlagMask>(); } - - //! Returns element type of the register. - inline constexpr uint32_t elementType() const noexcept { return _signature.getField<kSignatureRegElementTypeMask>(); } - //! Sets element type of the register to `elementType`. - inline void setElementType(uint32_t elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(elementType); } - //! Resets element type to none. - inline void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); } - + ASMJIT_INLINE_NODEBUG constexpr bool hasElementIndex() const noexcept { return _signature.hasField<kSignatureRegElementFlagMask>(); } //! Returns element index of the register. - inline constexpr uint32_t elementIndex() const noexcept { return _signature.getField<kSignatureRegElementIndexMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t elementIndex() const noexcept { return _signature.getField<kSignatureRegElementIndexMask>(); } //! Sets element index of the register to `elementType`. - inline void setElementIndex(uint32_t elementIndex) noexcept { + ASMJIT_INLINE_NODEBUG void setElementIndex(uint32_t elementIndex) noexcept { _signature |= kSignatureRegElementFlagMask; _signature.setField<kSignatureRegElementIndexMask>(elementIndex); } //! Resets element index of the register. - inline void resetElementIndex() noexcept { + ASMJIT_INLINE_NODEBUG void resetElementIndex() noexcept { _signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask); } - - inline constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB); } - inline constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH); } - inline constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); } - inline constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature); } - - inline constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB); } - inline constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH); } - inline constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS); } - inline constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD); } - inline constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4); } - inline constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2); } - - //! Creates a cloned register with element access. - inline Vec at(uint32_t elementIndex) const noexcept { - return Vec((signature() & ~kSignatureRegElementIndexMask) | (elementIndex << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id()); - } - - //! Cast this register to an 8-bit B register (scalar). - inline VecB b() const noexcept; - //! Cast this register to a 16-bit H register (scalar). - inline VecH h() const noexcept; - //! Cast this register to a 32-bit S register (scalar). - inline VecS s() const noexcept; - //! Cast this register to a 64-bit D register (scalar). - inline VecD d() const noexcept; - //! Cast this register to a 128-bit Q register (scalar). - inline VecV q() const noexcept; - //! Cast this register to a 128-bit V register. - inline VecV v() const noexcept; - - //! Cast this register to a 128-bit V.B[elementIndex] register. - inline VecV b(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.H[elementIndex] register. - inline VecV h(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.S[elementIndex] register. - inline VecV s(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.D[elementIndex] register. - inline VecV d(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.H2[elementIndex] register. - inline VecV h2(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.B4[elementIndex] register. - inline VecV b4(uint32_t elementIndex) const noexcept; - - //! Cast this register to V.8B. - inline VecD b8() const noexcept; - //! Cast this register to V.16B. - inline VecV b16() const noexcept; - //! Cast this register to V.2H. - inline VecS h2() const noexcept; - //! Cast this register to V.4H. - inline VecD h4() const noexcept; - //! Cast this register to V.8H. - inline VecV h8() const noexcept; - //! Cast this register to V.2S. - inline VecD s2() const noexcept; - //! Cast this register to V.4S. - inline VecV s4() const noexcept; - //! Cast this register to V.2D. - inline VecV d2() const noexcept; - - static inline constexpr OperandSignature _makeElementAccessSignature(uint32_t elementType, uint32_t elementIndex) noexcept { - return OperandSignature{ - uint32_t(RegTraits<RegType::kARM_VecV>::kSignature) | - uint32_t(kSignatureRegElementFlagMask) | - uint32_t(elementType << kSignatureRegElementTypeShift) | - uint32_t(elementIndex << kSignatureRegElementIndexShift)}; - } }; -//! 32-bit GPW (AArch64) and/or GPR (ARM/AArch32) register. -class GpW : public Gp { ASMJIT_DEFINE_FINAL_REG(GpW, Gp, RegTraits<RegType::kARM_GpW>) }; -//! 64-bit GPX (AArch64) register. -class GpX : public Gp { ASMJIT_DEFINE_FINAL_REG(GpX, Gp, RegTraits<RegType::kARM_GpX>) }; - -//! 8-bit view (S) of VFP/SIMD register. -class VecB : public Vec { ASMJIT_DEFINE_FINAL_REG(VecB, Vec, RegTraits<RegType::kARM_VecB>) }; -//! 16-bit view (S) of VFP/SIMD register. -class VecH : public Vec { ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits<RegType::kARM_VecH>) }; -//! 32-bit view (S) of VFP/SIMD register. -class VecS : public Vec { ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits<RegType::kARM_VecS>) }; -//! 64-bit view (D) of VFP/SIMD register. -class VecD : public Vec { ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits<RegType::kARM_VecD>) }; -//! 128-bit vector register (Q or V). -class VecV : public Vec { ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits<RegType::kARM_VecV>) }; - -inline GpW Gp::w() const noexcept { return GpW(id()); } -inline GpX Gp::x() const noexcept { return GpX(id()); } - -inline VecB Vec::b() const noexcept { return VecB(id()); } -inline VecH Vec::h() const noexcept { return VecH(id()); } -inline VecS Vec::s() const noexcept { return VecS(id()); } -inline VecD Vec::d() const noexcept { return VecD(id()); } -inline VecV Vec::q() const noexcept { return VecV(id()); } -inline VecV Vec::v() const noexcept { return VecV(id()); } - -inline VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB, elementIndex), id()); } -inline VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH, elementIndex), id()); } -inline VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeS, elementIndex), id()); } -inline VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeD, elementIndex), id()); } -inline VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH2, elementIndex), id()); } -inline VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB4, elementIndex), id()); } - -inline VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); } -inline VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); } -inline VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); } -inline VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); } -inline VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); } -inline VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); } -inline VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); } -inline VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); } - -#ifndef _DOXYGEN -namespace regs { -#endif - -//! Creates a 32-bit W register operand (ARM/AArch64). -static inline constexpr GpW w(uint32_t id) noexcept { return GpW(id); } -//! Creates a 64-bit X register operand (AArch64). -static inline constexpr GpX x(uint32_t id) noexcept { return GpX(id); } -//! Creates a 32-bit S register operand (ARM/AArch64). -static inline constexpr VecS s(uint32_t id) noexcept { return VecS(id); } -//! Creates a 64-bit D register operand (ARM/AArch64). -static inline constexpr VecD d(uint32_t id) noexcept { return VecD(id); } -//! Creates a 1282-bit V register operand (ARM/AArch64). -static inline constexpr VecV v(uint32_t id) noexcept { return VecV(id); } - -#ifndef _DOXYGEN -} // {regs} - -// Make `arm::regs` accessible through `arm` namespace as well. -using namespace regs; -#endif - //! Memory operand (ARM). class Mem : public BaseMem { public: @@ -385,64 +171,59 @@ public: kSignatureMemShiftValueShift = 14, kSignatureMemShiftValueMask = 0x1Fu << kSignatureMemShiftValueShift, - // Shift operation type (4 bits). + // Index shift operation (4 bits). // |........|XXXX....|........|........| - kSignatureMemPredicateShift = 20, - kSignatureMemPredicateMask = 0x0Fu << kSignatureMemPredicateShift - }; - //! \endcond + kSignatureMemShiftOpShift = 20, + kSignatureMemShiftOpMask = 0x0Fu << kSignatureMemShiftOpShift, - //! Memory offset mode. - //! - //! Additional constants that can be used with the `predicate`. - enum OffsetMode : uint32_t { - //! Pre-index "[BASE, #Offset {, <shift>}]!" with write-back. - kOffsetPreIndex = 0xE, - //! Post-index "[BASE], #Offset {, <shift>}" with write-back. - kOffsetPostIndex = 0xF + // Offset mode type (2 bits). + // |......XX|........|........|........| + kSignatureMemOffsetModeShift = 24, + kSignatureMemOffsetModeMask = 0x03u << kSignatureMemOffsetModeShift }; + //! \endcond //! \name Construction & Destruction //! \{ //! Construct a default `Mem` operand, that points to [0]. - inline constexpr Mem() noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem() noexcept : BaseMem() {} - inline constexpr Mem(const Mem& other) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const Mem& other) noexcept : BaseMem(other) {} - inline explicit Mem(Globals::NoInit_) noexcept + ASMJIT_INLINE_NODEBUG explicit Mem(Globals::NoInit_) noexcept : BaseMem(Globals::NoInit) {} - inline constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept : BaseMem(signature, baseId, indexId, offset) {} - inline constexpr explicit Mem(const Label& base, int32_t off = 0, Signature signature = Signature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr explicit Mem(const Label& base, int32_t off = 0, Signature signature = Signature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(RegType::kLabelTag) | signature, base.id(), 0, off) {} - inline constexpr explicit Mem(const BaseReg& base, int32_t off = 0, Signature signature = Signature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr explicit Mem(const BaseReg& base, int32_t off = 0, Signature signature = Signature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(base.type()) | signature, base.id(), 0, off) {} - inline constexpr Mem(const BaseReg& base, const BaseReg& index, Signature signature = Signature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const BaseReg& base, const BaseReg& index, Signature signature = Signature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(base.type()) | Signature::fromMemIndexType(index.type()) | signature, base.id(), index.id(), 0) {} - inline constexpr Mem(const BaseReg& base, const BaseReg& index, const Shift& shift, Signature signature = Signature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const BaseReg& base, const BaseReg& index, const Shift& shift, Signature signature = Signature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(base.type()) | Signature::fromMemIndexType(index.type()) | - Signature::fromValue<kSignatureMemPredicateMask>(uint32_t(shift.op())) | + Signature::fromValue<kSignatureMemShiftOpMask>(uint32_t(shift.op())) | Signature::fromValue<kSignatureMemShiftValueMask>(shift.value()) | signature, base.id(), index.id(), 0) {} - inline constexpr Mem(uint64_t base, Signature signature = Signature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr explicit Mem(uint64_t base, Signature signature = Signature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {} @@ -451,7 +232,7 @@ public: //! \name Overloaded Operators //! \{ - inline Mem& operator=(const Mem& other) noexcept = default; + ASMJIT_INLINE_NODEBUG Mem& operator=(const Mem& other) noexcept = default; //! \} @@ -459,41 +240,41 @@ public: //! \{ //! Clones the memory operand. - inline constexpr Mem clone() const noexcept { return Mem(*this); } + ASMJIT_INLINE_NODEBUG constexpr Mem clone() const noexcept { return Mem(*this); } //! Gets new memory operand adjusted by `off`. - inline Mem cloneAdjusted(int64_t off) const noexcept { + ASMJIT_INLINE_NODEBUG Mem cloneAdjusted(int64_t off) const noexcept { Mem result(*this); result.addOffset(off); return result; } //! Clones the memory operand and makes it pre-index. - inline Mem pre() const noexcept { + ASMJIT_INLINE_NODEBUG Mem pre() const noexcept { Mem result(*this); - result.setPredicate(kOffsetPreIndex); + result.setOffsetMode(OffsetMode::kPreIndex); return result; } //! Clones the memory operand, applies a given offset `off` and makes it pre-index. - inline Mem pre(int64_t off) const noexcept { + ASMJIT_INLINE_NODEBUG Mem pre(int64_t off) const noexcept { Mem result(*this); - result.setPredicate(kOffsetPreIndex); + result.setOffsetMode(OffsetMode::kPreIndex); result.addOffset(off); return result; } //! Clones the memory operand and makes it post-index. - inline Mem post() const noexcept { + ASMJIT_INLINE_NODEBUG Mem post() const noexcept { Mem result(*this); - result.setPredicate(kOffsetPreIndex); + result.setOffsetMode(OffsetMode::kPostIndex); return result; } //! Clones the memory operand, applies a given offset `off` and makes it post-index. - inline Mem post(int64_t off) const noexcept { + ASMJIT_INLINE_NODEBUG Mem post(int64_t off) const noexcept { Mem result(*this); - result.setPredicate(kOffsetPostIndex); + result.setOffsetMode(OffsetMode::kPostIndex); result.addOffset(off); return result; } @@ -506,16 +287,21 @@ public: //! Converts memory `baseType` and `baseId` to `arm::Reg` instance. //! //! The memory must have a valid base register otherwise the result will be wrong. - inline Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); } + ASMJIT_INLINE_NODEBUG Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); } //! Converts memory `indexType` and `indexId` to `arm::Reg` instance. //! //! The memory must have a valid index register otherwise the result will be wrong. - inline Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); } + ASMJIT_INLINE_NODEBUG Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); } using BaseMem::setIndex; - inline void setIndex(const BaseReg& index, uint32_t shift) noexcept { + ASMJIT_INLINE_NODEBUG void setIndex(const BaseReg& index, uint32_t shift) noexcept { + setIndex(index); + setShift(shift); + } + + ASMJIT_INLINE_NODEBUG void setIndex(const BaseReg& index, Shift shift) noexcept { setIndex(index); setShift(shift); } @@ -525,97 +311,86 @@ public: //! \name ARM Specific Features //! \{ + //! Gets offset mode. + ASMJIT_INLINE_NODEBUG constexpr OffsetMode offsetMode() const noexcept { return OffsetMode(_signature.getField<kSignatureMemOffsetModeMask>()); } + //! Sets offset mode to `mode`. + ASMJIT_INLINE_NODEBUG void setOffsetMode(OffsetMode mode) noexcept { _signature.setField<kSignatureMemOffsetModeMask>(uint32_t(mode)); } + //! Resets offset mode to default (fixed offset, without write-back). + ASMJIT_INLINE_NODEBUG void resetOffsetMode() noexcept { _signature.setField<kSignatureMemOffsetModeMask>(uint32_t(OffsetMode::kFixed)); } + + //! Tests whether the current memory offset mode is fixed (see \ref OffsetMode::kFixed). + ASMJIT_INLINE_NODEBUG constexpr bool isFixedOffset() const noexcept { return offsetMode() == OffsetMode::kFixed; } + //! Tests whether the current memory offset mode is either pre-index or post-index (write-back is used). + ASMJIT_INLINE_NODEBUG constexpr bool isPreOrPost() const noexcept { return offsetMode() != OffsetMode::kFixed; } + //! Tests whether the current memory offset mode is pre-index (write-back is used). + ASMJIT_INLINE_NODEBUG constexpr bool isPreIndex() const noexcept { return offsetMode() == OffsetMode::kPreIndex; } + //! Tests whether the current memory offset mode is post-index (write-back is used). + ASMJIT_INLINE_NODEBUG constexpr bool isPostIndex() const noexcept { return offsetMode() == OffsetMode::kPostIndex; } + + //! Sets offset mode of this memory operand to pre-index (write-back is used). + ASMJIT_INLINE_NODEBUG void makePreIndex() noexcept { setOffsetMode(OffsetMode::kPreIndex); } + //! Sets offset mode of this memory operand to post-index (write-back is used). + ASMJIT_INLINE_NODEBUG void makePostIndex() noexcept { setOffsetMode(OffsetMode::kPostIndex); } + + //! Gets shift operation that is used by index register. + ASMJIT_INLINE_NODEBUG constexpr ShiftOp shiftOp() const noexcept { return ShiftOp(_signature.getField<kSignatureMemShiftOpMask>()); } + //! Sets shift operation that is used by index register. + ASMJIT_INLINE_NODEBUG void setShiftOp(ShiftOp sop) noexcept { _signature.setField<kSignatureMemShiftOpMask>(uint32_t(sop)); } + //! Resets shift operation that is used by index register to LSL (default value). + ASMJIT_INLINE_NODEBUG void resetShiftOp() noexcept { _signature.setField<kSignatureMemShiftOpMask>(uint32_t(ShiftOp::kLSL)); } + //! Gets whether the memory operand has shift (aka scale) constant. - inline constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); } + ASMJIT_INLINE_NODEBUG constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); } //! Gets the memory operand's shift (aka scale) constant. - inline constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); } //! Sets the memory operand's shift (aka scale) constant. - inline void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); } - //! Resets the memory operand's shift (aka scale) constant to zero. - inline void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); } - - //! Gets memory predicate (shift mode or offset mode), see \ref ShiftOp and \ref OffsetMode. - inline constexpr uint32_t predicate() const noexcept { return _signature.getField<kSignatureMemPredicateMask>(); } - //! Sets memory predicate to `predicate`, see `Mem::ShiftOp`. - inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<kSignatureMemPredicateMask>(predicate); } - //! Resets shift mode to LSL (default). - inline void resetPredicate() noexcept { _signature.setField<kSignatureMemPredicateMask>(0); } + ASMJIT_INLINE_NODEBUG void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); } - inline constexpr bool isFixedOffset() const noexcept { return predicate() < kOffsetPreIndex; } - inline constexpr bool isPreOrPost() const noexcept { return predicate() >= kOffsetPreIndex; } - inline constexpr bool isPreIndex() const noexcept { return predicate() == kOffsetPreIndex; } - inline constexpr bool isPostIndex() const noexcept { return predicate() == kOffsetPostIndex; } + //! Sets the memory operand's shift and shift operation. + ASMJIT_INLINE_NODEBUG void setShift(Shift shift) noexcept { + _signature.setField<kSignatureMemShiftOpMask>(uint32_t(shift.op())); + _signature.setField<kSignatureMemShiftValueMask>(shift.value()); + } - inline void resetToFixedOffset() noexcept { resetPredicate(); } - inline void makePreIndex() noexcept { setPredicate(kOffsetPreIndex); } - inline void makePostIndex() noexcept { setPredicate(kOffsetPostIndex); } + //! Resets the memory operand's shift (aka scale) constant to zero. + ASMJIT_INLINE_NODEBUG void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); } //! \} }; -//! Creates `[base.reg, offset]` memory operand (offset mode). -static inline constexpr Mem ptr(const Gp& base, int32_t offset = 0) noexcept { - return Mem(base, offset); -} - -//! Creates `[base.reg, offset]!` memory operand (pre-index mode). -static inline constexpr Mem ptr_pre(const Gp& base, int32_t offset = 0) noexcept { - return Mem(base, offset, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPreIndex)); -} - -//! Creates `[base.reg], offset` memory operand (post-index mode). -static inline constexpr Mem ptr_post(const Gp& base, int32_t offset = 0) noexcept { - return Mem(base, offset, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPostIndex)); -} - -//! Creates `[base.reg, index]` memory operand. -static inline constexpr Mem ptr(const Gp& base, const Gp& index) noexcept { - return Mem(base, index); -} - -//! Creates `[base.reg], index` memory operand (post-index mode). -static inline constexpr Mem ptr_post(const Gp& base, const Gp& index) noexcept { - return Mem(base, index, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPostIndex)); -} - -//! Creates `[base.reg, index, SHIFT_OP #shift]` memory operand. -static inline constexpr Mem ptr(const Gp& base, const Gp& index, const Shift& shift) noexcept { - return Mem(base, index, shift); -} - -//! Creates `[base + offset]` memory operand. -static inline constexpr Mem ptr(const Label& base, int32_t offset = 0) noexcept { - return Mem(base, offset); -} - -// TODO: [ARM] PC + offset address. -#if 0 -//! Creates `[PC + offset]` (relative) memory operand. -static inline constexpr Mem ptr(const PC& pc, int32_t offset = 0) noexcept { - return Mem(pc, offset); -} -#endif - -//! Creates `[base]` absolute memory operand. +//! \name Shift Operation Construction +//! \{ + +//! Constructs a `LSL #value` shift (logical shift left). +static ASMJIT_INLINE_NODEBUG constexpr Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); } +//! Constructs a `LSR #value` shift (logical shift right). +static ASMJIT_INLINE_NODEBUG constexpr Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); } +//! Constructs a `ASR #value` shift (arithmetic shift right). +static ASMJIT_INLINE_NODEBUG constexpr Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); } +//! Constructs a `ROR #value` shift (rotate right). +static ASMJIT_INLINE_NODEBUG constexpr Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); } +//! Constructs a `RRX` shift (rotate with carry by 1). +static ASMJIT_INLINE_NODEBUG constexpr Shift rrx() noexcept { return Shift(ShiftOp::kRRX, 0); } +//! Constructs a `MSL #value` shift (logical shift left filling ones). +static ASMJIT_INLINE_NODEBUG constexpr Shift msl(uint32_t value) noexcept { return Shift(ShiftOp::kMSL, value); } + +//! \} + +//! \name Memory Operand Construction +//! \{ + +//! Creates `[base]` absolute memory operand (AArch32 or AArch64). //! //! \note The concept of absolute memory operands doesn't exist on ARM, the ISA only provides PC relative addressing. //! Absolute memory operands can only be used if it's known that the PC relative offset is encodable and that it -//! would be within the limits. Absolute address is also often output from disassemblers, so AsmJit support it so it -//! can assemble it back. -static inline constexpr Mem ptr(uint64_t base) noexcept { return Mem(base); } +//! would be within the limits. Absolute address is also often output from disassemblers, so AsmJit supports it to +//! make it possible to assemble such output back. +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base) noexcept { return Mem(base); } //! \} -ASMJIT_END_SUB_NAMESPACE +//! \} -//! \cond INTERNAL -ASMJIT_BEGIN_NAMESPACE -ASMJIT_DEFINE_TYPE_ID(arm::GpW, TypeId::kInt32); -ASMJIT_DEFINE_TYPE_ID(arm::GpX, TypeId::kInt64); -ASMJIT_DEFINE_TYPE_ID(arm::VecS, TypeId::kFloat32x1); -ASMJIT_DEFINE_TYPE_ID(arm::VecD, TypeId::kFloat64x1); -ASMJIT_DEFINE_TYPE_ID(arm::VecV, TypeId::kInt32x4); -ASMJIT_END_NAMESPACE -//! \endcond +ASMJIT_END_SUB_NAMESPACE #endif // ASMJIT_ARM_ARMOPERAND_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/arm/a64utils.h b/3rdparty/asmjit/src/asmjit/arm/armutils.h index 4a88ca51724..8241eda052e 100644 --- a/3rdparty/asmjit/src/asmjit/arm/a64utils.h +++ b/3rdparty/asmjit/src/asmjit/arm/armutils.h @@ -3,20 +3,53 @@ // See asmjit.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib -#ifndef ASMJIT_ARM_A64UTILS_H_INCLUDED -#define ASMJIT_ARM_A64UTILS_H_INCLUDED +#ifndef ASMJIT_ARM_ARMUTILS_H_INCLUDED +#define ASMJIT_ARM_ARMUTILS_H_INCLUDED -#include "../arm/a64globals.h" +#include "../core/support.h" +#include "../arm/armglobals.h" -ASMJIT_BEGIN_SUB_NAMESPACE(a64) +ASMJIT_BEGIN_SUB_NAMESPACE(arm) -//! \addtogroup asmjit_a64 +//! \addtogroup asmjit_arm //! \{ -//! Public utilities and helpers for targeting AArch64 architecture. +//! Public utilities and helpers for targeting AArch32 and AArch64 architectures. namespace Utils { -//! Decomposed fields of a logical immediate value (AArch64). +//! Encodes a 12-bit immediate part of opcode that ise used by a standard 32-bit ARM encoding. +ASMJIT_MAYBE_UNUSED +static inline bool encodeAArch32Imm(uint64_t imm, uint32_t* encodedImmOut) noexcept { + if (imm & 0xFFFFFFFF00000000u) + return false; + + uint32_t v = uint32_t(imm); + uint32_t r = 0; + + if (v <= 0xFFu) { + *encodedImmOut = v; + return true; + } + + // Rotate if there are bits on both ends (LSB and MSB) + // (otherwise we would not be able to calculate the rotation with ctz). + if (v & 0xFF0000FFu) { + v = Support::ror(v, 16); + r = 16u; + } + + uint32_t n = Support::ctz(v) & ~0x1u; + r = (r - n) & 0x1Eu; + v = Support::ror(v, n); + + if (v > 0xFFu) + return false; + + *encodedImmOut = v | (r << 7); + return true; +} + +//! Decomposed fields of a logical immediate value. struct LogicalImm { uint32_t n; uint32_t s; @@ -41,7 +74,7 @@ struct LogicalImm { //! +---+--------+--------+------+ //! ``` ASMJIT_MAYBE_UNUSED -static bool encodeLogicalImm(uint64_t imm, uint32_t width, a64::Utils::LogicalImm* out) noexcept { +static bool encodeLogicalImm(uint64_t imm, uint32_t width, LogicalImm* out) noexcept { // Determine the element width, which must be 2, 4, 8, 16, 32, or 64 bits. do { width /= 2; @@ -89,24 +122,38 @@ static bool encodeLogicalImm(uint64_t imm, uint32_t width, a64::Utils::LogicalIm //! width of the operation, and must be either 32 or 64. This function can be used to test whether an immediate //! value can be used with AND, ANDS, BIC, BICS, EON, EOR, ORN, and ORR instruction. ASMJIT_MAYBE_UNUSED -static inline bool isLogicalImm(uint64_t imm, uint32_t width) noexcept { +static ASMJIT_INLINE_NODEBUG bool isLogicalImm(uint64_t imm, uint32_t width) noexcept { LogicalImm dummy; return encodeLogicalImm(imm, width, &dummy); } +//! Returns true if the given `imm` value is encodable as an immediate with `add` and `sub` instructions on AArch64. +//! These two instructions can encode 12-bit immediate value optionally shifted left by 12 bits. +ASMJIT_MAYBE_UNUSED +static ASMJIT_INLINE_NODEBUG bool isAddSubImm(uint64_t imm) noexcept { + return imm <= 0xFFFu || (imm & ~uint64_t(0xFFFu << 12)) == 0; +} + //! Returns true if the given `imm` value is a byte mask. Byte mask has each byte part of the value set to either //! 0x00 or 0xFF. Some ARM instructions accept immediates that form a byte-mask and this function can be used to //! verify that the immediate is encodable before using the value. template<typename T> -static inline bool isByteMaskImm8(const T& imm) noexcept { +static ASMJIT_INLINE_NODEBUG bool isByteMaskImm8(const T& imm) noexcept { constexpr T kMask = T(0x0101010101010101 & Support::allOnes<T>()); return imm == (imm & kMask) * T(255); } +// [.......A|B.......|.......C|D.......|.......E|F.......|.......G|H.......] +static ASMJIT_INLINE_NODEBUG uint32_t encodeImm64ByteMaskToImm8(uint64_t imm) noexcept { + return uint32_t(((imm >> (7 - 0)) & 0b00000011) | // [.......G|H.......] + ((imm >> (23 - 2)) & 0b00001100) | // [.......E|F.......] + ((imm >> (39 - 4)) & 0b00110000) | // [.......C|D.......] + ((imm >> (55 - 6)) & 0b11000000)); // [.......A|B.......] +} //! \cond //! A generic implementation that checjs whether a floating point value can be converted to ARM Imm8. template<typename T, uint32_t kNumBBits, uint32_t kNumCDEFGHBits, uint32_t kNumZeroBits> -static inline bool isFPImm8Generic(T val) noexcept { +static ASMJIT_FORCE_INLINE bool isFPImm8Generic(T val) noexcept { constexpr uint32_t kAllBsMask = Support::lsbMask<uint32_t>(kNumBBits); constexpr uint32_t kB0Pattern = Support::bitMask(kNumBBits - 1); constexpr uint32_t kB1Pattern = kAllBsMask ^ kB0Pattern; @@ -127,7 +174,7 @@ static inline bool isFPImm8Generic(T val) noexcept { //! ``` //! [aBbbcdef|gh000000] //! ``` -static inline bool isFP16Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 3, 6, 6>(val); } +static ASMJIT_INLINE_NODEBUG bool isFP16Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 3, 6, 6>(val); } //! Returns true if the given single precision floating point `val` can be encoded as ARM IMM8 value, which represents //! a limited set of floating point immediate values, which can be used with FMOV instruction. @@ -137,9 +184,9 @@ static inline bool isFP16Imm8(uint32_t val) noexcept { return isFPImm8Generic<ui //! ``` //! [aBbbbbbc|defgh000|00000000|00000000] //! ``` -static inline bool isFP32Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 6, 6, 19>(val); } +static ASMJIT_INLINE_NODEBUG bool isFP32Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 6, 6, 19>(val); } //! \overload -static inline bool isFP32Imm8(float val) noexcept { return isFP32Imm8(Support::bitCast<uint32_t>(val)); } +static ASMJIT_INLINE_NODEBUG bool isFP32Imm8(float val) noexcept { return isFP32Imm8(Support::bitCast<uint32_t>(val)); } //! Returns true if the given double precision floating point `val` can be encoded as ARM IMM8 value, which represents //! a limited set of floating point immediate values, which can be used with FMOV instruction. @@ -149,13 +196,13 @@ static inline bool isFP32Imm8(float val) noexcept { return isFP32Imm8(Support::b //! ``` //! [aBbbbbbb|bbcdefgh|00000000|00000000|00000000|00000000|00000000|00000000] //! ``` -static inline bool isFP64Imm8(uint64_t val) noexcept { return isFPImm8Generic<uint64_t, 9, 6, 48>(val); } +static ASMJIT_INLINE_NODEBUG bool isFP64Imm8(uint64_t val) noexcept { return isFPImm8Generic<uint64_t, 9, 6, 48>(val); } //! \overload -static inline bool isFP64Imm8(double val) noexcept { return isFP64Imm8(Support::bitCast<uint64_t>(val)); } +static ASMJIT_INLINE_NODEBUG bool isFP64Imm8(double val) noexcept { return isFP64Imm8(Support::bitCast<uint64_t>(val)); } //! \cond template<typename T, uint32_t kNumBBits, uint32_t kNumCDEFGHBits, uint32_t kNumZeroBits> -static inline uint32_t encodeFPToImm8Generic(T val) noexcept { +static ASMJIT_INLINE_NODEBUG uint32_t encodeFPToImm8Generic(T val) noexcept { uint32_t bits = uint32_t(val >> kNumZeroBits); return ((bits >> (kNumBBits + kNumCDEFGHBits - 7)) & 0x80u) | (bits & 0x7F); } @@ -165,9 +212,9 @@ static inline uint32_t encodeFPToImm8Generic(T val) noexcept { //! //! \note This function expects that `isFP64Imm8(val) == true` so it doesn't perform any checks of the value and just //! rearranges some bits into Imm8 order. -static inline uint32_t encodeFP64ToImm8(uint64_t val) noexcept { return encodeFPToImm8Generic<uint64_t, 9, 6, 48>(val); } +static ASMJIT_INLINE_NODEBUG uint32_t encodeFP64ToImm8(uint64_t val) noexcept { return encodeFPToImm8Generic<uint64_t, 9, 6, 48>(val); } //! \overload -static inline uint32_t encodeFP64ToImm8(double val) noexcept { return encodeFP64ToImm8(Support::bitCast<uint64_t>(val)); } +static ASMJIT_INLINE_NODEBUG uint32_t encodeFP64ToImm8(double val) noexcept { return encodeFP64ToImm8(Support::bitCast<uint64_t>(val)); } } // {Utils} @@ -175,5 +222,5 @@ static inline uint32_t encodeFP64ToImm8(double val) noexcept { return encodeFP64 ASMJIT_END_SUB_NAMESPACE -#endif // ASMJIT_ARM_A64UTILS_H_INCLUDED +#endif // ASMJIT_ARM_ARMUTILS_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/asmjit.h b/3rdparty/asmjit/src/asmjit/asmjit.h index 1cd0651ffe1..f5184eb5777 100644 --- a/3rdparty/asmjit/src/asmjit/asmjit.h +++ b/3rdparty/asmjit/src/asmjit/asmjit.h @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Zlib // Official GitHub Repository: https://github.com/asmjit/asmjit // -// Copyright (c) 2008-2021 The AsmJit Authors +// Copyright (c) 2008-2024 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 diff --git a/3rdparty/asmjit/src/asmjit/core.h b/3rdparty/asmjit/src/asmjit/core.h index 4406ed89f30..cb19333ac38 100644 --- a/3rdparty/asmjit/src/asmjit/core.h +++ b/3rdparty/asmjit/src/asmjit/core.h @@ -105,40 +105,37 @@ namespace asmjit { //! //! - Tested: //! -//! - **Clang** - Tested by GitHub Actions - Clang 3.9+ (with C++11 enabled) is officially supported (older Clang -//! versions having C++11 support are probably fine, but are not regularly tested). +//! - **Clang** - Tested by GitHub Actions - Clang 10+ is officially supported and tested by CI, older Clang versions +//! having C++11 should work, but are not tested anymore due to upgraded CI images. //! -//! - **GNU** - Tested by GitHub Actions - GCC 4.8+ (with C++11 enabled) is officially supported. +//! - **GNU** - Tested by GitHub Actions - GCC 7+ is officially supported, older GCC versions from 4.8+ having C++11 +//! enabled should also work, but are not tested anymore due to upgraded CI images. //! -//! - **MINGW** - Should work, but it's not tested in our CI environment. +//! - **MINGW** - Reported to work, but not tested in our CI environment (help welcome). //! -//! - **MSVC** - Tested by GitHub Actions - VS2017+ is officially supported, VS2015 is reported to work. -//! -//! - Untested: -//! -//! - **Intel** - No maintainers and no CI environment to regularly test this compiler. -//! -//! - **Other** C++ compilers would require basic support in -//! [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h). +//! - **MSVC** - Tested by GitHub Actions - VS2019+ is officially supported, VS2015 and VS2017 is reported to work, +//! but not tested by CI anymore. //! //! ### Supported Operating Systems and Platforms //! //! - Tested: //! -//! - **Linux** - Tested by GitHub Actions (any distribution is generally supported). +//! - **BSD** - FreeBSD, NetBSD, and OpenBSD tested by GitHub Actions (only recent images are tested by CI). BSD +//! runners only test BSD images with clang compiler. //! -//! - **Mac OS** - Tested by GitHub Actions (any version is supported). +//! - **Linux** - Tested by GitHub Actions (only recent Ubuntu images are tested by CI, in general any distribution +//! should be supported as AsmJit has no dependencies). +//! +//! - **Mac OS** - Tested by GitHub Actions. //! //! - **Windows** - Tested by GitHub Actions - (Windows 7+ is officially supported). //! //! - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit cannot generate WASM code, but can be -//! used to generate X86/X64 code within a browser, for example. +//! used to generate X86/X64/AArch64 code within a browser, for example. //! //! - Untested: //! -//! - **BSDs** - No maintainers, no CI environment to regularly test BSDs, but they should work out of box. -//! -//! - **Haiku** - Not regularly tested, but reported to work. +//! - **Haiku** - Reported to work, not tested by CI. //! //! - **Other** operating systems would require some testing and support in the following files: //! - [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h) @@ -148,8 +145,7 @@ namespace asmjit { //! ### Supported Backends / Architectures //! //! - **X86** and **X86_64** - Both 32-bit and 64-bit backends tested on CI. -//! - **AArch64** - AArch64 backend is currently only partially tested (there is no native AArch64 runner to test -//! AsmJit Builder/Compiler) +//! - **AArch64** - Tested on CI (Native Apple runners and Linux emulated via QEMU). //! //! ### Static Builds and Embedding //! @@ -180,40 +176,49 @@ namespace asmjit { //! ### AsmJit Backends //! //! AsmJit currently supports only X86/X64 backend, but the plan is to add more backends in the future. By default -//! AsmJit builds only the host backend, which is autodetected at compile-time, but this can be overridden. +//! AsmJit builds only the host backend, which is auto-detected at compile-time, but this can be overridden. //! -//! - \ref ASMJIT_NO_X86 - Disable X86/X64 backends. -//! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architectures. -//! -//! ### Features Selection +//! - \ref ASMJIT_NO_X86 - Disables both X86 and X86_64 backends. +//! - \ref ASMJIT_NO_AARCH64 - Disables AArch64 backend. +//! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architecture backends, only keeps a native backend. //! -//! AsmJit builds by defaults all supported features, which includes all emitters, logging, instruction validation and -//! introspection, and JIT memory allocation. Features can be disabled at compile time by using `ASMJIT_NO_...` -//! definitions. +//! ### AsmJit Compilation Options //! //! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time so it won't be available and the //! compilation will fail if there is attempt to use such API. This includes deprecated classes, namespaces, //! enumerations, and functions. //! -//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality completely. This implies \ref -//! ASMJIT_NO_COMPILER as \ref asmjit_compiler cannot be used without \ref asmjit_builder. +//! - \ref ASMJIT_NO_SHM_OPEN - Disables functionality that uses `shm_open()`. //! -//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality completely. +//! - \ref ASMJIT_NO_ABI_NAMESPACE - Disables inline ABI namespace within `asmjit` namespace. This is only provided +//! for users that control all the dependencies (even transitive ones) and that make sure that no two AsmJit +//! versions are used at the same time. This option can be debugging a little simpler as there would not be ABI +//! tag after `asmjit::` namespace. Otherwise asmjit would look like `asmjit::_abi_1_13::`, for example. //! -//! - \ref ASMJIT_NO_JIT - Disables JIT memory management and \ref JitRuntime. +//! ### Features Selection //! -//! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. +//! AsmJit builds by defaults all supported features, which includes all emitters, logging, instruction validation and +//! introspection, and JIT memory allocation. Features can be disabled at compile time by using `ASMJIT_NO_...` +//! definitions. +//! - \ref ASMJIT_NO_JIT - Disables JIT memory management and \ref JitRuntime. //! //! - \ref ASMJIT_NO_TEXT - Disables everything that contains string representation of AsmJit constants, should //! be used together with \ref ASMJIT_NO_LOGGING as logging doesn't make sense without the ability to query //! instruction names, register names, etc... //! +//! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. +//! //! - \ref ASMJIT_NO_VALIDATION - Disables validation API. //! //! - \ref ASMJIT_NO_INTROSPECTION - Disables instruction introspection API, must be used together with \ref //! ASMJIT_NO_COMPILER as \ref asmjit_compiler requires introspection for its liveness analysis and register //! allocation. //! +//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality completely. This implies \ref +//! ASMJIT_NO_COMPILER as \ref asmjit_compiler cannot be used without \ref asmjit_builder. +//! +//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality completely. +//! //! \note It's not recommended to disable features if you plan to build AsmJit as a shared library that will be //! used by multiple projects that you don't control how AsmJit was built (for example AsmJit in a Linux distribution). //! The possibility to disable certain features exists mainly for customized AsmJit builds. @@ -234,7 +239,7 @@ namespace asmjit { //! //! Useful tips before you start: //! -//! - Visit our [Public Gitter Channel](https://gitter.im/asmjit/asmjit) if you need a quick help. +//! - Visit our [Public Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im) if you need a quick help. //! //! - Build AsmJit with `ASMJIT_NO_DEPRECATED` macro defined to make sure that you are not using deprecated //! functionality at all. Deprecated functions are decorated with `ASMJIT_DEPRECATED()` macro, but sometimes @@ -242,6 +247,77 @@ namespace asmjit { //! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_DEPRECATED` //! it's not using anything, which was deprecated. //! +//! ### Changes committed at 2024-01-01 +//! +//! Core changes: +//! +//! - Renamed equality functions `eq()` to `equals()` - Only related to `String`, `ZoneVector`, and `CpuFeatures`. +//! Old function names were deprecated. +//! +//! - Removed `CallConvId::kNone` in favor of `CallConvId::kCDecl`, which is now the default calling convention. +//! +//! - Deprecated `CallConvId::kHost` in favor of `CallConvId::kCDecl` - host calling convention is now not part +//! of CallConvId, it can be calculated from CallConvId and Environment instead. +//! +//! ### Changes committed at 2023-12-27 +//! +//! Core changes: +//! +//! - Renamed `a64::Vec::ElementType` to `a64::VecElementType` and made it a typed enum. This enum was used mostly +//! internally, but there is a public API using it, so it's a breaking change. +//! +//! - Refactored `FuncSignature`, `FuncSignatureT`, and `FuncSignatureBuilder`. There is only `FuncSignature` now, +//! which acts as a function signature holder and builder. Replace `FuncSignatureBuilder` with `FuncSignature` +//! and use `FuncSignature::build<args>` instead of `FuncSignatureT<args>`. The old API has been deprecated. +//! +//! - The maximum number of function arguments was raised from 16 to 32. +//! +//! ### Changes committed at 2023-12-26 +//! +//! Core changes: +//! +//! - Reworked InstNode and InstExNode to be friendlier to static analysis and to not cause undefined behavior. +//! InstNode has no operands visually embedded within the struct so there is no _opArray (which was internal). +//! This means that sizeof(InstNode) changed, but since it's allocated by AsmJit this should be fine. Moreover, +//! there is no longer InstExNode as that was more a hack, instead there is now InstNodeWithOperands, which is +//! a template and specifies the number of operands embedded (InstNode accesses these). All nodes that inherited +//! InstExNode now just inherit InstNodeWithOperands<InstNode::kBaseOpCapacity>, which would provide the same +//! number of nodes as InstNode. +//! +//! - Moved GP and Vec registers from asmjit::arm namespace to asmjit::a64 namespace. At this time there was +//! no prior deprecation as having arm::Vec would collide with a64::Vec as arm namespace is used within a64 +//! namespace. Just change `arm::Gp` to `a64::Gp` and `arm::Vec` to `a64::Vec`. +//! +//! ### Changes committed at 2023-09-10 +//! +//! Core changes: +//! +//! - Changed allocation API to work with spans (JitAllocator). +//! +//! - This change is required to support more hardened platforms in the future that make it very difficult +//! to write JIT compilers. +//! - `JitAllocator::Span` now represents a memory that the user can access. It abstracts both regular and +//! dual mappings. +//! - The `Span` is mostly designed to make it possible to write into it, so in general the read+execute +//! pointer is what user is intended to keep. Use `span.rx()` to access RX pointer. `Span` is not needed +//! after the memory it references has been modified, only remember `span.rx()` pointer, which is then +//! used to deallocate or change the memory the span references. +//! - Use a new `JitAllocator::alloc()` to allocate a `Span`, then pass the populated Span to `JitAllocator` +//! write API such as `JitAllocator::write()` - note that JitAllocator can also establish a scope, so you +//! can use a lambda function that would perform the write, but since it's going through JitAllocator it's +//! able to ensure that the memory is actually writable. +//! - If you need to repopulate a `Span` from rx pointer, use `JitAllocator::query(<span-out>, rx)` to get it. +//! - Study what JitRuntime is doing to better understand how this new API works in detail. +//! - Users of JitRuntime do not have to do anything as JitRuntime properly abstracts the allocation. +//! +//! - Renamed some X86 CPU features to make them compatible with architecture manuals: +//! +//! - Changed `AVX512_CDI` to `AVX512_CD`. +//! - Changed `AVX512_ERI` to `AVX512_ER`. +//! - Changed `AVX512_PFI` to `AVX512_PF`. +//! +//! - Old names were deprecated. +//! //! ### Changes committed at 2021-12-13 //! //! Core changes: @@ -309,7 +385,7 @@ namespace asmjit { //! However, `gpCount()` was removed - at the moment `ArchTraits` can be used to access such properties. //! //! Some other functions were renamed, like `ArchInfo::isX86Family()` is now `Environment::isFamilyX86()`, etc. -//! The reason for changing the order was support for more propertries and all the accessors now start with the +//! The reason for changing the order was support for more properties and all the accessors now start with the //! type of the property, like `Environment::isPlatformWindows()`. //! //! This function causes many other classes to provide `environment()` getter instead of `archInfo()` getter. @@ -392,7 +468,7 @@ namespace asmjit { //! // Calling a function (Compiler) changed - use invoke() instead of call(). //! void functionInvocation(x86::Compiler& cc) { //! InvokeNode* invokeNode; -//! cc.invoke(&invokeNode, targetOperand, FuncSignatureT<...>(...)); +//! cc.invoke(&invokeNode, targetOperand, FuncSignature::build<...>(...)); //! } //! ``` @@ -454,7 +530,8 @@ namespace asmjit { //! JitRuntime rt; // Runtime specialized for JIT code execution. //! //! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! a.mov(x86::eax, 1); // Move one to eax register. @@ -599,9 +676,10 @@ namespace asmjit { //! int main() { //! // Create a custom environment that matches the current host environment. //! Environment env = Environment::host(); +//! CpuFeatures cpuFeatures = CpuInfo::host().features(); //! //! CodeHolder code; // Create a CodeHolder. -//! code.init(env); // Initialize CodeHolder with environment. +//! code.init(env, cpuFeatures); // Initialize CodeHolder with environment. //! //! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. //! @@ -661,15 +739,17 @@ namespace asmjit { //! JitAllocator allocator; //! //! // Allocate an executable virtual memory and handle a possible failure. -//! void* p = allocator.alloc(estimatedSize); -//! if (!p) +//! JitAllocator::Span span; +//! Error err = allocator.alloc(span, estimatedSize); +//! +//! if (err != kErrorOk) // <- NOTE: This must be checked, always! //! return 0; //! //! // Now relocate the code to the address provided by the memory allocator. -//! // Please note that this DOESN'T COPY anything to `p`. This function will -//! // store the address in CodeHolder and use relocation entries to patch the -//! // existing code in all sections to respect the base address provided. -//! code.relocateToBase((uint64_t)p); +//! // Please note that this DOESN'T COPY anything to it. This function will +//! // store the address in CodeHolder and use relocation entries to patch +//! // the existing code in all sections to respect the base address provided. +//! code.relocateToBase((uint64_t)span.rx()); //! //! // This is purely optional. There are cases in which the relocation can omit //! // unneeded data, which would shrink the size of address table. If that @@ -682,12 +762,17 @@ namespace asmjit { //! // additional options that can be used to also zero pad sections' virtual //! // size, etc. //! // -//! // With some additional features, copyFlattenData() does roughly this: -//! // for (Section* section : code.sections()) -//! // memcpy((uint8_t*)p + section->offset(), -//! // section->data(), -//! // section->bufferSize()); -//! code.copyFlattenedData(p, codeSize, CopySectionFlags::kPadSectionBuffer); +//! // With some additional features, copyFlattenData() does roughly the following: +//! // +//! // allocator.write([&](JitAllocator::Span& span) { +//! // for (Section* section : code.sections()) { +//! // uint8_t* p = (uint8_t*)span.rw() + section->offset(); +//! // memcpy(p, section->data(), section->bufferSize()); +//! // } +//! // } +//! allocator.write([&](JitAllocator::Span& span) { +//! code.copyFlattenedData(span.rw(), codeSize, CopySectionFlags::kPadSectionBuffer); +//! }); //! //! // Execute the generated function. //! int inA[4] = { 4, 3, 2, 1 }; @@ -722,10 +807,11 @@ namespace asmjit { //! //! void initializeCodeHolder(CodeHolder& code) { //! Environment env = Environment::host(); +//! CpuFeatures cpuFeatures = CpuInfo::host().features(); //! uint64_t baseAddress = uint64_t(0x1234); //! //! // initialize CodeHolder with environment and custom base address. -//! code.init(env, baseAddress); +//! code.init(env, cpuFeatures, baseAddress); //! } //! ``` //! @@ -757,7 +843,7 @@ namespace asmjit { //! //! There is no function that would return the number of unbound labels as this is completely unimportant from //! CodeHolder's perspective. If a label is not used then it doesn't matter whether it's bound or not, only actually -//! used labels matter. After a Label is bound it's possible to query its offset offset relative to the start of the +//! used labels matter. After a Label is bound it's possible to query its offset relative to the start of the //! section where it was bound: //! //! ``` @@ -870,7 +956,7 @@ namespace asmjit { //! //! if (code.hasUnresolvedLinks()) { //! // This would mean either unbound label or some other issue. -//! printf("The code has %zu unbound labels\n", code.unresovedLinkCount()); +//! printf("The code has %zu unbound labels\n", code.unresolvedLinkCount()); //! exit(1); //! } //! } @@ -886,12 +972,15 @@ namespace asmjit { //! with assembler requires the knowledge of the following: //! //! - \ref BaseAssembler and architecture-specific assemblers: -//! - \ref x86::Assembler - Assembler specific to X86 architecture +//! - \ref x86::Assembler - Assembler implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Assembler - Assembler implementation targeting AArch64 architecture. //! - \ref Operand and its variations: //! - \ref BaseReg - Base class for a register operand, inherited by: -//! - \ref x86::Reg - Register operand specific to X86 architecture. +//! - \ref x86::Reg - Register operand specific to X86 and X86_64 architectures. +//! - \ref arm::Reg - Register operand specific to AArch64 architecture. //! - \ref BaseMem - Base class for a memory operand, inherited by: //! - \ref x86::Mem - Memory operand specific to X86 architecture. +//! - \ref arm::Mem - Memory operand specific to AArch64 architecture. //! - \ref Imm - Immediate (value) operand. //! - \ref Label - Label operand. //! @@ -999,7 +1088,7 @@ namespace asmjit { //! //! // Type-unsafe, but possible. //! a.emit(x86::Inst::kIdMov, dst, m); -//! // Also possible, `emit()` is typeless and can be used with raw Operand. +//! // Also possible, `emit()` is type-less and can be used with raw Operand. //! a.emit(x86::Inst::kIdMov, dst, op); //! } //! ``` @@ -1070,10 +1159,10 @@ namespace asmjit { //! //! void testX86Mem() { //! // The same as: dword ptr [rax + rbx]. -//! x86::Mem a = x86::dword_ptr(rax, rbx); +//! x86::Mem a = x86::dword_ptr(x86::rax, x86::rbx); //! //! // The same as: qword ptr [rdx + rsi << 0 + 1]. -//! x86::Mem b = x86::qword_ptr(rdx, rsi, 0, 1); +//! x86::Mem b = x86::qword_ptr(x86::rdx, x86::rsi, 0, 1); //! } //! ``` //! @@ -1086,18 +1175,18 @@ namespace asmjit { //! //! void testX86Mem() { //! // The same as: dword ptr [rax + 12]. -//! x86::Mem mem = x86::dword_ptr(rax, 12); +//! x86::Mem mem = x86::dword_ptr(x86::rax, 12); //! //! mem.hasBase(); // true. //! mem.hasIndex(); // false. //! mem.size(); // 4. //! mem.offset(); // 12. //! -//! mem.setSize(0); // Sets the size to 0 (makes it sizeless). +//! mem.setSize(0); // Sets the size to 0 (makes it size-less). //! mem.addOffset(-1); // Adds -1 to the offset and makes it 11. //! mem.setOffset(0); // Sets the offset to 0. -//! mem.setBase(rcx); // Changes BASE to RCX. -//! mem.setIndex(rax); // Changes INDEX to RAX. +//! mem.setBase(x86::rcx); // Changes BASE to RCX. +//! mem.setIndex(x86::rax); // Changes INDEX to RAX. //! mem.hasIndex(); // true. //! } //! // ... @@ -1189,7 +1278,8 @@ namespace asmjit { //! //! ### Builder Examples //! -//! - \ref x86::Builder provides many X86/X64 examples. +//! - \ref x86::Builder - Builder implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Builder - Builder implementation targeting AArch64 architecture. //! \defgroup asmjit_compiler Compiler @@ -1226,7 +1316,8 @@ namespace asmjit { //! //! ### Compiler Examples //! -//! - \ref x86::Compiler provides many X86/X64 examples. +//! - \ref x86::Compiler - Compiler implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Compiler - Compiler implementation targeting AArch64 architecture. //! //! ### Compiler Tips //! @@ -1346,7 +1437,8 @@ namespace asmjit { //! FileLogger logger(stdout); // Logger should always survive CodeHolder. //! //! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! code.setLogger(&logger); // Attach the `logger` to `code` holder. //! //! // ... code as usual, everything emitted will be logged to `stdout` ... @@ -1369,7 +1461,8 @@ namespace asmjit { //! StringLogger logger; // Logger should always survive CodeHolder. //! //! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! code.setLogger(&logger); // Attach the `logger` to `code` holder. //! //! // ... code as usual, logging will be concatenated to logger string ... @@ -1396,7 +1489,7 @@ namespace asmjit { //! The first example illustrates how to format operands: //! //! ``` -//! #include <asmjit/core.h> +//! #include <asmjit/x86.h> //! #include <stdio.h> //! //! using namespace asmjit; @@ -1421,17 +1514,17 @@ namespace asmjit { //! // compatible with what AsmJit normally does. //! Arch arch = Arch::kX64; //! -//! log(arch, rax); // Prints 'rax'. -//! log(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. -//! log(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`. -//! log(arch, imm(42)); // Prints '42'. +//! logOperand(arch, rax); // Prints 'rax'. +//! logOperand(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. +//! logOperand(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`. +//! logOperand(arch, imm(42)); // Prints '42'. //! } //! ``` //! //! Next example illustrates how to format whole instructions: //! //! ``` -//! #include <asmjit/core.h> +//! #include <asmjit/x86.h> //! #include <stdio.h> //! #include <utility> //! @@ -1446,7 +1539,7 @@ namespace asmjit { //! FormatFlags formatFlags = FormatFlags::kNone; //! //! // The formatter expects operands in an array. -//! Operand_ operands { std::forward<Args>(args)... }; +//! Operand_ operands[] { std::forward<Args>(args)... }; //! //! StringTmp<128> sb; //! Formatter::formatInstruction( @@ -1468,13 +1561,13 @@ namespace asmjit { //! // Prints 'vaddpd zmm0, zmm1, [rax] {1to8}'. //! logInstruction(arch, //! BaseInst(Inst::kIdVaddpd), -//! zmm0, zmm1, ptr(rax)._1toN()); +//! zmm0, zmm1, ptr(rax)._1to8()); //! //! // BaseInst abstracts instruction id, instruction options, and extraReg. //! // Prints 'lock add [rax], rcx'. //! logInstruction(arch, //! BaseInst(Inst::kIdAdd, InstOptions::kX86_Lock), -//! x86::ptr(rax), rcx); +//! ptr(rax), rcx); //! //! // Similarly an extra register (like AVX-512 selector) can be used. //! // Prints 'vaddpd zmm0 {k2} {z}, zmm1, [rax]'. @@ -1494,7 +1587,7 @@ namespace asmjit { //! using namespace asmjit; //! //! void formattingExample(BaseBuilder* builder) { -//! FormatFlags formatFlags = FormatFlags::kNone; +//! FormatOptions formatOptions {}; //! //! // This also shows how temporary strings can be used. //! StringTmp<512> sb; @@ -1503,7 +1596,7 @@ namespace asmjit { //! // were zero (no extra flags), and the builder instance, which we have //! // provided. An overloaded version also exists, which accepts begin and //! // and end nodes, which can be used to only format a range of nodes. -//! Formatter::formatNodeList(sb, formatFlags, builder); +//! Formatter::formatNodeList(sb, formatOptions, builder); //! //! // You can do whatever else with the string, it's always null terminated, //! // so it can be passed to C functions like printf(). @@ -1522,7 +1615,7 @@ namespace asmjit { //! override \ref ErrorHandler::handleError() to throw, in that case no error will be returned and exception will be //! thrown instead. All functions where this can happen are not marked `noexcept`. //! -//! Errors should never be ignored, however, checking errors after each AsmJit API call would simply overcomplicate +//! Errors should never be ignored, however, checking errors after each AsmJit API call would simply over-complicate //! the whole code generation experience. \ref ErrorHandler exists to make the use of AsmJit API simpler as it allows //! to customize how errors can be handled: //! @@ -1560,7 +1653,7 @@ namespace asmjit { //! MyErrorHandler myErrorHandler; //! CodeHolder code; //! -//! code.init(rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&myErrorHandler); //! //! x86::Assembler a(&code); @@ -1592,7 +1685,7 @@ namespace asmjit { //! //! Each instruction can be then queried for the following information: //! -//! - \ref InstRWInfo - Read/write information of instruction and its oprands (includes \ref OpRWInfo). +//! - \ref InstRWInfo - Read/write information of instruction and its operands (includes \ref OpRWInfo). //! //! - \ref CpuFeatures - CPU features required to execute the instruction. //! @@ -1631,14 +1724,57 @@ namespace asmjit { //! //! ### Overview //! -//! AsmJit's virtual memory management is divided into two main categories: -//! -//! - Low level API that provides cross-platform abstractions for virtual memory allocation. Implemented in -//! \ref VirtMem namespace. -//! -//! - High level API that makes it very easy to store generated code for execution. See \ref JitRuntime, which is -//! used by many examples for its simplicity and easy integration with \ref CodeHolder. There is also \ref -//! JitAllocator, which lays somewhere between RAW memory allocation and \ref JitRuntime. +//! AsmJit's virtual memory management is divided into three main categories: +//! +//! - Low level interface that provides cross-platform abstractions for virtual memory allocation. Implemented in +//! \ref VirtMem namespace. This API is a thin wrapper around operating system specific calls such as +//! `VirtualAlloc()` and `mmap()` and it's intended to be used by AsmJit's higher level API. Low-level virtual +//! memory functions can be used to allocate virtual memory, change its permissions, and to release it. +//! Additionally, an API that allows to create dual mapping (to support hardened environments) is provided. +//! +//! - Middle level API that is provided by \ref JitAllocator, which uses \ref VirtMem internally and offers nicer +//! API that can be used by users to allocate executable memory conveniently. \ref JitAllocator tries to be smart, +//! for example automatically using dual mapping or `MAP_JIT` on hardened environments. +//! +//! - High level API that is provided by \ref JitRuntime, which implements \ref Target interface and uses \ref +//! JitAllocator under the hood. Since \ref JitRuntime inherits from \ref Target it makes it easy to use with +//! \ref CodeHolder. Many AsmJit examples use \ref JitRuntime for its simplicity and easy integration. +//! +//! The main difference between \ref VirtMem and \ref JitAllocator is that \ref VirtMem can only be used to allocate +//! whole pages, whereas \ref JitAllocator has `malloc()` like API that allows to allocate smaller quantities that +//! usually represent the size of an assembled function or a chunk of functions that can represent a module, for +//! example. \ref JitAllocator then tracks used space of each page it maintains. Internally, \ref JitAllocator uses +//! two bit arrays to track occupied regions in each allocated block of pages. +//! +//! ### Hardened Environments +//! +//! In the past, allocating virtual memory with Read+Write+Execute (RWX) access permissions was easy. However, modern +//! operating systems and runtime environments often use hardening, which typically prohibits mapping pages with both +//! Write and Execute permissions (known as the W^X policy). This presents a challenge for JIT compilers because +//! generated code for a single function is unlikely to fit in exactly N pages without leaving some space empty. To +//! accommodate this, the execution environment may need to temporarily change the permissions of existing pages to +//! read+write (RW) to insert new code into them, however, sometimes it's not possible to ensure that no thread is +//! executing code in such affected pages in a multithreaded environment, in which multiple threads may be executing +//! generated code. +//! +//! Such restrictions leave a lot of complexity on the application, so AsmJit implements a dual mapping technique to +//! make the life of AsmJit users easier. In this technique, a region of memory is mapped to two different virtual +//! addresses with different access permissions. One virtual address is mapped with read and write (RW) access, which +//! is used by the JIT compiler to write generated code. The other virtual address is mapped with read and execute (RX) +//! access, which is used by the application to execute the generated code. +//! +//! However, implementing dual mapping can be challenging because it typically requires obtaining an anonymous file +//! descriptor on most Unix-like operating systems. This file descriptor is then passed to mmap() twice to create +//! the two mappings. AsmJit handles this challenge by using system-specific techniques such as `memfd_create()` on +//! Linux, `shm_open(SHM_ANON)` on BSD, and `MAP_REMAPDUP` with `mremap()` on NetBSD. The latter approach does not +//! require a file descriptor. If none of these options are available, AsmJit uses a plain `open()` call followed by +//! `unlink()`. +//! +//! The most challenging part is actually obtaining a file descriptor that can be passed to `mmap()` with `PROT_EXEC`. +//! This is still something that may fail, for example the environment could be hardened in a way that this would +//! not be possible at all, and thus dual mapping would not work. +//! +//! Dual mapping is provided by both \ref VirtMem and \ref JitAllocator. //! \defgroup asmjit_zone Zone Memory diff --git a/3rdparty/asmjit/src/asmjit/core/api-build_p.h b/3rdparty/asmjit/src/asmjit/core/api-build_p.h index 6eca971037e..3ddc9e78d22 100644 --- a/3rdparty/asmjit/src/asmjit/core/api-build_p.h +++ b/3rdparty/asmjit/src/asmjit/core/api-build_p.h @@ -27,6 +27,25 @@ #define NOMINMAX #endif #include <windows.h> +#else + // Most production code is compiled with large file support, so do the same. + #if !defined(_WIN32) && !defined(_LARGEFILE64_SOURCE) + #define _LARGEFILE64_SOURCE 1 + #endif + + // These OSes use 64-bit API by default. + #if defined(__APPLE__ ) || \ + defined(__HAIKU__ ) || \ + defined(__bsdi__ ) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__ ) || \ + defined(__NetBSD__ ) || \ + defined(__OpenBSD__ ) + #define ASMJIT_FILE64_API(NAME) NAME + #else + #define ASMJIT_FILE64_API(NAME) NAME##64 + #endif + #endif #include "./api-config.h" diff --git a/3rdparty/asmjit/src/asmjit/core/api-config.h b/3rdparty/asmjit/src/asmjit/core/api-config.h index 6bd5beecc0a..bbc35067778 100644 --- a/3rdparty/asmjit/src/asmjit/core/api-config.h +++ b/3rdparty/asmjit/src/asmjit/core/api-config.h @@ -12,20 +12,23 @@ //! \addtogroup asmjit_core //! \{ -//! AsmJit library version in `(Major << 16) | (Minor << 8) | (Patch)` format. -#define ASMJIT_LIBRARY_VERSION 0x010900 /* 1.9.0 */ +//! Makes a 32-bit integer that represents AsmJit version in `(major << 16) | (minor << 8) | patch` form. +#define ASMJIT_LIBRARY_MAKE_VERSION(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) + +//! AsmJit library version, see \ref ASMJIT_LIBRARY_MAKE_VERSION for a version format reference. +#define ASMJIT_LIBRARY_VERSION ASMJIT_LIBRARY_MAKE_VERSION(1, 13, 0) //! \def ASMJIT_ABI_NAMESPACE //! //! AsmJit ABI namespace is an inline namespace within \ref asmjit namespace. //! -//! It's used to make sure that when user links to an incompatible version of AsmJit, it won't link. It has also some -//! additional properties as well. When `ASMJIT_ABI_NAMESPACE` is defined by the user it would override the AsmJit -//! default, which makes it possible to use use multiple AsmJit libraries within a single project, totally controlled -//! by the users. This is useful especially in cases in which some of such library comes from a third party. -#ifndef ASMJIT_ABI_NAMESPACE - #define ASMJIT_ABI_NAMESPACE _abi_1_9 -#endif +//! It's used to make sure that when user links to an incompatible version of AsmJit, it won't link. It has also +//! some additional properties as well. When `ASMJIT_ABI_NAMESPACE` is defined by the user it would override the +//! AsmJit default, which makes it possible to use multiple AsmJit libraries within a single project, totally +//! controlled by users. This is useful especially in cases in which some of such library comes from third party. +#if !defined(ASMJIT_ABI_NAMESPACE) + #define ASMJIT_ABI_NAMESPACE _abi_1_13 +#endif // !ASMJIT_ABI_NAMESPACE //! \} @@ -39,9 +42,8 @@ #include <stdlib.h> #include <string.h> -#include <iterator> +#include <initializer_list> #include <limits> -#include <new> #include <type_traits> #include <utility> @@ -52,8 +54,6 @@ // Build Options // ============= -#define ASMJIT_STATIC - // NOTE: Doxygen cannot document macros that are not defined, that's why we have to define them and then undefine // them immediately, so it won't use the macros with its own preprocessor. #ifdef _DOXYGEN @@ -70,20 +70,17 @@ namespace asmjit { //! Defined when AsmJit's build configuration is 'Debug'. //! -//! \note Can be defined explicitly to bypass autodetection. +//! \note Can be defined explicitly to bypass auto-detection. #define ASMJIT_BUILD_DEBUG //! Defined when AsmJit's build configuration is 'Release'. //! -//! \note Can be defined explicitly to bypass autodetection. +//! \note Can be defined explicitly to bypass auto-detection. #define ASMJIT_BUILD_RELEASE //! Disables X86/X64 backends. #define ASMJIT_NO_X86 -//! Disables AArch32 backends (both ARM and Thumb). -#define ASMJIT_NO_AARCH32 - //! Disables AArch64 backend. #define ASMJIT_NO_AARCH64 @@ -115,7 +112,7 @@ namespace asmjit { #define ASMJIT_NO_INTROSPECTION // Avoid doxygen preprocessor using feature-selection definitions. -#undef ASMJIT_BUILD_EMBNED +#undef ASMJIT_BUILD_EMBED #undef ASMJIT_BUILD_STATIC #undef ASMJIT_BUILD_DEBUG #undef ASMJIT_BUILD_RELEASE @@ -166,6 +163,41 @@ namespace asmjit { // Target Architecture Detection // ============================= +//! \addtogroup asmjit_core +//! \{ + +//! \def ASMJIT_ARCH_X86 +//! +//! Defined to either 0, 32, or 64 depending on whether the target CPU is X86 (32) or X86_64 (64). + +//! \def ASMJIT_ARCH_ARM +//! +//! Defined to either 0, 32, or 64 depending on whether the target CPU is ARM (32) or AArch64 (64). + +//! \def ASMJIT_ARCH_MIPS +//! +//! Defined to either 0, 32, or 64 depending on whether the target CPU is MIPS (32) or MISP64 (64). + +//! \def ASMJIT_ARCH_RISCV +//! +//! Defined to either 0, 32, or 64 depending on whether the target CPU is RV32 (32) or RV64 (64). + +//! \def ASMJIT_ARCH_BITS +//! +//! Defined to either 32 or 64 depending on the target. + +//! \def ASMJIT_ARCH_LE +//! +//! Defined to 1 if the target architecture is little endian. + +//! \def ASMJIT_ARCH_BE +//! +//! Defined to 1 if the target architecture is big endian. + +//! \} + +//! \cond NONE + #if defined(_M_X64) || defined(__x86_64__) #define ASMJIT_ARCH_X86 64 #elif defined(_M_IX86) || defined(__X86__) || defined(__i386__) @@ -174,7 +206,7 @@ namespace asmjit { #define ASMJIT_ARCH_X86 0 #endif -#if defined(__arm64__) || defined(__aarch64__) +#if defined(_M_ARM64) || defined(__arm64__) || defined(__aarch64__) # define ASMJIT_ARCH_ARM 64 #elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__) || defined(__thumb2__) #define ASMJIT_ARCH_ARM 32 @@ -190,10 +222,17 @@ namespace asmjit { #define ASMJIT_ARCH_MIPS 0 #endif -#define ASMJIT_ARCH_BITS (ASMJIT_ARCH_X86 | ASMJIT_ARCH_ARM | ASMJIT_ARCH_MIPS) +// NOTE `__riscv` is the correct macro in this case as specified by "RISC-V Toolchain Conventions". +#if (defined(__riscv) || defined(__riscv__)) && defined(__riscv_xlen) + #define ASMJIT_ARCH_RISCV __riscv_xlen +#else + #define ASMJIT_ARCH_RISCV 0 +#endif + +#define ASMJIT_ARCH_BITS (ASMJIT_ARCH_X86 | ASMJIT_ARCH_ARM | ASMJIT_ARCH_MIPS | ASMJIT_ARCH_RISCV) #if ASMJIT_ARCH_BITS == 0 #undef ASMJIT_ARCH_BITS - #if defined (__LP64__) || defined(_LP64) + #if defined(__LP64__) || defined(_LP64) #define ASMJIT_ARCH_BITS 64 #else #define ASMJIT_ARCH_BITS 32 @@ -215,62 +254,88 @@ namespace asmjit { #define ASMJIT_NO_X86 #endif - #if !ASMJIT_ARCH_ARM && !defined(ASMJIT_NO_AARCH64) + #if ASMJIT_ARCH_ARM != 64 && !defined(ASMJIT_NO_AARCH64) #define ASMJIT_NO_AARCH64 #endif #endif +//! \endcond // C++ Compiler and Features Detection // =================================== -#define ASMJIT_CXX_GNU 0 -#define ASMJIT_CXX_MAKE_VER(MAJOR, MINOR) ((MAJOR) * 1000 + (MINOR)) - -// Intel Compiler [pretends to be GNU or MSC, so it must be checked first]: -// - https://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c14-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler -#if defined(__INTEL_COMPILER) - -// MSC Compiler: -// - https://msdn.microsoft.com/en-us/library/hh567368.aspx -// -// Version List: -// - 16.00.0 == VS2010 -// - 17.00.0 == VS2012 -// - 18.00.0 == VS2013 -// - 19.00.0 == VS2015 -// - 19.10.0 == VS2017 -#elif defined(_MSC_VER) && defined(_MSC_FULL_VER) - -// Clang Compiler [Pretends to be GNU, so it must be checked before]: -// - https://clang.llvm.org/cxx_status.html -#elif defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) - -// GNU Compiler: -// - https://gcc.gnu.org/projects/cxx-status.html -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) - - #undef ASMJIT_CXX_GNU - #define ASMJIT_CXX_GNU ASMJIT_CXX_MAKE_VER(__GNUC__, __GNUC_MINOR__) - -#endif - -// Compiler features detection macros. -#if defined(__clang__) && defined(__has_attribute) +#if defined(__GNUC__) && defined(__has_attribute) #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME)) #else #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK))) -#endif +#endif // !ASMJIT_CXX_HAS_ATTRIBUTE // API Decorators & C++ Extensions // =============================== +//! \addtogroup asmjit_core +//! \{ + //! \def ASMJIT_API //! //! A decorator that is used to decorate API that AsmJit exports when built as a shared library. +//! \def ASMJIT_VIRTAPI +//! +//! This is basically a workaround. When using MSVC and marking class as DLL export everything gets exported, which +//! is unwanted in most projects. MSVC automatically exports typeinfo and vtable if at least one symbol of the class +//! is exported. However, GCC has some strange behavior that even if one or more symbol is exported it doesn't export +//! typeinfo unless the class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). + +//! \def ASMJIT_FORCE_INLINE +//! +//! Decorator to force inlining of functions, uses either `__attribute__((__always_inline__))` or __forceinline, +//! depending on C++ compiler. + +//! \def ASMJIT_INLINE_NODEBUG +//! +//! Like \ref ASMJIT_FORCE_INLINE, but uses additionally `__nodebug__` or `__artificial__` attribute to make the +//! debugging of some AsmJit functions easier, especially getters and one-line abstractions where usually you don't +//! want to step in. + +//! \def ASMJIT_NOINLINE +//! +//! Decorator to avoid inlining of functions, uses either `__attribute__((__noinline__))` or `__declspec(noinline)` +//! depending on C++ compiler. + +//! \def ASMJIT_NORETURN +//! +//! Decorator that marks functions that should never return. Typically used to implement assertion handlers that +//! terminate, so the function never returns. + +//! \def ASMJIT_CDECL +//! +//! CDECL function attribute - either `__attribute__((__cdecl__))` or `__cdecl`. + +//! \def ASMJIT_STDCALL +//! +//! STDCALL function attribute - either `__attribute__((__stdcall__))` or `__stdcall`. +//! +//! \note This expands to nothing on non-x86 targets as STDCALL is X86 specific. + +//! \def ASMJIT_FASTCALL +//! +//! FASTCALL function attribute - either `__attribute__((__fastcall__))` or `__fastcall`. +//! +//! \note Expands to nothing on non-x86 targets as FASTCALL is X86 specific. + +//! \def ASMJIT_REGPARM(N) +//! +//! Expands to `__attribute__((__regparm__(N)))` when compiled by GCC or clang, nothing otherwise. + +//! \def ASMJIT_VECTORCALL +//! +//! VECTORCALL function attribute - either `__attribute__((__vectorcall__))` or `__vectorcall`. +//! +//! \note Expands to nothing on non-x86 targets as VECTORCALL is X86 specific. + +//! \} + // API (Export / Import). #if !defined(ASMJIT_STATIC) #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) @@ -298,13 +363,7 @@ namespace asmjit { #define ASMJIT_VARAPI extern ASMJIT_API #endif -//! \def ASMJIT_VIRTAPI -//! -//! This is basically a workaround. When using MSVC and marking class as DLL export everything gets exported, which -//! is unwanted in most projects. MSVC automatically exports typeinfo and vtable if at least one symbol of the class -//! is exported. However, GCC has some strange behavior that even if one or more symbol is exported it doesn't export -//! typeinfo unless the class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). -#if !defined(_WIN32) && defined(__GNUC__) +#if defined(__GNUC__) && !defined(_WIN32) #define ASMJIT_VIRTAPI ASMJIT_API #else #define ASMJIT_VIRTAPI @@ -319,6 +378,15 @@ namespace asmjit { #define ASMJIT_FORCE_INLINE inline #endif + +#if defined(__clang__) + #define ASMJIT_INLINE_NODEBUG inline __attribute__((__always_inline__, __nodebug__)) +#elif defined(__GNUC__) + #define ASMJIT_INLINE_NODEBUG inline __attribute__((__always_inline__, __artificial__)) +#else + #define ASMJIT_INLINE_NODEBUG inline +#endif + #if defined(__GNUC__) #define ASMJIT_NOINLINE __attribute__((__noinline__)) #define ASMJIT_NORETURN __attribute__((__noreturn__)) @@ -452,17 +520,10 @@ namespace asmjit { //! Marks function, class, struct, enum, or anything else as deprecated. #if defined(__GNUC__) #define ASMJIT_DEPRECATED(MESSAGE) __attribute__((__deprecated__(MESSAGE))) - #if defined(__clang__) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) __attribute__((__deprecated__(MESSAGE))) - #else - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */ - #endif #elif defined(_MSC_VER) #define ASMJIT_DEPRECATED(MESSAGE) __declspec(deprecated(MESSAGE)) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */ #else #define ASMJIT_DEPRECATED(MESSAGE) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) #endif // Utilities. @@ -471,66 +532,60 @@ namespace asmjit { #if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0) #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize__("undefined"))) -#elif ASMJIT_CXX_GNU >= ASMJIT_CXX_MAKE_VER(4, 9) +#elif defined(__GNUC__) && __GNUC__ >= 5 #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize_undefined__)) #else #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF #endif -// Begin-Namespace & End-Namespace Macros +// Diagnostic Macros // ====================================== -#if defined _DOXYGEN - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { - #define ASMJIT_END_NAMESPACE } -#elif defined(__clang__) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wconstant-logical-operand\"") \ - _Pragma("clang diagnostic ignored \"-Wunnamed-type-template-args\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("clang diagnostic pop") \ - }} -#elif defined(__GNUC__) && __GNUC__ == 4 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ +#if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(_DOXYGEN) + #if defined(__GNUC__) && __GNUC__ == 4 + // There is a bug in GCC 4.X that has been fixed in GCC 5+, so just silence the warning. + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - }} -#elif defined(__GNUC__) && __GNUC__ >= 8 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - }} -#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ + #define ASMJIT_END_DIAGNOSTIC_SCOPE \ + _Pragma("GCC diagnostic pop") + #elif defined(_MSC_VER) + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ __pragma(warning(push)) \ __pragma(warning(disable: 4127)) /* conditional expression is const */ \ __pragma(warning(disable: 4201)) /* nameless struct/union */ - #define ASMJIT_END_NAMESPACE \ - __pragma(warning(pop)) \ - }} + #define ASMJIT_END_DIAGNOSTIC_SCOPE \ + __pragma(warning(pop)) + #endif #endif -#if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE) - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { - #define ASMJIT_END_NAMESPACE }} +#if !defined(ASMJIT_BEGIN_DIAGNOSTIC_SCOPE) && !defined(ASMJIT_END_DIAGNOSTIC_SCOPE) + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE + #define ASMJIT_END_DIAGNOSTIC_SCOPE #endif -#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \ - ASMJIT_BEGIN_NAMESPACE \ - namespace NAMESPACE { +// Begin-Namespace & End-Namespace Macros +// ====================================== -#define ASMJIT_END_SUB_NAMESPACE \ - } \ - ASMJIT_END_NAMESPACE +#if !defined(ASMJIT_NO_ABI_NAMESPACE) && !defined(_DOXYGEN) + #define ASMJIT_BEGIN_NAMESPACE \ + ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ + namespace asmjit { \ + inline namespace ASMJIT_ABI_NAMESPACE { + #define ASMJIT_END_NAMESPACE \ + }} \ + ASMJIT_END_DIAGNOSTIC_SCOPE +#else + #define ASMJIT_BEGIN_NAMESPACE \ + ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ + namespace asmjit { + #define ASMJIT_END_NAMESPACE \ + } \ + ASMJIT_END_DIAGNOSTIC_SCOPE +#endif + +#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) ASMJIT_BEGIN_NAMESPACE namespace NAMESPACE { +#define ASMJIT_END_SUB_NAMESPACE } ASMJIT_END_NAMESPACE // C++ Utilities // ============= @@ -551,34 +606,34 @@ namespace asmjit { #define ASMJIT_DEFINE_ENUM_FLAGS(T) #else #define ASMJIT_DEFINE_ENUM_FLAGS(T) \ - static ASMJIT_FORCE_INLINE constexpr T operator~(T a) noexcept { \ + static ASMJIT_INLINE_NODEBUG constexpr T operator~(T a) noexcept { \ return T(~(std::underlying_type<T>::type)(a)); \ } \ \ - static ASMJIT_FORCE_INLINE constexpr T operator|(T a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG constexpr T operator|(T a, T b) noexcept { \ return T((std::underlying_type<T>::type)(a) | \ (std::underlying_type<T>::type)(b)); \ } \ - static ASMJIT_FORCE_INLINE constexpr T operator&(T a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG constexpr T operator&(T a, T b) noexcept { \ return T((std::underlying_type<T>::type)(a) & \ (std::underlying_type<T>::type)(b)); \ } \ - static ASMJIT_FORCE_INLINE constexpr T operator^(T a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG constexpr T operator^(T a, T b) noexcept { \ return T((std::underlying_type<T>::type)(a) ^ \ (std::underlying_type<T>::type)(b)); \ } \ \ - static ASMJIT_FORCE_INLINE T& operator|=(T& a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG T& operator|=(T& a, T b) noexcept { \ a = T((std::underlying_type<T>::type)(a) | \ (std::underlying_type<T>::type)(b)); \ return a; \ } \ - static ASMJIT_FORCE_INLINE T& operator&=(T& a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG T& operator&=(T& a, T b) noexcept { \ a = T((std::underlying_type<T>::type)(a) & \ (std::underlying_type<T>::type)(b)); \ return a; \ } \ - static ASMJIT_FORCE_INLINE T& operator^=(T& a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG T& operator^=(T& a, T b) noexcept { \ a = T((std::underlying_type<T>::type)(a) ^ \ (std::underlying_type<T>::type)(b)); \ return a; \ @@ -588,28 +643,22 @@ namespace asmjit { //! \def ASMJIT_DEFINE_ENUM_COMPARE(T) //! //! Defines comparison operations for enumeration flags. -#ifdef _DOXYGEN +#if defined(_DOXYGEN) || (defined(_MSC_VER) && _MSC_VER <= 1900) #define ASMJIT_DEFINE_ENUM_COMPARE(T) #else #define ASMJIT_DEFINE_ENUM_COMPARE(T) \ - static ASMJIT_FORCE_INLINE bool operator<(T a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG bool operator<(T a, T b) noexcept { \ return (std::underlying_type<T>::type)(a) < (std::underlying_type<T>::type)(b); \ } \ - static ASMJIT_FORCE_INLINE bool operator<=(T a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG bool operator<=(T a, T b) noexcept { \ return (std::underlying_type<T>::type)(a) <= (std::underlying_type<T>::type)(b); \ } \ - static ASMJIT_FORCE_INLINE bool operator>(T a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG bool operator>(T a, T b) noexcept { \ return (std::underlying_type<T>::type)(a) > (std::underlying_type<T>::type)(b); \ } \ - static ASMJIT_FORCE_INLINE bool operator>=(T a, T b) noexcept { \ + static ASMJIT_INLINE_NODEBUG bool operator>=(T a, T b) noexcept { \ return (std::underlying_type<T>::type)(a) >= (std::underlying_type<T>::type)(b); \ } #endif -// Cleanup Api-Config Specific Macros -// ================================== - -#undef ASMJIT_CXX_GNU -#undef ASMJIT_CXX_MAKE_VER - #endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/core/archcommons.h b/3rdparty/asmjit/src/asmjit/core/archcommons.h index e9d2c84d722..2b47d17c1b4 100644 --- a/3rdparty/asmjit/src/asmjit/core/archcommons.h +++ b/3rdparty/asmjit/src/asmjit/core/archcommons.h @@ -29,8 +29,8 @@ enum class CondCode : uint8_t { kNE = 0x03u, //!< Z==0 (any_sign !=) kCS = 0x04u, //!< C==1 (unsigned >=) kHS = 0x04u, //!< C==1 (unsigned >=) - kCC = 0x05u, //!< C==0 (unsigned < ) kLO = 0x05u, //!< C==0 (unsigned < ) + kCC = 0x05u, //!< C==0 (unsigned < ) kMI = 0x06u, //!< N==1 (is negative) kPL = 0x07u, //!< N==0 (is positive or zero) kVS = 0x08u, //!< V==1 (is overflow) @@ -42,21 +42,24 @@ enum class CondCode : uint8_t { kGT = 0x0Eu, //!< Z==0 & N==V (signed > ) kLE = 0x0Fu, //!< Z==1 | N!=V (signed <=) - kSign = kMI, //!< Sign. - kNotSign = kPL, //!< Not sign. - - kOverflow = kVS, //!< Signed overflow. - kNotOverflow = kVC, //!< Not signed overflow. + kZero = kEQ, //!< Zero flag (alias to equal). + kNotZero = kNE, //!< Not zero (alias to Not Equal). kEqual = kEQ, //!< Equal `a == b`. kNotEqual = kNE, //!< Not Equal `a != b`. - kZero = kEQ, //!< Zero (alias to equal). - kNotZero = kNE, //!< Not Zero (alias to Not Equal). + kCarry = kCS, //!< Carry flag. + kNotCarry = kCC, //!< Not carry. + + kSign = kMI, //!< Sign flag. + kNotSign = kPL, //!< Not sign. kNegative = kMI, //!< Negative. kPositive = kPL, //!< Positive or zero. + kOverflow = kVS, //!< Signed overflow. + kNotOverflow = kVC, //!< Not signed overflow. + kSignedLT = kLT, //!< Signed `a < b`. kSignedLE = kLE, //!< Signed `a <= b`. kSignedGT = kGT, //!< Signed `a > b`. @@ -67,47 +70,51 @@ enum class CondCode : uint8_t { kUnsignedGT = kHI, //!< Unsigned `a > b`. kUnsignedGE = kHS, //!< Unsigned `a >= b`. + kBTZero = kZero, //!< Tested bit is zero. + kBTNotZero = kNotZero, //!< Tested bit is not zero. + kAlways = kAL, //!< No condition code (always). kMaxValue = 0x0Fu //!< Maximum value of `CondCode`. }; -//! Negates a condition code. -static inline constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); } -//! Data type that can be encoded with the instruction (AArch32 only). -enum class DataType : uint32_t { - //! No data type specified (default for all general purpose instructions). - kNone = 0, - //! 8-bit signed integer, specified as `.s8` in assembly. - kS8 = 1, - //! 16-bit signed integer, specified as `.s16` in assembly. - kS16 = 2, - //! 32-bit signed integer, specified as `.s32` in assembly. - kS32 = 3, - //! 64-bit signed integer, specified as `.s64` in assembly. - kS64 = 4, - //! 8-bit unsigned integer, specified as `.u8` in assembly. - kU8 = 5, - //! 16-bit unsigned integer, specified as `.u16` in assembly. - kU16 = 6, - //! 32-bit unsigned integer, specified as `.u32` in assembly. - kU32 = 7, - //! 64-bit unsigned integer, specified as `.u64` in assembly. - kU64 = 8, - //! 16-bit floating point (half precision), specified as `.f16` in assembly. - kF16 = 10, - //! 32-bit floating point (single precision), specified as `.f32` in assembly. - kF32 = 11, - //! 64-bit floating point (double precision), specified as `.f64` in assembly. - kF64 = 12, - //! 8-bit polynomial. - kP8 = 13, - //! 64-bit polynomial. - kP64 = 15, +//! \cond +static constexpr CondCode _reverseCondTable[] = { + CondCode::kAL, // AL <- AL + CondCode::kNA, // NA <- NA + CondCode::kEQ, // EQ <- EQ + CondCode::kNE, // NE <- NE + CondCode::kLS, // LS <- CS + CondCode::kHI, // HI <- LO + CondCode::kMI, // MI <- MI + CondCode::kPL, // PL <- PL + CondCode::kVS, // VS <- VS + CondCode::kVC, // VC <- VC + CondCode::kLO, // LO <- HI + CondCode::kCS, // CS <- LS + CondCode::kLE, // LE <- GE + CondCode::kGT, // GT <- LT + CondCode::kLT, // LT <- GT + CondCode::kGE // GE <- LE +}; +//! \endcond - //! Maximum value of `DataType`. - kMaxValue = 15 +//! Reverses a condition code (reverses the corresponding operands of a comparison). +static ASMJIT_INLINE_NODEBUG constexpr CondCode reverseCond(CondCode cond) noexcept { return _reverseCondTable[uint8_t(cond)]; } +//! Negates a condition code. +static ASMJIT_INLINE_NODEBUG constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); } + +//! Memory offset mode. +//! +//! Describes either fixed, pre-index, or post-index offset modes. +enum class OffsetMode : uint32_t { + //! Fixed offset mode (either no index at all or a regular index without a write-back). + kFixed = 0u, + //! Pre-index "[BASE, #Offset {, <shift>}]!" with write-back. + kPreIndex = 1u, + //! Post-index "[BASE], #Offset {, <shift>}" with write-back. + kPostIndex = 2u }; //! Shift operation predicate (ARM) describes either SHIFT or EXTEND operation. @@ -170,60 +177,85 @@ public: uint32_t _value; //! Default constructed Shift is not initialized. - inline Shift() noexcept = default; + ASMJIT_INLINE_NODEBUG Shift() noexcept = default; //! Copy constructor (default) - constexpr Shift(const Shift& other) noexcept = default; + ASMJIT_INLINE_NODEBUG constexpr Shift(const Shift& other) noexcept = default; //! Constructs Shift from operation `op` and shift `value`. - constexpr Shift(ShiftOp op, uint32_t value) noexcept + ASMJIT_INLINE_NODEBUG constexpr Shift(ShiftOp op, uint32_t value) noexcept : _op(op), _value(value) {} //! Returns the shift operation. - constexpr ShiftOp op() const noexcept { return _op; } + ASMJIT_INLINE_NODEBUG constexpr ShiftOp op() const noexcept { return _op; } //! Sets shift operation to `op`. - inline void setOp(ShiftOp op) noexcept { _op = op; } + ASMJIT_INLINE_NODEBUG void setOp(ShiftOp op) noexcept { _op = op; } - //! Returns the shift smount. - constexpr uint32_t value() const noexcept { return _value; } + //! Returns the shift amount. + ASMJIT_INLINE_NODEBUG constexpr uint32_t value() const noexcept { return _value; } //! Sets shift amount to `value`. - inline void setValue(uint32_t value) noexcept { _value = value; } + ASMJIT_INLINE_NODEBUG void setValue(uint32_t value) noexcept { _value = value; } }; -//! Constructs a `LSL #value` shift (logical shift left). -static constexpr Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); } -//! Constructs a `LSR #value` shift (logical shift right). -static constexpr Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); } -//! Constructs a `ASR #value` shift (arithmetic shift right). -static constexpr Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); } -//! Constructs a `ROR #value` shift (rotate right). -static constexpr Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); } -//! Constructs a `RRX` shift (rotate with carry by 1). -static constexpr Shift rrx() noexcept { return Shift(ShiftOp::kRRX, 0); } -//! Constructs a `MSL #value` shift (logical shift left filling ones). -static constexpr Shift msl(uint32_t value) noexcept { return Shift(ShiftOp::kMSL, value); } - -//! Constructs a `UXTB #value` extend and shift (unsigned byte extend). -static constexpr Shift uxtb(uint32_t value) noexcept { return Shift(ShiftOp::kUXTB, value); } -//! Constructs a `UXTH #value` extend and shift (unsigned hword extend). -static constexpr Shift uxth(uint32_t value) noexcept { return Shift(ShiftOp::kUXTH, value); } -//! Constructs a `UXTW #value` extend and shift (unsigned word extend). -static constexpr Shift uxtw(uint32_t value) noexcept { return Shift(ShiftOp::kUXTW, value); } -//! Constructs a `UXTX #value` extend and shift (unsigned dword extend). -static constexpr Shift uxtx(uint32_t value) noexcept { return Shift(ShiftOp::kUXTX, value); } - -//! Constructs a `SXTB #value` extend and shift (signed byte extend). -static constexpr Shift sxtb(uint32_t value) noexcept { return Shift(ShiftOp::kSXTB, value); } -//! Constructs a `SXTH #value` extend and shift (signed hword extend). -static constexpr Shift sxth(uint32_t value) noexcept { return Shift(ShiftOp::kSXTH, value); } -//! Constructs a `SXTW #value` extend and shift (signed word extend). -static constexpr Shift sxtw(uint32_t value) noexcept { return Shift(ShiftOp::kSXTW, value); } -//! Constructs a `SXTX #value` extend and shift (signed dword extend). -static constexpr Shift sxtx(uint32_t value) noexcept { return Shift(ShiftOp::kSXTX, value); } - //! \} ASMJIT_END_SUB_NAMESPACE +ASMJIT_BEGIN_SUB_NAMESPACE(a32) + +using namespace arm; + +//! Data type that can be encoded with AArch32 instruction identifier. +//! +//! \note Data types are frequently used with AArch32 SIMD instructions. For example `VMAX` instruction can +//! use almost all datatypes in a form `VMAX.F32`, `VMAX.S16`, `VMAX.U32`, etc... Emitter automatically adds +//! the required data type at emit level. +enum class DataType : uint32_t { + //! No data type specified (default for all general purpose instructions). + kNone = 0, + //! 8-bit signed integer, specified as `.s8` in assembly. + kS8 = 1, + //! 16-bit signed integer, specified as `.s16` in assembly. + kS16 = 2, + //! 32-bit signed integer, specified as `.s32` in assembly. + kS32 = 3, + //! 64-bit signed integer, specified as `.s64` in assembly. + kS64 = 4, + //! 8-bit unsigned integer, specified as `.u8` in assembly. + kU8 = 5, + //! 16-bit unsigned integer, specified as `.u16` in assembly. + kU16 = 6, + //! 32-bit unsigned integer, specified as `.u32` in assembly. + kU32 = 7, + //! 64-bit unsigned integer, specified as `.u64` in assembly. + kU64 = 8, + //! 16-bit floating point (half precision), specified as `.f16` in assembly. + kF16 = 10, + //! 32-bit floating point (single precision), specified as `.f32` in assembly. + kF32 = 11, + //! 64-bit floating point (double precision), specified as `.f64` in assembly. + kF64 = 12, + //! 8-bit polynomial. + kP8 = 13, + //! 16-bit BF16 floating point. + kBF16 = 14, + //! 64-bit polynomial. + kP64 = 15, + + //! Maximum value of `DataType`. + kMaxValue = 15 +}; + +static ASMJIT_INLINE_NODEBUG uint32_t dataTypeSize(DataType dt) noexcept { + static constexpr uint8_t table[] = { 0, 1, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 1, 2, 8 }; + return table[size_t(dt)]; +} + +ASMJIT_END_SUB_NAMESPACE + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) +using namespace arm; +ASMJIT_END_SUB_NAMESPACE + #endif // ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/core/archtraits.cpp b/3rdparty/asmjit/src/asmjit/core/archtraits.cpp index fc825df8009..a15a00c048b 100644 --- a/3rdparty/asmjit/src/asmjit/core/archtraits.cpp +++ b/3rdparty/asmjit/src/asmjit/core/archtraits.cpp @@ -5,6 +5,7 @@ #include "../core/api-build_p.h" #include "../core/archtraits.h" +#include "../core/environment.h" #include "../core/misc_p.h" #if !defined(ASMJIT_NO_X86) diff --git a/3rdparty/asmjit/src/asmjit/core/archtraits.h b/3rdparty/asmjit/src/asmjit/core/archtraits.h index 192a826e511..9f08dea523f 100644 --- a/3rdparty/asmjit/src/asmjit/core/archtraits.h +++ b/3rdparty/asmjit/src/asmjit/core/archtraits.h @@ -74,6 +74,9 @@ enum class Arch : uint8_t { ASMJIT_ARCH_X86 == 32 ? kX86 : ASMJIT_ARCH_X86 == 64 ? kX64 : + ASMJIT_ARCH_RISCV == 32 ? kRISCV32 : + ASMJIT_ARCH_RISCV == 64 ? kRISCV64 : + ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_LE ? kARM : ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_BE ? kARM_BE : ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_LE ? kAArch64 : @@ -202,50 +205,50 @@ struct ArchTraits { //! \{ //! Returns stack pointer register id. - inline uint32_t spRegId() const noexcept { return _spRegId; } + ASMJIT_INLINE_NODEBUG uint32_t spRegId() const noexcept { return _spRegId; } //! Returns stack frame register id. - inline uint32_t fpRegId() const noexcept { return _fpRegId; } + ASMJIT_INLINE_NODEBUG uint32_t fpRegId() const noexcept { return _fpRegId; } //! Returns link register id, if the architecture provides it. - inline uint32_t linkRegId() const noexcept { return _linkRegId; } + ASMJIT_INLINE_NODEBUG uint32_t linkRegId() const noexcept { return _linkRegId; } //! Returns instruction pointer register id, if the architecture provides it. - inline uint32_t ipRegId() const noexcept { return _ipRegId; } + ASMJIT_INLINE_NODEBUG uint32_t ipRegId() const noexcept { return _ipRegId; } //! Returns a hardware stack alignment requirement. //! //! \note This is a hardware constraint. Architectures that don't constrain it would return the lowest alignment //! (1), however, some architectures may constrain the alignment, for example AArch64 requires 16-byte alignment. - inline uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; } + ASMJIT_INLINE_NODEBUG uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; } //! Tests whether the architecture provides link register, which is used across function calls. If the link //! register is not provided then a function call pushes the return address on stack (X86/X64). - inline bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; } //! Returns minimum addressable offset on stack guaranteed for all instructions. - inline uint32_t minStackOffset() const noexcept { return _minStackOffset; } + ASMJIT_INLINE_NODEBUG uint32_t minStackOffset() const noexcept { return _minStackOffset; } //! Returns maximum addressable offset on stack depending on specific instruction. - inline uint32_t maxStackOffset() const noexcept { return _maxStackOffset; } + ASMJIT_INLINE_NODEBUG uint32_t maxStackOffset() const noexcept { return _maxStackOffset; } //! Returns ISA flags of the given register `group`. - inline InstHints instFeatureHints(RegGroup group) const noexcept { return _instHints[group]; } + ASMJIT_INLINE_NODEBUG InstHints instFeatureHints(RegGroup group) const noexcept { return _instHints[group]; } //! Tests whether the given register `group` has the given `flag` set. - inline bool hasInstHint(RegGroup group, InstHints feature) const noexcept { return Support::test(_instHints[group], feature); } + ASMJIT_INLINE_NODEBUG bool hasInstHint(RegGroup group, InstHints feature) const noexcept { return Support::test(_instHints[group], feature); } //! Tests whether the ISA provides register swap instruction for the given register `group`. - inline bool hasInstRegSwap(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kRegSwap); } + ASMJIT_INLINE_NODEBUG bool hasInstRegSwap(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kRegSwap); } //! Tests whether the ISA provides push/pop instructions for the given register `group`. - inline bool hasInstPushPop(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kPushPop); } + ASMJIT_INLINE_NODEBUG bool hasInstPushPop(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kPushPop); } - inline bool hasRegType(RegType type) const noexcept { + ASMJIT_INLINE_NODEBUG bool hasRegType(RegType type) const noexcept { return type <= RegType::kMaxValue && _regSignature[type].isValid(); } //! Returns an operand signature from the given register `type` of this architecture. - inline OperandSignature regTypeToSignature(RegType type) const noexcept { return _regSignature[type]; } + ASMJIT_INLINE_NODEBUG OperandSignature regTypeToSignature(RegType type) const noexcept { return _regSignature[type]; } //! Returns a register from the given register `type` of this architecture. - inline RegGroup regTypeToGroup(RegType type) const noexcept { return _regSignature[type].regGroup(); } + ASMJIT_INLINE_NODEBUG RegGroup regTypeToGroup(RegType type) const noexcept { return _regSignature[type].regGroup(); } //! Returns a register size the given register `type` of this architecture. - inline uint32_t regTypeToSize(RegType type) const noexcept { return _regSignature[type].size(); } + ASMJIT_INLINE_NODEBUG uint32_t regTypeToSize(RegType type) const noexcept { return _regSignature[type].size(); } //! Returns a corresponding `TypeId` from the given register `type` of this architecture. - inline TypeId regTypeToTypeId(RegType type) const noexcept { return _regTypeToTypeId[type]; } + ASMJIT_INLINE_NODEBUG TypeId regTypeToTypeId(RegType type) const noexcept { return _regTypeToTypeId[type]; } //! Returns a table of ISA word names that appear in formatted text. Word names are ISA dependent. //! @@ -254,10 +257,10 @@ struct ArchTraits { //! - [1] 16-bits //! - [2] 32-bits //! - [3] 64-bits - inline const ArchTypeNameId* typeNameIdTable() const noexcept { return _typeNameIdTable; } + ASMJIT_INLINE_NODEBUG const ArchTypeNameId* typeNameIdTable() const noexcept { return _typeNameIdTable; } //! Returns an ISA word name identifier of the given `index`, see \ref typeNameIdTable() for more details. - inline ArchTypeNameId typeNameIdByIndex(uint32_t index) const noexcept { return _typeNameIdTable[index]; } + ASMJIT_INLINE_NODEBUG ArchTypeNameId typeNameIdByIndex(uint32_t index) const noexcept { return _typeNameIdTable[index]; } //! \} @@ -265,7 +268,7 @@ struct ArchTraits { //! \{ //! Returns a const reference to `ArchTraits` for the given architecture `arch`. - static inline const ArchTraits& byArch(Arch arch) noexcept; + static ASMJIT_INLINE_NODEBUG const ArchTraits& byArch(Arch arch) noexcept; //! \} }; @@ -273,7 +276,7 @@ struct ArchTraits { ASMJIT_VARAPI const ArchTraits _archTraits[uint32_t(Arch::kMaxValue) + 1]; //! \cond -inline const ArchTraits& ArchTraits::byArch(Arch arch) noexcept { return _archTraits[uint32_t(arch)]; } +ASMJIT_INLINE_NODEBUG const ArchTraits& ArchTraits::byArch(Arch arch) noexcept { return _archTraits[uint32_t(arch)]; } //! \endcond //! Architecture utilities. diff --git a/3rdparty/asmjit/src/asmjit/core/assembler.h b/3rdparty/asmjit/src/asmjit/core/assembler.h index 7ea2505f046..d53d9e53764 100644 --- a/3rdparty/asmjit/src/asmjit/core/assembler.h +++ b/3rdparty/asmjit/src/asmjit/core/assembler.h @@ -25,6 +25,7 @@ ASMJIT_BEGIN_NAMESPACE //! Check out architecture specific assemblers for more details and examples: //! //! - \ref x86::Assembler - X86/X64 assembler implementation. +//! - \ref a64::Assembler - AArch64 assembler implementation. class ASMJIT_VIRTAPI BaseAssembler : public BaseEmitter { public: ASMJIT_NONCOPYABLE(BaseAssembler) @@ -45,7 +46,7 @@ public: //! Creates a new `BaseAssembler` instance. ASMJIT_API BaseAssembler() noexcept; //! Destroys the `BaseAssembler` instance. - ASMJIT_API virtual ~BaseAssembler() noexcept; + ASMJIT_API ~BaseAssembler() noexcept override; //! \} @@ -53,12 +54,12 @@ public: //! \{ //! Returns the capacity of the current CodeBuffer. - inline size_t bufferCapacity() const noexcept { return (size_t)(_bufferEnd - _bufferData); } + ASMJIT_INLINE_NODEBUG size_t bufferCapacity() const noexcept { return (size_t)(_bufferEnd - _bufferData); } //! Returns the number of remaining bytes in the current CodeBuffer. - inline size_t remainingSpace() const noexcept { return (size_t)(_bufferEnd - _bufferPtr); } + ASMJIT_INLINE_NODEBUG size_t remainingSpace() const noexcept { return (size_t)(_bufferEnd - _bufferPtr); } //! Returns the current position in the CodeBuffer. - inline size_t offset() const noexcept { return (size_t)(_bufferPtr - _bufferData); } + ASMJIT_INLINE_NODEBUG size_t offset() const noexcept { return (size_t)(_bufferPtr - _bufferData); } //! Sets the current position in the CodeBuffer to `offset`. //! @@ -67,11 +68,11 @@ public: ASMJIT_API Error setOffset(size_t offset); //! Returns the start of the CodeBuffer in the current section. - inline uint8_t* bufferData() const noexcept { return _bufferData; } + ASMJIT_INLINE_NODEBUG uint8_t* bufferData() const noexcept { return _bufferData; } //! Returns the end (first invalid byte) in the current section. - inline uint8_t* bufferEnd() const noexcept { return _bufferEnd; } + ASMJIT_INLINE_NODEBUG uint8_t* bufferEnd() const noexcept { return _bufferEnd; } //! Returns the current pointer in the CodeBuffer in the current section. - inline uint8_t* bufferPtr() const noexcept { return _bufferPtr; } + ASMJIT_INLINE_NODEBUG uint8_t* bufferPtr() const noexcept { return _bufferPtr; } //! \} @@ -79,7 +80,7 @@ public: //! \{ //! Returns the current section. - inline Section* currentSection() const noexcept { return _section; } + ASMJIT_INLINE_NODEBUG Section* currentSection() const noexcept { return _section; } ASMJIT_API Error section(Section* section) override; diff --git a/3rdparty/asmjit/src/asmjit/core/builder.cpp b/3rdparty/asmjit/src/asmjit/core/builder.cpp index 5df243e7b8a..25433b9a0d8 100644 --- a/3rdparty/asmjit/src/asmjit/core/builder.cpp +++ b/3rdparty/asmjit/src/asmjit/core/builder.cpp @@ -65,7 +65,7 @@ Error BaseBuilder::newInstNode(InstNode** out, InstId instId, InstOptions instOp if (ASMJIT_UNLIKELY(!node)) return reportError(DebugUtils::errored(kErrorOutOfMemory)); - *out = new(node) InstNode(this, instId, instOptions, opCount, opCapacity); + *out = new(Support::PlacementNew{node}) InstNode(this, instId, instOptions, opCount, opCapacity); return kErrorOk; } @@ -151,14 +151,13 @@ BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept { ASMJIT_ASSERT(!node->isActive()); if (!_cursor) { - if (!_firstNode) { - _firstNode = node; - _lastNode = node; + if (_nodeList.empty()) { + _nodeList.reset(node, node); } else { - node->_next = _firstNode; - _firstNode->_prev = node; - _firstNode = node; + node->_next = _nodeList.first(); + _nodeList._first->_prev = node; + _nodeList._first = node; } } else { @@ -172,7 +171,7 @@ BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept { if (next) next->_prev = node; else - _lastNode = node; + _nodeList._last = node; } node->addFlags(NodeFlags::kIsActive); @@ -201,7 +200,7 @@ BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept { if (next) next->_prev = node; else - _lastNode = node; + _nodeList._last = node; return node; } @@ -226,7 +225,7 @@ BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept { if (prev) prev->_next = node; else - _firstNode = node; + _nodeList._first = node; return node; } @@ -238,13 +237,13 @@ BaseNode* BaseBuilder::removeNode(BaseNode* node) noexcept { BaseNode* prev = node->prev(); BaseNode* next = node->next(); - if (_firstNode == node) - _firstNode = next; + if (_nodeList._first == node) + _nodeList._first = next; else prev->_next = next; - if (_lastNode == node) - _lastNode = prev; + if (_nodeList._last == node) + _nodeList._last = prev; else next->_prev = prev; @@ -272,13 +271,13 @@ void BaseBuilder::removeNodes(BaseNode* first, BaseNode* last) noexcept { BaseNode* prev = first->prev(); BaseNode* next = last->next(); - if (_firstNode == first) - _firstNode = next; + if (_nodeList._first == first) + _nodeList._first = next; else prev->_next = next; - if (_lastNode == last) - _lastNode = prev; + if (_nodeList._last == last) + _nodeList._last = prev; else next->_prev = prev; @@ -368,7 +367,7 @@ Error BaseBuilder::section(Section* section) { if (node->_nextSection) _cursor = node->_nextSection->_prev; else - _cursor = _lastNode; + _cursor = _nodeList.last(); } return kErrorOk; @@ -378,7 +377,7 @@ void BaseBuilder::updateSectionLinks() noexcept { if (!_dirtySectionLinks) return; - BaseNode* node_ = _firstNode; + BaseNode* node_ = _nodeList.first(); SectionNode* currentSection = nullptr; while (node_) { @@ -591,13 +590,15 @@ Error BaseBuilder::_emit(InstId instId, const Operand_& o0, const Operand_& o1, EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); ValidationFlags validationFlags = isCompiler() ? ValidationFlags::kEnableVirtRegs : ValidationFlags::kNone; - Error err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount, validationFlags); + Error err = _funcs.validate(BaseInst(instId, options, _extraReg), opArray, opCount, validationFlags); if (ASMJIT_UNLIKELY(err)) { - resetInstOptions(); - resetExtraReg(); - resetInlineComment(); +#ifndef ASMJIT_NO_LOGGING + return EmitterUtils::logInstructionFailed(this, err, instId, options, o0, o1, o2, opExt); +#else + resetState(); return reportError(err); +#endif } } #endif @@ -620,7 +621,7 @@ Error BaseBuilder::_emit(InstId instId, const Operand_& o0, const Operand_& o1, return reportError(DebugUtils::errored(kErrorOutOfMemory)); } - node = new(node) InstNode(this, instId, options, opCount, opCapacity); + node = new(Support::PlacementNew{node}) InstNode(this, instId, options, opCount, opCapacity); node->setExtraReg(extraReg()); node->setOp(0, o0); node->setOp(1, o1); @@ -756,7 +757,7 @@ Error BaseBuilder::comment(const char* data, size_t size) { Error BaseBuilder::serializeTo(BaseEmitter* dst) { Error err = kErrorOk; - BaseNode* node_ = _firstNode; + BaseNode* node_ = _nodeList.first(); Operand_ opArray[Globals::kMaxOpCount]; @@ -852,8 +853,7 @@ Error BaseBuilder::onAttach(CodeHolder* code) noexcept { ASMJIT_ASSUME(initialSection != nullptr); _cursor = initialSection; - _firstNode = initialSection; - _lastNode = initialSection; + _nodeList.reset(initialSection, initialSection); initialSection->setFlags(NodeFlags::kIsActive); return kErrorOk; @@ -871,8 +871,7 @@ Error BaseBuilder::onDetach(CodeHolder* code) noexcept { _nodeFlags = NodeFlags::kNone; _cursor = nullptr; - _firstNode = nullptr; - _lastNode = nullptr; + _nodeList.reset(); return Base::onDetach(code); } @@ -884,6 +883,15 @@ Pass::Pass(const char* name) noexcept : _name(name) {} Pass::~Pass() noexcept {} +// Pass - Interface +// ================ + +// [[pure virtual]] +Error Pass::run(Zone* zone, Logger* logger) { + DebugUtils::unused(zone, logger); + return DebugUtils::errored(kErrorInvalidState); +} + ASMJIT_END_NAMESPACE #endif // !ASMJIT_NO_BUILDER diff --git a/3rdparty/asmjit/src/asmjit/core/builder.h b/3rdparty/asmjit/src/asmjit/core/builder.h index 3575de2fbb8..0de19234cb6 100644 --- a/3rdparty/asmjit/src/asmjit/core/builder.h +++ b/3rdparty/asmjit/src/asmjit/core/builder.h @@ -48,7 +48,7 @@ enum class NodeType : uint8_t { // [BaseBuilder] - //! Node is \ref InstNode or \ref InstExNode. + //! Node is \ref InstNode. kInst = 1, //! Node is \ref SectionNode. kSection = 2, @@ -109,7 +109,7 @@ enum class NodeFlags : uint8_t { }; ASMJIT_DEFINE_ENUM_FLAGS(NodeFlags) -//! Type of the sentinel (purery informative purpose). +//! Type of the sentinel (purely informative purpose). enum class SentinelType : uint8_t { //! Type of the sentinel is not known. kUnknown = 0u, @@ -117,6 +117,60 @@ enum class SentinelType : uint8_t { kFuncEnd = 1u }; +//! Node list. +//! +//! A double-linked list of pointers to \ref BaseNode, managed by \ref BaseBuilder or \ref BaseCompiler. +//! +//! \note At the moment NodeList is just a view, but it's planned that it will get more functionality in the future. +class NodeList { +public: + //! \name Members + //! \{ + + //! First node in the list or nullptr if there are no nodes in the list. + BaseNode* _first = nullptr; + //! Last node in the list or nullptr if there are no nodes in the list. + BaseNode* _last = nullptr; + + //! \} + + //! \name Construction & Destruction + //! \{ + + ASMJIT_INLINE_NODEBUG NodeList() noexcept {} + + ASMJIT_INLINE_NODEBUG NodeList(BaseNode* first, BaseNode* last) noexcept + : _first(first), + _last(last) {} + + //! \} + + //! \name Reset + //! \{ + + ASMJIT_INLINE_NODEBUG void reset() noexcept { + _first = nullptr; + _last = nullptr; + } + + ASMJIT_INLINE_NODEBUG void reset(BaseNode* first, BaseNode* last) noexcept { + _first = first; + _last = last; + } + + //! \} + + //! \name Accessors + //! \{ + + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _first == nullptr; } + + ASMJIT_INLINE_NODEBUG BaseNode* first() const noexcept { return _first; } + ASMJIT_INLINE_NODEBUG BaseNode* last() const noexcept { return _last; } + + //! \} +}; + //! Builder interface. //! //! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler replacement in case pre-processing or @@ -127,6 +181,7 @@ enum class SentinelType : uint8_t { //! Check out architecture specific builders for more details and examples: //! //! - \ref x86::Builder - X86/X64 builder implementation. +//! - \ref a64::Builder - AArch64 builder implementation. class ASMJIT_VIRTAPI BaseBuilder : public BaseEmitter { public: ASMJIT_NONCOPYABLE(BaseBuilder) @@ -153,10 +208,8 @@ public: //! Current node (cursor). BaseNode* _cursor = nullptr; - //! First node of the current section. - BaseNode* _firstNode = nullptr; - //! Last node of the current section. - BaseNode* _lastNode = nullptr; + //! First and last nodes. + NodeList _nodeList; //! Flags assigned to each new node. NodeFlags _nodeFlags = NodeFlags::kNone; @@ -171,17 +224,19 @@ public: //! Creates a new `BaseBuilder` instance. ASMJIT_API BaseBuilder() noexcept; //! Destroys the `BaseBuilder` instance. - ASMJIT_API virtual ~BaseBuilder() noexcept; + ASMJIT_API ~BaseBuilder() noexcept override; //! \} //! \name Node Management //! \{ + ASMJIT_INLINE_NODEBUG NodeList nodeList() const noexcept { return _nodeList; } + //! Returns the first node. - inline BaseNode* firstNode() const noexcept { return _firstNode; } + ASMJIT_INLINE_NODEBUG BaseNode* firstNode() const noexcept { return _nodeList.first(); } //! Returns the last node. - inline BaseNode* lastNode() const noexcept { return _lastNode; } + ASMJIT_INLINE_NODEBUG BaseNode* lastNode() const noexcept { return _nodeList.last(); } //! Allocates and instantiates a new node of type `T` and returns its instance. If the allocation fails `nullptr` //! is returned. @@ -227,7 +282,7 @@ public: //! When the Builder/Compiler is created it automatically creates a '.text' \ref SectionNode, which will be the //! initial one. When instructions are added they are always added after the cursor and the cursor is changed //! to be that newly added node. Use `setCursor()` to change where new nodes are inserted. - inline BaseNode* cursor() const noexcept { return _cursor; } + ASMJIT_INLINE_NODEBUG BaseNode* cursor() const noexcept { return _cursor; } //! Sets the current node to `node` and return the previous one. ASMJIT_API BaseNode* setCursor(BaseNode* node) noexcept; @@ -236,7 +291,7 @@ public: //! //! Only use this function if you are concerned about performance and want this inlined (for example if you set //! the cursor in a loop, etc...). - inline void _setCursor(BaseNode* node) noexcept { _cursor = node; } + ASMJIT_INLINE_NODEBUG void _setCursor(BaseNode* node) noexcept { _cursor = node; } //! \} @@ -247,12 +302,12 @@ public: //! //! \note If a section of some id is not associated with the Builder/Compiler it would be null, so always check //! for nulls if you iterate over the vector. - inline const ZoneVector<SectionNode*>& sectionNodes() const noexcept { + ASMJIT_INLINE_NODEBUG const ZoneVector<SectionNode*>& sectionNodes() const noexcept { return _sectionNodes; } //! Tests whether the `SectionNode` of the given `sectionId` was registered. - inline bool hasRegisteredSectionNode(uint32_t sectionId) const noexcept { + ASMJIT_INLINE_NODEBUG bool hasRegisteredSectionNode(uint32_t sectionId) const noexcept { return sectionId < _sectionNodes.size() && _sectionNodes[sectionId] != nullptr; } @@ -266,7 +321,7 @@ public: //! Returns whether the section links of active section nodes are dirty. You can update these links by calling //! `updateSectionLinks()` in such case. - inline bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; } + ASMJIT_INLINE_NODEBUG bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; } //! Updates links of all active section nodes. ASMJIT_API void updateSectionLinks() noexcept; @@ -280,15 +335,15 @@ public: //! //! \note If a label of some id is not associated with the Builder/Compiler it would be null, so always check for //! nulls if you iterate over the vector. - inline const ZoneVector<LabelNode*>& labelNodes() const noexcept { return _labelNodes; } + ASMJIT_INLINE_NODEBUG const ZoneVector<LabelNode*>& labelNodes() const noexcept { return _labelNodes; } //! Tests whether the `LabelNode` of the given `labelId` was registered. - inline bool hasRegisteredLabelNode(uint32_t labelId) const noexcept { + ASMJIT_INLINE_NODEBUG bool hasRegisteredLabelNode(uint32_t labelId) const noexcept { return labelId < _labelNodes.size() && _labelNodes[labelId] != nullptr; } //! \overload - inline bool hasRegisteredLabelNode(const Label& label) const noexcept { + ASMJIT_INLINE_NODEBUG bool hasRegisteredLabelNode(const Label& label) const noexcept { return hasRegisteredLabelNode(label.id()); } @@ -299,7 +354,7 @@ public: ASMJIT_API Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), uint32_t labelId); //! \overload - inline Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), const Label& label) { + ASMJIT_INLINE_NODEBUG Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), const Label& label) { return labelNodeOf(out, label.id()); } @@ -319,7 +374,7 @@ public: //! \{ //! Returns a vector of `Pass` instances that will be executed by `runPasses()`. - inline const ZoneVector<Pass*>& passes() const noexcept { return _passes; } + ASMJIT_INLINE_NODEBUG const ZoneVector<Pass*>& passes() const noexcept { return _passes; } //! Allocates and instantiates a new pass of type `T` and returns its instance. If the allocation fails `nullptr` is //! returned. @@ -492,7 +547,7 @@ public: uint8_t _reserved1; }; - //! Data that can have different meaning dependning on \ref NodeType. + //! Data that can have different meaning depending on \ref NodeType. union { //! Data useful by any node type. AnyData _any; @@ -529,7 +584,7 @@ public: //! \{ //! Creates a new `BaseNode` - always use `BaseBuilder` to allocate nodes. - inline BaseNode(BaseBuilder* cb, NodeType nodeType, NodeFlags nodeFlags = NodeFlags::kNone) noexcept { + ASMJIT_INLINE_NODEBUG BaseNode(BaseBuilder* cb, NodeType nodeType, NodeFlags nodeFlags = NodeFlags::kNone) noexcept { _prev = nullptr; _next = nullptr; _any._nodeType = nodeType; @@ -549,85 +604,85 @@ public: //! Casts this node to `T*`. template<typename T> - inline T* as() noexcept { return static_cast<T*>(this); } + ASMJIT_INLINE_NODEBUG T* as() noexcept { return static_cast<T*>(this); } //! Casts this node to `const T*`. template<typename T> - inline const T* as() const noexcept { return static_cast<const T*>(this); } + ASMJIT_INLINE_NODEBUG const T* as() const noexcept { return static_cast<const T*>(this); } //! Returns previous node or `nullptr` if this node is either first or not //! part of Builder/Compiler node-list. - inline BaseNode* prev() const noexcept { return _prev; } + ASMJIT_INLINE_NODEBUG BaseNode* prev() const noexcept { return _prev; } //! Returns next node or `nullptr` if this node is either last or not part //! of Builder/Compiler node-list. - inline BaseNode* next() const noexcept { return _next; } + ASMJIT_INLINE_NODEBUG BaseNode* next() const noexcept { return _next; } //! Returns the type of the node, see `NodeType`. - inline NodeType type() const noexcept { return _any._nodeType; } + ASMJIT_INLINE_NODEBUG NodeType type() const noexcept { return _any._nodeType; } //! Sets the type of the node, see `NodeType` (internal). //! //! \remarks You should never set a type of a node to anything else than the initial value. This function is only //! provided for users that use custom nodes and need to change the type either during construction or later. - inline void setType(NodeType type) noexcept { _any._nodeType = type; } + ASMJIT_INLINE_NODEBUG void setType(NodeType type) noexcept { _any._nodeType = type; } //! Tests whether this node is either `InstNode` or extends it. - inline bool isInst() const noexcept { return hasFlag(NodeFlags::kActsAsInst); } + ASMJIT_INLINE_NODEBUG bool isInst() const noexcept { return hasFlag(NodeFlags::kActsAsInst); } //! Tests whether this node is `SectionNode`. - inline bool isSection() const noexcept { return type() == NodeType::kSection; } + ASMJIT_INLINE_NODEBUG bool isSection() const noexcept { return type() == NodeType::kSection; } //! Tests whether this node is either `LabelNode` or extends it. - inline bool isLabel() const noexcept { return hasFlag(NodeFlags::kActsAsLabel); } + ASMJIT_INLINE_NODEBUG bool isLabel() const noexcept { return hasFlag(NodeFlags::kActsAsLabel); } //! Tests whether this node is `AlignNode`. - inline bool isAlign() const noexcept { return type() == NodeType::kAlign; } + ASMJIT_INLINE_NODEBUG bool isAlign() const noexcept { return type() == NodeType::kAlign; } //! Tests whether this node is `EmbedDataNode`. - inline bool isEmbedData() const noexcept { return type() == NodeType::kEmbedData; } + ASMJIT_INLINE_NODEBUG bool isEmbedData() const noexcept { return type() == NodeType::kEmbedData; } //! Tests whether this node is `EmbedLabelNode`. - inline bool isEmbedLabel() const noexcept { return type() == NodeType::kEmbedLabel; } + ASMJIT_INLINE_NODEBUG bool isEmbedLabel() const noexcept { return type() == NodeType::kEmbedLabel; } //! Tests whether this node is `EmbedLabelDeltaNode`. - inline bool isEmbedLabelDelta() const noexcept { return type() == NodeType::kEmbedLabelDelta; } + ASMJIT_INLINE_NODEBUG bool isEmbedLabelDelta() const noexcept { return type() == NodeType::kEmbedLabelDelta; } //! Tests whether this node is `ConstPoolNode`. - inline bool isConstPool() const noexcept { return type() == NodeType::kConstPool; } + ASMJIT_INLINE_NODEBUG bool isConstPool() const noexcept { return type() == NodeType::kConstPool; } //! Tests whether this node is `CommentNode`. - inline bool isComment() const noexcept { return type() == NodeType::kComment; } + ASMJIT_INLINE_NODEBUG bool isComment() const noexcept { return type() == NodeType::kComment; } //! Tests whether this node is `SentinelNode`. - inline bool isSentinel() const noexcept { return type() == NodeType::kSentinel; } + ASMJIT_INLINE_NODEBUG bool isSentinel() const noexcept { return type() == NodeType::kSentinel; } //! Tests whether this node is `FuncNode`. - inline bool isFunc() const noexcept { return type() == NodeType::kFunc; } + ASMJIT_INLINE_NODEBUG bool isFunc() const noexcept { return type() == NodeType::kFunc; } //! Tests whether this node is `FuncRetNode`. - inline bool isFuncRet() const noexcept { return type() == NodeType::kFuncRet; } + ASMJIT_INLINE_NODEBUG bool isFuncRet() const noexcept { return type() == NodeType::kFuncRet; } //! Tests whether this node is `InvokeNode`. - inline bool isInvoke() const noexcept { return type() == NodeType::kInvoke; } + ASMJIT_INLINE_NODEBUG bool isInvoke() const noexcept { return type() == NodeType::kInvoke; } //! Returns the node flags. - inline NodeFlags flags() const noexcept { return _any._nodeFlags; } + ASMJIT_INLINE_NODEBUG NodeFlags flags() const noexcept { return _any._nodeFlags; } //! Tests whether the node has the given `flag` set. - inline bool hasFlag(NodeFlags flag) const noexcept { return Support::test(_any._nodeFlags, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(NodeFlags flag) const noexcept { return Support::test(_any._nodeFlags, flag); } //! Replaces node flags with `flags`. - inline void setFlags(NodeFlags flags) noexcept { _any._nodeFlags = flags; } + ASMJIT_INLINE_NODEBUG void setFlags(NodeFlags flags) noexcept { _any._nodeFlags = flags; } //! Adds the given `flags` to node flags. - inline void addFlags(NodeFlags flags) noexcept { _any._nodeFlags |= flags; } + ASMJIT_INLINE_NODEBUG void addFlags(NodeFlags flags) noexcept { _any._nodeFlags |= flags; } //! Clears the given `flags` from node flags. - inline void clearFlags(NodeFlags flags) noexcept { _any._nodeFlags &= ~flags; } + ASMJIT_INLINE_NODEBUG void clearFlags(NodeFlags flags) noexcept { _any._nodeFlags &= ~flags; } //! Tests whether the node is code that can be executed. - inline bool isCode() const noexcept { return hasFlag(NodeFlags::kIsCode); } + ASMJIT_INLINE_NODEBUG bool isCode() const noexcept { return hasFlag(NodeFlags::kIsCode); } //! Tests whether the node is data that cannot be executed. - inline bool isData() const noexcept { return hasFlag(NodeFlags::kIsData); } + ASMJIT_INLINE_NODEBUG bool isData() const noexcept { return hasFlag(NodeFlags::kIsData); } //! Tests whether the node is informative only (is never encoded like comment, etc...). - inline bool isInformative() const noexcept { return hasFlag(NodeFlags::kIsInformative); } + ASMJIT_INLINE_NODEBUG bool isInformative() const noexcept { return hasFlag(NodeFlags::kIsInformative); } //! Tests whether the node is removable if it's in an unreachable code block. - inline bool isRemovable() const noexcept { return hasFlag(NodeFlags::kIsRemovable); } + ASMJIT_INLINE_NODEBUG bool isRemovable() const noexcept { return hasFlag(NodeFlags::kIsRemovable); } //! Tests whether the node has no effect when executed (label, .align, nop, ...). - inline bool hasNoEffect() const noexcept { return hasFlag(NodeFlags::kHasNoEffect); } + ASMJIT_INLINE_NODEBUG bool hasNoEffect() const noexcept { return hasFlag(NodeFlags::kHasNoEffect); } //! Tests whether the node is part of the code. - inline bool isActive() const noexcept { return hasFlag(NodeFlags::kIsActive); } + ASMJIT_INLINE_NODEBUG bool isActive() const noexcept { return hasFlag(NodeFlags::kIsActive); } //! Tests whether the node has a position assigned. //! //! \remarks Returns `true` if node position is non-zero. - inline bool hasPosition() const noexcept { return _position != 0; } + ASMJIT_INLINE_NODEBUG bool hasPosition() const noexcept { return _position != 0; } //! Returns node position. - inline uint32_t position() const noexcept { return _position; } + ASMJIT_INLINE_NODEBUG uint32_t position() const noexcept { return _position; } //! Sets node position. //! //! Node position is a 32-bit unsigned integer that is used by Compiler to track where the node is relatively to @@ -636,49 +691,50 @@ public: //! //! If you don't use Compiler then you may use `position()` and `setPosition()` freely for your own purposes if //! the 32-bit value limit is okay for you. - inline void setPosition(uint32_t position) noexcept { _position = position; } + ASMJIT_INLINE_NODEBUG void setPosition(uint32_t position) noexcept { _position = position; } //! Returns user data casted to `T*`. //! - //! User data is decicated to be used only by AsmJit users and not touched by the library. The data has a pointer - //! size so you can either store a pointer or `intptr_t` value through `setUserDataAsIntPtr()`. + //! User data is dedicated to be used only by AsmJit users and not touched by the library. The data is of a pointer + //! size so you can either store a pointer or `int64_t` value through `setUserDataAsPtr()`, `setUserDataAsInt64()` + //! and `setUserDataAsUInt64()`. template<typename T> - inline T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); } + ASMJIT_INLINE_NODEBUG T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); } //! Returns user data casted to `int64_t`. - inline int64_t userDataAsInt64() const noexcept { return int64_t(_userDataU64); } + ASMJIT_INLINE_NODEBUG int64_t userDataAsInt64() const noexcept { return int64_t(_userDataU64); } //! Returns user data casted to `uint64_t`. - inline uint64_t userDataAsUInt64() const noexcept { return _userDataU64; } + ASMJIT_INLINE_NODEBUG uint64_t userDataAsUInt64() const noexcept { return _userDataU64; } //! Sets user data to `data`. template<typename T> - inline void setUserDataAsPtr(T* data) noexcept { _userDataPtr = static_cast<void*>(data); } + ASMJIT_INLINE_NODEBUG void setUserDataAsPtr(T* data) noexcept { _userDataPtr = static_cast<void*>(data); } //! Sets used data to the given 64-bit signed `value`. - inline void setUserDataAsInt64(int64_t value) noexcept { _userDataU64 = uint64_t(value); } + ASMJIT_INLINE_NODEBUG void setUserDataAsInt64(int64_t value) noexcept { _userDataU64 = uint64_t(value); } //! Sets used data to the given 64-bit unsigned `value`. - inline void setUserDataAsUInt64(uint64_t value) noexcept { _userDataU64 = value; } + ASMJIT_INLINE_NODEBUG void setUserDataAsUInt64(uint64_t value) noexcept { _userDataU64 = value; } //! Resets user data to zero / nullptr. - inline void resetUserData() noexcept { _userDataU64 = 0; } + ASMJIT_INLINE_NODEBUG void resetUserData() noexcept { _userDataU64 = 0; } //! Tests whether the node has an associated pass data. - inline bool hasPassData() const noexcept { return _passData != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasPassData() const noexcept { return _passData != nullptr; } //! Returns the node pass data - data used during processing & transformations. template<typename T> - inline T* passData() const noexcept { return (T*)_passData; } + ASMJIT_INLINE_NODEBUG T* passData() const noexcept { return (T*)_passData; } //! Sets the node pass data to `data`. template<typename T> - inline void setPassData(T* data) noexcept { _passData = (void*)data; } + ASMJIT_INLINE_NODEBUG void setPassData(T* data) noexcept { _passData = (void*)data; } //! Resets the node pass data to nullptr. - inline void resetPassData() noexcept { _passData = nullptr; } + ASMJIT_INLINE_NODEBUG void resetPassData() noexcept { _passData = nullptr; } //! Tests whether the node has an inline comment/annotation. - inline bool hasInlineComment() const noexcept { return _inlineComment != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasInlineComment() const noexcept { return _inlineComment != nullptr; } //! Returns an inline comment/annotation string. - inline const char* inlineComment() const noexcept { return _inlineComment; } + ASMJIT_INLINE_NODEBUG const char* inlineComment() const noexcept { return _inlineComment; } //! Sets an inline comment/annotation string to `s`. - inline void setInlineComment(const char* s) noexcept { _inlineComment = s; } + ASMJIT_INLINE_NODEBUG void setInlineComment(const char* s) noexcept { _inlineComment = s; } //! Resets an inline comment/annotation string to nullptr. - inline void resetInlineComment() noexcept { _inlineComment = nullptr; } + ASMJIT_INLINE_NODEBUG void resetInlineComment() noexcept { _inlineComment = nullptr; } //! \} }; @@ -693,12 +749,15 @@ public: //! \name Constants //! \{ - enum : uint32_t { - //! Count of embedded operands per `InstNode` that are always allocated as a part of the instruction. Minimum - //! embedded operands is 4, but in 32-bit more pointers are smaller and we can embed 5. The rest (up to 6 operands) - //! is always stored in `InstExNode`. - kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)) - }; + //! The number of embedded operands for a default \ref InstNode instance that are always allocated as a part of + //! the instruction itself. Minimum embedded operands is 4, but in 32-bit more pointers are smaller and we can + //! embed 5. The rest (up to 6 operands) is considered extended. + //! + //! The number of operands InstNode holds is decided when \ref InstNode is created. + static constexpr uint32_t kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)); + + //! Count of maximum number of operands \ref InstNode can hold. + static constexpr uint32_t kFullOpCapacity = Globals::kMaxOpCount; //! \} @@ -707,8 +766,6 @@ public: //! Base instruction data. BaseInst _baseInst; - //! First 4 or 5 operands (indexed from 0). - Operand_ _opArray[kBaseOpCapacity]; //! \} @@ -716,7 +773,7 @@ public: //! \{ //! Creates a new `InstNode` instance. - inline InstNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept + ASMJIT_INLINE_NODEBUG InstNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept : BaseNode(cb, NodeType::kInst, NodeFlags::kIsCode | NodeFlags::kIsRemovable | NodeFlags::kActsAsInst), _baseInst(instId, options) { _inst._opCapacity = uint8_t(opCapacity); @@ -725,7 +782,7 @@ public: //! \cond INTERNAL //! Reset all built-in operands, including `extraReg`. - inline void _resetOps() noexcept { + ASMJIT_INLINE_NODEBUG void _resetOps() noexcept { _baseInst.resetExtraReg(); resetOpRange(0, opCapacity()); } @@ -736,8 +793,8 @@ public: //! \name Instruction Object //! \{ - inline BaseInst& baseInst() noexcept { return _baseInst; } - inline const BaseInst& baseInst() const noexcept { return _baseInst; } + ASMJIT_INLINE_NODEBUG BaseInst& baseInst() noexcept { return _baseInst; } + ASMJIT_INLINE_NODEBUG const BaseInst& baseInst() const noexcept { return _baseInst; } //! \} @@ -745,24 +802,30 @@ public: //! \{ //! Returns the instruction id, see `BaseInst::Id`. - inline InstId id() const noexcept { return _baseInst.id(); } + ASMJIT_INLINE_NODEBUG InstId id() const noexcept { return _baseInst.id(); } //! Returns the instruction real id, see `BaseInst::Id`. - inline InstId realId() const noexcept { return _baseInst.realId(); } + ASMJIT_INLINE_NODEBUG InstId realId() const noexcept { return _baseInst.realId(); } //! Sets the instruction id to `id`, see `BaseInst::Id`. - inline void setId(InstId id) noexcept { _baseInst.setId(id); } + ASMJIT_INLINE_NODEBUG void setId(InstId id) noexcept { _baseInst.setId(id); } //! \} //! \name Instruction Options //! \{ - inline InstOptions options() const noexcept { return _baseInst.options(); } - inline bool hasOption(InstOptions option) const noexcept { return _baseInst.hasOption(option); } - inline void setOptions(InstOptions options) noexcept { _baseInst.setOptions(options); } - inline void addOptions(InstOptions options) noexcept { _baseInst.addOptions(options); } - inline void clearOptions(InstOptions options) noexcept { _baseInst.clearOptions(options); } - inline void resetOptions() noexcept { _baseInst.resetOptions(); } + //! Returns instruction options, see \ref InstOptions for more details. + ASMJIT_INLINE_NODEBUG InstOptions options() const noexcept { return _baseInst.options(); } + //! Tests whether instruction has the given \option` set/enabled. + ASMJIT_INLINE_NODEBUG bool hasOption(InstOptions option) const noexcept { return _baseInst.hasOption(option); } + //! Sets instruction `options` to the provided value, resetting all others. + ASMJIT_INLINE_NODEBUG void setOptions(InstOptions options) noexcept { _baseInst.setOptions(options); } + //! Adds instruction `options` to the instruction. + ASMJIT_INLINE_NODEBUG void addOptions(InstOptions options) noexcept { _baseInst.addOptions(options); } + //! Clears instruction `options` of the instruction (disables the given options). + ASMJIT_INLINE_NODEBUG void clearOptions(InstOptions options) noexcept { _baseInst.clearOptions(options); } + //! Resets instruction options to none - disabling all instruction options. + ASMJIT_INLINE_NODEBUG void resetOptions() noexcept { _baseInst.resetOptions(); } //! \} @@ -770,17 +833,17 @@ public: //! \{ //! Tests whether the node has an extra register operand. - inline bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); } + ASMJIT_INLINE_NODEBUG bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); } //! Returns extra register operand. - inline RegOnly& extraReg() noexcept { return _baseInst.extraReg(); } + ASMJIT_INLINE_NODEBUG RegOnly& extraReg() noexcept { return _baseInst.extraReg(); } //! \overload - inline const RegOnly& extraReg() const noexcept { return _baseInst.extraReg(); } + ASMJIT_INLINE_NODEBUG const RegOnly& extraReg() const noexcept { return _baseInst.extraReg(); } //! Sets extra register operand to `reg`. - inline void setExtraReg(const BaseReg& reg) noexcept { _baseInst.setExtraReg(reg); } + ASMJIT_INLINE_NODEBUG void setExtraReg(const BaseReg& reg) noexcept { _baseInst.setExtraReg(reg); } //! Sets extra register operand to `reg`. - inline void setExtraReg(const RegOnly& reg) noexcept { _baseInst.setExtraReg(reg); } + ASMJIT_INLINE_NODEBUG void setExtraReg(const RegOnly& reg) noexcept { _baseInst.setExtraReg(reg); } //! Resets extra register operand. - inline void resetExtraReg() noexcept { _baseInst.resetExtraReg(); } + ASMJIT_INLINE_NODEBUG void resetExtraReg() noexcept { _baseInst.resetExtraReg(); } //! \} @@ -788,46 +851,60 @@ public: //! \{ //! Returns operand count. - inline uint32_t opCount() const noexcept { return _inst._opCount; } + ASMJIT_INLINE_NODEBUG uint32_t opCount() const noexcept { return _inst._opCount; } //! Returns operand capacity. - inline uint32_t opCapacity() const noexcept { return _inst._opCapacity; } + ASMJIT_INLINE_NODEBUG uint32_t opCapacity() const noexcept { return _inst._opCapacity; } //! Sets operand count. - inline void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); } + ASMJIT_INLINE_NODEBUG void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); } //! Returns operands array. - inline Operand* operands() noexcept { return (Operand*)_opArray; } + ASMJIT_INLINE_NODEBUG Operand* operands() noexcept { + return reinterpret_cast<Operand*>(reinterpret_cast<uint8_t*>(this) + sizeof(InstNode)); + } + //! Returns operands array (const). - inline const Operand* operands() const noexcept { return (const Operand*)_opArray; } + ASMJIT_INLINE_NODEBUG const Operand* operands() const noexcept { + return reinterpret_cast<const Operand*>(reinterpret_cast<const uint8_t*>(this) + sizeof(InstNode)); + } //! Returns operand at the given `index`. inline Operand& op(uint32_t index) noexcept { ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as<Operand>(); + + Operand* ops = operands(); + return ops[index].as<Operand>(); } //! Returns operand at the given `index` (const). inline const Operand& op(uint32_t index) const noexcept { ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as<Operand>(); + + const Operand* ops = operands(); + return ops[index].as<Operand>(); } //! Sets operand at the given `index` to `op`. inline void setOp(uint32_t index, const Operand_& op) noexcept { ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].copyFrom(op); + + Operand* ops = operands(); + ops[index].copyFrom(op); } //! Resets operand at the given `index` to none. inline void resetOp(uint32_t index) noexcept { ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].reset(); + + Operand* ops = operands(); + ops[index].reset(); } //! Resets operands at `[start, end)` range. inline void resetOpRange(uint32_t start, uint32_t end) noexcept { + Operand* ops = operands(); for (uint32_t i = start; i < end; i++) - _opArray[i].reset(); + ops[i].reset(); } //! \} @@ -835,33 +912,47 @@ public: //! \name Utilities //! \{ + //! Tests whether the given operand type `opType` is used by the instruction. inline bool hasOpType(OperandType opType) const noexcept { + const Operand* ops = operands(); for (uint32_t i = 0, count = opCount(); i < count; i++) - if (_opArray[i].opType() == opType) + if (ops[i].opType() == opType) return true; return false; } + //! Tests whether the instruction uses at least one register operand. inline bool hasRegOp() const noexcept { return hasOpType(OperandType::kReg); } + //! Tests whether the instruction uses at least one memory operand. inline bool hasMemOp() const noexcept { return hasOpType(OperandType::kMem); } + //! Tests whether the instruction uses at least one immediate operand. inline bool hasImmOp() const noexcept { return hasOpType(OperandType::kImm); } + //! Tests whether the instruction uses at least one label operand. inline bool hasLabelOp() const noexcept { return hasOpType(OperandType::kLabel); } + //! Returns the index of the given operand type `opType`. + //! + //! \note If the operand type wa found, the value returned represents its index in \ref operands() + //! array, otherwise \ref Globals::kNotFound is returned to signalize that the operand was not found. inline uint32_t indexOfOpType(OperandType opType) const noexcept { uint32_t i = 0; uint32_t count = opCount(); + const Operand* ops = operands(); while (i < count) { - if (_opArray[i].opType() == opType) - break; + if (ops[i].opType() == opType) + return i; i++; } - return i; + return Globals::kNotFound; } + //! A shortcut that calls `indexOfOpType(OperandType::kMem)`. inline uint32_t indexOfMemOp() const noexcept { return indexOfOpType(OperandType::kMem); } + //! A shortcut that calls `indexOfOpType(OperandType::kImm)`. inline uint32_t indexOfImmOp() const noexcept { return indexOfOpType(OperandType::kImm); } + //! A shortcut that calls `indexOfOpType(OperandType::kLabel)`. inline uint32_t indexOfLabelOp() const noexcept { return indexOfOpType(OperandType::kLabel); } //! \} @@ -870,20 +961,40 @@ public: //! \{ //! \cond INTERNAL - inline uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; } - inline const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; } + //! Returns uint32_t[] view that represents BaseInst::RegOnly and instruction operands. + ASMJIT_INLINE_NODEBUG uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; } + //! \overload + ASMJIT_INLINE_NODEBUG const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; } + + //! Maximum value of rewrite id - 6 operands each having 4 slots is 24, one RegOnly having 2 slots => 26. + static constexpr uint32_t kMaxRewriteId = 26 - 1; + + //! Returns a rewrite index of the given pointer to `id`. + //! + //! This function returns a value that can be then passed to `\ref rewriteIdAtIndex() function. It can address + //! any id from any operand that is used by the instruction in addition to \ref BaseInst::regOnly field, which + //! can also be used by the register allocator. inline uint32_t getRewriteIndex(const uint32_t* id) const noexcept { const uint32_t* array = _getRewriteArray(); ASMJIT_ASSERT(array <= id); size_t index = (size_t)(id - array); - ASMJIT_ASSERT(index < 32); + ASMJIT_ASSERT(index <= kMaxRewriteId); return uint32_t(index); } + //! Rewrites the given `index` to the provided identifier `id`. + //! + //! \note This is an internal function that is used by a \ref BaseCompiler implementation to rewrite virtual + //! registers to physical registers. The rewriter in this case sees all operands as array of uint32 values + //! and the given `index` describes a position in this array. For example a single \ref Operand would be + //! decomposed to 4 uint32_t values, where the first at index 0 would be operand signature, next would be + //! base id, etc... This is a comfortable way of patching operands without having to check for their types. inline void rewriteIdAtIndex(uint32_t index, uint32_t id) noexcept { + ASMJIT_ASSERT(index <= kMaxRewriteId); + uint32_t* array = _getRewriteArray(); array[index] = id; } @@ -895,43 +1006,40 @@ public: //! \{ //! \cond INTERNAL - static inline uint32_t capacityOfOpCount(uint32_t opCount) noexcept { - return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount; + + //! Returns the capacity required for the given operands count `opCount`. + //! + //! There are only two capacities used - \ref kBaseOpCapacity and \ref kFullOpCapacity, so this function + //! is used to decide between these two. The general rule is that instructions that can be represented with + //! \ref kBaseOpCapacity would use this value, and all others would take \ref kFullOpCapacity. + static ASMJIT_INLINE_NODEBUG constexpr uint32_t capacityOfOpCount(uint32_t opCount) noexcept { + return opCount <= kBaseOpCapacity ? kBaseOpCapacity : kFullOpCapacity; } - static inline size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept { - size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand); - return base + opCapacity * sizeof(Operand); + //! Calculates the size of \ref InstNode required to hold at most `opCapacity` operands. + //! + //! This function is used internally to allocate \ref InstNode. + static ASMJIT_INLINE_NODEBUG constexpr size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept { + return sizeof(InstNode) + opCapacity * sizeof(Operand); } //! \endcond //! \} }; -//! Instruction node with maximum number of operands. +//! Instruction node with embedded operands following \ref InstNode layout. //! -//! This node is created automatically by Builder/Compiler in case that the required number of operands exceeds -//! the default capacity of `InstNode`. -class InstExNode : public InstNode { +//! \note This is used to make tools such as static analysis and compilers happy about the layout. There were two +//! instruction nodes in the past, having the second extend the operand array of the first, but that has caused +//! undefined behavior and made recent tools unhappy about that. +template<uint32_t kN> +class InstNodeWithOperands : public InstNode { public: - ASMJIT_NONCOPYABLE(InstExNode) - - //! \name Members - //! \{ + Operand_ _operands[kN]; - //! Continued `_opArray[]` to hold up to `kMaxOpCount` operands. - Operand_ _opArrayEx[Globals::kMaxOpCount - kBaseOpCapacity]; - - //! \} - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InstExNode` instance. - inline InstExNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept - : InstNode(cb, instId, options, opCapacity) {} - - //! \} + //! Creates a new `InstNodeWithOperands` instance. + ASMJIT_INLINE_NODEBUG InstNodeWithOperands(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount) noexcept + : InstNode(cb, instId, options, opCount, kN) {} }; //! Section node. @@ -958,9 +1066,9 @@ public: //! \{ //! Creates a new `SectionNode` instance. - inline SectionNode(BaseBuilder* cb, uint32_t secionId = 0) noexcept + ASMJIT_INLINE_NODEBUG SectionNode(BaseBuilder* cb, uint32_t sectionId = 0) noexcept : BaseNode(cb, NodeType::kSection, NodeFlags::kHasNoEffect), - _id(secionId), + _id(sectionId), _nextSection(nullptr) {} //! \} @@ -969,7 +1077,7 @@ public: //! \{ //! Returns the section id. - inline uint32_t id() const noexcept { return _id; } + ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _id; } //! \} }; @@ -991,7 +1099,7 @@ public: //! \{ //! Creates a new `LabelNode` instance. - inline LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept + ASMJIT_INLINE_NODEBUG LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept : BaseNode(cb, NodeType::kLabel, NodeFlags::kHasNoEffect | NodeFlags::kActsAsLabel), _labelId(labelId) {} @@ -1001,9 +1109,9 @@ public: //! \{ //! Returns \ref Label representation of the \ref LabelNode. - inline Label label() const noexcept { return Label(_labelId); } + ASMJIT_INLINE_NODEBUG Label label() const noexcept { return Label(_labelId); } //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } + ASMJIT_INLINE_NODEBUG uint32_t labelId() const noexcept { return _labelId; } //! \} }; @@ -1027,7 +1135,7 @@ public: //! \{ //! Creates a new `AlignNode` instance. - inline AlignNode(BaseBuilder* cb, AlignMode alignMode, uint32_t alignment) noexcept + ASMJIT_INLINE_NODEBUG AlignNode(BaseBuilder* cb, AlignMode alignMode, uint32_t alignment) noexcept : BaseNode(cb, NodeType::kAlign, NodeFlags::kIsCode | NodeFlags::kHasNoEffect) { _alignData._alignMode = alignMode; @@ -1040,14 +1148,14 @@ public: //! \{ //! Returns align mode. - inline AlignMode alignMode() const noexcept { return _alignData._alignMode; } + ASMJIT_INLINE_NODEBUG AlignMode alignMode() const noexcept { return _alignData._alignMode; } //! Sets align mode to `alignMode`. - inline void setAlignMode(AlignMode alignMode) noexcept { _alignData._alignMode = alignMode; } + ASMJIT_INLINE_NODEBUG void setAlignMode(AlignMode alignMode) noexcept { _alignData._alignMode = alignMode; } //! Returns align offset in bytes. - inline uint32_t alignment() const noexcept { return _alignment; } + ASMJIT_INLINE_NODEBUG uint32_t alignment() const noexcept { return _alignment; } //! Sets align offset in bytes to `offset`. - inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; } + ASMJIT_INLINE_NODEBUG void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; } //! \} }; @@ -1083,7 +1191,7 @@ public: //! \{ //! Creates a new `EmbedDataNode` instance. - inline EmbedDataNode(BaseBuilder* cb) noexcept + ASMJIT_INLINE_NODEBUG EmbedDataNode(BaseBuilder* cb) noexcept : BaseNode(cb, NodeType::kEmbedData, NodeFlags::kIsData), _itemCount(0), _repeatCount(0) { @@ -1098,31 +1206,31 @@ public: //! \{ //! Returns data type as \ref TypeId. - inline TypeId typeId() const noexcept { return _embed._typeId; } + ASMJIT_INLINE_NODEBUG TypeId typeId() const noexcept { return _embed._typeId; } //! Returns the size of a single data element. - inline uint32_t typeSize() const noexcept { return _embed._typeSize; } + ASMJIT_INLINE_NODEBUG uint32_t typeSize() const noexcept { return _embed._typeSize; } //! Returns a pointer to the data casted to `uint8_t`. - inline uint8_t* data() const noexcept { + ASMJIT_INLINE_NODEBUG uint8_t* data() const noexcept { return dataSize() <= kInlineBufferSize ? const_cast<uint8_t*>(_inlineData) : _externalData; } //! Returns a pointer to the data casted to `T`. template<typename T> - inline T* dataAs() const noexcept { return reinterpret_cast<T*>(data()); } + ASMJIT_INLINE_NODEBUG T* dataAs() const noexcept { return reinterpret_cast<T*>(data()); } //! Returns the number of (typed) items in the array. - inline size_t itemCount() const noexcept { return _itemCount; } + ASMJIT_INLINE_NODEBUG size_t itemCount() const noexcept { return _itemCount; } //! Returns how many times the data is repeated (default 1). //! //! Repeated data is useful when defining constants for SIMD, for example. - inline size_t repeatCount() const noexcept { return _repeatCount; } + ASMJIT_INLINE_NODEBUG size_t repeatCount() const noexcept { return _repeatCount; } //! Returns the size of the data, not considering the number of times it repeats. //! //! \note The returned value is the same as `typeSize() * itemCount()`. - inline size_t dataSize() const noexcept { return typeSize() * _itemCount; } + ASMJIT_INLINE_NODEBUG size_t dataSize() const noexcept { return typeSize() * _itemCount; } //! \} }; @@ -1144,7 +1252,7 @@ public: //! \{ //! Creates a new `EmbedLabelNode` instance. - inline EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept + ASMJIT_INLINE_NODEBUG EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept : BaseNode(cb, NodeType::kEmbedLabel, NodeFlags::kIsData), _labelId(labelId), _dataSize(dataSize) {} @@ -1155,19 +1263,19 @@ public: //! \{ //! Returns the label to embed as \ref Label operand. - inline Label label() const noexcept { return Label(_labelId); } + ASMJIT_INLINE_NODEBUG Label label() const noexcept { return Label(_labelId); } //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } + ASMJIT_INLINE_NODEBUG uint32_t labelId() const noexcept { return _labelId; } //! Sets the label id from `label` operand. - inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); } + ASMJIT_INLINE_NODEBUG void setLabel(const Label& label) noexcept { setLabelId(label.id()); } //! Sets the label id (use with caution, improper use can break a lot of things). - inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; } + ASMJIT_INLINE_NODEBUG void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; } //! Returns the data size. - inline uint32_t dataSize() const noexcept { return _dataSize; } + ASMJIT_INLINE_NODEBUG uint32_t dataSize() const noexcept { return _dataSize; } //! Sets the data size. - inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } + ASMJIT_INLINE_NODEBUG void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } //! \} }; @@ -1190,7 +1298,7 @@ public: //! \{ //! Creates a new `EmbedLabelDeltaNode` instance. - inline EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept + ASMJIT_INLINE_NODEBUG EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept : BaseNode(cb, NodeType::kEmbedLabelDelta, NodeFlags::kIsData), _labelId(labelId), _baseLabelId(baseLabelId), @@ -1202,29 +1310,29 @@ public: //! \{ //! Returns the label as `Label` operand. - inline Label label() const noexcept { return Label(_labelId); } + ASMJIT_INLINE_NODEBUG Label label() const noexcept { return Label(_labelId); } //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } + ASMJIT_INLINE_NODEBUG uint32_t labelId() const noexcept { return _labelId; } //! Sets the label id from `label` operand. - inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); } + ASMJIT_INLINE_NODEBUG void setLabel(const Label& label) noexcept { setLabelId(label.id()); } //! Sets the label id. - inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; } + ASMJIT_INLINE_NODEBUG void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; } //! Returns the base label as `Label` operand. - inline Label baseLabel() const noexcept { return Label(_baseLabelId); } + ASMJIT_INLINE_NODEBUG Label baseLabel() const noexcept { return Label(_baseLabelId); } //! Returns the id of the base label. - inline uint32_t baseLabelId() const noexcept { return _baseLabelId; } + ASMJIT_INLINE_NODEBUG uint32_t baseLabelId() const noexcept { return _baseLabelId; } //! Sets the base label id from `label` operand. - inline void setBaseLabel(const Label& baseLabel) noexcept { setBaseLabelId(baseLabel.id()); } + ASMJIT_INLINE_NODEBUG void setBaseLabel(const Label& baseLabel) noexcept { setBaseLabelId(baseLabel.id()); } //! Sets the base label id. - inline void setBaseLabelId(uint32_t baseLabelId) noexcept { _baseLabelId = baseLabelId; } + ASMJIT_INLINE_NODEBUG void setBaseLabelId(uint32_t baseLabelId) noexcept { _baseLabelId = baseLabelId; } //! Returns the size of the embedded label address. - inline uint32_t dataSize() const noexcept { return _dataSize; } + ASMJIT_INLINE_NODEBUG uint32_t dataSize() const noexcept { return _dataSize; } //! Sets the size of the embedded label address. - inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } + ASMJIT_INLINE_NODEBUG void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } //! \} }; @@ -1245,7 +1353,7 @@ public: //! \{ //! Creates a new `ConstPoolNode` instance. - inline ConstPoolNode(BaseBuilder* cb, uint32_t id = 0) noexcept + ASMJIT_INLINE_NODEBUG ConstPoolNode(BaseBuilder* cb, uint32_t id = 0) noexcept : LabelNode(cb, id), _constPool(&cb->_codeZone) { @@ -1260,16 +1368,16 @@ public: //! \{ //! Tests whether the constant-pool is empty. - inline bool empty() const noexcept { return _constPool.empty(); } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _constPool.empty(); } //! Returns the size of the constant-pool in bytes. - inline size_t size() const noexcept { return _constPool.size(); } + ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _constPool.size(); } //! Returns minimum alignment. - inline size_t alignment() const noexcept { return _constPool.alignment(); } + ASMJIT_INLINE_NODEBUG size_t alignment() const noexcept { return _constPool.alignment(); } //! Returns the wrapped `ConstPool` instance. - inline ConstPool& constPool() noexcept { return _constPool; } + ASMJIT_INLINE_NODEBUG ConstPool& constPool() noexcept { return _constPool; } //! Returns the wrapped `ConstPool` instance (const). - inline const ConstPool& constPool() const noexcept { return _constPool; } + ASMJIT_INLINE_NODEBUG const ConstPool& constPool() const noexcept { return _constPool; } //! \} @@ -1277,7 +1385,7 @@ public: //! \{ //! See `ConstPool::add()`. - inline Error add(const void* data, size_t size, size_t& dstOffset) noexcept { + ASMJIT_INLINE_NODEBUG Error add(const void* data, size_t size, size_t& dstOffset) noexcept { return _constPool.add(data, size, dstOffset); } @@ -1293,7 +1401,7 @@ public: //! \{ //! Creates a new `CommentNode` instance. - inline CommentNode(BaseBuilder* cb, const char* comment) noexcept + ASMJIT_INLINE_NODEBUG CommentNode(BaseBuilder* cb, const char* comment) noexcept : BaseNode(cb, NodeType::kComment, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect | NodeFlags::kIsRemovable) { _inlineComment = comment; } @@ -1313,7 +1421,7 @@ public: //! \{ //! Creates a new `SentinelNode` instance. - inline SentinelNode(BaseBuilder* cb, SentinelType sentinelType = SentinelType::kUnknown) noexcept + ASMJIT_INLINE_NODEBUG SentinelNode(BaseBuilder* cb, SentinelType sentinelType = SentinelType::kUnknown) noexcept : BaseNode(cb, NodeType::kSentinel, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect) { _sentinel._sentinelType = sentinelType; @@ -1325,12 +1433,12 @@ public: //! \{ //! Returns the type of the sentinel. - inline SentinelType sentinelType() const noexcept { + ASMJIT_INLINE_NODEBUG SentinelType sentinelType() const noexcept { return _sentinel._sentinelType; } //! Sets the type of the sentinel. - inline void setSentinelType(SentinelType type) noexcept { + ASMJIT_INLINE_NODEBUG void setSentinelType(SentinelType type) noexcept { _sentinel._sentinelType = type; } @@ -1365,9 +1473,9 @@ public: //! \{ //! Returns \ref BaseBuilder associated with the pass. - inline const BaseBuilder* cb() const noexcept { return _cb; } + ASMJIT_INLINE_NODEBUG const BaseBuilder* cb() const noexcept { return _cb; } //! Returns the name of the pass. - inline const char* name() const noexcept { return _name; } + ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _name; } //! \} @@ -1378,7 +1486,7 @@ public: //! //! This is the only function that is called by the `BaseBuilder` to process the code. It passes `zone`, //! which will be reset after the `run()` finishes. - virtual Error run(Zone* zone, Logger* logger) = 0; + ASMJIT_API virtual Error run(Zone* zone, Logger* logger); //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/builder_p.h b/3rdparty/asmjit/src/asmjit/core/builder_p.h new file mode 100644 index 00000000000..98790fdf95f --- /dev/null +++ b/3rdparty/asmjit/src/asmjit/core/builder_p.h @@ -0,0 +1,37 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_CORE_BUILDER_P_H_INCLUDED +#define ASMJIT_CORE_BUILDER_P_H_INCLUDED + +#include "../core/api-config.h" +#ifndef ASMJIT_NO_BUILDER + +#include "../core/builder.h" + +ASMJIT_BEGIN_NAMESPACE + +//! \cond INTERNAL +//! \addtogroup asmjit_builder +//! \{ + +static inline void BaseBuilder_assignInlineComment(BaseBuilder* self, BaseNode* node, const char* comment) noexcept { + if (comment) + node->setInlineComment(static_cast<char*>(self->_dataZone.dup(comment, strlen(comment), true))); +} + +static inline void BaseBuilder_assignInstState(BaseBuilder* self, InstNode* node, const BaseEmitter::State& state) noexcept { + node->setOptions(state.options); + node->setExtraReg(state.extraReg); + BaseBuilder_assignInlineComment(self, node, state.comment); +} + +//! \} +//! \endcond + +ASMJIT_END_NAMESPACE + +#endif // !ASMJIT_NO_BUILDER +#endif // ASMJIT_CORE_BUILDER_P_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/core/codebuffer.h b/3rdparty/asmjit/src/asmjit/core/codebuffer.h index 4946e7a06a1..d4b7cebbcef 100644 --- a/3rdparty/asmjit/src/asmjit/core/codebuffer.h +++ b/3rdparty/asmjit/src/asmjit/core/codebuffer.h @@ -44,7 +44,7 @@ struct CodeBuffer { //! \name Overloaded Operators //! \{ - //! Returns a referebce to the byte at the given `index`. + //! Returns a reference to the byte at the given `index`. inline uint8_t& operator[](size_t index) noexcept { ASMJIT_ASSERT(index < _size); return _data[index]; @@ -61,46 +61,46 @@ struct CodeBuffer { //! \{ //! Returns code buffer flags. - inline CodeBufferFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG CodeBufferFlags flags() const noexcept { return _flags; } //! Tests whether the code buffer has the given `flag` set. - inline bool hasFlag(CodeBufferFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(CodeBufferFlags flag) const noexcept { return Support::test(_flags, flag); } //! Tests whether this code buffer has a fixed size. //! //! Fixed size means that the code buffer is fixed and cannot grow. - inline bool isFixed() const noexcept { return hasFlag(CodeBufferFlags::kIsFixed); } + ASMJIT_INLINE_NODEBUG bool isFixed() const noexcept { return hasFlag(CodeBufferFlags::kIsFixed); } //! Tests whether the data in this code buffer is external. //! //! External data can only be provided by users, it's never used by AsmJit. - inline bool isExternal() const noexcept { return hasFlag(CodeBufferFlags::kIsExternal); } + ASMJIT_INLINE_NODEBUG bool isExternal() const noexcept { return hasFlag(CodeBufferFlags::kIsExternal); } //! Tests whether the data in this code buffer is allocated (non-null). - inline bool isAllocated() const noexcept { return _data != nullptr; } + ASMJIT_INLINE_NODEBUG bool isAllocated() const noexcept { return _data != nullptr; } //! Tests whether the code buffer is empty. - inline bool empty() const noexcept { return !_size; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return !_size; } //! Returns the size of the data. - inline size_t size() const noexcept { return _size; } + ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; } //! Returns the capacity of the data. - inline size_t capacity() const noexcept { return _capacity; } + ASMJIT_INLINE_NODEBUG size_t capacity() const noexcept { return _capacity; } //! Returns the pointer to the data the buffer references. - inline uint8_t* data() noexcept { return _data; } + ASMJIT_INLINE_NODEBUG uint8_t* data() noexcept { return _data; } //! \overload - inline const uint8_t* data() const noexcept { return _data; } + ASMJIT_INLINE_NODEBUG const uint8_t* data() const noexcept { return _data; } //! \} //! \name Iterators //! \{ - inline uint8_t* begin() noexcept { return _data; } - inline const uint8_t* begin() const noexcept { return _data; } + ASMJIT_INLINE_NODEBUG uint8_t* begin() noexcept { return _data; } + ASMJIT_INLINE_NODEBUG const uint8_t* begin() const noexcept { return _data; } - inline uint8_t* end() noexcept { return _data + _size; } - inline const uint8_t* end() const noexcept { return _data + _size; } + ASMJIT_INLINE_NODEBUG uint8_t* end() noexcept { return _data + _size; } + ASMJIT_INLINE_NODEBUG const uint8_t* end() const noexcept { return _data + _size; } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/codeholder.cpp b/3rdparty/asmjit/src/asmjit/core/codeholder.cpp index cf763cfff12..63b15a3ada3 100644 --- a/3rdparty/asmjit/src/asmjit/core/codeholder.cpp +++ b/3rdparty/asmjit/src/asmjit/core/codeholder.cpp @@ -74,6 +74,7 @@ static void CodeHolder_resetInternal(CodeHolder* self, ResetPolicy resetPolicy) // Reset everything into its construction state. self->_environment.reset(); + self->_cpuFeatures.reset(); self->_baseAddress = Globals::kNoBaseAddress; self->_logger = nullptr; self->_errorHandler = nullptr; @@ -118,6 +119,7 @@ static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept { CodeHolder::CodeHolder(const Support::Temporary* temporary) noexcept : _environment(), + _cpuFeatures{}, _baseAddress(Globals::kNoBaseAddress), _logger(nullptr), _errorHandler(nullptr), @@ -130,8 +132,8 @@ CodeHolder::~CodeHolder() noexcept { CodeHolder_resetInternal(this, ResetPolicy::kHard); } -// CodeHolder - Init & Reset -// ========================= +// CodeHolder - Initialization & Reset +// =================================== inline void CodeHolder_setSectionDefaultName( Section* section, @@ -143,6 +145,10 @@ inline void CodeHolder_setSectionDefaultName( } Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noexcept { + return init(environment, CpuFeatures{}, baseAddress); +} + +Error CodeHolder::init(const Environment& environment, const CpuFeatures& cpuFeatures, uint64_t baseAddress) noexcept { // Cannot reinitialize if it's locked or there is one or more emitter attached. if (isInitialized()) return DebugUtils::errored(kErrorAlreadyInitialized); @@ -172,6 +178,7 @@ Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noe } else { _environment = environment; + _cpuFeatures = cpuFeatures; _baseAddress = baseAddress; return kErrorOk; } @@ -901,7 +908,7 @@ size_t CodeHolder::codeSize() const noexcept { } } - if ((sizeof(uint64_t) > sizeof(size_t) && offset > SIZE_MAX) || of) + if ((sizeof(uint64_t) > sizeof(size_t) && offset > uint64_t(SIZE_MAX)) || of) return SIZE_MAX; return size_t(offset); @@ -1119,30 +1126,30 @@ UNIT(code_holder) { env.init(Arch::kX86); code.init(env); - EXPECT(code.arch() == Arch::kX86); + EXPECT_EQ(code.arch(), Arch::kX86); INFO("Verifying named labels"); LabelEntry* le; - EXPECT(code.newNamedLabelEntry(&le, "NamedLabel", SIZE_MAX, LabelType::kGlobal) == kErrorOk); - EXPECT(strcmp(le->name(), "NamedLabel") == 0); - EXPECT(code.labelIdByName("NamedLabel") == le->id()); + EXPECT_EQ(code.newNamedLabelEntry(&le, "NamedLabel", SIZE_MAX, LabelType::kGlobal), kErrorOk); + EXPECT_EQ(strcmp(le->name(), "NamedLabel"), 0); + EXPECT_EQ(code.labelIdByName("NamedLabel"), le->id()); INFO("Verifying section ordering"); Section* section1; - EXPECT(code.newSection(§ion1, "high-priority", SIZE_MAX, SectionFlags::kNone, 1, -1) == kErrorOk); - EXPECT(code.sections()[1] == section1); - EXPECT(code.sectionsByOrder()[0] == section1); + EXPECT_EQ(code.newSection(§ion1, "high-priority", SIZE_MAX, SectionFlags::kNone, 1, -1), kErrorOk); + EXPECT_EQ(code.sections()[1], section1); + EXPECT_EQ(code.sectionsByOrder()[0], section1); Section* section0; - EXPECT(code.newSection(§ion0, "higher-priority", SIZE_MAX, SectionFlags::kNone, 1, -2) == kErrorOk); - EXPECT(code.sections()[2] == section0); - EXPECT(code.sectionsByOrder()[0] == section0); - EXPECT(code.sectionsByOrder()[1] == section1); + EXPECT_EQ(code.newSection(§ion0, "higher-priority", SIZE_MAX, SectionFlags::kNone, 1, -2), kErrorOk); + EXPECT_EQ(code.sections()[2], section0); + EXPECT_EQ(code.sectionsByOrder()[0], section0); + EXPECT_EQ(code.sectionsByOrder()[1], section1); Section* section3; - EXPECT(code.newSection(§ion3, "low-priority", SIZE_MAX, SectionFlags::kNone, 1, 2) == kErrorOk); - EXPECT(code.sections()[3] == section3); - EXPECT(code.sectionsByOrder()[3] == section3); + EXPECT_EQ(code.newSection(§ion3, "low-priority", SIZE_MAX, SectionFlags::kNone, 1, 2), kErrorOk); + EXPECT_EQ(code.sections()[3], section3); + EXPECT_EQ(code.sectionsByOrder()[3], section3); } #endif diff --git a/3rdparty/asmjit/src/asmjit/core/codeholder.h b/3rdparty/asmjit/src/asmjit/core/codeholder.h index 6ed2ddf9426..3f2d1d70745 100644 --- a/3rdparty/asmjit/src/asmjit/core/codeholder.h +++ b/3rdparty/asmjit/src/asmjit/core/codeholder.h @@ -45,7 +45,7 @@ enum class ExpressionOpType : uint8_t { kSra = 5 }; -//! Value tyoe that can be used within an \ref Expression. +//! Value type that can be used within an \ref Expression. enum class ExpressionValueType : uint8_t { //! No value or invalid. kNone = 0, @@ -89,22 +89,22 @@ struct Expression { //! Resets the whole expression. //! //! Changes both values to \ref ExpressionValueType::kNone. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = Expression{}; } //! Sets the value type at `index` to \ref ExpressionValueType::kConstant and its content to `constant`. - inline void setValueAsConstant(size_t index, uint64_t constant) noexcept { + ASMJIT_INLINE_NODEBUG void setValueAsConstant(size_t index, uint64_t constant) noexcept { valueType[index] = ExpressionValueType::kConstant; value[index].constant = constant; } //! Sets the value type at `index` to \ref ExpressionValueType::kLabel and its content to `labelEntry`. - inline void setValueAsLabel(size_t index, LabelEntry* labelEntry) noexcept { + ASMJIT_INLINE_NODEBUG void setValueAsLabel(size_t index, LabelEntry* labelEntry) noexcept { valueType[index] = ExpressionValueType::kLabel; value[index].label = labelEntry; } //! Sets the value type at `index` to \ref ExpressionValueType::kExpression and its content to `expression`. - inline void setValueAsExpression(size_t index, Expression* expression) noexcept { + ASMJIT_INLINE_NODEBUG void setValueAsExpression(size_t index, Expression* expression) noexcept { valueType[index] = ExpressionValueType::kExpression; value[index].expression = expression; } @@ -175,36 +175,36 @@ public: //! \{ //! Returns the section id. - inline uint32_t id() const noexcept { return _id; } + ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _id; } //! Returns the section name, as a null terminated string. - inline const char* name() const noexcept { return _name.str; } + ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _name.str; } //! Returns the section data. - inline uint8_t* data() noexcept { return _buffer.data(); } + ASMJIT_INLINE_NODEBUG uint8_t* data() noexcept { return _buffer.data(); } //! \overload - inline const uint8_t* data() const noexcept { return _buffer.data(); } + ASMJIT_INLINE_NODEBUG const uint8_t* data() const noexcept { return _buffer.data(); } //! Returns the section flags. - inline SectionFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG SectionFlags flags() const noexcept { return _flags; } //! Tests whether the section has the given `flag`. - inline bool hasFlag(SectionFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(SectionFlags flag) const noexcept { return Support::test(_flags, flag); } //! Adds `flags` to the section flags. - inline void addFlags(SectionFlags flags) noexcept { _flags |= flags; } + ASMJIT_INLINE_NODEBUG void addFlags(SectionFlags flags) noexcept { _flags |= flags; } //! Removes `flags` from the section flags. - inline void clearFlags(SectionFlags flags) noexcept { _flags &= ~flags; } + ASMJIT_INLINE_NODEBUG void clearFlags(SectionFlags flags) noexcept { _flags &= ~flags; } //! Returns the minimum section alignment - inline uint32_t alignment() const noexcept { return _alignment; } + ASMJIT_INLINE_NODEBUG uint32_t alignment() const noexcept { return _alignment; } //! Sets the minimum section alignment - inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; } + ASMJIT_INLINE_NODEBUG void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; } //! Returns the section order, which has a higher priority than section id. - inline int32_t order() const noexcept { return _order; } + ASMJIT_INLINE_NODEBUG int32_t order() const noexcept { return _order; } //! Returns the section offset, relative to base. - inline uint64_t offset() const noexcept { return _offset; } + ASMJIT_INLINE_NODEBUG uint64_t offset() const noexcept { return _offset; } //! Set the section offset. - inline void setOffset(uint64_t offset) noexcept { _offset = offset; } + ASMJIT_INLINE_NODEBUG void setOffset(uint64_t offset) noexcept { _offset = offset; } //! Returns the virtual size of the section. //! @@ -212,19 +212,19 @@ public: //! size returned by `bufferSize()` as the buffer stores real data emitted by assemblers or appended by users. //! //! Use `realSize()` to get the real and final size of this section. - inline uint64_t virtualSize() const noexcept { return _virtualSize; } + ASMJIT_INLINE_NODEBUG uint64_t virtualSize() const noexcept { return _virtualSize; } //! Sets the virtual size of the section. - inline void setVirtualSize(uint64_t virtualSize) noexcept { _virtualSize = virtualSize; } + ASMJIT_INLINE_NODEBUG void setVirtualSize(uint64_t virtualSize) noexcept { _virtualSize = virtualSize; } //! Returns the buffer size of the section. - inline size_t bufferSize() const noexcept { return _buffer.size(); } + ASMJIT_INLINE_NODEBUG size_t bufferSize() const noexcept { return _buffer.size(); } //! Returns the real size of the section calculated from virtual and buffer sizes. - inline uint64_t realSize() const noexcept { return Support::max<uint64_t>(virtualSize(), bufferSize()); } + ASMJIT_INLINE_NODEBUG uint64_t realSize() const noexcept { return Support::max<uint64_t>(virtualSize(), bufferSize()); } //! Returns the `CodeBuffer` used by this section. - inline CodeBuffer& buffer() noexcept { return _buffer; } + ASMJIT_INLINE_NODEBUG CodeBuffer& buffer() noexcept { return _buffer; } //! Returns the `CodeBuffer` used by this section (const). - inline const CodeBuffer& buffer() const noexcept { return _buffer; } + ASMJIT_INLINE_NODEBUG const CodeBuffer& buffer() const noexcept { return _buffer; } //! \} }; @@ -247,7 +247,7 @@ public: //! \name Construction & Destruction //! \{ - inline explicit AddressTableEntry(uint64_t address) noexcept + ASMJIT_INLINE_NODEBUG explicit AddressTableEntry(uint64_t address) noexcept : _address(address), _slot(0xFFFFFFFFu) {} @@ -256,22 +256,25 @@ public: //! \name Accessors //! \{ - inline uint64_t address() const noexcept { return _address; } - inline uint32_t slot() const noexcept { return _slot; } + ASMJIT_INLINE_NODEBUG uint64_t address() const noexcept { return _address; } + ASMJIT_INLINE_NODEBUG uint32_t slot() const noexcept { return _slot; } - inline bool hasAssignedSlot() const noexcept { return _slot != 0xFFFFFFFFu; } + ASMJIT_INLINE_NODEBUG bool hasAssignedSlot() const noexcept { return _slot != 0xFFFFFFFFu; } - inline bool operator<(const AddressTableEntry& other) const noexcept { return _address < other._address; } - inline bool operator>(const AddressTableEntry& other) const noexcept { return _address > other._address; } + ASMJIT_INLINE_NODEBUG bool operator<(const AddressTableEntry& other) const noexcept { return _address < other._address; } + ASMJIT_INLINE_NODEBUG bool operator>(const AddressTableEntry& other) const noexcept { return _address > other._address; } - inline bool operator<(uint64_t queryAddress) const noexcept { return _address < queryAddress; } - inline bool operator>(uint64_t queryAddress) const noexcept { return _address > queryAddress; } + ASMJIT_INLINE_NODEBUG bool operator<(uint64_t queryAddress) const noexcept { return _address < queryAddress; } + ASMJIT_INLINE_NODEBUG bool operator>(uint64_t queryAddress) const noexcept { return _address > queryAddress; } //! \} }; //! Offset format type, used by \ref OffsetFormat. enum class OffsetType : uint8_t { + // Common Offset Formats + // --------------------- + //! A value having `_immBitCount` bits and shifted by `_immBitShift`. //! //! This offset type is sufficient for many targets that store offset as a continuous set bits within an @@ -284,14 +287,82 @@ enum class OffsetType : uint8_t { // AArch64 Specific Offset Formats // ------------------------------- - //! AARCH64 ADR format of `[.|immlo:2|.....|immhi:19|.....]`. + //! AArch64 ADR format of `[.|immlo:2|.....|immhi:19|.....]`. kAArch64_ADR, - //! AARCH64 ADRP format of `[.|immlo:2|.....|immhi:19|.....]` (4kB pages). + //! AArch64 ADRP format of `[.|immlo:2|.....|immhi:19|.....]` (4kB pages). kAArch64_ADRP, + // AArch32 Specific Offset Formats (T16 & T32) + // ------------------------------------------- + + //! AArch32 THUMBv2 immediate encoding of 'ADR' instruction (12-bit payload and sign bit): + //! + //! `|.....|imm:1|..N.N|......|imm:3|....|imm:8|` + //! + //! Where `N` is one if the offset is negative. The immediate is encoded as absolute value of the offset if negative. + kThumb32_ADR, + + //! AArch32 THUMBv2 immediate encoding of 'BLX' instruction (23-bit immediate payload, multiplied by 4): + //! + //! `|.....|imm[22]|imm[19:10]|..|ja|1|jb|imm[9:0]|0` + //! + //! Where: + //! + //! - `ja` is calculated as imm[22] ^ imm[21] ^ 1. + //! - `jb` is calculated as imm[22] ^ imm[20] ^ 1. + kThumb32_BLX, + + //! AArch32 THUMBv2 immediate encoding of 'B' instruction without `<cond>` (24-bit immediate payload, multiplied by 2): + //! + //! `|.....|imm[23]|imm[20:11]|..|ja|1|jb|imm[10:0]` + //! + //! Where: + //! + //! - `ja` is calculated as imm[23] ^ imm[22] ^ 1. + //! - `jb` is calculated as imm[23] ^ imm[21] ^ 1. + kThumb32_B, + + //! AArch32 THUMBv2 immediate encoding of 'B' instruction with `<cond>` (20-bit immediate payload, multiplied by 2). + //! + //! `|.....|imm[19]|....|imm[16:11]|..|ja|1|jb|imm[10:0]` + //! + //! Where: + //! + //! - `ja` is calculated as imm[19] ^ imm[18] ^ 1. + //! - `jb` is calculated as imm[19] ^ imm[17] ^ 1. + kThumb32_BCond, + + // AArch32 Specific Offset Formats (A32) + // ------------------------------------- + + //! AArch32 ADR instruction, which uses a standard 12-bit immediate encoding that is used by other ARM instructions. + kAArch32_ADR, + + //! AArch32 signed offset that is similar to `kSignedOffset`, however it uses absolute value of the offset and its + //! sign is encoded in 23rd bit of the opcode. + //! + //! `|........|U.......|........|........|` + //! + kAArch32_U23_SignedOffset, + + //! AArch32 offset format that encodes 8-bit offset as: + //! + //! `|........|U.......|....|imm[7:4]|....|imm[3:0]|` + //! + //! in a 32-bit word, where U is a sign of the displacement and the displacement itself is encoded as its absolute + //! value. + kAArch32_U23_0To3At0_4To7At8, + + //! AArch32 offset format that encodes a signed 25-bit offset as: + //! + //! `|.......|imm[0]|imm[24:1]|` + //! + //! in a 32-bit word. + kAArch32_1To24At0_0At24, + //! Maximum value of `OffsetFormatType`. - kMaxValue = kAArch64_ADRP + kMaxValue = kAArch32_1To24At0_0At24 }; //! Provides information about formatting offsets, absolute addresses, or their parts. Offset format is used by both @@ -348,26 +419,35 @@ struct OffsetFormat { //! \{ //! Returns the type of the offset. - inline OffsetType type() const noexcept { return _type; } + ASMJIT_INLINE_NODEBUG OffsetType type() const noexcept { return _type; } - //! Returns flags. - inline uint32_t flags() const noexcept { return _flags; } + //! Returns whether the offset is encoded as an absolute value of the offset with additional field(s) that represent + //! the sign (AArch32 U/N fields in the opcode). + //! + //! If true, the offset itself is always positive and a separate U/N field is used to indicate the sign of the offset + //! (usually `U==1` means ADD, but sometimes `N==1` means negative offset, which implies SUB). + ASMJIT_INLINE_NODEBUG bool hasSignBit() const noexcept { + return _type == OffsetType::kThumb32_ADR || + _type == OffsetType::kAArch32_ADR || + _type == OffsetType::kAArch32_U23_SignedOffset || + _type == OffsetType::kAArch32_U23_0To3At0_4To7At8; + } + //! Returns flags. + ASMJIT_INLINE_NODEBUG uint32_t flags() const noexcept { return _flags; } //! Returns the size of the region/instruction where the offset is encoded. - inline uint32_t regionSize() const noexcept { return _regionSize; } - + ASMJIT_INLINE_NODEBUG uint32_t regionSize() const noexcept { return _regionSize; } //! Returns the offset of the word relative to the start of the region where the offset is. - inline uint32_t valueOffset() const noexcept { return _valueOffset; } - + ASMJIT_INLINE_NODEBUG uint32_t valueOffset() const noexcept { return _valueOffset; } //! Returns the size of the data-type (word) that contains the offset, in bytes. - inline uint32_t valueSize() const noexcept { return _valueSize; } + ASMJIT_INLINE_NODEBUG uint32_t valueSize() const noexcept { return _valueSize; } //! Returns the count of bits of the offset value in the data it's stored in. - inline uint32_t immBitCount() const noexcept { return _immBitCount; } + ASMJIT_INLINE_NODEBUG uint32_t immBitCount() const noexcept { return _immBitCount; } //! Returns the bit-shift of the offset value in the data it's stored in. - inline uint32_t immBitShift() const noexcept { return _immBitShift; } + ASMJIT_INLINE_NODEBUG uint32_t immBitShift() const noexcept { return _immBitShift; } //! Returns the number of least significant bits of the offset value, that must be zero and that are not part of //! the encoded data. - inline uint32_t immDiscardLsb() const noexcept { return _immDiscardLsb; } + ASMJIT_INLINE_NODEBUG uint32_t immDiscardLsb() const noexcept { return _immDiscardLsb; } //! Resets this offset format to a simple data value of `dataSize` bytes. //! @@ -456,18 +536,18 @@ struct RelocEntry { //! \name Accessors //! \{ - inline uint32_t id() const noexcept { return _id; } + ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _id; } - inline RelocType relocType() const noexcept { return _relocType; } - inline const OffsetFormat& format() const noexcept { return _format; } + ASMJIT_INLINE_NODEBUG RelocType relocType() const noexcept { return _relocType; } + ASMJIT_INLINE_NODEBUG const OffsetFormat& format() const noexcept { return _format; } - inline uint32_t sourceSectionId() const noexcept { return _sourceSectionId; } - inline uint32_t targetSectionId() const noexcept { return _targetSectionId; } + ASMJIT_INLINE_NODEBUG uint32_t sourceSectionId() const noexcept { return _sourceSectionId; } + ASMJIT_INLINE_NODEBUG uint32_t targetSectionId() const noexcept { return _targetSectionId; } - inline uint64_t sourceOffset() const noexcept { return _sourceOffset; } - inline uint64_t payload() const noexcept { return _payload; } + ASMJIT_INLINE_NODEBUG uint64_t sourceOffset() const noexcept { return _sourceOffset; } + ASMJIT_INLINE_NODEBUG uint64_t payload() const noexcept { return _payload; } - Expression* payloadAsExpression() const noexcept { + ASMJIT_INLINE_NODEBUG Expression* payloadAsExpression() const noexcept { return reinterpret_cast<Expression*>(uintptr_t(_payload)); } @@ -562,53 +642,53 @@ public: // compiler targeting 64-bit CPU will add to align the structure to 64-bits. //! Returns label id. - inline uint32_t id() const noexcept { return _customData; } + ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _customData; } //! Sets label id (internal, used only by `CodeHolder`). - inline void _setId(uint32_t id) noexcept { _customData = id; } + ASMJIT_INLINE_NODEBUG void _setId(uint32_t id) noexcept { _customData = id; } //! Returns label type. - inline LabelType type() const noexcept { return _type; } + ASMJIT_INLINE_NODEBUG LabelType type() const noexcept { return _type; } //! Tests whether the label has a parent label. - inline bool hasParent() const noexcept { return _parentId != Globals::kInvalidId; } + ASMJIT_INLINE_NODEBUG bool hasParent() const noexcept { return _parentId != Globals::kInvalidId; } //! Returns label's parent id. - inline uint32_t parentId() const noexcept { return _parentId; } + ASMJIT_INLINE_NODEBUG uint32_t parentId() const noexcept { return _parentId; } //! Returns the section where the label was bound. //! //! If the label was not yet bound the return value is `nullptr`. - inline Section* section() const noexcept { return _section; } + ASMJIT_INLINE_NODEBUG Section* section() const noexcept { return _section; } //! Tests whether the label has name. - inline bool hasName() const noexcept { return !_name.empty(); } + ASMJIT_INLINE_NODEBUG bool hasName() const noexcept { return !_name.empty(); } //! Returns the label's name. //! //! \note Local labels will return their local name without their parent part, for example ".L1". - inline const char* name() const noexcept { return _name.data(); } + ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _name.data(); } //! Returns size of label's name. //! //! \note Label name is always null terminated, so you can use `strlen()` to get it, however, it's also cached in //! `LabelEntry` itself, so if you want to know the size the fastest way is to call `LabelEntry::nameSize()`. - inline uint32_t nameSize() const noexcept { return _name.size(); } + ASMJIT_INLINE_NODEBUG uint32_t nameSize() const noexcept { return _name.size(); } //! Returns links associated with this label. - inline LabelLink* links() const noexcept { return _links; } + ASMJIT_INLINE_NODEBUG LabelLink* links() const noexcept { return _links; } //! Tests whether the label is bound. - inline bool isBound() const noexcept { return _section != nullptr; } + ASMJIT_INLINE_NODEBUG bool isBound() const noexcept { return _section != nullptr; } //! Tests whether the label is bound to a the given `sectionId`. - inline bool isBoundTo(Section* section) const noexcept { return _section == section; } + ASMJIT_INLINE_NODEBUG bool isBoundTo(Section* section) const noexcept { return _section == section; } //! Returns the label offset (only useful if the label is bound). - inline uint64_t offset() const noexcept { return _offset; } + ASMJIT_INLINE_NODEBUG uint64_t offset() const noexcept { return _offset; } //! Returns the hash-value of label's name and its parent label (if any). //! //! Label hash is calculated as `HASH(Name) ^ ParentId`. The hash function is implemented in `Support::hashString()` //! and `Support::hashRound()`. - inline uint32_t hashCode() const noexcept { return _hashCode; } + ASMJIT_INLINE_NODEBUG uint32_t hashCode() const noexcept { return _hashCode; } //! \} }; @@ -640,6 +720,8 @@ public: //! Environment information. Environment _environment; + //! CPU features of the target architecture. + CpuFeatures _cpuFeatures; //! Base address or \ref Globals::kNoBaseAddress. uint64_t _baseAddress; @@ -685,7 +767,7 @@ public: ASMJIT_API explicit CodeHolder(const Support::Temporary* temporary = nullptr) noexcept; //! \overload - inline explicit CodeHolder(const Support::Temporary& temporary) noexcept + ASMJIT_INLINE_NODEBUG explicit CodeHolder(const Support::Temporary& temporary) noexcept : CodeHolder(&temporary) {} //! Destroys the CodeHolder and frees all resources it has allocated. @@ -694,10 +776,12 @@ public: //! Tests whether the `CodeHolder` has been initialized. //! //! Emitters can be only attached to initialized `CodeHolder` instances. - inline bool isInitialized() const noexcept { return _environment.isInitialized(); } + ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _environment.isInitialized(); } //! Initializes CodeHolder to hold code described by the given `environment` and `baseAddress`. ASMJIT_API Error init(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept; + //! Initializes CodeHolder to hold code described by the given `environment`, `cpuFeatures`, and `baseAddress`. + ASMJIT_API Error init(const Environment& environment, const CpuFeatures& cpuFeatures, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept; //! Detaches all code-generators attached and resets the `CodeHolder`. ASMJIT_API void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept; @@ -721,7 +805,7 @@ public: //! \note This should be only used for AsmJit's purposes. Code holder uses arena allocator to allocate everything, //! so anything allocated through this allocator will be invalidated by \ref CodeHolder::reset() or by CodeHolder's //! destructor. - inline ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); } + ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); } //! \} @@ -729,17 +813,20 @@ public: //! \{ //! Returns the target environment information. - inline const Environment& environment() const noexcept { return _environment; } + ASMJIT_INLINE_NODEBUG const Environment& environment() const noexcept { return _environment; } //! Returns the target architecture. - inline Arch arch() const noexcept { return environment().arch(); } + ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return environment().arch(); } //! Returns the target sub-architecture. - inline SubArch subArch() const noexcept { return environment().subArch(); } + ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return environment().subArch(); } + + //! Returns the minimum CPU features of the target architecture. + ASMJIT_INLINE_NODEBUG const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; } //! Tests whether a static base-address is set. - inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; } + ASMJIT_INLINE_NODEBUG bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; } //! Returns a static base-address or \ref Globals::kNoBaseAddress, if not set. - inline uint64_t baseAddress() const noexcept { return _baseAddress; } + ASMJIT_INLINE_NODEBUG uint64_t baseAddress() const noexcept { return _baseAddress; } //! \} @@ -747,7 +834,7 @@ public: //! \{ //! Returns a vector of attached emitters. - inline const ZoneVector<BaseEmitter*>& emitters() const noexcept { return _emitters; } + ASMJIT_INLINE_NODEBUG const ZoneVector<BaseEmitter*>& emitters() const noexcept { return _emitters; } //! \} @@ -755,23 +842,23 @@ public: //! \{ //! Returns the attached logger. - inline Logger* logger() const noexcept { return _logger; } + ASMJIT_INLINE_NODEBUG Logger* logger() const noexcept { return _logger; } //! Attaches a `logger` to CodeHolder and propagates it to all attached emitters. ASMJIT_API void setLogger(Logger* logger) noexcept; //! Resets the logger to none. - inline void resetLogger() noexcept { setLogger(nullptr); } + ASMJIT_INLINE_NODEBUG void resetLogger() noexcept { setLogger(nullptr); } //! \name Error Handling //! \{ //! Tests whether the CodeHolder has an attached error handler, see \ref ErrorHandler. - inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; } //! Returns the attached error handler. - inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; } + ASMJIT_INLINE_NODEBUG ErrorHandler* errorHandler() const noexcept { return _errorHandler; } //! Attach an error handler to this `CodeHolder`. ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept; //! Resets the error handler to none. - inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); } + ASMJIT_INLINE_NODEBUG void resetErrorHandler() noexcept { setErrorHandler(nullptr); } //! \} @@ -794,14 +881,14 @@ public: //! \{ //! Returns an array of `Section*` records. - inline const ZoneVector<Section*>& sections() const noexcept { return _sections; } + ASMJIT_INLINE_NODEBUG const ZoneVector<Section*>& sections() const noexcept { return _sections; } //! Returns an array of `Section*` records sorted according to section order first, then section id. - inline const ZoneVector<Section*>& sectionsByOrder() const noexcept { return _sectionsByOrder; } + ASMJIT_INLINE_NODEBUG const ZoneVector<Section*>& sectionsByOrder() const noexcept { return _sectionsByOrder; } //! Returns the number of sections. - inline uint32_t sectionCount() const noexcept { return _sections.size(); } + ASMJIT_INLINE_NODEBUG uint32_t sectionCount() const noexcept { return _sections.size(); } //! Tests whether the given `sectionId` is valid. - inline bool isSectionValid(uint32_t sectionId) const noexcept { return sectionId < _sections.size(); } + ASMJIT_INLINE_NODEBUG bool isSectionValid(uint32_t sectionId) const noexcept { return sectionId < _sections.size(); } //! Creates a new section and return its pointer in `sectionOut`. //! @@ -809,7 +896,7 @@ public: ASMJIT_API Error newSection(Section** sectionOut, const char* name, size_t nameSize = SIZE_MAX, SectionFlags flags = SectionFlags::kNone, uint32_t alignment = 1, int32_t order = 0) noexcept; //! Returns a section entry of the given index. - inline Section* sectionById(uint32_t sectionId) const noexcept { return _sections[sectionId]; } + ASMJIT_INLINE_NODEBUG Section* sectionById(uint32_t sectionId) const noexcept { return _sections[sectionId]; } //! Returns section-id that matches the given `name`. //! @@ -819,10 +906,10 @@ public: //! Returns '.text' section (section that commonly represents code). //! //! \note Text section is always the first section in \ref CodeHolder::sections() array. - inline Section* textSection() const noexcept { return _sections[0]; } + ASMJIT_INLINE_NODEBUG Section* textSection() const noexcept { return _sections[0]; } //! Tests whether '.addrtab' section exists. - inline bool hasAddressTable() const noexcept { return _addressTableSection != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasAddressTable() const noexcept { return _addressTableSection != nullptr; } //! Returns '.addrtab' section. //! @@ -830,7 +917,7 @@ public: //! addresses that cannot be encoded in instructions like 'jmp' or 'call'. //! //! \note This section is created on demand, the returned pointer can be null. - inline Section* addressTableSection() const noexcept { return _addressTableSection; } + ASMJIT_INLINE_NODEBUG Section* addressTableSection() const noexcept { return _addressTableSection; } //! Ensures that '.addrtab' section exists (creates it if it doesn't) and //! returns it. Can return `nullptr` on out of memory condition. @@ -843,7 +930,7 @@ public: //! use the same slot. //! //! This function should be considered internal as it's used by assemblers to insert an absolute address into the - //! address table. Inserting address into address table without creating a particula relocation entry makes no sense. + //! address table. Inserting address into address table without creating a particular relocation entry makes no sense. ASMJIT_API Error addAddressToAddressTable(uint64_t address) noexcept; //! \} @@ -852,40 +939,40 @@ public: //! \{ //! Returns array of `LabelEntry*` records. - inline const ZoneVector<LabelEntry*>& labelEntries() const noexcept { return _labelEntries; } + ASMJIT_INLINE_NODEBUG const ZoneVector<LabelEntry*>& labelEntries() const noexcept { return _labelEntries; } //! Returns number of labels created. - inline uint32_t labelCount() const noexcept { return _labelEntries.size(); } + ASMJIT_INLINE_NODEBUG uint32_t labelCount() const noexcept { return _labelEntries.size(); } //! Tests whether the label having `id` is valid (i.e. created by `newLabelEntry()`). - inline bool isLabelValid(uint32_t labelId) const noexcept { + ASMJIT_INLINE_NODEBUG bool isLabelValid(uint32_t labelId) const noexcept { return labelId < _labelEntries.size(); } //! Tests whether the `label` is valid (i.e. created by `newLabelEntry()`). - inline bool isLabelValid(const Label& label) const noexcept { + ASMJIT_INLINE_NODEBUG bool isLabelValid(const Label& label) const noexcept { return label.id() < _labelEntries.size(); } //! \overload - inline bool isLabelBound(uint32_t labelId) const noexcept { + ASMJIT_INLINE_NODEBUG bool isLabelBound(uint32_t labelId) const noexcept { return isLabelValid(labelId) && _labelEntries[labelId]->isBound(); } //! Tests whether the `label` is already bound. //! //! Returns `false` if the `label` is not valid. - inline bool isLabelBound(const Label& label) const noexcept { + ASMJIT_INLINE_NODEBUG bool isLabelBound(const Label& label) const noexcept { return isLabelBound(label.id()); } //! Returns LabelEntry of the given label `id`. - inline LabelEntry* labelEntry(uint32_t labelId) const noexcept { + ASMJIT_INLINE_NODEBUG LabelEntry* labelEntry(uint32_t labelId) const noexcept { return isLabelValid(labelId) ? _labelEntries[labelId] : static_cast<LabelEntry*>(nullptr); } //! Returns LabelEntry of the given `label`. - inline LabelEntry* labelEntry(const Label& label) const noexcept { + ASMJIT_INLINE_NODEBUG LabelEntry* labelEntry(const Label& label) const noexcept { return labelEntry(label.id()); } @@ -893,13 +980,13 @@ public: //! //! The offset returned is relative to the start of the section. Zero offset is returned for unbound labels, //! which is their initial offset value. - inline uint64_t labelOffset(uint32_t labelId) const noexcept { + ASMJIT_INLINE_NODEBUG uint64_t labelOffset(uint32_t labelId) const noexcept { ASMJIT_ASSERT(isLabelValid(labelId)); return _labelEntries[labelId]->offset(); } //! \overload - inline uint64_t labelOffset(const Label& label) const noexcept { + ASMJIT_INLINE_NODEBUG uint64_t labelOffset(const Label& label) const noexcept { return labelOffset(label.id()); } @@ -944,7 +1031,7 @@ public: //! //! If the named label doesn't a default constructed \ref Label is returned, //! which has its id set to \ref Globals::kInvalidId. - inline Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept { + ASMJIT_INLINE_NODEBUG Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept { return Label(labelIdByName(name, nameSize, parentId)); } @@ -954,9 +1041,9 @@ public: ASMJIT_API uint32_t labelIdByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept; //! Tests whether there are any unresolved label links. - inline bool hasUnresolvedLinks() const noexcept { return _unresolvedLinkCount != 0; } + ASMJIT_INLINE_NODEBUG bool hasUnresolvedLinks() const noexcept { return _unresolvedLinkCount != 0; } //! Returns the number of label links, which are unresolved. - inline size_t unresolvedLinkCount() const noexcept { return _unresolvedLinkCount; } + ASMJIT_INLINE_NODEBUG size_t unresolvedLinkCount() const noexcept { return _unresolvedLinkCount; } //! Creates a new label-link used to store information about yet unbound labels. //! @@ -979,12 +1066,12 @@ public: //! \{ //! Tests whether the code contains relocation entries. - inline bool hasRelocEntries() const noexcept { return !_relocations.empty(); } + ASMJIT_INLINE_NODEBUG bool hasRelocEntries() const noexcept { return !_relocations.empty(); } //! Returns array of `RelocEntry*` records. - inline const ZoneVector<RelocEntry*>& relocEntries() const noexcept { return _relocations; } + ASMJIT_INLINE_NODEBUG const ZoneVector<RelocEntry*>& relocEntries() const noexcept { return _relocations; } //! Returns a RelocEntry of the given `id`. - inline RelocEntry* relocEntry(uint32_t id) const noexcept { return _relocations[id]; } + ASMJIT_INLINE_NODEBUG RelocEntry* relocEntry(uint32_t id) const noexcept { return _relocations[id]; } //! Creates a new relocation entry of type `relocType`. //! @@ -1011,7 +1098,8 @@ public: //! Relocates the code to the given `baseAddress`. //! //! \param baseAddress Absolute base address where the code will be relocated to. Please note that nothing is - //! copied to such base address, it's just an absolute value used by the relocator to resolve all stored relocations. + //! copied to such base address, it's just an absolute value used by the relocation code to resolve all stored + //! relocations. //! //! \note This should never be called more than once. ASMJIT_API Error relocateToBase(uint64_t baseAddress) noexcept; diff --git a/3rdparty/asmjit/src/asmjit/core/codewriter.cpp b/3rdparty/asmjit/src/asmjit/core/codewriter.cpp index 1babc5f172e..2ee5b38cda5 100644 --- a/3rdparty/asmjit/src/asmjit/core/codewriter.cpp +++ b/3rdparty/asmjit/src/asmjit/core/codewriter.cpp @@ -6,6 +6,7 @@ #include "../core/api-build_p.h" #include "../core/codeholder.h" #include "../core/codewriter_p.h" +#include "../arm/armutils.h" ASMJIT_BEGIN_NAMESPACE @@ -19,9 +20,20 @@ bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const Offs return false; uint32_t value; + uint32_t u = 0; + bool unsignedLogic = format.type() == OffsetType::kUnsignedOffset; + + // First handle all offsets that use additional field for their sign and the offset is encoded as its + // absolute value. + if (format.hasSignBit()) { + u = uint32_t(offset64 >= 0); + if (u == 0) + offset64 = -offset64; + unsignedLogic = true; + } // First handle all unsigned offset types. - if (format.type() == OffsetType::kUnsignedOffset) { + if (unsignedLogic) { if (discardLsb) { ASMJIT_ASSERT(discardLsb <= 32); if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0) @@ -57,6 +69,97 @@ bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const Offs return true; } + // Opcode: {.....|imm:1|..N.N|......|imm:3|....|imm:8} + case OffsetType::kThumb32_ADR: { + // Sanity checks. + if (format.valueSize() != 4 || bitCount != 12 || bitShift != 0) + return false; + + uint32_t imm8 = (value & 0x00FFu); + uint32_t imm3 = (value & 0x0700u) << (12 - 8); + uint32_t imm1 = (value & 0x0800u) << (26 - 11); + uint32_t n = u ^ 1u; + + *dst = imm8 | imm3 | imm1 | (n << 21) | (n << 23); + return true; + } + + // Opcode: {....|.|imm[22]|imm[19:10]|..|ja|.|jb|imm[9:0]|.} + case OffsetType::kThumb32_BLX: + // The calculation is the same as `B`, but the first LSB bit must be zero, so account for that. + value <<= 1; + ASMJIT_FALLTHROUGH; + + // Opcode: {....|.|imm[23]|imm[20:11]|..|ja|.|jb|imm[10:0]} + case OffsetType::kThumb32_B: { + // Sanity checks. + if (format.valueSize() != 4) + return false; + + uint32_t ia = (value & 0x0007FFu); + uint32_t ib = (value & 0x1FF800u) << (16 - 11); + uint32_t ic = (value & 0x800000u) << (26 - 23); + uint32_t ja = ((~value >> 23) ^ (value >> 22)) & 1u; + uint32_t jb = ((~value >> 23) ^ (value >> 21)) & 1u; + + *dst = ia | ib | ic | (ja << 14) | (jb << 11); + return true; + } + + // Opcode: {....|.|imm[19]|....|imm[16:11]|..|ja|.|jb|imm[10:0]} + case OffsetType::kThumb32_BCond: { + // Sanity checks. + if (format.valueSize() != 4 || bitCount != 20 || bitShift != 0) + return false; + + uint32_t ia = (value & 0x0007FFu); + uint32_t ib = (value & 0x01F800u) << (16 - 11); + uint32_t ic = (value & 0x080000u) << (26 - 19); + uint32_t ja = ((~value >> 19) ^ (value >> 22)) & 1u; + uint32_t jb = ((~value >> 19) ^ (value >> 21)) & 1u; + + *dst = ia | ib | ic | (ja << 14) | (jb << 11); + return true; + } + + case OffsetType::kAArch32_ADR: { + uint32_t encodedImm; + if (!arm::Utils::encodeAArch32Imm(value, &encodedImm)) + return false; + + *dst = (Support::bitMask(22) << u) | (encodedImm << bitShift); + return true; + } + + case OffsetType::kAArch32_U23_SignedOffset: { + *dst = (value << bitShift) | (u << 23); + return true; + } + + case OffsetType::kAArch32_U23_0To3At0_4To7At8: { + // Sanity checks. + if (format.valueSize() != 4 || bitCount != 8 || bitShift != 0) + return false; + + uint32_t immLo = (value & 0x0Fu); + uint32_t immHi = (value & 0xF0u) << (8 - 4); + + *dst = immLo | immHi | (u << 23); + return true; + } + + case OffsetType::kAArch32_1To24At0_0At24: { + // Sanity checks. + if (format.valueSize() != 4 || bitCount != 25 || bitShift != 0) + return false; + + uint32_t immLo = (value & 0x0000001u) << 24; + uint32_t immHi = (value & 0x1FFFFFEu) >> 1; + + *dst = immLo | immHi; + return true; + } + case OffsetType::kAArch64_ADR: case OffsetType::kAArch64_ADRP: { // Sanity checks. diff --git a/3rdparty/asmjit/src/asmjit/core/compiler.cpp b/3rdparty/asmjit/src/asmjit/core/compiler.cpp index b1c6b803b29..b09ae396608 100644 --- a/3rdparty/asmjit/src/asmjit/core/compiler.cpp +++ b/3rdparty/asmjit/src/asmjit/core/compiler.cpp @@ -7,6 +7,7 @@ #ifndef ASMJIT_NO_COMPILER #include "../core/assembler.h" +#include "../core/builder_p.h" #include "../core/compiler.h" #include "../core/cpuinfo.h" #include "../core/logger.h" @@ -103,9 +104,13 @@ Error BaseCompiler::newFuncNode(FuncNode** out, const FuncSignature& signature) } Error BaseCompiler::addFuncNode(FuncNode** out, const FuncSignature& signature) { + State state = _grabState(); + ASMJIT_PROPAGATE(newFuncNode(out, signature)); ASMJIT_ASSUME(*out != nullptr); + BaseBuilder_assignInlineComment(this, *out, state.comment); + addFunc(*out); return kErrorOk; } @@ -127,7 +132,13 @@ Error BaseCompiler::newFuncRetNode(FuncRetNode** out, const Operand_& o0, const } Error BaseCompiler::addFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { + State state = _grabState(); + ASMJIT_PROPAGATE(newFuncRetNode(out, o0, o1)); + ASMJIT_ASSUME(*out != nullptr); + + BaseBuilder_assignInlineComment(this, *out, state.comment); + addNode(*out); return kErrorOk; } @@ -146,6 +157,7 @@ FuncNode* BaseCompiler::addFunc(FuncNode* func) { Error BaseCompiler::endFunc() { FuncNode* func = _func; + resetState(); if (ASMJIT_UNLIKELY(!func)) return reportError(DebugUtils::errored(kErrorInvalidState)); @@ -196,7 +208,12 @@ Error BaseCompiler::newInvokeNode(InvokeNode** out, InstId instId, const Operand } Error BaseCompiler::addInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature) { + State state = _grabState(); + ASMJIT_PROPAGATE(newInvokeNode(out, instId, o0, signature)); + ASMJIT_ASSUME(*out != nullptr); + + BaseBuilder_assignInstState(this, *out, state); addNode(*out); return kErrorOk; } @@ -231,7 +248,7 @@ Error BaseCompiler::newVirtReg(VirtReg** out, TypeId typeId, OperandSignature si uint32_t size = TypeUtils::sizeOf(typeId); uint32_t alignment = Support::min<uint32_t>(size, 64); - vReg = new(vReg) VirtReg(signature, Operand::indexToVirtId(index), size, alignment, typeId); + vReg = new(Support::PlacementNew{vReg}) VirtReg(signature, Operand::indexToVirtId(index), size, alignment, typeId); #ifndef ASMJIT_NO_LOGGING if (name && name[0] != '\0') @@ -473,7 +490,7 @@ Error BaseCompiler::newJumpNode(JumpNode** out, InstId instId, InstOptions instO if (ASMJIT_UNLIKELY(!node)) return reportError(DebugUtils::errored(kErrorOutOfMemory)); - node = new(node) JumpNode(this, instId, instOptions, opCount, annotation); + node = new(Support::PlacementNew{node}) JumpNode(this, instId, instOptions, opCount, annotation); node->setOp(0, o0); node->resetOpRange(opCount, JumpNode::kBaseOpCapacity); @@ -481,20 +498,13 @@ Error BaseCompiler::newJumpNode(JumpNode** out, InstId instId, InstOptions instO } Error BaseCompiler::emitAnnotatedJump(InstId instId, const Operand_& o0, JumpAnnotation* annotation) { - InstOptions options = instOptions() | forcedInstOptions(); - RegOnly extra = extraReg(); - const char* comment = inlineComment(); - - resetInstOptions(); - resetInlineComment(); - resetExtraReg(); + State state = _grabState(); JumpNode* node; - ASMJIT_PROPAGATE(newJumpNode(&node, instId, options, o0, annotation)); + ASMJIT_PROPAGATE(newJumpNode(&node, instId, state.options, o0, annotation)); - node->setExtraReg(extra); - if (comment) - node->setInlineComment(static_cast<char*>(_dataZone.dup(comment, strlen(comment), true))); + node->setExtraReg(state.extraReg); + BaseBuilder_assignInlineComment(this, node, state.comment); addNode(node); return kErrorOk; @@ -577,6 +587,12 @@ Error FuncPass::run(Zone* zone, Logger* logger) { return kErrorOk; } +// [[pure virtual]] +Error FuncPass::runOnFunction(Zone* zone, Logger* logger, FuncNode* func) { + DebugUtils::unused(zone, logger, func); + return DebugUtils::errored(kErrorInvalidState); +} + ASMJIT_END_NAMESPACE #endif // !ASMJIT_NO_COMPILER diff --git a/3rdparty/asmjit/src/asmjit/core/compiler.h b/3rdparty/asmjit/src/asmjit/core/compiler.h index 709fd952acc..7d4b47c4597 100644 --- a/3rdparty/asmjit/src/asmjit/core/compiler.h +++ b/3rdparty/asmjit/src/asmjit/core/compiler.h @@ -47,6 +47,7 @@ class InvokeNode; //! Check out architecture specific compilers for more details and examples: //! //! - \ref x86::Compiler - X86/X64 compiler implementation. +//! - \ref a64::Compiler - AArch64 compiler implementation. class ASMJIT_VIRTAPI BaseCompiler : public BaseBuilder { public: ASMJIT_NONCOPYABLE(BaseCompiler) @@ -77,7 +78,7 @@ public: //! Creates a new `BaseCompiler` instance. ASMJIT_API BaseCompiler() noexcept; //! Destroys the `BaseCompiler` instance. - ASMJIT_API virtual ~BaseCompiler() noexcept; + ASMJIT_API ~BaseCompiler() noexcept override; //! \} @@ -95,7 +96,7 @@ public: ASMJIT_API Error addFuncRetNode(FuncRetNode** ASMJIT_NONNULL(out), const Operand_& o0, const Operand_& o1); //! Returns the current function. - inline FuncNode* func() const noexcept { return _func; } + ASMJIT_INLINE_NODEBUG FuncNode* func() const noexcept { return _func; } //! Creates a new \ref FuncNode with the given `signature` and returns it. inline FuncNode* newFunc(const FuncSignature& signature) { @@ -162,6 +163,8 @@ public: //! //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments. ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId, const char* fmt, ...); + //! \overload + inline Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId) { return _newRegFmt(out, typeId, nullptr); } //! Creates a new virtual register compatible with the provided reference register `ref`. ASMJIT_API Error _newReg(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* name = nullptr); @@ -172,12 +175,12 @@ public: ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* fmt, ...); //! Tests whether the given `id` is a valid virtual register id. - inline bool isVirtIdValid(uint32_t id) const noexcept { + ASMJIT_INLINE_NODEBUG bool isVirtIdValid(uint32_t id) const noexcept { uint32_t index = Operand::virtIdToIndex(id); return index < _vRegArray.size(); } //! Tests whether the given `reg` is a virtual register having a valid id. - inline bool isVirtRegValid(const BaseReg& reg) const noexcept { + ASMJIT_INLINE_NODEBUG bool isVirtRegValid(const BaseReg& reg) const noexcept { return isVirtIdValid(reg.id()); } @@ -188,16 +191,16 @@ public: } //! Returns \ref VirtReg associated with the given `reg`. - inline VirtReg* virtRegByReg(const BaseReg& reg) const noexcept { return virtRegById(reg.id()); } + ASMJIT_INLINE_NODEBUG VirtReg* virtRegByReg(const BaseReg& reg) const noexcept { return virtRegById(reg.id()); } //! Returns \ref VirtReg associated with the given virtual register `index`. //! //! \note This is not the same as virtual register id. The conversion between id and its index is implemented //! by \ref Operand_::virtIdToIndex() and \ref Operand_::indexToVirtId() functions. - inline VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; } + ASMJIT_INLINE_NODEBUG VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; } //! Returns an array of all virtual registers managed by the Compiler. - inline const ZoneVector<VirtReg*>& virtRegs() const noexcept { return _vRegArray; } + ASMJIT_INLINE_NODEBUG const ZoneVector<VirtReg*>& virtRegs() const noexcept { return _vRegArray; } //! \name Stack //! \{ @@ -211,7 +214,7 @@ public: ASMJIT_API Error setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment = 0); //! Updates the stack size of a stack created by `_newStack()`. - inline Error setStackSize(const BaseMem& mem, uint32_t newSize, uint32_t newAlignment = 0) { + ASMJIT_INLINE_NODEBUG Error setStackSize(const BaseMem& mem, uint32_t newSize, uint32_t newAlignment = 0) { return setStackSize(mem.id(), newSize, newAlignment); } @@ -239,7 +242,7 @@ public: //! \name Jump Annotations //! \{ - inline const ZoneVector<JumpAnnotation*>& jumpAnnotations() const noexcept { + ASMJIT_INLINE_NODEBUG const ZoneVector<JumpAnnotation*>& jumpAnnotations() const noexcept { return _jumpAnnotations; } @@ -286,7 +289,7 @@ public: //! \name Construction & Destruction //! \{ - inline JumpAnnotation(BaseCompiler* ASMJIT_NONNULL(compiler), uint32_t annotationId) noexcept + ASMJIT_INLINE_NODEBUG JumpAnnotation(BaseCompiler* ASMJIT_NONNULL(compiler), uint32_t annotationId) noexcept : _compiler(compiler), _annotationId(annotationId) {} @@ -296,16 +299,16 @@ public: //! \{ //! Returns the compiler that owns this JumpAnnotation. - inline BaseCompiler* compiler() const noexcept { return _compiler; } + ASMJIT_INLINE_NODEBUG BaseCompiler* compiler() const noexcept { return _compiler; } //! Returns the annotation id. - inline uint32_t annotationId() const noexcept { return _annotationId; } + ASMJIT_INLINE_NODEBUG uint32_t annotationId() const noexcept { return _annotationId; } //! Returns a vector of label identifiers that lists all targets of the jump. - const ZoneVector<uint32_t>& labelIds() const noexcept { return _labelIds; } + ASMJIT_INLINE_NODEBUG const ZoneVector<uint32_t>& labelIds() const noexcept { return _labelIds; } //! Tests whether the given `label` is a target of this JumpAnnotation. - inline bool hasLabel(const Label& label) const noexcept { return hasLabelId(label.id()); } + ASMJIT_INLINE_NODEBUG bool hasLabel(const Label& label) const noexcept { return hasLabelId(label.id()); } //! Tests whether the given `labelId` is a target of this JumpAnnotation. - inline bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); } + ASMJIT_INLINE_NODEBUG bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); } //! \} @@ -313,9 +316,9 @@ public: //! \{ //! Adds the `label` to the list of targets of this JumpAnnotation. - inline Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); } + ASMJIT_INLINE_NODEBUG Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); } //! Adds the `labelId` to the list of targets of this JumpAnnotation. - inline Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); } + ASMJIT_INLINE_NODEBUG Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); } //! \} }; @@ -325,7 +328,7 @@ public: //! \note This node should be only used to represent jump where the jump target cannot be deduced by examining //! instruction operands. For example if the jump target is register or memory location. This pattern is often //! used to perform indirect jumps that use jump table, e.g. to implement `switch{}` statement. -class JumpNode : public InstNode { +class JumpNode : public InstNodeWithOperands<InstNode::kBaseOpCapacity> { public: ASMJIT_NONCOPYABLE(JumpNode) @@ -340,7 +343,7 @@ public: //! \{ inline JumpNode(BaseCompiler* ASMJIT_NONNULL(cc), InstId instId, InstOptions options, uint32_t opCount, JumpAnnotation* annotation) noexcept - : InstNode(cc, instId, options, opCount, kBaseOpCapacity), + : InstNodeWithOperands(cc, instId, options, opCount), _annotation(annotation) { setType(NodeType::kJump); } @@ -351,11 +354,11 @@ public: //! \{ //! Tests whether this JumpNode has associated a \ref JumpAnnotation. - inline bool hasAnnotation() const noexcept { return _annotation != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasAnnotation() const noexcept { return _annotation != nullptr; } //! Returns the \ref JumpAnnotation associated with this jump, or `nullptr`. - inline JumpAnnotation* annotation() const noexcept { return _annotation; } + ASMJIT_INLINE_NODEBUG JumpAnnotation* annotation() const noexcept { return _annotation; } //! Sets the \ref JumpAnnotation associated with this jump to `annotation`. - inline void setAnnotation(JumpAnnotation* annotation) noexcept { _annotation = annotation; } + ASMJIT_INLINE_NODEBUG void setAnnotation(JumpAnnotation* annotation) noexcept { _annotation = annotation; } //! \} }; @@ -455,35 +458,35 @@ public: //! \name Accessors //! Returns function exit `LabelNode`. - inline LabelNode* exitNode() const noexcept { return _exitNode; } + ASMJIT_INLINE_NODEBUG LabelNode* exitNode() const noexcept { return _exitNode; } //! Returns function exit label. - inline Label exitLabel() const noexcept { return _exitNode->label(); } + ASMJIT_INLINE_NODEBUG Label exitLabel() const noexcept { return _exitNode->label(); } //! Returns "End of Func" sentinel node. - inline SentinelNode* endNode() const noexcept { return _end; } + ASMJIT_INLINE_NODEBUG SentinelNode* endNode() const noexcept { return _end; } //! Returns function detail. - inline FuncDetail& detail() noexcept { return _funcDetail; } + ASMJIT_INLINE_NODEBUG FuncDetail& detail() noexcept { return _funcDetail; } //! Returns function detail. - inline const FuncDetail& detail() const noexcept { return _funcDetail; } + ASMJIT_INLINE_NODEBUG const FuncDetail& detail() const noexcept { return _funcDetail; } //! Returns function frame. - inline FuncFrame& frame() noexcept { return _frame; } + ASMJIT_INLINE_NODEBUG FuncFrame& frame() noexcept { return _frame; } //! Returns function frame. - inline const FuncFrame& frame() const noexcept { return _frame; } + ASMJIT_INLINE_NODEBUG const FuncFrame& frame() const noexcept { return _frame; } //! Returns function attributes. - inline FuncAttributes attributes() const noexcept { return _frame.attributes(); } + ASMJIT_INLINE_NODEBUG FuncAttributes attributes() const noexcept { return _frame.attributes(); } //! Adds `attrs` to the function attributes. - inline void addAttributes(FuncAttributes attrs) noexcept { _frame.addAttributes(attrs); } + ASMJIT_INLINE_NODEBUG void addAttributes(FuncAttributes attrs) noexcept { _frame.addAttributes(attrs); } //! Returns arguments count. - inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); } + ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _funcDetail.argCount(); } //! Returns argument packs. - inline ArgPack* argPacks() const noexcept { return _args; } + ASMJIT_INLINE_NODEBUG ArgPack* argPacks() const noexcept { return _args; } //! Tests whether the function has a return value. - inline bool hasRet() const noexcept { return _funcDetail.hasRet(); } + ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _funcDetail.hasRet(); } //! Returns argument pack at `argIndex`. inline ArgPack& argPack(size_t argIndex) const noexcept { @@ -531,7 +534,7 @@ public: }; //! Function return, used by \ref BaseCompiler. -class FuncRetNode : public InstNode { +class FuncRetNode : public InstNodeWithOperands<InstNode::kBaseOpCapacity> { public: ASMJIT_NONCOPYABLE(FuncRetNode) @@ -539,7 +542,8 @@ public: //! \{ //! Creates a new `FuncRetNode` instance. - inline FuncRetNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept : InstNode(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) { + inline FuncRetNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept + : InstNodeWithOperands(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) { _any._nodeType = NodeType::kFuncRet; } @@ -547,12 +551,12 @@ public: }; //! Function invocation, used by \ref BaseCompiler. -class InvokeNode : public InstNode { +class InvokeNode : public InstNodeWithOperands<InstNode::kBaseOpCapacity> { public: ASMJIT_NONCOPYABLE(InvokeNode) //! Operand pack provides multiple operands that can be associated with a single return value of function - //! argument. Sometims this is necessary to express an argument or return value that requires multiple + //! argument. Sometimes this is necessary to express an argument or return value that requires multiple //! registers, for example 64-bit value in 32-bit mode or passing / returning homogeneous data structures. struct OperandPack { //! Operands. @@ -594,7 +598,7 @@ public: //! Creates a new `InvokeNode` instance. inline InvokeNode(BaseBuilder* ASMJIT_NONNULL(cb), InstId instId, InstOptions options) noexcept - : InstNode(cb, instId, options, kBaseOpCapacity), + : InstNodeWithOperands(cb, instId, options, 0), _funcDetail(), _args(nullptr) { setType(NodeType::kInvoke); @@ -614,29 +618,29 @@ public: } //! Returns the function detail. - inline FuncDetail& detail() noexcept { return _funcDetail; } + ASMJIT_INLINE_NODEBUG FuncDetail& detail() noexcept { return _funcDetail; } //! Returns the function detail. - inline const FuncDetail& detail() const noexcept { return _funcDetail; } + ASMJIT_INLINE_NODEBUG const FuncDetail& detail() const noexcept { return _funcDetail; } //! Returns the target operand. - inline Operand& target() noexcept { return _opArray[0].as<Operand>(); } + ASMJIT_INLINE_NODEBUG Operand& target() noexcept { return op(0); } //! \overload - inline const Operand& target() const noexcept { return _opArray[0].as<Operand>(); } + ASMJIT_INLINE_NODEBUG const Operand& target() const noexcept { return op(0); } //! Returns the number of function return values. - inline bool hasRet() const noexcept { return _funcDetail.hasRet(); } + ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _funcDetail.hasRet(); } //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); } + ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _funcDetail.argCount(); } //! Returns operand pack representing function return value(s). - inline OperandPack& retPack() noexcept { return _rets; } + ASMJIT_INLINE_NODEBUG OperandPack& retPack() noexcept { return _rets; } //! Returns operand pack representing function return value(s). - inline const OperandPack& retPack() const noexcept { return _rets; } + ASMJIT_INLINE_NODEBUG const OperandPack& retPack() const noexcept { return _rets; } //! Returns the return value at the given `valueIndex`. - inline Operand& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; } + ASMJIT_INLINE_NODEBUG Operand& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; } //! \overload - inline const Operand& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; } + ASMJIT_INLINE_NODEBUG const Operand& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; } //! Returns operand pack representing function return value(s). inline OperandPack& argPack(size_t argIndex) noexcept { @@ -669,17 +673,17 @@ public: } //! Sets the function return value at `valueIndex` to `reg`. - inline void setRet(size_t valueIndex, const BaseReg& reg) noexcept { _setRet(valueIndex, reg); } + ASMJIT_INLINE_NODEBUG void setRet(size_t valueIndex, const BaseReg& reg) noexcept { _setRet(valueIndex, reg); } //! Sets the first function argument in a value-pack at `argIndex` to `reg`. - inline void setArg(size_t argIndex, const BaseReg& reg) noexcept { _setArg(argIndex, 0, reg); } + ASMJIT_INLINE_NODEBUG void setArg(size_t argIndex, const BaseReg& reg) noexcept { _setArg(argIndex, 0, reg); } //! Sets the first function argument in a value-pack at `argIndex` to `imm`. - inline void setArg(size_t argIndex, const Imm& imm) noexcept { _setArg(argIndex, 0, imm); } + ASMJIT_INLINE_NODEBUG void setArg(size_t argIndex, const Imm& imm) noexcept { _setArg(argIndex, 0, imm); } //! Sets the function argument at `argIndex` and `valueIndex` to `reg`. - inline void setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) noexcept { _setArg(argIndex, valueIndex, reg); } + ASMJIT_INLINE_NODEBUG void setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) noexcept { _setArg(argIndex, valueIndex, reg); } //! Sets the function argument at `argIndex` and `valueIndex` to `imm`. - inline void setArg(size_t argIndex, size_t valueIndex, const Imm& imm) noexcept { _setArg(argIndex, valueIndex, imm); } + ASMJIT_INLINE_NODEBUG void setArg(size_t argIndex, size_t valueIndex, const Imm& imm) noexcept { _setArg(argIndex, valueIndex, imm); } //! \} }; @@ -701,7 +705,7 @@ public: //! \{ //! Returns the associated `BaseCompiler`. - inline BaseCompiler* cc() const noexcept { return static_cast<BaseCompiler*>(_cb); } + ASMJIT_INLINE_NODEBUG BaseCompiler* cc() const noexcept { return static_cast<BaseCompiler*>(_cb); } //! \} @@ -712,7 +716,7 @@ public: ASMJIT_API Error run(Zone* zone, Logger* logger) override; //! Called once per `FuncNode`. - virtual Error runOnFunction(Zone* zone, Logger* logger, FuncNode* func) = 0; + ASMJIT_API virtual Error runOnFunction(Zone* zone, Logger* logger, FuncNode* func); //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/compilerdefs.h b/3rdparty/asmjit/src/asmjit/core/compilerdefs.h index 1870e688bc9..e2e74ce6790 100644 --- a/3rdparty/asmjit/src/asmjit/core/compilerdefs.h +++ b/3rdparty/asmjit/src/asmjit/core/compilerdefs.h @@ -66,18 +66,16 @@ public: //! \name Construction & Destruction //! \{ - inline VirtReg(OperandSignature signature, uint32_t id, uint32_t virtSize, uint32_t alignment, TypeId typeId) noexcept + ASMJIT_INLINE_NODEBUG VirtReg(OperandSignature signature, uint32_t id, uint32_t virtSize, uint32_t alignment, TypeId typeId) noexcept : _signature(signature), _id(id), _virtSize(virtSize), _alignment(uint8_t(alignment)), _typeId(typeId), - _isFixed(false), - _isStack(false), - _hasStackSlot(false), - _reservedBits(0), - _stackOffset(0), - _reservedU32(0) {} + _isFixed(0), + _isStack(0), + _hasStackSlot(0), + _reservedBits(0) {} //! \} @@ -85,64 +83,64 @@ public: //! \{ //! Returns the virtual register id. - inline uint32_t id() const noexcept { return _id; } + ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _id; } //! Returns the virtual register name. - inline const char* name() const noexcept { return _name.data(); } + ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _name.data(); } //! Returns the size of the virtual register name. - inline uint32_t nameSize() const noexcept { return _name.size(); } + ASMJIT_INLINE_NODEBUG uint32_t nameSize() const noexcept { return _name.size(); } //! Returns a register signature of this virtual register. - inline OperandSignature signature() const noexcept { return _signature; } + ASMJIT_INLINE_NODEBUG OperandSignature signature() const noexcept { return _signature; } //! Returns a virtual register type (maps to the physical register type as well). - inline RegType type() const noexcept { return _signature.regType(); } + ASMJIT_INLINE_NODEBUG RegType type() const noexcept { return _signature.regType(); } //! Returns a virtual register group (maps to the physical register group as well). - inline RegGroup group() const noexcept { return _signature.regGroup(); } + ASMJIT_INLINE_NODEBUG RegGroup group() const noexcept { return _signature.regGroup(); } //! Returns a real size of the register this virtual register maps to. //! //! For example if this is a 128-bit SIMD register used for a scalar single precision floating point value then //! its virtSize would be 4, however, the `regSize` would still say 16 (128-bits), because it's the smallest size //! of that register type. - inline uint32_t regSize() const noexcept { return _signature.size(); } + ASMJIT_INLINE_NODEBUG uint32_t regSize() const noexcept { return _signature.size(); } //! Returns the virtual register size. //! //! The virtual register size describes how many bytes the virtual register needs to store its content. It can be //! smaller than the physical register size, see `regSize()`. - inline uint32_t virtSize() const noexcept { return _virtSize; } + ASMJIT_INLINE_NODEBUG uint32_t virtSize() const noexcept { return _virtSize; } //! Returns the virtual register alignment. - inline uint32_t alignment() const noexcept { return _alignment; } + ASMJIT_INLINE_NODEBUG uint32_t alignment() const noexcept { return _alignment; } //! Returns the virtual register type id. - inline TypeId typeId() const noexcept { return _typeId; } + ASMJIT_INLINE_NODEBUG TypeId typeId() const noexcept { return _typeId; } //! Returns the virtual register weight - the register allocator can use it as explicit hint for alloc/spill //! decisions. - inline uint32_t weight() const noexcept { return _weight; } + ASMJIT_INLINE_NODEBUG uint32_t weight() const noexcept { return _weight; } //! Sets the virtual register weight (0 to 255) - the register allocator can use it as explicit hint for //! alloc/spill decisions and initial bin-packing. - inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); } + ASMJIT_INLINE_NODEBUG void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); } //! Returns whether the virtual register is always allocated to a fixed physical register (and never reallocated). //! //! \note This is only used for special purposes and it's mostly internal. - inline bool isFixed() const noexcept { return bool(_isFixed); } + ASMJIT_INLINE_NODEBUG bool isFixed() const noexcept { return bool(_isFixed); } //! Tests whether the virtual register is in fact a stack that only uses the virtual register id. //! //! \note It's an error if a stack is accessed as a register. - inline bool isStack() const noexcept { return bool(_isStack); } + ASMJIT_INLINE_NODEBUG bool isStack() const noexcept { return bool(_isStack); } //! Tests whether this virtual register (or stack) has assigned a stack offset. //! //! If this is a virtual register that was never allocated on stack, it would return false, otherwise if //! it's a virtual register that was spilled or explicitly allocated stack, the return value would be true. - inline bool hasStackSlot() const noexcept { return bool(_hasStackSlot); } + ASMJIT_INLINE_NODEBUG bool hasStackSlot() const noexcept { return bool(_hasStackSlot); } //! Assigns a stack offset of this virtual register to `stackOffset` and sets `_hasStackSlot` to true. - inline void assignStackSlot(int32_t stackOffset) noexcept { + ASMJIT_INLINE_NODEBUG void assignStackSlot(int32_t stackOffset) noexcept { _hasStackSlot = 1; _stackOffset = stackOffset; } @@ -151,16 +149,16 @@ public: //! //! \note Always verify that the stack offset has been assigned by calling \ref hasStackSlot(). The return //! value will be zero when the stack offset was not assigned. - inline int32_t stackOffset() const noexcept { return _stackOffset; } + ASMJIT_INLINE_NODEBUG int32_t stackOffset() const noexcept { return _stackOffset; } //! Tests whether the virtual register has an associated `RAWorkReg` at the moment. - inline bool hasWorkReg() const noexcept { return _workReg != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasWorkReg() const noexcept { return _workReg != nullptr; } //! Returns an associated RAWorkReg with this virtual register (only valid during register allocation). - inline RAWorkReg* workReg() const noexcept { return _workReg; } + ASMJIT_INLINE_NODEBUG RAWorkReg* workReg() const noexcept { return _workReg; } //! Associates a RAWorkReg with this virtual register (used by register allocator). - inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; } + ASMJIT_INLINE_NODEBUG void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; } //! Reset the RAWorkReg association (used by register allocator). - inline void resetWorkReg() noexcept { _workReg = nullptr; } + ASMJIT_INLINE_NODEBUG void resetWorkReg() noexcept { _workReg = nullptr; } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/constpool.cpp b/3rdparty/asmjit/src/asmjit/core/constpool.cpp index ad5fe4f2fc0..2ac5edf33c6 100644 --- a/3rdparty/asmjit/src/asmjit/core/constpool.cpp +++ b/3rdparty/asmjit/src/asmjit/core/constpool.cpp @@ -252,18 +252,18 @@ UNIT(const_pool) { size_t curOffset; uint64_t c = 0x0101010101010101u; - EXPECT(pool.add(&c, 8, prevOffset) == kErrorOk); - EXPECT(prevOffset == 0); + EXPECT_EQ(pool.add(&c, 8, prevOffset), kErrorOk); + EXPECT_EQ(prevOffset, 0u); for (i = 1; i < kCount; i++) { c++; - EXPECT(pool.add(&c, 8, curOffset) == kErrorOk); - EXPECT(prevOffset + 8 == curOffset); - EXPECT(pool.size() == (i + 1) * 8); + EXPECT_EQ(pool.add(&c, 8, curOffset), kErrorOk); + EXPECT_EQ(prevOffset + 8, curOffset); + EXPECT_EQ(pool.size(), (i + 1) * 8); prevOffset = curOffset; } - EXPECT(pool.alignment() == 8); + EXPECT_EQ(pool.alignment(), 8u); } INFO("Retrieving %u constants from the pool", kCount); @@ -272,20 +272,27 @@ UNIT(const_pool) { for (i = 0; i < kCount; i++) { size_t offset; - EXPECT(pool.add(&c, 8, offset) == kErrorOk); - EXPECT(offset == i * 8); + EXPECT_EQ(pool.add(&c, 8, offset), kErrorOk); + EXPECT_EQ(offset, i * 8); c++; } } INFO("Checking if the constants were split into 4-byte patterns"); { - uint32_t c = 0x01010101; - for (i = 0; i < kCount; i++) { - size_t offset; - EXPECT(pool.add(&c, 4, offset) == kErrorOk); - EXPECT(offset == i * 8); + uint32_t c = 0x01010101u; + size_t offset; + + EXPECT_EQ(pool.add(&c, 4, offset), kErrorOk); + EXPECT_EQ(offset, 0u); + + // NOTE: We have to adjust the offset to successfully test this on big endian architectures. + size_t baseOffset = size_t(ASMJIT_ARCH_BE ? 4 : 0); + + for (i = 1; i < kCount; i++) { c++; + EXPECT_EQ(pool.add(&c, 4, offset), kErrorOk); + EXPECT_EQ(offset, baseOffset + i * 8); } } @@ -294,9 +301,9 @@ UNIT(const_pool) { uint16_t c = 0xFFFF; size_t offset; - EXPECT(pool.add(&c, 2, offset) == kErrorOk); - EXPECT(offset == kCount * 8); - EXPECT(pool.alignment() == 8); + EXPECT_EQ(pool.add(&c, 2, offset), kErrorOk); + EXPECT_EQ(offset, kCount * 8); + EXPECT_EQ(pool.alignment(), 8u); } INFO("Adding 8 byte constant to check if pool gets aligned again"); @@ -304,8 +311,8 @@ UNIT(const_pool) { uint64_t c = 0xFFFFFFFFFFFFFFFFu; size_t offset; - EXPECT(pool.add(&c, 8, offset) == kErrorOk); - EXPECT(offset == kCount * 8 + 8); + EXPECT_EQ(pool.add(&c, 8, offset), kErrorOk); + EXPECT_EQ(offset, kCount * 8 + 8u); } INFO("Adding 2 byte constant to verify the gap is filled"); @@ -313,9 +320,9 @@ UNIT(const_pool) { uint16_t c = 0xFFFE; size_t offset; - EXPECT(pool.add(&c, 2, offset) == kErrorOk); - EXPECT(offset == kCount * 8 + 2); - EXPECT(pool.alignment() == 8); + EXPECT_EQ(pool.add(&c, 2, offset), kErrorOk); + EXPECT_EQ(offset, kCount * 8 + 2); + EXPECT_EQ(pool.alignment(), 8u); } INFO("Checking reset functionality"); @@ -323,8 +330,8 @@ UNIT(const_pool) { pool.reset(&zone); zone.reset(); - EXPECT(pool.size() == 0); - EXPECT(pool.alignment() == 0); + EXPECT_EQ(pool.size(), 0u); + EXPECT_EQ(pool.alignment(), 0u); } INFO("Checking pool alignment when combined constants are added"); @@ -333,29 +340,29 @@ UNIT(const_pool) { size_t offset; pool.add(bytes, 1, offset); - EXPECT(pool.size() == 1); - EXPECT(pool.alignment() == 1); - EXPECT(offset == 0); + EXPECT_EQ(pool.size(), 1u); + EXPECT_EQ(pool.alignment(), 1u); + EXPECT_EQ(offset, 0u); pool.add(bytes, 2, offset); - EXPECT(pool.size() == 4); - EXPECT(pool.alignment() == 2); - EXPECT(offset == 2); + EXPECT_EQ(pool.size(), 4u); + EXPECT_EQ(pool.alignment(), 2u); + EXPECT_EQ(offset, 2u); pool.add(bytes, 4, offset); - EXPECT(pool.size() == 8); - EXPECT(pool.alignment() == 4); - EXPECT(offset == 4); + EXPECT_EQ(pool.size(), 8u); + EXPECT_EQ(pool.alignment(), 4u); + EXPECT_EQ(offset, 4u); pool.add(bytes, 4, offset); - EXPECT(pool.size() == 8); - EXPECT(pool.alignment() == 4); - EXPECT(offset == 4); + EXPECT_EQ(pool.size(), 8u); + EXPECT_EQ(pool.alignment(), 4u); + EXPECT_EQ(offset, 4u); pool.add(bytes, 32, offset); - EXPECT(pool.size() == 64); - EXPECT(pool.alignment() == 32); - EXPECT(offset == 32); + EXPECT_EQ(pool.size(), 64u); + EXPECT_EQ(pool.alignment(), 32u); + EXPECT_EQ(offset, 32u); } } #endif diff --git a/3rdparty/asmjit/src/asmjit/core/constpool.h b/3rdparty/asmjit/src/asmjit/core/constpool.h index 32b84b1065d..673c11d6a93 100644 --- a/3rdparty/asmjit/src/asmjit/core/constpool.h +++ b/3rdparty/asmjit/src/asmjit/core/constpool.h @@ -27,6 +27,9 @@ enum class ConstPoolScope : uint32_t { }; //! Constant pool. +//! +//! Constant pool is designed to hold 1, 2, 4, 8, 16, 32, and 64 byte constants. It's not designed to hold constants +//! having arbitrary length like strings and arrays. class ConstPool { public: ASMJIT_NONCOPYABLE(ConstPool) @@ -65,12 +68,12 @@ public: //! Data offset from the beginning of the pool. uint32_t _offset; - inline Node(size_t offset, bool shared) noexcept + ASMJIT_INLINE_NODEBUG Node(size_t offset, bool shared) noexcept : ZoneTreeNodeT<Node>(), _shared(shared), _offset(uint32_t(offset)) {} - inline void* data() const noexcept { + ASMJIT_INLINE_NODEBUG void* data() const noexcept { return static_cast<void*>(const_cast<ConstPool::Node*>(this) + 1); } }; @@ -80,14 +83,14 @@ public: public: size_t _dataSize; - inline Compare(size_t dataSize) noexcept + ASMJIT_INLINE_NODEBUG Compare(size_t dataSize) noexcept : _dataSize(dataSize) {} - inline int operator()(const Node& a, const Node& b) const noexcept { + ASMJIT_INLINE_NODEBUG int operator()(const Node& a, const Node& b) const noexcept { return ::memcmp(a.data(), b.data(), _dataSize); } - inline int operator()(const Node& a, const void* data) const noexcept { + ASMJIT_INLINE_NODEBUG int operator()(const Node& a, const void* data) const noexcept { return ::memcmp(a.data(), data, _dataSize); } }; @@ -101,30 +104,30 @@ public: //! Size of the data. size_t _dataSize; - inline explicit Tree(size_t dataSize = 0) noexcept + ASMJIT_INLINE_NODEBUG explicit Tree(size_t dataSize = 0) noexcept : _tree(), _size(0), _dataSize(dataSize) {} - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _tree.reset(); _size = 0; } - inline bool empty() const noexcept { return _size == 0; } - inline size_t size() const noexcept { return _size; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; } + ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; } inline void setDataSize(size_t dataSize) noexcept { ASMJIT_ASSERT(empty()); _dataSize = dataSize; } - inline Node* get(const void* data) noexcept { + ASMJIT_INLINE_NODEBUG Node* get(const void* data) noexcept { Compare cmp(_dataSize); return _tree.get(data, cmp); } - inline void insert(Node* node) noexcept { + ASMJIT_INLINE_NODEBUG void insert(Node* node) noexcept { Compare cmp(_dataSize); _tree.insert(node, cmp); _size++; @@ -167,7 +170,7 @@ public: Node* node = zone->allocT<Node>(sizeof(Node) + size); if (ASMJIT_UNLIKELY(!node)) return nullptr; - node = new(node) Node(offset, shared); + node = new(Support::PlacementNew{node}) Node(offset, shared); memcpy(node->data(), data, size); return node; } @@ -199,9 +202,17 @@ public: //! \name Construction & Destruction //! \{ - ASMJIT_API ConstPool(Zone* zone) noexcept; + //! Creates a new constant pool that would use `zone` as a memory allocator. + ASMJIT_API explicit ConstPool(Zone* zone) noexcept; + //! Destroys this constant pool. ASMJIT_API ~ConstPool() noexcept; + //! \} + + //! \name Reset + //! \{ + + //! Resets this constant pool and its allocator to `zone`. ASMJIT_API void reset(Zone* zone) noexcept; //! \} @@ -210,13 +221,13 @@ public: //! \{ //! Tests whether the constant-pool is empty. - inline bool empty() const noexcept { return _size == 0; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; } //! Returns the size of the constant-pool in bytes. - inline size_t size() const noexcept { return _size; } + ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; } //! Returns minimum alignment. - inline size_t alignment() const noexcept { return _alignment; } + ASMJIT_INLINE_NODEBUG size_t alignment() const noexcept { return _alignment; } //! Returns the minimum size of all items added to the constant pool. - inline size_t minItemSize() const noexcept { return _minItemSize; } + ASMJIT_INLINE_NODEBUG size_t minItemSize() const noexcept { return _minItemSize; } //! \} diff --git a/3rdparty/asmjit/src/asmjit/core/cpuinfo.cpp b/3rdparty/asmjit/src/asmjit/core/cpuinfo.cpp index 7bf7407f005..88f85e0f82e 100644 --- a/3rdparty/asmjit/src/asmjit/core/cpuinfo.cpp +++ b/3rdparty/asmjit/src/asmjit/core/cpuinfo.cpp @@ -7,31 +7,93 @@ #include "../core/cpuinfo.h" #include "../core/support.h" -#if !defined(_WIN32) - #include <errno.h> - #include <sys/utsname.h> - #include <unistd.h> -#endif +#include <atomic> -// Required by `getauxval()` on Linux. -#if defined(__linux__) - #include <sys/auxv.h> -#endif +// Required by `__cpuidex()` and `_xgetbv()`. +#if ASMJIT_ARCH_X86 + #if defined(_MSC_VER) + #include <intrin.h> + #endif +#endif // ASMJIT_ARCH_X86 -//! Required to detect CPU and features on Apple platforms. -#if defined(__APPLE__) - #include <mach/machine.h> - #include <sys/types.h> - #include <sys/sysctl.h> +#if ASMJIT_ARCH_ARM + // Required by various utilities that are required by features detection. + #if !defined(_WIN32) + #include <errno.h> + #include <sys/utsname.h> + #endif + + //! Required to detect CPU and features on Apple platforms. + #if defined(__APPLE__) + #include <mach/machine.h> + #include <sys/types.h> + #include <sys/sysctl.h> + #endif + + #if (defined(__linux__) || defined(__FreeBSD__)) + // Required by `getauxval()` on Linux and FreeBSD. + #include <sys/auxv.h> + #define ASMJIT_ARM_DETECT_VIA_HWCAPS + #endif + + #if ASMJIT_ARCH_ARM >= 64 && defined(__GNUC__) && defined(__linux__) && 0 + // This feature is disabled at the moment - it works, but it seems linux supports ARM features + // via HWCAPS pretty well and the most recent features need to access more registers that were + // not originally accessible, which would break on some systems. + #define ASMJIT_ARM_DETECT_VIA_CPUID + #endif + + #if ASMJIT_ARCH_ARM >= 64 && defined(__OpenBSD__) + #include <sys/sysctl.h> + #include <machine/cpu.h> + #endif +#endif // ASMJIT_ARCH_ARM + +#if !defined(_WIN32) && (ASMJIT_ARCH_X86 || ASMJIT_ARCH_ARM) + #include <unistd.h> #endif -// Required by `__cpuidex()` and `_xgetbv()`. +// Unfortunately when compiling in C++11 mode MSVC would warn about unused functions as +// [[maybe_unused]] attribute is not used in that case (it's used only by C++17 mode and later). #if defined(_MSC_VER) - #include <intrin.h> -#endif + #pragma warning(push) + #pragma warning(disable: 4505) // unreferenced local function has been removed. +#endif // _MSC_VER ASMJIT_BEGIN_NAMESPACE +// CpuInfo - Detect - Compatibility +// ================================ + +// CPU features detection is a minefield on non-X86 platforms. The following list describes which +// operating systems and architectures are supported and the status of the implementation: +// +// * X86, X86_64: +// - All OSes supported +// - Detection is based on using a CPUID instruction, which is a user-space instruction, so there +// is no need to use any OS specific APIs or syscalls to detect all features provided by the CPU. +// +// * ARM32: +// - Linux - HWCAPS based detection. +// - FreeBSD - HWCAPS based detection (shared with Linux code). +// - NetBSD - NOT IMPLEMENTED! +// - OpenBSD - NOT IMPLEMENTED! +// - Apple - sysctlbyname() based detection (this architecture is deprecated on Apple HW). +// - Windows - IsProcessorFeaturePresent() based detection (only detects a subset of features). +// - Others - NOT IMPLEMENTED! +// +// * ARM64: +// - Linux - HWCAPS and CPUID based detection. +// - FreeBSD - HWCAPS and CPUID based detection (shared with Linux code). +// - NetBSD - NOT IMPLEMENTED! +// - OpenBSD - CPUID based detection (reading CPUID via sysctl's CTL_MACHDEP). +// - Apple - sysctlbyname() based detection with FamilyId matrix (record for each family id). +// - Windows - IsProcessorFeaturePresent() based detection (only detects a subset of features). +// - Others - NOT IMPLEMENTED! +// +// * Others +// - NOT IMPLEMENTED! + // CpuInfo - Detect - HW-Thread Count // ================================== @@ -55,8 +117,14 @@ static inline uint32_t detectHWThreadCount() noexcept { // CpuInfo - Detect - X86 // ====================== +// X86 and X86_64 detection is based on CPUID. + #if ASMJIT_ARCH_X86 +namespace x86 { + +typedef CpuFeatures::X86 Ext; + struct cpuid_t { uint32_t eax, ebx, ecx, edx; }; struct xgetbv_t { uint32_t eax, edx; }; @@ -137,7 +205,7 @@ static ASMJIT_FAVOR_SIZE void simplifyCpuBrand(char* s) noexcept { if (!c) break; - if (!(c == ' ' && (prev == '@' || s[1] == ' ' || s[1] == '@'))) { + if (!(c == ' ' && (prev == '@' || s[1] == ' ' || s[1] == '@' || s[1] == '\0'))) { *d++ = c; prev = c; } @@ -160,7 +228,7 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { cpu._maxLogicalProcessors = 1; // We are gonna execute CPUID, which was introduced by I486, so it's the requirement. - features.add(CpuFeatures::X86::kI486); + features.add(Ext::kI486); // CPUID EAX=0 // ----------- @@ -191,40 +259,40 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { if (familyId == 0x0Fu) familyId += ((regs.eax >> 20) & 0xFFu); - cpu._modelId = modelId; - cpu._familyId = familyId; - cpu._brandId = ((regs.ebx ) & 0xFF); - cpu._processorType = ((regs.eax >> 12) & 0x03); - cpu._maxLogicalProcessors = ((regs.ebx >> 16) & 0xFF); - cpu._stepping = ((regs.eax ) & 0x0F); - cpu._cacheLineSize = ((regs.ebx >> 8) & 0xFF) * 8; - - features.addIf(bitTest(regs.ecx, 0), CpuFeatures::X86::kSSE3); - features.addIf(bitTest(regs.ecx, 1), CpuFeatures::X86::kPCLMULQDQ); - features.addIf(bitTest(regs.ecx, 3), CpuFeatures::X86::kMONITOR); - features.addIf(bitTest(regs.ecx, 5), CpuFeatures::X86::kVMX); - features.addIf(bitTest(regs.ecx, 6), CpuFeatures::X86::kSMX); - features.addIf(bitTest(regs.ecx, 9), CpuFeatures::X86::kSSSE3); - features.addIf(bitTest(regs.ecx, 13), CpuFeatures::X86::kCMPXCHG16B); - features.addIf(bitTest(regs.ecx, 19), CpuFeatures::X86::kSSE4_1); - features.addIf(bitTest(regs.ecx, 20), CpuFeatures::X86::kSSE4_2); - features.addIf(bitTest(regs.ecx, 22), CpuFeatures::X86::kMOVBE); - features.addIf(bitTest(regs.ecx, 23), CpuFeatures::X86::kPOPCNT); - features.addIf(bitTest(regs.ecx, 25), CpuFeatures::X86::kAESNI); - features.addIf(bitTest(regs.ecx, 26), CpuFeatures::X86::kXSAVE); - features.addIf(bitTest(regs.ecx, 27), CpuFeatures::X86::kOSXSAVE); - features.addIf(bitTest(regs.ecx, 30), CpuFeatures::X86::kRDRAND); - features.addIf(bitTest(regs.edx, 0), CpuFeatures::X86::kFPU); - features.addIf(bitTest(regs.edx, 4), CpuFeatures::X86::kRDTSC); - features.addIf(bitTest(regs.edx, 5), CpuFeatures::X86::kMSR); - features.addIf(bitTest(regs.edx, 8), CpuFeatures::X86::kCMPXCHG8B); - features.addIf(bitTest(regs.edx, 15), CpuFeatures::X86::kCMOV); - features.addIf(bitTest(regs.edx, 19), CpuFeatures::X86::kCLFLUSH); - features.addIf(bitTest(regs.edx, 23), CpuFeatures::X86::kMMX); - features.addIf(bitTest(regs.edx, 24), CpuFeatures::X86::kFXSR); - features.addIf(bitTest(regs.edx, 25), CpuFeatures::X86::kSSE); - features.addIf(bitTest(regs.edx, 25), CpuFeatures::X86::kSSE, CpuFeatures::X86::kSSE2); - features.addIf(bitTest(regs.edx, 28), CpuFeatures::X86::kMT); + cpu._modelId = modelId; + cpu._familyId = familyId; + cpu._brandId = (regs.ebx) & 0xFF; + cpu._processorType = (regs.eax >> 12) & 0x03; + cpu._maxLogicalProcessors = (regs.ebx >> 16) & 0xFF; + cpu._stepping = (regs.eax) & 0x0F; + cpu._cacheLineSize = ((regs.ebx >> 8) & 0xFF) * 8; + + features.addIf(bitTest(regs.ecx, 0), Ext::kSSE3); + features.addIf(bitTest(regs.ecx, 1), Ext::kPCLMULQDQ); + features.addIf(bitTest(regs.ecx, 3), Ext::kMONITOR); + features.addIf(bitTest(regs.ecx, 5), Ext::kVMX); + features.addIf(bitTest(regs.ecx, 6), Ext::kSMX); + features.addIf(bitTest(regs.ecx, 9), Ext::kSSSE3); + features.addIf(bitTest(regs.ecx, 13), Ext::kCMPXCHG16B); + features.addIf(bitTest(regs.ecx, 19), Ext::kSSE4_1); + features.addIf(bitTest(regs.ecx, 20), Ext::kSSE4_2); + features.addIf(bitTest(regs.ecx, 22), Ext::kMOVBE); + features.addIf(bitTest(regs.ecx, 23), Ext::kPOPCNT); + features.addIf(bitTest(regs.ecx, 25), Ext::kAESNI); + features.addIf(bitTest(regs.ecx, 26), Ext::kXSAVE); + features.addIf(bitTest(regs.ecx, 27), Ext::kOSXSAVE); + features.addIf(bitTest(regs.ecx, 30), Ext::kRDRAND); + features.addIf(bitTest(regs.edx, 0), Ext::kFPU); + features.addIf(bitTest(regs.edx, 4), Ext::kRDTSC); + features.addIf(bitTest(regs.edx, 5), Ext::kMSR); + features.addIf(bitTest(regs.edx, 8), Ext::kCMPXCHG8B); + features.addIf(bitTest(regs.edx, 15), Ext::kCMOV); + features.addIf(bitTest(regs.edx, 19), Ext::kCLFLUSH); + features.addIf(bitTest(regs.edx, 23), Ext::kMMX); + features.addIf(bitTest(regs.edx, 24), Ext::kFXSR); + features.addIf(bitTest(regs.edx, 25), Ext::kSSE, Ext::kMMX2); + features.addIf(bitTest(regs.edx, 26), Ext::kSSE2, Ext::kSSE); + features.addIf(bitTest(regs.edx, 28), Ext::kMT); // Get the content of XCR0 if supported by the CPU and enabled by the OS. if (features.hasXSAVE() && features.hasOSXSAVE()) { @@ -236,9 +304,9 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { // - XCR0[2:1] == 11b // XMM & YMM states need to be enabled by OS. if ((xcr0.eax & 0x00000006u) == 0x00000006u) { - features.add(CpuFeatures::X86::kAVX); - features.addIf(bitTest(regs.ecx, 12), CpuFeatures::X86::kFMA); - features.addIf(bitTest(regs.ecx, 29), CpuFeatures::X86::kF16C); + features.add(Ext::kAVX); + features.addIf(bitTest(regs.ecx, 12), Ext::kFMA); + features.addIf(bitTest(regs.ecx, 29), Ext::kF16C); } } } @@ -270,84 +338,114 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { maybeMPX = bitTest(regs.ebx, 14); maxSubLeafId_0x7 = regs.eax; - features.addIf(bitTest(regs.ebx, 0), CpuFeatures::X86::kFSGSBASE); - features.addIf(bitTest(regs.ebx, 3), CpuFeatures::X86::kBMI); - features.addIf(bitTest(regs.ebx, 4), CpuFeatures::X86::kHLE); - features.addIf(bitTest(regs.ebx, 7), CpuFeatures::X86::kSMEP); - features.addIf(bitTest(regs.ebx, 8), CpuFeatures::X86::kBMI2); - features.addIf(bitTest(regs.ebx, 9), CpuFeatures::X86::kERMS); - features.addIf(bitTest(regs.ebx, 11), CpuFeatures::X86::kRTM); - features.addIf(bitTest(regs.ebx, 18), CpuFeatures::X86::kRDSEED); - features.addIf(bitTest(regs.ebx, 19), CpuFeatures::X86::kADX); - features.addIf(bitTest(regs.ebx, 20), CpuFeatures::X86::kSMAP); - features.addIf(bitTest(regs.ebx, 23), CpuFeatures::X86::kCLFLUSHOPT); - features.addIf(bitTest(regs.ebx, 24), CpuFeatures::X86::kCLWB); - features.addIf(bitTest(regs.ebx, 29), CpuFeatures::X86::kSHA); - features.addIf(bitTest(regs.ecx, 0), CpuFeatures::X86::kPREFETCHWT1); - features.addIf(bitTest(regs.ecx, 4), CpuFeatures::X86::kOSPKE); - features.addIf(bitTest(regs.ecx, 5), CpuFeatures::X86::kWAITPKG); - features.addIf(bitTest(regs.ecx, 7), CpuFeatures::X86::kCET_SS); - features.addIf(bitTest(regs.ecx, 8), CpuFeatures::X86::kGFNI); - features.addIf(bitTest(regs.ecx, 9), CpuFeatures::X86::kVAES); - features.addIf(bitTest(regs.ecx, 10), CpuFeatures::X86::kVPCLMULQDQ); - features.addIf(bitTest(regs.ecx, 22), CpuFeatures::X86::kRDPID); - features.addIf(bitTest(regs.ecx, 25), CpuFeatures::X86::kCLDEMOTE); - features.addIf(bitTest(regs.ecx, 27), CpuFeatures::X86::kMOVDIRI); - features.addIf(bitTest(regs.ecx, 28), CpuFeatures::X86::kMOVDIR64B); - features.addIf(bitTest(regs.ecx, 29), CpuFeatures::X86::kENQCMD); - features.addIf(bitTest(regs.edx, 5), CpuFeatures::X86::kUINTR); - features.addIf(bitTest(regs.edx, 14), CpuFeatures::X86::kSERIALIZE); - features.addIf(bitTest(regs.edx, 16), CpuFeatures::X86::kTSXLDTRK); - features.addIf(bitTest(regs.edx, 18), CpuFeatures::X86::kPCONFIG); - features.addIf(bitTest(regs.edx, 20), CpuFeatures::X86::kCET_IBT); + features.addIf(bitTest(regs.ebx, 0), Ext::kFSGSBASE); + features.addIf(bitTest(regs.ebx, 3), Ext::kBMI); + features.addIf(bitTest(regs.ebx, 4), Ext::kHLE); + features.addIf(bitTest(regs.ebx, 7), Ext::kSMEP); + features.addIf(bitTest(regs.ebx, 8), Ext::kBMI2); + features.addIf(bitTest(regs.ebx, 9), Ext::kERMS); + features.addIf(bitTest(regs.ebx, 11), Ext::kRTM); + features.addIf(bitTest(regs.ebx, 18), Ext::kRDSEED); + features.addIf(bitTest(regs.ebx, 19), Ext::kADX); + features.addIf(bitTest(regs.ebx, 20), Ext::kSMAP); + features.addIf(bitTest(regs.ebx, 23), Ext::kCLFLUSHOPT); + features.addIf(bitTest(regs.ebx, 24), Ext::kCLWB); + features.addIf(bitTest(regs.ebx, 29), Ext::kSHA); + features.addIf(bitTest(regs.ecx, 0), Ext::kPREFETCHWT1); + features.addIf(bitTest(regs.ecx, 4), Ext::kOSPKE); + features.addIf(bitTest(regs.ecx, 5), Ext::kWAITPKG); + features.addIf(bitTest(regs.ecx, 7), Ext::kCET_SS); + features.addIf(bitTest(regs.ecx, 8), Ext::kGFNI); + features.addIf(bitTest(regs.ecx, 9), Ext::kVAES); + features.addIf(bitTest(regs.ecx, 10), Ext::kVPCLMULQDQ); + features.addIf(bitTest(regs.ecx, 22), Ext::kRDPID); + features.addIf(bitTest(regs.ecx, 25), Ext::kCLDEMOTE); + features.addIf(bitTest(regs.ecx, 27), Ext::kMOVDIRI); + features.addIf(bitTest(regs.ecx, 28), Ext::kMOVDIR64B); + features.addIf(bitTest(regs.ecx, 29), Ext::kENQCMD); + features.addIf(bitTest(regs.edx, 4), Ext::kFSRM); + features.addIf(bitTest(regs.edx, 5), Ext::kUINTR); + features.addIf(bitTest(regs.edx, 14), Ext::kSERIALIZE); + features.addIf(bitTest(regs.edx, 16), Ext::kTSXLDTRK); + features.addIf(bitTest(regs.edx, 18), Ext::kPCONFIG); + features.addIf(bitTest(regs.edx, 20), Ext::kCET_IBT); // Detect 'TSX' - Requires at least one of `HLE` and `RTM` features. - if (features.hasHLE() || features.hasRTM()) - features.add(CpuFeatures::X86::kTSX); + if (features.hasHLE() || features.hasRTM()) { + features.add(Ext::kTSX); + } - // Detect 'AVX2' - Requires AVX as well. - if (bitTest(regs.ebx, 5) && features.hasAVX()) - features.add(CpuFeatures::X86::kAVX2); + if (bitTest(regs.ebx, 5) && features.hasAVX()) { + features.add(Ext::kAVX2); + } - // Detect 'AVX512'. if (avx512EnabledByOS && bitTest(regs.ebx, 16)) { - features.add(CpuFeatures::X86::kAVX512_F); - - features.addIf(bitTest(regs.ebx, 17), CpuFeatures::X86::kAVX512_DQ); - features.addIf(bitTest(regs.ebx, 21), CpuFeatures::X86::kAVX512_IFMA); - features.addIf(bitTest(regs.ebx, 26), CpuFeatures::X86::kAVX512_PFI); - features.addIf(bitTest(regs.ebx, 27), CpuFeatures::X86::kAVX512_ERI); - features.addIf(bitTest(regs.ebx, 28), CpuFeatures::X86::kAVX512_CDI); - features.addIf(bitTest(regs.ebx, 30), CpuFeatures::X86::kAVX512_BW); - features.addIf(bitTest(regs.ebx, 31), CpuFeatures::X86::kAVX512_VL); - features.addIf(bitTest(regs.ecx, 1), CpuFeatures::X86::kAVX512_VBMI); - features.addIf(bitTest(regs.ecx, 6), CpuFeatures::X86::kAVX512_VBMI2); - features.addIf(bitTest(regs.ecx, 11), CpuFeatures::X86::kAVX512_VNNI); - features.addIf(bitTest(regs.ecx, 12), CpuFeatures::X86::kAVX512_BITALG); - features.addIf(bitTest(regs.ecx, 14), CpuFeatures::X86::kAVX512_VPOPCNTDQ); - features.addIf(bitTest(regs.edx, 2), CpuFeatures::X86::kAVX512_4VNNIW); - features.addIf(bitTest(regs.edx, 3), CpuFeatures::X86::kAVX512_4FMAPS); - features.addIf(bitTest(regs.edx, 8), CpuFeatures::X86::kAVX512_VP2INTERSECT); - features.addIf(bitTest(regs.edx, 23), CpuFeatures::X86::kAVX512_FP16); + features.add(Ext::kAVX512_F); + + features.addIf(bitTest(regs.ebx, 17), Ext::kAVX512_DQ); + features.addIf(bitTest(regs.ebx, 21), Ext::kAVX512_IFMA); + features.addIf(bitTest(regs.ebx, 26), Ext::kAVX512_PF); + features.addIf(bitTest(regs.ebx, 27), Ext::kAVX512_ER); + features.addIf(bitTest(regs.ebx, 28), Ext::kAVX512_CD); + features.addIf(bitTest(regs.ebx, 30), Ext::kAVX512_BW); + features.addIf(bitTest(regs.ebx, 31), Ext::kAVX512_VL); + features.addIf(bitTest(regs.ecx, 1), Ext::kAVX512_VBMI); + features.addIf(bitTest(regs.ecx, 6), Ext::kAVX512_VBMI2); + features.addIf(bitTest(regs.ecx, 11), Ext::kAVX512_VNNI); + features.addIf(bitTest(regs.ecx, 12), Ext::kAVX512_BITALG); + features.addIf(bitTest(regs.ecx, 14), Ext::kAVX512_VPOPCNTDQ); + features.addIf(bitTest(regs.edx, 2), Ext::kAVX512_4VNNIW); + features.addIf(bitTest(regs.edx, 3), Ext::kAVX512_4FMAPS); + features.addIf(bitTest(regs.edx, 8), Ext::kAVX512_VP2INTERSECT); + features.addIf(bitTest(regs.edx, 23), Ext::kAVX512_FP16); } - // Detect 'AMX'. if (amxEnabledByOS) { - features.addIf(bitTest(regs.edx, 22), CpuFeatures::X86::kAMX_BF16); - features.addIf(bitTest(regs.edx, 24), CpuFeatures::X86::kAMX_TILE); - features.addIf(bitTest(regs.edx, 25), CpuFeatures::X86::kAMX_INT8); + features.addIf(bitTest(regs.edx, 22), Ext::kAMX_BF16); + features.addIf(bitTest(regs.edx, 24), Ext::kAMX_TILE); + features.addIf(bitTest(regs.edx, 25), Ext::kAMX_INT8); } } // CPUID EAX=7 ECX=1 // ----------------- - if (features.hasAVX512_F() && maxSubLeafId_0x7 >= 1) { + if (maxSubLeafId_0x7 >= 1) { cpuidQuery(®s, 0x7, 1); - features.addIf(bitTest(regs.eax, 3), CpuFeatures::X86::kAVX_VNNI); - features.addIf(bitTest(regs.eax, 5), CpuFeatures::X86::kAVX512_BF16); - features.addIf(bitTest(regs.eax, 22), CpuFeatures::X86::kHRESET); + features.addIf(bitTest(regs.eax, 0), Ext::kSHA512); + features.addIf(bitTest(regs.eax, 1), Ext::kSM3); + features.addIf(bitTest(regs.eax, 2), Ext::kSM4); + features.addIf(bitTest(regs.eax, 3), Ext::kRAO_INT); + features.addIf(bitTest(regs.eax, 7), Ext::kCMPCCXADD); + features.addIf(bitTest(regs.eax, 10), Ext::kFZRM); + features.addIf(bitTest(regs.eax, 11), Ext::kFSRS); + features.addIf(bitTest(regs.eax, 12), Ext::kFSRC); + features.addIf(bitTest(regs.eax, 19), Ext::kWRMSRNS); + features.addIf(bitTest(regs.eax, 22), Ext::kHRESET); + features.addIf(bitTest(regs.eax, 26), Ext::kLAM); + features.addIf(bitTest(regs.eax, 27), Ext::kMSRLIST); + features.addIf(bitTest(regs.ebx, 1), Ext::kTSE); + features.addIf(bitTest(regs.edx, 14), Ext::kPREFETCHI); + features.addIf(bitTest(regs.edx, 18), Ext::kCET_SSS); + features.addIf(bitTest(regs.edx, 21), Ext::kAPX_F); + + if (features.hasAVX2()) { + features.addIf(bitTest(regs.eax, 4), Ext::kAVX_VNNI); + features.addIf(bitTest(regs.eax, 23), Ext::kAVX_IFMA); + features.addIf(bitTest(regs.edx, 4), Ext::kAVX_VNNI_INT8); + features.addIf(bitTest(regs.edx, 5), Ext::kAVX_NE_CONVERT); + features.addIf(bitTest(regs.edx, 10), Ext::kAVX_VNNI_INT16); + } + + if (features.hasAVX512_F()) { + features.addIf(bitTest(regs.eax, 5), Ext::kAVX512_BF16); + } + + if (amxEnabledByOS) { + features.addIf(bitTest(regs.eax, 21), Ext::kAMX_FP16); + features.addIf(bitTest(regs.edx, 8), Ext::kAMX_COMPLEX); + } } // CPUID EAX=13 ECX=0 @@ -358,13 +456,13 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { // Both CPUID result and XCR0 has to be enabled to have support for MPX. if (((regs.eax & xcr0.eax) & 0x00000018u) == 0x00000018u && maybeMPX) - features.add(CpuFeatures::X86::kMPX); + features.add(Ext::kMPX); cpuidQuery(®s, 0xD, 1); - features.addIf(bitTest(regs.eax, 0), CpuFeatures::X86::kXSAVEOPT); - features.addIf(bitTest(regs.eax, 1), CpuFeatures::X86::kXSAVEC); - features.addIf(bitTest(regs.eax, 3), CpuFeatures::X86::kXSAVES); + features.addIf(bitTest(regs.eax, 0), Ext::kXSAVEOPT); + features.addIf(bitTest(regs.eax, 1), Ext::kXSAVEC); + features.addIf(bitTest(regs.eax, 3), Ext::kXSAVES); } // CPUID EAX=14 ECX=0 @@ -373,7 +471,7 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { if (maxId >= 0xE) { cpuidQuery(®s, 0xE, 0); - features.addIf(bitTest(regs.ebx, 4), CpuFeatures::X86::kPTWRITE); + features.addIf(bitTest(regs.ebx, 4), Ext::kPTWRITE); } // CPUID EAX=0x80000000...maxId @@ -396,32 +494,32 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { break; case 0x80000001u: - features.addIf(bitTest(regs.ecx, 0), CpuFeatures::X86::kLAHFSAHF); - features.addIf(bitTest(regs.ecx, 2), CpuFeatures::X86::kSVM); - features.addIf(bitTest(regs.ecx, 5), CpuFeatures::X86::kLZCNT); - features.addIf(bitTest(regs.ecx, 6), CpuFeatures::X86::kSSE4A); - features.addIf(bitTest(regs.ecx, 7), CpuFeatures::X86::kMSSE); - features.addIf(bitTest(regs.ecx, 8), CpuFeatures::X86::kPREFETCHW); - features.addIf(bitTest(regs.ecx, 12), CpuFeatures::X86::kSKINIT); - features.addIf(bitTest(regs.ecx, 15), CpuFeatures::X86::kLWP); - features.addIf(bitTest(regs.ecx, 21), CpuFeatures::X86::kTBM); - features.addIf(bitTest(regs.ecx, 29), CpuFeatures::X86::kMONITORX); - features.addIf(bitTest(regs.edx, 20), CpuFeatures::X86::kNX); - features.addIf(bitTest(regs.edx, 21), CpuFeatures::X86::kFXSROPT); - features.addIf(bitTest(regs.edx, 22), CpuFeatures::X86::kMMX2); - features.addIf(bitTest(regs.edx, 27), CpuFeatures::X86::kRDTSCP); - features.addIf(bitTest(regs.edx, 29), CpuFeatures::X86::kPREFETCHW); - features.addIf(bitTest(regs.edx, 30), CpuFeatures::X86::k3DNOW2, CpuFeatures::X86::kMMX2); - features.addIf(bitTest(regs.edx, 31), CpuFeatures::X86::kPREFETCHW); + features.addIf(bitTest(regs.ecx, 0), Ext::kLAHFSAHF); + features.addIf(bitTest(regs.ecx, 2), Ext::kSVM); + features.addIf(bitTest(regs.ecx, 5), Ext::kLZCNT); + features.addIf(bitTest(regs.ecx, 6), Ext::kSSE4A); + features.addIf(bitTest(regs.ecx, 7), Ext::kMSSE); + features.addIf(bitTest(regs.ecx, 8), Ext::kPREFETCHW); + features.addIf(bitTest(regs.ecx, 12), Ext::kSKINIT); + features.addIf(bitTest(regs.ecx, 15), Ext::kLWP); + features.addIf(bitTest(regs.ecx, 21), Ext::kTBM); + features.addIf(bitTest(regs.ecx, 29), Ext::kMONITORX); + features.addIf(bitTest(regs.edx, 20), Ext::kNX); + features.addIf(bitTest(regs.edx, 21), Ext::kFXSROPT); + features.addIf(bitTest(regs.edx, 22), Ext::kMMX2); + features.addIf(bitTest(regs.edx, 27), Ext::kRDTSCP); + features.addIf(bitTest(regs.edx, 29), Ext::kPREFETCHW); + features.addIf(bitTest(regs.edx, 30), Ext::k3DNOW2, Ext::kMMX2); + features.addIf(bitTest(regs.edx, 31), Ext::kPREFETCHW); if (features.hasAVX()) { - features.addIf(bitTest(regs.ecx, 11), CpuFeatures::X86::kXOP); - features.addIf(bitTest(regs.ecx, 16), CpuFeatures::X86::kFMA4); + features.addIf(bitTest(regs.ecx, 11), Ext::kXOP); + features.addIf(bitTest(regs.ecx, 16), Ext::kFMA4); } // This feature seems to be only supported by AMD. if (cpu.isVendor("AMD")) { - features.addIf(bitTest(regs.ecx, 4), CpuFeatures::X86::kALTMOVCR8); + features.addIf(bitTest(regs.ecx, 4), Ext::kALTMOVCR8); } break; @@ -439,17 +537,21 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { break; case 0x80000008u: - features.addIf(bitTest(regs.ebx, 0), CpuFeatures::X86::kCLZERO); - features.addIf(bitTest(regs.ebx, 0), CpuFeatures::X86::kRDPRU); - features.addIf(bitTest(regs.ebx, 8), CpuFeatures::X86::kMCOMMIT); - features.addIf(bitTest(regs.ebx, 9), CpuFeatures::X86::kWBNOINVD); + features.addIf(bitTest(regs.ebx, 0), Ext::kCLZERO); + features.addIf(bitTest(regs.ebx, 0), Ext::kRDPRU); + features.addIf(bitTest(regs.ebx, 8), Ext::kMCOMMIT); + features.addIf(bitTest(regs.ebx, 9), Ext::kWBNOINVD); // Go directly to the next one we are interested in. i = 0x8000001Fu - 1; break; case 0x8000001Fu: - features.addIf(bitTest(regs.eax, 4), CpuFeatures::X86::kSNP); + features.addIf(bitTest(regs.eax, 0), Ext::kSME); + features.addIf(bitTest(regs.eax, 1), Ext::kSEV); + features.addIf(bitTest(regs.eax, 3), Ext::kSEV_ES); + features.addIf(bitTest(regs.eax, 4), Ext::kSEV_SNP); + features.addIf(bitTest(regs.eax, 6), Ext::kRMPQUERY); break; } } while (++i <= maxId); @@ -458,11 +560,17 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { simplifyCpuBrand(cpu._brand.str); } +} // {x86} + #endif // ASMJIT_ARCH_X86 // CpuInfo - Detect - ARM // ====================== +// Implement the most code outside the platform specific #ifdefs to minimize breaking the detection on +// platforms that don't run on our CI infrastructure. The problem with the detection is that every OS +// requires a specific implementation as ARM features cannot be detected in user-mode without OS enablement. + // The most relevant and accurate information can be found here: // https://github.com/llvm-project/llvm/blob/master/lib/Target/AArch64/AArch64.td // https://github.com/apple/llvm-project/blob/apple/main/llvm/lib/Target/AArch64/AArch64.td (Apple fork) @@ -470,277 +578,921 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { // Other resources: // https://en.wikipedia.org/wiki/AArch64 // https://en.wikipedia.org/wiki/Apple_silicon#List_of_Apple_processors +// https://developer.arm.com/downloads/-/exploration-tools/feature-names-for-a-profile // https://developer.arm.com/architectures/learn-the-architecture/understanding-the-armv8-x-extensions/single-page #if ASMJIT_ARCH_ARM +namespace arm { + +// ARM commonly refers to CPU features using FEAT_ prefix, we use Ext:: to make it compatible with other parts. +typedef CpuFeatures::ARM Ext; + +// CpuInfo - Detect - ARM - OS Kernel Version +// ========================================== + +#if defined(__linux__) +struct UNameKernelVersion { + int parts[3]; + + inline bool atLeast(int major, int minor, int patch = 0) const noexcept { + if (parts[0] >= major) { + if (parts[0] > major) + return true; + + if (parts[1] >= minor) { + if (parts[1] > minor) + return true; + + return parts[2] >= patch; + } + } + + return false; + } +}; + +ASMJIT_MAYBE_UNUSED +static UNameKernelVersion getUNameKernelVersion() noexcept { + UNameKernelVersion ver{}; + ver.parts[0] = -1; + + utsname buffer; + if (uname(&buffer) != 0) + return ver; + + size_t count = 0; + char* p = buffer.release; + while (*p) { + uint32_t c = uint8_t(*p); + if (c >= uint32_t('0') && c <= uint32_t('9')) { + ver.parts[count] = int(strtol(p, &p, 10)); + if (++count == 3) + break; + } + else if (c == '.' || c == '-') { + p++; + } + else { + break; + } + } + + return ver; +} +#endif // __linux__ + +// CpuInfo - Detect - ARM - Baseline Features of ARM Architectures +// =============================================================== + +ASMJIT_MAYBE_UNUSED +static inline void populateBaseAArch32Features(CpuFeatures::ARM& features) noexcept { + // No baseline flags at the moment. + DebugUtils::unused(features); +} + +ASMJIT_MAYBE_UNUSED +static inline void populateBaseAArch64Features(CpuFeatures::ARM& features) noexcept { + // AArch64 is based on ARMv8.0 and later. + features.add(Ext::kARMv6); + features.add(Ext::kARMv7); + features.add(Ext::kARMv8a); + + // AArch64 comes with these features by default. + features.add(Ext::kASIMD); + features.add(Ext::kFP); + features.add(Ext::kIDIVA); +} + static inline void populateBaseARMFeatures(CpuInfo& cpu) noexcept { #if ASMJIT_ARCH_ARM == 32 - // No baseline flags at the moment. - DebugUtils::unused(cpu); + populateBaseAArch32Features(cpu.features().arm()); #else - // AArch64 is based on ARMv8-A and later. - cpu.addFeature(CpuFeatures::ARM::kARMv6); - cpu.addFeature(CpuFeatures::ARM::kARMv7); - cpu.addFeature(CpuFeatures::ARM::kARMv8a); + populateBaseAArch64Features(cpu.features().arm()); +#endif +} - // AArch64 comes with these features by default. - cpu.addFeature(CpuFeatures::ARM::kVFPv2); - cpu.addFeature(CpuFeatures::ARM::kVFPv3); - cpu.addFeature(CpuFeatures::ARM::kVFPv4); - cpu.addFeature(CpuFeatures::ARM::kASIMD); - cpu.addFeature(CpuFeatures::ARM::kIDIVA); +// CpuInfo - Detect - ARM - Mandatory Features of ARM Architectures +// ================================================================ + +// Populates mandatory ARMv8.[v]A features. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void populateARMv8AFeatures(CpuFeatures::ARM& features, uint32_t v) noexcept { + switch (v) { + default: + ASMJIT_FALLTHROUGH; + case 9: // ARMv8.9 + features.add(Ext::kCLRBHB, Ext::kCSSC, Ext::kPRFMSLC, Ext::kSPECRES2, Ext::kRAS2); + ASMJIT_FALLTHROUGH; + case 8: // ARMv8.8 + features.add(Ext::kHBC, Ext::kMOPS, Ext::kNMI); + ASMJIT_FALLTHROUGH; + case 7: // ARMv8.7 + features.add(Ext::kHCX, Ext::kPAN3, Ext::kWFXT, Ext::kXS); + ASMJIT_FALLTHROUGH; + case 6: // ARMv8.6 + features.add(Ext::kAMU1_1, Ext::kBF16, Ext::kECV, Ext::kFGT, Ext::kI8MM); + ASMJIT_FALLTHROUGH; + case 5: // ARMv8.5 + features.add(Ext::kBTI, Ext::kCSV2, Ext::kDPB2, Ext::kFLAGM2, Ext::kFRINTTS, Ext::kSB, Ext::kSPECRES, Ext::kSSBS); + ASMJIT_FALLTHROUGH; + case 4: // ARMv8.4 + features.add(Ext::kAMU1, Ext::kDIT, Ext::kDOTPROD, Ext::kFLAGM, + Ext::kLRCPC2, Ext::kLSE2, Ext::kMPAM, Ext::kNV, + Ext::kSEL2, Ext::kTLBIOS, Ext::kTLBIRANGE, Ext::kTRF); + ASMJIT_FALLTHROUGH; + case 3: // ARMv8.3 + features.add(Ext::kCCIDX, Ext::kFCMA, Ext::kJSCVT, Ext::kLRCPC, Ext::kPAUTH); + ASMJIT_FALLTHROUGH; + case 2: // ARMv8.2 + features.add(Ext::kDPB, Ext::kPAN2, Ext::kRAS, Ext::kUAO); + ASMJIT_FALLTHROUGH; + case 1: // ARMv8.1 + features.add(Ext::kCRC32, Ext::kLOR, Ext::kLSE, Ext::kPAN, Ext::kRDM, Ext::kVHE); + ASMJIT_FALLTHROUGH; + case 0: // ARMv8.0 + features.add(Ext::kASIMD, Ext::kFP, Ext::kIDIVA, Ext::kVFP_D32); + break; + } +} + +// Populates mandatory ARMv9.[v] features. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void populateARMv9AFeatures(CpuFeatures::ARM& features, uint32_t v) noexcept { + populateARMv8AFeatures(features, v <= 4u ? 5u + v : 9u); + + switch (v) { + default: + ASMJIT_FALLTHROUGH; + case 4: // ARMv9.4 - based on ARMv8.9. + ASMJIT_FALLTHROUGH; + case 3: // ARMv9.3 - based on ARMv8.8. + ASMJIT_FALLTHROUGH; + case 2: // ARMv9.2 - based on ARMv8.7. + ASMJIT_FALLTHROUGH; + case 1: // ARMv9.1 - based on ARMv8.6. + ASMJIT_FALLTHROUGH; + case 0: // ARMv9.0 - based on ARMv8.5. + features.add(Ext::kRME, Ext::kSVE, Ext::kSVE2); + break; + } +} + +// CpuInfo - Detect - ARM - CPUID Based Features +// ============================================= + +// This implements detection based on the content of CPUID registers. The following code doesn't actually read any +// of the registers so it's an implementation that can theoretically be tested / used in mocks. + +// Merges a feature that contains 0b1111 when it doesn't exist and starts at 0b0000 when it does. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeatureNA(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, + Ext::Id f0, + Ext::Id f1 = Ext::kNone, + Ext::Id f2 = Ext::kNone, + Ext::Id f3 = Ext::kNone) noexcept { + + uint32_t val = uint32_t((regBits >> offset) & 0xFu); + + // If val == 0b1111 then the feature is not implemented in this case (some early extensions). + if (val == 0xFu) + return; + + if (f0 != Ext::kNone) features.add(f0); + if (f1 != Ext::kNone) features.addIf(val >= 1, f1); + if (f2 != Ext::kNone) features.addIf(val >= 2, f2); + if (f3 != Ext::kNone) features.addIf(val >= 3, f3); +} + +// Merges a feature identified by a single bit at `offset`. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeature1B(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, Ext::Id f1) noexcept { + features.addIf((regBits & (uint64_t(1) << offset)) != 0, f1); +} + +// Merges a feature-list starting from 0b01 when it does (0b00 means feature not supported). +ASMJIT_MAYBE_UNUSED +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeature2B(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, Ext::Id f1, Ext::Id f2, Ext::Id f3) noexcept { + uint32_t val = uint32_t((regBits >> offset) & 0x3u); + + if (f1 != Ext::kNone) features.addIf(val >= 1, f1); + if (f2 != Ext::kNone) features.addIf(val >= 2, f2); + if (f3 != Ext::kNone) features.addIf(val == 3, f3); +} + +// Merges a feature-list starting from 0b0001 when it does (0b0000 means feature not supported). +ASMJIT_MAYBE_UNUSED +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeature4B(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, + Ext::Id f1, + Ext::Id f2 = Ext::kNone, + Ext::Id f3 = Ext::kNone, + Ext::Id f4 = Ext::kNone) noexcept { + + uint32_t val = uint32_t((regBits >> offset) & 0xFu); + + // if val == 0 it means that this feature is not supported. + + if (f1 != Ext::kNone) features.addIf(val >= 1, f1); + if (f2 != Ext::kNone) features.addIf(val >= 2, f2); + if (f3 != Ext::kNone) features.addIf(val >= 3, f3); + if (f4 != Ext::kNone) features.addIf(val >= 4, f4); +} + +// Merges a feature that is identified by an exact bit-combination of 4 bits. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeature4S(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, uint32_t value, Ext::Id f1) noexcept { + features.addIf(uint32_t((regBits >> offset) & 0xFu) == value, f1); +} + +#define MERGE_FEATURE_NA(identifier, reg, offset, ...) mergeAArch64CPUIDFeatureNA(cpu.features().arm(), reg, offset, __VA_ARGS__) +#define MERGE_FEATURE_1B(identifier, reg, offset, ...) mergeAArch64CPUIDFeature1B(cpu.features().arm(), reg, offset, __VA_ARGS__) +#define MERGE_FEATURE_2B(identifier, reg, offset, ...) mergeAArch64CPUIDFeature2B(cpu.features().arm(), reg, offset, __VA_ARGS__) +#define MERGE_FEATURE_4B(identifier, reg, offset, ...) mergeAArch64CPUIDFeature4B(cpu.features().arm(), reg, offset, __VA_ARGS__) +#define MERGE_FEATURE_4S(identifier, reg, offset, ...) mergeAArch64CPUIDFeature4S(cpu.features().arm(), reg, offset, __VA_ARGS__) + +// Detects features based on the content of ID_AA64PFR0_EL1 and ID_AA64PFR1_EL1 registers. +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64PFR0_AA64PFR1(CpuInfo& cpu, uint64_t fpr0, uint64_t fpr1) noexcept { + // ID_AA64PFR0_EL1 + // =============== + + // FP and AdvSIMD bits should match (i.e. if FP features FP16, ASIMD must feature it too). + MERGE_FEATURE_NA("FP bits [19:16]" , fpr0, 16, Ext::kFP, Ext::kFP16); + MERGE_FEATURE_NA("AdvSIMD bits [23:20]" , fpr0, 20, Ext::kASIMD, Ext::kFP16); + /* + MERGE_FEATURE_4B("GIC bits [27:24]" , fpr0, 24, ...); + */ + MERGE_FEATURE_4B("RAS bits [31:28]" , fpr0, 28, Ext::kRAS, Ext::kRAS1_1, Ext::kRAS2); + MERGE_FEATURE_4B("SVE bits [35:32]" , fpr0, 32, Ext::kSVE); + MERGE_FEATURE_4B("SEL2 bits [39:36]" , fpr0, 36, Ext::kSEL2); + MERGE_FEATURE_4B("MPAM bits [43:40]" , fpr0, 40, Ext::kMPAM); + MERGE_FEATURE_4B("AMU bits [47:44]" , fpr0, 44, Ext::kAMU1, Ext::kAMU1_1); + MERGE_FEATURE_4B("DIT bits [51:48]" , fpr0, 48, Ext::kDIT); + MERGE_FEATURE_4B("RME bits [55:52]" , fpr0, 52, Ext::kRME); + MERGE_FEATURE_4B("CSV2 bits [59:56]" , fpr0, 56, Ext::kCSV2, Ext::kCSV2, Ext::kCSV2, Ext::kCSV2_3); + MERGE_FEATURE_4B("CSV3 bits [63:60]" , fpr0, 60, Ext::kCSV3); + + // ID_AA64PFR1_EL1 + // =============== + + MERGE_FEATURE_4B("BT bits [3:0]" , fpr1, 0, Ext::kBTI); + MERGE_FEATURE_4B("SSBS bits [7:4]" , fpr1, 4, Ext::kSSBS, Ext::kSSBS2); + MERGE_FEATURE_4B("MTE bits [11:8]" , fpr1, 8, Ext::kMTE, Ext::kMTE2, Ext::kMTE3); + /* + MERGE_FEATURE_4B("RAS_frac bits [15:12]" , fpr1, 12, ...); + MERGE_FEATURE_4B("MPAM_frac bits [19:16]" , fpr1, 16, ...); + */ + MERGE_FEATURE_4B("SME bits [27:24]" , fpr1, 24, Ext::kSME, Ext::kSME2); + MERGE_FEATURE_4B("RNDR_trap bits [31:28]" , fpr1, 28, Ext::kRNG_TRAP); + /* + MERGE_FEATURE_4B("CSV2_frac bits [35:32]" , fpr1, 32, ...); + */ + MERGE_FEATURE_4B("NMI bits [39:36]" , fpr1, 36, Ext::kNMI); + /* + MERGE_FEATURE_4B("MTE_frac bits [43:40]" , fpr1, 40, ...); + */ + MERGE_FEATURE_4B("GCS bits [47:44]" , fpr1, 44, Ext::kGCS); + MERGE_FEATURE_4B("THE bits [51:48]" , fpr1, 48, Ext::kTHE); + + // MTEX extensions are only available when MTE3 is available. + if (cpu.features().arm().hasMTE3()) + MERGE_FEATURE_4B("MTEX bits [55:52]" , fpr1, 52, Ext::kMTE4); + + /* + MERGE_FEATURE_4B("DF2 bits [59:56]" , fpr1, 56, ...); + */ + MERGE_FEATURE_4B("PFAR bits [63:60]" , fpr1, 60, Ext::kPFAR); + + // ID_AA64PFR0_EL1 + ID_AA64PFR1_EL1 + // ================================= + + uint32_t rasMain = uint32_t((fpr0 >> 28) & 0xFu); + uint32_t rasFrac = uint32_t((fpr1 >> 12) & 0xFu); + + if (rasMain == 1 && rasFrac == 1) { + cpu.features().arm().add(Ext::kRAS1_1); + } + + uint32_t mpamMain = uint32_t((fpr0 >> 40) & 0xFu); + uint32_t mpamFrac = uint32_t((fpr1 >> 16) & 0xFu); + + if (mpamMain || mpamFrac) + cpu.features().arm().add(Ext::kMPAM); +} + +// Detects features based on the content of ID_AA64ISAR0_EL1 and ID_AA64ISAR1_EL1 registers. +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64ISAR0_AA64ISAR1(CpuInfo& cpu, uint64_t isar0, uint64_t isar1) noexcept { + // ID_AA64ISAR0_EL1 + // ================ + + MERGE_FEATURE_4B("AES bits [7:4]" , isar0, 4, Ext::kAES, Ext::kPMULL); + MERGE_FEATURE_4B("SHA1 bits [11:8]" , isar0, 8, Ext::kSHA1); + MERGE_FEATURE_4B("SHA2 bits [15:12]" , isar0, 12, Ext::kSHA256, Ext::kSHA512); + MERGE_FEATURE_4B("CRC32 bits [19:16]" , isar0, 16, Ext::kCRC32); + MERGE_FEATURE_4B("Atomic bits [23:20]" , isar0, 20, Ext::kNone, Ext::kLSE, Ext::kLSE128); + MERGE_FEATURE_4B("TME bits [27:24]" , isar0, 24, Ext::kTME); + MERGE_FEATURE_4B("RDM bits [31:28]" , isar0, 28, Ext::kRDM); + MERGE_FEATURE_4B("SHA3 bits [35:32]" , isar0, 32, Ext::kSHA3); + MERGE_FEATURE_4B("SM3 bits [39:36]" , isar0, 36, Ext::kSM3); + MERGE_FEATURE_4B("SM4 bits [43:40]" , isar0, 40, Ext::kSM4); + MERGE_FEATURE_4B("DP bits [47:44]" , isar0, 44, Ext::kDOTPROD); + MERGE_FEATURE_4B("FHM bits [51:48]" , isar0, 48, Ext::kFHM); + MERGE_FEATURE_4B("TS bits [55:52]" , isar0, 52, Ext::kFLAGM, Ext::kFLAGM2); + /* + MERGE_FEATURE_4B("TLB bits [59:56]" , isar0, 56, ...); + */ + MERGE_FEATURE_4B("RNDR bits [63:60]" , isar0, 60, Ext::kFLAGM, Ext::kRNG); + + // ID_AA64ISAR1_EL1 + // ================ + + MERGE_FEATURE_4B("DPB bits [3:0]" , isar1, 0, Ext::kDPB, Ext::kDPB2); + /* + MERGE_FEATURE_4B("APA bits [7:4]" , isar1, 4, ...); + MERGE_FEATURE_4B("API bits [11:8]" , isar1, 8, ...); + */ + MERGE_FEATURE_4B("JSCVT bits [15:12]" , isar1, 12, Ext::kJSCVT); + MERGE_FEATURE_4B("FCMA bits [19:16]" , isar1, 16, Ext::kFCMA); + MERGE_FEATURE_4B("LRCPC bits [23:20]" , isar1, 20, Ext::kLRCPC, Ext::kLRCPC2, Ext::kLRCPC3); + /* + MERGE_FEATURE_4B("GPA bits [27:24]" , isar1, 24, ...); + MERGE_FEATURE_4B("GPI bits [31:28]" , isar1, 28, ...); + */ + MERGE_FEATURE_4B("FRINTTS bits [35:32]" , isar1, 32, Ext::kFRINTTS); + MERGE_FEATURE_4B("SB bits [39:36]" , isar1, 36, Ext::kSB); + MERGE_FEATURE_4B("SPECRES bits [43:40]" , isar1, 40, Ext::kSPECRES, Ext::kSPECRES2); + MERGE_FEATURE_4B("BF16 bits [47:44]" , isar1, 44, Ext::kBF16, Ext::kEBF16); + MERGE_FEATURE_4B("DGH bits [51:48]" , isar1, 48, Ext::kDGH); + MERGE_FEATURE_4B("I8MM bits [55:52]" , isar1, 52, Ext::kI8MM); + MERGE_FEATURE_4B("XS bits [59:56]" , isar1, 56, Ext::kXS); + MERGE_FEATURE_4B("LS64 bits [63:60]" , isar1, 60, Ext::kLS64, Ext::kLS64_V, Ext::kLS64_ACCDATA); +} + +// Detects features based on the content of ID_AA64ISAR2_EL1 register. +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64ISAR2(CpuInfo& cpu, uint64_t isar2) noexcept { + MERGE_FEATURE_4B("WFxT bits [3:0]" , isar2, 0, Ext::kNone, Ext::kWFXT); + MERGE_FEATURE_4B("RPRES bits [7:4]" , isar2, 4, Ext::kRPRES); + /* + MERGE_FEATURE_4B("GPA3 bits [11:8]" , isar2, 8, ...); + MERGE_FEATURE_4B("APA3 bits [15:12]" , isar2, 12, ...); + */ + MERGE_FEATURE_4B("MOPS bits [19:16]" , isar2, 16, Ext::kMOPS); + MERGE_FEATURE_4B("BC bits [23:20]" , isar2, 20, Ext::kHBC); + MERGE_FEATURE_4B("PAC_frac bits [27:24]" , isar2, 24, Ext::kCONSTPACFIELD); + MERGE_FEATURE_4B("CLRBHB bits [31:28]" , isar2, 28, Ext::kCLRBHB); + MERGE_FEATURE_4B("SYSREG128 bits [35:32]" , isar2, 32, Ext::kSYSREG128); + MERGE_FEATURE_4B("SYSINSTR128 bits [39:36]" , isar2, 36, Ext::kSYSINSTR128); + MERGE_FEATURE_4B("PRFMSLC bits [43:40]" , isar2, 40, Ext::kPRFMSLC); + MERGE_FEATURE_4B("RPRFM bits [51:48]" , isar2, 48, Ext::kRPRFM); + MERGE_FEATURE_4B("CSSC bits [55:52]" , isar2, 52, Ext::kCSSC); + MERGE_FEATURE_4B("LUT bits [59:56]" , isar2, 56, Ext::kLUT); +} + +// TODO: This register is not accessed at the moment. +#if 0 +// Detects features based on the content of ID_AA64ISAR3_EL1register. +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64ISAR3(CpuInfo& cpu, uint64_t isar3) noexcept { + // ID_AA64ISAR3_EL1 + // ================ + + MERGE_FEATURE_4B("CPA bits [3:0]" , isar3, 0, Ext::kCPA, Ext::kCPA2); + MERGE_FEATURE_4B("FAMINMAX bits [7:4]" , isar3, 4, Ext::kFAMINMAX); + MERGE_FEATURE_4B("TLBIW bits [11:8]" , isar3, 8, Ext::kTLBIW); +} #endif + +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64MMFR0(CpuInfo& cpu, uint64_t mmfr0) noexcept { + // ID_AA64MMFR0_EL1 + // ================ + + /* + MERGE_FEATURE_4B("PARange bits [3:0]" , mmfr0, 0, ...); + MERGE_FEATURE_4B("ASIDBits bits [7:4]" , mmfr0, 4, ...); + MERGE_FEATURE_4B("BigEnd bits [11:8]" , mmfr0, 8, ...); + MERGE_FEATURE_4B("SNSMem bits [15:12]" , mmfr0, 12, ...); + MERGE_FEATURE_4B("BigEndEL0 bits [19:16]" , mmfr0, 16, ...); + MERGE_FEATURE_4B("TGran16 bits [23:20]" , mmfr0, 20, ...); + MERGE_FEATURE_4B("TGran64 bits [27:24]" , mmfr0, 24, ...); + MERGE_FEATURE_4B("TGran4 bits [31:28]" , mmfr0, 28, ...); + MERGE_FEATURE_4B("TGran16_2 bits [35:32]" , mmfr0, 32, ...); + MERGE_FEATURE_4B("TGran64_2 bits [39:36]" , mmfr0, 36, ...); + MERGE_FEATURE_4B("TGran4_2 bits [43:40]" , mmfr0, 40, ...); + MERGE_FEATURE_4B("ExS bits [47:44]" , mmfr0, 44, ...); + */ + MERGE_FEATURE_4B("FGT bits [59:56]" , mmfr0, 56, Ext::kFGT, Ext::kFGT2); + MERGE_FEATURE_4B("ECV bits [63:60]" , mmfr0, 60, Ext::kECV); +} + +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64MMFR1(CpuInfo& cpu, uint64_t mmfr1) noexcept { + // ID_AA64MMFR1_EL1 + // ================ + + MERGE_FEATURE_4B("HAFDBS bits [3:0]" , mmfr1, 0, Ext::kHAFDBS, Ext::kNone, Ext::kHAFT, Ext::kHDBSS); + MERGE_FEATURE_4B("VMIDBits bits [7:4]" , mmfr1, 4, Ext::kVMID16); + MERGE_FEATURE_4B("VH bits [11:8]" , mmfr1, 8, Ext::kVHE); + MERGE_FEATURE_4B("HPDS bits [15:12]" , mmfr1, 12, Ext::kHPDS, Ext::kHPDS2); + MERGE_FEATURE_4B("LO bits [19:16]" , mmfr1, 16, Ext::kLOR); + MERGE_FEATURE_4B("PAN bits [23:20]" , mmfr1, 20, Ext::kPAN, Ext::kPAN2, Ext::kPAN3); + /* + MERGE_FEATURE_4B("SpecSEI bits [27:24]" , mmfr1, 24, ...); + */ + MERGE_FEATURE_4B("XNX bits [31:28]" , mmfr1, 28, Ext::kXNX); + /* + MERGE_FEATURE_4B("TWED bits [35:32]" , mmfr1, 32, ...); + MERGE_FEATURE_4B("ETS bits [39:36]" , mmfr1, 36, ...); + */ + MERGE_FEATURE_4B("HCX bits [43:40]" , mmfr1, 40, Ext::kHCX); + MERGE_FEATURE_4B("AFP bits [47:44]" , mmfr1, 44, Ext::kAFP); + /* + MERGE_FEATURE_4B("nTLBPA bits [51:48]" , mmfr1, 48, ...); + MERGE_FEATURE_4B("TIDCP1 bits [55:52]" , mmfr1, 52, ...); + */ + MERGE_FEATURE_4B("CMOW bits [59:56]" , mmfr1, 56, Ext::kCMOW); + MERGE_FEATURE_4B("ECBHB bits [63:60]" , mmfr1, 60, Ext::kECBHB); +} + +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64MMFR2(CpuInfo& cpu, uint64_t mmfr2) noexcept { + // ID_AA64MMFR2_EL1 + // ================ + + /* + MERGE_FEATURE_4B("CnP bits [3:0]" , mmfr2, 0, ...); + */ + MERGE_FEATURE_4B("UAO bits [7:4]" , mmfr2, 4, Ext::kUAO); + /* + MERGE_FEATURE_4B("LSM bits [11:8]" , mmfr2, 8, ...); + MERGE_FEATURE_4B("IESB bits [15:12]" , mmfr2, 12, ...); + */ + MERGE_FEATURE_4B("VARange bits [19:16]" , mmfr2, 16, Ext::kLVA, Ext::kLVA3); + MERGE_FEATURE_4B("CCIDX bits [23:20]" , mmfr2, 20, Ext::kCCIDX); + MERGE_FEATURE_4B("NV bits [27:24]" , mmfr2, 24, Ext::kNV, Ext::kNV2); + /* + MERGE_FEATURE_4B("ST bits [31:28]" , mmfr2, 28, ...); + */ + MERGE_FEATURE_4B("AT bits [35:32]" , mmfr2, 32, Ext::kLSE2); + /* + MERGE_FEATURE_4B("IDS bits [39:36]" , mmfr2, 36, ...); + MERGE_FEATURE_4B("FWB bits [43:40]" , mmfr2, 40, ...); + MERGE_FEATURE_4B("TTL bits [51:48]" , mmfr2, 48, ...); + MERGE_FEATURE_4B("BBM bits [55:52]" , mmfr2, 52, ...); + MERGE_FEATURE_4B("EVT bits [59:56]" , mmfr2, 56, ...); + MERGE_FEATURE_4B("E0PD bits [63:60]" , mmfr2, 60, ...); + */ +} + +// Detects features based on the content of ID_AA64ZFR0_EL1 register. +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64ZFR0(CpuInfo& cpu, uint64_t zfr0) noexcept { + MERGE_FEATURE_4B("SVEver bits [3:0]" , zfr0, 0, Ext::kSVE2, Ext::kSVE2_1); + MERGE_FEATURE_4B("AES bits [7:4]" , zfr0, 4, Ext::kSVE_AES, Ext::kSVE_PMULL128); + MERGE_FEATURE_4B("BitPerm bits [19:16]" , zfr0, 16, Ext::kSVE_BITPERM); + MERGE_FEATURE_4B("BF16 bits [23:20]" , zfr0, 20, Ext::kSVE_BF16, Ext::kSVE_EBF16); + MERGE_FEATURE_4B("B16B16 bits [27:24]" , zfr0, 24, Ext::kSVE_B16B16); + MERGE_FEATURE_4B("SHA3 bits [35:32]" , zfr0, 32, Ext::kSVE_SHA3); + MERGE_FEATURE_4B("SM4 bits [43:40]" , zfr0, 40, Ext::kSVE_SM4); + MERGE_FEATURE_4B("I8MM bits [47:44]" , zfr0, 44, Ext::kSVE_I8MM); + MERGE_FEATURE_4B("F32MM bits [55:52]" , zfr0, 52, Ext::kSVE_F32MM); + MERGE_FEATURE_4B("F64MM bits [59:56]" , zfr0, 56, Ext::kSVE_F64MM); +} + +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64SMFR0(CpuInfo& cpu, uint64_t smfr0) noexcept { + MERGE_FEATURE_1B("SF8DP2 bit [28]" , smfr0, 29, Ext::kSSVE_FP8DOT2); + MERGE_FEATURE_1B("SF8DP4 bit [29]" , smfr0, 29, Ext::kSSVE_FP8DOT4); + MERGE_FEATURE_1B("SF8FMA bit [30]" , smfr0, 30, Ext::kSSVE_FP8FMA); + MERGE_FEATURE_1B("F32F32 bit [32]" , smfr0, 32, Ext::kSME_F32F32); + MERGE_FEATURE_1B("BI32I32 bit [33]" , smfr0, 33, Ext::kSME_BI32I32); + MERGE_FEATURE_1B("B16F32 bit [34]" , smfr0, 34, Ext::kSME_B16F32); + MERGE_FEATURE_1B("F16F32 bit [35]" , smfr0, 35, Ext::kSME_F16F32); + MERGE_FEATURE_4S("I8I32 bits [39:36]" , smfr0, 36, 0xF, Ext::kSME_I8I32); + MERGE_FEATURE_1B("F8F32 bit [40]" , smfr0, 40, Ext::kSME_F8F32); + MERGE_FEATURE_1B("F8F16 bit [41]" , smfr0, 41, Ext::kSME_F8F16); + MERGE_FEATURE_1B("F16F16 bit [42]" , smfr0, 42, Ext::kSME_F16F16); + MERGE_FEATURE_1B("B16B16 bit [43]" , smfr0, 43, Ext::kSME_B16B16); + MERGE_FEATURE_4S("I16I32 bits [47:44]" , smfr0, 44, 0x5, Ext::kSME_I16I32); + MERGE_FEATURE_1B("F64F64 bit [48]" , smfr0, 48, Ext::kSME_F64F64); + MERGE_FEATURE_4S("I16I64 bits [55:52]" , smfr0, 52, 0xF, Ext::kSME_I16I64); + MERGE_FEATURE_4B("SMEver bits [59:56]" , smfr0, 56, Ext::kSME2, Ext::kSME2_1); + MERGE_FEATURE_1B("LUTv2 bit [60]" , smfr0, 60, Ext::kSME_LUTv2); + MERGE_FEATURE_1B("FA64 bit [63]" , smfr0, 63, Ext::kSME_FA64); +} + +#undef MERGE_FEATURE_4S +#undef MERGE_FEATURE_4B +#undef MERGE_FEATURE_2B +#undef MERGE_FEATURE_1B +#undef MERGE_FEATURE_NA + +// CpuInfo - Detect - ARM - CPU Vendor Features +// ============================================ + +// CPU features detection based on Apple family ID. +enum class AppleFamilyId : uint32_t { + // Apple design. + kSWIFT = 0x1E2D6381u, // Apple A6/A6X (ARMv7s). + kCYCLONE = 0x37A09642u, // Apple A7 (ARMv8.0-A). + kTYPHOON = 0x2C91A47Eu, // Apple A8 (ARMv8.0-A). + kTWISTER = 0x92FB37C8u, // Apple A9 (ARMv8.0-A). + kHURRICANE = 0x67CEEE93u, // Apple A10 (ARMv8.1-A). + kMONSOON_MISTRAL = 0xE81E7EF6u, // Apple A11 (ARMv8.2-A). + kVORTEX_TEMPEST = 0x07D34B9Fu, // Apple A12 (ARMv8.3-A). + kLIGHTNING_THUNDER = 0x462504D2u, // Apple A13 (ARMv8.4-A). + kFIRESTORM_ICESTORM = 0x1B588BB3u, // Apple A14/M1 (ARMv8.5-A). + kAVALANCHE_BLIZZARD = 0XDA33D83Du, // Apple A15/M2. + kEVEREST_SAWTOOTH = 0X8765EDEAu // Apple A16. +}; + +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE bool detectARMFeaturesViaAppleFamilyId(CpuInfo& cpu) noexcept { + typedef AppleFamilyId Id; + CpuFeatures::ARM& features = cpu.features().arm(); + + switch (cpu.familyId()) { + // Apple A7-A9 (ARMv8.0-A). + case uint32_t(Id::kCYCLONE): + case uint32_t(Id::kTYPHOON): + case uint32_t(Id::kTWISTER): + populateARMv8AFeatures(features, 0); + features.add(Ext::kAES, Ext::kPMU, Ext::kPMULL, Ext::kSHA1, Ext::kSHA256); + return true; + + // Apple A10 (ARMv8.0-A). + case uint32_t(Id::kHURRICANE): + populateARMv8AFeatures(features, 0); + features.add(Ext::kAES, Ext::kCRC32, Ext::kLOR, Ext::kPAN, Ext::kPMU, Ext::kPMULL, Ext::kRDM, Ext::kSHA1, + Ext::kSHA256, Ext::kVHE); + return true; + + // Apple A11 (ARMv8.2-A). + case uint32_t(Id::kMONSOON_MISTRAL): + populateARMv8AFeatures(features, 2); + features.add(Ext::kAES, Ext::kFP16, Ext::kFP16CONV, Ext::kPMU, Ext::kPMULL, Ext::kSHA1, Ext::kSHA256); + return true; + + // Apple A12 (ARMv8.3-A). + case uint32_t(Id::kVORTEX_TEMPEST): + populateARMv8AFeatures(features, 3); + features.add(Ext::kAES, Ext::kFP16, Ext::kFP16CONV, Ext::kPMU, Ext::kPMULL, Ext::kSHA1, Ext::kSHA256); + return true; + + // Apple A13 (ARMv8.4-A). + case uint32_t(Id::kLIGHTNING_THUNDER): + populateARMv8AFeatures(features, 4); + features.add(Ext::kAES, Ext::kFHM, Ext::kFP16, Ext::kFP16CONV, Ext::kPMU, Ext::kPMULL, Ext::kSHA1, + Ext::kSHA256, Ext::kSHA3, Ext::kSHA512); + return true; + + // Apple A14/M1 (ARMv8.5-A). + case uint32_t(Id::kFIRESTORM_ICESTORM): + populateARMv8AFeatures(features, 4); + features.add(Ext::kAES, Ext::kCSV2, Ext::kCSV3, Ext::kDPB2, Ext::kECV, Ext::kFHM, Ext::kFLAGM2, + Ext::kFP16, Ext::kFP16CONV, Ext::kFRINTTS, Ext::kPMU, Ext::kPMULL, Ext::kSB, + Ext::kSHA1, Ext::kSHA256, Ext::kSHA3, Ext::kSHA512, Ext::kSSBS); + return true; + + // Apple A15/M2. + case uint32_t(Id::kAVALANCHE_BLIZZARD): + populateARMv8AFeatures(features, 6); + features.add(Ext::kAES, Ext::kFHM, Ext::kFP16, Ext::kFP16CONV, Ext::kPMU, Ext::kPMULL, Ext::kSHA1, + Ext::kSHA256, Ext::kSHA3, Ext::kSHA512); + return true; + + // Apple A16. + case uint32_t(Id::kEVEREST_SAWTOOTH): + populateARMv8AFeatures(features, 6); + features.add(Ext::kAES, Ext::kFHM, Ext::kFP16, Ext::kFP16CONV, Ext::kHCX, Ext::kPMU, Ext::kPMULL, + Ext::kSHA1, Ext::kSHA256, Ext::kSHA3, Ext::kSHA512); + return true; + + default: + return false; + } } +// CpuInfo - Detect - ARM - Compile Flags Features +// =============================================== + // Detects ARM version by macros defined at compile time. This means that AsmJit will report features forced at // compile time that should always be provided by the target CPU. This also means that if we don't provide any // means to detect CPU features the features reported by AsmJit will at least not report less features than the // target it was compiled to. -ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void detectARMFeaturesViaCompilerFlags(CpuInfo& cpu) noexcept { - DebugUtils::unused(cpu); #if ASMJIT_ARCH_ARM == 32 +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void detectAArch32FeaturesViaCompilerFlags(CpuInfo& cpu) noexcept { + DebugUtils::unused(cpu); // ARM targets have no baseline at the moment. -# if defined(__ARM_ARCH_7A__) +#if defined(__ARM_ARCH_7A__) cpu.addFeature(CpuFeatures::ARM::kARMv7); -# endif -# if defined(__ARM_ARCH_8A__) +#endif + +#if defined(__ARM_ARCH_8A__) cpu.addFeature(CpuFeatures::ARM::kARMv8a); -# endif +#endif -# if defined(__TARGET_ARCH_THUMB) +#if defined(__TARGET_ARCH_THUMB) cpu.addFeature(CpuFeatures::ARM::kTHUMB); -# if __TARGET_ARCH_THUMB >= 4 +#if __TARGET_ARCH_THUMB >= 4 cpu.addFeature(CpuFeatures::ARM::kTHUMBv2); -# endif -# endif - -# if defined(__ARM_FEATURE_FMA) - cpu.addFeature(CpuFeatures::ARM::kVFPv3); - cpu.addFeature(CpuFeatures::ARM::kVFPv4); -# endif - -# if defined(__ARM_NEON) - cpu.addFeature(CpuFeatures::ARM::kASIMD); -# endif - -# if defined(__ARM_FEATURE_IDIV) && defined(__TARGET_ARCH_THUMB) - cpu.addFeature(CpuFeatures::ARM::kIDIVT); #endif -# if defined(__ARM_FEATURE_IDIV) && !defined(__TARGET_ARCH_THUMB) - cpu.addFeature(CpuFeatures::ARM::kIDIVA); -# endif - #endif -#if defined(__ARM_ARCH_8_1A__) - cpu.addFeature(CpuFeatures::ARM::kARMv8_1a); +#if defined(__ARM_FEATURE_FMA) + cpu.addFeature(Ext::kFP); #endif -#if defined(__ARM_ARCH_8_2A__) - cpu.addFeature(CpuFeatures::ARM::kARMv8_2a); -#endif -#if defined(__ARM_ARCH_8_3A__) - cpu.addFeature(CpuFeatures::ARM::kARMv8_3a); -#endif -#if defined(__ARM_ARCH_8_4A__) - cpu.addFeature(CpuFeatures::ARM::kARMv8_4a); + +#if defined(__ARM_NEON) + cpu.addFeature(Ext::kASIMD); #endif -#if defined(__ARM_ARCH_8_5A__) - cpu.addFeature(CpuFeatures::ARM::kARMv8_5a); + +#if defined(__ARM_FEATURE_IDIV) && defined(__TARGET_ARCH_THUMB) + cpu.addFeature(Ext::kIDIVT); #endif -#if defined(__ARM_ARCH_8_6A__) - cpu.addFeature(CpuFeatures::ARM::kARMv8_6a); +#if defined(__ARM_FEATURE_IDIV) && !defined(__TARGET_ARCH_THUMB) + cpu.addFeature(Ext::kIDIVA); #endif -#if defined(__ARM_ARCH_8_7A__) - cpu.addFeature(CpuFeatures::ARM::kARMv8_7a); +} +#endif // ASMJIT_ARCH_ARM == 32 + +#if ASMJIT_ARCH_ARM == 64 +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCompilerFlags(CpuInfo& cpu) noexcept { + DebugUtils::unused(cpu); + +#if defined(__ARM_ARCH_9_5A__) + populateARMv9AFeatures(cpu.features().arm(), 5); +#elif defined(__ARM_ARCH_9_4A__) + populateARMv9AFeatures(cpu.features().arm(), 4); +#elif defined(__ARM_ARCH_9_3A__) + populateARMv9AFeatures(cpu.features().arm(), 3); +#elif defined(__ARM_ARCH_9_2A__) + populateARMv9AFeatures(cpu.features().arm(), 2); +#elif defined(__ARM_ARCH_9_1A__) + populateARMv9AFeatures(cpu.features().arm(), 1); +#elif defined(__ARM_ARCH_9A__) + populateARMv9AFeatures(cpu.features().arm(), 0); +#elif defined(__ARM_ARCH_8_9A__) + populateARMv8AFeatures(cpu.features().arm(), 9); +#elif defined(__ARM_ARCH_8_8A__) + populateARMv8AFeatures(cpu.features().arm(), 8); +#elif defined(__ARM_ARCH_8_7A__) + populateARMv8AFeatures(cpu.features().arm(), 7); +#elif defined(__ARM_ARCH_8_6A__) + populateARMv8AFeatures(cpu.features().arm(), 6); +#elif defined(__ARM_ARCH_8_5A__) + populateARMv8AFeatures(cpu.features().arm(), 5); +#elif defined(__ARM_ARCH_8_4A__) + populateARMv8AFeatures(cpu.features().arm(), 4); +#elif defined(__ARM_ARCH_8_3A__) + populateARMv8AFeatures(cpu.features().arm(), 3); +#elif defined(__ARM_ARCH_8_2A__) + populateARMv8AFeatures(cpu.features().arm(), 2); +#elif defined(__ARM_ARCH_8_1A__) + populateARMv8AFeatures(cpu.features().arm(), 1); +#else + populateARMv8AFeatures(cpu.features().arm(), 0); #endif #if defined(__ARM_FEATURE_AES) - cpu.addFeature(CpuFeatures::ARM::kAES); + cpu.addFeature(Ext::kAES); #endif #if defined(__ARM_FEATURE_BF16_SCALAR_ARITHMETIC) && defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) - cpu.addFeature(CpuFeatures::ARM::kBF16); + cpu.addFeature(Ext::kBF16); #endif #if defined(__ARM_FEATURE_CRC32) - cpu.addFeature(CpuFeatures::ARM::kCRC32); + cpu.addFeature(Ext::kCRC32); #endif #if defined(__ARM_FEATURE_CRYPTO) - cpu.addFeature(CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2); + cpu.addFeature(Ext::kAES, Ext::kSHA1, Ext::kSHA256); #endif #if defined(__ARM_FEATURE_DOTPROD) - cpu.addFeature(CpuFeatures::ARM::kDOTPROD); + cpu.addFeature(Ext::kDOTPROD); #endif #if defined(__ARM_FEATURE_FP16FML) || defined(__ARM_FEATURE_FP16_FML) - cpu.addFeature(CpuFeatures::ARM::kFP16FML); + cpu.addFeature(Ext::kFHM); #endif #if defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC) - cpu.addFeature(CpuFeatures::ARM::kFP16FULL); + cpu.addFeature(Ext::kFP16); #endif #if defined(__ARM_FEATURE_FRINT) - cpu.addFeature(CpuFeatures::ARM::kFRINT); + cpu.addFeature(Ext::kFRINTTS); #endif #if defined(__ARM_FEATURE_JCVT) - cpu.addFeature(CpuFeatures::ARM::kFJCVTZS); + cpu.addFeature(Ext::kJSCVT); #endif #if defined(__ARM_FEATURE_MATMUL_INT8) - cpu.addFeature(CpuFeatures::ARM::kI8MM); + cpu.addFeature(Ext::kI8MM); #endif #if defined(__ARM_FEATURE_ATOMICS) - cpu.addFeature(CpuFeatures::ARM::kLSE); + cpu.addFeature(Ext::kLSE); #endif #if defined(__ARM_FEATURE_MEMORY_TAGGING) - cpu.addFeature(CpuFeatures::ARM::kMTE); + cpu.addFeature(Ext::kMTE); #endif #if defined(__ARM_FEATURE_QRDMX) - cpu.addFeature(CpuFeatures::ARM::kRDM); + cpu.addFeature(Ext::kRDM); #endif #if defined(__ARM_FEATURE_RNG) - cpu.addFeature(CpuFeatures::ARM::kRNG); + cpu.addFeature(Ext::kRNG); #endif #if defined(__ARM_FEATURE_SHA2) - cpu.addFeature(CpuFeatures::ARM::kSHA2); + cpu.addFeature(Ext::kSHA256); #endif #if defined(__ARM_FEATURE_SHA3) - cpu.addFeature(CpuFeatures::ARM::kSHA3); + cpu.addFeature(Ext::kSHA3); #endif #if defined(__ARM_FEATURE_SHA512) - cpu.addFeature(CpuFeatures::ARM::kSHA512); + cpu.addFeature(Ext::kSHA512); #endif #if defined(__ARM_FEATURE_SM3) - cpu.addFeature(CpuFeatures::ARM::kSM3); + cpu.addFeature(Ext::kSM3); #endif #if defined(__ARM_FEATURE_SM4) - cpu.addFeature(CpuFeatures::ARM::kSM4); + cpu.addFeature(Ext::kSM4); #endif #if defined(__ARM_FEATURE_SVE) || defined(__ARM_FEATURE_SVE_VECTOR_OPERATORS) - cpu.addFeature(CpuFeatures::ARM::kSVE); + cpu.addFeature(Ext::kSVE); #endif #if defined(__ARM_FEATURE_SVE_MATMUL_INT8) - cpu.addFeature(CpuFeatures::ARM::kSVE_I8MM); + cpu.addFeature(Ext::kSVE_I8MM); #endif #if defined(__ARM_FEATURE_SVE_MATMUL_FP32) - cpu.addFeature(CpuFeatures::ARM::kSVE_F32MM); + cpu.addFeature(Ext::kSVE_F32MM); #endif #if defined(__ARM_FEATURE_SVE_MATMUL_FP64) - cpu.addFeature(CpuFeatures::ARM::kSVE_F64MM); + cpu.addFeature(Ext::kSVE_F64MM); #endif #if defined(__ARM_FEATURE_SVE2) - cpu.addFeature(CpuFeatures::ARM::kSVE2); + cpu.addFeature(Ext::kSVE2); #endif #if defined(__ARM_FEATURE_SVE2_AES) - cpu.addFeature(CpuFeatures::ARM::kSVE2_AES); + cpu.addFeature(Ext::kSVE_AES); #endif #if defined(__ARM_FEATURE_SVE2_BITPERM) - cpu.addFeature(CpuFeatures::ARM::kSVE2_BITPERM); + cpu.addFeature(Ext::kSVE_BITPERM); #endif #if defined(__ARM_FEATURE_SVE2_SHA3) - cpu.addFeature(CpuFeatures::ARM::kSVE2_SHA3); + cpu.addFeature(Ext::kSVE_SHA3); #endif #if defined(__ARM_FEATURE_SVE2_SM4) - cpu.addFeature(CpuFeatures::ARM::kSVE2_SM4); + cpu.addFeature(Ext::kSVE_SM4); #endif #if defined(__ARM_FEATURE_TME) - cpu.addFeature(CpuFeatures::ARM::kTME); + cpu.addFeature(Ext::kTME); #endif } +#endif // ASMJIT_ARCH_ARM == 64 ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void expandARMFeaturesByVersion(CpuInfo& cpu) noexcept { - CpuFeatures::ARM& features = cpu.features().arm(); +static ASMJIT_FAVOR_SIZE void detectARMFeaturesViaCompilerFlags(CpuInfo& cpu) noexcept { +#if ASMJIT_ARCH_ARM == 32 + detectAArch32FeaturesViaCompilerFlags(cpu); +#else + detectAArch64FeaturesViaCompilerFlags(cpu); +#endif // ASMJIT_ARCH_ARM +} - if (features.hasARMv8_7a()) { - features.add(CpuFeatures::ARM::kARMv8_6a); - } +// CpuInfo - Detect - ARM - Post Processing ARM Features +// ===================================================== - if (features.hasARMv8_6a()) { - features.add(CpuFeatures::ARM::kARMv8_5a, - CpuFeatures::ARM::kBF16); +// Postprocesses AArch32 features. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void postProcessAArch32Features(CpuFeatures::ARM& features) noexcept { + DebugUtils::unused(features); +} - if (features.hasSVE()) - features.add(CpuFeatures::ARM::kSVE_I8MM); - } +// Postprocesses AArch64 features. +// +// The only reason to use this function is to deduce some flags from others. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void postProcessAArch64Features(CpuFeatures::ARM& features) noexcept { + if (features.hasFP16()) + features.add(Ext::kFP16CONV); - if (features.hasARMv8_5a()) { - features.add(CpuFeatures::ARM::kARMv8_4a, - CpuFeatures::ARM::kALTNZCV, - CpuFeatures::ARM::kBTI, - CpuFeatures::ARM::kFRINT, - CpuFeatures::ARM::kSB, - CpuFeatures::ARM::kSSBS); - } + if (features.hasMTE3()) + features.add(Ext::kMTE2); - if (features.hasARMv8_4a()) { - features.add(CpuFeatures::ARM::kARMv8_3a, - CpuFeatures::ARM::kDIT, - CpuFeatures::ARM::kDOTPROD, - CpuFeatures::ARM::kFLAGM, - CpuFeatures::ARM::kPMU, - CpuFeatures::ARM::kRCPC_IMMO); - } + if (features.hasMTE2()) + features.add(Ext::kMTE); - if (features.hasARMv8_3a()) { - features.add(CpuFeatures::ARM::kARMv8_2a, - CpuFeatures::ARM::kFCMA, - CpuFeatures::ARM::kFJCVTZS); - } + if (features.hasSSBS2()) + features.add(Ext::kSSBS); +} - if (features.hasARMv8_2a()) { - features.add(CpuFeatures::ARM::kARMv8_1a); - } +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void postProcessARMCpuInfo(CpuInfo& cpu) noexcept { +#if ASMJIT_ARCH_ARM == 32 + postProcessAArch32Features(cpu.features().arm()); +#else + postProcessAArch64Features(cpu.features().arm()); +#endif // ASMJIT_ARCH_ARM +} + +// CpuInfo - Detect - ARM - Detect by Reading CPUID Registers +// ========================================================== - if (features.hasARMv8_1a()) { - features.add(CpuFeatures::ARM::kARMv8a, - CpuFeatures::ARM::kCRC32, - CpuFeatures::ARM::kLSE, - CpuFeatures::ARM::kRDM); +// Support CPUID-based detection on AArch64. +#if defined(ASMJIT_ARM_DETECT_VIA_CPUID) + +// Since the register ID is encoded with the instruction we have to create a function for each register ID to read. +#define ASMJIT_AARCH64_DEFINE_CPUID_READ_FN(func, regId) \ +ASMJIT_MAYBE_UNUSED \ +static inline uint64_t func() noexcept { \ + uint64_t output; \ + __asm__ __volatile__("mrs %0, " #regId : "=r"(output)); \ + return output; \ +} + +// NOTE: Older tools don't know the IDs. For example Ubuntu on RPI (GCC 9) won't compile ID_AA64ISAR2_EL1 in 2023. +ASMJIT_AARCH64_DEFINE_CPUID_READ_FN(aarch64ReadPFR0, ID_AA64PFR0_EL1) +ASMJIT_AARCH64_DEFINE_CPUID_READ_FN(aarch64ReadPFR1, ID_AA64PFR1_EL1) +ASMJIT_AARCH64_DEFINE_CPUID_READ_FN(aarch64ReadISAR0, ID_AA64ISAR0_EL1) +ASMJIT_AARCH64_DEFINE_CPUID_READ_FN(aarch64ReadISAR1, ID_AA64ISAR1_EL1) +ASMJIT_AARCH64_DEFINE_CPUID_READ_FN(aarch64ReadISAR2, S3_0_C0_C6_2) // ID_AA64ISAR2_EL1 +ASMJIT_AARCH64_DEFINE_CPUID_READ_FN(aarch64ReadZFR0, S3_0_C0_C4_4) // ID_AA64ZFR0_EL1 + +#undef ASMJIT_AARCH64_DEFINE_CPUID_READ_FN + +// Detects AArch64 features by reading CPUID bits directly from CPUID registers. This is the most reliable method +// as the OS doesn't have to know all supported extensions this way (if there is something missing in HWCAPS then +// there is no way to detect such feature without reading CPUID bits). +// +// This function uses MSR instructions, which means that it reads registers that cannot be read in user-mode. The +// OS typically implements this feature by handling SIGILL internally and providing a filtered content of these +// registers back to the user - at least this is what Linux documentation states - everything implementation +// dependent is zeroed, only the bits that are used for CPU feature identification would be present. +// +// References: +// - https://docs.kernel.org/arch/arm64/cpu-feature-registers.html +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID(CpuInfo& cpu) noexcept { + populateBaseARMFeatures(cpu); + + detectAArch64FeaturesViaCPUID_AA64PFR0_AA64PFR1(cpu, + aarch64ReadPFR0(), + aarch64ReadPFR1()); + + detectAArch64FeaturesViaCPUID_AA64ISAR0_AA64ISAR1(cpu, + aarch64ReadISAR0(), + aarch64ReadISAR1()); + + // TODO: Fix this on FreeBSD - I don't know what kernel version allows to access the registers below... + +#if defined(__linux__) + UNameKernelVersion kVer = getUNameKernelVersion(); + + // Introduced in Linux 4.19 by "arm64: add ID_AA64ISAR2_EL1 sys register"), so we want at least 4.20. + if (kVer.atLeast(4, 20)) { + detectAArch64FeaturesViaCPUID_AA64ISAR2(cpu, aarch64ReadISAR2()); } - if (features.hasARMv8a()) { - features.add(CpuFeatures::ARM::kARMv7, - CpuFeatures::ARM::kVFPv2, - CpuFeatures::ARM::kVFPv3, - CpuFeatures::ARM::kVFPv4, - CpuFeatures::ARM::kVFP_D32, - CpuFeatures::ARM::kASIMD, - CpuFeatures::ARM::kIDIVA); + // Introduced in Linux 5.10 by "arm64: Expose SVE2 features for userspace", so we want at least 5.11. + if (kVer.atLeast(5, 11) && cpu.features().arm().hasAny(Ext::kSVE, Ext::kSME)) { + // Only read CPU_ID_AA64ZFR0 when either SVE or SME is available. + detectAArch64FeaturesViaCPUID_AA64ZFR0(cpu, aarch64ReadZFR0()); } +#endif } -// CpuInfo - Detect - ARM [Windows] -// ================================ +#endif // ASMJIT_ARM_DETECT_VIA_CPUID + +// CpuInfo - Detect - ARM - Detect by Windows API +// ============================================== #if defined(_WIN32) struct WinPFPMapping { @@ -749,9 +1501,11 @@ struct WinPFPMapping { }; static ASMJIT_FAVOR_SIZE void detectPFPFeatures(CpuInfo& cpu, const WinPFPMapping* mapping, size_t size) noexcept { - for (size_t i = 0; i < size; i++) - if (::IsProcessorFeaturePresent(mapping[i].pfpFeatureId)) + for (size_t i = 0; i < size; i++) { + if (::IsProcessorFeaturePresent(mapping[i].pfpFeatureId)) { cpu.addFeature(mapping[i].featureId); + } + } } //! Detect ARM CPU features on Windows. @@ -763,400 +1517,495 @@ static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { CpuFeatures::ARM& features = cpu.features().arm(); - // Win32 for ARM requires ARMv7 with DSP extensions, VFPv3, and uses THUMBv2 by default. + // Win32 for ARM requires ARMv7 with DSP extensions, VFPv3 (FP), and uses THUMBv2 by default. #if ASMJIT_ARCH_ARM == 32 - features.add(CpuFeatures::ARM::kTHUMB); - features.add(CpuFeatures::ARM::kTHUMBv2); - features.add(CpuFeatures::ARM::kARMv6); - features.add(CpuFeatures::ARM::kARMv7); - features.add(CpuFeatures::ARM::kEDSP); - features.add(CpuFeatures::ARM::kVFPv2); - features.add(CpuFeatures::ARM::kVFPv3); + features.add(Ext::kTHUMB); + features.add(Ext::kTHUMBv2); + features.add(Ext::kARMv6); + features.add(Ext::kARMv7); + features.add(Ext::kEDSP); #endif - // Windows for ARM requires ASIMD. - features.add(CpuFeatures::ARM::kASIMD); + // Windows for ARM requires FP and ASIMD. + features.add(Ext::kFP); + features.add(Ext::kASIMD); // Detect additional CPU features by calling `IsProcessorFeaturePresent()`. static const WinPFPMapping mapping[] = { #if ASMJIT_ARCH_ARM == 32 - { uint8_t(CpuFeatures::ARM::kVFP_D32) , 18 }, // PF_ARM_VFP_32_REGISTERS_AVAILABLE - { uint8_t(CpuFeatures::ARM::kIDIVT) , 24 }, // PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE - { uint8_t(CpuFeatures::ARM::kVFPv4) , 27 }, // PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE - { uint8_t(CpuFeatures::ARM::kARMv8a) , 29 }, // PF_ARM_V8_INSTRUCTIONS_AVAILABLE + { uint8_t(Ext::kVFP_D32) , 18 }, // PF_ARM_VFP_32_REGISTERS_AVAILABLE + { uint8_t(Ext::kIDIVT) , 24 }, // PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE + { uint8_t(Ext::kFMAC) , 27 }, // PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE + { uint8_t(Ext::kARMv8a) , 29 }, // PF_ARM_V8_INSTRUCTIONS_AVAILABLE #endif - { uint8_t(CpuFeatures::ARM::kAES) , 30 }, // PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE - { uint8_t(CpuFeatures::ARM::kCRC32) , 31 }, // PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE - { uint8_t(CpuFeatures::ARM::kLSE) , 34 } // PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE - + { uint8_t(Ext::kAES) , 30 }, // PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE + { uint8_t(Ext::kCRC32) , 31 }, // PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE + { uint8_t(Ext::kLSE) , 34 }, // PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE + { uint8_t(Ext::kDOTPROD) , 43 }, // PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE + { uint8_t(Ext::kJSCVT) , 44 }, // PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE + { uint8_t(Ext::kLRCPC) , 45 } // PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE }; detectPFPFeatures(cpu, mapping, ASMJIT_ARRAY_SIZE(mapping)); + // Windows can only report ARMv8A at the moment. + if (features.hasARMv8a()) { + populateARMv8AFeatures(cpu.features().arm(), 0); + } + // Windows provides several instructions under a single flag: if (features.hasAES()) { - features.add(CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2); + features.add(Ext::kPMULL, Ext::kSHA1, Ext::kSHA256); } - expandARMFeaturesByVersion(cpu); + postProcessARMCpuInfo(cpu); } -// CpuInfo - Detect - ARM [Linux] -// ============================== +// CpuInfo - Detect - ARM - Detect by Reading HWCAPS +// ================================================= + +#elif defined(ASMJIT_ARM_DETECT_VIA_HWCAPS) + +#ifndef AT_HWCAP + #define AT_HWCAP 16 +#endif // !AT_HWCAP -#elif defined(__linux__) +#ifndef AT_HWCAP2 + #define AT_HWCAP2 26 +#endif // !AT_HWCAP2 + +#if defined(__linux__) +static void getAuxValues(unsigned long* vals, const unsigned long* tags, size_t count) noexcept { + for (size_t i = 0; i < count; i++) { + vals[i] = getauxval(tags[i]); + } +} +#elif defined(__FreeBSD__) +static void getAuxValues(unsigned long* vals, const unsigned long* tags, size_t count) noexcept { + for (size_t i = 0; i < count; i++) { + unsigned long result = 0; + if (elf_aux_info(int(tags[i]), &result, int(sizeof(unsigned long))) != 0) + result = 0; + vals[i] = result; + } +} +#else +#error "[asmjit] getAuxValues() - Unsupported OS." +#endif -struct LinuxHWCapMapping { +struct HWCapMapping { uint8_t featureId; uint8_t hwCapBit; }; -static ASMJIT_FAVOR_SIZE void detectHWCaps(CpuInfo& cpu, unsigned long type, const LinuxHWCapMapping* mapping, size_t size) noexcept { - unsigned long mask = getauxval(type); - for (size_t i = 0; i < size; i++) +static const unsigned long hwCapTags[2] = { AT_HWCAP, AT_HWCAP2 }; + +static ASMJIT_FAVOR_SIZE void mergeHWCaps(CpuInfo& cpu, unsigned long mask, const HWCapMapping* mapping, size_t size) noexcept { + for (size_t i = 0; i < size; i++) { cpu.features().addIf(Support::bitTest(mask, mapping[i].hwCapBit), mapping[i].featureId); + } } #if ASMJIT_ARCH_ARM == 32 -// `AT_HWCAP` provides ARMv7 (and less) related flags. -static const LinuxHWCapMapping hwCapMapping[] = { - { uint8_t(CpuFeatures::ARM::kVFPv2) , 6 }, // HWCAP_VFP - { uint8_t(CpuFeatures::ARM::kEDSP) , 7 }, // HWCAP_EDSP - { uint8_t(CpuFeatures::ARM::kASIMD) , 12 }, // HWCAP_NEON - { uint8_t(CpuFeatures::ARM::kVFPv3) , 13 }, // HWCAP_VFPv3 - { uint8_t(CpuFeatures::ARM::kVFPv4) , 16 }, // HWCAP_VFPv4 - { uint8_t(CpuFeatures::ARM::kIDIVA) , 17 }, // HWCAP_IDIVA - { uint8_t(CpuFeatures::ARM::kIDIVT) , 18 }, // HWCAP_IDIVT - { uint8_t(CpuFeatures::ARM::kVFP_D32) , 19 } // HWCAP_VFPD32 +// Reference: +// - https://github.com/torvalds/linux/blob/master/arch/arm/include/uapi/asm/hwcap.h +static const HWCapMapping hwCapMapping[] = { + { uint8_t(Ext::kEDSP) , 7 }, // HWCAP_EDSP + { uint8_t(Ext::kASIMD) , 12 }, // HWCAP_NEON + { uint8_t(Ext::kFP) , 13 }, // HWCAP_VFPv3 + { uint8_t(Ext::kFMAC) , 16 }, // HWCAP_VFPv4 + { uint8_t(Ext::kIDIVA) , 17 }, // HWCAP_IDIVA + { uint8_t(Ext::kIDIVT) , 18 }, // HWCAP_IDIVT + { uint8_t(Ext::kVFP_D32) , 19 }, // HWCAP_VFPD32 + { uint8_t(Ext::kFP16CONV) , 22 }, // HWCAP_FPHP + { uint8_t(Ext::kFP16) , 23 }, // HWCAP_ASIMDHP + { uint8_t(Ext::kDOTPROD) , 24 }, // HWCAP_ASIMDDP + { uint8_t(Ext::kFHM) , 25 }, // HWCAP_ASIMDFHM + { uint8_t(Ext::kBF16) , 26 }, // HWCAP_ASIMDBF16 + { uint8_t(Ext::kI8MM) , 27 } // HWCAP_I8MM }; -// `AT_HWCAP2` provides ARMv8+ related flags. -static const LinuxHWCapMapping hwCap2Mapping[] = { - { uint8_t(CpuFeatures::ARM::kAES) , 0 }, // HWCAP2_AES - { uint8_t(CpuFeatures::ARM::kPMULL) , 1 }, // HWCAP2_PMULL - { uint8_t(CpuFeatures::ARM::kSHA1) , 2 }, // HWCAP2_SHA1 - { uint8_t(CpuFeatures::ARM::kSHA2) , 3 }, // HWCAP2_SHA2 - { uint8_t(CpuFeatures::ARM::kCRC32) , 4 } // HWCAP2_CRC32 +static const HWCapMapping hwCap2Mapping[] = { + { uint8_t(Ext::kAES) , 0 }, // HWCAP2_AES + { uint8_t(Ext::kPMULL) , 1 }, // HWCAP2_PMULL + { uint8_t(Ext::kSHA1) , 2 }, // HWCAP2_SHA1 + { uint8_t(Ext::kSHA256) , 3 }, // HWCAP2_SHA2 + { uint8_t(Ext::kCRC32) , 4 }, // HWCAP2_CRC32 + { uint8_t(Ext::kSB) , 5 }, // HWCAP2_SB + { uint8_t(Ext::kSSBS) , 6 } // HWCAP2_SSBS }; static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { cpu._wasDetected = true; - populateBaseARMFeatures(cpu); - CpuFeatures::ARM& features = cpu.features().arm(); - - detectHWCaps(cpu, AT_HWCAP, hwCapMapping, ASMJIT_ARRAY_SIZE(hwCapMapping)); - detectHWCaps(cpu, AT_HWCAP2, hwCap2Mapping, ASMJIT_ARRAY_SIZE(hwCap2Mapping)); + unsigned long hwCapMasks[2] {}; + getAuxValues(hwCapMasks, hwCapTags, 2u); - // VFPv3 implies VFPv2. - if (features.hasVFPv3()) - features.add(CpuFeatures::ARM::kVFPv2); + mergeHWCaps(cpu, hwCapMasks[0], hwCapMapping, ASMJIT_ARRAY_SIZE(hwCapMapping)); + mergeHWCaps(cpu, hwCapMasks[1], hwCap2Mapping, ASMJIT_ARRAY_SIZE(hwCap2Mapping)); - // VFPv2 implies ARMv6. - if (features.hasVFPv2()) - features.add(CpuFeatures::ARM::kARMv6); + CpuFeatures::ARM& features = cpu.features().arm(); - // ARMv7 provides VFPv3|ASIMD. - if (features.hasVFPv3() || features.hasASIMD()) + // ARMv7 provides FP|ASIMD. + if (features.hasFP() || features.hasASIMD()) features.add(CpuFeatures::ARM::kARMv7); - // ARMv8 provives AES, CRC32, PMULL, SHA1, and SHA2. - if (features.hasAES() || features.hasCRC32() || features.hasPMULL() || features.hasSHA1() || features.hasSHA2()) + // ARMv8 provives AES, CRC32, PMULL, SHA1, and SHA256. + if (features.hasAES() || features.hasCRC32() || features.hasPMULL() || features.hasSHA1() || features.hasSHA256()) features.add(CpuFeatures::ARM::kARMv8a); + + postProcessARMCpuInfo(cpu); } #else -// `AT_HWCAP` provides ARMv8+ related flags. -static const LinuxHWCapMapping hwCapMapping[] = { +// Reference: +// - https://docs.kernel.org/arch/arm64/elf_hwcaps.html +// - https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h +static const HWCapMapping hwCapMapping[] = { + { uint8_t(Ext::kFP) , 0 }, // HWCAP_FP + { uint8_t(Ext::kASIMD) , 1 }, // HWCAP_ASIMD /* - { uint8_t(CpuFeatures::ARM::k) , 0 }, // HWCAP_FP + { uint8_t(Ext::k) , 2 }, // HWCAP_EVTSTRM */ - { uint8_t(CpuFeatures::ARM::kASIMD) , 1 }, // HWCAP_ASIMD + { uint8_t(Ext::kAES) , 3 }, // HWCAP_AES + { uint8_t(Ext::kPMULL) , 4 }, // HWCAP_PMULL + { uint8_t(Ext::kSHA1) , 5 }, // HWCAP_SHA1 + { uint8_t(Ext::kSHA256) , 6 }, // HWCAP_SHA2 + { uint8_t(Ext::kCRC32) , 7 }, // HWCAP_CRC32 + { uint8_t(Ext::kLSE) , 8 }, // HWCAP_ATOMICS + { uint8_t(Ext::kFP16CONV) , 9 }, // HWCAP_FPHP + { uint8_t(Ext::kFP16) , 10 }, // HWCAP_ASIMDHP + { uint8_t(Ext::kCPUID) , 11 }, // HWCAP_CPUID + { uint8_t(Ext::kRDM) , 12 }, // HWCAP_ASIMDRDM + { uint8_t(Ext::kJSCVT) , 13 }, // HWCAP_JSCVT + { uint8_t(Ext::kFCMA) , 14 }, // HWCAP_FCMA + { uint8_t(Ext::kLRCPC) , 15 }, // HWCAP_LRCPC + { uint8_t(Ext::kDPB) , 16 }, // HWCAP_DCPOP + { uint8_t(Ext::kSHA3) , 17 }, // HWCAP_SHA3 + { uint8_t(Ext::kSM3) , 18 }, // HWCAP_SM3 + { uint8_t(Ext::kSM4) , 19 }, // HWCAP_SM4 + { uint8_t(Ext::kDOTPROD) , 20 }, // HWCAP_ASIMDDP + { uint8_t(Ext::kSHA512) , 21 }, // HWCAP_SHA512 + { uint8_t(Ext::kSVE) , 22 }, // HWCAP_SVE + { uint8_t(Ext::kFHM) , 23 }, // HWCAP_ASIMDFHM + { uint8_t(Ext::kDIT) , 24 }, // HWCAP_DIT + { uint8_t(Ext::kLSE2) , 25 }, // HWCAP_USCAT + { uint8_t(Ext::kLRCPC2) , 26 }, // HWCAP_ILRCPC + { uint8_t(Ext::kFLAGM) , 27 }, // HWCAP_FLAGM + { uint8_t(Ext::kSSBS) , 28 }, // HWCAP_SSBS + { uint8_t(Ext::kSB) , 29 } // HWCAP_SB /* - { uint8_t(CpuFeatures::ARM::k) , 2 }, // HWCAP_EVTSTRM - */ - { uint8_t(CpuFeatures::ARM::kAES) , 3 }, // HWCAP_AES - { uint8_t(CpuFeatures::ARM::kPMULL) , 4 }, // HWCAP_PMULL - { uint8_t(CpuFeatures::ARM::kSHA1) , 5 }, // HWCAP_SHA1 - { uint8_t(CpuFeatures::ARM::kSHA2) , 6 }, // HWCAP_SHA2 - { uint8_t(CpuFeatures::ARM::kCRC32) , 7 }, // HWCAP_CRC32 - { uint8_t(CpuFeatures::ARM::kLSE) , 8 }, // HWCAP_ATOMICS - { uint8_t(CpuFeatures::ARM::kFP16CONV) , 9 }, // HWCAP_FPHP - { uint8_t(CpuFeatures::ARM::kFP16FULL) , 10 }, // HWCAP_ASIMDHP - { uint8_t(CpuFeatures::ARM::kCPUID) , 11 }, // HWCAP_CPUID - { uint8_t(CpuFeatures::ARM::kRDM) , 12 }, // HWCAP_ASIMDRDM - { uint8_t(CpuFeatures::ARM::kFJCVTZS) , 13 }, // HWCAP_JSCVT - { uint8_t(CpuFeatures::ARM::kFCMA) , 14 }, // HWCAP_FCMA - /* - { uint8_t(CpuFeatures::ARM::k) , 15 }, // HWCAP_LRCPC - { uint8_t(CpuFeatures::ARM::k) , 16 }, // HWCAP_DCPOP - */ - { uint8_t(CpuFeatures::ARM::kSHA3) , 17 }, // HWCAP_SHA3 - { uint8_t(CpuFeatures::ARM::kSM3) , 18 }, // HWCAP_SM3 - { uint8_t(CpuFeatures::ARM::kSM4) , 19 }, // HWCAP_SM4 - { uint8_t(CpuFeatures::ARM::kDOTPROD) , 20 }, // HWCAP_ASIMDDP - { uint8_t(CpuFeatures::ARM::kSHA512) , 21 }, // HWCAP_SHA512 - { uint8_t(CpuFeatures::ARM::kSVE) , 22 }, // HWCAP_SVE - { uint8_t(CpuFeatures::ARM::kFP16FML) , 23 }, // HWCAP_ASIMDFHM - { uint8_t(CpuFeatures::ARM::kDIT) , 24 }, // HWCAP_DIT - /* - { uint8_t(CpuFeatures::ARM::k) , 25 }, // HWCAP_USCAT - { uint8_t(CpuFeatures::ARM::k) , 26 }, // HWCAP_ILRCPC - */ - { uint8_t(CpuFeatures::ARM::kFLAGM) , 27 }, // HWCAP_FLAGM - { uint8_t(CpuFeatures::ARM::kSSBS) , 28 }, // HWCAP_SSBS - { uint8_t(CpuFeatures::ARM::kSB) , 29 } // HWCAP_SB - /* - { uint8_t(CpuFeatures::ARM::k) , 30 }, // HWCAP_PACA - { uint8_t(CpuFeatures::ARM::k) , 31 } // HWCAP_PACG + { uint8_t(Ext::k) , 30 }, // HWCAP_PACA + { uint8_t(Ext::k) , 31 } // HWCAP_PACG */ }; -// `AT_HWCAP2` provides ARMv8+ related flags. -static const LinuxHWCapMapping hwCapMapping2[] = { - /* - { uint8_t(CpuFeatures::ARM::k) , 0 }, // HWCAP2_DCPODP - */ - { uint8_t(CpuFeatures::ARM::kSVE2) , 1 }, // HWCAP2_SVE2 - { uint8_t(CpuFeatures::ARM::kSVE2_AES) , 2 }, // HWCAP2_SVEAES - { uint8_t(CpuFeatures::ARM::kSVE_PMULL) , 3 }, // HWCAP2_SVEPMULL - { uint8_t(CpuFeatures::ARM::kSVE2_BITPERM), 4 }, // HWCAP2_SVEBITPERM - { uint8_t(CpuFeatures::ARM::kSVE2_SHA3) , 5 }, // HWCAP2_SVESHA3 - { uint8_t(CpuFeatures::ARM::kSVE2_SM4) , 6 }, // HWCAP2_SVESM4 - { uint8_t(CpuFeatures::ARM::kALTNZCV) , 7 }, // HWCAP2_FLAGM2 - { uint8_t(CpuFeatures::ARM::kFRINT) , 8 }, // HWCAP2_FRINT - { uint8_t(CpuFeatures::ARM::kSVE_I8MM) , 9 }, // HWCAP2_SVEI8MM - { uint8_t(CpuFeatures::ARM::kSVE_F32MM) , 10 }, // HWCAP2_SVEF32MM - { uint8_t(CpuFeatures::ARM::kSVE_F64MM) , 11 }, // HWCAP2_SVEF64MM - { uint8_t(CpuFeatures::ARM::kSVE_BF16) , 12 }, // HWCAP2_SVEBF16 - { uint8_t(CpuFeatures::ARM::kI8MM) , 13 }, // HWCAP2_I8MM - { uint8_t(CpuFeatures::ARM::kBF16) , 14 }, // HWCAP2_BF16 - { uint8_t(CpuFeatures::ARM::kDGH) , 15 }, // HWCAP2_DGH - { uint8_t(CpuFeatures::ARM::kRNG) , 16 }, // HWCAP2_RNG - { uint8_t(CpuFeatures::ARM::kBTI) , 17 }, // HWCAP2_BTI - { uint8_t(CpuFeatures::ARM::kMTE) , 18 } // HWCAP2_MTE +static const HWCapMapping hwCap2Mapping[] = { + { uint8_t(Ext::kDPB2) , 0 }, // HWCAP2_DCPODP + { uint8_t(Ext::kSVE2) , 1 }, // HWCAP2_SVE2 + { uint8_t(Ext::kSVE_AES) , 2 }, // HWCAP2_SVEAES + { uint8_t(Ext::kSVE_PMULL128) , 3 }, // HWCAP2_SVEPMULL + { uint8_t(Ext::kSVE_BITPERM) , 4 }, // HWCAP2_SVEBITPERM + { uint8_t(Ext::kSVE_SHA3) , 5 }, // HWCAP2_SVESHA3 + { uint8_t(Ext::kSVE_SM4) , 6 }, // HWCAP2_SVESM4 + { uint8_t(Ext::kFLAGM2) , 7 }, // HWCAP2_FLAGM2 + { uint8_t(Ext::kFRINTTS) , 8 }, // HWCAP2_FRINT + { uint8_t(Ext::kSVE_I8MM) , 9 }, // HWCAP2_SVEI8MM + { uint8_t(Ext::kSVE_F32MM) , 10 }, // HWCAP2_SVEF32MM + { uint8_t(Ext::kSVE_F64MM) , 11 }, // HWCAP2_SVEF64MM + { uint8_t(Ext::kSVE_BF16) , 12 }, // HWCAP2_SVEBF16 + { uint8_t(Ext::kI8MM) , 13 }, // HWCAP2_I8MM + { uint8_t(Ext::kBF16) , 14 }, // HWCAP2_BF16 + { uint8_t(Ext::kDGH) , 15 }, // HWCAP2_DGH + { uint8_t(Ext::kRNG) , 16 }, // HWCAP2_RNG + { uint8_t(Ext::kBTI) , 17 }, // HWCAP2_BTI + { uint8_t(Ext::kMTE) , 18 }, // HWCAP2_MTE + { uint8_t(Ext::kECV) , 19 }, // HWCAP2_ECV + { uint8_t(Ext::kAFP) , 20 }, // HWCAP2_AFP + { uint8_t(Ext::kRPRES) , 21 }, // HWCAP2_RPRES + { uint8_t(Ext::kMTE3) , 22 }, // HWCAP2_MTE3 + { uint8_t(Ext::kSME) , 23 }, // HWCAP2_SME + { uint8_t(Ext::kSME_I16I64) , 24 }, // HWCAP2_SME_I16I64 + { uint8_t(Ext::kSME_F64F64) , 25 }, // HWCAP2_SME_F64F64 + { uint8_t(Ext::kSME_I8I32) , 26 }, // HWCAP2_SME_I8I32 + { uint8_t(Ext::kSME_F16F32) , 27 }, // HWCAP2_SME_F16F32 + { uint8_t(Ext::kSME_B16F32) , 28 }, // HWCAP2_SME_B16F32 + { uint8_t(Ext::kSME_F32F32) , 29 }, // HWCAP2_SME_F32F32 + { uint8_t(Ext::kSME_FA64) , 30 }, // HWCAP2_SME_FA64 + { uint8_t(Ext::kWFXT) , 31 }, // HWCAP2_WFXT + { uint8_t(Ext::kEBF16) , 32 }, // HWCAP2_EBF16 + { uint8_t(Ext::kSVE_EBF16) , 33 }, // HWCAP2_SVE_EBF16 + { uint8_t(Ext::kCSSC) , 34 }, // HWCAP2_CSSC + { uint8_t(Ext::kRPRFM) , 35 }, // HWCAP2_RPRFM + { uint8_t(Ext::kSVE2_1) , 36 }, // HWCAP2_SVE2P1 + { uint8_t(Ext::kSME2) , 37 }, // HWCAP2_SME2 + { uint8_t(Ext::kSME2_1) , 38 }, // HWCAP2_SME2P1 + { uint8_t(Ext::kSME_I16I32) , 39 }, // HWCAP2_SME_I16I32 + { uint8_t(Ext::kSME_BI32I32) , 40 }, // HWCAP2_SME_BI32I32 + { uint8_t(Ext::kSME_B16B16) , 41 }, // HWCAP2_SME_B16B16 + { uint8_t(Ext::kSME_F16F16) , 42 }, // HWCAP2_SME_F16F16 + { uint8_t(Ext::kMOPS) , 43 }, // HWCAP2_MOPS + { uint8_t(Ext::kHBC) , 44 }, // HWCAP2_HBC + { uint8_t(Ext::kSVE_B16B16) , 45 }, // HWCAP2_SVE_B16B16 + { uint8_t(Ext::kLRCPC3) , 46 }, // HWCAP2_LRCPC3 + { uint8_t(Ext::kLSE128) , 47 }, // HWCAP2_LSE128 }; static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { cpu._wasDetected = true; populateBaseARMFeatures(cpu); - detectHWCaps(cpu, AT_HWCAP, hwCapMapping, ASMJIT_ARRAY_SIZE(hwCapMapping)); - detectHWCaps(cpu, AT_HWCAP2, hwCapMapping2, ASMJIT_ARRAY_SIZE(hwCapMapping2)); -} + unsigned long hwCapMasks[2] {}; + getAuxValues(hwCapMasks, hwCapTags, 2u); -#endif + mergeHWCaps(cpu, hwCapMasks[0], hwCapMapping, ASMJIT_ARRAY_SIZE(hwCapMapping)); + mergeHWCaps(cpu, hwCapMasks[1], hwCap2Mapping, ASMJIT_ARRAY_SIZE(hwCap2Mapping)); -// CpuInfo - Detect - ARM [Apple] -// ============================== +#if defined(ASMJIT_ARM_DETECT_VIA_CPUID) + if (cpu.features().arm().hasCPUID()) { + detectAArch64FeaturesViaCPUID(cpu); + return; + } +#endif // ASMJIT_ARM_DETECT_VIA_CPUID -#elif defined(__APPLE__) + postProcessARMCpuInfo(cpu); +} -namespace AppleHWId { - enum CpuFamily : uint32_t { - // Generic ARM. - kCpuFamily_ARM_9 = 0xE73283AEu, - kCpuFamily_ARM_11 = 0x8FF620D8u, - kCpuFamily_ARM_12 = 0xBD1B0AE9u, - kCpuFamily_ARM_13 = 0x0CC90E64u, - kCpuFamily_ARM_14 = 0x96077EF1u, - kCpuFamily_ARM_15 = 0xA8511BCAu, - - // Apple design. - kCpuFamily_SWIFT = 0x1E2D6381u, - kCpuFamily_CYCLONE = 0x37A09642u, - kCpuFamily_TYPHOON = 0x2C91A47Eu, - kCpuFamily_TWISTER = 0x92FB37C8u, - kCpuFamily_HURRICANE = 0x67CEEE93u, - kCpuFamily_MONSOON_MISTRAL = 0xE81E7EF6u, - kCpuFamily_VORTEX_TEMPEST = 0x07D34B9Fu, - kCpuFamily_LIGHTNING_THUNDER = 0x462504D2u, - kCpuFamily_FIRESTORM_ICESTORM = 0x1B588BB3u - }; +#endif // ASMJIT_ARCH_ARM + +// CpuInfo - Detect - ARM - Detect by OpenBSD API That Reads CPUID +// =============================================================== + +#elif defined(__OpenBSD__) && ASMJIT_ARCH_ARM >= 64 + +// Supported CPUID registers on OpenBSD (CTL_MACHDEP definitions): +// - https://github.com/openbsd/src/blob/master/sys/arch/arm64/include/cpu.h +enum class OpenBSDAArch64CPUID { + kAA64ISAR0 = 2, + kAA64ISAR1 = 3, + kAA64ISAR2 = 4, + kAA64MMFR0 = 5, + kAA64MMFR1 = 6, + kAA64MMFR2 = 7, + kAA64PFR0 = 8, + kAA64PFR1 = 9, + kAA64SMFR0 = 10, + kAA64ZFR0 = 11 }; -static ASMJIT_FAVOR_SIZE uint32_t queryARMCpuFamilyId() noexcept { - uint32_t result = 0; - size_t size = sizeof(result); +static uint64_t openbsdReadAArch64CPUID(OpenBSDAArch64CPUID id) noexcept { + uint64_t bits = 0; + size_t size = sizeof(bits); + int name[2] = { CTL_MACHDEP, int(id) }; - int res = sysctlbyname("hw.cpufamily", &result, &size, nullptr, 0); - if (res != 0) - return 0; - else - return result; + return (sysctl(name, 2, &bits, &size, NULL, 0) < 0) ? uint64_t(0) : bits; } static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { - cpu._wasDetected = true; + typedef OpenBSDAArch64CPUID ID; + populateBaseARMFeatures(cpu); - uint32_t cpuFamilyId = queryARMCpuFamilyId(); - CpuFeatures::ARM& features = cpu.features().arm(); + detectAArch64FeaturesViaCPUID_AA64PFR0_AA64PFR1(cpu, + openbsdReadAArch64CPUID(ID::kAA64PFR0), + openbsdReadAArch64CPUID(ID::kAA64PFR1)); - switch (cpuFamilyId) { - case AppleHWId::kCpuFamily_ARM_9: - case AppleHWId::kCpuFamily_ARM_11: - case AppleHWId::kCpuFamily_ARM_12: - break; + detectAArch64FeaturesViaCPUID_AA64ISAR0_AA64ISAR1(cpu, + openbsdReadAArch64CPUID(ID::kAA64ISAR0), + openbsdReadAArch64CPUID(ID::kAA64ISAR1)); - // ARM Cortex A8. - case AppleHWId::kCpuFamily_ARM_13: - break; + detectAArch64FeaturesViaCPUID_AA64ISAR2(cpu, openbsdReadAArch64CPUID(ID::kAA64ISAR2)); + detectAArch64FeaturesViaCPUID_AA64MMFR0(cpu, openbsdReadAArch64CPUID(ID::kAA64MMFR0)); + detectAArch64FeaturesViaCPUID_AA64MMFR1(cpu, openbsdReadAArch64CPUID(ID::kAA64MMFR1)); + detectAArch64FeaturesViaCPUID_AA64MMFR2(cpu, openbsdReadAArch64CPUID(ID::kAA64MMFR2)); - // ARM Cortex A9. - case AppleHWId::kCpuFamily_ARM_14: - break; + // Only read CPU_ID_AA64ZFR0 when either SVE or SME is available. + if (cpu.features().arm().hasAny(Ext::kSVE, Ext::kSME)) { + detectAArch64FeaturesViaCPUID_AA64ZFR0(cpu, openbsdReadAArch64CPUID(ID::kAA64ZFR0)); - // ARM Cortex A7 - ARMv7k. - case AppleHWId::kCpuFamily_ARM_15: - features.add(CpuFeatures::ARM::kARMv7); - break; + if (cpu.features().arm().hasSME()) + detectAArch64FeaturesViaCPUID_AA64SMFR0(cpu, openbsdReadAArch64CPUID(ID::kAA64SMFR0)); + } - // Apple A6/A6X - ARMv7s. - case AppleHWId::kCpuFamily_SWIFT: - features.add(CpuFeatures::ARM::kARMv7); - break; + postProcessARMCpuInfo(cpu); +} - // Apple A7 - ARMv8.0-A. - case AppleHWId::kCpuFamily_CYCLONE: - features.add(CpuFeatures::ARM::kARMv8a, - CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2); - break; +// CpuInfo - Detect - ARM - Detect by Apple API (sysctlbyname) +// =========================================================== - // Apple A8 - ARMv8.0-A. - case AppleHWId::kCpuFamily_TYPHOON: - features.add(CpuFeatures::ARM::kARMv8a, - CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2); - break; +#elif defined(__APPLE__) - // Apple A9 - ARMv8.0-A. - case AppleHWId::kCpuFamily_TWISTER: - features.add(CpuFeatures::ARM::kARMv8a, - CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2); - break; +enum class AppleFeatureType : uint8_t { + kHWOptional, + kHWOptionalArmFEAT +}; - // Apple A10 - ARMv8.1-A. - case AppleHWId::kCpuFamily_HURRICANE: - features.add(CpuFeatures::ARM::kARMv8_1a, - CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kRDM, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2); +struct AppleFeatureMapping { + AppleFeatureType type; + char name[18]; + uint8_t featureId; +}; - break; +template<typename T> +static inline bool appleSysctlByName(const char* sysctlName, T* dst, size_t size = sizeof(T)) noexcept { + return sysctlbyname(sysctlName, dst, &size, nullptr, 0) == 0; +} - // Apple A11 - ARMv8.2-A. - case AppleHWId::kCpuFamily_MONSOON_MISTRAL: - features.add(CpuFeatures::ARM::kARMv8_2a, - CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kFP16FULL, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2); - break; +static ASMJIT_FAVOR_SIZE long appleDetectARMFeatureViaSysctl(AppleFeatureType type, const char* featureName) noexcept { + static const char hwOptionalPrefix[] = "hw.optional."; + static const char hwOptionalArmFeatPrefix[] = "hw.optional.arm.FEAT_"; - // Apple A12 - ARMv8.3-A. - case AppleHWId::kCpuFamily_VORTEX_TEMPEST: - features.add(CpuFeatures::ARM::kARMv8_3a, - CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kFP16FULL, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2); - break; + char sysctlName[128]; - // Apple A13 - ARMv8.4-A. - case AppleHWId::kCpuFamily_LIGHTNING_THUNDER: - features.add(CpuFeatures::ARM::kARMv8_4a, - CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kFP16FML, - CpuFeatures::ARM::kFP16FULL, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2, - CpuFeatures::ARM::kSHA3, - CpuFeatures::ARM::kSHA512); - break; + const char* prefix = type == AppleFeatureType::kHWOptional ? hwOptionalPrefix : hwOptionalArmFeatPrefix; + size_t prefixSize = (type == AppleFeatureType::kHWOptional ? sizeof(hwOptionalPrefix) : sizeof(hwOptionalArmFeatPrefix)) - 1u; + size_t featureNameSize = strlen(featureName); - // Apple A14/M1 - ARMv8.5-A. - case AppleHWId::kCpuFamily_FIRESTORM_ICESTORM: - features.add(CpuFeatures::ARM::kARMv8_4a, - CpuFeatures::ARM::kAES, - CpuFeatures::ARM::kALTNZCV, - CpuFeatures::ARM::kFP16FML, - CpuFeatures::ARM::kFP16FULL, - CpuFeatures::ARM::kFRINT, - CpuFeatures::ARM::kSB, - CpuFeatures::ARM::kSHA1, - CpuFeatures::ARM::kSHA2, - CpuFeatures::ARM::kSHA3, - CpuFeatures::ARM::kSHA512, - CpuFeatures::ARM::kSSBS); - break; + if (featureNameSize < 128 - prefixSize) { + memcpy(sysctlName, prefix, prefixSize); + memcpy(sysctlName + prefixSize, featureName, featureNameSize + 1u); // Include NULL terminator. - default: - cpu._wasDetected = false; - break; + long val = 0; + if (appleSysctlByName<long>(sysctlName, &val)) + return val; } - expandARMFeaturesByVersion(cpu); + return 0; } -// CpuInfo - Detect - ARM [Unknown] -// ================================ +static ASMJIT_FAVOR_SIZE void appleDetectARMFeaturesViaSysctl(CpuInfo& cpu) noexcept { + typedef AppleFeatureType FT; + + // Based on: + // - https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics + static const AppleFeatureMapping mappings[] = { + // Determine Advanced SIMD and Floating Point Capabilities: + { FT::kHWOptional , "AdvSIMD_HPFPCvt", uint8_t(Ext::kFP16CONV) }, + { FT::kHWOptional , "neon_hpfp" , uint8_t(Ext::kFP16CONV) }, + { FT::kHWOptionalArmFEAT, "BF16" , uint8_t(Ext::kBF16) }, + { FT::kHWOptionalArmFEAT, "DotProd" , uint8_t(Ext::kDOTPROD) }, + { FT::kHWOptionalArmFEAT, "FCMA" , uint8_t(Ext::kFCMA) }, + { FT::kHWOptional , "armv8_3_compnum", uint8_t(Ext::kFCMA) }, + { FT::kHWOptionalArmFEAT, "FHM" , uint8_t(Ext::kFHM) }, + { FT::kHWOptional , "armv8_2_fhm" , uint8_t(Ext::kFHM) }, + { FT::kHWOptionalArmFEAT, "FP16" , uint8_t(Ext::kFP16) }, + { FT::kHWOptional , "neon_fp16" , uint8_t(Ext::kFP16) }, + { FT::kHWOptionalArmFEAT, "FRINTTS" , uint8_t(Ext::kFRINTTS) }, + { FT::kHWOptionalArmFEAT, "I8MM" , uint8_t(Ext::kI8MM) }, + { FT::kHWOptionalArmFEAT, "JSCVT" , uint8_t(Ext::kJSCVT) }, + { FT::kHWOptionalArmFEAT, "RDM" , uint8_t(Ext::kRDM) }, + + // Determine Integer Capabilities: + { FT::kHWOptional , "armv8_crc32" , uint8_t(Ext::kCRC32) }, + { FT::kHWOptionalArmFEAT, "FlagM" , uint8_t(Ext::kFLAGM) }, + { FT::kHWOptionalArmFEAT, "FlagM2" , uint8_t(Ext::kFLAGM2) }, + + // Determine Atomic and Memory Ordering Instruction Capabilities: + { FT::kHWOptionalArmFEAT, "LRCPC" , uint8_t(Ext::kLRCPC) }, + { FT::kHWOptionalArmFEAT, "LRCPC2" , uint8_t(Ext::kLRCPC2) }, + { FT::kHWOptional , "armv8_1_atomics", uint8_t(Ext::kLSE) }, + { FT::kHWOptionalArmFEAT, "LSE" , uint8_t(Ext::kLSE) }, + { FT::kHWOptionalArmFEAT, "LSE2" , uint8_t(Ext::kLSE2) }, + + // Determine Encryption Capabilities: + { FT::kHWOptionalArmFEAT, "AES" , uint8_t(Ext::kAES) }, + { FT::kHWOptionalArmFEAT, "PMULL" , uint8_t(Ext::kPMULL) }, + { FT::kHWOptionalArmFEAT, "SHA1" , uint8_t(Ext::kSHA1) }, + { FT::kHWOptionalArmFEAT, "SHA256" , uint8_t(Ext::kSHA256) }, + { FT::kHWOptionalArmFEAT, "SHA512" , uint8_t(Ext::kSHA512) }, + { FT::kHWOptional , "armv8_2_sha512" , uint8_t(Ext::kSHA512) }, + { FT::kHWOptionalArmFEAT, "SHA3" , uint8_t(Ext::kSHA3) }, + { FT::kHWOptional , "armv8_2_sha3" , uint8_t(Ext::kSHA3) }, + + // Determine General Capabilities: + { FT::kHWOptionalArmFEAT, "BTI" , uint8_t(Ext::kBTI) }, + { FT::kHWOptionalArmFEAT, "DPB" , uint8_t(Ext::kDPB) }, + { FT::kHWOptionalArmFEAT, "DPB2" , uint8_t(Ext::kDPB2) }, + { FT::kHWOptionalArmFEAT, "ECV" , uint8_t(Ext::kECV) }, + { FT::kHWOptionalArmFEAT, "SB" , uint8_t(Ext::kSB) }, + { FT::kHWOptionalArmFEAT, "SSBS" , uint8_t(Ext::kSSBS) } + }; + + for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(mappings); i++) { + const AppleFeatureMapping& mapping = mappings[i]; + if (!cpu.features().arm().has(mapping.featureId) && appleDetectARMFeatureViaSysctl(mapping.type, mapping.name)) { + cpu.features().arm().add(mapping.featureId); + } + } +} + +static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { + cpu._wasDetected = true; + populateBaseARMFeatures(cpu); + + appleSysctlByName<uint32_t>("hw.cpufamily", &cpu._familyId); + appleSysctlByName<uint32_t>("hw.cachelinesize", &cpu._cacheLineSize); + appleSysctlByName<uint32_t>("machdep.cpu.logical_per_package", &cpu._maxLogicalProcessors); + appleSysctlByName<char>("machdep.cpu.brand_string", cpu._brand.str, sizeof(cpu._brand.str)); + + memcpy(cpu._vendor.str, "APPLE", 6); + + bool cpuFeaturesPopulated = detectARMFeaturesViaAppleFamilyId(cpu); + if (!cpuFeaturesPopulated) + appleDetectARMFeaturesViaSysctl(cpu); + postProcessARMCpuInfo(cpu); +} + +// CpuInfo - Detect - ARM - Detect by Fallback (Using Compiler Flags) +// ================================================================== #else -#if ASMJIT_ARCH_ARM == 64 - #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with AArch64 CPU)") +#if ASMJIT_ARCH_ARM == 32 + #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with AArch32 CPU)") #else - #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with ARM CPU)") + #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with AArch64 CPU)") #endif static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { populateBaseARMFeatures(cpu); detectARMFeaturesViaCompilerFlags(cpu); - expandARMFeaturesByVersion(cpu); + postProcessARMCpuInfo(cpu); } #endif +} // {arm} + #endif // CpuInfo - Detect - Host // ======================= -static uint32_t cpuInfoInitialized; -static CpuInfo cpuInfoGlobal(Globals::NoInit); - const CpuInfo& CpuInfo::host() noexcept { - // This should never cause a problem as the resulting information should always be the same. In the worst case we - // would just overwrite it non-atomically. - if (!cpuInfoInitialized) { + static std::atomic<uint32_t> cpuInfoInitialized; + static CpuInfo cpuInfoGlobal(Globals::NoInit); + + // This should never cause a problem as the resulting information should always + // be the same. In the worst case it would just be overwritten non-atomically. + if (!cpuInfoInitialized.load(std::memory_order_relaxed)) { CpuInfo cpuInfoLocal; cpuInfoLocal._arch = Arch::kHost; cpuInfoLocal._subArch = SubArch::kHost; #if ASMJIT_ARCH_X86 - detectX86Cpu(cpuInfoLocal); + x86::detectX86Cpu(cpuInfoLocal); #elif ASMJIT_ARCH_ARM - detectARMCpu(cpuInfoLocal); -#else - #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown CPU)") + arm::detectARMCpu(cpuInfoLocal); #endif cpuInfoLocal._hwThreadCount = detectHWThreadCount(); cpuInfoGlobal = cpuInfoLocal; - cpuInfoInitialized = 1; + cpuInfoInitialized.store(1, std::memory_order_seq_cst); } return cpuInfoGlobal; } +#if defined(_MSC_VER) + #pragma warning(pop) +#endif // _MSC_VER + ASMJIT_END_NAMESPACE diff --git a/3rdparty/asmjit/src/asmjit/core/cpuinfo.h b/3rdparty/asmjit/src/asmjit/core/cpuinfo.h index 4af5c3a82f9..2638146a4cc 100644 --- a/3rdparty/asmjit/src/asmjit/core/cpuinfo.h +++ b/3rdparty/asmjit/src/asmjit/core/cpuinfo.h @@ -22,11 +22,6 @@ ASMJIT_BEGIN_NAMESPACE //! 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 //! \{ @@ -37,6 +32,13 @@ public: }; //! \endcond + //! 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; + + typedef Support::Array<BitWord, kNumBitWords> Bits; + //! \} //! \name Data @@ -48,15 +50,15 @@ public: //! \{ //! Data bits. - Support::Array<BitWord, kNumBitWords> _bits; + Bits _bits; //! \} //! \name Overloaded Operators //! \{ - inline bool operator==(const Data& other) noexcept { return eq(other); } - inline bool operator!=(const Data& other) noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const Data& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const Data& other) const noexcept { return !equals(other); } //! \} @@ -64,22 +66,22 @@ public: //! \{ //! Returns true if there are no features set. - inline bool empty() const noexcept { return _bits.aggregate<Support::Or>(0) == 0; } + ASMJIT_INLINE_NODEBUG 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(); } + ASMJIT_INLINE_NODEBUG BitWord* bits() noexcept { return _bits.data(); } //! Returns all features as array of bitwords (const). - inline const BitWord* bits() const noexcept { return _bits.data(); } + ASMJIT_INLINE_NODEBUG 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; } + ASMJIT_INLINE_NODEBUG 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); } + ASMJIT_INLINE_NODEBUG 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_INLINE_NODEBUG bool has(const FeatureId& featureId) const noexcept { ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures); uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits; @@ -88,12 +90,27 @@ public: return bool((_bits[idx] >> bit) & 0x1); } + //! \cond NONE + template<typename FeatureId> + ASMJIT_INLINE_NODEBUG bool hasAny(const FeatureId& featureId) const noexcept { + return has(featureId); + } + //! \endcond + + //! Tests whether any feature given is present. + //! + //! \note This is a variadic function template that can be used with multiple features. + template<typename FeatureId, typename... Args> + ASMJIT_INLINE_NODEBUG bool hasAny(const FeatureId& featureId, Args&&... otherFeatureIds) const noexcept { + return bool(unsigned(has(featureId)) | unsigned(hasAny(std::forward<Args>(otherFeatureIds)...))); + } + //! Tests whether all features as defined by `other` are present. - ASMJIT_FORCE_INLINE bool hasAll(const Data& other) const noexcept { + ASMJIT_INLINE_NODEBUG bool hasAll(const Data& other) const noexcept { + uint32_t result = 1; for (uint32_t i = 0; i < kNumBitWords; i++) - if ((_bits[i] & other._bits[i]) != other._bits[i]) - return false; - return true; + result &= uint32_t((_bits[i] & other._bits[i]) == other._bits[i]); + return bool(result); } //! \} @@ -101,11 +118,12 @@ public: //! \name Manipulation //! \{ - inline void reset() noexcept { _bits.fill(0); } + //! Clears all features set. + ASMJIT_INLINE_NODEBUG 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_INLINE_NODEBUG void add(const FeatureId& featureId) noexcept { ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures); uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits; @@ -115,13 +133,13 @@ public: } template<typename FeatureId, typename... Args> - ASMJIT_FORCE_INLINE void add(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept { + ASMJIT_INLINE_NODEBUG 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_INLINE_NODEBUG void addIf(bool condition, const FeatureId& featureId) noexcept { ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures); uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits; @@ -131,14 +149,14 @@ public: } template<typename FeatureId, typename... Args> - ASMJIT_FORCE_INLINE void addIf(bool condition, const FeatureId& featureId, Args&&... otherFeatureIds) noexcept { + ASMJIT_INLINE_NODEBUG 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_INLINE_NODEBUG void remove(const FeatureId& featureId) noexcept { ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures); uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits; @@ -148,17 +166,21 @@ public: } template<typename FeatureId, typename... Args> - ASMJIT_FORCE_INLINE void remove(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept { + ASMJIT_INLINE_NODEBUG 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; } + ASMJIT_INLINE_NODEBUG bool equals(const Data& other) const noexcept { return _bits == other._bits; } - //! \} +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use CpuFeatures::Data::equals() instead") + ASMJIT_INLINE_NODEBUG bool eq(const Data& other) const noexcept { return equals(other); } +#endif // !ASMJIT_NO_DEPRECATED - }; + //! \} + }; //! X86 specific features data. struct X86 : public Data { @@ -169,68 +191,83 @@ public: 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]. + k3DNOW, //!< CPU has 3DNOW (3DNOW base instructions) {AMD} (deprecated). + k3DNOW2, //!< CPU has 3DNOW2 (enhanced 3DNOW) {AMD} (deprecated). 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). + 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 (AMX-BF16 instructions). + kAMX_COMPLEX, //!< CPU has AMX_COMPLEX (AMX-COMPLEX instructions). + kAMX_FP16, //!< CPU has AMX_FP16 (AMX-FP16 instructions). + kAMX_INT8, //!< CPU has AMX_INT8 (AMX-INT8 instructions). kAMX_TILE, //!< CPU has AMX_TILE (advanced matrix extensions). + kAPX_F, //!< CPU has APX_F (advanced performance extensions - 32 GP registers, REX2 prefix, ...) {X86_64}. 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_BF16, //!< CPU has AVX512_BF16 (AVX512 BFLOAT16 support instructions). + kAVX512_BITALG, //!< CPU has AVX512_BITALG (AVX512 VPOPCNT[B|W] and VPSHUFBITQMB instructions). + kAVX512_BW, //!< CPU has AVX512_BW (AVX512 integer BYTE|WORD instructions). + kAVX512_CD, //!< CPU has AVX512_CD (AVX512 conflict detection DWORD|QWORD instructions). + kAVX512_DQ, //!< CPU has AVX512_DQ (AVX512 integer DWORD|QWORD instructions). + kAVX512_ER, //!< CPU has AVX512_ER (AVX512 exponential and reciprocal instructions). 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_FP16, //!< CPU has AVX512_FP16 (AVX512 FP16 instructions). + kAVX512_IFMA, //!< CPU has AVX512_IFMA (AVX512 integer fused-multiply-add using 52-bit precision). + kAVX512_PF, //!< CPU has AVX512_PF (AVX512 prefetch instructions). + kAVX512_VBMI, //!< CPU has AVX512_VBMI (AVX152 vector byte manipulation instructions). + kAVX512_VBMI2, //!< CPU has AVX512_VBMI2 (AVX512 vector byte manipulation instructions v2). + kAVX512_VL, //!< CPU has AVX512_VL (AVX512 vector length extensions). + kAVX512_VNNI, //!< CPU has AVX512_VNNI (AVX512 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). + kAVX512_VPOPCNTDQ, //!< CPU has AVX512_VPOPCNTDQ (AVX512 VPOPCNT[D|Q] instructions). + kAVX_IFMA, //!< CPU has AVX_IFMA (AVX/VEX encoding of vpmadd52huq/vpmadd52luq). + kAVX_NE_CONVERT, //!< CPU has AVX_NE_CONVERT. + kAVX_VNNI, //!< CPU has AVX_VNNI (AVX/VEX encoding of vpdpbusd/vpdpbusds/vpdpwssd/vpdpwssds). + kAVX_VNNI_INT16, //!< CPU has AVX_VNNI_INT16. + kAVX_VNNI_INT8, //!< CPU has AVX_VNNI_INT8. 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. + kCET_SSS, //!< CPU has CET-SSS. kCLDEMOTE, //!< CPU has CLDEMOTE (cache line demote). - kCLFLUSH, //!< CPU has CLFUSH (Cache Line flush). - kCLFLUSHOPT, //!< CPU has CLFUSHOPT (Cache Line flush - optimized). + 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]. + kCMPCCXADD, //!< CPU has CMPCCXADD. + 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). + kF16C, //!< CPU has F16C (AVX FP16 conversion instructions). + kFMA, //!< CPU has FMA (AVX fused-multiply-add - 3 operand form). + kFMA4, //!< CPU has FMA4 (AVX fused-multiply-add - 4 operand form) (deprecated). kFPU, //!< CPU has FPU (FPU support). kFSGSBASE, //!< CPU has FSGSBASE. + kFSRM, //!< CPU has FSRM (fast short REP MOVSB). + kFSRC, //!< CPU has FSRC (fast short REP CMPSB|SCASB). + kFSRS, //!< CPU has FSRS (fast short REP STOSB) 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). + kFZRM, //!< CPU has FZRM (fast zero-length REP MOVSB). + kGEODE, //!< CPU has GEODE extensions (GEODE 3DNOW additions) (deprecated). + 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]. + kINVLPGB, //!< CPU has INVLPGB. + kLAHFSAHF, //!< CPU has LAHF/SAHF (LAHF/SAHF in 64-bit mode) {X86_64}. + kLAM, //!< CPU has LAM (linear address masking) {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). + kMMX, //!< CPU has MMX (MMX base instructions) (deprecated). + kMMX2, //!< CPU has MMX2 (MMX2 extensions or initial SSE extensions) (deprecated). kMONITOR, //!< CPU has MONITOR (MONITOR/MWAIT instructions). kMONITORX, //!< CPU has MONITORX (MONITORX/MWAITX instructions). kMOVBE, //!< CPU has MOVBE (move with byte-order swap). @@ -238,58 +275,78 @@ public: kMOVDIRI, //!< CPU has MOVDIRI (move dword/qword as direct store). kMPX, //!< CPU has MPX (memory protection extensions). kMSR, //!< CPU has MSR (RDMSR/WRMSR instructions). + kMSRLIST, //!< CPU has MSRLIST. 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). + kPREFETCHI, //!< CPU has PREFETCHI. 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. + kRAO_INT, //!< CPU has RAO_INT (AADD, AAND, AOR, AXOR instructions). + kRMPQUERY, //!< CPU has RMPQUERY (RMPQUERY instruction). + kRDPID, //!< CPU has RDPID (RDPID instruction). + kRDPRU, //!< CPU has RDPRU (RDPRU instruction). + kRDRAND, //!< CPU has RDRAND (RDRAND instruction). + kRDSEED, //!< CPU has RDSEED (RDSEED instruction). kRDTSC, //!< CPU has RDTSC. kRDTSCP, //!< CPU has RDTSCP. kRTM, //!< CPU has RTM. + kSEAM, //!< CPU has SEAM. kSERIALIZE, //!< CPU has SERIALIZE. + kSEV, //!< CPU has SEV (secure encrypted virtualization). + kSEV_ES, //!< CPU has SEV_ES (SEV encrypted state). + kSEV_SNP, //!< CPU has SEV_SNP (SEV secure nested paging). kSHA, //!< CPU has SHA (SHA-1 and SHA-256 instructions). - kSKINIT, //!< CPU has SKINIT (SKINIT/STGI instructions) [AMD]. + kSHA512, //!< CPU has SHA512 (SHA-512 instructions). + kSKINIT, //!< CPU has SKINIT (SKINIT/STGI instructions) {AMD}. + kSM3, //!< CPU has SM3 (SM3 hash extensions). + kSM4, //!< CPU has SM4 (SM4 cipher extensions). kSMAP, //!< CPU has SMAP (supervisor-mode access prevention). + kSME , //!< CPU has SME (secure memory encryption). 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]. + kSSE, //!< CPU has SSE (SSE instructions). + kSSE2, //!< CPU has SSE2 (SSE2 instructions). + kSSE3, //!< CPU has SSE3 (SSE3 instructions). + kSSE4_1, //!< CPU has SSE4.1 (SSE4.1 instructions). + kSSE4_2, //!< CPU has SSE4.2 (SSE4.2 instructions). + kSSE4A, //!< CPU has SSE4A (SSE4.A instructions) {AMD} (deprecated). + kSSSE3, //!< CPU has SSSE3 (SSSE3 instructions). + kSVM, //!< CPU has SVM (virtualization) {AMD}. + kTBM, //!< CPU has TBM (trailing bit manipulation) {AMD}. + kTSE, //!< CPU has TSE. 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]. + 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]. + kWRMSRNS, //!< CPU has WRMSRNS. + kXOP, //!< CPU has XOP (XOP instructions) {AMD} (deprecated). kXSAVE, //!< CPU has XSAVE. kXSAVEC, //!< CPU has XSAVEC. kXSAVEOPT, //!< CPU has XSAVEOPT. kXSAVES, //!< CPU has XSAVES. // @EnumValuesEnd@ +#ifndef ASMJIT_NO_DEPRECATED + kAVX512_CDI = kAVX512_CD, + kAVX512_ERI = kAVX512_ER, + kAVX512_PFI = kAVX512_PF, +#endif + kMaxValue = kXSAVES }; #define ASMJIT_X86_FEATURE(FEATURE) \ - inline bool has##FEATURE() const noexcept { return has(X86::k##FEATURE); } + /*! Tests whether FEATURE is present. */ \ + ASMJIT_INLINE_NODEBUG bool has##FEATURE() const noexcept { return has(X86::k##FEATURE); } ASMJIT_X86_FEATURE(MT) ASMJIT_X86_FEATURE(NX) @@ -299,8 +356,11 @@ public: ASMJIT_X86_FEATURE(AESNI) ASMJIT_X86_FEATURE(ALTMOVCR8) ASMJIT_X86_FEATURE(AMX_BF16) + ASMJIT_X86_FEATURE(AMX_COMPLEX) + ASMJIT_X86_FEATURE(AMX_FP16) ASMJIT_X86_FEATURE(AMX_INT8) ASMJIT_X86_FEATURE(AMX_TILE) + ASMJIT_X86_FEATURE(APX_F) ASMJIT_X86_FEATURE(AVX) ASMJIT_X86_FEATURE(AVX2) ASMJIT_X86_FEATURE(AVX512_4FMAPS) @@ -308,24 +368,29 @@ public: ASMJIT_X86_FEATURE(AVX512_BF16) ASMJIT_X86_FEATURE(AVX512_BITALG) ASMJIT_X86_FEATURE(AVX512_BW) - ASMJIT_X86_FEATURE(AVX512_CDI) + ASMJIT_X86_FEATURE(AVX512_CD) ASMJIT_X86_FEATURE(AVX512_DQ) - ASMJIT_X86_FEATURE(AVX512_ERI) + ASMJIT_X86_FEATURE(AVX512_ER) ASMJIT_X86_FEATURE(AVX512_F) ASMJIT_X86_FEATURE(AVX512_FP16) ASMJIT_X86_FEATURE(AVX512_IFMA) - ASMJIT_X86_FEATURE(AVX512_PFI) + ASMJIT_X86_FEATURE(AVX512_PF) 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_IFMA) + ASMJIT_X86_FEATURE(AVX_NE_CONVERT) ASMJIT_X86_FEATURE(AVX_VNNI) + ASMJIT_X86_FEATURE(AVX_VNNI_INT16) + ASMJIT_X86_FEATURE(AVX_VNNI_INT8) ASMJIT_X86_FEATURE(BMI) ASMJIT_X86_FEATURE(BMI2) ASMJIT_X86_FEATURE(CET_IBT) ASMJIT_X86_FEATURE(CET_SS) + ASMJIT_X86_FEATURE(CET_SSS) ASMJIT_X86_FEATURE(CLDEMOTE) ASMJIT_X86_FEATURE(CLFLUSH) ASMJIT_X86_FEATURE(CLFLUSHOPT) @@ -342,14 +407,20 @@ public: ASMJIT_X86_FEATURE(FMA4) ASMJIT_X86_FEATURE(FPU) ASMJIT_X86_FEATURE(FSGSBASE) + ASMJIT_X86_FEATURE(FSRM) + ASMJIT_X86_FEATURE(FSRC) + ASMJIT_X86_FEATURE(FSRS) ASMJIT_X86_FEATURE(FXSR) ASMJIT_X86_FEATURE(FXSROPT) + ASMJIT_X86_FEATURE(FZRM) ASMJIT_X86_FEATURE(GEODE) ASMJIT_X86_FEATURE(GFNI) ASMJIT_X86_FEATURE(HLE) ASMJIT_X86_FEATURE(HRESET) ASMJIT_X86_FEATURE(I486) + ASMJIT_X86_FEATURE(INVLPGB) ASMJIT_X86_FEATURE(LAHFSAHF) + ASMJIT_X86_FEATURE(LAM) ASMJIT_X86_FEATURE(LWP) ASMJIT_X86_FEATURE(LZCNT) ASMJIT_X86_FEATURE(MCOMMIT) @@ -362,15 +433,19 @@ public: ASMJIT_X86_FEATURE(MOVDIRI) ASMJIT_X86_FEATURE(MPX) ASMJIT_X86_FEATURE(MSR) + ASMJIT_X86_FEATURE(MSRLIST) 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(PREFETCHI) ASMJIT_X86_FEATURE(PREFETCHW) ASMJIT_X86_FEATURE(PREFETCHWT1) ASMJIT_X86_FEATURE(PTWRITE) + ASMJIT_X86_FEATURE(RAO_INT) + ASMJIT_X86_FEATURE(RMPQUERY) ASMJIT_X86_FEATURE(RDPID) ASMJIT_X86_FEATURE(RDPRU) ASMJIT_X86_FEATURE(RDRAND) @@ -378,13 +453,16 @@ public: ASMJIT_X86_FEATURE(RDTSC) ASMJIT_X86_FEATURE(RDTSCP) ASMJIT_X86_FEATURE(RTM) + ASMJIT_X86_FEATURE(SEAM) ASMJIT_X86_FEATURE(SERIALIZE) + ASMJIT_X86_FEATURE(SEV) + ASMJIT_X86_FEATURE(SEV_ES) + ASMJIT_X86_FEATURE(SEV_SNP) 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) @@ -394,6 +472,7 @@ public: ASMJIT_X86_FEATURE(SSSE3) ASMJIT_X86_FEATURE(SVM) ASMJIT_X86_FEATURE(TBM) + ASMJIT_X86_FEATURE(TSE) ASMJIT_X86_FEATURE(TSX) ASMJIT_X86_FEATURE(TSXLDTRK) ASMJIT_X86_FEATURE(UINTR) @@ -402,95 +481,248 @@ public: ASMJIT_X86_FEATURE(VPCLMULQDQ) ASMJIT_X86_FEATURE(WAITPKG) ASMJIT_X86_FEATURE(WBNOINVD) + ASMJIT_X86_FEATURE(WRMSRNS) ASMJIT_X86_FEATURE(XOP) ASMJIT_X86_FEATURE(XSAVE) ASMJIT_X86_FEATURE(XSAVEC) ASMJIT_X86_FEATURE(XSAVEOPT) ASMJIT_X86_FEATURE(XSAVES) +#ifndef ASMJIT_NO_DEPRECATED + ASMJIT_DEPRECATED("Use hasAVX512_CD() instead") + ASMJIT_X86_FEATURE(AVX512_CDI) + + ASMJIT_DEPRECATED("Use hasAVX512_ER() instead") + ASMJIT_X86_FEATURE(AVX512_ERI) + + ASMJIT_DEPRECATED("Use hasAVX512_PF() instead") + ASMJIT_X86_FEATURE(AVX512_PFI) +#endif + #undef ASMJIT_X86_FEATURE }; //! ARM specific features data. + //! + //! Naming reference: + //! - https://developer.arm.com/downloads/-/exploration-tools/feature-names-for-a-profile 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.7-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). + + kARMv6, //!< CPU is at least ARMv6 {A32}. + kARMv7, //!< CPU is at least ARMv7 {A32}. + kARMv8a, //!< CPU is at least ARMv8A. + kTHUMB, //!< CPU has THUMB (16-bit THUMB encoding) {A32}. + kTHUMBv2, //!< CPU has THUMBv2 (32-bit THUMB encoding) {A32}. + + kABLE, //!< CPU has ABLE (address breakpoint linking extension) {A64}. + kADERR, //!< CPU has ADERR (asynchronous device error exceptions) {A64}. + kAES, //!< CPU has AES (ASIMD AES instructions). + kAFP, //!< CPU has AFP (alternate floating-point behavior) {A64}. + kAIE, //!< CPU has AIE (memory attribute index enhancement) {A64}. + kAMU1, //!< CPU has AMUv1 (activity monitors extension version 1) {A64}. + kAMU1_1, //!< CPU has AMUv1p1 (activity monitors extension version 1.1) {A64}. + kANERR, //!< CPU has ANERR (asynchronous normal error exception) {A64}. + kASIMD, //!< CPU has ASIMD (NEON on ARM/THUMB). + kBF16, //!< CPU has BF16 (BFloat16 instructions) {A64}. + kBRBE, //!< CPU has BRBE (branch record buffer extension) {A64}. + kBTI, //!< CPU has BTI (branch target identification). + kBWE, //!< CPU has BWE (breakpoint mismatch and range extension) {A64}. + kCCIDX, //!< CPU has CCIDX (extend of the CCSIDR number of sets). + kCHK, //!< CPU has CHK (check feature status - CHKFEAT instruction) {A64}. + kCLRBHB, //!< CPU has CLRBHB (clear BHB instruction). + kCMOW, //!< CPU has CMOW (control for cache maintenance permission) {A64}. + kCONSTPACFIELD, //!< CPU has CONSTPACFIELD (PAC algorithm enhancement) {A64}. + kCPA, //!< CPU has CPA (instruction-only Checked Pointer Arithmetic) {A64}. + kCPA2, //!< CPU has CPA2 (checked Pointer Arithmetic) {A64}. + kCPUID, //!< CPU has CPUID (CPUID registers accessible in user-space). + kCRC32, //!< CPU has CRC32 (CRC32 instructions). + kCSSC, //!< CPU has CSSC (common short sequence compression) {A64}. + kCSV2, //!< CPU has CSV2 (cache speculation variant 2 version 2.1) {A64}. + kCSV2_3, //!< CPU has CSV2_3 (cache speculation variant 2 version 3) {A64}. + kCSV3, //!< CPU has CSV3 (cache speculation Variant 3) {A64}. + kD128, //!< CPU has D128 (128-bit translation tables, 56 bit PA) {A64}. + kDGH, //!< CPU has DGH (data gathering hint) {A64}. + kDIT, //!< CPU has DIT (data independent timing of instructions). + kDOTPROD, //!< CPU has DOTPROD (ASIMD Int8 dot product instructions). + kDPB, //!< CPU has DPB (DC CVAP instruction) {A64}. + kDPB2, //!< CPU has DPB2 (DC CVADP instruction) {A64}. + kEBEP, //!< CPU has EBEP (exception-based event profiling) {A64}. + kEBF16, //!< CPU has EBF16 (extended BFloat16 mode) {A64}. + kECBHB, //!< CPU has ECBHB (exploitative control using branch history information) {A64}. + kECV, //!< CPU has ECV (enhanced counter virtualization). + kEDHSR, //!< CPU has EDHSR (support for EDHSR) {A64}. + kEDSP, //!< CPU has EDSP (ARM/THUMB only). + kFAMINMAX, //!< CPU has FAMINMAX (floating-point maximum and minimum absolute value instructions) {A64}. + kFCMA, //!< CPU has FCMA (FCADD/FCMLA). + kFGT, //!< CPU has FGT (fine-grained traps). + kFGT2, //!< CPU has FGT2 (fine-grained traps 2). + kFHM, //!< CPU has FHM (half-precision floating-point FMLAL instructions). + kFLAGM, //!< CPU has FLAGM (condition flag manipulation) {A64}. + kFLAGM2, //!< CPU has FLAGM2 (condition flag manipulation version v2) {A64}. + kFMAC, //!< CPU has FMAC (ARM/THUMB only). + kFP, //!< CPU has FP (floating-point) (on 32-bit ARM this means VFPv3). + kFP16, //!< CPU has FP16 (half-precision floating-point data processing). + kFP16CONV, //!< CPU has FP16CONV (half-precision float conversion). + kFP8, //!< CPU has FP8 (FP8 convert instructions) {A64}. + kFP8DOT2, //!< CPU has FP8DOT2 (FP8 2-way dot product to half-precision instructions) {A64}. + kFP8DOT4, //!< CPU has FP8DOT4 (FP8 4-way dot product to single-precision instructions) {A64}. + kFP8FMA, //!< CPU has FP8FMA (FP8 multiply-accumulate to half-precision and single-precision instructions) {A64}. + kFPMR, //!< CPU has FPMR (floating-point Mode Register) {A64}. + kFRINTTS, //!< CPU has FRINTTS (FRINT[32|64][X|Z] instructions) {A64}. + kGCS, //!< CPU has GCS (guarded control stack extension) {A64}. + kHACDBS, //!< CPU has HACDBS (hardware accelerator for cleaning Dirty state) {A64}. + kHAFDBS, //!< CPU has HAFDBS (hardware management of the access flag and dirty state) {A64}. + kHAFT, //!< CPU has HAFT (hardware managed access flag for table descriptors) {A64}. + kHDBSS, //!< CPU has HDBSS (hardware Dirty state tracking Structure) {A64}. + kHBC, //!< CPU has HBC (hinted conditional branches) {A64}. + kHCX, //!< CPU has HCX (support for the HCRX_EL2 register) {A64}. + kHPDS, //!< CPU has HPDS (hierarchical permission disables in translation tables ) {A64}. + kHPDS2, //!< CPU has HPDS2 (hierarchical permission disables) {A64}. + kI8MM, //!< CPU has I8MM (int8 matrix multiplication) {A64}. + kIDIVA, //!< CPU has IDIV (hardware SDIV and UDIV in ARM mode). + kIDIVT, //!< CPU has IDIV (hardware SDIV and UDIV in THUMB mode). + kITE, //!< CPU has ITE (instrumentation extension) {A64}. + kJSCVT, //!< CPU has JSCVT (JavaScript FJCVTS conversion instruction) {A64}. + kLOR, //!< CPU has LOR (limited ordering regions extension). + kLRCPC, //!< CPU has LRCPC (load-acquire RCpc instructions) {A64}. + kLRCPC2, //!< CPU has LRCPC2 (load-acquire RCpc instructions v2) {A64}. + kLRCPC3, //!< CPU has LRCPC3 (load-Acquire RCpc instructions v3) {A64}. + kLS64, //!< CPU has LS64 (64 byte loads/stores without return) {A64}. + kLS64_ACCDATA, //!< CPU has LS64_ACCDATA (64-byte EL0 stores with return) {A64}. + kLS64_V, //!< CPU has LS64_V (64-byte stores with return) {A64}. + kLSE, //!< CPU has LSE (large system extensions) {A64}. + kLSE128, //!< CPU has LSE128 (128-bit atomics) {A64}. + kLSE2, //!< CPU has LSE2 (large system extensions v2) {A64}. + kLUT, //!< CPU has LUT (lookup table instructions with 2-bit and 4-bit indices) {A64}. + kLVA, //!< CPU has LVA (large VA support) {A64}. + kLVA3, //!< CPU has LVA3 (56-bit VA) {A64}. + kMEC, //!< CPU has MEC (memory encryption contexts) {A64}. + kMOPS, //!< CPU has MOPS (memcpy and memset acceleration instructions) {A64}. + kMPAM, //!< CPU has MPAM (memory system partitioning and monitoring extension) {A64}. + kMTE, //!< CPU has MTE (instruction-only memory tagging extension) {A64}. + kMTE2, //!< CPU has MTE2 (full memory tagging extension) {A64}. + kMTE3, //!< CPU has MTE3 (MTE asymmetric fault handling) {A64}. + kMTE4, //!< CPU has MTE4 (MTE v4) {A64}. + kMTE_ASYM_FAULT, //!< CPU has MTE_ASYM_FAULT (memory tagging asymmetric faults) {A64}. + kMTE_ASYNC, //!< CPU has MTE_ASYNC (memory tagging asynchronous faulting) {A64}. + kMTE_CANONICAL_TAGS, //!< CPU has MTE_CANONICAL_TAGS (canonical tag checking for untagged memory) {A64}. + kMTE_NO_ADDRESS_TAGS, //!< CPU has MTE_NO_ADDRESS_TAGS (memory tagging with address tagging disabled) {A64}. + kMTE_PERM_S1, //!< CPU has MTE_PERM_S1 (allocation tag access permission) {A64}. + kMTE_STORE_ONLY, //!< CPU has MTE_STORE_ONLY (store-only tag checking) {A64}. + kMTE_TAGGED_FAR, //!< CPU has MTE_TAGGED_FAR (FAR_ELx on a tag check fault) {A64}. + kMTPMU, //!< CPU has MTPMU (multi-threaded PMU extensions) {A64}. + kNMI, //!< CPU has NMI (non-maskable Interrupt) {A64}. + kNV, //!< CPU has NV (nested virtualization enchancement) {A64}. + kNV2, //!< CPU has NV2 (enhanced support for nested virtualization) {A64}. + kPAN, //!< CPU has PAN (privileged access-never extension) {A64}. + kPAN2, //!< CPU has PAN2 (PAN s1e1R and s1e1W variants) {A64}. + kPAN3, //!< CPU has PAN3 (support for SCTLR_ELx.EPAN) {A64}. + kPAUTH, //!< CPU has PAUTH (pointer authentication extension) {A64}. + kPFAR, //!< CPU has PFAR (physical fault address registers) {A64}. + kPMU, //!< CPU has PMU {A64}. + kPMULL, //!< CPU has PMULL (ASIMD PMULL instructions) {A64}. + kPRFMSLC, //!< CPU has PRFMSLC (PRFM instructions support the SLC target) {A64}. + kRAS, //!< CPU has RAS (reliability, availability and serviceability extensions). + kRAS1_1, //!< CPU has RASv1p1 (RAS v1.1). + kRAS2, //!< CPU has RASv2 (RAS v2). + kRASSA2, //!< CPU has RASSAv2 (RAS v2 system architecture). + kRDM, //!< CPU has RDM (rounding double multiply accumulate) {A64}. + kRME, //!< CPU has RME (memory encryption contexts extension) {A64}. + kRNG, //!< CPU has RNG (random number generation). + kRNG_TRAP, //!< CPU has RNG_TRAP (random number trap to EL3 field) {A64}. + kRPRES, //!< CPU has RPRES (increased precision of reciprocal estimate and RSQRT estimate) {A64}. + kRPRFM, //!< CPU has RPRFM (range prefetch hint instruction). + kS1PIE, //!< CPU has S1PIE (permission model enhancements) {A64}. + kS1POE, //!< CPU has S1POE (permission model enhancements) {A64}. + kS2PIE, //!< CPU has S2PIE (permission model enhancements) {A64}. + kS2POE, //!< CPU has S2POE (permission model enhancements) {A64}. + kSB, //!< CPU has SB (speculative barrier). + kSCTLR2, //!< CPU has SCTLR2 (extension to SCTLR_ELx) {A64}. + kSEBEP, //!< CPU has SEBEP (synchronous exception-based event profiling) {A64}. + kSEL2, //!< CPU has SEL2 (secure EL2) {A64}. + kSHA1, //!< CPU has SHA1 (ASIMD SHA1 instructions). + kSHA256, //!< CPU has SHA256 (ASIMD SHA256 instructions). + kSHA3, //!< CPU has SHA3 (ASIMD EOR3, RAX1, XAR, and BCAX instructions). + kSHA512, //!< CPU has SHA512 (ASIMD SHA512 instructions). + kSM3, //!< CPU has SM3 (ASIMD SM3 instructions). + kSM4, //!< CPU has SM4 (ASIMD SM4 instructions). + kSME, //!< CPU has SME (SME v1 - scalable matrix extension) {A64}. + kSME2, //!< CPU has SME2 (SME v2) {A64}. + kSME2_1, //!< CPU has SME2p1 (SME v2.1) {A64}. + kSME_B16B16, //!< CPU has SME_B16B16 (SME non-widening BFloat16 to BFloat16 arithmetic) {A64}. + kSME_B16F32, //!< CPU has SME_B16F32 (BFMOPA and BFMOPS instructions that accumulate BFloat16 outer products into single-precision tiles) {A64}. + kSME_BI32I32, //!< CPU has SME_BI32I32 (BMOPA and BMOPS instructions that accumulate 1-bit binary outer products into 32-bit integer tiles) {A64}. + kSME_F16F16, //!< CPU has SME_F16F16 (SME2.1 non-widening half-precision FP16 to FP16 arithmetic) {A64}. + kSME_F16F32, //!< CPU has SME_F16F32 {A64}. + kSME_F32F32, //!< CPU has SME_F32F32 {A64}. + kSME_F64F64, //!< CPU has SME_F64F64 {A64}. + kSME_F8F16, //!< CPU has SME_F8F16 (SME2 ZA-targeting FP8 multiply-accumulate, dot product, and outer product to half-precision instructions) {A64}. + kSME_F8F32, //!< CPU has SME_F8F32 (SME2 ZA-targeting FP8 multiply-accumulate, dot product, and outer product to single-precision instructions) {A64}. + kSME_FA64, //!< CPU has SME_FA64 {A64}. + kSME_I16I32, //!< CPU has SME_I16I32 {A64}. + kSME_I16I64, //!< CPU has SME_I16I64 {A64}. + kSME_I8I32, //!< CPU has SME_I8I32 {A64}. + kSME_LUTv2, //!< CPU has SME_LUTv2 (lookup table instructions with 4-bit indices and 8-bit elements) {A64}. + kSPE, //!< CPU has SPE (statistical profiling extension) {A64}. + kSPE1_1, //!< CPU has SPEv1p1 (statistical profiling extensions version 1.1) {A64}. + kSPE1_2, //!< CPU has SPEv1p2 (statistical profiling extensions version 1.2) {A64}. + kSPE1_3, //!< CPU has SPEv1p3 (statistical profiling extensions version 1.3) {A64}. + kSPE1_4, //!< CPU has SPEv1p4 (statistical profiling extensions version 1.4) {A64}. + kSPE_ALTCLK, //!< CPU has SPE_ALTCLK (statistical profiling alternate clock domain extension) {A64}. + kSPE_CRR, //!< CPU has SPE_CRR (statistical profiling call return branch records) {A64}. + kSPE_EFT, //!< CPU has SPE_EFT (statistical profiling extended filtering by type) {A64}. + kSPE_FDS, //!< CPU has SPE_FDS (statistical profiling data source filtering) {A64}. + kSPE_FPF, //!< CPU has SPE_FPF (statistical profiling floating-point flag extension) {A64}. + kSPE_SME, //!< CPU has SPE_SME (statistical profiling extensions for SME) {A64}. + kSPECRES, //!< CPU has SPECRES (speculation restriction instructions). + kSPECRES2, //!< CPU has SPECRES2 (clear other speculative predictions). + kSPMU, //!< CPU has SPMU (system performance monitors extension) {A64}. + kSSBS, //!< CPU has SSBS (speculative store bypass safe instruction). + kSSBS2, //!< CPU has SSBS2 (MRS and MSR instructions for SSBS). + kSSVE_FP8DOT2, //!< CPU has SSVE_FP8DOT2 (SVE2 FP8 2-way dot product to half-precision instructions in Streaming SVE mode) {A64}. + kSSVE_FP8DOT4, //!< CPU has SSVE_FP8DOT4 (SVE2 FP8 4-way dot product to single-precision instructions in Streaming SVE mode) {A64}. + kSSVE_FP8FMA, //!< CPU has SSVE_FP8FMA (SVE2 FP8 multiply-accumulate to half-precision and single-precision instructions in Streaming SVE mode) {A64}. + kSVE, //!< CPU has SVE (SVE v1 - scalable vector extension) {A64}. + kSVE2, //!< CPU has SVE2 (SVE v2) {A64}. + kSVE2_1, //!< CPU has SVE2p1 (SVE v2.1) {A64}. + kSVE_AES, //!< CPU has SVE_AES (SVE AES instructions) {A64}. + kSVE_B16B16, //!< CPU has SVE_B16B16 (SVE non-widening BFloat16 to BFloat16 arithmetic) {A64}. + kSVE_BF16, //!< CPU has SVE_BF16 (SVE BF16 instructions) {A64}. + kSVE_BITPERM, //!< CPU has SVE_BITPERM (SVE bit permute) {A64}. + kSVE_EBF16, //!< CPU has SVE_EBF16 (SVE extended BFloat16 mode) {A64}. + kSVE_F32MM, //!< CPU has SVE_F32MM (SVE single-precision floating-point matrix multiply instruction) {A64}. + kSVE_F64MM, //!< CPU has SVE_F64MM (SVE double-precision floating-point matrix multiply instruction) {A64}. + kSVE_I8MM, //!< CPU has SVE_I8MM (SVE int8 matrix multiplication) {A64}. + kSVE_PMULL128, //!< CPU has SVE_PMULL128 (SVE PMULL instructions) {A64}. + kSVE_SHA3, //!< CPU has SVE_SHA3 (SVE SHA-3 instructions) {A64}. + kSVE_SM4, //!< CPU has SVE_SM4 (SVE SM4 instructions {A64}. + kSYSINSTR128, //!< CPU has SYSINSTR128 (128-bit system instructions) {A64}. + kSYSREG128, //!< CPU has SYSREG128 (128-bit system registers) {A64}. + kTHE, //!< CPU has THE (translation hardening extension). + kTLBIOS, //!< CPU has TLBIOS (TLBI instructions in Outer Shareable domain) {A64}. + kTLBIRANGE, //!< CPU has TLBIRANGE (TLBI range instructions) {A64}. + kTLBIW, //!< CPU has TLBIW (TLBI VMALL for dirty state) {A64}. + kTME, //!< CPU has TME (transactional memory extensions). + kTRF, //!< CPU has TRF (self-hosted trace extensions). + kUAO, //!< CPU has UAO (AArch64 v8.2 UAO PState) {A64}. + kVFP_D32, //!< CPU has VFP_D32 (32 VFP-D registers) (ARM/THUMB only). + kVHE, //!< CPU has VHE (virtual host extension). + kVMID16, //!< CPU has VMID16 (16-bit VMID) {A64}. + kWFXT, //!< CPU has WFxT (WFE and WFI instructions with timeout) {A64}. + kXNX, //!< CPU has XNX (translation table stage 2 unprivileged execute-never) {A64}. + kXS, //!< CPU has XS (XS attribute in TLBI and DSB instructions) {A64}. // @EnumValuesEnd@ - kMaxValue = kTME + kMaxValue = kXS }; #define ASMJIT_ARM_FEATURE(FEATURE) \ - inline bool has##FEATURE() const noexcept { return has(ARM::k##FEATURE); } + /*! Tests whether FEATURE is present. */ \ + ASMJIT_INLINE_NODEBUG bool has##FEATURE() const noexcept { return has(ARM::k##FEATURE); } ASMJIT_ARM_FEATURE(THUMB) ASMJIT_ARM_FEATURE(THUMBv2) @@ -498,67 +730,204 @@ public: 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(ABLE) + ASMJIT_ARM_FEATURE(ADERR) ASMJIT_ARM_FEATURE(AES) - ASMJIT_ARM_FEATURE(ALTNZCV) + ASMJIT_ARM_FEATURE(AFP) + ASMJIT_ARM_FEATURE(AIE) + ASMJIT_ARM_FEATURE(AMU1) + ASMJIT_ARM_FEATURE(AMU1_1) + ASMJIT_ARM_FEATURE(ANERR) ASMJIT_ARM_FEATURE(ASIMD) ASMJIT_ARM_FEATURE(BF16) + ASMJIT_ARM_FEATURE(BRBE) ASMJIT_ARM_FEATURE(BTI) + ASMJIT_ARM_FEATURE(BWE) + ASMJIT_ARM_FEATURE(CCIDX) + ASMJIT_ARM_FEATURE(CHK) + ASMJIT_ARM_FEATURE(CLRBHB) + ASMJIT_ARM_FEATURE(CMOW) + ASMJIT_ARM_FEATURE(CONSTPACFIELD) + ASMJIT_ARM_FEATURE(CPA) + ASMJIT_ARM_FEATURE(CPA2) ASMJIT_ARM_FEATURE(CPUID) ASMJIT_ARM_FEATURE(CRC32) + ASMJIT_ARM_FEATURE(CSSC) + ASMJIT_ARM_FEATURE(CSV2) + ASMJIT_ARM_FEATURE(CSV2_3) + ASMJIT_ARM_FEATURE(CSV3) + ASMJIT_ARM_FEATURE(D128) ASMJIT_ARM_FEATURE(DGH) ASMJIT_ARM_FEATURE(DIT) ASMJIT_ARM_FEATURE(DOTPROD) + ASMJIT_ARM_FEATURE(DPB) + ASMJIT_ARM_FEATURE(DPB2) + ASMJIT_ARM_FEATURE(EBEP) + ASMJIT_ARM_FEATURE(EBF16) + ASMJIT_ARM_FEATURE(ECBHB) + ASMJIT_ARM_FEATURE(ECV) + ASMJIT_ARM_FEATURE(EDHSR) ASMJIT_ARM_FEATURE(EDSP) + ASMJIT_ARM_FEATURE(FAMINMAX) ASMJIT_ARM_FEATURE(FCMA) + ASMJIT_ARM_FEATURE(FGT) + ASMJIT_ARM_FEATURE(FGT2) + ASMJIT_ARM_FEATURE(FHM) ASMJIT_ARM_FEATURE(FLAGM) + ASMJIT_ARM_FEATURE(FLAGM2) + ASMJIT_ARM_FEATURE(FMAC) + ASMJIT_ARM_FEATURE(FP) + ASMJIT_ARM_FEATURE(FP16) ASMJIT_ARM_FEATURE(FP16CONV) - ASMJIT_ARM_FEATURE(FP16FML) - ASMJIT_ARM_FEATURE(FP16FULL) - ASMJIT_ARM_FEATURE(FRINT) + ASMJIT_ARM_FEATURE(FP8) + ASMJIT_ARM_FEATURE(FP8DOT2) + ASMJIT_ARM_FEATURE(FP8DOT4) + ASMJIT_ARM_FEATURE(FP8FMA) + ASMJIT_ARM_FEATURE(FPMR) + ASMJIT_ARM_FEATURE(FRINTTS) + ASMJIT_ARM_FEATURE(GCS) + ASMJIT_ARM_FEATURE(HACDBS) + ASMJIT_ARM_FEATURE(HAFDBS) + ASMJIT_ARM_FEATURE(HAFT) + ASMJIT_ARM_FEATURE(HDBSS) + ASMJIT_ARM_FEATURE(HBC) + ASMJIT_ARM_FEATURE(HCX) + ASMJIT_ARM_FEATURE(HPDS) + ASMJIT_ARM_FEATURE(HPDS2) + ASMJIT_ARM_FEATURE(I8MM) ASMJIT_ARM_FEATURE(IDIVA) ASMJIT_ARM_FEATURE(IDIVT) + ASMJIT_ARM_FEATURE(ITE) + ASMJIT_ARM_FEATURE(JSCVT) + ASMJIT_ARM_FEATURE(LOR) + ASMJIT_ARM_FEATURE(LRCPC) + ASMJIT_ARM_FEATURE(LRCPC2) + ASMJIT_ARM_FEATURE(LRCPC3) + ASMJIT_ARM_FEATURE(LS64) + ASMJIT_ARM_FEATURE(LS64_ACCDATA) + ASMJIT_ARM_FEATURE(LS64_V) ASMJIT_ARM_FEATURE(LSE) + ASMJIT_ARM_FEATURE(LSE128) + ASMJIT_ARM_FEATURE(LSE2) + ASMJIT_ARM_FEATURE(LUT) + ASMJIT_ARM_FEATURE(LVA) + ASMJIT_ARM_FEATURE(LVA3) + ASMJIT_ARM_FEATURE(MEC) + ASMJIT_ARM_FEATURE(MOPS) + ASMJIT_ARM_FEATURE(MPAM) ASMJIT_ARM_FEATURE(MTE) - ASMJIT_ARM_FEATURE(FJCVTZS) - ASMJIT_ARM_FEATURE(I8MM) - ASMJIT_ARM_FEATURE(RCPC_IMMO) - ASMJIT_ARM_FEATURE(RDM) + ASMJIT_ARM_FEATURE(MTE2) + ASMJIT_ARM_FEATURE(MTE3) + ASMJIT_ARM_FEATURE(MTE4) + ASMJIT_ARM_FEATURE(MTE_ASYM_FAULT) + ASMJIT_ARM_FEATURE(MTE_ASYNC) + ASMJIT_ARM_FEATURE(MTE_CANONICAL_TAGS) + ASMJIT_ARM_FEATURE(MTE_NO_ADDRESS_TAGS) + ASMJIT_ARM_FEATURE(MTE_PERM_S1) + ASMJIT_ARM_FEATURE(MTE_STORE_ONLY) + ASMJIT_ARM_FEATURE(MTE_TAGGED_FAR) + ASMJIT_ARM_FEATURE(MTPMU) + ASMJIT_ARM_FEATURE(NMI) + ASMJIT_ARM_FEATURE(NV) + ASMJIT_ARM_FEATURE(NV2) + ASMJIT_ARM_FEATURE(PAN) + ASMJIT_ARM_FEATURE(PAN2) + ASMJIT_ARM_FEATURE(PAN3) + ASMJIT_ARM_FEATURE(PAUTH) + ASMJIT_ARM_FEATURE(PFAR) ASMJIT_ARM_FEATURE(PMU) ASMJIT_ARM_FEATURE(PMULL) + ASMJIT_ARM_FEATURE(PRFMSLC) + ASMJIT_ARM_FEATURE(RAS) + ASMJIT_ARM_FEATURE(RAS1_1) + ASMJIT_ARM_FEATURE(RAS2) + ASMJIT_ARM_FEATURE(RASSA2) + ASMJIT_ARM_FEATURE(RDM) + ASMJIT_ARM_FEATURE(RME) ASMJIT_ARM_FEATURE(RNG) + ASMJIT_ARM_FEATURE(RNG_TRAP) + ASMJIT_ARM_FEATURE(RPRES) + ASMJIT_ARM_FEATURE(RPRFM) + ASMJIT_ARM_FEATURE(S1PIE) + ASMJIT_ARM_FEATURE(S1POE) + ASMJIT_ARM_FEATURE(S2PIE) + ASMJIT_ARM_FEATURE(S2POE) ASMJIT_ARM_FEATURE(SB) + ASMJIT_ARM_FEATURE(SCTLR2) + ASMJIT_ARM_FEATURE(SEBEP) + ASMJIT_ARM_FEATURE(SEL2) ASMJIT_ARM_FEATURE(SHA1) - ASMJIT_ARM_FEATURE(SHA2) + ASMJIT_ARM_FEATURE(SHA256) ASMJIT_ARM_FEATURE(SHA3) ASMJIT_ARM_FEATURE(SHA512) ASMJIT_ARM_FEATURE(SM3) ASMJIT_ARM_FEATURE(SM4) + ASMJIT_ARM_FEATURE(SME) + ASMJIT_ARM_FEATURE(SME2) + ASMJIT_ARM_FEATURE(SME2_1) + ASMJIT_ARM_FEATURE(SME_B16B16) + ASMJIT_ARM_FEATURE(SME_B16F32) + ASMJIT_ARM_FEATURE(SME_BI32I32) + ASMJIT_ARM_FEATURE(SME_F16F16) + ASMJIT_ARM_FEATURE(SME_F16F32) + ASMJIT_ARM_FEATURE(SME_F32F32) + ASMJIT_ARM_FEATURE(SME_F64F64) + ASMJIT_ARM_FEATURE(SME_F8F16) + ASMJIT_ARM_FEATURE(SME_F8F32) + ASMJIT_ARM_FEATURE(SME_FA64) + ASMJIT_ARM_FEATURE(SME_I16I32) + ASMJIT_ARM_FEATURE(SME_I16I64) + ASMJIT_ARM_FEATURE(SME_I8I32) + ASMJIT_ARM_FEATURE(SME_LUTv2) + ASMJIT_ARM_FEATURE(SPE) + ASMJIT_ARM_FEATURE(SPE1_1) + ASMJIT_ARM_FEATURE(SPE1_2) + ASMJIT_ARM_FEATURE(SPE1_3) + ASMJIT_ARM_FEATURE(SPE1_4) + ASMJIT_ARM_FEATURE(SPE_ALTCLK) + ASMJIT_ARM_FEATURE(SPE_CRR) + ASMJIT_ARM_FEATURE(SPE_EFT) + ASMJIT_ARM_FEATURE(SPE_FDS) + ASMJIT_ARM_FEATURE(SPE_FPF) + ASMJIT_ARM_FEATURE(SPE_SME) + ASMJIT_ARM_FEATURE(SPECRES) + ASMJIT_ARM_FEATURE(SPECRES2) + ASMJIT_ARM_FEATURE(SPMU) ASMJIT_ARM_FEATURE(SSBS) + ASMJIT_ARM_FEATURE(SSBS2) + ASMJIT_ARM_FEATURE(SSVE_FP8DOT2) + ASMJIT_ARM_FEATURE(SSVE_FP8DOT4) + ASMJIT_ARM_FEATURE(SSVE_FP8FMA) ASMJIT_ARM_FEATURE(SVE) + ASMJIT_ARM_FEATURE(SVE2) + ASMJIT_ARM_FEATURE(SVE2_1) + ASMJIT_ARM_FEATURE(SVE_AES) + ASMJIT_ARM_FEATURE(SVE_B16B16) ASMJIT_ARM_FEATURE(SVE_BF16) + ASMJIT_ARM_FEATURE(SVE_BITPERM) + ASMJIT_ARM_FEATURE(SVE_EBF16) 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(SVE_PMULL128) + ASMJIT_ARM_FEATURE(SVE_SHA3) + ASMJIT_ARM_FEATURE(SVE_SM4) + ASMJIT_ARM_FEATURE(SYSINSTR128) + ASMJIT_ARM_FEATURE(SYSREG128) + ASMJIT_ARM_FEATURE(THE) + ASMJIT_ARM_FEATURE(TLBIOS) + ASMJIT_ARM_FEATURE(TLBIRANGE) + ASMJIT_ARM_FEATURE(TLBIW) ASMJIT_ARM_FEATURE(TME) + ASMJIT_ARM_FEATURE(TRF) + ASMJIT_ARM_FEATURE(UAO) + ASMJIT_ARM_FEATURE(VFP_D32) + ASMJIT_ARM_FEATURE(VHE) + ASMJIT_ARM_FEATURE(VMID16) + ASMJIT_ARM_FEATURE(WFXT) + ASMJIT_ARM_FEATURE(XNX) + ASMJIT_ARM_FEATURE(XS) #undef ASMJIT_ARM_FEATURE }; @@ -578,19 +947,20 @@ public: //! \name Construction & Destruction //! \{ - inline CpuFeatures() noexcept {} - inline CpuFeatures(const CpuFeatures& other) noexcept = default; - inline explicit CpuFeatures(Globals::NoInit_) noexcept {} + ASMJIT_INLINE_NODEBUG CpuFeatures() noexcept {} + ASMJIT_INLINE_NODEBUG CpuFeatures(const CpuFeatures& other) noexcept = default; + ASMJIT_INLINE_NODEBUG explicit CpuFeatures(const Data& other) noexcept : _data{other._bits} {} + ASMJIT_INLINE_NODEBUG explicit CpuFeatures(Globals::NoInit_) noexcept {} //! \} //! \name Overloaded Operators //! \{ - inline CpuFeatures& operator=(const CpuFeatures& other) noexcept = default; + ASMJIT_INLINE_NODEBUG 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); } + ASMJIT_INLINE_NODEBUG bool operator==(const CpuFeatures& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const CpuFeatures& other) const noexcept { return !equals(other); } //! \} @@ -598,64 +968,74 @@ public: //! \{ //! Returns true if there are no features set. - inline bool empty() const noexcept { return _data.empty(); } + ASMJIT_INLINE_NODEBUG 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); } + ASMJIT_INLINE_NODEBUG 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); } + ASMJIT_INLINE_NODEBUG 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>(); } + ASMJIT_INLINE_NODEBUG X86& x86() noexcept { return data<X86>(); } //! Returns CpuFeatures::Data as \ref CpuFeatures::X86 (const). - inline const X86& x86() const noexcept { return data<X86>(); } + ASMJIT_INLINE_NODEBUG const X86& x86() const noexcept { return data<X86>(); } //! Returns CpuFeatures::Data as \ref CpuFeatures::ARM. - inline ARM& arm() noexcept { return data<ARM>(); } + ASMJIT_INLINE_NODEBUG ARM& arm() noexcept { return data<ARM>(); } //! Returns CpuFeatures::Data as \ref CpuFeatures::ARM (const). - inline const ARM& arm() const noexcept { return data<ARM>(); } + ASMJIT_INLINE_NODEBUG 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(); } + ASMJIT_INLINE_NODEBUG BitWord* bits() noexcept { return _data.bits(); } //! Returns all features as array of bitwords (const). - inline const BitWord* bits() const noexcept { return _data.bits(); } + ASMJIT_INLINE_NODEBUG 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(); } + ASMJIT_INLINE_NODEBUG 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(); } + ASMJIT_INLINE_NODEBUG 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); } + ASMJIT_INLINE_NODEBUG bool has(const FeatureId& featureId) const noexcept { return _data.has(featureId); } + + //! Tests whether any of the features is present. + template<typename... Args> + ASMJIT_INLINE_NODEBUG bool hasAny(Args&&... args) const noexcept { return _data.hasAny(std::forward<Args>(args)...); } //! Tests whether all features as defined by `other` are present. - inline bool hasAll(const CpuFeatures& other) const noexcept { return _data.hasAll(other._data); } + ASMJIT_INLINE_NODEBUG bool hasAll(const CpuFeatures& other) const noexcept { return _data.hasAll(other._data); } //! \} //! \name Manipulation //! \{ - inline void reset() noexcept { _data.reset(); } + //! Clears all features set. + ASMJIT_INLINE_NODEBUG 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)...); } + ASMJIT_INLINE_NODEBUG 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)...); } + ASMJIT_INLINE_NODEBUG 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)...); } + ASMJIT_INLINE_NODEBUG 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); } + ASMJIT_INLINE_NODEBUG bool equals(const CpuFeatures& other) const noexcept { return _data.equals(other._data); } + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use CpuFeatures::equals() instead") + ASMJIT_INLINE_NODEBUG bool eq(const CpuFeatures& other) const noexcept { return equals(other); } +#endif // !ASMJIT_NO_DEPRECATED //! \} }; @@ -667,65 +1047,82 @@ public: //! \{ //! Architecture. - Arch _arch; + Arch _arch {}; //! Sub-architecture. - SubArch _subArch; + SubArch _subArch {}; //! True if the CPU was detected, false if the detection failed or it's not available. - bool _wasDetected; + bool _wasDetected {}; //! Reserved for future use. - uint8_t _reserved; + uint8_t _reserved {}; //! CPU family ID. - uint32_t _familyId; + uint32_t _familyId {}; //! CPU model ID. - uint32_t _modelId; + uint32_t _modelId {}; //! CPU brand ID. - uint32_t _brandId; + uint32_t _brandId {}; //! CPU stepping. - uint32_t _stepping; + uint32_t _stepping {}; //! Processor type. - uint32_t _processorType; + uint32_t _processorType {}; //! Maximum number of addressable IDs for logical processors. - uint32_t _maxLogicalProcessors; + uint32_t _maxLogicalProcessors {}; //! Cache line size (in bytes). - uint32_t _cacheLineSize; + uint32_t _cacheLineSize {}; //! Number of hardware threads. - uint32_t _hwThreadCount; + uint32_t _hwThreadCount {}; //! CPU vendor string. - FixedString<16> _vendor; + FixedString<16> _vendor {}; //! CPU brand string. - FixedString<64> _brand; + FixedString<64> _brand {}; //! CPU features. - CpuFeatures _features; + CpuFeatures _features {}; //! \} //! \name Construction & Destruction //! \{ - inline CpuInfo() noexcept { reset(); } - inline CpuInfo(const CpuInfo& other) noexcept = default; + //! Creates a new CpuInfo instance. + ASMJIT_INLINE_NODEBUG CpuInfo() noexcept {} + //! Creates a copy of `other` instance. + ASMJIT_INLINE_NODEBUG CpuInfo(const CpuInfo& other) noexcept = default; - inline explicit CpuInfo(Globals::NoInit_) noexcept + //! Creates an unitialized `CpuInfo` instance. + ASMJIT_INLINE_NODEBUG explicit CpuInfo(Globals::NoInit_) noexcept : _features(Globals::NoInit) {}; + //! \} + + //! \name CPU Information Detection + //! \{ + //! Returns the host CPU information. + //! + //! \note The returned reference is global - it's setup only once and then shared. ASMJIT_API static const CpuInfo& host() noexcept; - //! 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; - } + //! \} + + //! \name Overloaded Operators + //! \{ - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + //! Copy assignment. + ASMJIT_INLINE_NODEBUG CpuInfo& operator=(const CpuInfo& other) noexcept = default; //! \} - //! \name Overloaded Operators + //! \name Initialization & Reset //! \{ - inline CpuInfo& operator=(const CpuInfo& other) noexcept = default; + //! Initializes CpuInfo architecture and sub-architecture members to `arch` and `subArch`, respectively. + ASMJIT_INLINE_NODEBUG void initArch(Arch arch, SubArch subArch = SubArch::kUnknown) noexcept { + _arch = arch; + _subArch = subArch; + } + + //! Resets this \ref CpuInfo to a default constructed state. + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = CpuInfo{}; } //! \} @@ -733,75 +1130,89 @@ public: //! \{ //! Returns the CPU architecture this information relates to. - inline Arch arch() const noexcept { return _arch; } + ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; } //! Returns the CPU sub-architecture this information relates to. - inline SubArch subArch() const noexcept { return _subArch; } + ASMJIT_INLINE_NODEBUG 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; } + ASMJIT_INLINE_NODEBUG 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; } + //! The information provided depends on architecture and OS: + //! - X86: + //! - Family identifier matches the FamilyId read by using CPUID. + //! - ARM: + //! - Apple - returns Apple Family identifier returned by sysctlbyname("hw.cpufamily"). + ASMJIT_INLINE_NODEBUG uint32_t familyId() const noexcept { return _familyId; } //! Returns the CPU model ID. //! - //! Family identifier matches the ModelId read by using CPUID on X86 architecture. + //! The information provided depends on architecture and OS: + //! - X86: + //! - Model identifier matches the ModelId read by using CPUID. + ASMJIT_INLINE_NODEBUG uint32_t modelId() const noexcept { return _modelId; } - 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; } + //! The information provided depends on architecture and OS: + //! - X86: + //! - Brand identifier matches the BrandId read by using CPUID. + ASMJIT_INLINE_NODEBUG 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; } + //! The information provided depends on architecture and OS: + //! - X86: + //! - Stepping identifier matches the Stepping information read by using CPUID. + ASMJIT_INLINE_NODEBUG 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; } + //! The information provided depends on architecture and OS: + //! - X86: + //! - Processor type identifier matches the ProcessorType read by using CPUID. + ASMJIT_INLINE_NODEBUG uint32_t processorType() const noexcept { return _processorType; } //! Returns the maximum number of logical processors. - inline uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; } + ASMJIT_INLINE_NODEBUG uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; } - //! Returns the size of a cache line flush. - inline uint32_t cacheLineSize() const noexcept { return _cacheLineSize; } + //! Returns the size of a CPU cache line. + //! + //! On a multi-architecture system this should return the smallest cache line of all CPUs. + ASMJIT_INLINE_NODEBUG uint32_t cacheLineSize() const noexcept { return _cacheLineSize; } //! Returns number of hardware threads available. - inline uint32_t hwThreadCount() const noexcept { return _hwThreadCount; } + ASMJIT_INLINE_NODEBUG uint32_t hwThreadCount() const noexcept { return _hwThreadCount; } //! Returns a CPU vendor string. - inline const char* vendor() const noexcept { return _vendor.str; } + ASMJIT_INLINE_NODEBUG const char* vendor() const noexcept { return _vendor.str; } //! Tests whether the CPU vendor string is equal to `s`. - inline bool isVendor(const char* s) const noexcept { return _vendor.eq(s); } + ASMJIT_INLINE_NODEBUG bool isVendor(const char* s) const noexcept { return _vendor.equals(s); } //! Returns a CPU brand string. - inline const char* brand() const noexcept { return _brand.str; } + ASMJIT_INLINE_NODEBUG const char* brand() const noexcept { return _brand.str; } //! Returns CPU features. - inline CpuFeatures& features() noexcept { return _features; } + ASMJIT_INLINE_NODEBUG CpuFeatures& features() noexcept { return _features; } //! Returns CPU features (const). - inline const CpuFeatures& features() const noexcept { return _features; } + ASMJIT_INLINE_NODEBUG const CpuFeatures& features() const noexcept { return _features; } //! Tests whether the CPU has the given `feature`. template<typename FeatureId> - inline bool hasFeature(const FeatureId& featureId) const noexcept { return _features.has(featureId); } + ASMJIT_INLINE_NODEBUG 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)...); } + ASMJIT_INLINE_NODEBUG 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)...); } + ASMJIT_INLINE_NODEBUG void removeFeature(Args&&... args) noexcept { return _features.remove(std::forward<Args>(args)...); } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/emithelper.cpp b/3rdparty/asmjit/src/asmjit/core/emithelper.cpp index bcdf098f48b..36b984f832f 100644 --- a/3rdparty/asmjit/src/asmjit/core/emithelper.cpp +++ b/3rdparty/asmjit/src/asmjit/core/emithelper.cpp @@ -61,6 +61,24 @@ static void dumpAssignment(String& sb, const FuncArgsContext& ctx) noexcept { } #endif +// BaseEmitHelper - Abstract +// ========================= + +Error BaseEmitHelper::emitRegMove(const Operand_& dst_, const Operand_& src_, TypeId typeId, const char* comment) { + DebugUtils::unused(dst_, src_, typeId, comment); + return DebugUtils::errored(kErrorInvalidState); +} + +Error BaseEmitHelper::emitRegSwap(const BaseReg& a, const BaseReg& b, const char* comment) { + DebugUtils::unused(a, b, comment); + return DebugUtils::errored(kErrorInvalidState); +} + +Error BaseEmitHelper::emitArgMove(const BaseReg& dst_, TypeId dstTypeId, const Operand_& src_, TypeId srcTypeId, const char* comment) { + DebugUtils::unused(dst_, dstTypeId, src_, srcTypeId, comment); + return DebugUtils::errored(kErrorInvalidState); +} + // BaseEmitHelper - EmitArgsAssignment // =================================== @@ -198,14 +216,17 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram } else { WorkData& wd = workData[outGroup]; - if (!wd.isAssigned(outId)) { + if (!wd.isAssigned(outId) || curId == outId) { EmitMove: ASMJIT_PROPAGATE( emitArgMove( BaseReg(archTraits.regTypeToSignature(out.regType()), outId), out.typeId(), BaseReg(archTraits.regTypeToSignature(cur.regType()), curId), cur.typeId())); - wd.reassign(varId, outId, curId); + // Only reassign if this is not a sign/zero extension that happens on the same in/out register. + if (curId != outId) + wd.reassign(varId, outId, curId); + cur.initReg(out.regType(), outId, out.typeId()); if (outId == out.regId()) diff --git a/3rdparty/asmjit/src/asmjit/core/emithelper_p.h b/3rdparty/asmjit/src/asmjit/core/emithelper_p.h index 0333959e144..0f4a2f3ece4 100644 --- a/3rdparty/asmjit/src/asmjit/core/emithelper_p.h +++ b/3rdparty/asmjit/src/asmjit/core/emithelper_p.h @@ -21,22 +21,22 @@ class BaseEmitHelper { public: BaseEmitter* _emitter; - inline explicit BaseEmitHelper(BaseEmitter* emitter = nullptr) noexcept + ASMJIT_INLINE_NODEBUG explicit BaseEmitHelper(BaseEmitter* emitter = nullptr) noexcept : _emitter(emitter) {} - inline BaseEmitter* emitter() const noexcept { return _emitter; } - inline void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; } + ASMJIT_INLINE_NODEBUG BaseEmitter* emitter() const noexcept { return _emitter; } + ASMJIT_INLINE_NODEBUG void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; } //! Emits a pure move operation between two registers or the same type or between a register and its home //! slot. This function does not handle register conversion. virtual Error emitRegMove( const Operand_& dst_, - const Operand_& src_, TypeId typeId, const char* comment = nullptr) = 0; + const Operand_& src_, TypeId typeId, const char* comment = nullptr); //! Emits swap between two registers. virtual Error emitRegSwap( const BaseReg& a, - const BaseReg& b, const char* comment = nullptr) = 0; + const BaseReg& b, const char* comment = nullptr); //! Emits move from a function argument (either register or stack) to a register. //! @@ -45,7 +45,7 @@ public: //! (for example conversion from K to MMX on X86/X64) will fail. virtual Error emitArgMove( const BaseReg& dst_, TypeId dstTypeId, - const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr) = 0; + const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr); Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args); }; diff --git a/3rdparty/asmjit/src/asmjit/core/emitter.cpp b/3rdparty/asmjit/src/asmjit/core/emitter.cpp index 92d67a7e5b5..4c855ea5688 100644 --- a/3rdparty/asmjit/src/asmjit/core/emitter.cpp +++ b/3rdparty/asmjit/src/asmjit/core/emitter.cpp @@ -125,13 +125,39 @@ Error BaseEmitter::reportError(Error err, const char* message) { return err; } +// BaseEmitter - Sections +// ====================== + +// [[pure virtual]] +Error BaseEmitter::section(Section* section) { + DebugUtils::unused(section); + return DebugUtils::errored(kErrorInvalidState); +} + // BaseEmitter - Labels // ==================== +// [[pure virtual]] +Label BaseEmitter::newLabel() { + return Label(Globals::kInvalidId); +} + +// [[pure virtual]] +Label BaseEmitter::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) { + DebugUtils::unused(name, nameSize, type, parentId); + return Label(Globals::kInvalidId); +} + Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept { return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : Globals::kInvalidId); } +// [[pure virtual]] +Error BaseEmitter::bind(const Label& label) { + DebugUtils::unused(label); + return DebugUtils::errored(kErrorInvalidState); +} + bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept { return _code && labelId < _code->labelCount(); } @@ -172,6 +198,12 @@ Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, return _emit(instId, o0, o1, o2, opExt); } +// [[pure virtual]] +Error BaseEmitter::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) { + DebugUtils::unused(instId, o0, o1, o2, oExt); + return DebugUtils::errored(kErrorInvalidState); +} + Error BaseEmitter::_emitOpArray(InstId instId, const Operand_* operands, size_t opCount) { const Operand_* op = operands; Operand_ opExt[3]; @@ -233,9 +265,57 @@ Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssi return _funcs.emitArgsAssignment(this, frame, args); } +// BaseEmitter - Align +// =================== + +// [[pure virtual]] +Error BaseEmitter::align(AlignMode alignMode, uint32_t alignment) { + DebugUtils::unused(alignMode, alignment); + return DebugUtils::errored(kErrorInvalidState); +} + +// BaseEmitter - Embed +// =================== + +// [[pure virtual]] +Error BaseEmitter::embed(const void* data, size_t dataSize) { + DebugUtils::unused(data, dataSize); + return DebugUtils::errored(kErrorInvalidState); +} + +// [[pure virtual]] +Error BaseEmitter::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) { + DebugUtils::unused(typeId, data, itemCount, repeatCount); + return DebugUtils::errored(kErrorInvalidState); +} + +// [[pure virtual]] +Error BaseEmitter::embedConstPool(const Label& label, const ConstPool& pool) { + DebugUtils::unused(label, pool); + return DebugUtils::errored(kErrorInvalidState); +} + +// [[pure virtual]] +Error BaseEmitter::embedLabel(const Label& label, size_t dataSize) { + DebugUtils::unused(label, dataSize); + return DebugUtils::errored(kErrorInvalidState); +} + +// [[pure virtual]] +Error BaseEmitter::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) { + DebugUtils::unused(label, base, dataSize); + return DebugUtils::errored(kErrorInvalidState); +} + // BaseEmitter - Comment // ===================== +// [[pure virtual]] +Error BaseEmitter::comment(const char* data, size_t size) { + DebugUtils::unused(data, size); + return DebugUtils::errored(kErrorInvalidState); +} + Error BaseEmitter::commentf(const char* fmt, ...) { if (!hasEmitterFlag(EmitterFlags::kLogComments)) { if (!hasEmitterFlag(EmitterFlags::kAttached)) @@ -304,6 +384,7 @@ Error BaseEmitter::onDetach(CodeHolder* code) noexcept { _errorHandler = nullptr; _clearEmitterFlags(~kEmitterPreservedFlags); + _instructionAlignment = uint8_t(0); _forcedInstOptions = InstOptions::kReserved; _privateData = 0; @@ -313,6 +394,7 @@ Error BaseEmitter::onDetach(CodeHolder* code) noexcept { _instOptions = InstOptions::kNone; _extraReg.reset(); _inlineComment = nullptr; + _funcs.reset(); return kErrorOk; } diff --git a/3rdparty/asmjit/src/asmjit/core/emitter.h b/3rdparty/asmjit/src/asmjit/core/emitter.h index b8afd6b8e06..3053721c9c6 100644 --- a/3rdparty/asmjit/src/asmjit/core/emitter.h +++ b/3rdparty/asmjit/src/asmjit/core/emitter.h @@ -194,6 +194,7 @@ ASMJIT_DEFINE_ENUM_FLAGS(DiagnosticOptions) class ASMJIT_VIRTAPI BaseEmitter { public: ASMJIT_BASE_CLASS(BaseEmitter) + ASMJIT_NONCOPYABLE(BaseEmitter) //! \name Members //! \{ @@ -202,6 +203,11 @@ public: EmitterType _emitterType = EmitterType::kNone; //! See \ref EmitterFlags. EmitterFlags _emitterFlags = EmitterFlags::kNone; + //! Instruction alignment. + uint8_t _instructionAlignment = 0u; + //! \cond + uint8_t _reservedBaseEmitter = 0u; + //! \endcond //! Validation flags in case validation is used. //! //! \note Validation flags are specific to the emitter and they are setup at construction time and then never @@ -233,6 +239,13 @@ public: //! Native GP register signature and signature related information. OperandSignature _gpSignature {}; + //! Emitter state that can be used to specify options and inline comment of a next node or instruction. + struct State { + InstOptions options; + RegOnly extraReg; + const char* comment; + }; + //! Next instruction options (affects the next instruction). InstOptions _instOptions = InstOptions::kNone; //! Extra register (op-mask {k} on AVX-512) (affects the next instruction). @@ -255,7 +268,7 @@ public: Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) ASMJIT_NOEXCEPT_TYPE; - typedef Error (ASMJIT_CDECL* ValidateFunc)(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) ASMJIT_NOEXCEPT_TYPE; + typedef Error (ASMJIT_CDECL* ValidateFunc)(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) ASMJIT_NOEXCEPT_TYPE; //! Emit prolog implementation. EmitProlog emitProlog; @@ -269,7 +282,7 @@ public: ValidateFunc validate; //! Resets all functions to nullptr. - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { emitProlog = nullptr; emitEpilog = nullptr; emitArgsAssignment = nullptr; @@ -293,10 +306,10 @@ public: //! \{ template<typename T> - inline T* as() noexcept { return reinterpret_cast<T*>(this); } + ASMJIT_INLINE_NODEBUG T* as() noexcept { return reinterpret_cast<T*>(this); } template<typename T> - inline const T* as() const noexcept { return reinterpret_cast<const T*>(this); } + ASMJIT_INLINE_NODEBUG const T* as() const noexcept { return reinterpret_cast<const T*>(this); } //! \} @@ -304,54 +317,72 @@ public: //! \{ //! Returns the type of this emitter, see `EmitterType`. - inline EmitterType emitterType() const noexcept { return _emitterType; } + ASMJIT_INLINE_NODEBUG EmitterType emitterType() const noexcept { return _emitterType; } //! Returns emitter flags , see `Flags`. - inline EmitterFlags emitterFlags() const noexcept { return _emitterFlags; } + ASMJIT_INLINE_NODEBUG EmitterFlags emitterFlags() const noexcept { return _emitterFlags; } //! Tests whether the emitter inherits from `BaseAssembler`. - inline bool isAssembler() const noexcept { return _emitterType == EmitterType::kAssembler; } + ASMJIT_INLINE_NODEBUG bool isAssembler() const noexcept { return _emitterType == EmitterType::kAssembler; } //! Tests whether the emitter inherits from `BaseBuilder`. //! //! \note Both Builder and Compiler emitters would return `true`. - inline bool isBuilder() const noexcept { return uint32_t(_emitterType) >= uint32_t(EmitterType::kBuilder); } + ASMJIT_INLINE_NODEBUG bool isBuilder() const noexcept { return uint32_t(_emitterType) >= uint32_t(EmitterType::kBuilder); } //! Tests whether the emitter inherits from `BaseCompiler`. - inline bool isCompiler() const noexcept { return _emitterType == EmitterType::kCompiler; } + ASMJIT_INLINE_NODEBUG bool isCompiler() const noexcept { return _emitterType == EmitterType::kCompiler; } //! Tests whether the emitter has the given `flag` enabled. - inline bool hasEmitterFlag(EmitterFlags flag) const noexcept { return Support::test(_emitterFlags, flag); } + ASMJIT_INLINE_NODEBUG bool hasEmitterFlag(EmitterFlags flag) const noexcept { return Support::test(_emitterFlags, flag); } //! Tests whether the emitter is finalized. - inline bool isFinalized() const noexcept { return hasEmitterFlag(EmitterFlags::kFinalized); } + ASMJIT_INLINE_NODEBUG bool isFinalized() const noexcept { return hasEmitterFlag(EmitterFlags::kFinalized); } //! Tests whether the emitter is destroyed (only used during destruction). - inline bool isDestroyed() const noexcept { return hasEmitterFlag(EmitterFlags::kDestroyed); } + ASMJIT_INLINE_NODEBUG bool isDestroyed() const noexcept { return hasEmitterFlag(EmitterFlags::kDestroyed); } + + //! \} + + //! \cond INTERNAL + //! \name Internal Functions + //! \{ - inline void _addEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags |= flags; } - inline void _clearEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags &= _emitterFlags & ~flags; } + ASMJIT_INLINE_NODEBUG void _addEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags |= flags; } + ASMJIT_INLINE_NODEBUG void _clearEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags &= _emitterFlags & ~flags; } //! \} + //! \endcond //! \name Target Information //! \{ //! Returns the CodeHolder this emitter is attached to. - inline CodeHolder* code() const noexcept { return _code; } + ASMJIT_INLINE_NODEBUG CodeHolder* code() const noexcept { return _code; } //! Returns the target environment. //! //! The returned \ref Environment reference matches \ref CodeHolder::environment(). - inline const Environment& environment() const noexcept { return _environment; } + ASMJIT_INLINE_NODEBUG const Environment& environment() const noexcept { return _environment; } //! Tests whether the target architecture is 32-bit. - inline bool is32Bit() const noexcept { return environment().is32Bit(); } + ASMJIT_INLINE_NODEBUG bool is32Bit() const noexcept { return environment().is32Bit(); } //! Tests whether the target architecture is 64-bit. - inline bool is64Bit() const noexcept { return environment().is64Bit(); } + ASMJIT_INLINE_NODEBUG bool is64Bit() const noexcept { return environment().is64Bit(); } //! Returns the target architecture type. - inline Arch arch() const noexcept { return environment().arch(); } + ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return environment().arch(); } //! Returns the target architecture sub-type. - inline SubArch subArch() const noexcept { return environment().subArch(); } + ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return environment().subArch(); } //! Returns the target architecture's GP register size (4 or 8 bytes). - inline uint32_t registerSize() const noexcept { return environment().registerSize(); } + ASMJIT_INLINE_NODEBUG uint32_t registerSize() const noexcept { return environment().registerSize(); } + + //! Returns a signature of a native general purpose register (either 32-bit or 64-bit depending on the architecture). + ASMJIT_INLINE_NODEBUG OperandSignature gpSignature() const noexcept { return _gpSignature; } + + //! Returns instruction alignment. + //! + //! The following values are returned based on the target architecture: + //! - X86 and X86_64 - instruction alignment is 1 + //! - AArch32 - instruction alignment is 4 in A32 mode and 2 in THUMB mode. + //! - AArch64 - instruction alignment is 4 + ASMJIT_INLINE_NODEBUG uint32_t instructionAlignment() const noexcept { return _instructionAlignment; } //! \} @@ -359,7 +390,7 @@ public: //! \{ //! Tests whether the emitter is initialized (i.e. attached to \ref CodeHolder). - inline bool isInitialized() const noexcept { return _code != nullptr; } + ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _code != nullptr; } //! Finalizes this emitter. //! @@ -376,19 +407,19 @@ public: //! \{ //! Tests whether the emitter has a logger. - inline bool hasLogger() const noexcept { return _logger != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasLogger() const noexcept { return _logger != nullptr; } //! Tests whether the emitter has its own logger. //! //! Own logger means that it overrides the possible logger that may be used by \ref CodeHolder this emitter is //! attached to. - inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnLogger); } + ASMJIT_INLINE_NODEBUG bool hasOwnLogger() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnLogger); } //! Returns the logger this emitter uses. //! //! The returned logger is either the emitter's own logger or it's logger used by \ref CodeHolder this emitter //! is attached to. - inline Logger* logger() const noexcept { return _logger; } + ASMJIT_INLINE_NODEBUG Logger* logger() const noexcept { return _logger; } //! Sets or resets the logger of the emitter. //! @@ -401,7 +432,7 @@ public: //! //! The emitter will bail to using a logger attached to \ref CodeHolder this emitter is attached to, or no logger //! at all if \ref CodeHolder doesn't have one. - inline void resetLogger() noexcept { return setLogger(nullptr); } + ASMJIT_INLINE_NODEBUG void resetLogger() noexcept { return setLogger(nullptr); } //! \} @@ -409,25 +440,25 @@ public: //! \{ //! Tests whether the emitter has an error handler attached. - inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; } //! Tests whether the emitter has its own error handler. //! //! Own error handler means that it overrides the possible error handler that may be used by \ref CodeHolder this //! emitter is attached to. - inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnErrorHandler); } + ASMJIT_INLINE_NODEBUG bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnErrorHandler); } //! Returns the error handler this emitter uses. //! //! The returned error handler is either the emitter's own error handler or it's error handler used by //! \ref CodeHolder this emitter is attached to. - inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; } + ASMJIT_INLINE_NODEBUG ErrorHandler* errorHandler() const noexcept { return _errorHandler; } //! Sets or resets the error handler of the emitter. ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept; //! Resets the error handler. - inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); } + ASMJIT_INLINE_NODEBUG void resetErrorHandler() noexcept { setErrorHandler(nullptr); } //! Handles the given error in the following way: //! 1. If the emitter has \ref ErrorHandler attached, it calls its \ref ErrorHandler::handleError() member function @@ -441,14 +472,14 @@ public: //! \{ //! Returns encoding options. - inline EncodingOptions encodingOptions() const noexcept { return _encodingOptions; } + ASMJIT_INLINE_NODEBUG EncodingOptions encodingOptions() const noexcept { return _encodingOptions; } //! Tests whether the encoding `option` is set. - inline bool hasEncodingOption(EncodingOptions option) const noexcept { return Support::test(_encodingOptions, option); } + ASMJIT_INLINE_NODEBUG bool hasEncodingOption(EncodingOptions option) const noexcept { return Support::test(_encodingOptions, option); } //! Enables the given encoding `options`. - inline void addEncodingOptions(EncodingOptions options) noexcept { _encodingOptions |= options; } + ASMJIT_INLINE_NODEBUG void addEncodingOptions(EncodingOptions options) noexcept { _encodingOptions |= options; } //! Disables the given encoding `options`. - inline void clearEncodingOptions(EncodingOptions options) noexcept { _encodingOptions &= ~options; } + ASMJIT_INLINE_NODEBUG void clearEncodingOptions(EncodingOptions options) noexcept { _encodingOptions &= ~options; } //! \} @@ -456,10 +487,10 @@ public: //! \{ //! Returns the emitter's diagnostic options. - inline DiagnosticOptions diagnosticOptions() const noexcept { return _diagnosticOptions; } + ASMJIT_INLINE_NODEBUG DiagnosticOptions diagnosticOptions() const noexcept { return _diagnosticOptions; } //! Tests whether the given `option` is present in the emitter's diagnostic options. - inline bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); } + ASMJIT_INLINE_NODEBUG bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); } //! Activates the given diagnostic `options`. //! @@ -496,44 +527,76 @@ public: //! Forced instruction options are merged with next instruction options before the instruction is encoded. These //! options have some bits reserved that are used by error handling, logging, and instruction validation purposes. //! Other options are globals that affect each instruction. - inline InstOptions forcedInstOptions() const noexcept { return _forcedInstOptions; } + ASMJIT_INLINE_NODEBUG InstOptions forcedInstOptions() const noexcept { return _forcedInstOptions; } //! Returns options of the next instruction. - inline InstOptions instOptions() const noexcept { return _instOptions; } + ASMJIT_INLINE_NODEBUG InstOptions instOptions() const noexcept { return _instOptions; } //! Returns options of the next instruction. - inline void setInstOptions(InstOptions options) noexcept { _instOptions = options; } + ASMJIT_INLINE_NODEBUG void setInstOptions(InstOptions options) noexcept { _instOptions = options; } //! Adds options of the next instruction. - inline void addInstOptions(InstOptions options) noexcept { _instOptions |= options; } + ASMJIT_INLINE_NODEBUG void addInstOptions(InstOptions options) noexcept { _instOptions |= options; } //! Resets options of the next instruction. - inline void resetInstOptions() noexcept { _instOptions = InstOptions::kNone; } + ASMJIT_INLINE_NODEBUG void resetInstOptions() noexcept { _instOptions = InstOptions::kNone; } //! Tests whether the extra register operand is valid. - inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); } + ASMJIT_INLINE_NODEBUG bool hasExtraReg() const noexcept { return _extraReg.isReg(); } //! Returns an extra operand that will be used by the next instruction (architecture specific). - inline const RegOnly& extraReg() const noexcept { return _extraReg; } + ASMJIT_INLINE_NODEBUG const RegOnly& extraReg() const noexcept { return _extraReg; } //! Sets an extra operand that will be used by the next instruction (architecture specific). - inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); } + ASMJIT_INLINE_NODEBUG void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); } //! Sets an extra operand that will be used by the next instruction (architecture specific). - inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); } + ASMJIT_INLINE_NODEBUG void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); } //! Resets an extra operand that will be used by the next instruction (architecture specific). - inline void resetExtraReg() noexcept { _extraReg.reset(); } + ASMJIT_INLINE_NODEBUG void resetExtraReg() noexcept { _extraReg.reset(); } //! Returns comment/annotation of the next instruction. - inline const char* inlineComment() const noexcept { return _inlineComment; } + ASMJIT_INLINE_NODEBUG const char* inlineComment() const noexcept { return _inlineComment; } //! Sets comment/annotation of the next instruction. //! //! \note This string is set back to null by `_emit()`, but until that it has to remain valid as the Emitter is not //! required to make a copy of it (and it would be slow to do that for each instruction). - inline void setInlineComment(const char* s) noexcept { _inlineComment = s; } + ASMJIT_INLINE_NODEBUG void setInlineComment(const char* s) noexcept { _inlineComment = s; } //! Resets the comment/annotation to nullptr. - inline void resetInlineComment() noexcept { _inlineComment = nullptr; } + ASMJIT_INLINE_NODEBUG void resetInlineComment() noexcept { _inlineComment = nullptr; } + + //! \} + + //! \name Emitter State + //! \{ + + //! Resets the emitter state, which contains instruction options, extra register, and inline comment. + //! + //! Emitter can have a state that describes instruction options and extra register used by the instruction. Most + //! instructions don't need nor use the state, however, if an instruction uses a prefix such as REX or REP prefix, + //! which is set explicitly, then the state would contain it. This allows to mimic the syntax of assemblers such + //! as X86. For example `rep().movs(...)` would map to a `REP MOVS` instuction on X86. The same applies to various + //! hints and the use of a mask register in AVX-512 mode. + ASMJIT_INLINE_NODEBUG void resetState() noexcept { + resetInstOptions(); + resetExtraReg(); + resetInlineComment(); + } + + //! \cond INTERNAL + + //! Grabs the current emitter state and resets the emitter state at the same time, returning the state the emitter + //! had before the state was reset. + ASMJIT_INLINE_NODEBUG State _grabState() noexcept { + State s{_instOptions | _forcedInstOptions, _extraReg, _inlineComment}; + resetState(); + return s; + } + //! \endcond //! \} //! \name Sections //! \{ - virtual Error section(Section* section) = 0; + //! Switches the given `section`. + //! + //! Once switched, everything is added to the given `section`. + ASMJIT_API virtual Error section(Section* section); //! \} @@ -541,14 +604,14 @@ public: //! \{ //! Creates a new label. - virtual Label newLabel() = 0; + ASMJIT_API virtual Label newLabel(); //! Creates a new named label. - virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) = 0; + ASMJIT_API virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId); //! Creates a new anonymous label with a name, which can only be used for debugging purposes. - inline Label newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kAnonymous); } + ASMJIT_INLINE_NODEBUG Label newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kAnonymous); } //! Creates a new external label. - inline Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kExternal); } + ASMJIT_INLINE_NODEBUG Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kExternal); } //! Returns `Label` by `name`. //! @@ -561,12 +624,12 @@ public: //! Binds the `label` to the current position of the current section. //! //! \note Attempt to bind the same label multiple times will return an error. - virtual Error bind(const Label& label) = 0; + ASMJIT_API virtual Error bind(const Label& label); //! Tests whether the label `id` is valid (i.e. registered). ASMJIT_API bool isLabelValid(uint32_t labelId) const noexcept; //! Tests whether the `label` is valid (i.e. registered). - inline bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); } + ASMJIT_INLINE_NODEBUG bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); } //! \} @@ -596,35 +659,51 @@ public: ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5); //! Emits an instruction `instId` with the given `operands`. + //! + //! This is the most universal way of emitting code, which accepts an instruction identifier and instruction + //! operands. This is called an "unchecked" API as emit doesn't provide any type checks at compile-time. This + //! allows to emit instruction with just \ref Operand instances, which could be handy in some cases - for + //! example emitting generic code where you don't know whether some operand is register, memory, or immediate. template<typename... Args> - ASMJIT_FORCE_INLINE Error emit(InstId instId, Args&&... operands) { + ASMJIT_INLINE_NODEBUG Error emit(InstId instId, Args&&... operands) { return _emitI(instId, Support::ForwardOp<Args>::forward(operands)...); } - ASMJIT_FORCE_INLINE Error emitOpArray(InstId instId, const Operand_* operands, size_t opCount) { + //! Similar to \ref emit(), but uses array of `operands` instead. + ASMJIT_INLINE_NODEBUG Error emitOpArray(InstId instId, const Operand_* operands, size_t opCount) { return _emitOpArray(instId, operands, opCount); } + //! Similar to \ref emit(), but emits instruction with both instruction options and extra register, followed + //! by an array of `operands`. ASMJIT_FORCE_INLINE Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) { setInstOptions(inst.options()); setExtraReg(inst.extraReg()); return _emitOpArray(inst.id(), operands, opCount); } + //! \} + //! \cond INTERNAL + //! \name Emit Internals + //! \{ + //! Emits an instruction - all 6 operands must be defined. - virtual Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0; + ASMJIT_API virtual Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt); //! Emits instruction having operands stored in array. ASMJIT_API virtual Error _emitOpArray(InstId instId, const Operand_* operands, size_t opCount); - //! \endcond //! \} + //! \endcond //! \name Emit Utilities //! \{ + //! Emits a function prolog described by the given function `frame`. ASMJIT_API Error emitProlog(const FuncFrame& frame); + //! Emits a function epilog described by the given function `frame`. ASMJIT_API Error emitEpilog(const FuncFrame& frame); + //! Emits code that reassigns function `frame` arguments to the given `args`. ASMJIT_API Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args); //! \} @@ -637,7 +716,7 @@ public: //! The sequence that is used to fill the gap between the aligned location and the current location depends on the //! align `mode`, see \ref AlignMode. The `alignment` argument specifies alignment in bytes, so for example when //! it's `32` it means that the code buffer will be aligned to `32` bytes. - virtual Error align(AlignMode alignMode, uint32_t alignment) = 0; + ASMJIT_API virtual Error align(AlignMode alignMode, uint32_t alignment); //! \} @@ -645,7 +724,7 @@ public: //! \{ //! Embeds raw data into the \ref CodeBuffer. - virtual Error embed(const void* data, size_t dataSize) = 0; + ASMJIT_API virtual Error embed(const void* data, size_t dataSize); //! Embeds a typed data array. //! @@ -656,44 +735,44 @@ public: //! //! - Repeat the given data `repeatCount` times, so the data can be used as a fill pattern for example, or as a //! pattern used by SIMD instructions. - virtual Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0; + ASMJIT_API virtual Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1); //! Embeds int8_t `value` repeated by `repeatCount`. - inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt8, &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt8, &value, 1, repeatCount); } //! Embeds uint8_t `value` repeated by `repeatCount`. - inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt8, &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt8, &value, 1, repeatCount); } //! Embeds int16_t `value` repeated by `repeatCount`. - inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt16, &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt16, &value, 1, repeatCount); } //! Embeds uint16_t `value` repeated by `repeatCount`. - inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt16, &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt16, &value, 1, repeatCount); } //! Embeds int32_t `value` repeated by `repeatCount`. - inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt32, &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt32, &value, 1, repeatCount); } //! Embeds uint32_t `value` repeated by `repeatCount`. - inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt32, &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt32, &value, 1, repeatCount); } //! Embeds int64_t `value` repeated by `repeatCount`. - inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt64, &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt64, &value, 1, repeatCount); } //! Embeds uint64_t `value` repeated by `repeatCount`. - inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt64, &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt64, &value, 1, repeatCount); } //! Embeds a floating point `value` repeated by `repeatCount`. - inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<float>::kTypeId), &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<float>::kTypeId), &value, 1, repeatCount); } //! Embeds a floating point `value` repeated by `repeatCount`. - inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<double>::kTypeId), &value, 1, repeatCount); } + ASMJIT_INLINE_NODEBUG Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<double>::kTypeId), &value, 1, repeatCount); } //! Embeds a constant pool at the current offset by performing the following: //! 1. Aligns by using AlignMode::kData to the minimum `pool` alignment. //! 2. Binds the ConstPool label so it's bound to an aligned location. //! 3. Emits ConstPool content. - virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0; + ASMJIT_API virtual Error embedConstPool(const Label& label, const ConstPool& pool); //! Embeds an absolute `label` address as data. //! //! The `dataSize` is an optional argument that can be used to specify the size of the address data. If it's zero //! (default) the address size is deduced from the target architecture (either 4 or 8 bytes). - virtual Error embedLabel(const Label& label, size_t dataSize = 0) = 0; + ASMJIT_API virtual Error embedLabel(const Label& label, size_t dataSize = 0); //! Embeds a delta (distance) between the `label` and `base` calculating it as `label - base`. This function was //! designed to make it easier to embed lookup tables where each index is a relative distance of two labels. - virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) = 0; + ASMJIT_API virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0); //! \} @@ -701,7 +780,7 @@ public: //! \{ //! Emits a comment stored in `data` with an optional `size` parameter. - virtual Error comment(const char* data, size_t size = SIZE_MAX) = 0; + ASMJIT_API virtual Error comment(const char* data, size_t size = SIZE_MAX); //! Emits a formatted comment specified by `fmt` and variable number of arguments. ASMJIT_API Error commentf(const char* fmt, ...); @@ -714,9 +793,9 @@ public: //! \{ //! Called after the emitter was attached to `CodeHolder`. - virtual Error onAttach(CodeHolder* ASMJIT_NONNULL(code)) noexcept = 0; + ASMJIT_API virtual Error onAttach(CodeHolder* ASMJIT_NONNULL(code)) noexcept; //! Called after the emitter was detached from `CodeHolder`. - virtual Error onDetach(CodeHolder* ASMJIT_NONNULL(code)) noexcept = 0; + ASMJIT_API virtual Error onDetach(CodeHolder* ASMJIT_NONNULL(code)) noexcept; //! Called when \ref CodeHolder has updated an important setting, which involves the following: //! diff --git a/3rdparty/asmjit/src/asmjit/core/emitterutils.cpp b/3rdparty/asmjit/src/asmjit/core/emitterutils.cpp index f36a1b37745..d0a687244b3 100644 --- a/3rdparty/asmjit/src/asmjit/core/emitterutils.cpp +++ b/3rdparty/asmjit/src/asmjit/core/emitterutils.cpp @@ -96,7 +96,7 @@ void logInstructionEmitted( } Error logInstructionFailed( - BaseAssembler* self, + BaseEmitter* self, Error err, InstId instId, InstOptions options, @@ -109,16 +109,14 @@ Error logInstructionFailed( Operand_ opArray[Globals::kMaxOpCount]; opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - self->_funcs.formatInstruction(sb, FormatFlags::kNone, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); + self->_funcs.formatInstruction(sb, FormatFlags::kRegType, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); if (self->inlineComment()) { sb.append(" ; "); sb.append(self->inlineComment()); } - self->resetInstOptions(); - self->resetExtraReg(); - self->resetInlineComment(); + self->resetState(); return self->reportError(err, sb.data()); } diff --git a/3rdparty/asmjit/src/asmjit/core/emitterutils_p.h b/3rdparty/asmjit/src/asmjit/core/emitterutils_p.h index b7610e70261..8b6e1e0547e 100644 --- a/3rdparty/asmjit/src/asmjit/core/emitterutils_p.h +++ b/3rdparty/asmjit/src/asmjit/core/emitterutils_p.h @@ -23,7 +23,7 @@ namespace EmitterUtils { //! Default paddings used by Emitter utils and Formatter. -static constexpr Operand noExt[3]; +static constexpr Operand noExt[3] = { {}, {}, {} }; enum kOpIndex : uint32_t { kOp3 = 0, @@ -71,7 +71,7 @@ void logInstructionEmitted( uint32_t relSize, uint32_t immSize, uint8_t* afterCursor); Error logInstructionFailed( - BaseAssembler* self, + BaseEmitter* self, Error err, InstId instId, InstOptions options, diff --git a/3rdparty/asmjit/src/asmjit/core/environment.h b/3rdparty/asmjit/src/asmjit/core/environment.h index 7e328a97c8e..c3678dc65bc 100644 --- a/3rdparty/asmjit/src/asmjit/core/environment.h +++ b/3rdparty/asmjit/src/asmjit/core/environment.h @@ -24,7 +24,7 @@ enum class Vendor : uint8_t { //! Unknown or uninitialized platform vendor. kUnknown = 0, - //! Maximum value of `PlatformVendor`. + //! Maximum value of `Vendor`. kMaxValue = kUnknown, //! Platform vendor detected at compile-time. @@ -116,7 +116,7 @@ enum class Platform : uint8_t { //! Platform ABI (application binary interface). enum class PlatformABI : uint8_t { - //! Unknown or uninitialied environment. + //! Unknown or uninitialized environment. kUnknown = 0, //! Microsoft ABI. kMSVC, @@ -126,6 +126,8 @@ enum class PlatformABI : uint8_t { kAndroid, //! Cygwin ABI. kCygwin, + //! Darwin ABI. + kDarwin, //! Maximum value of `PlatformABI`. kMaxValue, @@ -142,11 +144,26 @@ enum class PlatformABI : uint8_t { kGNU #elif defined(__ANDROID__) kAndroid +#elif defined(__APPLE__) + kDarwin #else kUnknown #endif }; +//! Floating point ABI (ARM). +enum class FloatABI : uint8_t { + kHardFloat = 0, + kSoftFloat, + + kHost = +#if ASMJIT_ARCH_ARM == 32 && defined(__SOFTFP__) + kSoftFloat +#else + kHardFloat +#endif +}; + //! Object format. //! //! \note AsmJit doesn't really use anything except \ref ObjectFormat::kUnknown and \ref ObjectFormat::kJIT at @@ -186,53 +203,56 @@ public: //! \{ //! Architecture. - Arch _arch; + Arch _arch = Arch::kUnknown; //! Sub-architecture type. - SubArch _subArch; + SubArch _subArch = SubArch::kUnknown; //! Vendor type. - Vendor _vendor; + Vendor _vendor = Vendor::kUnknown; //! Platform. - Platform _platform; + Platform _platform = Platform::kUnknown; //! Platform ABI. - PlatformABI _platformABI; + PlatformABI _platformABI = PlatformABI::kUnknown; //! Object format. - ObjectFormat _objectFormat; + ObjectFormat _objectFormat = ObjectFormat::kUnknown; + //! Floating point ABI. + FloatABI _floatABI = FloatABI::kHardFloat; //! Reserved for future use, must be zero. - uint8_t _reserved[2]; + uint8_t _reserved = 0; //! \} //! \name Construction & Destruction //! \{ - inline Environment() noexcept : - _arch(Arch::kUnknown), - _subArch(SubArch::kUnknown), - _vendor(Vendor::kUnknown), - _platform(Platform::kUnknown), - _platformABI(PlatformABI::kUnknown), - _objectFormat(ObjectFormat::kUnknown), - _reserved { 0, 0 } {} + //! Creates a default initialized environment (all values either unknown or set to safe defaults). + ASMJIT_INLINE_NODEBUG constexpr Environment() noexcept = default; + //! Creates a copy of `other` instance. + ASMJIT_INLINE_NODEBUG constexpr Environment(const Environment& other) noexcept = default; - inline explicit Environment( + //! Creates \ref Environment initialized to `arch`, `subArch`, `vendor`, `platform`, `platformABI`, `objectFormat`, + //! and `floatABI`. + ASMJIT_INLINE_NODEBUG constexpr explicit Environment( Arch arch, SubArch subArch = SubArch::kUnknown, Vendor vendor = Vendor::kUnknown, Platform platform = Platform::kUnknown, - PlatformABI abi = PlatformABI::kUnknown, - ObjectFormat objectFormat = ObjectFormat::kUnknown) noexcept { - - init(arch, subArch, vendor, platform, abi, objectFormat); - } - - inline Environment(const Environment& other) noexcept = default; + PlatformABI platformABI = PlatformABI::kUnknown, + ObjectFormat objectFormat = ObjectFormat::kUnknown, + FloatABI floatABI = FloatABI::kHardFloat) noexcept + : _arch(arch), + _subArch(subArch), + _vendor(vendor), + _platform(platform), + _platformABI(platformABI), + _objectFormat(objectFormat), + _floatABI(floatABI) {} //! Returns the host environment constructed from preprocessor macros defined by the compiler. //! //! The returned environment should precisely match the target host architecture, sub-architecture, platform, //! and ABI. - static inline Environment host() noexcept { - return Environment(Arch::kHost, SubArch::kHost, Vendor::kHost, Platform::kHost, PlatformABI::kHost, ObjectFormat::kUnknown); + static ASMJIT_INLINE_NODEBUG Environment host() noexcept { + return Environment(Arch::kHost, SubArch::kHost, Vendor::kHost, Platform::kHost, PlatformABI::kHost, ObjectFormat::kUnknown, FloatABI::kHost); } //! \} @@ -240,10 +260,10 @@ public: //! \name Overloaded Operators //! \{ - inline Environment& operator=(const Environment& other) noexcept = default; + ASMJIT_INLINE_NODEBUG Environment& operator=(const Environment& other) noexcept = default; - inline bool operator==(const Environment& other) const noexcept { return equals(other); } - inline bool operator!=(const Environment& other) const noexcept { return !equals(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const Environment& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const Environment& other) const noexcept { return !equals(other); } //! \} @@ -253,59 +273,54 @@ public: //! Tests whether the environment is not set up. //! //! Returns true if all members are zero, and thus unknown. - inline bool empty() const noexcept { + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { // Unfortunately compilers won't optimize fields are checked one by one... return _packed() == 0; } //! Tests whether the environment is initialized, which means it must have //! a valid architecture. - inline bool isInitialized() const noexcept { + ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _arch != Arch::kUnknown; } - inline uint64_t _packed() const noexcept { + ASMJIT_INLINE_NODEBUG uint64_t _packed() const noexcept { uint64_t x; memcpy(&x, this, 8); return x; } //! Resets all members of the environment to zero / unknown. - inline void reset() noexcept { - _arch = Arch::kUnknown; - _subArch = SubArch::kUnknown; - _vendor = Vendor::kUnknown; - _platform = Platform::kUnknown; - _platformABI = PlatformABI::kUnknown; - _objectFormat = ObjectFormat::kUnknown; - _reserved[0] = 0; - _reserved[1] = 0; - } + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = Environment{}; } - inline bool equals(const Environment& other) const noexcept { - return _packed() == other._packed(); - } + //! Tests whether this environment is equal to `other`. + ASMJIT_INLINE_NODEBUG bool equals(const Environment& other) const noexcept { return _packed() == other._packed(); } //! Returns the architecture. - inline Arch arch() const noexcept { return _arch; } + ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; } //! Returns the sub-architecture. - inline SubArch subArch() const noexcept { return _subArch; } + ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return _subArch; } //! Returns vendor. - inline Vendor vendor() const noexcept { return _vendor; } + ASMJIT_INLINE_NODEBUG Vendor vendor() const noexcept { return _vendor; } //! Returns target's platform or operating system. - inline Platform platform() const noexcept { return _platform; } + ASMJIT_INLINE_NODEBUG Platform platform() const noexcept { return _platform; } //! Returns target's ABI. - inline PlatformABI platformABI() const noexcept { return _platformABI; } + ASMJIT_INLINE_NODEBUG PlatformABI platformABI() const noexcept { return _platformABI; } //! Returns target's object format. - inline ObjectFormat objectFormat() const noexcept { return _objectFormat; } + ASMJIT_INLINE_NODEBUG ObjectFormat objectFormat() const noexcept { return _objectFormat; } + //! Returns floating point ABI. + ASMJIT_INLINE_NODEBUG FloatABI floatABI() const noexcept { return _floatABI; } + //! Initializes \ref Environment to `arch`, `subArch`, `vendor`, `platform`, `platformABI`, `objectFormat`, + //! and `floatABI`. inline void init( Arch arch, SubArch subArch = SubArch::kUnknown, Vendor vendor = Vendor::kUnknown, Platform platform = Platform::kUnknown, PlatformABI platformABI = PlatformABI::kUnknown, - ObjectFormat objectFormat = ObjectFormat::kUnknown) noexcept { + ObjectFormat objectFormat = ObjectFormat::kUnknown, + FloatABI floatABI = FloatABI::kHardFloat) noexcept { _arch = arch; _subArch = subArch; @@ -313,57 +328,63 @@ public: _platform = platform; _platformABI = platformABI; _objectFormat = objectFormat; - _reserved[0] = 0; - _reserved[1] = 0; + _floatABI = floatABI; + _reserved = 0; } - inline bool isArchX86() const noexcept { return _arch == Arch::kX86; } - inline bool isArchX64() const noexcept { return _arch == Arch::kX64; } - inline bool isArchARM() const noexcept { return isArchARM(_arch); } - inline bool isArchThumb() const noexcept { return isArchThumb(_arch); } - inline bool isArchAArch64() const noexcept { return isArchAArch64(_arch); } - inline bool isArchMIPS32() const noexcept { return isArchMIPS32(_arch); } - inline bool isArchMIPS64() const noexcept { return isArchMIPS64(_arch); } - inline bool isArchRISCV32() const noexcept { return _arch == Arch::kRISCV32; } - inline bool isArchRISCV64() const noexcept { return _arch == Arch::kRISCV64; } + //! Tests whether this environment describes a 32-bit X86. + ASMJIT_INLINE_NODEBUG bool isArchX86() const noexcept { return _arch == Arch::kX86; } + //! Tests whether this environment describes a 64-bit X86. + ASMJIT_INLINE_NODEBUG bool isArchX64() const noexcept { return _arch == Arch::kX64; } + //! Tests whether this environment describes a 32-bit ARM. + ASMJIT_INLINE_NODEBUG bool isArchARM() const noexcept { return isArchARM(_arch); } + //! Tests whether this environment describes a 32-bit ARM in THUMB mode. + ASMJIT_INLINE_NODEBUG bool isArchThumb() const noexcept { return isArchThumb(_arch); } + //! Tests whether this environment describes a 64-bit X86. + ASMJIT_INLINE_NODEBUG bool isArchAArch64() const noexcept { return isArchAArch64(_arch); } + //! Tests whether this environment describes a 32-bit MIPS. + ASMJIT_INLINE_NODEBUG bool isArchMIPS32() const noexcept { return isArchMIPS32(_arch); } + //! Tests whether this environment describes a 64-bit MIPS. + ASMJIT_INLINE_NODEBUG bool isArchMIPS64() const noexcept { return isArchMIPS64(_arch); } + //! Tests whether this environment describes a 32-bit RISC-V. + ASMJIT_INLINE_NODEBUG bool isArchRISCV32() const noexcept { return _arch == Arch::kRISCV32; } + //! Tests whether this environment describes a 64-bit RISC-V. + ASMJIT_INLINE_NODEBUG bool isArchRISCV64() const noexcept { return _arch == Arch::kRISCV64; } //! Tests whether the architecture is 32-bit. - inline bool is32Bit() const noexcept { return is32Bit(_arch); } + ASMJIT_INLINE_NODEBUG bool is32Bit() const noexcept { return is32Bit(_arch); } //! Tests whether the architecture is 64-bit. - inline bool is64Bit() const noexcept { return is64Bit(_arch); } + ASMJIT_INLINE_NODEBUG bool is64Bit() const noexcept { return is64Bit(_arch); } //! Tests whether the architecture is little endian. - inline bool isLittleEndian() const noexcept { return isLittleEndian(_arch); } + ASMJIT_INLINE_NODEBUG bool isLittleEndian() const noexcept { return isLittleEndian(_arch); } //! Tests whether the architecture is big endian. - inline bool isBigEndian() const noexcept { return isBigEndian(_arch); } + ASMJIT_INLINE_NODEBUG bool isBigEndian() const noexcept { return isBigEndian(_arch); } //! Tests whether this architecture is of X86 family. - inline bool isFamilyX86() const noexcept { return isFamilyX86(_arch); } + ASMJIT_INLINE_NODEBUG bool isFamilyX86() const noexcept { return isFamilyX86(_arch); } //! Tests whether this architecture family is ARM, THUMB, or AArch64. - inline bool isFamilyARM() const noexcept { return isFamilyARM(_arch); } + ASMJIT_INLINE_NODEBUG bool isFamilyARM() const noexcept { return isFamilyARM(_arch); } //! Tests whether this architecture family is AArch32 (ARM or THUMB). - inline bool isFamilyAArch32() const noexcept { return isFamilyAArch32(_arch); } + ASMJIT_INLINE_NODEBUG bool isFamilyAArch32() const noexcept { return isFamilyAArch32(_arch); } //! Tests whether this architecture family is AArch64. - inline bool isFamilyAArch64() const noexcept { return isFamilyAArch64(_arch); } + ASMJIT_INLINE_NODEBUG bool isFamilyAArch64() const noexcept { return isFamilyAArch64(_arch); } //! Tests whether this architecture family is MISP or MIPS64. - inline bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); } + ASMJIT_INLINE_NODEBUG bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); } //! Tests whether this architecture family is RISC-V (both 32-bit and 64-bit). - inline bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); } + ASMJIT_INLINE_NODEBUG bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); } //! Tests whether the environment platform is Windows. - inline bool isPlatformWindows() const noexcept { return _platform == Platform::kWindows; } - + ASMJIT_INLINE_NODEBUG bool isPlatformWindows() const noexcept { return _platform == Platform::kWindows; } //! Tests whether the environment platform is Linux. - inline bool isPlatformLinux() const noexcept { return _platform == Platform::kLinux; } - + ASMJIT_INLINE_NODEBUG bool isPlatformLinux() const noexcept { return _platform == Platform::kLinux; } //! Tests whether the environment platform is Hurd. - inline bool isPlatformHurd() const noexcept { return _platform == Platform::kHurd; } - + ASMJIT_INLINE_NODEBUG bool isPlatformHurd() const noexcept { return _platform == Platform::kHurd; } //! Tests whether the environment platform is Haiku. - inline bool isPlatformHaiku() const noexcept { return _platform == Platform::kHaiku; } + ASMJIT_INLINE_NODEBUG bool isPlatformHaiku() const noexcept { return _platform == Platform::kHaiku; } //! Tests whether the environment platform is any BSD. - inline bool isPlatformBSD() const noexcept { + ASMJIT_INLINE_NODEBUG bool isPlatformBSD() const noexcept { return _platform == Platform::kFreeBSD || _platform == Platform::kOpenBSD || _platform == Platform::kNetBSD || @@ -371,7 +392,7 @@ public: } //! Tests whether the environment platform is any Apple platform (OSX, iOS, TVOS, WatchOS). - inline bool isPlatformApple() const noexcept { + ASMJIT_INLINE_NODEBUG bool isPlatformApple() const noexcept { return _platform == Platform::kOSX || _platform == Platform::kIOS || _platform == Platform::kTVOS || @@ -379,119 +400,124 @@ public: } //! Tests whether the ABI is MSVC. - inline bool isMSVC() const noexcept { return _platformABI == PlatformABI::kMSVC; } + ASMJIT_INLINE_NODEBUG bool isMSVC() const noexcept { return _platformABI == PlatformABI::kMSVC; } //! Tests whether the ABI is GNU. - inline bool isGNU() const noexcept { return _platformABI == PlatformABI::kGNU; } + ASMJIT_INLINE_NODEBUG bool isGNU() const noexcept { return _platformABI == PlatformABI::kGNU; } + //! Tests whether the ABI is GNU. + ASMJIT_INLINE_NODEBUG bool isDarwin() const noexcept { return _platformABI == PlatformABI::kDarwin; } //! Returns a calculated stack alignment for this environment. ASMJIT_API uint32_t stackAlignment() const noexcept; //! Returns a native register size of this architecture. - uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); } + ASMJIT_INLINE_NODEBUG uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); } //! Sets the architecture to `arch`. - inline void setArch(Arch arch) noexcept { _arch = arch; } + ASMJIT_INLINE_NODEBUG void setArch(Arch arch) noexcept { _arch = arch; } //! Sets the sub-architecture to `subArch`. - inline void setSubArch(SubArch subArch) noexcept { _subArch = subArch; } + ASMJIT_INLINE_NODEBUG void setSubArch(SubArch subArch) noexcept { _subArch = subArch; } //! Sets the vendor to `vendor`. - inline void setVendor(Vendor vendor) noexcept { _vendor = vendor; } + ASMJIT_INLINE_NODEBUG void setVendor(Vendor vendor) noexcept { _vendor = vendor; } //! Sets the platform to `platform`. - inline void setPlatform(Platform platform) noexcept { _platform = platform; } + ASMJIT_INLINE_NODEBUG void setPlatform(Platform platform) noexcept { _platform = platform; } //! Sets the ABI to `platformABI`. - inline void setPlatformABI(PlatformABI platformABI) noexcept { _platformABI = platformABI; } + ASMJIT_INLINE_NODEBUG void setPlatformABI(PlatformABI platformABI) noexcept { _platformABI = platformABI; } //! Sets the object format to `objectFormat`. - inline void setObjectFormat(ObjectFormat objectFormat) noexcept { _objectFormat = objectFormat; } + ASMJIT_INLINE_NODEBUG void setObjectFormat(ObjectFormat objectFormat) noexcept { _objectFormat = objectFormat; } + + //! Sets floating point ABI to `floatABI`. + ASMJIT_INLINE_NODEBUG void setFloatABI(FloatABI floatABI) noexcept { _floatABI = floatABI; } //! \} //! \name Static Utilities //! \{ - static inline bool isDefinedArch(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isDefinedArch(Arch arch) noexcept { return uint32_t(arch) <= uint32_t(Arch::kMaxValue); } - static inline bool isValidArch(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isValidArch(Arch arch) noexcept { return arch != Arch::kUnknown && uint32_t(arch) <= uint32_t(Arch::kMaxValue); } //! Tests whether the given architecture `arch` is 32-bit. - static inline bool is32Bit(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool is32Bit(Arch arch) noexcept { return (uint32_t(arch) & uint32_t(Arch::k32BitMask)) == uint32_t(Arch::k32BitMask); } //! Tests whether the given architecture `arch` is 64-bit. - static inline bool is64Bit(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool is64Bit(Arch arch) noexcept { return (uint32_t(arch) & uint32_t(Arch::k32BitMask)) == 0; } //! Tests whether the given architecture `arch` is little endian. - static inline bool isLittleEndian(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isLittleEndian(Arch arch) noexcept { return uint32_t(arch) < uint32_t(Arch::kBigEndian); } //! Tests whether the given architecture `arch` is big endian. - static inline bool isBigEndian(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isBigEndian(Arch arch) noexcept { return uint32_t(arch) >= uint32_t(Arch::kBigEndian); } //! Tests whether the given architecture is Thumb or Thumb_BE. - static inline bool isArchThumb(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isArchThumb(Arch arch) noexcept { return arch == Arch::kThumb || arch == Arch::kThumb_BE; } //! Tests whether the given architecture is ARM or ARM_BE. - static inline bool isArchARM(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isArchARM(Arch arch) noexcept { return arch == Arch::kARM || arch == Arch::kARM_BE; } //! Tests whether the given architecture is AArch64 or AArch64_BE. - static inline bool isArchAArch64(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isArchAArch64(Arch arch) noexcept { return arch == Arch::kAArch64 || arch == Arch::kAArch64_BE; } //! Tests whether the given architecture is MIPS32_LE or MIPS32_BE. - static inline bool isArchMIPS32(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isArchMIPS32(Arch arch) noexcept { return arch == Arch::kMIPS32_LE || arch == Arch::kMIPS32_BE; } //! Tests whether the given architecture is MIPS64_LE or MIPS64_BE. - static inline bool isArchMIPS64(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isArchMIPS64(Arch arch) noexcept { return arch == Arch::kMIPS64_LE || arch == Arch::kMIPS64_BE; } //! Tests whether the given architecture family is X86 or X64. - static inline bool isFamilyX86(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isFamilyX86(Arch arch) noexcept { return arch == Arch::kX86 || arch == Arch::kX64; } - //! Tests whether the given architecture family is ARM, THUMB, or AArch64. - static inline bool isFamilyARM(Arch arch) noexcept { - return isArchARM(arch) || isArchAArch64(arch) || isArchThumb(arch); - } - //! Tests whether the given architecture family is AArch32 (ARM or THUMB). - static inline bool isFamilyAArch32(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isFamilyAArch32(Arch arch) noexcept { return isArchARM(arch) || isArchThumb(arch); } //! Tests whether the given architecture family is AArch64. - static inline bool isFamilyAArch64(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isFamilyAArch64(Arch arch) noexcept { return isArchAArch64(arch); } - //! Tests whether the given architecture family is MISP or MIPS64. - static inline bool isFamilyMIPS(Arch arch) noexcept { + //! Tests whether the given architecture family is ARM, THUMB, or AArch64. + static ASMJIT_INLINE_NODEBUG bool isFamilyARM(Arch arch) noexcept { + return isFamilyAArch32(arch) || isFamilyAArch64(arch); + } + + //! Tests whether the given architecture family is MIPS or MIPS64. + static ASMJIT_INLINE_NODEBUG bool isFamilyMIPS(Arch arch) noexcept { return isArchMIPS32(arch) || isArchMIPS64(arch); } //! Tests whether the given architecture family is RISC-V (both 32-bit and 64-bit). - static inline bool isFamilyRISCV(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG bool isFamilyRISCV(Arch arch) noexcept { return arch == Arch::kRISCV32 || arch == Arch::kRISCV64; } //! Returns a native general purpose register size from the given architecture. - static inline uint32_t registerSizeFromArch(Arch arch) noexcept { + static ASMJIT_INLINE_NODEBUG uint32_t registerSizeFromArch(Arch arch) noexcept { return is32Bit(arch) ? 4u : 8u; } diff --git a/3rdparty/asmjit/src/asmjit/core/errorhandler.cpp b/3rdparty/asmjit/src/asmjit/core/errorhandler.cpp index 5a7dac52356..ce2ad016af1 100644 --- a/3rdparty/asmjit/src/asmjit/core/errorhandler.cpp +++ b/3rdparty/asmjit/src/asmjit/core/errorhandler.cpp @@ -11,4 +11,8 @@ ASMJIT_BEGIN_NAMESPACE ErrorHandler::ErrorHandler() noexcept {} ErrorHandler::~ErrorHandler() noexcept {} +void ErrorHandler::handleError(Error err, const char* message, BaseEmitter* origin) { + DebugUtils::unused(err, message, origin); +} + ASMJIT_END_NAMESPACE diff --git a/3rdparty/asmjit/src/asmjit/core/errorhandler.h b/3rdparty/asmjit/src/asmjit/core/errorhandler.h index 5151d43304e..a1a2dd2d5db 100644 --- a/3rdparty/asmjit/src/asmjit/core/errorhandler.h +++ b/3rdparty/asmjit/src/asmjit/core/errorhandler.h @@ -61,7 +61,7 @@ class BaseEmitter; //! SimpleErrorHandler eh; //! //! CodeHolder code; -//! code.init(rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&eh); //! //! // Try to emit instruction that doesn't exist. @@ -117,7 +117,7 @@ class BaseEmitter; //! ThrowableErrorHandler eh; //! //! CodeHolder code; -//! code.init(rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&eh); //! //! x86::Assembler a(&code); @@ -166,7 +166,7 @@ class BaseEmitter; //! LongJmpErrorHandler eh; //! //! CodeHolder code; -//! code.init(rt.rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&eh); //! //! x86::Assembler a(&code); @@ -215,7 +215,7 @@ public: //! calling `handleError()` so `longjmp()` can be used without any issues to cancel the code generation if an //! error occurred. There is no difference between exceptions and `longjmp()` from AsmJit's perspective, however, //! never jump outside of `CodeHolder` and `BaseEmitter` scope as you would leak memory. - virtual void handleError(Error err, const char* message, BaseEmitter* origin) = 0; + ASMJIT_API virtual void handleError(Error err, const char* message, BaseEmitter* origin); //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/formatter.cpp b/3rdparty/asmjit/src/asmjit/core/formatter.cpp index 1a9a386e3f3..0f12e416364 100644 --- a/3rdparty/asmjit/src/asmjit/core/formatter.cpp +++ b/3rdparty/asmjit/src/asmjit/core/formatter.cpp @@ -57,7 +57,7 @@ Error formatTypeId(String& sb, TypeId typeId) noexcept { if (!TypeUtils::isValid(typeId)) return sb.append("unknown"); - const char* typeName = "unknown"; + const char* typeName = nullptr; uint32_t typeSize = TypeUtils::sizeOf(typeId); TypeId scalarType = TypeUtils::scalarOf(typeId); @@ -107,7 +107,7 @@ Error formatFeature( return x86::FormatterInternal::formatFeature(sb, featureId); #endif -#if !defined(ASMJIT_NO_AARCH32) && !defined(ASMJIT_NO_AARCH64) +#if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyARM(arch)) return arm::FormatterInternal::formatFeature(sb, featureId); #endif @@ -123,32 +123,33 @@ Error formatLabel( DebugUtils::unused(formatFlags); - const LabelEntry* le = emitter->code()->labelEntry(labelId); - if (ASMJIT_UNLIKELY(!le)) - return sb.appendFormat("<InvalidLabel:%u>", labelId); + if (emitter && emitter->code()) { + const LabelEntry* le = emitter->code()->labelEntry(labelId); + if (ASMJIT_UNLIKELY(!le)) + return sb.appendFormat("<InvalidLabel:%u>", labelId); - if (le->hasName()) { - if (le->hasParent()) { - uint32_t parentId = le->parentId(); - const LabelEntry* pe = emitter->code()->labelEntry(parentId); + if (le->hasName()) { + if (le->hasParent()) { + uint32_t parentId = le->parentId(); + const LabelEntry* pe = emitter->code()->labelEntry(parentId); - if (ASMJIT_UNLIKELY(!pe)) - ASMJIT_PROPAGATE(sb.appendFormat("<InvalidLabel:%u>", labelId)); - else if (ASMJIT_UNLIKELY(!pe->hasName())) - ASMJIT_PROPAGATE(sb.appendFormat("L%u", parentId)); - else - ASMJIT_PROPAGATE(sb.append(pe->name())); + if (ASMJIT_UNLIKELY(!pe)) + ASMJIT_PROPAGATE(sb.appendFormat("<InvalidLabel:%u>", labelId)); + else if (ASMJIT_UNLIKELY(!pe->hasName())) + ASMJIT_PROPAGATE(sb.appendFormat("L%u", parentId)); + else + ASMJIT_PROPAGATE(sb.append(pe->name())); - ASMJIT_PROPAGATE(sb.append('.')); - } + ASMJIT_PROPAGATE(sb.append('.')); + } - if (le->type() == LabelType::kAnonymous) - ASMJIT_PROPAGATE(sb.appendFormat("L%u@", labelId)); - return sb.append(le->name()); - } - else { - return sb.appendFormat("L%u", labelId); + if (le->type() == LabelType::kAnonymous) + ASMJIT_PROPAGATE(sb.appendFormat("L%u@", labelId)); + return sb.append(le->name()); + } } + + return sb.appendFormat("L%u", labelId); } Error formatRegister( @@ -165,8 +166,8 @@ Error formatRegister( #endif #if !defined(ASMJIT_NO_AARCH64) - if (Environment::isFamilyAArch64(arch)) - return a64::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); + if (Environment::isFamilyARM(arch)) + return arm::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); #endif return kErrorInvalidArch; @@ -185,8 +186,8 @@ Error formatOperand( #endif #if !defined(ASMJIT_NO_AARCH64) - if (Environment::isFamilyAArch64(arch)) - return a64::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); + if (Environment::isFamilyARM(arch)) + return arm::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); #endif return kErrorInvalidArch; @@ -283,7 +284,7 @@ Error formatInstruction( #endif #if !defined(ASMJIT_NO_AARCH64) - if (Environment::isFamilyARM(arch)) + if (Environment::isFamilyAArch64(arch)) return a64::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); #endif @@ -471,8 +472,7 @@ Error formatNode( case NodeType::kComment: { const CommentNode* commentNode = node->as<CommentNode>(); - ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment())); - break; + return sb.appendFormat("; %s", commentNode->inlineComment()); } case NodeType::kSentinel: { @@ -514,7 +514,7 @@ Error formatNode( ASMJIT_PROPAGATE(sb.append("[FuncRet]")); for (uint32_t i = 0; i < 2; i++) { - const Operand_& op = retNode->_opArray[i]; + const Operand_& op = retNode->op(i); if (!op.isNone()) { ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); ASMJIT_PROPAGATE(formatOperand(sb, formatOptions.flags(), builder, builder->arch(), op)); diff --git a/3rdparty/asmjit/src/asmjit/core/formatter.h b/3rdparty/asmjit/src/asmjit/core/formatter.h index d7a4b93476a..392e4787302 100644 --- a/3rdparty/asmjit/src/asmjit/core/formatter.h +++ b/3rdparty/asmjit/src/asmjit/core/formatter.h @@ -37,7 +37,9 @@ enum class FormatFlags : uint32_t { //! Show casts between virtual register types (Compiler output). kRegCasts = 0x00000010u, //! Show positions associated with nodes (Compiler output). - kPositions = 0x00000020u + kPositions = 0x00000020u, + //! Always format a register type (Compiler output). + kRegType = 0x00000040u }; ASMJIT_DEFINE_ENUM_FLAGS(FormatFlags) @@ -89,7 +91,7 @@ public: //! \{ //! Resets FormatOptions to its default initialized state. - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _flags = FormatFlags::kNone; _indentation.fill(uint8_t(0)); _padding.fill(uint16_t(0)); @@ -101,31 +103,31 @@ public: //! \{ //! Returns format flags. - inline FormatFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG FormatFlags flags() const noexcept { return _flags; } //! Tests whether the given `flag` is set in format flags. - inline bool hasFlag(FormatFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(FormatFlags flag) const noexcept { return Support::test(_flags, flag); } //! Resets all format flags to `flags`. - inline void setFlags(FormatFlags flags) noexcept { _flags = flags; } + ASMJIT_INLINE_NODEBUG void setFlags(FormatFlags flags) noexcept { _flags = flags; } //! Adds `flags` to format flags. - inline void addFlags(FormatFlags flags) noexcept { _flags |= flags; } + ASMJIT_INLINE_NODEBUG void addFlags(FormatFlags flags) noexcept { _flags |= flags; } //! Removes `flags` from format flags. - inline void clearFlags(FormatFlags flags) noexcept { _flags &= ~flags; } + ASMJIT_INLINE_NODEBUG void clearFlags(FormatFlags flags) noexcept { _flags &= ~flags; } //! Returns indentation for the given indentation `group`. - inline uint8_t indentation(FormatIndentationGroup group) const noexcept { return _indentation[group]; } + ASMJIT_INLINE_NODEBUG uint8_t indentation(FormatIndentationGroup group) const noexcept { return _indentation[group]; } //! Sets indentation for the given indentation `group`. - inline void setIndentation(FormatIndentationGroup group, uint32_t n) noexcept { _indentation[group] = uint8_t(n); } + ASMJIT_INLINE_NODEBUG void setIndentation(FormatIndentationGroup group, uint32_t n) noexcept { _indentation[group] = uint8_t(n); } //! Resets indentation for the given indentation `group` to zero. - inline void resetIndentation(FormatIndentationGroup group) noexcept { _indentation[group] = uint8_t(0); } + ASMJIT_INLINE_NODEBUG void resetIndentation(FormatIndentationGroup group) noexcept { _indentation[group] = uint8_t(0); } - //! Returns pading for the given padding `group`. - inline size_t padding(FormatPaddingGroup group) const noexcept { return _padding[group]; } - //! Sets pading for the given padding `group`. - inline void setPadding(FormatPaddingGroup group, size_t n) noexcept { _padding[group] = uint16_t(n); } - //! Resets pading for the given padding `group` to zero, which means that a default padding will be used + //! Returns padding for the given padding `group`. + ASMJIT_INLINE_NODEBUG size_t padding(FormatPaddingGroup group) const noexcept { return _padding[group]; } + //! Sets padding for the given padding `group`. + ASMJIT_INLINE_NODEBUG void setPadding(FormatPaddingGroup group, size_t n) noexcept { _padding[group] = uint16_t(n); } + //! Resets padding for the given padding `group` to zero, which means that a default padding will be used //! based on the target architecture properties. - inline void resetPadding(FormatPaddingGroup group) noexcept { _padding[group] = uint16_t(0); } + ASMJIT_INLINE_NODEBUG void resetPadding(FormatPaddingGroup group) noexcept { _padding[group] = uint16_t(0); } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/func.cpp b/3rdparty/asmjit/src/asmjit/core/func.cpp index 04dc2aaf208..a8a6d3ab932 100644 --- a/3rdparty/asmjit/src/asmjit/core/func.cpp +++ b/3rdparty/asmjit/src/asmjit/core/func.cpp @@ -20,8 +20,8 @@ ASMJIT_BEGIN_NAMESPACE -// CallConv - Init & Reset -// ======================= +// CallConv - Initialization & Reset +// ================================= ASMJIT_FAVOR_SIZE Error CallConv::init(CallConvId ccId, const Environment& environment) noexcept { reset(); @@ -75,7 +75,7 @@ ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const E #if !defined(ASMJIT_NO_AARCH64) if (environment.isFamilyAArch64()) - return a64::FuncInternal::initFuncDetail(*this, signature, registerSize); + return a64::FuncInternal::initFuncDetail(*this, signature); #endif // We should never bubble here as if `cc.init()` succeeded then there has to be an implementation for the current @@ -283,4 +283,18 @@ ASMJIT_FAVOR_SIZE Error FuncArgsAssignment::updateFuncFrame(FuncFrame& frame) co return kErrorOk; } +// Func API - Tests +// ================ + +#if defined(ASMJIT_TEST) +UNIT(func_signature) { + FuncSignature signature; + signature.setRetT<int8_t>(); + signature.addArgT<int16_t>(); + signature.addArg(TypeId::kInt32); + + EXPECT_EQ(signature, FuncSignature::build<int8_t, int16_t, int32_t>()); +} +#endif + ASMJIT_END_NAMESPACE diff --git a/3rdparty/asmjit/src/asmjit/core/func.h b/3rdparty/asmjit/src/asmjit/core/func.h index 78a41f98f65..695a23bbcf0 100644 --- a/3rdparty/asmjit/src/asmjit/core/func.h +++ b/3rdparty/asmjit/src/asmjit/core/func.h @@ -28,58 +28,45 @@ ASMJIT_BEGIN_NAMESPACE //! - Target specific - calling conventions that are used by a particular architecture and ABI. For example //! Windows 64-bit calling convention and AMD64 SystemV calling convention. enum class CallConvId : uint8_t { - //! None or invalid (can't be used). - kNone = 0, - // Universal Calling Conventions // ----------------------------- //! Standard function call or explicit `__cdecl` where it can be specified. //! - //! This is a universal calling convention, which is used to initialize specific calling connventions based on + //! This is a universal calling convention, which is used to initialize specific calling conventions based on //! architecture, platform, and its ABI. - kCDecl = 1, + kCDecl = 0, //! `__stdcall` on targets that support this calling convention (X86). //! //! \note This calling convention is only supported on 32-bit X86. If used on environment that doesn't support //! this calling convention it will be replaced by \ref CallConvId::kCDecl. - kStdCall = 2, + kStdCall = 1, //! `__fastcall` on targets that support this calling convention (X86). //! //! \note This calling convention is only supported on 32-bit X86. If used on environment that doesn't support //! this calling convention it will be replaced by \ref CallConvId::kCDecl. - kFastCall = 3, + kFastCall = 2, //! `__vectorcall` on targets that support this calling convention (X86/X64). //! //! \note This calling convention is only supported on 32-bit and 64-bit X86 architecture on Windows platform. //! If used on environment that doesn't support this calling it will be replaced by \ref CallConvId::kCDecl. - kVectorCall = 4, + kVectorCall = 3, //! `__thiscall` on targets that support this calling convention (X86). //! //! \note This calling convention is only supported on 32-bit X86 Windows platform. If used on environment that //! doesn't support this calling convention it will be replaced by \ref CallConvId::kCDecl. - kThisCall = 5, + kThisCall = 4, //! `__attribute__((regparm(1)))` convention (GCC and Clang). - kRegParm1 = 6, + kRegParm1 = 5, //! `__attribute__((regparm(2)))` convention (GCC and Clang). - kRegParm2 = 7, + kRegParm2 = 6, //! `__attribute__((regparm(3)))` convention (GCC and Clang). - kRegParm3 = 8, - - //! Soft-float calling convention (ARM). - //! - //! Floating point arguments are passed via general purpose registers. - kSoftFloat = 9, - - //! Hard-float calling convention (ARM). - //! - //! Floating point arguments are passed via SIMD registers. - kHardFloat = 10, + kRegParm3 = 7, //! AsmJit specific calling convention designed for calling functions inside a multimedia code that don't use many //! registers internally, but are long enough to be called and not inlined. These functions are usually used to @@ -91,28 +78,32 @@ enum class CallConvId : uint8_t { // ABI-Specific Calling Conventions // -------------------------------- + //! Soft-float calling convention (AArch32). + //! + //! Floating point arguments are passed via general purpose registers. + kSoftFloat = 30, + + //! Hard-float calling convention (AArch32). + //! + //! Floating point arguments are passed via SIMD registers. + kHardFloat = 31, + //! X64 System-V calling convention. kX64SystemV = 32, //! X64 Windows calling convention. kX64Windows = 33, //! Maximum value of `CallConvId`. - kMaxValue = kX64Windows, - - // Host Calling Conventions - // ------------------------ - - //! Host calling convention detected at compile-time. - kHost = -#if defined(_DOXYGEN) - DETECTED_AT_COMPILE_TIME -#elif ASMJIT_ARCH_ARM == 32 && defined(__SOFTFP__) - kSoftFloat -#elif ASMJIT_ARCH_ARM == 32 && !defined(__SOFTFP__) - kHardFloat -#else - kCDecl -#endif + kMaxValue = kX64Windows + + // Deprecated Aliases + // ------------------ + +#if !defined(ASMJIT_NO_DEPRECATED) + , + kNone = kCDecl, + kHost = kCDecl +#endif // !ASMJIT_NO_DEPRECATED }; //! Strategy used by calling conventions to assign registers to function arguments. @@ -128,6 +119,8 @@ enum class CallConvStrategy : uint8_t { kX64Windows = 1, //! Windows 64-bit __vectorcall register assignment strategy. kX64VectorCall = 2, + //! Apple's AArch64 calling convention (differs compared to AArch64 calling convention used by Linux). + kAArch64Apple = 3, //! Maximum value of `CallConvStrategy`. kMaxValue = kX64VectorCall @@ -163,14 +156,12 @@ struct CallConv { //! \name Constants //! \{ - enum : uint32_t { - //! Maximum number of register arguments per register group. - //! - //! \note This is not really AsmJit's limitatation, it's just the number that makes sense considering all common - //! calling conventions. Usually even conventions that use registers to pass function arguments are limited to 8 - //! and less arguments passed via registers per group. - kMaxRegArgsPerGroup = 16 - }; + //! Maximum number of register arguments per register group. + //! + //! \note This is not really AsmJit's limitation, it's just the number that makes sense considering all common + //! calling conventions. Usually even conventions that use registers to pass function arguments are limited to 8 + //! and less arguments passed via registers per group. + static constexpr uint32_t kMaxRegArgsPerGroup = 16; //! \} @@ -191,6 +182,11 @@ struct CallConv { //! Natural stack alignment as defined by OS/ABI. uint8_t _naturalStackAlignment; + //! \cond INTERNAL + //! Reserved for future use. + uint8_t _reserved[2]; + //! \endcond + //! Calling convention flags. CallConvFlags _flags; @@ -230,8 +226,8 @@ struct CallConv { //! It's recommended to reset the \ref CallConv struct in case you would like create a custom calling convention //! as it prevents from using an uninitialized data (CallConv doesn't have a constructor that would initialize it, //! it's just a struct). - inline void reset() noexcept { - memset(this, 0, sizeof(*this)); + ASMJIT_INLINE_NODEBUG void reset() noexcept { + *this = CallConv{}; memset(_passedOrder.data(), 0xFF, sizeof(_passedOrder)); } @@ -241,61 +237,61 @@ struct CallConv { //! \{ //! Returns the target architecture of this calling convention. - inline Arch arch() const noexcept { return _arch; } + ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; } //! Sets the target architecture of this calling convention. - inline void setArch(Arch arch) noexcept { _arch = arch; } + ASMJIT_INLINE_NODEBUG void setArch(Arch arch) noexcept { _arch = arch; } //! Returns the calling convention id. - inline CallConvId id() const noexcept { return _id; } + ASMJIT_INLINE_NODEBUG CallConvId id() const noexcept { return _id; } //! Sets the calling convention id. - inline void setId(CallConvId ccId) noexcept { _id = ccId; } + ASMJIT_INLINE_NODEBUG void setId(CallConvId ccId) noexcept { _id = ccId; } //! Returns the strategy used to assign registers to arguments. - inline CallConvStrategy strategy() const noexcept { return _strategy; } + ASMJIT_INLINE_NODEBUG CallConvStrategy strategy() const noexcept { return _strategy; } //! Sets the strategy used to assign registers to arguments. - inline void setStrategy(CallConvStrategy ccStrategy) noexcept { _strategy = ccStrategy; } + ASMJIT_INLINE_NODEBUG void setStrategy(CallConvStrategy ccStrategy) noexcept { _strategy = ccStrategy; } //! Tests whether the calling convention has the given `flag` set. - inline bool hasFlag(CallConvFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(CallConvFlags flag) const noexcept { return Support::test(_flags, flag); } //! Returns the calling convention flags, see `Flags`. - inline CallConvFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG CallConvFlags flags() const noexcept { return _flags; } //! Adds the calling convention flags, see `Flags`. - inline void setFlags(CallConvFlags flag) noexcept { _flags = flag; }; + ASMJIT_INLINE_NODEBUG void setFlags(CallConvFlags flag) noexcept { _flags = flag; }; //! Adds the calling convention flags, see `Flags`. - inline void addFlags(CallConvFlags flags) noexcept { _flags |= flags; }; + ASMJIT_INLINE_NODEBUG void addFlags(CallConvFlags flags) noexcept { _flags |= flags; }; //! Tests whether this calling convention specifies 'RedZone'. - inline bool hasRedZone() const noexcept { return _redZoneSize != 0; } + ASMJIT_INLINE_NODEBUG bool hasRedZone() const noexcept { return _redZoneSize != 0; } //! Tests whether this calling convention specifies 'SpillZone'. - inline bool hasSpillZone() const noexcept { return _spillZoneSize != 0; } + ASMJIT_INLINE_NODEBUG bool hasSpillZone() const noexcept { return _spillZoneSize != 0; } //! Returns size of 'RedZone'. - inline uint32_t redZoneSize() const noexcept { return _redZoneSize; } + ASMJIT_INLINE_NODEBUG uint32_t redZoneSize() const noexcept { return _redZoneSize; } //! Returns size of 'SpillZone'. - inline uint32_t spillZoneSize() const noexcept { return _spillZoneSize; } + ASMJIT_INLINE_NODEBUG uint32_t spillZoneSize() const noexcept { return _spillZoneSize; } //! Sets size of 'RedZone'. - inline void setRedZoneSize(uint32_t size) noexcept { _redZoneSize = uint8_t(size); } + ASMJIT_INLINE_NODEBUG void setRedZoneSize(uint32_t size) noexcept { _redZoneSize = uint8_t(size); } //! Sets size of 'SpillZone'. - inline void setSpillZoneSize(uint32_t size) noexcept { _spillZoneSize = uint8_t(size); } + ASMJIT_INLINE_NODEBUG void setSpillZoneSize(uint32_t size) noexcept { _spillZoneSize = uint8_t(size); } //! Returns a natural stack alignment. - inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } + ASMJIT_INLINE_NODEBUG uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } //! Sets a natural stack alignment. //! //! This function can be used to override the default stack alignment in case that you know that it's alignment is //! different. For example it allows to implement custom calling conventions that guarantee higher stack alignment. - inline void setNaturalStackAlignment(uint32_t value) noexcept { _naturalStackAlignment = uint8_t(value); } + ASMJIT_INLINE_NODEBUG void setNaturalStackAlignment(uint32_t value) noexcept { _naturalStackAlignment = uint8_t(value); } //! Returns the size of a register (or its part) to be saved and restored of the given `group`. - inline uint32_t saveRestoreRegSize(RegGroup group) const noexcept { return _saveRestoreRegSize[group]; } + ASMJIT_INLINE_NODEBUG uint32_t saveRestoreRegSize(RegGroup group) const noexcept { return _saveRestoreRegSize[group]; } //! Sets the size of a vector register (or its part) to be saved and restored. - inline void setSaveRestoreRegSize(RegGroup group, uint32_t size) noexcept { _saveRestoreRegSize[group] = uint8_t(size); } + ASMJIT_INLINE_NODEBUG void setSaveRestoreRegSize(RegGroup group, uint32_t size) noexcept { _saveRestoreRegSize[group] = uint8_t(size); } //! Returns the alignment of a save-restore area of the given `group`. - inline uint32_t saveRestoreAlignment(RegGroup group) const noexcept { return _saveRestoreAlignment[group]; } + ASMJIT_INLINE_NODEBUG uint32_t saveRestoreAlignment(RegGroup group) const noexcept { return _saveRestoreAlignment[group]; } //! Sets the alignment of a save-restore area of the given `group`. - inline void setSaveRestoreAlignment(RegGroup group, uint32_t alignment) noexcept { _saveRestoreAlignment[group] = uint8_t(alignment); } + ASMJIT_INLINE_NODEBUG void setSaveRestoreAlignment(RegGroup group, uint32_t alignment) noexcept { _saveRestoreAlignment[group] = uint8_t(alignment); } //! Returns the order of passed registers of the given `group`. inline const uint8_t* passedOrder(RegGroup group) const noexcept { @@ -364,16 +360,21 @@ struct CallConv { //! Function signature. //! -//! Contains information about function return type, count of arguments and their TypeIds. Function signature is -//! a low level structure which doesn't contain platform specific or calling convention specific information. +//! Contains information about a function return type, count of arguments, and their TypeIds. Function signature +//! is a low level structure which doesn't contain platform specific or calling convention specific information. +//! It's typically used to describe function arguments in a C-API like form, which is then used to calculate a +//! \ref FuncDetail instance, which then maps function signature into a platform and calling convention specific +//! format. +//! +//! Function signature can be built either dynamically by using \ref addArg() and \ref addArgT() functionality, +//! or dynamically by using a template-based \ref FuncSignature::build() function, which maps template types +//! into a function signature. struct FuncSignature { //! \name Constants //! \{ - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFFu - }; + //! Doesn't have variable number of arguments (`...`). + static constexpr uint8_t kNoVarArgs = 0xFFu; //! \} @@ -381,90 +382,87 @@ struct FuncSignature { //! \{ //! Calling convention id. - CallConvId _ccId; + CallConvId _ccId = CallConvId::kCDecl; //! Count of arguments. - uint8_t _argCount; + uint8_t _argCount = 0; //! Index of a first VA or `kNoVarArgs`. - uint8_t _vaIndex; + uint8_t _vaIndex = kNoVarArgs; //! Return value TypeId. - TypeId _ret; - //! Function arguments TypeIds. - const TypeId* _args; + TypeId _ret = TypeId::kVoid; + //! Reserved for future use. + uint8_t _reserved[4] {}; + //! Function argument TypeIds. + TypeId _args[Globals::kMaxFuncArgs] {}; //! \} - //! \name Initializtion & Reset + //! \name Construction & Destruction //! \{ - //! Initializes the function signature. - inline void init(CallConvId ccId, uint32_t vaIndex, TypeId ret, const TypeId* args, uint32_t argCount) noexcept { - ASMJIT_ASSERT(argCount <= 0xFF); + //! Default constructed function signature, initialized to \ref CallConvId::kCDecl, having no return value and no arguments. + ASMJIT_FORCE_INLINE constexpr FuncSignature() = default; - _ccId = ccId; - _argCount = uint8_t(argCount); - _vaIndex = uint8_t(vaIndex); - _ret = ret; - _args = args; - } + //! Copy constructor, which is initialized to the same function signature as `other`. + ASMJIT_FORCE_INLINE constexpr FuncSignature(const FuncSignature& other) = default; + + //! Initializes the function signature with calling convention id `ccId` and variable argument's index `vaIndex`. + ASMJIT_FORCE_INLINE constexpr FuncSignature(CallConvId ccId, uint32_t vaIndex = kNoVarArgs) noexcept + : _ccId(ccId), + _vaIndex(uint8_t(vaIndex)) {} - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + //! Initializes the function signature with calling convention id `ccId`, `vaIndex`, return value, and function arguments. + template<typename... Args> + ASMJIT_FORCE_INLINE constexpr FuncSignature(CallConvId ccId, uint32_t vaIndex, TypeId ret, Args&&...args) noexcept + : _ccId(ccId), + _argCount(uint8_t(sizeof...(args))), + _vaIndex(uint8_t(vaIndex)), + _ret(ret), + _args{std::forward<Args>(args)...} {} + + //! Builds a function signature based on `RetValueAndArgs`. The first template argument is a function return type, + //! and function arguments follow. + //! + //! \note This function returns a new function signature, which can be passed to functions where it's required. It's + //! a convenience function that allows to build function signature statically based on types known at compile time, + //! which is common in JIT code generation. + template<typename... RetValueAndArgs> + static ASMJIT_INLINE_NODEBUG constexpr FuncSignature build(CallConvId ccId = CallConvId::kCDecl, uint32_t vaIndex = kNoVarArgs) noexcept { + return FuncSignature(ccId, vaIndex, (TypeId(TypeUtils::TypeIdOfT<RetValueAndArgs>::kTypeId))... ); + } //! \} - //! \name Accessors + //! \name Overloaded Operators //! \{ - //! Returns the calling convention. - inline CallConvId callConvId() const noexcept { return _ccId; } - //! Sets the calling convention to `ccId`; - inline void setCallConvId(CallConvId ccId) noexcept { _ccId = ccId; } + //! Copy assignment - function signature can be copied by value. + ASMJIT_FORCE_INLINE FuncSignature& operator=(const FuncSignature& other) noexcept = default; - //! Tests whether the function has variable number of arguments (...). - inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } - //! Returns the variable arguments (...) index, `kNoVarArgs` if none. - inline uint32_t vaIndex() const noexcept { return _vaIndex; } - //! Sets the variable arguments (...) index to `index`. - inline void setVaIndex(uint32_t index) noexcept { _vaIndex = uint8_t(index); } - //! Resets the variable arguments index (making it a non-va function). - inline void resetVaIndex() noexcept { _vaIndex = kNoVarArgs; } + //! Compares this function signature with `other` for equality.. + ASMJIT_FORCE_INLINE bool operator==(const FuncSignature& other) const noexcept { return equals(other); } + //! Compares this function signature with `other` for inequality.. + ASMJIT_FORCE_INLINE bool operator!=(const FuncSignature& other) const noexcept { return !equals(other); } - //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _argCount; } + //! \} - inline bool hasRet() const noexcept { return _ret != TypeId::kVoid; } - //! Returns the return value type. - inline TypeId ret() const noexcept { return _ret; } + //! \name Initialization & Reset + //! \{ - //! Returns the type of the argument at index `i`. - inline TypeId arg(uint32_t i) const noexcept { - ASMJIT_ASSERT(i < _argCount); - return _args[i]; - } - //! Returns the array of function arguments' types. - inline const TypeId* args() const noexcept { return _args; } + //! Resets this function signature to a default constructed state. + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncSignature{}; } //! \} -}; -template<typename... RET_ARGS> -class FuncSignatureT : public FuncSignature { -public: - inline FuncSignatureT(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept { - static constexpr TypeId ret_args[] = { (TypeId(TypeUtils::TypeIdOfT<RET_ARGS>::kTypeId))... }; - init(ccId, vaIndex, ret_args[0], ret_args + 1, uint32_t(ASMJIT_ARRAY_SIZE(ret_args) - 1)); - } -}; - -//! Function signature builder. -class FuncSignatureBuilder : public FuncSignature { -public: - TypeId _builderArgList[Globals::kMaxFuncArgs]; - - //! \name Initializtion & Reset + //! \name Equality & Comparison //! \{ - inline FuncSignatureBuilder(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept { - init(ccId, vaIndex, TypeId::kVoid, _builderArgList, 0); + //! Compares this function signature with `other` for equality.. + ASMJIT_INLINE_NODEBUG bool equals(const FuncSignature& other) const noexcept { + return _ccId == other._ccId && + _argCount == other._argCount && + _vaIndex == other._vaIndex && + _ret == other._ret && + memcmp(_args, other._args, sizeof(_args)) == 0; } //! \} @@ -472,33 +470,85 @@ public: //! \name Accessors //! \{ + //! Returns the calling convention. + ASMJIT_INLINE_NODEBUG CallConvId callConvId() const noexcept { return _ccId; } + //! Sets the calling convention to `ccId`; + ASMJIT_INLINE_NODEBUG void setCallConvId(CallConvId ccId) noexcept { _ccId = ccId; } + + //! Tests whether the function signature has a return value. + ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _ret != TypeId::kVoid; } + //! Returns the type of the return value. + ASMJIT_INLINE_NODEBUG TypeId ret() const noexcept { return _ret; } //! Sets the return type to `retType`. - inline void setRet(TypeId retType) noexcept { _ret = retType; } + ASMJIT_INLINE_NODEBUG void setRet(TypeId retType) noexcept { _ret = retType; } //! Sets the return type based on `T`. template<typename T> - inline void setRetT() noexcept { setRet(TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); } + ASMJIT_INLINE_NODEBUG void setRetT() noexcept { setRet(TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); } + + + //! Returns the array of function arguments' types. + ASMJIT_INLINE_NODEBUG const TypeId* args() const noexcept { return _args; } + //! Returns the number of function arguments. + ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _argCount; } + + //! Returns the type of the argument at index `i`. + inline TypeId arg(uint32_t i) const noexcept { + ASMJIT_ASSERT(i < _argCount); + return _args[i]; + } //! Sets the argument at index `index` to `argType`. inline void setArg(uint32_t index, TypeId argType) noexcept { ASMJIT_ASSERT(index < _argCount); - _builderArgList[index] = argType; + _args[index] = argType; } //! Sets the argument at index `i` to the type based on `T`. template<typename T> inline void setArgT(uint32_t index) noexcept { setArg(index, TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); } + //! Tests whether an argument can be added to the signature, use before calling \ref addArg() and \ref addArgT(). + //! + //! \note If you know that you are not adding more arguments than \ref Globals::kMaxFuncArgs then it's not necessary + //! to use this function. However, if you are adding arguments based on user input, for example, then either check + //! the number of arguments before using function signature or use \ref canAddArg() before actually adding them to + //! the function signature. + inline bool canAddArg() const noexcept { return _argCount < Globals::kMaxFuncArgs; } + //! Appends an argument of `type` to the function prototype. inline void addArg(TypeId type) noexcept { ASMJIT_ASSERT(_argCount < Globals::kMaxFuncArgs); - _builderArgList[_argCount++] = type; + _args[_argCount++] = type; } + //! Appends an argument of type based on `T` to the function prototype. template<typename T> inline void addArgT() noexcept { addArg(TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); } + //! Tests whether the function has variable number of arguments (...). + ASMJIT_INLINE_NODEBUG bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } + //! Returns the variable arguments (...) index, `kNoVarArgs` if none. + ASMJIT_INLINE_NODEBUG uint32_t vaIndex() const noexcept { return _vaIndex; } + //! Sets the variable arguments (...) index to `index`. + ASMJIT_INLINE_NODEBUG void setVaIndex(uint32_t index) noexcept { _vaIndex = uint8_t(index); } + //! Resets the variable arguments index (making it a non-va function). + ASMJIT_INLINE_NODEBUG void resetVaIndex() noexcept { _vaIndex = kNoVarArgs; } + //! \} }; +#if !defined(ASMJIT_NO_DEPRECATED) +template<typename... RetValueAndArgs> +class FuncSignatureT : public FuncSignature { +public: + ASMJIT_DEPRECATED("Use FuncSignature::build<RetValueAndArgs>() instead") + ASMJIT_INLINE_NODEBUG constexpr FuncSignatureT(CallConvId ccId = CallConvId::kCDecl, uint32_t vaIndex = kNoVarArgs) noexcept + : FuncSignature(ccId, vaIndex, (TypeId(TypeUtils::TypeIdOfT<RetValueAndArgs>::kTypeId))... ) {} +}; + +ASMJIT_DEPRECATED("Use FuncSignature instead of FuncSignatureBuilder") +typedef FuncSignature FuncSignatureBuilder; +#endif // !ASMJIT_NO_DEPRECATED + //! Argument or return value (or its part) as defined by `FuncSignature`, but with register or stack address //! (and other metadata) assigned. struct FuncValue { @@ -533,43 +583,47 @@ struct FuncValue { //! \} - //! \name Initializtion & Reset + //! \name Initialization & Reset //! //! These initialize the whole `FuncValue` to either register or stack. Useful when you know all of these //! properties and wanna just set it up. //! //! \{ - //! Initializes the `typeId` of this `FuncValue`. - inline void initTypeId(TypeId typeId) noexcept { + //! Initializes this `FuncValue` only to the `typeId` provided - the rest of the values will be cleared. + ASMJIT_INLINE_NODEBUG void initTypeId(TypeId typeId) noexcept { _data = uint32_t(typeId) << kTypeIdShift; } - inline void initReg(RegType regType, uint32_t regId, TypeId typeId, uint32_t flags = 0) noexcept { + //! Initializes this `FuncValue` to a register of `regType`, `regId`, and assigns its `typeId` and `flags`. + ASMJIT_INLINE_NODEBUG void initReg(RegType regType, uint32_t regId, TypeId typeId, uint32_t flags = 0) noexcept { _data = (uint32_t(regType) << kRegTypeShift) | (regId << kRegIdShift) | (uint32_t(typeId) << kTypeIdShift) | kFlagIsReg | flags; } - inline void initStack(int32_t offset, TypeId typeId) noexcept { + //! Initializes this `FuncValue` to a stack at the given `offset` and assigns its `typeId`. + ASMJIT_INLINE_NODEBUG void initStack(int32_t offset, TypeId typeId) noexcept { _data = (uint32_t(offset) << kStackOffsetShift) | (uint32_t(typeId) << kTypeIdShift) | kFlagIsStack; } //! Resets the value to its unassigned state. - inline void reset() noexcept { _data = 0; } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _data = 0; } //! \} //! \name Assign //! //! These initialize only part of `FuncValue`, useful when building `FuncValue` incrementally. The caller - //! should first init the type-id by caliing `initTypeId` and then continue building either register or stack. + //! should first init the type-id by calling `initTypeId` and then continue building either register or stack. //! //! \{ + //! Assigns a register of `regType` and `regId`. inline void assignRegData(RegType regType, uint32_t regId) noexcept { ASMJIT_ASSERT((_data & (kRegTypeMask | kRegIdMask)) == 0); _data |= (uint32_t(regType) << kRegTypeShift) | (regId << kRegIdShift) | kFlagIsReg; } + //! Assigns a stack location at `offset`. inline void assignStackOffset(int32_t offset) noexcept { ASMJIT_ASSERT((_data & kStackOffsetMask) == 0); _data |= (uint32_t(offset) << kStackOffsetShift) | kFlagIsStack; @@ -581,52 +635,54 @@ struct FuncValue { //! \{ //! Returns true if the value is initialized (explicit bool cast). - inline explicit operator bool() const noexcept { return _data != 0; } + ASMJIT_INLINE_NODEBUG explicit operator bool() const noexcept { return _data != 0; } - inline void _replaceValue(uint32_t mask, uint32_t value) noexcept { _data = (_data & ~mask) | value; } + //! \cond INTERNAL + ASMJIT_INLINE_NODEBUG void _replaceValue(uint32_t mask, uint32_t value) noexcept { _data = (_data & ~mask) | value; } + //! \endcond //! Tests whether the `FuncValue` has a flag `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return Support::test(_data, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(uint32_t flag) const noexcept { return Support::test(_data, flag); } //! Adds `flags` to `FuncValue`. - inline void addFlags(uint32_t flags) noexcept { _data |= flags; } + ASMJIT_INLINE_NODEBUG void addFlags(uint32_t flags) noexcept { _data |= flags; } //! Clears `flags` of `FuncValue`. - inline void clearFlags(uint32_t flags) noexcept { _data &= ~flags; } + ASMJIT_INLINE_NODEBUG void clearFlags(uint32_t flags) noexcept { _data &= ~flags; } //! Tests whether the value is initialized (i.e. contains a valid data). - inline bool isInitialized() const noexcept { return _data != 0; } + ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _data != 0; } //! Tests whether the argument is passed by register. - inline bool isReg() const noexcept { return hasFlag(kFlagIsReg); } + ASMJIT_INLINE_NODEBUG bool isReg() const noexcept { return hasFlag(kFlagIsReg); } //! Tests whether the argument is passed by stack. - inline bool isStack() const noexcept { return hasFlag(kFlagIsStack); } + ASMJIT_INLINE_NODEBUG bool isStack() const noexcept { return hasFlag(kFlagIsStack); } //! Tests whether the argument is passed by register. - inline bool isAssigned() const noexcept { return hasFlag(kFlagIsReg | kFlagIsStack); } + ASMJIT_INLINE_NODEBUG bool isAssigned() const noexcept { return hasFlag(kFlagIsReg | kFlagIsStack); } //! Tests whether the argument is passed through a pointer (used by WIN64 to pass XMM|YMM|ZMM). - inline bool isIndirect() const noexcept { return hasFlag(kFlagIsIndirect); } + ASMJIT_INLINE_NODEBUG bool isIndirect() const noexcept { return hasFlag(kFlagIsIndirect); } //! Tests whether the argument was already processed (used internally). - inline bool isDone() const noexcept { return hasFlag(kFlagIsDone); } + ASMJIT_INLINE_NODEBUG bool isDone() const noexcept { return hasFlag(kFlagIsDone); } //! Returns a register type of the register used to pass function argument or return value. - inline RegType regType() const noexcept { return RegType((_data & kRegTypeMask) >> kRegTypeShift); } + ASMJIT_INLINE_NODEBUG RegType regType() const noexcept { return RegType((_data & kRegTypeMask) >> kRegTypeShift); } //! Sets a register type of the register used to pass function argument or return value. - inline void setRegType(RegType regType) noexcept { _replaceValue(kRegTypeMask, uint32_t(regType) << kRegTypeShift); } + ASMJIT_INLINE_NODEBUG void setRegType(RegType regType) noexcept { _replaceValue(kRegTypeMask, uint32_t(regType) << kRegTypeShift); } //! Returns a physical id of the register used to pass function argument or return value. - inline uint32_t regId() const noexcept { return (_data & kRegIdMask) >> kRegIdShift; } + ASMJIT_INLINE_NODEBUG uint32_t regId() const noexcept { return (_data & kRegIdMask) >> kRegIdShift; } //! Sets a physical id of the register used to pass function argument or return value. - inline void setRegId(uint32_t regId) noexcept { _replaceValue(kRegIdMask, regId << kRegIdShift); } + ASMJIT_INLINE_NODEBUG void setRegId(uint32_t regId) noexcept { _replaceValue(kRegIdMask, regId << kRegIdShift); } //! Returns a stack offset of this argument. - inline int32_t stackOffset() const noexcept { return int32_t(_data & kStackOffsetMask) >> kStackOffsetShift; } + ASMJIT_INLINE_NODEBUG int32_t stackOffset() const noexcept { return int32_t(_data & kStackOffsetMask) >> kStackOffsetShift; } //! Sets a stack offset of this argument. - inline void setStackOffset(int32_t offset) noexcept { _replaceValue(kStackOffsetMask, uint32_t(offset) << kStackOffsetShift); } + ASMJIT_INLINE_NODEBUG void setStackOffset(int32_t offset) noexcept { _replaceValue(kStackOffsetMask, uint32_t(offset) << kStackOffsetShift); } //! Tests whether the argument or return value has associated `TypeId`. - inline bool hasTypeId() const noexcept { return Support::test(_data, kTypeIdMask); } + ASMJIT_INLINE_NODEBUG bool hasTypeId() const noexcept { return Support::test(_data, kTypeIdMask); } //! Returns a TypeId of this argument or return value. - inline TypeId typeId() const noexcept { return TypeId((_data & kTypeIdMask) >> kTypeIdShift); } + ASMJIT_INLINE_NODEBUG TypeId typeId() const noexcept { return TypeId((_data & kTypeIdMask) >> kTypeIdShift); } //! Sets a TypeId of this argument or return value. - inline void setTypeId(TypeId typeId) noexcept { _replaceValue(kTypeIdMask, uint32_t(typeId) << kTypeIdShift); } + ASMJIT_INLINE_NODEBUG void setTypeId(TypeId typeId) noexcept { _replaceValue(kTypeIdMask, uint32_t(typeId) << kTypeIdShift); } //! \} }; @@ -665,40 +721,52 @@ public: return n; } - inline FuncValue* values() noexcept { return _values; } - inline const FuncValue* values() const noexcept { return _values; } + //! Returns values in this value in the pack. + //! + //! \note The returned array has exactly \ref Globals::kMaxValuePack elements. + ASMJIT_INLINE_NODEBUG FuncValue* values() noexcept { return _values; } + //! \overload + ASMJIT_INLINE_NODEBUG const FuncValue* values() const noexcept { return _values; } + //! Resets a value at the given `index` in the pack, which makes it unassigned. inline void resetValue(size_t index) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); _values[index].reset(); } + //! Tests whether the value at the given `index` in the pack is assigned. inline bool hasValue(size_t index) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); return _values[index].isInitialized(); } + //! Assigns a register at the given `index` to `reg` and an optional `typeId`. inline void assignReg(size_t index, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); ASMJIT_ASSERT(reg.isPhysReg()); _values[index].initReg(reg.type(), reg.id(), typeId); } + //! Assigns a register at the given `index` to `regType`, `regId`, and an optional `typeId`. inline void assignReg(size_t index, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); _values[index].initReg(regType, regId, typeId); } + //! Assigns a stack location at the given `index` to `offset` and an optional `typeId`. inline void assignStack(size_t index, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); _values[index].initStack(offset, typeId); } + //! Accesses the value in the pack at the given `index`. + //! + //! \note The maximum index value is `Globals::kMaxValuePack - 1`. inline FuncValue& operator[](size_t index) { ASMJIT_ASSERT(index < Globals::kMaxValuePack); return _values[index]; } - + //! \overload inline const FuncValue& operator[](size_t index) const { ASMJIT_ASSERT(index < Globals::kMaxValuePack); return _values[index]; @@ -721,6 +789,11 @@ enum class FuncAttributes : uint32_t { kHasFuncCalls = 0x00000020u, //! Function has aligned save/restore of vector registers. kAlignedVecSR = 0x00000040u, + //! Function must begin with an instruction that marks a start of a branch or function. + //! + //! * `ENDBR32/ENDBR64` instruction is inserted at the beginning of the function (X86, X86_64). + //! * `BTI` instruction is inserted at the beginning of the function (AArch64) + kIndirectBranchProtection = 0x00000080u, //! FuncFrame is finalized and can be used by prolog/epilog inserter (PEI). kIsFinalized = 0x00000800u, @@ -757,10 +830,8 @@ public: //! \name Constants //! \{ - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFFu - }; + //! Function doesn't have a variable number of arguments (`...`). + static constexpr uint8_t kNoVarArgs = 0xFFu; //! \} @@ -768,33 +839,53 @@ public: //! \{ //! Calling convention. - CallConv _callConv; + CallConv _callConv {}; //! Number of function arguments. - uint8_t _argCount; + uint8_t _argCount = 0; //! Variable arguments index of `kNoVarArgs`. - uint8_t _vaIndex; + uint8_t _vaIndex = 0; //! Reserved for future use. - uint16_t _reserved; + uint16_t _reserved = 0; //! Registers that contain arguments. - Support::Array<RegMask, Globals::kNumVirtGroups> _usedRegs; + Support::Array<RegMask, Globals::kNumVirtGroups> _usedRegs {}; //! Size of arguments passed by stack. - uint32_t _argStackSize; + uint32_t _argStackSize = 0; //! Function return value(s). - FuncValuePack _rets; + FuncValuePack _rets {}; //! Function arguments. - FuncValuePack _args[Globals::kMaxFuncArgs]; + FuncValuePack _args[Globals::kMaxFuncArgs] {}; //! \} //! \name Construction & Destruction //! \{ - inline FuncDetail() noexcept { reset(); } - inline FuncDetail(const FuncDetail& other) noexcept = default; + //! Creates a default constructed \ref FuncDetail. + ASMJIT_INLINE_NODEBUG FuncDetail() noexcept {} + + //! Copy constructor. + //! + //! Function details are copyable. + ASMJIT_INLINE_NODEBUG FuncDetail(const FuncDetail& other) noexcept = default; //! Initializes this `FuncDetail` to the given signature. ASMJIT_API Error init(const FuncSignature& signature, const Environment& environment) noexcept; - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + + //! \} + + //! \name Overloaded Operators + //! \{ + + //! Assignment operator, copies `other` to this \ref FuncDetail. + ASMJIT_INLINE_NODEBUG FuncDetail& operator=(const FuncDetail& other) noexcept = default; + + //! \} + + //! \name Reset + //! \{ + + //! Resets the function detail to its default constructed state. + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncDetail{}; } //! \} @@ -802,32 +893,32 @@ public: //! \{ //! Returns the function's calling convention, see `CallConv`. - inline const CallConv& callConv() const noexcept { return _callConv; } + ASMJIT_INLINE_NODEBUG const CallConv& callConv() const noexcept { return _callConv; } //! Returns the associated calling convention flags, see `CallConv::Flags`. - inline CallConvFlags flags() const noexcept { return _callConv.flags(); } + ASMJIT_INLINE_NODEBUG CallConvFlags flags() const noexcept { return _callConv.flags(); } //! Checks whether a CallConv `flag` is set, see `CallConv::Flags`. - inline bool hasFlag(CallConvFlags ccFlag) const noexcept { return _callConv.hasFlag(ccFlag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(CallConvFlags ccFlag) const noexcept { return _callConv.hasFlag(ccFlag); } //! Tests whether the function has a return value. - inline bool hasRet() const noexcept { return bool(_rets[0]); } + ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return bool(_rets[0]); } //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _argCount; } + ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _argCount; } //! Returns function return values. - inline FuncValuePack& retPack() noexcept { return _rets; } + ASMJIT_INLINE_NODEBUG FuncValuePack& retPack() noexcept { return _rets; } //! Returns function return values. - inline const FuncValuePack& retPack() const noexcept { return _rets; } + ASMJIT_INLINE_NODEBUG const FuncValuePack& retPack() const noexcept { return _rets; } //! Returns a function return value associated with the given `valueIndex`. - inline FuncValue& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; } + ASMJIT_INLINE_NODEBUG FuncValue& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; } //! Returns a function return value associated with the given `valueIndex` (const). - inline const FuncValue& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; } + ASMJIT_INLINE_NODEBUG const FuncValue& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; } //! Returns function argument packs array. - inline FuncValuePack* argPacks() noexcept { return _args; } + ASMJIT_INLINE_NODEBUG FuncValuePack* argPacks() noexcept { return _args; } //! Returns function argument packs array (const). - inline const FuncValuePack* argPacks() const noexcept { return _args; } + ASMJIT_INLINE_NODEBUG const FuncValuePack* argPacks() const noexcept { return _args; } //! Returns function argument pack at the given `argIndex`. inline FuncValuePack& argPack(size_t argIndex) noexcept { @@ -862,26 +953,26 @@ public: } //! Tests whether the function has variable arguments. - inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } + ASMJIT_INLINE_NODEBUG bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } //! Returns an index of a first variable argument. - inline uint32_t vaIndex() const noexcept { return _vaIndex; } + ASMJIT_INLINE_NODEBUG uint32_t vaIndex() const noexcept { return _vaIndex; } //! Tests whether the function passes one or more argument by stack. - inline bool hasStackArgs() const noexcept { return _argStackSize != 0; } + ASMJIT_INLINE_NODEBUG bool hasStackArgs() const noexcept { return _argStackSize != 0; } //! Returns stack size needed for function arguments passed on the stack. - inline uint32_t argStackSize() const noexcept { return _argStackSize; } + ASMJIT_INLINE_NODEBUG uint32_t argStackSize() const noexcept { return _argStackSize; } //! Returns red zone size. - inline uint32_t redZoneSize() const noexcept { return _callConv.redZoneSize(); } + ASMJIT_INLINE_NODEBUG uint32_t redZoneSize() const noexcept { return _callConv.redZoneSize(); } //! Returns spill zone size. - inline uint32_t spillZoneSize() const noexcept { return _callConv.spillZoneSize(); } + ASMJIT_INLINE_NODEBUG uint32_t spillZoneSize() const noexcept { return _callConv.spillZoneSize(); } //! Returns natural stack alignment. - inline uint32_t naturalStackAlignment() const noexcept { return _callConv.naturalStackAlignment(); } + ASMJIT_INLINE_NODEBUG uint32_t naturalStackAlignment() const noexcept { return _callConv.naturalStackAlignment(); } //! Returns a mask of all passed registers of the given register `group`. - inline RegMask passedRegs(RegGroup group) const noexcept { return _callConv.passedRegs(group); } + ASMJIT_INLINE_NODEBUG RegMask passedRegs(RegGroup group) const noexcept { return _callConv.passedRegs(group); } //! Returns a mask of all preserved registers of the given register `group`. - inline RegMask preservedRegs(RegGroup group) const noexcept { return _callConv.preservedRegs(group); } + ASMJIT_INLINE_NODEBUG RegMask preservedRegs(RegGroup group) const noexcept { return _callConv.preservedRegs(group); } //! Returns a mask of all used registers of the given register `group`. inline RegMask usedRegs(RegGroup group) const noexcept { @@ -901,7 +992,7 @@ public: //! Function frame. //! //! Function frame is used directly by prolog and epilog insertion (PEI) utils. It provides information necessary to -//! insert a proper and ABI comforming prolog and epilog. Function frame calculation is based on `CallConv` and +//! insert a proper and ABI conforming prolog and epilog. Function frame calculation is based on `CallConv` and //! other function attributes. //! //! SSE vs AVX vs AVX-512 @@ -954,87 +1045,98 @@ public: //! \{ //! Function attributes. - FuncAttributes _attributes; + FuncAttributes _attributes {}; //! Target architecture. - Arch _arch; + Arch _arch {}; //! SP register ID (to access call stack and local stack). - uint8_t _spRegId; + uint8_t _spRegId = uint8_t(BaseReg::kIdBad); //! SA register ID (to access stack arguments). - uint8_t _saRegId; + uint8_t _saRegId = uint8_t(BaseReg::kIdBad); //! Red zone size (copied from CallConv). - uint8_t _redZoneSize; + uint8_t _redZoneSize = 0; //! Spill zone size (copied from CallConv). - uint8_t _spillZoneSize; + uint8_t _spillZoneSize = 0; //! Natural stack alignment (copied from CallConv). - uint8_t _naturalStackAlignment; + uint8_t _naturalStackAlignment = 0; //! Minimum stack alignment to turn on dynamic alignment. - uint8_t _minDynamicAlignment; + uint8_t _minDynamicAlignment = 0; //! Call stack alignment. - uint8_t _callStackAlignment; + uint8_t _callStackAlignment = 0; //! Local stack alignment. - uint8_t _localStackAlignment; + uint8_t _localStackAlignment = 0; //! Final stack alignment. - uint8_t _finalStackAlignment; + uint8_t _finalStackAlignment = 0; //! Adjustment of the stack before returning (X86-STDCALL). - uint16_t _calleeStackCleanup; + uint16_t _calleeStackCleanup = 0; //! Call stack size. - uint32_t _callStackSize; + uint32_t _callStackSize = 0; //! Local stack size. - uint32_t _localStackSize; + uint32_t _localStackSize = 0; //! Final stack size (sum of call stack and local stack). - uint32_t _finalStackSize; + uint32_t _finalStackSize = 0; //! Local stack offset (non-zero only if call stack is used). - uint32_t _localStackOffset; + uint32_t _localStackOffset = 0; //! Offset relative to SP that contains previous SP (before alignment). - uint32_t _daOffset; + uint32_t _daOffset = 0; //! Offset of the first stack argument relative to SP. - uint32_t _saOffsetFromSP; + uint32_t _saOffsetFromSP = 0; //! Offset of the first stack argument relative to SA (_saRegId or FP). - uint32_t _saOffsetFromSA; + uint32_t _saOffsetFromSA = 0; //! Local stack adjustment in prolog/epilog. - uint32_t _stackAdjustment; + uint32_t _stackAdjustment = 0; //! Registers that are dirty. - Support::Array<RegMask, Globals::kNumVirtGroups> _dirtyRegs; + Support::Array<RegMask, Globals::kNumVirtGroups> _dirtyRegs {}; //! Registers that must be preserved (copied from CallConv). - Support::Array<RegMask, Globals::kNumVirtGroups> _preservedRegs; + Support::Array<RegMask, Globals::kNumVirtGroups> _preservedRegs {}; //! Size to save/restore per register group. - Support::Array<uint8_t, Globals::kNumVirtGroups> _saveRestoreRegSize; + Support::Array<uint8_t, Globals::kNumVirtGroups> _saveRestoreRegSize {}; //! Alignment of save/restore area per register group. - Support::Array<uint8_t, Globals::kNumVirtGroups> _saveRestoreAlignment; + Support::Array<uint8_t, Globals::kNumVirtGroups> _saveRestoreAlignment {}; //! Stack size required to save registers with push/pop. - uint16_t _pushPopSaveSize; + uint16_t _pushPopSaveSize = 0; //! Stack size required to save extra registers that cannot use push/pop. - uint16_t _extraRegSaveSize; + uint16_t _extraRegSaveSize = 0; //! Offset where registers saved/restored via push/pop are stored - uint32_t _pushPopSaveOffset; - //! Offset where extra ragisters that cannot use push/pop are stored. - uint32_t _extraRegSaveOffset; + uint32_t _pushPopSaveOffset = 0; + //! Offset where extra registers that cannot use push/pop are stored. + uint32_t _extraRegSaveOffset = 0; //! \} //! \name Construction & Destruction //! \{ - inline FuncFrame() noexcept { reset(); } - inline FuncFrame(const FuncFrame& other) noexcept = default; + //! Creates a default constructed function frame, which has initialized all members to their default values. + ASMJIT_INLINE_NODEBUG FuncFrame() noexcept = default; + //! Creates a copy of `other` function frame. + ASMJIT_INLINE_NODEBUG FuncFrame(const FuncFrame& other) noexcept = default; + //! \} + + //! \name Initialization & Reset + //! \{ + + //! Initializes the function frame based on `func` detail. ASMJIT_API Error init(const FuncDetail& func) noexcept; + //! Resets the function frame into its default constructed state. + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncFrame{}; } - inline void reset() noexcept { - memset(this, 0, sizeof(FuncFrame)); - _spRegId = BaseReg::kIdBad; - _saRegId = BaseReg::kIdBad; - _daOffset = kTagInvalidOffset; - } + //! \} + + //! \name Overloaded Operators + //! \{ + + //! Copy assignment - function frame is copy assignable. + ASMJIT_INLINE_NODEBUG FuncFrame& operator=(const FuncFrame& other) noexcept = default; //! \} @@ -1042,100 +1144,116 @@ public: //! \{ //! Returns the target architecture of the function frame. - inline Arch arch() const noexcept { return _arch; } + ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; } //! Returns function frame attributes, see `Attributes`. - inline FuncAttributes attributes() const noexcept { return _attributes; } + ASMJIT_INLINE_NODEBUG FuncAttributes attributes() const noexcept { return _attributes; } //! Checks whether the FuncFame contains an attribute `attr`. - inline bool hasAttribute(FuncAttributes attr) const noexcept { return Support::test(_attributes, attr); } + ASMJIT_INLINE_NODEBUG bool hasAttribute(FuncAttributes attr) const noexcept { return Support::test(_attributes, attr); } //! Adds attributes `attrs` to the FuncFrame. - inline void addAttributes(FuncAttributes attrs) noexcept { _attributes |= attrs; } + ASMJIT_INLINE_NODEBUG void addAttributes(FuncAttributes attrs) noexcept { _attributes |= attrs; } //! Clears attributes `attrs` from the FrameFrame. - inline void clearAttributes(FuncAttributes attrs) noexcept { _attributes &= ~attrs; } + ASMJIT_INLINE_NODEBUG void clearAttributes(FuncAttributes attrs) noexcept { _attributes &= ~attrs; } //! Tests whether the function has variable number of arguments. - inline bool hasVarArgs() const noexcept { return hasAttribute(FuncAttributes::kHasVarArgs); } + ASMJIT_INLINE_NODEBUG bool hasVarArgs() const noexcept { return hasAttribute(FuncAttributes::kHasVarArgs); } //! Sets the variable arguments flag. - inline void setVarArgs() noexcept { addAttributes(FuncAttributes::kHasVarArgs); } + ASMJIT_INLINE_NODEBUG void setVarArgs() noexcept { addAttributes(FuncAttributes::kHasVarArgs); } //! Resets variable arguments flag. - inline void resetVarArgs() noexcept { clearAttributes(FuncAttributes::kHasVarArgs); } + ASMJIT_INLINE_NODEBUG void resetVarArgs() noexcept { clearAttributes(FuncAttributes::kHasVarArgs); } //! Tests whether the function preserves frame pointer (EBP|ESP on X86). - inline bool hasPreservedFP() const noexcept { return hasAttribute(FuncAttributes::kHasPreservedFP); } + ASMJIT_INLINE_NODEBUG bool hasPreservedFP() const noexcept { return hasAttribute(FuncAttributes::kHasPreservedFP); } //! Enables preserved frame pointer. - inline void setPreservedFP() noexcept { addAttributes(FuncAttributes::kHasPreservedFP); } + ASMJIT_INLINE_NODEBUG void setPreservedFP() noexcept { addAttributes(FuncAttributes::kHasPreservedFP); } //! Disables preserved frame pointer. - inline void resetPreservedFP() noexcept { clearAttributes(FuncAttributes::kHasPreservedFP); } + ASMJIT_INLINE_NODEBUG void resetPreservedFP() noexcept { clearAttributes(FuncAttributes::kHasPreservedFP); } //! Tests whether the function calls other functions. - inline bool hasFuncCalls() const noexcept { return hasAttribute(FuncAttributes::kHasFuncCalls); } - //! Sets `kFlagHasCalls` to true. - inline void setFuncCalls() noexcept { addAttributes(FuncAttributes::kHasFuncCalls); } - //! Sets `kFlagHasCalls` to false. - inline void resetFuncCalls() noexcept { clearAttributes(FuncAttributes::kHasFuncCalls); } + ASMJIT_INLINE_NODEBUG bool hasFuncCalls() const noexcept { return hasAttribute(FuncAttributes::kHasFuncCalls); } + //! Sets `FuncAttributes::kHasFuncCalls` to true. + ASMJIT_INLINE_NODEBUG void setFuncCalls() noexcept { addAttributes(FuncAttributes::kHasFuncCalls); } + //! Sets `FuncAttributes::kHasFuncCalls` to false. + ASMJIT_INLINE_NODEBUG void resetFuncCalls() noexcept { clearAttributes(FuncAttributes::kHasFuncCalls); } + + //! Tests whether the function uses indirect branch protection, see \ref FuncAttributes::kIndirectBranchProtection. + ASMJIT_INLINE_NODEBUG bool hasIndirectBranchProtection() const noexcept { return hasAttribute(FuncAttributes::kIndirectBranchProtection); } + //! Enabled indirect branch protection (sets `FuncAttributes::kIndirectBranchProtection` attribute to true). + ASMJIT_INLINE_NODEBUG void setIndirectBranchProtection() noexcept { addAttributes(FuncAttributes::kIndirectBranchProtection); } + //! Disables indirect branch protection (sets `FuncAttributes::kIndirectBranchProtection` attribute to false). + ASMJIT_INLINE_NODEBUG void resetIndirectBranchProtection() noexcept { clearAttributes(FuncAttributes::kIndirectBranchProtection); } //! Tests whether the function has AVX enabled. - inline bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); } + ASMJIT_INLINE_NODEBUG bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); } //! Enables AVX use. - inline void setAvxEnabled() noexcept { addAttributes(FuncAttributes::kX86_AVXEnabled); } + ASMJIT_INLINE_NODEBUG void setAvxEnabled() noexcept { addAttributes(FuncAttributes::kX86_AVXEnabled); } //! Disables AVX use. - inline void resetAvxEnabled() noexcept { clearAttributes(FuncAttributes::kX86_AVXEnabled); } + ASMJIT_INLINE_NODEBUG void resetAvxEnabled() noexcept { clearAttributes(FuncAttributes::kX86_AVXEnabled); } //! Tests whether the function has AVX-512 enabled. - inline bool isAvx512Enabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVX512Enabled); } + ASMJIT_INLINE_NODEBUG bool isAvx512Enabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVX512Enabled); } //! Enables AVX-512 use. - inline void setAvx512Enabled() noexcept { addAttributes(FuncAttributes::kX86_AVX512Enabled); } + ASMJIT_INLINE_NODEBUG void setAvx512Enabled() noexcept { addAttributes(FuncAttributes::kX86_AVX512Enabled); } //! Disables AVX-512 use. - inline void resetAvx512Enabled() noexcept { clearAttributes(FuncAttributes::kX86_AVX512Enabled); } + ASMJIT_INLINE_NODEBUG void resetAvx512Enabled() noexcept { clearAttributes(FuncAttributes::kX86_AVX512Enabled); } //! Tests whether the function has MMX cleanup - 'emms' instruction in epilog. - inline bool hasMmxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_MMXCleanup); } + ASMJIT_INLINE_NODEBUG bool hasMmxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_MMXCleanup); } //! Enables MMX cleanup. - inline void setMmxCleanup() noexcept { addAttributes(FuncAttributes::kX86_MMXCleanup); } + ASMJIT_INLINE_NODEBUG void setMmxCleanup() noexcept { addAttributes(FuncAttributes::kX86_MMXCleanup); } //! Disables MMX cleanup. - inline void resetMmxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_MMXCleanup); } + ASMJIT_INLINE_NODEBUG void resetMmxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_MMXCleanup); } //! Tests whether the function has AVX cleanup - 'vzeroupper' instruction in epilog. - inline bool hasAvxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXCleanup); } + ASMJIT_INLINE_NODEBUG bool hasAvxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXCleanup); } //! Enables AVX cleanup. - inline void setAvxCleanup() noexcept { addAttributes(FuncAttributes::kX86_AVXCleanup); } + ASMJIT_INLINE_NODEBUG void setAvxCleanup() noexcept { addAttributes(FuncAttributes::kX86_AVXCleanup); } //! Disables AVX cleanup. - inline void resetAvxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_AVXCleanup); } + ASMJIT_INLINE_NODEBUG void resetAvxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_AVXCleanup); } //! Tests whether the function uses call stack. - inline bool hasCallStack() const noexcept { return _callStackSize != 0; } + ASMJIT_INLINE_NODEBUG bool hasCallStack() const noexcept { return _callStackSize != 0; } //! Tests whether the function uses local stack. - inline bool hasLocalStack() const noexcept { return _localStackSize != 0; } + ASMJIT_INLINE_NODEBUG bool hasLocalStack() const noexcept { return _localStackSize != 0; } //! Tests whether vector registers can be saved and restored by using aligned reads and writes. - inline bool hasAlignedVecSR() const noexcept { return hasAttribute(FuncAttributes::kAlignedVecSR); } + ASMJIT_INLINE_NODEBUG bool hasAlignedVecSR() const noexcept { return hasAttribute(FuncAttributes::kAlignedVecSR); } //! Tests whether the function has to align stack dynamically. - inline bool hasDynamicAlignment() const noexcept { return _finalStackAlignment >= _minDynamicAlignment; } + ASMJIT_INLINE_NODEBUG bool hasDynamicAlignment() const noexcept { return _finalStackAlignment >= _minDynamicAlignment; } //! Tests whether the calling convention specifies 'RedZone'. - inline bool hasRedZone() const noexcept { return _redZoneSize != 0; } + ASMJIT_INLINE_NODEBUG bool hasRedZone() const noexcept { return _redZoneSize != 0; } //! Tests whether the calling convention specifies 'SpillZone'. - inline bool hasSpillZone() const noexcept { return _spillZoneSize != 0; } + ASMJIT_INLINE_NODEBUG bool hasSpillZone() const noexcept { return _spillZoneSize != 0; } //! Returns the size of 'RedZone'. - inline uint32_t redZoneSize() const noexcept { return _redZoneSize; } + ASMJIT_INLINE_NODEBUG uint32_t redZoneSize() const noexcept { return _redZoneSize; } //! Returns the size of 'SpillZone'. - inline uint32_t spillZoneSize() const noexcept { return _spillZoneSize; } + ASMJIT_INLINE_NODEBUG uint32_t spillZoneSize() const noexcept { return _spillZoneSize; } + + //! Resets the size of red zone, which would disable it entirely. + //! + //! \note Red zone is currently only used by an AMD64 SystemV calling convention, which expects 128 + //! bytes of stack to be accessible below stack pointer. These bytes are then accessible within the + //! function and Compiler can use this space as a spill area. However, sometimes it's better to + //! disallow the use of red zone in case that a user wants to use this stack for a custom purpose. + ASMJIT_INLINE_NODEBUG void resetRedZone() noexcept { _redZoneSize = 0; } + //! Returns natural stack alignment (guaranteed stack alignment upon entry). - inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } + ASMJIT_INLINE_NODEBUG uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } //! Returns natural stack alignment (guaranteed stack alignment upon entry). - inline uint32_t minDynamicAlignment() const noexcept { return _minDynamicAlignment; } + ASMJIT_INLINE_NODEBUG uint32_t minDynamicAlignment() const noexcept { return _minDynamicAlignment; } //! Tests whether the callee must adjust SP before returning (X86-STDCALL only) - inline bool hasCalleeStackCleanup() const noexcept { return _calleeStackCleanup != 0; } + ASMJIT_INLINE_NODEBUG bool hasCalleeStackCleanup() const noexcept { return _calleeStackCleanup != 0; } //! Returns home many bytes of the stack the callee must adjust before returning (X86-STDCALL only) - inline uint32_t calleeStackCleanup() const noexcept { return _calleeStackCleanup; } + ASMJIT_INLINE_NODEBUG uint32_t calleeStackCleanup() const noexcept { return _calleeStackCleanup; } //! Returns call stack alignment. - inline uint32_t callStackAlignment() const noexcept { return _callStackAlignment; } + ASMJIT_INLINE_NODEBUG uint32_t callStackAlignment() const noexcept { return _callStackAlignment; } //! Returns local stack alignment. - inline uint32_t localStackAlignment() const noexcept { return _localStackAlignment; } + ASMJIT_INLINE_NODEBUG uint32_t localStackAlignment() const noexcept { return _localStackAlignment; } //! Returns final stack alignment (the maximum value of call, local, and natural stack alignments). - inline uint32_t finalStackAlignment() const noexcept { return _finalStackAlignment; } + ASMJIT_INLINE_NODEBUG uint32_t finalStackAlignment() const noexcept { return _finalStackAlignment; } //! Sets call stack alignment. //! @@ -1170,38 +1288,38 @@ public: } //! Returns call stack size. - inline uint32_t callStackSize() const noexcept { return _callStackSize; } + ASMJIT_INLINE_NODEBUG uint32_t callStackSize() const noexcept { return _callStackSize; } //! Returns local stack size. - inline uint32_t localStackSize() const noexcept { return _localStackSize; } + ASMJIT_INLINE_NODEBUG uint32_t localStackSize() const noexcept { return _localStackSize; } //! Sets call stack size. - inline void setCallStackSize(uint32_t size) noexcept { _callStackSize = size; } + ASMJIT_INLINE_NODEBUG void setCallStackSize(uint32_t size) noexcept { _callStackSize = size; } //! Sets local stack size. - inline void setLocalStackSize(uint32_t size) noexcept { _localStackSize = size; } + ASMJIT_INLINE_NODEBUG void setLocalStackSize(uint32_t size) noexcept { _localStackSize = size; } //! Combines call stack size with `size`, updating it to the greater value. - inline void updateCallStackSize(uint32_t size) noexcept { _callStackSize = Support::max(_callStackSize, size); } + ASMJIT_INLINE_NODEBUG void updateCallStackSize(uint32_t size) noexcept { _callStackSize = Support::max(_callStackSize, size); } //! Combines local stack size with `size`, updating it to the greater value. - inline void updateLocalStackSize(uint32_t size) noexcept { _localStackSize = Support::max(_localStackSize, size); } + ASMJIT_INLINE_NODEBUG void updateLocalStackSize(uint32_t size) noexcept { _localStackSize = Support::max(_localStackSize, size); } //! Returns final stack size (only valid after the FuncFrame is finalized). - inline uint32_t finalStackSize() const noexcept { return _finalStackSize; } + ASMJIT_INLINE_NODEBUG uint32_t finalStackSize() const noexcept { return _finalStackSize; } //! Returns an offset to access the local stack (non-zero only if call stack is used). - inline uint32_t localStackOffset() const noexcept { return _localStackOffset; } + ASMJIT_INLINE_NODEBUG uint32_t localStackOffset() const noexcept { return _localStackOffset; } //! Tests whether the function prolog/epilog requires a memory slot for storing unaligned SP. - inline bool hasDAOffset() const noexcept { return _daOffset != kTagInvalidOffset; } + ASMJIT_INLINE_NODEBUG bool hasDAOffset() const noexcept { return _daOffset != kTagInvalidOffset; } //! Returns a memory offset used to store DA (dynamic alignment) slot (relative to SP). - inline uint32_t daOffset() const noexcept { return _daOffset; } + ASMJIT_INLINE_NODEBUG uint32_t daOffset() const noexcept { return _daOffset; } - inline uint32_t saOffset(uint32_t regId) const noexcept { + ASMJIT_INLINE_NODEBUG uint32_t saOffset(uint32_t regId) const noexcept { return regId == _spRegId ? saOffsetFromSP() : saOffsetFromSA(); } - inline uint32_t saOffsetFromSP() const noexcept { return _saOffsetFromSP; } - inline uint32_t saOffsetFromSA() const noexcept { return _saOffsetFromSA; } + ASMJIT_INLINE_NODEBUG uint32_t saOffsetFromSP() const noexcept { return _saOffsetFromSP; } + ASMJIT_INLINE_NODEBUG uint32_t saOffsetFromSA() const noexcept { return _saOffsetFromSA; } //! Returns mask of registers of the given register `group` that are modified by the function. The engine would //! then calculate which registers must be saved & restored by the function by using the data provided by the @@ -1239,11 +1357,16 @@ public: addDirtyRegs(std::forward<Args>(args)...); } - inline void setAllDirty() noexcept { + //! A helper function to set all registers from all register groups dirty. + //! + //! \note This should not be used in general as it's the most pessimistic case. However, it can be used for testing + //! or in cases in which all registers are considered clobbered. + ASMJIT_INLINE_NODEBUG void setAllDirty() noexcept { for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_dirtyRegs); i++) _dirtyRegs[i] = 0xFFFFFFFFu; } + //! A helper function to set all registers from the given register `group` dirty. inline void setAllDirty(RegGroup group) noexcept { ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); _dirtyRegs[group] = 0xFFFFFFFFu; @@ -1260,12 +1383,13 @@ public: //! Returns the mask of preserved registers of the given register `group`. //! //! Preserved registers are those that must survive the function call unmodified. The function can only modify - //! preserved registers it they are saved and restored in funciton's prolog and epilog, respectively. + //! preserved registers it they are saved and restored in function's prolog and epilog, respectively. inline RegMask preservedRegs(RegGroup group) const noexcept { ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _preservedRegs[group]; } + //! Returns the size of a save-restore are for the required register `group`. inline uint32_t saveRestoreRegSize(RegGroup group) const noexcept { ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _saveRestoreRegSize[group]; @@ -1276,35 +1400,35 @@ public: return _saveRestoreAlignment[group]; } - inline bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } - inline uint32_t saRegId() const noexcept { return _saRegId; } - inline void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } - inline void resetSARegId() { setSARegId(BaseReg::kIdBad); } + ASMJIT_INLINE_NODEBUG bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG uint32_t saRegId() const noexcept { return _saRegId; } + ASMJIT_INLINE_NODEBUG void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } + ASMJIT_INLINE_NODEBUG void resetSARegId() { setSARegId(BaseReg::kIdBad); } //! Returns stack size required to save/restore registers via push/pop. - inline uint32_t pushPopSaveSize() const noexcept { return _pushPopSaveSize; } + ASMJIT_INLINE_NODEBUG uint32_t pushPopSaveSize() const noexcept { return _pushPopSaveSize; } //! Returns an offset to the stack where registers are saved via push/pop. - inline uint32_t pushPopSaveOffset() const noexcept { return _pushPopSaveOffset; } + ASMJIT_INLINE_NODEBUG uint32_t pushPopSaveOffset() const noexcept { return _pushPopSaveOffset; } //! Returns stack size required to save/restore extra registers that don't use push/pop/ //! //! \note On X86 this covers all registers except GP registers, on other architectures it can be always //! zero (for example AArch64 saves all registers via push/pop like instructions, so this would be zero). - inline uint32_t extraRegSaveSize() const noexcept { return _extraRegSaveSize; } + ASMJIT_INLINE_NODEBUG uint32_t extraRegSaveSize() const noexcept { return _extraRegSaveSize; } //! Returns an offset to the stack where extra registers are saved. - inline uint32_t extraRegSaveOffset() const noexcept { return _extraRegSaveOffset; } + ASMJIT_INLINE_NODEBUG uint32_t extraRegSaveOffset() const noexcept { return _extraRegSaveOffset; } //! Tests whether the functions contains stack adjustment. - inline bool hasStackAdjustment() const noexcept { return _stackAdjustment != 0; } + ASMJIT_INLINE_NODEBUG bool hasStackAdjustment() const noexcept { return _stackAdjustment != 0; } //! Returns function's stack adjustment used in function's prolog and epilog. //! //! If the returned value is zero it means that the stack is not adjusted. This can mean both that the stack //! is not used and/or the stack is only adjusted by instructions that pust/pop registers into/from stack. - inline uint32_t stackAdjustment() const noexcept { return _stackAdjustment; } + ASMJIT_INLINE_NODEBUG uint32_t stackAdjustment() const noexcept { return _stackAdjustment; } //! \} - //! \name Finaliztion + //! \name Finalization //! \{ ASMJIT_API Error finalize() noexcept; @@ -1320,25 +1444,27 @@ public: //! \{ //! Function detail. - const FuncDetail* _funcDetail; + const FuncDetail* _funcDetail {}; //! Register that can be used to access arguments passed by stack. - uint8_t _saRegId; + uint8_t _saRegId = uint8_t(BaseReg::kIdBad); //! Reserved for future use. - uint8_t _reserved[3]; + uint8_t _reserved[3] {}; //! Mapping of each function argument. - FuncValuePack _argPacks[Globals::kMaxFuncArgs]; + FuncValuePack _argPacks[Globals::kMaxFuncArgs] {}; //! \} //! \name Construction & Destruction //! \{ - inline explicit FuncArgsAssignment(const FuncDetail* fd = nullptr) noexcept { reset(fd); } + //! Creates either a default initialized `FuncArgsAssignment` or to assignment that links to `fd`, if non-null. + ASMJIT_INLINE_NODEBUG explicit FuncArgsAssignment(const FuncDetail* fd = nullptr) noexcept { reset(fd); } - inline FuncArgsAssignment(const FuncArgsAssignment& other) noexcept { - memcpy(this, &other, sizeof(*this)); - } + //! Copy constructor. + ASMJIT_INLINE_NODEBUG FuncArgsAssignment(const FuncArgsAssignment& other) noexcept = default; + //! Resets this `FuncArgsAssignment` to either default constructed state or to assignment that links to `fd`, + //! if non-null. inline void reset(const FuncDetail* fd = nullptr) noexcept { _funcDetail = fd; _saRegId = uint8_t(BaseReg::kIdBad); @@ -1348,58 +1474,80 @@ public: //! \} + //! \name Overloaded Operators + //! \{ + + //! Copy assignment. + ASMJIT_INLINE_NODEBUG FuncArgsAssignment& operator=(const FuncArgsAssignment& other) noexcept = default; + + //! \} + //! \name Accessors //! \{ - inline const FuncDetail* funcDetail() const noexcept { return _funcDetail; } - inline void setFuncDetail(const FuncDetail* fd) noexcept { _funcDetail = fd; } + //! Returns the associated \ref FuncDetail of this `FuncArgsAssignment`. + ASMJIT_INLINE_NODEBUG const FuncDetail* funcDetail() const noexcept { return _funcDetail; } + //! Associates \ref FuncDetails with this `FuncArgsAssignment`. + ASMJIT_INLINE_NODEBUG void setFuncDetail(const FuncDetail* fd) noexcept { _funcDetail = fd; } - inline bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } - inline uint32_t saRegId() const noexcept { return _saRegId; } - inline void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } - inline void resetSARegId() { _saRegId = uint8_t(BaseReg::kIdBad); } + ASMJIT_INLINE_NODEBUG bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG uint32_t saRegId() const noexcept { return _saRegId; } + ASMJIT_INLINE_NODEBUG void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } + ASMJIT_INLINE_NODEBUG void resetSARegId() { _saRegId = uint8_t(BaseReg::kIdBad); } + //! Returns assigned argument at `argIndex` and `valueIndex`. + //! + //! \note `argIndex` refers to he function argument and `valueIndex` refers to a value pack (in case multiple + //! values are passed as a single argument). inline FuncValue& arg(size_t argIndex, size_t valueIndex) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); return _argPacks[argIndex][valueIndex]; } + //! \overload inline const FuncValue& arg(size_t argIndex, size_t valueIndex) const noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); return _argPacks[argIndex][valueIndex]; } + //! Tests whether argument at `argIndex` and `valueIndex` has been assigned. inline bool isAssigned(size_t argIndex, size_t valueIndex) const noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); return _argPacks[argIndex][valueIndex].isAssigned(); } + //! Assigns register at `argIndex` and value index of 0 to `reg` and an optional `typeId`. inline void assignReg(size_t argIndex, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); ASMJIT_ASSERT(reg.isPhysReg()); _argPacks[argIndex][0].initReg(reg.type(), reg.id(), typeId); } + //! Assigns register at `argIndex` and value index of 0 to `regType`, `regId`, and an optional `typeId`. inline void assignReg(size_t argIndex, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][0].initReg(regType, regId, typeId); } + //! Assigns stack at `argIndex` and value index of 0 to `offset` and an optional `typeId`. inline void assignStack(size_t argIndex, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][0].initStack(offset, typeId); } + //! Assigns register at `argIndex` and `valueIndex` to `reg` and an optional `typeId`. inline void assignRegInPack(size_t argIndex, size_t valueIndex, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); ASMJIT_ASSERT(reg.isPhysReg()); _argPacks[argIndex][valueIndex].initReg(reg.type(), reg.id(), typeId); } + //! Assigns register at `argIndex` and `valueIndex` to `regType`, `regId`, and an optional `typeId`. inline void assignRegInPack(size_t argIndex, size_t valueIndex, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][valueIndex].initReg(regType, regId, typeId); } + //! Assigns stack at `argIndex` and `valueIndex` to `offset` and an optional `typeId`. inline void assignStackInPack(size_t argIndex, size_t valueIndex, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][valueIndex].initStack(offset, typeId); @@ -1418,6 +1566,9 @@ public: _assignAllInternal(argIndex + 1, std::forward<Args>(args)...); } + //! Assigns all argument at once. + //! + //! \note This function can be only used if the arguments don't contain value packs (multiple values per argument). template<typename... Args> inline void assignAll(Args&&... args) noexcept { _assignAllInternal(0, std::forward<Args>(args)...); @@ -1430,8 +1581,8 @@ public: //! Update `FuncFrame` based on function's arguments assignment. //! - //! \note You MUST call this in orher to use `BaseEmitter::emitArgsAssignment()`, otherwise the FuncFrame would - //! not contain the information necessary to assign all arguments into the registers and/or stack specified. + //! \note This function must be called in order to use `BaseEmitter::emitArgsAssignment()`, otherwise the \ref FuncFrame + //! would not contain the information necessary to assign all arguments into the registers and/or stack specified. ASMJIT_API Error updateFuncFrame(FuncFrame& frame) const noexcept; //! \} @@ -1442,4 +1593,3 @@ public: ASMJIT_END_NAMESPACE #endif // ASMJIT_CORE_FUNC_H_INCLUDED - diff --git a/3rdparty/asmjit/src/asmjit/core/funcargscontext.cpp b/3rdparty/asmjit/src/asmjit/core/funcargscontext.cpp index 1db50a7082a..a6580874089 100644 --- a/3rdparty/asmjit/src/asmjit/core/funcargscontext.cpp +++ b/3rdparty/asmjit/src/asmjit/core/funcargscontext.cpp @@ -102,9 +102,23 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co ASMJIT_ASSERT(dstWd != nullptr); dstWd->assign(varId, srcId); - // The best case, register is allocated where it is expected to be. - if (dstId == srcId) - var.markDone(); + // The best case, register is allocated where it is expected to be. However, we should + // not mark this as done if both registers are GP and sign or zero extension is required. + if (dstId == srcId) { + if (dstGroup != RegGroup::kGp) { + var.markDone(); + } + else { + TypeId dt = dst.typeId(); + TypeId st = src.typeId(); + + uint32_t dstSize = TypeUtils::sizeOf(dt); + uint32_t srcSize = TypeUtils::sizeOf(st); + + if (dt == TypeId::kVoid || st == TypeId::kVoid || dstSize <= srcSize) + var.markDone(); + } + } } else { if (ASMJIT_UNLIKELY(srcGroup > RegGroup::kMaxVirt)) diff --git a/3rdparty/asmjit/src/asmjit/core/funcargscontext_p.h b/3rdparty/asmjit/src/asmjit/core/funcargscontext_p.h index 72ee10585a4..a8ad6b47dcd 100644 --- a/3rdparty/asmjit/src/asmjit/core/funcargscontext_p.h +++ b/3rdparty/asmjit/src/asmjit/core/funcargscontext_p.h @@ -176,14 +176,14 @@ public: FuncArgsContext() noexcept; - inline const ArchTraits& archTraits() const noexcept { return *_archTraits; } - inline Arch arch() const noexcept { return _arch; } + ASMJIT_INLINE_NODEBUG const ArchTraits& archTraits() const noexcept { return *_archTraits; } + ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; } - inline uint32_t varCount() const noexcept { return _varCount; } - inline size_t indexOf(const Var* var) const noexcept { return (size_t)(var - _vars); } + ASMJIT_INLINE_NODEBUG uint32_t varCount() const noexcept { return _varCount; } + ASMJIT_INLINE_NODEBUG size_t indexOf(const Var* var) const noexcept { return (size_t)(var - _vars); } - inline Var& var(size_t varId) noexcept { return _vars[varId]; } - inline const Var& var(size_t varId) const noexcept { return _vars[varId]; } + ASMJIT_INLINE_NODEBUG Var& var(size_t varId) noexcept { return _vars[varId]; } + ASMJIT_INLINE_NODEBUG const Var& var(size_t varId) const noexcept { return _vars[varId]; } Error initWorkData(const FuncFrame& frame, const FuncArgsAssignment& args, const RAConstraints* constraints) noexcept; Error markScratchRegs(FuncFrame& frame) noexcept; diff --git a/3rdparty/asmjit/src/asmjit/core/globals.cpp b/3rdparty/asmjit/src/asmjit/core/globals.cpp index 2bbd0c0577d..4a98431b6d5 100644 --- a/3rdparty/asmjit/src/asmjit/core/globals.cpp +++ b/3rdparty/asmjit/src/asmjit/core/globals.cpp @@ -86,6 +86,8 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { "ExpressionLabelNotBound\0" "ExpressionOverflow\0" "FailedToOpenAnonymousMemory\0" + "FailedToOpenFile\0" + "ProtectionFailure\0" "<Unknown>\0"; static const uint16_t sErrorIndex[] = { @@ -93,7 +95,7 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { 247, 264, 283, 298, 314, 333, 352, 370, 392, 410, 429, 444, 460, 474, 488, 508, 533, 551, 573, 595, 612, 629, 645, 661, 677, 694, 709, 724, 744, 764, 784, 817, 837, 852, 869, 888, 909, 929, 943, 964, 978, 996, 1012, 1028, 1047, - 1073, 1088, 1104, 1119, 1134, 1164, 1188, 1207, 1235 + 1073, 1088, 1104, 1119, 1134, 1164, 1188, 1207, 1235, 1252, 1270 }; // @EnumStringEnd@ diff --git a/3rdparty/asmjit/src/asmjit/core/globals.h b/3rdparty/asmjit/src/asmjit/core/globals.h index f2d3c6e63df..db921cfc6e1 100644 --- a/3rdparty/asmjit/src/asmjit/core/globals.h +++ b/3rdparty/asmjit/src/asmjit/core/globals.h @@ -14,9 +14,14 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_utilities //! \{ namespace Support { - //! Cast designed to cast between function and void* pointers. - template<typename Dst, typename Src> - static inline Dst ptr_cast_impl(Src p) noexcept { return (Dst)p; } + +//! Cast designed to cast between function and void* pointers. +template<typename Dst, typename Src> +static inline Dst ptr_cast_impl(Src p) noexcept { return (Dst)p; } + +//! Helper to implement placement new/delete without relying on `<new>` header. +struct PlacementNew { void* ptr; }; + } // {Support} #if defined(ASMJIT_NO_STDCXX) @@ -25,17 +30,15 @@ namespace Support { ASMJIT_FORCE_INLINE void operatorDelete(void* p) noexcept { if (p) free(p); } } // {Support} -#define ASMJIT_BASE_CLASS(TYPE) \ - ASMJIT_FORCE_INLINE void* operator new(size_t n) noexcept { \ - return Support::operatorNew(n); \ - } \ - \ - ASMJIT_FORCE_INLINE void operator delete(void* p) noexcept { \ - Support::operatorDelete(p); \ - } \ - \ - ASMJIT_FORCE_INLINE void* operator new(size_t, void* p) noexcept { return p; } \ - ASMJIT_FORCE_INLINE void operator delete(void*, void*) noexcept {} +#define ASMJIT_BASE_CLASS(TYPE) \ + ASMJIT_FORCE_INLINE void* operator new(size_t n) noexcept { return Support::operatorNew(n); } \ + ASMJIT_FORCE_INLINE void operator delete(void* ptr) noexcept { Support::operatorDelete(ptr); } \ + \ + ASMJIT_FORCE_INLINE void* operator new(size_t, void* ptr) noexcept { return ptr; } \ + ASMJIT_FORCE_INLINE void operator delete(void*, void*) noexcept {} \ + \ + ASMJIT_FORCE_INLINE void* operator new(size_t, Support::PlacementNew ptr) noexcept { return ptr.ptr; } \ + ASMJIT_FORCE_INLINE void operator delete(void*, Support::PlacementNew) noexcept {} #else #define ASMJIT_BASE_CLASS(TYPE) #endif @@ -93,10 +96,9 @@ static constexpr uint32_t kMaxTreeHeight = (ASMJIT_ARCH_BITS == 32 ? 30 : 61) + static constexpr uint32_t kMaxOpCount = 6; //! Maximum arguments of a function supported by the Compiler / Function API. -static constexpr uint32_t kMaxFuncArgs = 16; +static constexpr uint32_t kMaxFuncArgs = 32; -//! The number of values that can be assigned to a single function argument or -//! return value. +//! The number of values that can be assigned to a single function argument or return value. static constexpr uint32_t kMaxValuePack = 4; //! Maximum number of physical registers AsmJit can use per register group. @@ -129,16 +131,20 @@ static constexpr uint32_t kNumVirtGroups = 4; struct Init_ {}; struct NoInit_ {}; +//! A decorator used to initialize. static const constexpr Init_ Init {}; +//! A decorator used to not initialize. static const constexpr NoInit_ NoInit {}; } // {Globals} +//! Casts a `void*` pointer `func` to a function pointer `Func`. template<typename Func> -static inline Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl<Func, void*>(func); } +static ASMJIT_INLINE_NODEBUG Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl<Func, void*>(func); } +//! Casts a function pointer `func` to a void pointer `void*`. template<typename Func> -static inline void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_impl<void*, Func>(func); } +static ASMJIT_INLINE_NODEBUG void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_impl<void*, Func>(func); } //! \} @@ -175,7 +181,10 @@ enum ErrorCode : uint32_t { //! The object is already initialized. kErrorAlreadyInitialized, - //! Built-in feature was disabled at compile time and it's not available. + //! Either a built-in feature was disabled at compile time and it's not available or the feature is not + //! available on the target platform. + //! + //! For example trying to allocate large pages on unsupported platform would return this error. kErrorFeatureNotEnabled, //! Too many handles (Windows) or file descriptors (Unix/Posix). @@ -320,6 +329,15 @@ enum ErrorCode : uint32_t { //! Failed to open anonymous memory handle or file descriptor. kErrorFailedToOpenAnonymousMemory, + //! Failed to open a file. + //! + //! \note This is a generic error that is used by internal filesystem API. + kErrorFailedToOpenFile, + + //! Protection failure can be returned from a virtual memory allocator or when trying to change memory access + //! permissions. + kErrorProtectionFailure, + // @EnumValuesEnd@ //! Count of AsmJit error codes. @@ -332,7 +350,7 @@ namespace DebugUtils { //! \cond INTERNAL //! Used to silence warnings about unused arguments or variables. template<typename... Args> -static inline void unused(Args&&...) noexcept {} +static ASMJIT_INLINE_NODEBUG void unused(Args&&...) noexcept {} //! \endcond //! Returns the error `err` passed. @@ -390,4 +408,14 @@ ASMJIT_API void ASMJIT_NORETURN assertionFailed(const char* file, int line, cons ASMJIT_END_NAMESPACE +//! Implementation of a placement new so we don't have to depend on `<new>`. +ASMJIT_INLINE_NODEBUG void* operator new(size_t, const asmjit::Support::PlacementNew& p) noexcept { +#if defined(_MSC_VER) && !defined(__clang__) + __assume(p.ptr != nullptr); // Otherwise MSVC would emit a nullptr check. +#endif + return p.ptr; +} + +ASMJIT_INLINE_NODEBUG void operator delete(void*, const asmjit::Support::PlacementNew&) noexcept {} + #endif // ASMJIT_CORE_GLOBALS_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/core/inst.cpp b/3rdparty/asmjit/src/asmjit/core/inst.cpp index 8f29d8b7585..ade4ae001f2 100644 --- a/3rdparty/asmjit/src/asmjit/core/inst.cpp +++ b/3rdparty/asmjit/src/asmjit/core/inst.cpp @@ -24,12 +24,12 @@ ASMJIT_BEGIN_NAMESPACE Error InstAPI::instIdToString(Arch arch, InstId instId, String& output) noexcept { #if !defined(ASMJIT_NO_X86) if (Environment::isFamilyX86(arch)) - return x86::InstInternal::instIdToString(arch, instId, output); + return x86::InstInternal::instIdToString(instId, output); #endif #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::instIdToString(arch, instId, output); + return a64::InstInternal::instIdToString(instId, output); #endif return DebugUtils::errored(kErrorInvalidArch); @@ -38,12 +38,12 @@ Error InstAPI::instIdToString(Arch arch, InstId instId, String& output) noexcept InstId InstAPI::stringToInstId(Arch arch, const char* s, size_t len) noexcept { #if !defined(ASMJIT_NO_X86) if (Environment::isFamilyX86(arch)) - return x86::InstInternal::stringToInstId(arch, s, len); + return x86::InstInternal::stringToInstId(s, len); #endif #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::stringToInstId(arch, s, len); + return a64::InstInternal::stringToInstId(s, len); #endif return 0; @@ -56,13 +56,17 @@ InstId InstAPI::stringToInstId(Arch arch, const char* s, size_t len) noexcept { #ifndef ASMJIT_NO_VALIDATION Error InstAPI::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { #if !defined(ASMJIT_NO_X86) - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::validate(arch, inst, operands, opCount, validationFlags); + if (Environment::isFamilyX86(arch)) { + if (arch == Arch::kX86) + return x86::InstInternal::validateX86(inst, operands, opCount, validationFlags); + else + return x86::InstInternal::validateX64(inst, operands, opCount, validationFlags); + } #endif #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::validate(arch, inst, operands, opCount, validationFlags); + return a64::InstInternal::validate(inst, operands, opCount, validationFlags); #endif return DebugUtils::errored(kErrorInvalidArch); @@ -84,7 +88,7 @@ Error InstAPI::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* oper #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::queryRWInfo(arch, inst, operands, opCount, out); + return a64::InstInternal::queryRWInfo(inst, operands, opCount, out); #endif return DebugUtils::errored(kErrorInvalidArch); @@ -103,7 +107,7 @@ Error InstAPI::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* op #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::queryFeatures(arch, inst, operands, opCount, out); + return a64::InstInternal::queryFeatures(inst, operands, opCount, out); #endif return DebugUtils::errored(kErrorInvalidArch); diff --git a/3rdparty/asmjit/src/asmjit/core/inst.h b/3rdparty/asmjit/src/asmjit/core/inst.h index 643678971a7..a653fe8e4cc 100644 --- a/3rdparty/asmjit/src/asmjit/core/inst.h +++ b/3rdparty/asmjit/src/asmjit/core/inst.h @@ -20,7 +20,7 @@ ASMJIT_BEGIN_NAMESPACE //! //! Each architecture has a set of valid instructions indexed from 0. Instruction with 0 id is, however, a special //! instruction that describes a "no instruction" or "invalid instruction". Different architectures can assign a. -//! different instruction to the same id, each architecture typicall has its own instructions indexed from 1. +//! different instruction to the same id, each architecture typically has its own instructions indexed from 1. //! //! Instruction identifiers listed by architecture: //! @@ -189,7 +189,7 @@ enum class InstControlFlow : uint32_t { //! Hint that is used when both input operands to the instruction are the same. //! -//! Provides hints to the instrution RW query regarding special cases in which two or more operands are the same +//! Provides hints to the instruction RW query regarding special cases in which two or more operands are the same //! registers. This is required by instructions such as XOR, AND, OR, SUB, etc... These hints will influence the //! RW operations query. enum class InstSameRegHint : uint8_t { @@ -231,17 +231,17 @@ public: //! //! Default values of `id` and `options` are zero, which means 'none' instruction. Such instruction is guaranteed //! to never exist for any architecture supported by AsmJit. - inline explicit BaseInst(InstId instId = 0, InstOptions options = InstOptions::kNone) noexcept + ASMJIT_INLINE_NODEBUG explicit BaseInst(InstId instId = 0, InstOptions options = InstOptions::kNone) noexcept : _id(instId), _options(options), _extraReg() {} - inline BaseInst(InstId instId, InstOptions options, const RegOnly& extraReg) noexcept + ASMJIT_INLINE_NODEBUG BaseInst(InstId instId, InstOptions options, const RegOnly& extraReg) noexcept : _id(instId), _options(options), _extraReg(extraReg) {} - inline BaseInst(InstId instId, InstOptions options, const BaseReg& extraReg) noexcept + ASMJIT_INLINE_NODEBUG BaseInst(InstId instId, InstOptions options, const BaseReg& extraReg) noexcept : _id(instId), _options(options), _extraReg { extraReg.signature(), extraReg.id() } {} @@ -252,22 +252,22 @@ public: //! \{ //! Returns the instruction id with modifiers. - inline InstId id() const noexcept { return _id; } + ASMJIT_INLINE_NODEBUG InstId id() const noexcept { return _id; } //! Sets the instruction id and modiiers from `id`. - inline void setId(InstId id) noexcept { _id = id; } + ASMJIT_INLINE_NODEBUG void setId(InstId id) noexcept { _id = id; } //! Resets the instruction id and modifiers to zero, see \ref kIdNone. - inline void resetId() noexcept { _id = 0; } + ASMJIT_INLINE_NODEBUG void resetId() noexcept { _id = 0; } //! Returns a real instruction id that doesn't contain any modifiers. - inline InstId realId() const noexcept { return _id & uint32_t(InstIdParts::kRealId); } + ASMJIT_INLINE_NODEBUG InstId realId() const noexcept { return _id & uint32_t(InstIdParts::kRealId); } template<InstIdParts kPart> - inline uint32_t getInstIdPart() const noexcept { + ASMJIT_INLINE_NODEBUG uint32_t getInstIdPart() const noexcept { return (uint32_t(_id) & uint32_t(kPart)) >> Support::ConstCTZ<uint32_t(kPart)>::value; } template<InstIdParts kPart> - inline void setInstIdPart(uint32_t value) noexcept { + ASMJIT_INLINE_NODEBUG void setInstIdPart(uint32_t value) noexcept { _id = (_id & ~uint32_t(kPart)) | (value << Support::ConstCTZ<uint32_t(kPart)>::value); } @@ -276,47 +276,61 @@ public: //! \name Instruction Options //! \{ - inline InstOptions options() const noexcept { return _options; } - inline bool hasOption(InstOptions option) const noexcept { return Support::test(_options, option); } - inline void setOptions(InstOptions options) noexcept { _options = options; } - inline void addOptions(InstOptions options) noexcept { _options |= options; } - inline void clearOptions(InstOptions options) noexcept { _options &= ~options; } - inline void resetOptions() noexcept { _options = InstOptions::kNone; } + ASMJIT_INLINE_NODEBUG InstOptions options() const noexcept { return _options; } + ASMJIT_INLINE_NODEBUG bool hasOption(InstOptions option) const noexcept { return Support::test(_options, option); } + ASMJIT_INLINE_NODEBUG void setOptions(InstOptions options) noexcept { _options = options; } + ASMJIT_INLINE_NODEBUG void addOptions(InstOptions options) noexcept { _options |= options; } + ASMJIT_INLINE_NODEBUG void clearOptions(InstOptions options) noexcept { _options &= ~options; } + ASMJIT_INLINE_NODEBUG void resetOptions() noexcept { _options = InstOptions::kNone; } //! \} //! \name Extra Register //! \{ - inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); } - inline RegOnly& extraReg() noexcept { return _extraReg; } - inline const RegOnly& extraReg() const noexcept { return _extraReg; } - inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); } - inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); } - inline void resetExtraReg() noexcept { _extraReg.reset(); } + ASMJIT_INLINE_NODEBUG bool hasExtraReg() const noexcept { return _extraReg.isReg(); } + ASMJIT_INLINE_NODEBUG RegOnly& extraReg() noexcept { return _extraReg; } + ASMJIT_INLINE_NODEBUG const RegOnly& extraReg() const noexcept { return _extraReg; } + ASMJIT_INLINE_NODEBUG void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); } + ASMJIT_INLINE_NODEBUG void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); } + ASMJIT_INLINE_NODEBUG void resetExtraReg() noexcept { _extraReg.reset(); } //! \} //! \name ARM Specific //! \{ - inline arm::CondCode armCondCode() const noexcept { return (arm::CondCode)getInstIdPart<InstIdParts::kARM_Cond>(); } - inline void setArmCondCode(arm::CondCode cc) noexcept { setInstIdPart<InstIdParts::kARM_Cond>(uint32_t(cc)); } + ASMJIT_INLINE_NODEBUG arm::CondCode armCondCode() const noexcept { return (arm::CondCode)getInstIdPart<InstIdParts::kARM_Cond>(); } + ASMJIT_INLINE_NODEBUG void setArmCondCode(arm::CondCode cc) noexcept { setInstIdPart<InstIdParts::kARM_Cond>(uint32_t(cc)); } + + ASMJIT_INLINE_NODEBUG a32::DataType armDt() const noexcept { return (a32::DataType)getInstIdPart<InstIdParts::kA32_DT>(); } + ASMJIT_INLINE_NODEBUG a32::DataType armDt2() const noexcept { return (a32::DataType)getInstIdPart<InstIdParts::kA32_DT2>(); } //! \} //! \name Statics //! \{ - static inline constexpr InstId composeARMInstId(uint32_t id, arm::CondCode cc) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, arm::CondCode cc) noexcept { return id | (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value); } - static inline constexpr InstId extractRealId(uint32_t id) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, a32::DataType dt, arm::CondCode cc = arm::CondCode::kAL) noexcept { + return id | (uint32_t(dt) << Support::ConstCTZ<uint32_t(InstIdParts::kA32_DT)>::value) + | (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value); + } + + static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, a32::DataType dt, a32::DataType dt2, arm::CondCode cc = arm::CondCode::kAL) noexcept { + return id | (uint32_t(dt) << Support::ConstCTZ<uint32_t(InstIdParts::kA32_DT)>::value) + | (uint32_t(dt2) << Support::ConstCTZ<uint32_t(InstIdParts::kA32_DT2)>::value) + | (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value); + } + + static ASMJIT_INLINE_NODEBUG constexpr InstId extractRealId(uint32_t id) noexcept { return id & uint32_t(InstIdParts::kRealId); } - static inline constexpr arm::CondCode extractARMCondCode(uint32_t id) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr arm::CondCode extractARMCondCode(uint32_t id) noexcept { return (arm::CondCode)((uint32_t(id) & uint32_t(InstIdParts::kARM_Cond)) >> Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value); } @@ -333,16 +347,16 @@ enum class CpuRWFlags : uint32_t { // Common RW Flags (0x000000FF) // ---------------------------- - //! Carry flag. - kCF = 0x00000001u, //! Signed overflow flag. - kOF = 0x00000002u, - //! Sign flag (negative/sign, if set). - kSF = 0x00000004u, + kOF = 0x00000001u, + //! Carry flag. + kCF = 0x00000002u, //! Zero and/or equality flag (1 if zero/equal). - kZF = 0x00000008u, + kZF = 0x00000004u, + //! Sign flag (negative/sign, if set). + kSF = 0x00000008u, - // X86 Specific RW Flags (0xFFFFFF00) + // X86 Specific RW Flags // ---------------------------------- //! Carry flag (X86, X86_64). @@ -373,12 +387,22 @@ enum class CpuRWFlags : uint32_t { //! FPU C2 status flag (X86, X86_64). kX86_C2 = 0x00040000u, //! FPU C3 status flag (X86, X86_64). - kX86_C3 = 0x00080000u + kX86_C3 = 0x00080000u, + + // ARM Specific RW Flags + // ---------------------------------- + + kARM_V = kOF, + kARM_C = kCF, + kARM_Z = kZF, + kARM_N = kSF, + kARM_Q = 0x00000100u, + kARM_GE = 0x00000200u }; ASMJIT_DEFINE_ENUM_FLAGS(CpuRWFlags) //! Operand read/write flags describe how the operand is accessed and some additional features. -enum class OpRWFlags { +enum class OpRWFlags : uint32_t { //! No flags. kNone = 0, @@ -406,6 +430,9 @@ enum class OpRWFlags { //! The `extendByteMask()` represents a zero extension. kZExt = 0x00000010u, + //! The register must have assigned a unique physical ID, which cannot be assigned to any other register. + kUnique = 0x00000080u, + //! Register operand must use \ref OpRWInfo::physId(). kRegPhysId = 0x00000100u, //! Base register of a memory operand must use \ref OpRWInfo::physId(). @@ -474,7 +501,7 @@ struct OpRWInfo { //! \{ //! Resets this operand information to all zeros. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = OpRWInfo{}; } //! Resets this operand info (resets all members) and set common information //! to the given `opFlags`, `regSize`, and possibly `physId`. @@ -485,13 +512,14 @@ struct OpRWInfo { _consecutiveLeadCount = 0; _resetReserved(); - uint64_t mask = Support::lsbMask<uint64_t>(regSize); + uint64_t mask = Support::lsbMask<uint64_t>(Support::min<uint32_t>(regSize, 64)); + _readByteMask = Support::test(opFlags, OpRWFlags::kRead) ? mask : uint64_t(0); _writeByteMask = Support::test(opFlags, OpRWFlags::kWrite) ? mask : uint64_t(0); _extendByteMask = 0; } - inline void _resetReserved() noexcept { + ASMJIT_INLINE_NODEBUG void _resetReserved() noexcept { _reserved[0] = 0; } @@ -501,36 +529,40 @@ struct OpRWInfo { //! \{ //! Returns operand flags. - inline OpRWFlags opFlags() const noexcept { return _opFlags; } + ASMJIT_INLINE_NODEBUG OpRWFlags opFlags() const noexcept { return _opFlags; } //! Tests whether operand flags contain the given `flag`. - inline bool hasOpFlag(OpRWFlags flag) const noexcept { return Support::test(_opFlags, flag); } + ASMJIT_INLINE_NODEBUG bool hasOpFlag(OpRWFlags flag) const noexcept { return Support::test(_opFlags, flag); } //! Adds the given `flags` to operand flags. - inline void addOpFlags(OpRWFlags flags) noexcept { _opFlags |= flags; } + ASMJIT_INLINE_NODEBUG void addOpFlags(OpRWFlags flags) noexcept { _opFlags |= flags; } //! Removes the given `flags` from operand flags. - inline void clearOpFlags(OpRWFlags flags) noexcept { _opFlags &= ~flags; } + ASMJIT_INLINE_NODEBUG void clearOpFlags(OpRWFlags flags) noexcept { _opFlags &= ~flags; } //! Tests whether this operand is read from. - inline bool isRead() const noexcept { return hasOpFlag(OpRWFlags::kRead); } + ASMJIT_INLINE_NODEBUG bool isRead() const noexcept { return hasOpFlag(OpRWFlags::kRead); } //! Tests whether this operand is written to. - inline bool isWrite() const noexcept { return hasOpFlag(OpRWFlags::kWrite); } + ASMJIT_INLINE_NODEBUG bool isWrite() const noexcept { return hasOpFlag(OpRWFlags::kWrite); } //! Tests whether this operand is both read and write. - inline bool isReadWrite() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRW; } + ASMJIT_INLINE_NODEBUG bool isReadWrite() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRW; } //! Tests whether this operand is read only. - inline bool isReadOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRead; } + ASMJIT_INLINE_NODEBUG bool isReadOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRead; } //! Tests whether this operand is write only. - inline bool isWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kWrite; } + ASMJIT_INLINE_NODEBUG bool isWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kWrite; } //! Returns the type of a lead register, which is followed by consecutive registers. - inline uint32_t consecutiveLeadCount() const noexcept { return _consecutiveLeadCount; } + ASMJIT_INLINE_NODEBUG uint32_t consecutiveLeadCount() const noexcept { return _consecutiveLeadCount; } //! Tests whether this operand is Reg/Mem //! //! Reg/Mem operands can use either register or memory. - inline bool isRm() const noexcept { return hasOpFlag(OpRWFlags::kRegMem); } + ASMJIT_INLINE_NODEBUG bool isRm() const noexcept { return hasOpFlag(OpRWFlags::kRegMem); } //! Tests whether the operand will be zero extended. - inline bool isZExt() const noexcept { return hasOpFlag(OpRWFlags::kZExt); } + ASMJIT_INLINE_NODEBUG bool isZExt() const noexcept { return hasOpFlag(OpRWFlags::kZExt); } + + //! Tests whether the operand must have allocated a unique physical id that cannot be shared with other register + //! operands. + ASMJIT_INLINE_NODEBUG bool isUnique() const noexcept { return hasOpFlag(OpRWFlags::kUnique); } //! \} @@ -539,38 +571,38 @@ struct OpRWInfo { //! Tests whether this is a fake memory operand, which is only used, because of encoding. Fake memory operands do //! not access any memory, they are only used to encode registers. - inline bool isMemFake() const noexcept { return hasOpFlag(OpRWFlags::kMemFake); } + ASMJIT_INLINE_NODEBUG bool isMemFake() const noexcept { return hasOpFlag(OpRWFlags::kMemFake); } //! Tests whether the instruction's memory BASE register is used. - inline bool isMemBaseUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRW); } + ASMJIT_INLINE_NODEBUG bool isMemBaseUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRW); } //! Tests whether the instruction reads from its BASE registers. - inline bool isMemBaseRead() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRead); } + ASMJIT_INLINE_NODEBUG bool isMemBaseRead() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRead); } //! Tests whether the instruction writes to its BASE registers. - inline bool isMemBaseWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseWrite); } + ASMJIT_INLINE_NODEBUG bool isMemBaseWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseWrite); } //! Tests whether the instruction reads and writes from/to its BASE registers. - inline bool isMemBaseReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRW; } + ASMJIT_INLINE_NODEBUG bool isMemBaseReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRW; } //! Tests whether the instruction only reads from its BASE registers. - inline bool isMemBaseReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRead; } + ASMJIT_INLINE_NODEBUG bool isMemBaseReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRead; } //! Tests whether the instruction only writes to its BASE registers. - inline bool isMemBaseWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseWrite; } + ASMJIT_INLINE_NODEBUG bool isMemBaseWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseWrite; } //! Tests whether the instruction modifies the BASE register before it uses it to calculate the target address. - inline bool isMemBasePreModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePreModify); } + ASMJIT_INLINE_NODEBUG bool isMemBasePreModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePreModify); } //! Tests whether the instruction modifies the BASE register after it uses it to calculate the target address. - inline bool isMemBasePostModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePostModify); } + ASMJIT_INLINE_NODEBUG bool isMemBasePostModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePostModify); } //! Tests whether the instruction's memory INDEX register is used. - inline bool isMemIndexUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRW); } + ASMJIT_INLINE_NODEBUG bool isMemIndexUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRW); } //! Tests whether the instruction reads the INDEX registers. - inline bool isMemIndexRead() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRead); } + ASMJIT_INLINE_NODEBUG bool isMemIndexRead() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRead); } //! Tests whether the instruction writes to its INDEX registers. - inline bool isMemIndexWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexWrite); } + ASMJIT_INLINE_NODEBUG bool isMemIndexWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexWrite); } //! Tests whether the instruction reads and writes from/to its INDEX registers. - inline bool isMemIndexReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRW; } + ASMJIT_INLINE_NODEBUG bool isMemIndexReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRW; } //! Tests whether the instruction only reads from its INDEX registers. - inline bool isMemIndexReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRead; } + ASMJIT_INLINE_NODEBUG bool isMemIndexReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRead; } //! Tests whether the instruction only writes to its INDEX registers. - inline bool isMemIndexWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexWrite; } + ASMJIT_INLINE_NODEBUG bool isMemIndexWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexWrite; } //! \} @@ -580,11 +612,11 @@ struct OpRWInfo { //! Returns a physical id of the register that is fixed for this operand. //! //! Returns \ref BaseReg::kIdBad if any register can be used. - inline uint32_t physId() const noexcept { return _physId; } + ASMJIT_INLINE_NODEBUG uint32_t physId() const noexcept { return _physId; } //! Tests whether \ref physId() would return a valid physical register id. - inline bool hasPhysId() const noexcept { return _physId != BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG bool hasPhysId() const noexcept { return _physId != BaseReg::kIdBad; } //! Sets physical register id, which would be fixed for this operand. - inline void setPhysId(uint32_t physId) noexcept { _physId = uint8_t(physId); } + ASMJIT_INLINE_NODEBUG void setPhysId(uint32_t physId) noexcept { _physId = uint8_t(physId); } //! \} @@ -592,9 +624,9 @@ struct OpRWInfo { //! \{ //! Returns Reg/Mem size of the operand. - inline uint32_t rmSize() const noexcept { return _rmSize; } + ASMJIT_INLINE_NODEBUG uint32_t rmSize() const noexcept { return _rmSize; } //! Sets Reg/Mem size of the operand. - inline void setRmSize(uint32_t rmSize) noexcept { _rmSize = uint8_t(rmSize); } + ASMJIT_INLINE_NODEBUG void setRmSize(uint32_t rmSize) noexcept { _rmSize = uint8_t(rmSize); } //! \} @@ -602,18 +634,18 @@ struct OpRWInfo { //! \{ //! Returns read mask. - inline uint64_t readByteMask() const noexcept { return _readByteMask; } + ASMJIT_INLINE_NODEBUG uint64_t readByteMask() const noexcept { return _readByteMask; } //! Returns write mask. - inline uint64_t writeByteMask() const noexcept { return _writeByteMask; } + ASMJIT_INLINE_NODEBUG uint64_t writeByteMask() const noexcept { return _writeByteMask; } //! Returns extend mask. - inline uint64_t extendByteMask() const noexcept { return _extendByteMask; } + ASMJIT_INLINE_NODEBUG uint64_t extendByteMask() const noexcept { return _extendByteMask; } //! Sets read mask. - inline void setReadByteMask(uint64_t mask) noexcept { _readByteMask = mask; } + ASMJIT_INLINE_NODEBUG void setReadByteMask(uint64_t mask) noexcept { _readByteMask = mask; } //! Sets write mask. - inline void setWriteByteMask(uint64_t mask) noexcept { _writeByteMask = mask; } - //! Sets externd mask. - inline void setExtendByteMask(uint64_t mask) noexcept { _extendByteMask = mask; } + ASMJIT_INLINE_NODEBUG void setWriteByteMask(uint64_t mask) noexcept { _writeByteMask = mask; } + //! Sets extend mask. + ASMJIT_INLINE_NODEBUG void setExtendByteMask(uint64_t mask) noexcept { _extendByteMask = mask; } //! \} }; @@ -647,7 +679,7 @@ struct InstRWInfo { uint8_t _rmFeature; //! Reserved for future use. uint8_t _reserved[18]; - //! Read/Write onfo of extra register (rep{} or kz{}). + //! Read/Write info of extra register (rep{} or kz{}). OpRWInfo _extraReg; //! Read/Write info of instruction operands. OpRWInfo _operands[Globals::kMaxOpCount]; @@ -658,7 +690,7 @@ struct InstRWInfo { //! \{ //! Resets this RW information to all zeros. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = InstRWInfo{}; } //! \} @@ -666,13 +698,13 @@ struct InstRWInfo { //! \{ //! Returns flags associated with the instruction, see \ref InstRWFlags. - inline InstRWFlags instFlags() const noexcept { return _instFlags; } + ASMJIT_INLINE_NODEBUG InstRWFlags instFlags() const noexcept { return _instFlags; } //! Tests whether the instruction flags contain `flag`. - inline bool hasInstFlag(InstRWFlags flag) const noexcept { return Support::test(_instFlags, flag); } + ASMJIT_INLINE_NODEBUG bool hasInstFlag(InstRWFlags flag) const noexcept { return Support::test(_instFlags, flag); } //! Tests whether the instruction flags contain \ref InstRWFlags::kMovOp. - inline bool isMovOp() const noexcept { return hasInstFlag(InstRWFlags::kMovOp); } + ASMJIT_INLINE_NODEBUG bool isMovOp() const noexcept { return hasInstFlag(InstRWFlags::kMovOp); } //! \} @@ -680,9 +712,9 @@ struct InstRWInfo { //! \{ //! Returns a mask of CPU flags read. - inline CpuRWFlags readFlags() const noexcept { return _readFlags; } + ASMJIT_INLINE_NODEBUG CpuRWFlags readFlags() const noexcept { return _readFlags; } //! Returns a mask of CPU flags written. - inline CpuRWFlags writeFlags() const noexcept { return _writeFlags; } + ASMJIT_INLINE_NODEBUG CpuRWFlags writeFlags() const noexcept { return _writeFlags; } //! \} @@ -699,7 +731,7 @@ struct InstRWInfo { //! Some AVX+ instructions may require extra features for replacing registers with memory operands, for example //! VPSLLDQ instruction only supports `vpslldq reg, reg, imm` combination on AVX/AVX2 capable CPUs and requires //! AVX-512 for `vpslldq reg, mem, imm` combination. - inline uint32_t rmFeature() const noexcept { return _rmFeature; } + ASMJIT_INLINE_NODEBUG uint32_t rmFeature() const noexcept { return _rmFeature; } //! \} @@ -707,10 +739,10 @@ struct InstRWInfo { //! \{ //! Returns RW information of extra register operand (extraReg). - inline const OpRWInfo& extraReg() const noexcept { return _extraReg; } + ASMJIT_INLINE_NODEBUG const OpRWInfo& extraReg() const noexcept { return _extraReg; } //! Returns RW information of all instruction's operands. - inline const OpRWInfo* operands() const noexcept { return _operands; } + ASMJIT_INLINE_NODEBUG const OpRWInfo* operands() const noexcept { return _operands; } //! Returns RW information of the operand at the given `index`. inline const OpRWInfo& operand(size_t index) const noexcept { @@ -719,7 +751,7 @@ struct InstRWInfo { } //! Returns the number of operands this instruction has. - inline uint32_t opCount() const noexcept { return _opCount; } + ASMJIT_INLINE_NODEBUG uint32_t opCount() const noexcept { return _opCount; } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/instdb.cpp b/3rdparty/asmjit/src/asmjit/core/instdb.cpp new file mode 100644 index 00000000000..cde369f6a18 --- /dev/null +++ b/3rdparty/asmjit/src/asmjit/core/instdb.cpp @@ -0,0 +1,101 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#include "../core/instdb_p.h" + +ASMJIT_BEGIN_NAMESPACE + +namespace InstNameUtils { + +static constexpr uint32_t kBufferSize = 32; + +static ASMJIT_FORCE_INLINE char decode5BitChar(uint32_t c) noexcept { + uint32_t base = c <= 26 ? uint32_t('a') - 1u : uint32_t('0') - 27u; + return char(base + c); +} + +static ASMJIT_FORCE_INLINE size_t decodeToBuffer(char nameOut[kBufferSize], uint32_t nameValue, const char* stringTable) noexcept { + size_t i; + + if (nameValue & 0x80000000u) { + // Small string of 5-bit characters. + for (i = 0; i < 6; i++, nameValue >>= 5) { + uint32_t c = nameValue & 0x1F; + if (c == 0) + break; + nameOut[i] = decode5BitChar(c); + } + return i; + } + else { + size_t prefixBase = nameValue & 0xFFFu; + size_t prefixSize = (nameValue >> 12) & 0xFu; + + size_t suffixBase = (nameValue >> 16) & 0xFFFu; + size_t suffixSize = (nameValue >> 28) & 0x7u; + + for (i = 0; i < prefixSize; i++) + nameOut[i] = stringTable[prefixBase + i]; + + char* suffixOut = nameOut + prefixSize; + for (i = 0; i < suffixSize; i++) + suffixOut[i] = stringTable[suffixBase + i]; + + return prefixSize + suffixSize; + } +} + +Error decode(String& output, uint32_t nameValue, const char* stringTable) noexcept { + char nameData[kBufferSize]; + size_t nameSize = decodeToBuffer(nameData, nameValue, stringTable); + + return output.append(nameData, nameSize); +} + +InstId find(const char* s, size_t len, const InstNameIndex& nameIndex, const uint32_t* nameTable, const char* stringTable) noexcept { + if (ASMJIT_UNLIKELY(!s)) + return BaseInst::kIdNone; + + if (len == SIZE_MAX) + len = strlen(s); + + if (ASMJIT_UNLIKELY(len == 0 || len > nameIndex.maxNameLength)) + return BaseInst::kIdNone; + + uint32_t prefix = uint32_t(s[0]) - 'a'; + if (ASMJIT_UNLIKELY(prefix > 'z' - 'a')) + return BaseInst::kIdNone; + + size_t base = nameIndex.data[prefix].start; + size_t end = nameIndex.data[prefix].end; + + if (ASMJIT_UNLIKELY(!base)) + return BaseInst::kIdNone; + + char nameData[kBufferSize]; + for (size_t lim = end - base; lim != 0; lim >>= 1) { + size_t instId = base + (lim >> 1); + size_t nameSize = decodeToBuffer(nameData, nameTable[instId], stringTable); + + int result = Support::compareStringViews(s, len, nameData, nameSize); + if (result < 0) + continue; + + if (result > 0) { + base = instId + 1; + lim--; + continue; + } + + return InstId(instId); + } + + return BaseInst::kIdNone; +} + +} // {InstNameUtils} + +ASMJIT_END_NAMESPACE diff --git a/3rdparty/asmjit/src/asmjit/core/instdb_p.h b/3rdparty/asmjit/src/asmjit/core/instdb_p.h new file mode 100644 index 00000000000..b5afb72cb36 --- /dev/null +++ b/3rdparty/asmjit/src/asmjit/core/instdb_p.h @@ -0,0 +1,40 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_CORE_INSTDB_P_H_INCLUDED +#define ASMJIT_CORE_INSTDB_P_H_INCLUDED + +#include "../core/inst.h" +#include "../core/string.h" + +ASMJIT_BEGIN_NAMESPACE + +//! \cond INTERNAL +//! \addtogroup asmjit_instruction_db +//! \{ + +struct InstNameIndex { + struct Span { + uint16_t start; + uint16_t end; + }; + + Span data[26]; + uint16_t maxNameLength; +}; + +namespace InstNameUtils { + +Error decode(String& output, uint32_t nameValue, const char* stringTable) noexcept; +InstId find(const char* s, size_t len, const InstNameIndex& nameIndex, const uint32_t* nameTable, const char* stringTable) noexcept; + +} // {InstNameUtils} + +//! \} +//! \endcond + +ASMJIT_END_NAMESPACE + +#endif // ASMJIT_CORE_INSTDB_P_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/core/jitallocator.cpp b/3rdparty/asmjit/src/asmjit/core/jitallocator.cpp index 19fbe4b2338..44e864105fe 100644 --- a/3rdparty/asmjit/src/asmjit/core/jitallocator.cpp +++ b/3rdparty/asmjit/src/asmjit/core/jitallocator.cpp @@ -31,18 +31,19 @@ static constexpr uint32_t kJitAllocatorMultiPoolCount = 3; static constexpr uint32_t kJitAllocatorBaseGranularity = 64; //! Maximum block size (32MB). -static constexpr uint32_t kJitAllocatorMaxBlockSize = 1024 * 1024 * 32; +static constexpr uint32_t kJitAllocatorMaxBlockSize = 1024 * 1024 * 64; // JitAllocator - Fill Pattern // =========================== static inline uint32_t JitAllocator_defaultFillPattern() noexcept { +#if ASMJIT_ARCH_X86 // X86 and X86_64 - 4x 'int3' instruction. - if (ASMJIT_ARCH_X86) - return 0xCCCCCCCCu; - + return 0xCCCCCCCCu; +#else // Unknown... return 0u; +#endif } // JitAllocator - BitVectorRangeIterator @@ -146,42 +147,38 @@ public: //! Double linked list of blocks. ZoneList<JitAllocatorBlock> blocks; //! Where to start looking first. - JitAllocatorBlock* cursor; + JitAllocatorBlock* cursor = nullptr; //! Count of blocks. - uint32_t blockCount; + uint32_t blockCount = 0; //! Allocation granularity. - uint16_t granularity; + uint16_t granularity = 0; //! Log2(granularity). - uint8_t granularityLog2; + uint8_t granularityLog2 = 0; //! Count of empty blocks (either 0 or 1 as we won't keep more blocks empty). - uint8_t emptyBlockCount; + uint8_t emptyBlockCount = 0; //! Number of bits reserved across all blocks. - size_t totalAreaSize; + size_t totalAreaSize[2] {}; //! Number of bits used across all blocks. - size_t totalAreaUsed; + size_t totalAreaUsed[2] {}; //! Overhead of all blocks (in bytes). - size_t totalOverheadBytes; + size_t totalOverheadBytes = 0; inline JitAllocatorPool(uint32_t granularity) noexcept : blocks(), - cursor(nullptr), - blockCount(0), granularity(uint16_t(granularity)), - granularityLog2(uint8_t(Support::ctz(granularity))), - emptyBlockCount(0), - totalAreaSize(0), - totalAreaUsed(0), - totalOverheadBytes(0) {} + granularityLog2(uint8_t(Support::ctz(granularity))) {} inline void reset() noexcept { blocks.reset(); cursor = nullptr; - blockCount = 0; - totalAreaSize = 0; - totalAreaUsed = 0; - totalOverheadBytes = 0; + blockCount = 0u; + totalAreaSize[0] = 0u; + totalAreaSize[1] = 0u; + totalAreaUsed[0] = 0u; + totalAreaUsed[1] = 0u; + totalOverheadBytes = 0u; } inline size_t byteSizeFromAreaSize(uint32_t areaSize) const noexcept { return size_t(areaSize) * granularity; } @@ -202,39 +199,47 @@ public: ASMJIT_NONCOPYABLE(JitAllocatorBlock) enum Flags : uint32_t { + //! Block has initial padding, see \ref JitAllocatorOptions::kDisableInitialPadding. + kFlagInitialPadding = 0x00000001u, //! Block is empty. - kFlagEmpty = 0x00000001u, + kFlagEmpty = 0x00000002u, //! Block is dirty (largestUnusedArea, searchStart, searchEnd). - kFlagDirty = 0x00000002u, - //! Block is dual-mapped. - kFlagDualMapped = 0x00000004u + kFlagDirty = 0x00000004u, + //! Block represents memory that is using large pages. + kFlagLargePages = 0x00000008u, + //! Block represents memory that is dual-mapped. + kFlagDualMapped = 0x00000010u }; + static_assert(kFlagInitialPadding == 1, "JitAllocatorBlock::kFlagInitialPadding must be equal to 1"); + + static inline uint32_t initialAreaStartByFlags(uint32_t flags) noexcept { return flags & kFlagInitialPadding; } + //! Link to the pool that owns this block. - JitAllocatorPool* _pool; + JitAllocatorPool* _pool {}; //! Virtual memory mapping - either single mapping (both pointers equal) or //! dual mapping, where one pointer is Read+Execute and the second Read+Write. - VirtMem::DualMapping _mapping; + VirtMem::DualMapping _mapping {}; //! Virtual memory size (block size) [bytes]. - size_t _blockSize; + size_t _blockSize = 0; //! Block flags. - uint32_t _flags; + uint32_t _flags = 0; //! Size of the whole block area (bit-vector size). - uint32_t _areaSize; + uint32_t _areaSize = 0; //! Used area (number of bits in bit-vector used). - uint32_t _areaUsed; + uint32_t _areaUsed = 0; //! The largest unused continuous area in the bit-vector (or `areaSize` to initiate rescan). - uint32_t _largestUnusedArea; + uint32_t _largestUnusedArea = 0; //! Start of a search range (for unused bits). - uint32_t _searchStart; + uint32_t _searchStart = 0; //! End of a search range (for unused bits). - uint32_t _searchEnd; + uint32_t _searchEnd = 0; //! Used bit-vector (0 = unused, 1 = used). - Support::BitWord* _usedBitVector; + Support::BitWord* _usedBitVector {}; //! Stop bit-vector (0 = don't care, 1 = stop). - Support::BitWord* _stopBitVector; + Support::BitWord* _stopBitVector {}; inline JitAllocatorBlock( JitAllocatorPool* pool, @@ -250,12 +255,15 @@ public: _blockSize(blockSize), _flags(blockFlags), _areaSize(areaSize), - _areaUsed(0), - _largestUnusedArea(areaSize), - _searchStart(0), - _searchEnd(areaSize), + _areaUsed(0), // Will be initialized by clearBlock(). + _largestUnusedArea(0), // Will be initialized by clearBlock(). + _searchStart(0), // Will be initialized by clearBlock(). + _searchEnd(0), // Will be initialized by clearBlock(). _usedBitVector(usedBitVector), - _stopBitVector(stopBitVector) {} + _stopBitVector(stopBitVector) { + + clearBlock(); + } inline JitAllocatorPool* pool() const noexcept { return _pool; } @@ -266,9 +274,15 @@ public: inline void addFlags(uint32_t f) noexcept { _flags |= f; } inline void clearFlags(uint32_t f) noexcept { _flags &= ~f; } + inline bool empty() const noexcept { return hasFlag(kFlagEmpty); } inline bool isDirty() const noexcept { return hasFlag(kFlagDirty); } inline void makeDirty() noexcept { addFlags(kFlagDirty); } + inline bool hasLargePages() const noexcept { return hasFlag(kFlagLargePages); } + inline bool hasInitialPadding() const noexcept { return hasFlag(kFlagInitialPadding); } + + inline uint32_t initialAreaStart() const noexcept { return initialAreaStartByFlags(_flags); } + inline size_t blockSize() const noexcept { return _blockSize; } inline uint32_t areaSize() const noexcept { return _areaSize; } @@ -278,7 +292,27 @@ public: inline void decreaseUsedArea(uint32_t value) noexcept { _areaUsed -= value; - _pool->totalAreaUsed -= value; + _pool->totalAreaUsed[size_t(hasLargePages())] -= value; + } + + inline void clearBlock() noexcept { + bool bit = hasInitialPadding(); + size_t numBitWords = _pool->bitWordCountFromAreaSize(_areaSize); + + memset(_usedBitVector, 0, numBitWords * sizeof(Support::BitWord)); + memset(_stopBitVector, 0, numBitWords * sizeof(Support::BitWord)); + + Support::bitVectorSetBit(_usedBitVector, 0, bit); + Support::bitVectorSetBit(_stopBitVector, 0, bit); + + uint32_t start = initialAreaStartByFlags(_flags); + _areaUsed = start; + _largestUnusedArea = _areaSize - start; + _searchStart = start; + _searchEnd = _areaSize; + + addFlags(JitAllocatorBlock::kFlagEmpty); + clearFlags(JitAllocatorBlock::kFlagDirty); } inline void markAllocatedArea(uint32_t allocatedAreaStart, uint32_t allocatedAreaEnd) noexcept { @@ -289,21 +323,24 @@ public: Support::bitVectorSetBit(_stopBitVector, allocatedAreaEnd - 1, true); // Update search region and statistics. - _pool->totalAreaUsed += allocatedAreaSize; + _pool->totalAreaUsed[size_t(hasLargePages())] += allocatedAreaSize; _areaUsed += allocatedAreaSize; if (areaAvailable() == 0) { _searchStart = _areaSize; _searchEnd = 0; _largestUnusedArea = 0; - clearFlags(kFlagDirty); + + clearFlags(kFlagDirty | kFlagEmpty); } else { if (_searchStart == allocatedAreaStart) _searchStart = allocatedAreaEnd; if (_searchEnd == allocatedAreaEnd) _searchEnd = allocatedAreaStart; + addFlags(kFlagDirty); + clearFlags(kFlagEmpty); } } @@ -311,7 +348,7 @@ public: uint32_t releasedAreaSize = releasedAreaEnd - releasedAreaStart; // Update the search region and statistics. - _pool->totalAreaUsed -= releasedAreaSize; + _pool->totalAreaUsed[size_t(hasLargePages())] -= releasedAreaSize; _areaUsed -= releasedAreaSize; _searchStart = Support::min(_searchStart, releasedAreaStart); _searchEnd = Support::max(_searchEnd, releasedAreaEnd); @@ -320,10 +357,10 @@ public: Support::bitVectorClear(_usedBitVector, releasedAreaStart, releasedAreaSize); Support::bitVectorSetBit(_stopBitVector, releasedAreaEnd - 1, false); - if (areaUsed() == 0) { - _searchStart = 0; + if (areaUsed() == initialAreaStart()) { + _searchStart = initialAreaStart(); _searchEnd = _areaSize; - _largestUnusedArea = _areaSize; + _largestUnusedArea = _areaSize - initialAreaStart(); addFlags(kFlagEmpty); clearFlags(kFlagDirty); } @@ -341,7 +378,7 @@ public: ASMJIT_ASSERT(shrunkAreaSize != 0); // Update the search region and statistics. - _pool->totalAreaUsed -= shrunkAreaSize; + _pool->totalAreaUsed[size_t(hasLargePages())] -= shrunkAreaSize; _areaUsed -= shrunkAreaSize; _searchStart = Support::min(_searchStart, shrunkAreaStart); _searchEnd = Support::max(_searchEnd, shrunkAreaEnd); @@ -411,7 +448,7 @@ static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator:: // Setup pool count to [1..3]. size_t poolCount = 1; if (Support::test(options, JitAllocatorOptions::kUseMultiplePools)) - poolCount = kJitAllocatorMultiPoolCount;; + poolCount = kJitAllocatorMultiPoolCount; // Setup block size [64kB..256MB]. if (blockSize < 64 * 1024 || blockSize > 256 * 1024 * 1024 || !Support::isPowerOf2(blockSize)) @@ -430,8 +467,17 @@ static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator:: if (ASMJIT_UNLIKELY(!p)) return nullptr; + VirtMem::HardenedRuntimeInfo hardenedRtInfo = VirtMem::hardenedRuntimeInfo(); + if (Support::test(hardenedRtInfo.flags, VirtMem::HardenedRuntimeFlags::kEnabled)) { + // If we are running within a hardened environment (mapping RWX is not allowed) then we have to use dual mapping + // or other runtime capabilities like Apple specific MAP_JIT. There is no point in not enabling these as otherwise + // the allocation would fail and JitAllocator would not be able to allocate memory. + if (!Support::test(hardenedRtInfo.flags, VirtMem::HardenedRuntimeFlags::kMapJit)) + options |= JitAllocatorOptions::kUseDualMapping; + } + JitAllocatorPool* pools = reinterpret_cast<JitAllocatorPool*>((uint8_t*)p + sizeof(JitAllocatorPrivateImpl)); - JitAllocatorPrivateImpl* impl = new(p) JitAllocatorPrivateImpl(pools, poolCount); + JitAllocatorPrivateImpl* impl = new(Support::PlacementNew{p}) JitAllocatorPrivateImpl(pools, poolCount); impl->options = options; impl->blockSize = blockSize; @@ -440,7 +486,7 @@ static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator:: impl->pageSize = vmInfo.pageSize; for (size_t poolId = 0; poolId < poolCount; poolId++) - new(&pools[poolId]) JitAllocatorPool(granularity << poolId); + new(Support::PlacementNew{&pools[poolId]}) JitAllocatorPool(granularity << poolId); return impl; } @@ -473,6 +519,14 @@ static inline size_t JitAllocatorImpl_calculateIdealBlockSize(JitAllocatorPrivat JitAllocatorBlock* last = pool->blocks.last(); size_t blockSize = last ? last->blockSize() : size_t(impl->blockSize); + // We have to increase the allocationSize if we know that the block must provide padding. + if (!Support::test(impl->options, JitAllocatorOptions::kDisableInitialPadding)) { + size_t granularity = pool->granularity; + if (SIZE_MAX - allocationSize < granularity) + return 0; // Overflown + allocationSize += granularity; + } + if (blockSize < kJitAllocatorMaxBlockSize) blockSize *= 2u; @@ -485,64 +539,102 @@ static inline size_t JitAllocatorImpl_calculateIdealBlockSize(JitAllocatorPrivat return blockSize; } -ASMJIT_FAVOR_SPEED static void JitAllocatorImpl_fillPattern(void* mem, uint32_t pattern, size_t sizeInBytes) noexcept { - size_t n = sizeInBytes / 4u; - uint32_t* p = static_cast<uint32_t*>(mem); +ASMJIT_NOINLINE +ASMJIT_FAVOR_SPEED static void JitAllocatorImpl_fillPattern(void* mem, uint32_t pattern, size_t byteSize) noexcept { + // NOTE: This is always used to fill a pattern in allocated / freed memory. The allocation has always + // a granularity that is greater than the pattern, however, when shrink() is used, we may end up having + // an unaligned start, so deal with it here and then copy aligned pattern in the loop. + if ((uintptr_t(mem) & 0x1u) && byteSize >= 1u) { + static_cast<uint8_t*>(mem)[0] = uint8_t(pattern & 0xFF); + mem = static_cast<uint8_t*>(mem) + 1; + byteSize--; + } + + if ((uintptr_t(mem) & 0x2u) && byteSize >= 2u) { + static_cast<uint16_t*>(mem)[0] = uint16_t(pattern & 0xFFFF); + mem = static_cast<uint16_t*>(mem) + 1; + byteSize -= 2; + } + + // Something would be seriously broken if we end up with aligned `mem`, but unaligned `byteSize`. + ASMJIT_ASSERT((byteSize & 0x3u) == 0u); + + uint32_t* mem32 = static_cast<uint32_t*>(mem); + size_t n = byteSize / 4u; for (size_t i = 0; i < n; i++) - p[i] = pattern; + mem32[i] = pattern; } // Allocate a new `JitAllocatorBlock` for the given `blockSize`. // // NOTE: The block doesn't have `kFlagEmpty` flag set, because the new block // is only allocated when it's actually needed, so it would be cleared anyway. -static JitAllocatorBlock* JitAllocatorImpl_newBlock(JitAllocatorPrivateImpl* impl, JitAllocatorPool* pool, size_t blockSize) noexcept { +static Error JitAllocatorImpl_newBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock** dst, JitAllocatorPool* pool, size_t blockSize) noexcept { using Support::BitWord; using Support::kBitWordSizeInBits; - uint32_t areaSize = uint32_t((blockSize + pool->granularity - 1) >> pool->granularityLog2); - uint32_t numBitWords = (areaSize + kBitWordSizeInBits - 1u) / kBitWordSizeInBits; + uint32_t blockFlags = 0; + if (!Support::test(impl->options, JitAllocatorOptions::kDisableInitialPadding)) + blockFlags |= JitAllocatorBlock::kFlagInitialPadding; - JitAllocatorBlock* block = static_cast<JitAllocatorBlock*>(::malloc(sizeof(JitAllocatorBlock))); - BitWord* bitWords = nullptr; VirtMem::DualMapping virtMem {}; - Error err = kErrorOutOfMemory; - - if (block != nullptr) - bitWords = static_cast<BitWord*>(::malloc(size_t(numBitWords) * 2 * sizeof(BitWord))); + VirtMem::MemoryFlags memFlags = VirtMem::MemoryFlags::kAccessRWX; - uint32_t blockFlags = 0; - if (bitWords != nullptr) { - if (Support::test(impl->options, JitAllocatorOptions::kUseDualMapping)) { - err = VirtMem::allocDualMapping(&virtMem, blockSize, VirtMem::MemoryFlags::kAccessRWX); - blockFlags |= JitAllocatorBlock::kFlagDualMapped; - } - else { - err = VirtMem::alloc(&virtMem.rx, blockSize, VirtMem::MemoryFlags::kAccessRWX); - virtMem.rw = virtMem.rx; - } + if (Support::test(impl->options, JitAllocatorOptions::kUseDualMapping)) { + ASMJIT_PROPAGATE(VirtMem::allocDualMapping(&virtMem, blockSize, memFlags)); + blockFlags |= JitAllocatorBlock::kFlagDualMapped; } + else { + bool allocateRegularPages = true; + if (Support::test(impl->options, JitAllocatorOptions::kUseLargePages)) { + size_t largePageSize = VirtMem::largePageSize(); + bool tryLargePage = blockSize >= largePageSize || Support::test(impl->options, JitAllocatorOptions::kAlignBlockSizeToLargePage); + + // Only proceed if we can actually allocate large pages. + if (largePageSize && tryLargePage) { + size_t largeBlockSize = Support::alignUp(blockSize, largePageSize); + Error err = VirtMem::alloc(&virtMem.rx, largeBlockSize, memFlags | VirtMem::MemoryFlags::kMMapLargePages); + + // Fallback to regular pages if large page(s) allocation failed. + if (err == kErrorOk) { + allocateRegularPages = false; + blockSize = largeBlockSize; + blockFlags |= JitAllocatorBlock::kFlagLargePages; + } + } + } - // Out of memory. - if (ASMJIT_UNLIKELY(!block || !bitWords || err != kErrorOk)) { - if (bitWords) - ::free(bitWords); + // Called either if large pages were not requested or large page(s) allocation failed. + if (allocateRegularPages) { + ASMJIT_PROPAGATE(VirtMem::alloc(&virtMem.rx, blockSize, memFlags)); + } - if (block) - ::free(block); + virtMem.rw = virtMem.rx; + } - return nullptr; + uint32_t areaSize = uint32_t((blockSize + pool->granularity - 1) >> pool->granularityLog2); + uint32_t numBitWords = (areaSize + kBitWordSizeInBits - 1u) / kBitWordSizeInBits; + uint8_t* blockPtr = static_cast<uint8_t*>(::malloc(sizeof(JitAllocatorBlock) + size_t(numBitWords) * 2u * sizeof(BitWord))); + + // Out of memory... + if (ASMJIT_UNLIKELY(blockPtr == nullptr)) { + if (Support::test(impl->options, JitAllocatorOptions::kUseDualMapping)) + VirtMem::releaseDualMapping(&virtMem, blockSize); + else + VirtMem::release(virtMem.rx, blockSize); + return DebugUtils::errored(kErrorOutOfMemory); } - // Fill the memory if the secure mode is enabled. + // Fill the allocated virtual memory if secure mode is enabled. if (Support::test(impl->options, JitAllocatorOptions::kFillUnusedMemory)) { VirtMem::ProtectJitReadWriteScope scope(virtMem.rw, blockSize); JitAllocatorImpl_fillPattern(virtMem.rw, impl->fillPattern, blockSize); } - memset(bitWords, 0, size_t(numBitWords) * 2 * sizeof(BitWord)); - return new(block) JitAllocatorBlock(pool, virtMem, blockSize, blockFlags, bitWords, bitWords + numBitWords, areaSize); + BitWord* bitWords = reinterpret_cast<BitWord*>(blockPtr + sizeof(JitAllocatorBlock)); + *dst = new(Support::PlacementNew{blockPtr}) JitAllocatorBlock(pool, virtMem, blockSize, blockFlags, bitWords, bitWords + numBitWords, areaSize); + return kErrorOk; } static void JitAllocatorImpl_deleteBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { @@ -553,7 +645,6 @@ static void JitAllocatorImpl_deleteBlock(JitAllocatorPrivateImpl* impl, JitAlloc else VirtMem::release(block->rxPtr(), block->blockSize()); - ::free(block->_usedBitVector); ::free(block); } @@ -568,8 +659,10 @@ static void JitAllocatorImpl_insertBlock(JitAllocatorPrivateImpl* impl, JitAlloc pool->blocks.append(block); // Update statistics. + size_t statIndex = size_t(block->hasLargePages()); pool->blockCount++; - pool->totalAreaSize += block->areaSize(); + pool->totalAreaSize[statIndex] += block->areaSize(); + pool->totalAreaUsed[statIndex] += block->areaUsed(); pool->totalOverheadBytes += sizeof(JitAllocatorBlock) + JitAllocatorImpl_bitVectorSizeToByteSize(block->areaSize()) * 2u; } @@ -584,8 +677,10 @@ static void JitAllocatorImpl_removeBlock(JitAllocatorPrivateImpl* impl, JitAlloc pool->blocks.unlink(block); // Update statistics. + size_t statIndex = size_t(block->hasLargePages()); pool->blockCount--; - pool->totalAreaSize -= block->areaSize(); + pool->totalAreaSize[statIndex] -= block->areaSize(); + pool->totalAreaUsed[statIndex] -= block->areaUsed(); pool->totalOverheadBytes -= sizeof(JitAllocatorBlock) + JitAllocatorImpl_bitVectorSizeToByteSize(block->areaSize()) * 2u; } @@ -594,12 +689,10 @@ static void JitAllocatorImpl_wipeOutBlock(JitAllocatorPrivateImpl* impl, JitAllo return; JitAllocatorPool* pool = block->pool(); - uint32_t areaSize = block->areaSize(); - uint32_t granularity = pool->granularity; - size_t numBitWords = pool->bitWordCountFromAreaSize(areaSize); - - VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadWrite); if (Support::test(impl->options, JitAllocatorOptions::kFillUnusedMemory)) { + VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadWrite); + + uint32_t granularity = pool->granularity; uint8_t* rwPtr = block->rwPtr(); BitVectorRangeIterator<Support::BitWord, 0> it(block->_usedBitVector, pool->bitWordCountFromAreaSize(block->areaSize())); @@ -613,18 +706,10 @@ static void JitAllocatorImpl_wipeOutBlock(JitAllocatorPrivateImpl* impl, JitAllo JitAllocatorImpl_fillPattern(spanPtr, impl->fillPattern, spanSize); VirtMem::flushInstructionCache(spanPtr, spanSize); } + VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadExecute); } - VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadExecute); - memset(block->_usedBitVector, 0, size_t(numBitWords) * sizeof(Support::BitWord)); - memset(block->_stopBitVector, 0, size_t(numBitWords) * sizeof(Support::BitWord)); - - block->_areaUsed = 0; - block->_largestUnusedArea = areaSize; - block->_searchStart = 0; - block->_searchEnd = areaSize; - block->addFlags(JitAllocatorBlock::kFlagEmpty); - block->clearFlags(JitAllocatorBlock::kFlagDirty); + block->clearBlock(); } // JitAllocator - Construction & Destruction @@ -659,26 +744,28 @@ void JitAllocator::reset(ResetPolicy resetPolicy) noexcept { JitAllocatorPool& pool = impl->pools[poolId]; JitAllocatorBlock* block = pool.blocks.first(); - JitAllocatorBlock* blockToKeep = nullptr; - if (resetPolicy != ResetPolicy::kHard && uint32_t(impl->options & JitAllocatorOptions::kImmediateRelease) == 0) { - blockToKeep = block; - block = block->next(); - } + pool.reset(); - while (block) { - JitAllocatorBlock* next = block->next(); - JitAllocatorImpl_deleteBlock(impl, block); - block = next; - } + if (block) { + JitAllocatorBlock* blockToKeep = nullptr; + if (resetPolicy != ResetPolicy::kHard && uint32_t(impl->options & JitAllocatorOptions::kImmediateRelease) == 0) { + blockToKeep = block; + block = block->next(); + } - pool.reset(); + while (block) { + JitAllocatorBlock* next = block->next(); + JitAllocatorImpl_deleteBlock(impl, block); + block = next; + } - if (blockToKeep) { - blockToKeep->_listNodes[0] = nullptr; - blockToKeep->_listNodes[1] = nullptr; - JitAllocatorImpl_wipeOutBlock(impl, blockToKeep); - JitAllocatorImpl_insertBlock(impl, blockToKeep); - pool.emptyBlockCount = 1; + if (blockToKeep) { + blockToKeep->_listNodes[0] = nullptr; + blockToKeep->_listNodes[1] = nullptr; + JitAllocatorImpl_wipeOutBlock(impl, blockToKeep); + JitAllocatorImpl_insertBlock(impl, blockToKeep); + pool.emptyBlockCount = 1; + } } } } @@ -698,8 +785,8 @@ JitAllocator::Statistics JitAllocator::statistics() const noexcept { for (size_t poolId = 0; poolId < poolCount; poolId++) { const JitAllocatorPool& pool = impl->pools[poolId]; statistics._blockCount += size_t(pool.blockCount); - statistics._reservedSize += size_t(pool.totalAreaSize) * pool.granularity; - statistics._usedSize += size_t(pool.totalAreaUsed) * pool.granularity; + statistics._reservedSize += size_t(pool.totalAreaSize[0] + pool.totalAreaSize[1]) * pool.granularity; + statistics._usedSize += size_t(pool.totalAreaUsed[0] + pool.totalAreaUsed[1]) * pool.granularity; statistics._overheadSize += size_t(pool.totalOverheadBytes); } @@ -712,16 +799,15 @@ JitAllocator::Statistics JitAllocator::statistics() const noexcept { // JitAllocator - Alloc & Release // ============================== -Error JitAllocator::alloc(void** rxPtrOut, void** rwPtrOut, size_t size) noexcept { +Error JitAllocator::alloc(Span& out, size_t size) noexcept { + out = Span{}; + if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) return DebugUtils::errored(kErrorNotInitialized); JitAllocatorPrivateImpl* impl = static_cast<JitAllocatorPrivateImpl*>(_impl); constexpr uint32_t kNoIndex = std::numeric_limits<uint32_t>::max(); - *rxPtrOut = nullptr; - *rwPtrOut = nullptr; - // Align to the minimum granularity by default. size = Support::alignUp<size_t>(size, impl->granularity); if (ASMJIT_UNLIKELY(size == 0)) @@ -783,21 +869,18 @@ Error JitAllocator::alloc(void** rxPtrOut, void** rwPtrOut, size_t size) noexcep } while (block != initial); } - // Allocate a new block if there is no region of a required width. + // Allocate a new block if there is no region of a required size. if (areaIndex == kNoIndex) { size_t blockSize = JitAllocatorImpl_calculateIdealBlockSize(impl, pool, size); if (ASMJIT_UNLIKELY(!blockSize)) return DebugUtils::errored(kErrorOutOfMemory); - block = JitAllocatorImpl_newBlock(impl, pool, blockSize); - areaIndex = 0; - - if (ASMJIT_UNLIKELY(!block)) - return DebugUtils::errored(kErrorOutOfMemory); + ASMJIT_PROPAGATE(JitAllocatorImpl_newBlock(impl, &block, pool, blockSize)); + areaIndex = block->initialAreaStart(); JitAllocatorImpl_insertBlock(impl, block); - block->_searchStart = areaSize; - block->_largestUnusedArea = block->areaSize() - areaSize; + block->_searchStart += areaSize; + block->_largestUnusedArea -= areaSize; } else if (block->hasFlag(JitAllocatorBlock::kFlagEmpty)) { pool->emptyBlockCount--; @@ -808,32 +891,35 @@ Error JitAllocator::alloc(void** rxPtrOut, void** rwPtrOut, size_t size) noexcep impl->allocationCount++; block->markAllocatedArea(areaIndex, areaIndex + areaSize); - // Return a pointer to the allocated memory. + // Return a span referencing the allocated memory. size_t offset = pool->byteSizeFromAreaSize(areaIndex); ASMJIT_ASSERT(offset <= block->blockSize() - size); - *rxPtrOut = block->rxPtr() + offset; - *rwPtrOut = block->rwPtr() + offset; + out._rx = block->rxPtr() + offset; + out._rw = block->rwPtr() + offset; + out._size = size; + out._block = static_cast<void*>(block); + return kErrorOk; } -Error JitAllocator::release(void* rxPtr) noexcept { +Error JitAllocator::release(void* rx) noexcept { if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) return DebugUtils::errored(kErrorNotInitialized); - if (ASMJIT_UNLIKELY(!rxPtr)) + if (ASMJIT_UNLIKELY(!rx)) return DebugUtils::errored(kErrorInvalidArgument); JitAllocatorPrivateImpl* impl = static_cast<JitAllocatorPrivateImpl*>(_impl); LockGuard guard(impl->lock); - JitAllocatorBlock* block = impl->tree.get(static_cast<uint8_t*>(rxPtr)); + JitAllocatorBlock* block = impl->tree.get(static_cast<uint8_t*>(rx)); if (ASMJIT_UNLIKELY(!block)) return DebugUtils::errored(kErrorInvalidState); // Offset relative to the start of the block. JitAllocatorPool* pool = block->pool(); - size_t offset = (size_t)((uint8_t*)rxPtr - block->rxPtr()); + size_t offset = (size_t)((uint8_t*)rx - block->rxPtr()); // The first bit representing the allocated area and its size. uint32_t areaIndex = uint32_t(offset >> pool->granularityLog2); @@ -853,7 +939,7 @@ Error JitAllocator::release(void* rxPtr) noexcept { } // Release the whole block if it became empty. - if (block->areaUsed() == 0) { + if (block->empty()) { if (pool->emptyBlockCount || Support::test(impl->options, JitAllocatorOptions::kImmediateRelease)) { JitAllocatorImpl_removeBlock(impl, block); JitAllocatorImpl_deleteBlock(impl, block); @@ -866,49 +952,196 @@ Error JitAllocator::release(void* rxPtr) noexcept { return kErrorOk; } -Error JitAllocator::shrink(void* rxPtr, size_t newSize) noexcept { +static Error JitAllocatorImpl_shrink(JitAllocatorPrivateImpl* impl, JitAllocator::Span& span, size_t newSize, bool alreadyUnderWriteScope) noexcept { + JitAllocatorBlock* block = static_cast<JitAllocatorBlock*>(span._block); + if (ASMJIT_UNLIKELY(!block)) + return DebugUtils::errored(kErrorInvalidArgument); + + LockGuard guard(impl->lock); + + // Offset relative to the start of the block. + JitAllocatorPool* pool = block->pool(); + size_t offset = (size_t)((uint8_t*)span.rx() - block->rxPtr()); + + // The first bit representing the allocated area and its size. + uint32_t areaStart = uint32_t(offset >> pool->granularityLog2); + + // Don't trust `span.size()` - if it has been already truncated we would be off... + bool isUsed = Support::bitVectorGetBit(block->_usedBitVector, areaStart); + if (ASMJIT_UNLIKELY(!isUsed)) + return DebugUtils::errored(kErrorInvalidArgument); + + uint32_t areaEnd = uint32_t(Support::bitVectorIndexOf(block->_stopBitVector, areaStart, true)) + 1; + uint32_t areaPrevSize = areaEnd - areaStart; + uint32_t spanPrevSize = areaPrevSize * pool->granularity; + uint32_t areaShrunkSize = pool->areaSizeFromByteSize(newSize); + + if (ASMJIT_UNLIKELY(areaShrunkSize > areaPrevSize)) + return DebugUtils::errored(kErrorInvalidArgument); + + uint32_t areaDiff = areaPrevSize - areaShrunkSize; + if (areaDiff) { + block->markShrunkArea(areaStart + areaShrunkSize, areaEnd); + span._size = pool->byteSizeFromAreaSize(areaShrunkSize); + } + + // Fill released memory if the secure mode is enabled. + if (newSize < spanPrevSize && Support::test(impl->options, JitAllocatorOptions::kFillUnusedMemory)) { + uint8_t* spanPtr = block->rwPtr() + (areaStart + areaShrunkSize) * pool->granularity; + size_t spanSize = areaDiff * pool->granularity; + + if (!alreadyUnderWriteScope) { + VirtMem::ProtectJitReadWriteScope scope(spanPtr, spanSize, VirtMem::CachePolicy::kNeverFlush); + JitAllocatorImpl_fillPattern(spanPtr, impl->fillPattern, spanSize); + } + else { + JitAllocatorImpl_fillPattern(spanPtr, impl->fillPattern, spanSize); + } + } + + return kErrorOk; +} + +Error JitAllocator::shrink(Span& span, size_t newSize) noexcept { if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) return DebugUtils::errored(kErrorNotInitialized); - if (ASMJIT_UNLIKELY(!rxPtr)) + if (ASMJIT_UNLIKELY(!span.rx())) return DebugUtils::errored(kErrorInvalidArgument); - if (ASMJIT_UNLIKELY(newSize == 0)) - return release(rxPtr); + if (ASMJIT_UNLIKELY(newSize == 0)) { + Error err = release(span.rx()); + span = Span{}; + return err; + } + + return JitAllocatorImpl_shrink(static_cast<JitAllocatorPrivateImpl*>(_impl), span, newSize, false); +} + +Error JitAllocator::query(Span& out, void* rx) const noexcept { + out = Span{}; + + if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) + return DebugUtils::errored(kErrorNotInitialized); JitAllocatorPrivateImpl* impl = static_cast<JitAllocatorPrivateImpl*>(_impl); LockGuard guard(impl->lock); - JitAllocatorBlock* block = impl->tree.get(static_cast<uint8_t*>(rxPtr)); + JitAllocatorBlock* block = impl->tree.get(static_cast<uint8_t*>(rx)); if (ASMJIT_UNLIKELY(!block)) return DebugUtils::errored(kErrorInvalidArgument); // Offset relative to the start of the block. JitAllocatorPool* pool = block->pool(); - size_t offset = (size_t)((uint8_t*)rxPtr - block->rxPtr()); + size_t offset = (size_t)((uint8_t*)rx - block->rxPtr()); // The first bit representing the allocated area and its size. uint32_t areaStart = uint32_t(offset >> pool->granularityLog2); + + bool isUsed = Support::bitVectorGetBit(block->_usedBitVector, areaStart); + if (ASMJIT_UNLIKELY(!isUsed)) + return DebugUtils::errored(kErrorInvalidArgument); + uint32_t areaEnd = uint32_t(Support::bitVectorIndexOf(block->_stopBitVector, areaStart, true)) + 1; + size_t byteOffset = pool->byteSizeFromAreaSize(areaStart); + size_t byteSize = pool->byteSizeFromAreaSize(areaEnd - areaStart); - uint32_t areaPrevSize = areaEnd - areaStart; - uint32_t areaShrunkSize = pool->areaSizeFromByteSize(newSize); + out._rx = static_cast<uint8_t*>(block->_mapping.rx) + byteOffset; + out._rw = static_cast<uint8_t*>(block->_mapping.rw) + byteOffset; + out._size = byteSize; + out._block = static_cast<void*>(block); - if (ASMJIT_UNLIKELY(areaShrunkSize > areaPrevSize)) - return DebugUtils::errored(kErrorInvalidState); + return kErrorOk; +} - uint32_t areaDiff = areaPrevSize - areaShrunkSize; - if (areaDiff) { - block->markShrunkArea(areaStart + areaShrunkSize, areaEnd); +// JitAllocator - Write +// ==================== - // Fill released memory if the secure mode is enabled. - if (Support::test(impl->options, JitAllocatorOptions::kFillUnusedMemory)) - JitAllocatorImpl_fillPattern(block->rwPtr() + (areaStart + areaShrunkSize) * pool->granularity, fillPattern(), areaDiff * pool->granularity); +static ASMJIT_FORCE_INLINE VirtMem::CachePolicy JitAllocator_defaultPolicyForSpan(const JitAllocator::Span& span) noexcept { + if (Support::test(span.flags(), JitAllocator::Span::Flags::kInstructionCacheClean)) + return VirtMem::CachePolicy::kNeverFlush; + else + return VirtMem::CachePolicy::kFlushAfterWrite; +} + +Error JitAllocator::write(Span& span, size_t offset, const void* src, size_t size, VirtMem::CachePolicy policy) noexcept { + if (ASMJIT_UNLIKELY(span._block == nullptr || offset > span.size() || span.size() - offset < size)) + return DebugUtils::errored(kErrorInvalidArgument); + + if (ASMJIT_UNLIKELY(size == 0)) + return kErrorOk; + + if (policy == VirtMem::CachePolicy::kDefault) + policy = JitAllocator_defaultPolicyForSpan(span); + + VirtMem::ProtectJitReadWriteScope writeScope(span.rx(), span.size(), policy); + memcpy(static_cast<uint8_t*>(span.rw()) + offset, src, size); + return kErrorOk; +} + +Error JitAllocator::write(Span& span, WriteFunc writeFunc, void* userData, VirtMem::CachePolicy policy) noexcept { + if (ASMJIT_UNLIKELY(span._block == nullptr) || span.size() == 0) + return DebugUtils::errored(kErrorInvalidArgument); + + size_t size = span.size(); + if (ASMJIT_UNLIKELY(size == 0)) + return kErrorOk; + + if (policy == VirtMem::CachePolicy::kDefault) + policy = JitAllocator_defaultPolicyForSpan(span); + + VirtMem::ProtectJitReadWriteScope writeScope(span.rx(), span.size(), policy); + ASMJIT_PROPAGATE(writeFunc(span, userData)); + + // Check whether span.truncate() has been called. + if (span.size() != size) { + // OK, this is a bit awkward... However, shrink wants the original span and newSize, so we have to swap. + std::swap(span._size, size); + return JitAllocatorImpl_shrink(static_cast<JitAllocatorPrivateImpl*>(_impl), span, size, true); } return kErrorOk; } +// JitAllocator - Write Scope +// ========================== + +Error JitAllocator::beginWriteScope(WriteScopeData& scope, VirtMem::CachePolicy policy) noexcept { + scope._allocator = this; + scope._data[0] = size_t(policy); + return kErrorOk; +} + +Error JitAllocator::endWriteScope(WriteScopeData& scope) noexcept { + if (ASMJIT_UNLIKELY(!scope._allocator)) + return DebugUtils::errored(kErrorInvalidArgument); + + return kErrorOk; +} + +Error JitAllocator::flushWriteScope(WriteScopeData& scope) noexcept { + if (ASMJIT_UNLIKELY(!scope._allocator)) + return DebugUtils::errored(kErrorInvalidArgument); + + return kErrorOk; +} + +Error JitAllocator::scopedWrite(WriteScopeData& scope, Span& span, size_t offset, const void* src, size_t size) noexcept { + if (ASMJIT_UNLIKELY(!scope._allocator)) + return DebugUtils::errored(kErrorInvalidArgument); + + VirtMem::CachePolicy policy = VirtMem::CachePolicy(scope._data[0]); + return scope._allocator->write(span, offset, src, size, policy); +} + +Error JitAllocator::scopedWrite(WriteScopeData& scope, Span& span, WriteFunc writeFunc, void* userData) noexcept { + if (ASMJIT_UNLIKELY(!scope._allocator)) + return DebugUtils::errored(kErrorInvalidArgument); + + VirtMem::CachePolicy policy = VirtMem::CachePolicy(scope._data[0]); + return scope._allocator->write(span, writeFunc, userData, policy); +} + // JitAllocator - Tests // ==================== @@ -963,6 +1196,34 @@ public: uint64_t _state[2]; }; +namespace JitAllocatorUtils { + static void fillPattern64(void* p_, uint64_t pattern, size_t sizeInBytes) noexcept { + uint64_t* p = static_cast<uint64_t*>(p_); + size_t n = sizeInBytes / 8u; + + for (size_t i = 0; i < n; i++) + p[i] = pattern; + } + + static bool verifyPattern64(const void* p_, uint64_t pattern, size_t sizeInBytes) noexcept { + const uint64_t* p = static_cast<const uint64_t*>(p_); + size_t n = sizeInBytes / 8u; + + for (size_t i = 0; i < n; i++) { + if (p[i] != pattern) { + INFO("Pattern verification failed at 0x%p [%zu * 8]: value(0x%016llX) != expected(0x%016llX)", + p, + i, + (unsigned long long)p[i], + (unsigned long long)pattern); + return false; + } + } + + return true; + } +} + // Helper class to verify that JitAllocator doesn't return addresses that overlap. class JitAllocatorWrapper { public: @@ -980,9 +1241,19 @@ public: class Record : public ZoneTreeNodeT<Record>, public Range { public: - inline Record(uint8_t* addr, size_t size) + //! Read/write address, in case this is a dual mapping. + void* _rw; + //! Describes a pattern used to fill the allocated memory. + uint64_t pattern; + + inline Record(void* rx, void* rw, size_t size, uint64_t pattern) : ZoneTreeNodeT<Record>(), - Range(addr, size) {} + Range(static_cast<uint8_t*>(rx), size), + _rw(rw), + pattern(pattern) {} + + inline void* rx() const noexcept { return addr; } + inline void* rw() const noexcept { return _rw; } inline bool operator<(const Record& other) const noexcept { return addr < other.addr; } inline bool operator>(const Record& other) const noexcept { return addr > other.addr; } @@ -995,65 +1266,82 @@ public: ZoneAllocator _heap; ZoneTree<Record> _records; JitAllocator _allocator; + Random _rng; explicit JitAllocatorWrapper(const JitAllocator::CreateParams* params) noexcept : _zone(1024 * 1024), _heap(&_zone), - _allocator(params) {} + _allocator(params), + _rng(0x123456789u) {} - void _insert(void* p_, size_t size) noexcept { - uint8_t* p = static_cast<uint8_t*>(p_); + void _insert(void* pRX, void* pRW, size_t size) noexcept { + uint8_t* p = static_cast<uint8_t*>(pRX); uint8_t* pEnd = p + size - 1; Record* record; record = _records.get(p); - if (record) - EXPECT(record == nullptr, "Address [%p:%p] collides with a newly allocated [%p:%p]\n", record->addr, record->addr + record->size, p, p + size); + EXPECT_NULL(record) + .message("Address [%p:%p] collides with a newly allocated [%p:%p]\n", record->addr, record->addr + record->size, p, p + size); record = _records.get(pEnd); - if (record) - EXPECT(record == nullptr, "Address [%p:%p] collides with a newly allocated [%p:%p]\n", record->addr, record->addr + record->size, p, p + size); + EXPECT_NULL(record) + .message("Address [%p:%p] collides with a newly allocated [%p:%p]\n", record->addr, record->addr + record->size, p, p + size); + + uint64_t pattern = _rng.nextUInt64(); + record = _heap.newT<Record>(pRX, pRW, size, pattern); + EXPECT_NOT_NULL(record); + + { + VirtMem::ProtectJitReadWriteScope scope(pRW, size); + JitAllocatorUtils::fillPattern64(pRW, pattern, size); + } - record = _heap.newT<Record>(p, size); - EXPECT(record != nullptr, "Out of memory, cannot allocate 'Record'"); + VirtMem::flushInstructionCache(pRX, size); + EXPECT_TRUE(JitAllocatorUtils::verifyPattern64(pRX, pattern, size)); _records.insert(record); } void _remove(void* p) noexcept { Record* record = _records.get(static_cast<uint8_t*>(p)); - EXPECT(record != nullptr, "Address [%p] doesn't exist\n", p); + EXPECT_NOT_NULL(record); + + EXPECT_TRUE(JitAllocatorUtils::verifyPattern64(record->rx(), record->pattern, record->size)); + EXPECT_TRUE(JitAllocatorUtils::verifyPattern64(record->rw(), record->pattern, record->size)); _records.remove(record); _heap.release(record, sizeof(Record)); } void* alloc(size_t size) noexcept { - void* rxPtr; - void* rwPtr; - - Error err = _allocator.alloc(&rxPtr, &rwPtr, size); - EXPECT(err == kErrorOk, "JitAllocator failed to allocate %zu bytes\n", size); + JitAllocator::Span span; + Error err = _allocator.alloc(span, size); + EXPECT_EQ(err, kErrorOk) + .message("JitAllocator failed to allocate %zu bytes\n", size); - _insert(rxPtr, size); - return rxPtr; + _insert(span.rx(), span.rw(), size); + return span.rx(); } void release(void* p) noexcept { _remove(p); - EXPECT(_allocator.release(p) == kErrorOk, "JitAllocator failed to release '%p'\n", p); + EXPECT_EQ(_allocator.release(p), kErrorOk) + .message("JitAllocator failed to release '%p'\n", p); } void shrink(void* p, size_t newSize) noexcept { Record* record = _records.get(static_cast<uint8_t*>(p)); - EXPECT(record != nullptr, "Address [%p] doesn't exist\n", p); + EXPECT_NOT_NULL(record); if (!newSize) return release(p); - Error err = _allocator.shrink(p, newSize); - EXPECT(err == kErrorOk, "JitAllocator failed to shrink %p to %zu bytes\n", p, newSize); + JitAllocator::Span span; + EXPECT_EQ(_allocator.query(span, p), kErrorOk); + Error err = _allocator.shrink(span, newSize); + EXPECT_EQ(err, kErrorOk) + .message("JitAllocator failed to shrink %p to %zu bytes\n", p, newSize); record->size = newSize; } @@ -1095,13 +1383,19 @@ static void BitVectorRangeIterator_testRandom(Random& rnd, size_t count) noexcep } for (size_t j = 0; j < kPatternSize; j++) { - EXPECT(in[j] == out[j], "Invalid pattern detected at [%zu] (%llX != %llX)", j, (unsigned long long)in[j], (unsigned long long)out[j]); + EXPECT_EQ(in[j], out[j]) + .message("Invalid pattern detected at [%zu] (%llX != %llX)", j, (unsigned long long)in[j], (unsigned long long)out[j]); } } } -UNIT(jit_allocator) { - size_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 100000; +static void test_jit_allocator_reset_empty() noexcept { + JitAllocator allocator; + allocator.reset(ResetPolicy::kSoft); +} + +static void test_jit_allocator_alloc_release() noexcept { + size_t kCount = BrokenAPI::hasArg("--quick") ? 20000 : 100000; struct TestParams { const char* name; @@ -1110,15 +1404,23 @@ UNIT(jit_allocator) { uint32_t granularity; }; - static TestParams testParams[] = { - { "Default", JitAllocatorOptions::kNone, 0, 0 }, - { "16MB blocks", JitAllocatorOptions::kNone, 16 * 1024 * 1024, 0 }, - { "256B granularity", JitAllocatorOptions::kNone, 0, 256 }, - { "kUseDualMapping", JitAllocatorOptions::kUseDualMapping, 0, 0 }, - { "kUseMultiplePools", JitAllocatorOptions::kUseMultiplePools, 0, 0 }, - { "kFillUnusedMemory", JitAllocatorOptions::kFillUnusedMemory, 0, 0 }, - { "kImmediateRelease", JitAllocatorOptions::kImmediateRelease, 0, 0 }, - { "kUseDualMapping | kFillUnusedMemory", JitAllocatorOptions::kUseDualMapping | JitAllocatorOptions::kFillUnusedMemory, 0, 0 } + using Opt = JitAllocatorOptions; + + VirtMem::HardenedRuntimeInfo hri = VirtMem::hardenedRuntimeInfo(); + + TestParams testParams[] = { + { "Default" , Opt::kNone, 0, 0 }, + { "16MB blocks" , Opt::kNone, 16 * 1024 * 1024, 0 }, + { "256B granularity" , Opt::kNone, 0, 256 }, + { "kUseMultiplePools" , Opt::kUseMultiplePools, 0, 0 }, + { "kFillUnusedMemory" , Opt::kFillUnusedMemory, 0, 0 }, + { "kImmediateRelease" , Opt::kImmediateRelease, 0, 0 }, + { "kDisableInitialPadding" , Opt::kDisableInitialPadding, 0, 0 }, + { "kUseLargePages" , Opt::kUseLargePages, 0, 0 }, + { "kUseLargePages | kFillUnusedMemory" , Opt::kUseLargePages | Opt::kFillUnusedMemory, 0, 0 }, + { "kUseLargePages | kAlignBlockSizeToLargePage", Opt::kUseLargePages | Opt::kAlignBlockSizeToLargePage, 0, 0 }, + { "kUseDualMapping" , Opt::kUseDualMapping , 0, 0 }, + { "kUseDualMapping | kFillUnusedMemory" , Opt::kUseDualMapping | Opt::kFillUnusedMemory, 0, 0 } }; INFO("BitVectorRangeIterator<uint32_t>"); @@ -1134,6 +1436,12 @@ UNIT(jit_allocator) { } for (uint32_t testId = 0; testId < ASMJIT_ARRAY_SIZE(testParams); testId++) { + // Don't try to allocate dual-mapping if dual mapping is not possible - it would fail the test. + if (Support::test(testParams[testId].options, JitAllocatorOptions::kUseDualMapping) && + !Support::test(hri.flags, VirtMem::HardenedRuntimeFlags::kDualMapping)) { + continue; + } + INFO("JitAllocator(%s)", testParams[testId].name); JitAllocator::CreateParams params {}; @@ -1151,8 +1459,7 @@ UNIT(jit_allocator) { INFO(" Memory alloc/release test - %d allocations", kCount); void** ptrArray = (void**)::malloc(sizeof(void*) * size_t(kCount)); - EXPECT(ptrArray != nullptr, - "Couldn't allocate '%u' bytes for pointer-array", unsigned(sizeof(void*) * size_t(kCount))); + EXPECT_NOT_NULL(ptrArray); // Random blocks tests... INFO(" Allocating random blocks..."); @@ -1235,8 +1542,30 @@ UNIT(jit_allocator) { ::free(ptrArray); } } -#endif + +static void test_jit_allocator_query() noexcept { + JitAllocator allocator; + size_t allocatedSize = 100; + + JitAllocator::Span allocatedSpan; + EXPECT_EQ(allocator.alloc(allocatedSpan, allocatedSize), kErrorOk); + EXPECT_NOT_NULL(allocatedSpan.rx()); + EXPECT_GE(allocatedSpan.size(), allocatedSize); + + JitAllocator::Span queriedSpan; + EXPECT_EQ(allocator.query(queriedSpan, allocatedSpan.rx()), kErrorOk); + EXPECT_EQ(allocatedSpan.rx(), queriedSpan.rx()); + EXPECT_EQ(allocatedSpan.rw(), queriedSpan.rw()); + EXPECT_EQ(allocatedSpan.size(), queriedSpan.size()); +} + +UNIT(jit_allocator) { + test_jit_allocator_reset_empty(); + test_jit_allocator_alloc_release(); + test_jit_allocator_query(); +} +#endif // ASMJIT_TEST ASMJIT_END_NAMESPACE -#endif +#endif // !ASMJIT_NO_JIT diff --git a/3rdparty/asmjit/src/asmjit/core/jitallocator.h b/3rdparty/asmjit/src/asmjit/core/jitallocator.h index e8fe69519ee..b694f8cd535 100644 --- a/3rdparty/asmjit/src/asmjit/core/jitallocator.h +++ b/3rdparty/asmjit/src/asmjit/core/jitallocator.h @@ -10,6 +10,7 @@ #ifndef ASMJIT_NO_JIT #include "../core/globals.h" +#include "../core/support.h" #include "../core/virtmem.h" ASMJIT_BEGIN_NAMESPACE @@ -26,6 +27,10 @@ enum class JitAllocatorOptions : uint32_t { //! The first buffer has read and execute permissions and the second buffer has read+write permissions. //! //! See \ref VirtMem::allocDualMapping() for more details about this feature. + //! + //! \remarks Dual mapping would be automatically turned on by \ref JitAllocator in case of hardened runtime that + //! enforces `W^X` policy, so specifying this flag is essentially forcing to use dual mapped pages even when RWX + //! pages can be allocated and dual mapping is not necessary. kUseDualMapping = 0x00000001u, //! Enables the use of multiple pools with increasing granularity instead of a single pool. This flag would enable @@ -50,6 +55,40 @@ enum class JitAllocatorOptions : uint32_t { //! or have all blocks fully occupied. kImmediateRelease = 0x00000008u, + //! This flag enables placing functions (or allocating memory) at the very beginning of each memory mapped region. + //! + //! Initially, this was the default behavior. However, LLVM developers working on undefined behavior sanitizer + //! (UBSAN) decided that they want to store metadata before each function and to access such metadata before an + //! indirect function call. This means that the instrumented code always reads from `[fnPtr - 8]` to decode whether + //! the function has his metadata present. However, reading 8 bytes below a function means that if a function is + //! placed at the very beginning of a memory mapped region, it could try to read bytes that are inaccessible. And + //! since AsmJit can be compiled as a shared library and used by applications instrumented by UBSAN, it's not + //! possible to conditionally compile the support only when necessary. + //! + //! \remarks This flag controls a workaround to make it possible to use LLVM UBSAN with AsmJit's \ref JitAllocator. + //! There is no undefined behavior even when `kDisableInitialPadding` is used, however, that doesn't really matter + //! as LLVM's UBSAN introduces one, and according to LLVM developers it's a "trade-off". This flag is safe to use + //! when the code is not instrumented with LLVM's UBSAN. + kDisableInitialPadding = 0x00000010u, + + //! Enables the use of large pages, if they are supported and the process can actually allocate them. + //! + //! \remarks This flag is a hint - if large pages can be allocated, JitAllocator would try to allocate them. + //! However, if the allocation fails, it will still try to fallback to use regular pages as \ref JitAllocator + //! is designed to minimize allocation failures, so a regular page is better than no page at all. Also, if a + //! block \ref JitAllocator wants to allocate is too small to consume a whole large page, regular page(s) will + //! be allocated as well. + kUseLargePages = 0x00000020u, + + //! Forces \ref JitAllocator to always align block size to be at least as big as a large page, if large pages are + //! enabled. This option does nothing if large pages are disabled. + //! + //! \remarks If \ref kUseLargePages option is used, the allocator would prefer large pages only when allocating a + //! block that has a sufficient size. Usually the allocator first allocates smaller block and when more requests + //! come it will start increasing the block size of next allocations. This option makes it sure that even the first + //! allocation would be the same as a minimum large page when large pages are enabled and can be allocated. + kAlignBlockSizeToLargePage = 0x00000040u, + //! Use a custom fill pattern, must be combined with `kFlagFillUnusedMemory`. kCustomFillPattern = 0x10000000u }; @@ -75,6 +114,7 @@ class JitAllocator { public: ASMJIT_NONCOPYABLE(JitAllocator) + //! Visible \ref JitAllocator implementation data. struct Impl { //! Allocator options. JitAllocatorOptions options; @@ -86,9 +126,14 @@ public: uint32_t fillPattern; }; + //! \name Members + //! \{ + //! Allocator implementation (private). Impl* _impl; + //! \} + //! \name Construction & Destruction //! \{ @@ -129,7 +174,7 @@ public: uint32_t fillPattern = 0; // Reset the content of `CreateParams`. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = CreateParams{}; } }; //! Creates a `JitAllocator` instance. @@ -137,7 +182,7 @@ public: //! Destroys the `JitAllocator` instance and release all blocks held. ASMJIT_API ~JitAllocator() noexcept; - inline bool isInitialized() const noexcept { return _impl->blockSize == 0; } + ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _impl->blockSize == 0; } //! Free all allocated memory - makes all pointers returned by `alloc()` invalid. //! @@ -151,47 +196,315 @@ public: //! \{ //! Returns allocator options, see `Flags`. - inline JitAllocatorOptions options() const noexcept { return _impl->options; } + ASMJIT_INLINE_NODEBUG JitAllocatorOptions options() const noexcept { return _impl->options; } //! Tests whether the allocator has the given `option` set. - inline bool hasOption(JitAllocatorOptions option) const noexcept { return uint32_t(_impl->options & option) != 0; } + ASMJIT_INLINE_NODEBUG bool hasOption(JitAllocatorOptions option) const noexcept { return uint32_t(_impl->options & option) != 0; } //! Returns a base block size (a minimum size of block that the allocator would allocate). - inline uint32_t blockSize() const noexcept { return _impl->blockSize; } + ASMJIT_INLINE_NODEBUG uint32_t blockSize() const noexcept { return _impl->blockSize; } //! Returns granularity of the allocator. - inline uint32_t granularity() const noexcept { return _impl->granularity; } + ASMJIT_INLINE_NODEBUG uint32_t granularity() const noexcept { return _impl->granularity; } //! Returns pattern that is used to fill unused memory if `kFlagUseFillPattern` is set. - inline uint32_t fillPattern() const noexcept { return _impl->fillPattern; } + ASMJIT_INLINE_NODEBUG uint32_t fillPattern() const noexcept { return _impl->fillPattern; } //! \} //! \name Alloc & Release //! \{ - //! Allocates a new memory block of the requested `size`. + //! A memory reference returned by \ref JitAllocator::alloc(). //! - //! When the function is successful it stores two pointers in `rxPtrOut` and `rwPtrOut`. The pointers will be - //! different only if `kOptionUseDualMapping` was used to setup the allocator (in that case the `rxPtrOut` would - //! point to a Read+Execute region and `rwPtrOut` would point to a Read+Write region of the same memory-mapped block. - ASMJIT_API Error alloc(void** rxPtrOut, void** rwPtrOut, size_t size) noexcept; + //! Span contains everything needed to actually write new code to the memory chunk it references. + class Span { + public: + //! \name Constants + //! \{ + + //! Span flags + enum class Flags : uint32_t { + //! No flags. + kNone = 0u, + + //! The process has never executed the region of the span. + //! + //! If this flag is set on a \ref Span it would mean that the allocator can avoid flushing + //! instruction cache after a code has been written to it. + kInstructionCacheClean = 0x00000001u + }; + + //! \} + + //! \name Members + //! \{ + + //! Address of memory that has Read and Execute permissions. + void* _rx = nullptr; + + //! Address of memory that has Read and Write permissions. + void* _rw = nullptr; + + //! Size of the span in bytes (rounded up to the allocation granularity). + size_t _size = 0; + + //! Pointer that references a memory block maintained by \ref JitAllocator. + //! + //! This pointer is considered private and should never be used nor inspected outside of AsmJit. + void* _block = nullptr; + + //! Span flags. + Flags _flags = Flags::kNone; + + //! Reserved for future use. + uint32_t _reserved = 0; + + //! \} + + //! \name Accessors + //! \{ + + //! Returns a pointer having Read & Execute permissions (references executable memory). + //! + //! This pointer is never NULL if the allocation succeeded, it points to an executable memory. + ASMJIT_INLINE_NODEBUG void* rx() const noexcept { return _rx; } + + //! Returns a pointer having Read & Write permissions (references writable memory). + //! + //! Depending on the type of the allocation strategy this could either be: + //! + //! - the same address as returned by `rx()` if the allocator uses RWX mapping (pages have all of Read, Write, + //! and Execute permissions) or MAP_JIT, which requires either \ref VirtMem::ProtectJitReadWriteScope or to + //! call \ref VirtMem::protectJitMemory() manually. + //! - a valid pointer, but not the same as `rx` - this would be valid if dual mapping is used. + //! - NULL pointer, in case that the allocation strategy doesn't use RWX, MAP_JIT, or dual mapping. In this + //! case only \ref JitAllocator can copy new code into the executable memory referenced by \ref Span. + //! + //! \note If `rw()` returns a non-null pointer it's important to use either VirtMem::protectJitMemory() or + //! \ref VirtMem::ProtectJitReadWriteScope to guard the write, because in case of `MAP_JIT` it would temporarily + //! switch the permissions of the pointer to RW (that's per thread permissions). + //! + //! If \ref VirtMem::ProtectJitReadWriteScope is not used it's important to clear the instruction cache via + //! \ref VirtMem::flushInstructionCache() after the write is done. + ASMJIT_INLINE_NODEBUG void* rw() const noexcept { return _rw; } + + //! Returns size of this span, aligned to the allocator granularity. + ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; } + + //! Returns span flags. + ASMJIT_INLINE_NODEBUG Flags flags() const noexcept { return _flags; } + + //! Shrinks this span to `newSize`. + //! + //! \note This is the only function that is able to change the size of a span, and it's only use case is to + //! shrink the span size during \ref JitAllocator::write(). When the writer detects that the span size shrunk, + //! it will automatically shrink the memory used by the span, and propagate the new aligned size to the caller. + ASMJIT_INLINE_NODEBUG void shrink(size_t newSize) noexcept { _size = Support::min(_size, newSize); } + + //! Returns whether \ref rw() returns a non-null pointer. + ASMJIT_INLINE_NODEBUG bool isDirectlyWritable() const noexcept { return _rw != nullptr; } + + //! \} + }; + + //! Allocates a new memory span of the requested `size`. + ASMJIT_API Error alloc(Span& out, size_t size) noexcept; //! Releases a memory block returned by `alloc()`. //! //! \remarks This function is thread-safe. - ASMJIT_API Error release(void* rxPtr) noexcept; + ASMJIT_API Error release(void* rx) noexcept; - //! Frees extra memory allocated with `rxPtr` by shrinking it to the given `newSize`. + //! Frees extra memory allocated with `rx` by shrinking it to the given `newSize`. //! //! \remarks This function is thread-safe. - ASMJIT_API Error shrink(void* rxPtr, size_t newSize) noexcept; + ASMJIT_API Error shrink(Span& span, size_t newSize) noexcept; - //! Queries information about an allocated memory block that contains the given `rxPtr`. + //! Queries information about an allocated memory block that contains the given `rx`, and writes it to `out`. //! - //! The function returns `kErrorOk` when `rxPtr` is matched and fills `rxPtrOut`, `rwPtrOut`, and `sizeOut` output - //! arguments. The returned `rxPtrOut` and `rwPtrOut` pointers point to the beginning of the block, and `sizeOut` - //! describes the total amount of bytes this allocation uses - `sizeOut` will always be aligned to the allocation - //! granularity, so for example if an allocation was 1 byte and the size granularity is 64, the returned `sizeOut` - //! will be 64 bytes, because that's what the allocator sees. - ASMJIT_API Error query(void* rxPtr, void** rxPtrOut, void** rwPtrOut, size_t* sizeOut) const noexcept; + //! If the pointer is matched, the function returns `kErrorOk` and fills `out` with the corresponding span. + ASMJIT_API Error query(Span& out, void* rx) const noexcept; + +#if !defined(ASMJIT_NO_DEPRECATED) + //! Allocates a new memory block of the requested `size`. + ASMJIT_DEPRECATED("Use alloc(Span& out, size_t size) instead") + ASMJIT_FORCE_INLINE Error alloc(void** rxPtrOut, void** rwPtrOut, size_t size) noexcept { + Span span; + Error err = alloc(span, size); + *rwPtrOut = span.rw(); + *rxPtrOut = span.rx(); + return err; + } + + ASMJIT_DEPRECATED("Use shrink(Span& span, size_t newSize) instead") + ASMJIT_FORCE_INLINE Error shrink(void* rxPtr, size_t newSize) noexcept { + Span span; + ASMJIT_PROPAGATE(query(span, rxPtr)); + return (span.size() > newSize) ? shrink(span, newSize) : Error(kErrorOk); + } + + ASMJIT_DEPRECATED("Use query(Span& out, void* rx) instead") + ASMJIT_FORCE_INLINE Error query(void* rxPtr, void** rxPtrOut, void** rwPtrOut, size_t* sizeOut) const noexcept { + Span span; + Error err = query(span, rxPtr); + *rxPtrOut = span.rx(); + *rwPtrOut = span.rw(); + *sizeOut = span.size(); + return err; + } +#endif + + //! \} + + //! \name Write Operations + //! \{ + + typedef Error (ASMJIT_CDECL* WriteFunc)(Span& span, void* userData) ASMJIT_NOEXCEPT_TYPE; + + ASMJIT_API Error write( + Span& span, + size_t offset, + const void* src, + size_t size, + VirtMem::CachePolicy policy = VirtMem::CachePolicy::kDefault) noexcept; + + ASMJIT_API Error write( + Span& span, + WriteFunc writeFunc, + void* userData, + VirtMem::CachePolicy policy = VirtMem::CachePolicy::kDefault) noexcept; + + template<class Lambda> + ASMJIT_FORCE_INLINE Error write( + Span& span, + Lambda&& lambdaFunc, + VirtMem::CachePolicy policy = VirtMem::CachePolicy::kDefault) noexcept { + + WriteFunc wrapperFunc = [](Span& span, void* userData) noexcept -> Error { + Lambda& lambdaFunc = *static_cast<Lambda*>(userData); + return lambdaFunc(span); + }; + return write(span, wrapperFunc, (void*)(&lambdaFunc), policy); + } + + //! \} + + //! \name Write Operations with Scope + //! \{ + + //! \cond INTERNAL + + //! Write scope data. + //! + //! This is mostly for internal purposes, please use \ref WriteScope instead. + struct WriteScopeData { + //! \name Members + //! \{ + + //! Link to the allocator. + JitAllocator* _allocator; + //! Cache policy passed to \ref JitAllocator::beginWriteScope(). + VirtMem::CachePolicy _policy; + //! Internal flags used by the implementation. + uint32_t _flags; + //! Internal data used by the implementation. + size_t _data[64]; + + //! \} + }; + + //! Begins a write `scope`. + //! + //! This is mostly for internal purposes, please use \ref WriteScope constructor instead. + ASMJIT_API Error beginWriteScope(WriteScopeData& scope, VirtMem::CachePolicy policy = VirtMem::CachePolicy::kDefault) noexcept; + + //! Ends a write `scope`. + //! + //! This is mostly for internal purposes, please use \ref WriteScope destructor instead. + ASMJIT_API Error endWriteScope(WriteScopeData& scope) noexcept; + + //! Flushes accumulated changes in a write `scope`. + //! + //! This is mostly for internal purposes, please use \ref WriteScope destructor or \ref WriteScope::flush() instead. + ASMJIT_API Error flushWriteScope(WriteScopeData& scope) noexcept; + + //! Alternative to `JitAllocator::write(span, offset, src, size)`, but under a write `scope`. + //! + //! This is mostly for internal purposes, please use \ref WriteScope::write() instead. + ASMJIT_API Error scopedWrite(WriteScopeData& scope, Span& span, size_t offset, const void* src, size_t size) noexcept; + + //! Alternative to `JitAllocator::write(span, writeFunc, userData)`, but under a write `scope`. + //! + //! This is mostly for internal purposes, please use \ref WriteScope::write() instead. + ASMJIT_API Error scopedWrite(WriteScopeData& scope, Span& span, WriteFunc writeFunc, void* userData) noexcept; + + //! Alternative to `JitAllocator::write(span, [lambda])`, but under a write `scope`. + //! + //! This is mostly for internal purposes, please use \ref WriteScope::write() instead. + template<class Lambda> + inline Error scopedWrite(WriteScopeData& scope, Span& span, Lambda&& lambdaFunc) noexcept { + WriteFunc wrapperFunc = [](Span& span, void* userData) noexcept -> Error { + Lambda& lambdaFunc = *static_cast<Lambda*>(userData); + return lambdaFunc(span); + }; + return scopedWrite(scope, span, wrapperFunc, (void*)(&lambdaFunc)); + } + + //! \endcond + + //! Write scope can be used to create a single scope that is optimized for writing multiple spans. + class WriteScope : public WriteScopeData { + public: + ASMJIT_NONCOPYABLE(WriteScope) + + //! \name Construction & Destruction + //! \{ + + // Begins a write scope. + inline explicit WriteScope(JitAllocator* allocator, VirtMem::CachePolicy policy = VirtMem::CachePolicy::kDefault) noexcept { + allocator->beginWriteScope(*this, policy); + } + + // Ends a write scope. + inline ~WriteScope() noexcept { + if (_allocator) + _allocator->endWriteScope(*this); + } + + //! \} + + //! \name Accessors + //! \{ + + ASMJIT_INLINE_NODEBUG JitAllocator* allocator() const noexcept { return _allocator; } + ASMJIT_INLINE_NODEBUG VirtMem::CachePolicy policy() const noexcept { return _policy; } + + //! \} + + //! \name Operations + //! \{ + + //! Similar to `JitAllocator::write(span, offset, src, size)`, but under a write scope. + ASMJIT_INLINE_NODEBUG Error write(Span& span, size_t offset, const void* src, size_t size) noexcept { + return _allocator->scopedWrite(*this, span, offset, src, size); + } + + //! Similar to `JitAllocator::write(span, writeFunc, userData)`, but under a write scope. + ASMJIT_INLINE_NODEBUG Error write(Span& span, WriteFunc writeFunc, void* userData) noexcept { + return _allocator->scopedWrite(*this, span, writeFunc, userData); + } + + //! Similar to `JitAllocator::write(span, <lambda>)`, but under a write scope. + template<class Lambda> + ASMJIT_INLINE_NODEBUG Error write(Span& span, Lambda&& lambdaFunc) noexcept { + return _allocator->scopedWrite(*this, span, lambdaFunc); + } + + //! Flushes accumulated changes in this write scope. + ASMJIT_INLINE_NODEBUG Error flush() noexcept { + return _allocator->flushWriteScope(*this); + } + + //! \} + }; //! \} @@ -211,36 +524,32 @@ public: //! Allocation overhead (in bytes) required to maintain all blocks. size_t _overheadSize; - inline void reset() noexcept { - _blockCount = 0; - _usedSize = 0; - _reservedSize = 0; - _overheadSize = 0; - } + //! Resets the statistics to all zeros. + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = Statistics{}; } //! Returns count of blocks managed by `JitAllocator` at the moment. - inline size_t blockCount() const noexcept { return _blockCount; } + ASMJIT_INLINE_NODEBUG size_t blockCount() const noexcept { return _blockCount; } //! Returns the number of active allocations. - inline size_t allocationCount() const noexcept { return _allocationCount; } + ASMJIT_INLINE_NODEBUG size_t allocationCount() const noexcept { return _allocationCount; } //! Returns how many bytes are currently used. - inline size_t usedSize() const noexcept { return _usedSize; } + ASMJIT_INLINE_NODEBUG size_t usedSize() const noexcept { return _usedSize; } //! Returns the number of bytes unused by the allocator at the moment. - inline size_t unusedSize() const noexcept { return _reservedSize - _usedSize; } - //! Returns the total number of bytes bytes reserved by the allocator (sum of sizes of all blocks). - inline size_t reservedSize() const noexcept { return _reservedSize; } + ASMJIT_INLINE_NODEBUG size_t unusedSize() const noexcept { return _reservedSize - _usedSize; } + //! Returns the total number of bytes reserved by the allocator (sum of sizes of all blocks). + ASMJIT_INLINE_NODEBUG size_t reservedSize() const noexcept { return _reservedSize; } //! Returns the number of bytes the allocator needs to manage the allocated memory. - inline size_t overheadSize() const noexcept { return _overheadSize; } + ASMJIT_INLINE_NODEBUG size_t overheadSize() const noexcept { return _overheadSize; } - inline double usedSizeAsPercent() const noexcept { + ASMJIT_INLINE_NODEBUG double usedSizeAsPercent() const noexcept { return (double(usedSize()) / (double(reservedSize()) + 1e-16)) * 100.0; } - inline double unusedSizeAsPercent() const noexcept { + ASMJIT_INLINE_NODEBUG double unusedSizeAsPercent() const noexcept { return (double(unusedSize()) / (double(reservedSize()) + 1e-16)) * 100.0; } - inline double overheadSizeAsPercent() const noexcept { + ASMJIT_INLINE_NODEBUG double overheadSizeAsPercent() const noexcept { return (double(overheadSize()) / (double(reservedSize()) + 1e-16)) * 100.0; } }; diff --git a/3rdparty/asmjit/src/asmjit/core/jitruntime.cpp b/3rdparty/asmjit/src/asmjit/core/jitruntime.cpp index 491c2040fbe..0cc026987a2 100644 --- a/3rdparty/asmjit/src/asmjit/core/jitruntime.cpp +++ b/3rdparty/asmjit/src/asmjit/core/jitruntime.cpp @@ -15,6 +15,7 @@ JitRuntime::JitRuntime(const JitAllocator::CreateParams* params) noexcept : _allocator(params) { _environment = Environment::host(); _environment.setObjectFormat(ObjectFormat::kJIT); + _cpuFeatures = CpuInfo::host().features(); } JitRuntime::~JitRuntime() noexcept {} @@ -29,45 +30,43 @@ Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { if (ASMJIT_UNLIKELY(estimatedCodeSize == 0)) return DebugUtils::errored(kErrorNoCodeGenerated); - uint8_t* rx; - uint8_t* rw; - ASMJIT_PROPAGATE(_allocator.alloc((void**)&rx, (void**)&rw, estimatedCodeSize)); + JitAllocator::Span span; + ASMJIT_PROPAGATE(_allocator.alloc(span, estimatedCodeSize)); // Relocate the code. - Error err = code->relocateToBase(uintptr_t((void*)rx)); + Error err = code->relocateToBase(uintptr_t(span.rx())); if (ASMJIT_UNLIKELY(err)) { - _allocator.release(rx); + _allocator.release(span.rx()); return err; } // Recalculate the final code size and shrink the memory we allocated for it // in case that some relocations didn't require records in an address table. size_t codeSize = code->codeSize(); - if (codeSize < estimatedCodeSize) - _allocator.shrink(rx, codeSize); + ASMJIT_ASSERT(codeSize <= estimatedCodeSize); - if (codeSize < estimatedCodeSize) - _allocator.shrink(rx, codeSize); - - { - VirtMem::ProtectJitReadWriteScope rwScope(rx, codeSize); + _allocator.write(span, [&](JitAllocator::Span& span) noexcept -> Error { + uint8_t* rw = static_cast<uint8_t*>(span.rw()); for (Section* section : code->_sections) { size_t offset = size_t(section->offset()); size_t bufferSize = size_t(section->bufferSize()); size_t virtualSize = size_t(section->virtualSize()); - ASMJIT_ASSERT(offset + bufferSize <= codeSize); + ASMJIT_ASSERT(offset + bufferSize <= span.size()); memcpy(rw + offset, section->data(), bufferSize); if (virtualSize > bufferSize) { - ASMJIT_ASSERT(offset + virtualSize <= codeSize); + ASMJIT_ASSERT(offset + virtualSize <= span.size()); memset(rw + offset + bufferSize, 0, virtualSize - bufferSize); } } - } - *dst = rx; + span.shrink(codeSize); + return kErrorOk; + }); + + *dst = span.rx(); return kErrorOk; } diff --git a/3rdparty/asmjit/src/asmjit/core/jitruntime.h b/3rdparty/asmjit/src/asmjit/core/jitruntime.h index 6f35e21277a..717a6b58d6b 100644 --- a/3rdparty/asmjit/src/asmjit/core/jitruntime.h +++ b/3rdparty/asmjit/src/asmjit/core/jitruntime.h @@ -20,8 +20,10 @@ class CodeHolder; //! \addtogroup asmjit_virtual_memory //! \{ -//! JIT execution runtime is a special `Target` that is designed to store and -//! execute the generated code. +//! JIT execution runtime is a special `Target` that is designed to store and execute a generated code. +//! +//! JIT runtime is the easiest way of using AsmJit as it abstracts allocation and deallocation of virtual memory +//! where executable code can be placed and from which it can be executed as well. class ASMJIT_VIRTAPI JitRuntime : public Target { public: ASMJIT_NONCOPYABLE(JitRuntime) @@ -35,9 +37,19 @@ public: //! Creates a `JitRuntime` instance. ASMJIT_API explicit JitRuntime(const JitAllocator::CreateParams* params = nullptr) noexcept; //! Destroys the `JitRuntime` instance. - ASMJIT_API virtual ~JitRuntime() noexcept; + ASMJIT_API ~JitRuntime() noexcept override; - inline void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept { + //! \} + + //! \name Accessors + //! \{ + + //! Resets the \ref JitRuntime, freeing everything that was allocated by it. + //! + //! Depending on `resetPolicy` the currently held memory can be either freed entirely when ResetPolicy::kHard is used, + //! or the allocator can keep some of it for next allocations when ResetPolicy::kSoft is used, which is the default + //! behavior. + ASMJIT_INLINE_NODEBUG void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept { _allocator.reset(resetPolicy); } @@ -47,7 +59,7 @@ public: //! \{ //! Returns the associated `JitAllocator`. - inline JitAllocator* allocator() const noexcept { return const_cast<JitAllocator*>(&_allocator); } + ASMJIT_INLINE_NODEBUG JitAllocator* allocator() const noexcept { return const_cast<JitAllocator*>(&_allocator); } //! \} @@ -62,13 +74,13 @@ public: //! The beginning of the memory allocated for the function is returned in `dst`. If failed `Error` code is returned //! and `dst` is explicitly set to `nullptr` (this means that you don't have to set it to null before calling `add()`). template<typename Func> - inline Error add(Func* dst, CodeHolder* code) noexcept { + ASMJIT_INLINE_NODEBUG Error add(Func* dst, CodeHolder* code) noexcept { return _add(Support::ptr_cast_impl<void**, Func*>(dst), code); } //! Releases `p` which was obtained by calling `add()`. template<typename Func> - inline Error release(Func p) noexcept { + ASMJIT_INLINE_NODEBUG Error release(Func p) noexcept { return _release(Support::ptr_cast_impl<void*, Func>(p)); } diff --git a/3rdparty/asmjit/src/asmjit/core/logger.cpp b/3rdparty/asmjit/src/asmjit/core/logger.cpp index 4567b3c9389..9bc14bae5fd 100644 --- a/3rdparty/asmjit/src/asmjit/core/logger.cpp +++ b/3rdparty/asmjit/src/asmjit/core/logger.cpp @@ -19,6 +19,14 @@ Logger::Logger() noexcept : _options() {} Logger::~Logger() noexcept {} +// [[pure virtual]] +Error Logger::_log(const char* data, size_t size) noexcept { + DebugUtils::unused(data, size); + + // Do not error in this case - the logger would just sink to /dev/null. + return kErrorOk; +} + Error Logger::logf(const char* fmt, ...) noexcept { Error err; va_list ap; diff --git a/3rdparty/asmjit/src/asmjit/core/logger.h b/3rdparty/asmjit/src/asmjit/core/logger.h index d416a50d84d..54c169f52fe 100644 --- a/3rdparty/asmjit/src/asmjit/core/logger.h +++ b/3rdparty/asmjit/src/asmjit/core/logger.h @@ -47,38 +47,38 @@ public: //! \{ //! Returns \ref FormatOptions of this logger. - inline FormatOptions& options() noexcept { return _options; } + ASMJIT_INLINE_NODEBUG FormatOptions& options() noexcept { return _options; } //! \overload - inline const FormatOptions& options() const noexcept { return _options; } + ASMJIT_INLINE_NODEBUG const FormatOptions& options() const noexcept { return _options; } //! Sets formatting options of this Logger to `options`. - inline void setOptions(const FormatOptions& options) noexcept { _options = options; } + ASMJIT_INLINE_NODEBUG void setOptions(const FormatOptions& options) noexcept { _options = options; } //! Resets formatting options of this Logger to defaults. - inline void resetOptions() noexcept { _options.reset(); } + ASMJIT_INLINE_NODEBUG void resetOptions() noexcept { _options.reset(); } //! Returns formatting flags. - inline FormatFlags flags() const noexcept { return _options.flags(); } + ASMJIT_INLINE_NODEBUG FormatFlags flags() const noexcept { return _options.flags(); } //! Tests whether the logger has the given `flag` enabled. - inline bool hasFlag(FormatFlags flag) const noexcept { return _options.hasFlag(flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(FormatFlags flag) const noexcept { return _options.hasFlag(flag); } //! Sets formatting flags to `flags`. - inline void setFlags(FormatFlags flags) noexcept { _options.setFlags(flags); } + ASMJIT_INLINE_NODEBUG void setFlags(FormatFlags flags) noexcept { _options.setFlags(flags); } //! Enables the given formatting `flags`. - inline void addFlags(FormatFlags flags) noexcept { _options.addFlags(flags); } + ASMJIT_INLINE_NODEBUG void addFlags(FormatFlags flags) noexcept { _options.addFlags(flags); } //! Disables the given formatting `flags`. - inline void clearFlags(FormatFlags flags) noexcept { _options.clearFlags(flags); } + ASMJIT_INLINE_NODEBUG void clearFlags(FormatFlags flags) noexcept { _options.clearFlags(flags); } //! Returns indentation of a given indentation `group`. - inline uint32_t indentation(FormatIndentationGroup type) const noexcept { return _options.indentation(type); } + ASMJIT_INLINE_NODEBUG uint32_t indentation(FormatIndentationGroup type) const noexcept { return _options.indentation(type); } //! Sets indentation of the given indentation `group` to `n` spaces. - inline void setIndentation(FormatIndentationGroup type, uint32_t n) noexcept { _options.setIndentation(type, n); } + ASMJIT_INLINE_NODEBUG void setIndentation(FormatIndentationGroup type, uint32_t n) noexcept { _options.setIndentation(type, n); } //! Resets indentation of the given indentation `group` to 0 spaces. - inline void resetIndentation(FormatIndentationGroup type) noexcept { _options.resetIndentation(type); } + ASMJIT_INLINE_NODEBUG void resetIndentation(FormatIndentationGroup type) noexcept { _options.resetIndentation(type); } //! Returns padding of a given padding `group`. - inline size_t padding(FormatPaddingGroup type) const noexcept { return _options.padding(type); } + ASMJIT_INLINE_NODEBUG size_t padding(FormatPaddingGroup type) const noexcept { return _options.padding(type); } //! Sets padding of a given padding `group` to `n`. - inline void setPadding(FormatPaddingGroup type, uint32_t n) noexcept { _options.setPadding(type, n); } + ASMJIT_INLINE_NODEBUG void setPadding(FormatPaddingGroup type, uint32_t n) noexcept { _options.setPadding(type, n); } //! Resets padding of a given padding `group` to 0, which means that a default will be used. - inline void resetPadding(FormatPaddingGroup type) noexcept { _options.resetPadding(type); } + ASMJIT_INLINE_NODEBUG void resetPadding(FormatPaddingGroup type) noexcept { _options.resetPadding(type); } //! \} @@ -90,12 +90,12 @@ public: //! The function can accept either a null terminated string if `size` is `SIZE_MAX` or a non-null terminated //! string of the given `size`. The function cannot assume that the data is null terminated and must handle //! non-null terminated inputs. - virtual Error _log(const char* data, size_t size) noexcept = 0; + ASMJIT_API virtual Error _log(const char* data, size_t size) noexcept; //! Logs string `str`, which is either null terminated or having size `size`. - inline Error log(const char* data, size_t size = SIZE_MAX) noexcept { return _log(data, size); } + ASMJIT_INLINE_NODEBUG Error log(const char* data, size_t size = SIZE_MAX) noexcept { return _log(data, size); } //! Logs content of a string `str`. - inline Error log(const String& str) noexcept { return _log(str.data(), str.size()); } + ASMJIT_INLINE_NODEBUG Error log(const String& str) noexcept { return _log(str.data(), str.size()); } //! Formats the message by using `snprintf()` and then passes the formatted string to \ref _log(). ASMJIT_API Error logf(const char* fmt, ...) noexcept; @@ -119,7 +119,7 @@ public: //! Creates a new `FileLogger` that logs to `FILE*`. ASMJIT_API FileLogger(FILE* file = nullptr) noexcept; //! Destroys the `FileLogger`. - ASMJIT_API virtual ~FileLogger() noexcept; + ASMJIT_API ~FileLogger() noexcept override; //! \} @@ -127,14 +127,14 @@ public: //! \{ //! Returns the logging output stream or null if the logger has no output stream. - inline FILE* file() const noexcept { return _file; } + ASMJIT_INLINE_NODEBUG FILE* file() const noexcept { return _file; } //! Sets the logging output stream to `stream` or null. //! //! \note If the `file` is null the logging will be disabled. When a logger is attached to `CodeHolder` or any //! emitter the logging API will always be called regardless of the output file. This means that if you really //! want to disable logging at emitter level you must not attach a logger to it. - inline void setFile(FILE* file) noexcept { _file = file; } + ASMJIT_INLINE_NODEBUG void setFile(FILE* file) noexcept { _file = file; } //! \} @@ -155,7 +155,7 @@ public: //! Create new `StringLogger`. ASMJIT_API StringLogger() noexcept; //! Destroys the `StringLogger`. - ASMJIT_API virtual ~StringLogger() noexcept; + ASMJIT_API ~StringLogger() noexcept override; //! \} @@ -165,16 +165,16 @@ public: //! Returns the content of the logger as \ref String. //! //! It can be moved, if desired. - inline String& content() noexcept { return _content; } + ASMJIT_INLINE_NODEBUG String& content() noexcept { return _content; } //! \overload - inline const String& content() const noexcept { return _content; } + ASMJIT_INLINE_NODEBUG const String& content() const noexcept { return _content; } //! Returns aggregated logger data as `char*` pointer. //! //! The pointer is owned by `StringLogger`, it can't be modified or freed. - inline const char* data() const noexcept { return _content.data(); } + ASMJIT_INLINE_NODEBUG const char* data() const noexcept { return _content.data(); } //! Returns size of the data returned by `data()`. - inline size_t dataSize() const noexcept { return _content.size(); } + ASMJIT_INLINE_NODEBUG size_t dataSize() const noexcept { return _content.size(); } //! \} @@ -182,7 +182,7 @@ public: //! \{ //! Clears the accumulated logger data. - inline void clear() noexcept { _content.clear(); } + ASMJIT_INLINE_NODEBUG void clear() noexcept { _content.clear(); } //! \} diff --git a/3rdparty/asmjit/src/asmjit/core/operand.cpp b/3rdparty/asmjit/src/asmjit/core/operand.cpp index ee026817f8e..b78dc54678a 100644 --- a/3rdparty/asmjit/src/asmjit/core/operand.cpp +++ b/3rdparty/asmjit/src/asmjit/core/operand.cpp @@ -19,36 +19,36 @@ enum class StrongEnumForImmTests : uint32_t { UNIT(operand) { INFO("Checking operand sizes"); - EXPECT(sizeof(Operand) == 16); - EXPECT(sizeof(BaseReg) == 16); - EXPECT(sizeof(BaseMem) == 16); - EXPECT(sizeof(Imm) == 16); - EXPECT(sizeof(Label) == 16); + EXPECT_EQ(sizeof(Operand), 16u); + EXPECT_EQ(sizeof(BaseReg), 16u); + EXPECT_EQ(sizeof(BaseMem), 16u); + EXPECT_EQ(sizeof(Imm), 16u); + EXPECT_EQ(sizeof(Label), 16u); INFO("Checking basic functionality of Operand"); Operand a, b; Operand dummy; - EXPECT(a.isNone() == true); - EXPECT(a.isReg() == false); - EXPECT(a.isMem() == false); - EXPECT(a.isImm() == false); - EXPECT(a.isLabel() == false); - EXPECT(a == b); - EXPECT(a._data[0] == 0); - EXPECT(a._data[1] == 0); + EXPECT_TRUE(a.isNone()); + EXPECT_FALSE(a.isReg()); + EXPECT_FALSE(a.isMem()); + EXPECT_FALSE(a.isImm()); + EXPECT_FALSE(a.isLabel()); + EXPECT_EQ(a, b); + EXPECT_EQ(a._data[0], 0u); + EXPECT_EQ(a._data[1], 0u); INFO("Checking basic functionality of Label"); Label label; - EXPECT(label.isValid() == false); - EXPECT(label.id() == Globals::kInvalidId); + EXPECT_FALSE(label.isValid()); + EXPECT_EQ(label.id(), Globals::kInvalidId); INFO("Checking basic functionality of BaseReg"); - EXPECT(BaseReg().isReg() == true); - EXPECT(BaseReg().isValid() == false); - EXPECT(BaseReg()._data[0] == 0); - EXPECT(BaseReg()._data[1] == 0); - EXPECT(dummy.as<BaseReg>().isValid() == false); + EXPECT_TRUE(BaseReg().isReg()); + EXPECT_FALSE(BaseReg().isValid()); + EXPECT_EQ(BaseReg()._data[0], 0u); + EXPECT_EQ(BaseReg()._data[1], 0u); + EXPECT_FALSE(dummy.as<BaseReg>().isValid()); // Create some register (not specific to any architecture). OperandSignature rSig = OperandSignature::fromOpType(OperandType::kReg) | @@ -57,75 +57,75 @@ UNIT(operand) { OperandSignature::fromSize(8); BaseReg r1(rSig, 5); - EXPECT(r1.isValid() == true); - EXPECT(r1.isReg() == true); - EXPECT(r1.isReg(RegType::kVec128) == true); - EXPECT(r1.isPhysReg() == true); - EXPECT(r1.isVirtReg() == false); - EXPECT(r1.signature() == rSig); - EXPECT(r1.type() == RegType::kVec128); - EXPECT(r1.group() == RegGroup::kVec); - EXPECT(r1.size() == 8); - EXPECT(r1.id() == 5); - EXPECT(r1.isReg(RegType::kVec128, 5) == true); // RegType and Id. - EXPECT(r1._data[0] == 0); - EXPECT(r1._data[1] == 0); + EXPECT_TRUE(r1.isValid()); + EXPECT_TRUE(r1.isReg()); + EXPECT_TRUE(r1.isReg(RegType::kVec128)); + EXPECT_TRUE(r1.isPhysReg()); + EXPECT_FALSE(r1.isVirtReg()); + EXPECT_EQ(r1.signature(), rSig); + EXPECT_EQ(r1.type(), RegType::kVec128); + EXPECT_EQ(r1.group(), RegGroup::kVec); + EXPECT_EQ(r1.size(), 8u); + EXPECT_EQ(r1.id(), 5u); + EXPECT_TRUE(r1.isReg(RegType::kVec128, 5)); // RegType and Id. + EXPECT_EQ(r1._data[0], 0u); + EXPECT_EQ(r1._data[1], 0u); // The same type of register having different id. BaseReg r2(r1, 6); - EXPECT(r2.isValid() == true); - EXPECT(r2.isReg() == true); - EXPECT(r2.isReg(RegType::kVec128) == true); - EXPECT(r2.isPhysReg() == true); - EXPECT(r2.isVirtReg() == false); - EXPECT(r2.signature() == rSig); - EXPECT(r2.type() == r1.type()); - EXPECT(r2.group() == r1.group()); - EXPECT(r2.size() == r1.size()); - EXPECT(r2.id() == 6); - EXPECT(r2.isReg(RegType::kVec128, 6) == true); + EXPECT_TRUE(r2.isValid()); + EXPECT_TRUE(r2.isReg()); + EXPECT_TRUE(r2.isReg(RegType::kVec128)); + EXPECT_TRUE(r2.isPhysReg()); + EXPECT_FALSE(r2.isVirtReg()); + EXPECT_EQ(r2.signature(), rSig); + EXPECT_EQ(r2.type(), r1.type()); + EXPECT_EQ(r2.group(), r1.group()); + EXPECT_EQ(r2.size(), r1.size()); + EXPECT_EQ(r2.id(), 6u); + EXPECT_TRUE(r2.isReg(RegType::kVec128, 6)); r1.reset(); - EXPECT(!r1.isReg()); - EXPECT(!r1.isValid()); + EXPECT_FALSE(r1.isReg()); + EXPECT_FALSE(r1.isValid()); INFO("Checking basic functionality of BaseMem"); BaseMem m; - EXPECT(m.isMem()); - EXPECT(m == BaseMem()); - EXPECT(m.hasBase() == false); - EXPECT(m.hasIndex() == false); - EXPECT(m.hasOffset() == false); - EXPECT(m.isOffset64Bit() == true); - EXPECT(m.offset() == 0); + EXPECT_TRUE(m.isMem()); + EXPECT_EQ(m, BaseMem()); + EXPECT_FALSE(m.hasBase()); + EXPECT_FALSE(m.hasIndex()); + EXPECT_FALSE(m.hasOffset()); + EXPECT_TRUE(m.isOffset64Bit()); + EXPECT_EQ(m.offset(), 0); m.setOffset(-1); - EXPECT(m.offsetLo32() == -1); - EXPECT(m.offset() == -1); + EXPECT_EQ(m.offsetLo32(), -1); + EXPECT_EQ(m.offset(), -1); int64_t x = int64_t(0xFF00FF0000000001u); int32_t xHi = int32_t(0xFF00FF00u); m.setOffset(x); - EXPECT(m.offset() == x); - EXPECT(m.offsetLo32() == 1); - EXPECT(m.offsetHi32() == xHi); + EXPECT_EQ(m.offset(), x); + EXPECT_EQ(m.offsetLo32(), 1); + EXPECT_EQ(m.offsetHi32(), xHi); INFO("Checking basic functionality of Imm"); Imm immValue(-42); - EXPECT(immValue.type() == ImmType::kInt); - EXPECT(Imm(-1).value() == -1); - EXPECT(imm(-1).value() == -1); - EXPECT(immValue.value() == -42); - EXPECT(imm(0xFFFFFFFF).value() == int64_t(0xFFFFFFFF)); + EXPECT_EQ(immValue.type(), ImmType::kInt); + EXPECT_EQ(Imm(-1).value(), -1); + EXPECT_EQ(imm(-1).value(), -1); + EXPECT_EQ(immValue.value(), -42); + EXPECT_EQ(imm(0xFFFFFFFF).value(), int64_t(0xFFFFFFFF)); Imm immDouble(0.4); - EXPECT(immDouble.type() == ImmType::kDouble); - EXPECT(immDouble.valueAs<double>() == 0.4); - EXPECT(immDouble == imm(0.4)); + EXPECT_EQ(immDouble.type(), ImmType::kDouble); + EXPECT_EQ(immDouble.valueAs<double>(), 0.4); + EXPECT_EQ(immDouble, imm(0.4)); - EXPECT(Imm(StrongEnumForImmTests::kValue0).value() == 0); - EXPECT(Imm(StrongEnumForImmTests::kValue0xFFFFFFFF).value() == 0xFFFFFFFFu); + EXPECT_EQ(Imm(StrongEnumForImmTests::kValue0).value(), 0); + EXPECT_EQ(Imm(StrongEnumForImmTests::kValue0xFFFFFFFF).value(), 0xFFFFFFFFu); } #endif diff --git a/3rdparty/asmjit/src/asmjit/core/operand.h b/3rdparty/asmjit/src/asmjit/core/operand.h index 2f81a217f1b..3626779316d 100644 --- a/3rdparty/asmjit/src/asmjit/core/operand.h +++ b/3rdparty/asmjit/src/asmjit/core/operand.h @@ -23,13 +23,15 @@ enum class OperandType : uint32_t { kReg = 1, //! Operand is a memory. kMem = 2, + //! Operand is a register-list. + kRegList = 3, //! Operand is an immediate value. - kImm = 3, + kImm = 4, //! Operand is a label. - kLabel = 4, + kLabel = 5, //! Maximum value of `OperandType`. - kMaxValue = kLabel + kMaxValue = kRegList }; static_assert(uint32_t(OperandType::kMem) == uint32_t(OperandType::kReg) + 1, @@ -47,7 +49,7 @@ enum class RegType : uint8_t { //! No register - unused, invalid, multiple meanings. kNone = 0, - //! This is not a register type. This value is reserved for a \ref Label that used in \ref BaseMem as a base. + //! This is not a register type. This value is reserved for a \ref Label that's used in \ref BaseMem as a base. //! //! Label tag is used as a sub-type, forming a unique signature across all operand types as 0x1 is never associated //! with any register type. This means that a memory operand's BASE register can be constructed from virtually any @@ -55,7 +57,7 @@ enum class RegType : uint8_t { kLabelTag = 1, //! Universal type describing program counter (PC) or instruction pointer (IP) register, if the target architecture - //! actually exposes it as a separate register type, which most modern targets do. + //! actually exposes it as a separate register type, which most modern architectures do. kPC = 2, //! 8-bit low general purpose register (X86). @@ -64,21 +66,21 @@ enum class RegType : uint8_t { kGp8Hi = 4, //! 16-bit general purpose register (X86). kGp16 = 5, - //! 32-bit general purpose register (X86|ARM). + //! 32-bit general purpose register (X86|AArch32|AArch64). kGp32 = 6, - //! 64-bit general purpose register (X86|ARM). + //! 64-bit general purpose register (X86|AArch64). kGp64 = 7, - //! 8-bit view of a vector register (ARM). + //! 8-bit view of a vector register (AArch64). kVec8 = 8, - //! 16-bit view of a vector register (ARM). + //! 16-bit view of a vector register (AArch64). kVec16 = 9, - //! 32-bit view of a vector register (ARM). + //! 32-bit view of a vector register (AArch32|AArch64). kVec32 = 10, - //! 64-bit view of a vector register (ARM). + //! 64-bit view of a vector register (AArch32|AArch64). //! //! \note This is never used for MMX registers on X86, MMX registers have its own category. kVec64 = 11, - //! 128-bit view of a vector register (X86|ARM). + //! 128-bit view of a vector register (X86|AArch32|AArch64). kVec128 = 12, //! 256-bit view of a vector register (X86). kVec256 = 13, @@ -98,9 +100,6 @@ enum class RegType : uint8_t { // X86 Specific Register Types // --------------------------- - // X86 Specific Register Types - // =========================== - //! Instruction pointer (RIP), only addressable in \ref x86::Mem in 64-bit targets. kX86_Rip = kPC, //! Low GPB register (AL, BL, CL, DL, ...). @@ -137,7 +136,7 @@ enum class RegType : uint8_t { kX86_Tmm = kExtra + 6, // ARM Specific Register Types - // =========================== + // --------------------------- //! Program pointer (PC) register (AArch64). kARM_PC = kPC, @@ -153,7 +152,9 @@ enum class RegType : uint8_t { kARM_VecS = kVec32, //! 64-bit view of VFP/ASIMD register (D). kARM_VecD = kVec64, - //! 128-bit view of VFP/ASIMD register (Q|V). + //! 128-bit view of VFP/ASIMD register (Q). + kARM_VecQ = kVec128, + //! 128-bit view of VFP/ASIMD register (V). kARM_VecV = kVec128, //! Maximum value of `RegType`. @@ -172,8 +173,8 @@ enum class RegGroup : uint8_t { //! Describes X86 XMM|YMM|ZMM registers ARM/AArch64 V registers. kVec = 1, - //! Extra virtual group #2 that can be used by Compiler for register allocation. - kExtraVirt2 = 2, + //! Mask register group compatible with all backends that can use masking. + kMask = 2, //! Extra virtual group #3 that can be used by Compiler for register allocation. kExtraVirt3 = 3, @@ -186,8 +187,8 @@ enum class RegGroup : uint8_t { // X86 Specific Register Groups // ---------------------------- - //! K register group (KReg) - maps to \ref RegGroup::kExtraVirt2 (X86, X86_64). - kX86_K = kExtraVirt2, + //! K register group (KReg) - maps to \ref RegGroup::kMask (X86, X86_64). + kX86_K = kMask, //! MMX register group (MM) - maps to \ref RegGroup::kExtraVirt3 (X86, X86_64). kX86_MM = kExtraVirt3, @@ -294,147 +295,150 @@ struct OperandSignature { //! //! \{ - inline constexpr bool operator!() const noexcept { return _bits != 0; } - inline constexpr explicit operator bool() const noexcept { return _bits != 0; } + ASMJIT_INLINE_NODEBUG constexpr bool operator!() const noexcept { return _bits == 0; } + ASMJIT_INLINE_NODEBUG constexpr explicit operator bool() const noexcept { return _bits != 0; } - inline OperandSignature& operator|=(uint32_t x) noexcept { _bits |= x; return *this; } - inline OperandSignature& operator&=(uint32_t x) noexcept { _bits &= x; return *this; } - inline OperandSignature& operator^=(uint32_t x) noexcept { _bits ^= x; return *this; } + ASMJIT_INLINE_NODEBUG OperandSignature& operator|=(uint32_t x) noexcept { _bits |= x; return *this; } + ASMJIT_INLINE_NODEBUG OperandSignature& operator&=(uint32_t x) noexcept { _bits &= x; return *this; } + ASMJIT_INLINE_NODEBUG OperandSignature& operator^=(uint32_t x) noexcept { _bits ^= x; return *this; } - inline OperandSignature& operator|=(const OperandSignature& other) noexcept { return operator|=(other._bits); } - inline OperandSignature& operator&=(const OperandSignature& other) noexcept { return operator&=(other._bits); } - inline OperandSignature& operator^=(const OperandSignature& other) noexcept { return operator^=(other._bits); } + ASMJIT_INLINE_NODEBUG OperandSignature& operator|=(const OperandSignature& other) noexcept { return operator|=(other._bits); } + ASMJIT_INLINE_NODEBUG OperandSignature& operator&=(const OperandSignature& other) noexcept { return operator&=(other._bits); } + ASMJIT_INLINE_NODEBUG OperandSignature& operator^=(const OperandSignature& other) noexcept { return operator^=(other._bits); } - inline constexpr OperandSignature operator~() const noexcept { return OperandSignature{~_bits}; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature operator~() const noexcept { return OperandSignature{~_bits}; } - inline constexpr OperandSignature operator|(uint32_t x) const noexcept { return OperandSignature{_bits | x}; } - inline constexpr OperandSignature operator&(uint32_t x) const noexcept { return OperandSignature{_bits & x}; } - inline constexpr OperandSignature operator^(uint32_t x) const noexcept { return OperandSignature{_bits ^ x}; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature operator|(uint32_t x) const noexcept { return OperandSignature{_bits | x}; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature operator&(uint32_t x) const noexcept { return OperandSignature{_bits & x}; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature operator^(uint32_t x) const noexcept { return OperandSignature{_bits ^ x}; } - inline constexpr OperandSignature operator|(const OperandSignature& other) const noexcept { return OperandSignature{_bits | other._bits}; } - inline constexpr OperandSignature operator&(const OperandSignature& other) const noexcept { return OperandSignature{_bits & other._bits}; } - inline constexpr OperandSignature operator^(const OperandSignature& other) const noexcept { return OperandSignature{_bits ^ other._bits}; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature operator|(const OperandSignature& other) const noexcept { return OperandSignature{_bits | other._bits}; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature operator&(const OperandSignature& other) const noexcept { return OperandSignature{_bits & other._bits}; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature operator^(const OperandSignature& other) const noexcept { return OperandSignature{_bits ^ other._bits}; } - inline constexpr bool operator==(uint32_t x) const noexcept { return _bits == x; } - inline constexpr bool operator!=(uint32_t x) const noexcept { return _bits != x; } + ASMJIT_INLINE_NODEBUG constexpr bool operator==(uint32_t x) const noexcept { return _bits == x; } + ASMJIT_INLINE_NODEBUG constexpr bool operator!=(uint32_t x) const noexcept { return _bits != x; } - inline constexpr bool operator==(const OperandSignature& other) const noexcept { return _bits == other._bits; } - inline constexpr bool operator!=(const OperandSignature& other) const noexcept { return _bits != other._bits; } + ASMJIT_INLINE_NODEBUG constexpr bool operator==(const OperandSignature& other) const noexcept { return _bits == other._bits; } + ASMJIT_INLINE_NODEBUG constexpr bool operator!=(const OperandSignature& other) const noexcept { return _bits != other._bits; } //! \} //! \name Accessors //! \{ - inline void reset() noexcept { _bits = 0; } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _bits = 0; } - inline constexpr uint32_t bits() const noexcept { return _bits; } - inline void setBits(uint32_t bits) noexcept { _bits = bits; } + ASMJIT_INLINE_NODEBUG constexpr uint32_t bits() const noexcept { return _bits; } + ASMJIT_INLINE_NODEBUG void setBits(uint32_t bits) noexcept { _bits = bits; } - template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> - inline constexpr bool hasField() const noexcept { + template<uint32_t kFieldMask> + ASMJIT_INLINE_NODEBUG constexpr bool hasField() const noexcept { return (_bits & kFieldMask) != 0; } - template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> - inline constexpr bool hasField(uint32_t value) const noexcept { - return (_bits & kFieldMask) != value << kFieldShift; + template<uint32_t kFieldMask> + ASMJIT_INLINE_NODEBUG constexpr bool hasField(uint32_t value) const noexcept { + return (_bits & kFieldMask) != value << Support::ConstCTZ<kFieldMask>::value; } - template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> - inline constexpr uint32_t getField() const noexcept { - return (_bits >> kFieldShift) & (kFieldMask >> kFieldShift); + template<uint32_t kFieldMask> + ASMJIT_INLINE_NODEBUG constexpr uint32_t getField() const noexcept { + return (_bits >> Support::ConstCTZ<kFieldMask>::value) & (kFieldMask >> Support::ConstCTZ<kFieldMask>::value); } - template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> - inline void setField(uint32_t value) noexcept { - ASMJIT_ASSERT((value & ~(kFieldMask >> kFieldShift)) == 0); - _bits = (_bits & ~kFieldMask) | (value << kFieldShift); + template<uint32_t kFieldMask> + ASMJIT_INLINE_NODEBUG void setField(uint32_t value) noexcept { + ASMJIT_ASSERT(((value << Support::ConstCTZ<kFieldMask>::value) & ~kFieldMask) == 0); + _bits = (_bits & ~kFieldMask) | (value << Support::ConstCTZ<kFieldMask>::value); } - inline constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature{_bits & mask}; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature{_bits & mask}; } + + template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> + ASMJIT_INLINE_NODEBUG constexpr OperandSignature replacedValue(uint32_t value) const noexcept { return OperandSignature{(_bits & ~kFieldMask) | (value << kFieldShift)}; } template<uint32_t kFieldMask> - inline constexpr bool matchesSignature(const OperandSignature& signature) const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool matchesSignature(const OperandSignature& signature) const noexcept { return (_bits & kFieldMask) == signature._bits; } template<uint32_t kFieldMask> - inline constexpr bool matchesFields(uint32_t bits) const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool matchesFields(uint32_t bits) const noexcept { return (_bits & kFieldMask) == bits; } template<uint32_t kFieldMask> - inline constexpr bool matchesFields(const OperandSignature& fields) const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool matchesFields(const OperandSignature& fields) const noexcept { return (_bits & kFieldMask) == fields._bits; } - inline constexpr bool isValid() const noexcept { return _bits != 0; } + ASMJIT_INLINE_NODEBUG constexpr bool isValid() const noexcept { return _bits != 0; } - inline constexpr OperandType opType() const noexcept { return (OperandType)getField<kOpTypeMask>(); } + ASMJIT_INLINE_NODEBUG constexpr OperandType opType() const noexcept { return (OperandType)getField<kOpTypeMask>(); } - inline constexpr RegType regType() const noexcept { return (RegType)getField<kRegTypeMask>(); } - inline constexpr RegGroup regGroup() const noexcept { return (RegGroup)getField<kRegGroupMask>(); } + ASMJIT_INLINE_NODEBUG constexpr RegType regType() const noexcept { return (RegType)getField<kRegTypeMask>(); } + ASMJIT_INLINE_NODEBUG constexpr RegGroup regGroup() const noexcept { return (RegGroup)getField<kRegGroupMask>(); } - inline constexpr RegType memBaseType() const noexcept { return (RegType)getField<kMemBaseTypeMask>(); } - inline constexpr RegType memIndexType() const noexcept { return (RegType)getField<kMemIndexTypeMask>(); } + ASMJIT_INLINE_NODEBUG constexpr RegType memBaseType() const noexcept { return (RegType)getField<kMemBaseTypeMask>(); } + ASMJIT_INLINE_NODEBUG constexpr RegType memIndexType() const noexcept { return (RegType)getField<kMemIndexTypeMask>(); } - inline constexpr uint32_t predicate() const noexcept { return getField<kPredicateMask>(); } - inline constexpr uint32_t size() const noexcept { return getField<kSizeMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t predicate() const noexcept { return getField<kPredicateMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t size() const noexcept { return getField<kSizeMask>(); } - inline void setOpType(OperandType opType) noexcept { setField<kOpTypeMask>(uint32_t(opType)); } - inline void setRegType(RegType regType) noexcept { setField<kRegTypeMask>(uint32_t(regType)); } - inline void setRegGroup(RegGroup regGroup) noexcept { setField<kRegGroupMask>(uint32_t(regGroup)); } + ASMJIT_INLINE_NODEBUG void setOpType(OperandType opType) noexcept { setField<kOpTypeMask>(uint32_t(opType)); } + ASMJIT_INLINE_NODEBUG void setRegType(RegType regType) noexcept { setField<kRegTypeMask>(uint32_t(regType)); } + ASMJIT_INLINE_NODEBUG void setRegGroup(RegGroup regGroup) noexcept { setField<kRegGroupMask>(uint32_t(regGroup)); } - inline void setMemBaseType(RegGroup baseType) noexcept { setField<kMemBaseTypeMask>(uint32_t(baseType)); } - inline void setMemIndexType(RegGroup indexType) noexcept { setField<kMemIndexTypeMask>(uint32_t(indexType)); } + ASMJIT_INLINE_NODEBUG void setMemBaseType(RegType baseType) noexcept { setField<kMemBaseTypeMask>(uint32_t(baseType)); } + ASMJIT_INLINE_NODEBUG void setMemIndexType(RegType indexType) noexcept { setField<kMemIndexTypeMask>(uint32_t(indexType)); } - inline void setPredicate(uint32_t predicate) noexcept { setField<kPredicateMask>(predicate); } - inline void setSize(uint32_t size) noexcept { setField<kSizeMask>(size); } + ASMJIT_INLINE_NODEBUG void setPredicate(uint32_t predicate) noexcept { setField<kPredicateMask>(predicate); } + ASMJIT_INLINE_NODEBUG void setSize(uint32_t size) noexcept { setField<kSizeMask>(size); } //! \} //! \name Static Constructors //! \{ - static inline constexpr OperandSignature fromBits(uint32_t bits) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromBits(uint32_t bits) noexcept { return OperandSignature{bits}; } template<uint32_t kFieldMask, typename T> - static inline constexpr OperandSignature fromValue(const T& value) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromValue(const T& value) noexcept { return OperandSignature{uint32_t(value) << Support::ConstCTZ<kFieldMask>::value}; } - static inline constexpr OperandSignature fromOpType(OperandType opType) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromOpType(OperandType opType) noexcept { return OperandSignature{uint32_t(opType) << kOpTypeShift}; } - static inline constexpr OperandSignature fromRegType(RegType regType) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromRegType(RegType regType) noexcept { return OperandSignature{uint32_t(regType) << kRegTypeShift}; } - static inline constexpr OperandSignature fromRegGroup(RegGroup regGroup) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromRegGroup(RegGroup regGroup) noexcept { return OperandSignature{uint32_t(regGroup) << kRegGroupShift}; } - static inline constexpr OperandSignature fromRegTypeAndGroup(RegType regType, RegGroup regGroup) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromRegTypeAndGroup(RegType regType, RegGroup regGroup) noexcept { return fromRegType(regType) | fromRegGroup(regGroup); } - static inline constexpr OperandSignature fromMemBaseType(RegType baseType) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromMemBaseType(RegType baseType) noexcept { return OperandSignature{uint32_t(baseType) << kMemBaseTypeShift}; } - static inline constexpr OperandSignature fromMemIndexType(RegType indexType) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromMemIndexType(RegType indexType) noexcept { return OperandSignature{uint32_t(indexType) << kMemIndexTypeShift}; } - static inline constexpr OperandSignature fromPredicate(uint32_t predicate) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromPredicate(uint32_t predicate) noexcept { return OperandSignature{predicate << kPredicateShift}; } - static inline constexpr OperandSignature fromSize(uint32_t size) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature fromSize(uint32_t size) noexcept { return OperandSignature{size << kSizeShift}; } @@ -506,18 +510,18 @@ struct Operand_ { //! Tests whether the given `id` is a valid virtual register id. Since AsmJit supports both physical and virtual //! registers it must be able to distinguish between these two. The idea is that physical registers are always //! limited in size, so virtual identifiers start from `kVirtIdMin` and end at `kVirtIdMax`. - static inline bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); } + static ASMJIT_INLINE_NODEBUG bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); } //! Converts a real-id into a packed-id that can be stored in Operand. - static inline uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; } + static ASMJIT_INLINE_NODEBUG uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; } //! Converts a packed-id back to real-id. - static inline uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; } + static ASMJIT_INLINE_NODEBUG uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; } //! \name Construction & Destruction //! \{ //! \cond INTERNAL //! Initializes a `BaseReg` operand from `signature` and register `id`. - inline void _initReg(const Signature& signature, uint32_t id) noexcept { + ASMJIT_INLINE_NODEBUG void _initReg(const Signature& signature, uint32_t id) noexcept { _signature = signature; _baseId = id; _data[0] = 0; @@ -526,7 +530,12 @@ struct Operand_ { //! \endcond //! Initializes the operand from `other` operand (used by operator overloads). - inline void copyFrom(const Operand_& other) noexcept { memcpy(this, &other, sizeof(Operand_)); } + ASMJIT_INLINE_NODEBUG void copyFrom(const Operand_& other) noexcept { + _signature._bits = other._signature._bits; + _baseId = other._baseId; + _data[0] = other._data[0]; + _data[1] = other._data[1]; + } //! Resets the `Operand` to none. //! @@ -555,7 +564,7 @@ struct Operand_ { //! memset(&b, 0, sizeof(Operand)); //! assert(a == b); //! ``` - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _signature.reset(); _baseId = 0; _data[0] = 0; @@ -568,9 +577,9 @@ struct Operand_ { //! \{ //! Tests whether this operand is the same as `other`. - inline constexpr bool operator==(const Operand_& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG constexpr bool operator==(const Operand_& other) const noexcept { return equals(other); } //! Tests whether this operand is not the same as `other`. - inline constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); } + ASMJIT_INLINE_NODEBUG constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); } //! \} @@ -579,11 +588,27 @@ struct Operand_ { //! Casts this operand to `T` type. template<typename T> - inline T& as() noexcept { return static_cast<T&>(*this); } + ASMJIT_INLINE_NODEBUG T& as() noexcept { return static_cast<T&>(*this); } //! Casts this operand to `T` type (const). template<typename T> - inline const T& as() const noexcept { return static_cast<const T&>(*this); } + ASMJIT_INLINE_NODEBUG const T& as() const noexcept { return static_cast<const T&>(*this); } + + //! \} + + //! \name Equality + //! \{ + + //! Tests whether the operand is 100% equal to `other` operand. + //! + //! \note This basically performs a binary comparison, if aby bit is + //! different the operands are not equal. + ASMJIT_INLINE_NODEBUG constexpr bool equals(const Operand_& other) const noexcept { + return bool(unsigned(_signature == other._signature) & + unsigned(_baseId == other._baseId ) & + unsigned(_data[0] == other._data[0] ) & + unsigned(_data[1] == other._data[1] )); + } //! \} @@ -591,55 +616,44 @@ struct Operand_ { //! \{ //! Tests whether the operand's signature matches the signature of the `other` operand. - inline constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other._signature; } + ASMJIT_INLINE_NODEBUG constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other._signature; } //! Tests whether the operand's signature matches the given signature `sign`. - inline constexpr bool hasSignature(const Signature& other) const noexcept { return _signature == other; } + ASMJIT_INLINE_NODEBUG constexpr bool hasSignature(const Signature& other) const noexcept { return _signature == other; } //! Returns operand signature as unsigned 32-bit integer. //! //! Signature is first 4 bytes of the operand data. It's used mostly for operand checking as it's //! much faster to check packed 4 bytes at once than having to check these bytes individually. - inline constexpr Signature signature() const noexcept { return _signature; } + ASMJIT_INLINE_NODEBUG constexpr Signature signature() const noexcept { return _signature; } //! Sets the operand signature, see `signature()`. //! //! \note Improper use of `setSignature()` can lead to hard-to-debug errors. - inline void setSignature(const Signature& signature) noexcept { _signature = signature; } + ASMJIT_INLINE_NODEBUG void setSignature(const Signature& signature) noexcept { _signature = signature; } + //! \overload + ASMJIT_INLINE_NODEBUG void setSignature(uint32_t signature) noexcept { _signature._bits = signature; } //! Returns the type of the operand, see `OpType`. - inline constexpr OperandType opType() const noexcept { return _signature.opType(); } + ASMJIT_INLINE_NODEBUG constexpr OperandType opType() const noexcept { return _signature.opType(); } //! Tests whether the operand is none (`OperandType::kNone`). - inline constexpr bool isNone() const noexcept { return _signature == Signature::fromBits(0); } + ASMJIT_INLINE_NODEBUG constexpr bool isNone() const noexcept { return _signature == Signature::fromBits(0); } //! Tests whether the operand is a register (`OperandType::kReg`). - inline constexpr bool isReg() const noexcept { return opType() == OperandType::kReg; } + ASMJIT_INLINE_NODEBUG constexpr bool isReg() const noexcept { return opType() == OperandType::kReg; } + //! Tests whether the operand is a register-list. + //! + //! \note Register-list is currently only used by 32-bit ARM architecture. + ASMJIT_INLINE_NODEBUG constexpr bool isRegList() const noexcept { return opType() == OperandType::kRegList; } //! Tests whether the operand is a memory location (`OperandType::kMem`). - inline constexpr bool isMem() const noexcept { return opType() == OperandType::kMem; } + ASMJIT_INLINE_NODEBUG constexpr bool isMem() const noexcept { return opType() == OperandType::kMem; } //! Tests whether the operand is an immediate (`OperandType::kImm`). - inline constexpr bool isImm() const noexcept { return opType() == OperandType::kImm; } + ASMJIT_INLINE_NODEBUG constexpr bool isImm() const noexcept { return opType() == OperandType::kImm; } //! Tests whether the operand is a label (`OperandType::kLabel`). - inline constexpr bool isLabel() const noexcept { return opType() == OperandType::kLabel; } + ASMJIT_INLINE_NODEBUG constexpr bool isLabel() const noexcept { return opType() == OperandType::kLabel; } //! Tests whether the operand is a physical register. - inline constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; } + ASMJIT_INLINE_NODEBUG constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; } //! Tests whether the operand is a virtual register. - inline constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; } - - //! Tests whether the operand specifies a size (i.e. the size is not zero). - inline constexpr bool hasSize() const noexcept { return _signature.hasField<Signature::kSizeMask>(); } - //! Tests whether the size of the operand matches `size`. - inline constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; } - - //! Returns the size of the operand in bytes. - //! - //! The value returned depends on the operand type: - //! * None - Should always return zero size. - //! * Reg - Should always return the size of the register. If the register size depends on architecture - //! (like `x86::CReg` and `x86::DReg`) the size returned should be the greatest possible (so it - //! should return 64-bit size in such case). - //! * Mem - Size is optional and will be in most cases zero. - //! * Imm - Should always return zero size. - //! * Label - Should always return zero size. - inline constexpr uint32_t size() const noexcept { return _signature.getField<Signature::kSizeMask>(); } + ASMJIT_INLINE_NODEBUG constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; } //! Returns the operand id. //! @@ -650,35 +664,98 @@ struct Operand_ { //! * Imm - Should be `0`. //! * Label - Label id if it was created by using `newLabel()` or `Globals::kInvalidId` if the label is invalid or //! not initialized. - inline constexpr uint32_t id() const noexcept { return _baseId; } - - //! Tests whether the operand is 100% equal to `other` operand. - //! - //! \note This basically performs a binary comparison, if aby bit is - //! different the operands are not equal. - inline constexpr bool equals(const Operand_& other) const noexcept { - return (_signature == other._signature) & - (_baseId == other._baseId ) & - (_data[0] == other._data[0] ) & - (_data[1] == other._data[1] ) ; - } + ASMJIT_INLINE_NODEBUG constexpr uint32_t id() const noexcept { return _baseId; } //! Tests whether the operand is a register matching the given register `type`. - inline constexpr bool isReg(RegType type) const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType type) const noexcept { return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegType(type)); } - //! Tests whether the operand is register and of register `type` and `id`. - inline constexpr bool isReg(RegType type, uint32_t id) const noexcept { - return isReg(type) && this->id() == id; + //! Tests whether the operand is a register of the provided register group `regGroup`. + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegGroup regGroup) const noexcept { + return _signature.subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(regGroup)); + } + + //! Tests whether the operand is register and of register type `regType` and `regId`. + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType regType, uint32_t regId) const noexcept { return isReg(regType) && _baseId == regId; } + //! Tests whether the operand is register and of register group `regGroup` and `regId`. + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegGroup regGroup, uint32_t regId) const noexcept { return isReg(regGroup) && _baseId == regId; } + + //! Tests whether the register is a general purpose register (any size). + ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isReg(RegGroup::kGp); } + //! Tests whether the register is a 32-bit general purpose register. + ASMJIT_INLINE_NODEBUG constexpr bool isGp32() const noexcept { return isReg(RegType::kGp32); } + //! Tests whether the register is a 64-bit general purpose register. + ASMJIT_INLINE_NODEBUG constexpr bool isGp64() const noexcept { return isReg(RegType::kGp64); } + + //! Tests whether the register is a vector register of any size. + ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isReg(RegGroup::kVec); } + //! Tests whether the register is an 8-bit vector register or view (AArch64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec8() const noexcept { return isReg(RegType::kVec8); } + //! Tests whether the register is a 16-bit vector register or view (AArch64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec16() const noexcept { return isReg(RegType::kVec16); } + //! Tests whether the register is a 32-bit vector register or view (AArch32, AArch64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec32() const noexcept { return isReg(RegType::kVec32); } + //! Tests whether the register is a 64-bit vector register or view (AArch32, AArch64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec64() const noexcept { return isReg(RegType::kVec64); } + //! Tests whether the register is a 128-bit vector register or view (AArch32, AArch64, X86, X86_64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return isReg(RegType::kVec128); } + //! Tests whether the register is a 256-bit vector register or view (X86, X86_64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec256() const noexcept { return isReg(RegType::kVec256); } + //! Tests whether the register is a 512-bit vector register or view (X86, X86_64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec512() const noexcept { return isReg(RegType::kVec512); } + + //! Tests whether the register is a mask register of any size. + ASMJIT_INLINE_NODEBUG constexpr bool isMask() const noexcept { return isReg(RegGroup::kMask); } + + //! Tests whether the operand is a register matching the given register `type`. + ASMJIT_INLINE_NODEBUG constexpr bool isRegList(RegType type) const noexcept { + return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kRegList) | Signature::fromRegType(type)); } //! Tests whether the operand is a register or memory. - inline constexpr bool isRegOrMem() const noexcept { + //! + //! \note This is useful on X86 and X86_64 architectures as many instructions support Reg/Mem operand combination. + //! So if the user code works with just \ref Operand, it's possible to check whether the operand is either a register + //! or memory location with a single check. + ASMJIT_INLINE_NODEBUG constexpr bool isRegOrMem() const noexcept { return Support::isBetween<uint32_t>(uint32_t(opType()), uint32_t(OperandType::kReg), uint32_t(OperandType::kMem)); } + //! Tests whether the operand is a register, register-list, or memory. + //! + //! \note This is useful on 32-bit ARM architecture to check whether an operand references a register. It can be + //! used in other architectures too, but it would work identically to \ref isRegOrMem() as other architectures + //! don't provide register lists. + ASMJIT_INLINE_NODEBUG constexpr bool isRegOrRegListOrMem() const noexcept { + return Support::isBetween<uint32_t>(uint32_t(opType()), uint32_t(OperandType::kReg), uint32_t(OperandType::kRegList)); + } + //! \} + + //! \name Accessors (X86 Specific) + //! \{ + + //! Returns a size of a register or an X86 memory operand. + //! + //! \remarks At the moment only X86 and X86_64 memory operands have a size - other memory operands can use bits + //! that represent size as an additional payload. This means that memory size is architecture specific and should + //! be accessed via \ref x86::Mem::size(). Sometimes when the user knows that the operand is either a register or + //! memory operand this function can be helpful as it avoids casting, but it only works when it targets X86 and X86_64. + ASMJIT_INLINE_NODEBUG constexpr uint32_t x86RmSize() const noexcept { return _signature.size(); } + + //! \} + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("hasSize() is no longer portable - use x86RmSize() or x86::Mem::hasSize() instead, if your target is X86/X86_64") + ASMJIT_INLINE_NODEBUG constexpr bool hasSize() const noexcept { return x86RmSize() != 0u; } + + ASMJIT_DEPRECATED("hasSize() is no longer portable - use x86RmSize() or x86::Mem::hasSize() instead, if your target is X86/X86_64") + ASMJIT_INLINE_NODEBUG constexpr bool hasSize(uint32_t s) const noexcept { return x86RmSize() == s; } + + ASMJIT_DEPRECATED("size() is no longer portable - use x86RmSize() or x86::Mem::size() instead, if your target is X86/X86_64") + ASMJIT_INLINE_NODEBUG constexpr uint32_t size() const noexcept { return _signature.getField<Signature::kSizeMask>(); } +#endif }; //! Base class representing an operand in AsmJit (default constructed version). @@ -688,30 +765,30 @@ public: //! \{ //! Creates `kOpNone` operand having all members initialized to zero. - inline constexpr Operand() noexcept + ASMJIT_INLINE_NODEBUG constexpr Operand() noexcept : Operand_{ Signature::fromOpType(OperandType::kNone), 0u, { 0u, 0u }} {} //! Creates a cloned `other` operand. - inline constexpr Operand(const Operand& other) noexcept = default; + ASMJIT_INLINE_NODEBUG constexpr Operand(const Operand& other) noexcept = default; //! Creates a cloned `other` operand. - inline constexpr explicit Operand(const Operand_& other) + ASMJIT_INLINE_NODEBUG constexpr explicit Operand(const Operand_& other) : Operand_(other) {} //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values. - inline constexpr Operand(Globals::Init_, const Signature& u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : Operand_{ u0, u1, { u2, u3 }} {} + ASMJIT_INLINE_NODEBUG constexpr Operand(Globals::Init_, const Signature& u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept + : Operand_{{u0._bits}, u1, {u2, u3}} {} //! Creates an uninitialized operand (dangerous). - inline explicit Operand(Globals::NoInit_) noexcept {} + ASMJIT_INLINE_NODEBUG explicit Operand(Globals::NoInit_) noexcept {} //! \} //! \name Overloaded Operators //! \{ - inline Operand& operator=(const Operand& other) noexcept = default; - inline Operand& operator=(const Operand_& other) noexcept { return operator=(static_cast<const Operand&>(other)); } + ASMJIT_INLINE_NODEBUG Operand& operator=(const Operand& other) noexcept = default; + ASMJIT_INLINE_NODEBUG Operand& operator=(const Operand_& other) noexcept { return operator=(static_cast<const Operand&>(other)); } //! \} @@ -719,7 +796,7 @@ public: //! \{ //! Clones this operand and returns its copy. - inline constexpr Operand clone() const noexcept { return Operand(*this); } + ASMJIT_INLINE_NODEBUG constexpr Operand clone() const noexcept { return Operand(*this); } //! \} }; @@ -756,22 +833,22 @@ public: //! \{ //! Creates a label operand without ID (you must set the ID to make it valid). - inline constexpr Label() noexcept + ASMJIT_INLINE_NODEBUG constexpr Label() noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), Globals::kInvalidId, 0, 0) {} //! Creates a cloned label operand of `other`. - inline constexpr Label(const Label& other) noexcept + ASMJIT_INLINE_NODEBUG constexpr Label(const Label& other) noexcept : Operand(other) {} //! Creates a label operand of the given `id`. - inline constexpr explicit Label(uint32_t id) noexcept + ASMJIT_INLINE_NODEBUG constexpr explicit Label(uint32_t id) noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), id, 0, 0) {} - inline explicit Label(Globals::NoInit_) noexcept + ASMJIT_INLINE_NODEBUG explicit Label(Globals::NoInit_) noexcept : Operand(Globals::NoInit) {} //! Resets the label, will reset all properties and set its ID to `Globals::kInvalidId`. - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _signature = Signature::fromOpType(OperandType::kLabel); _baseId = Globals::kInvalidId; _data[0] = 0; @@ -783,7 +860,7 @@ public: //! \name Overloaded Operators //! \{ - inline Label& operator=(const Label& other) noexcept = default; + ASMJIT_INLINE_NODEBUG Label& operator=(const Label& other) noexcept = default; //! \} @@ -791,9 +868,9 @@ public: //! \{ //! Tests whether the label was created by CodeHolder and/or an attached emitter. - inline constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; } + ASMJIT_INLINE_NODEBUG constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; } //! Sets the label `id`. - inline void setId(uint32_t id) noexcept { _baseId = id; } + ASMJIT_INLINE_NODEBUG void setId(uint32_t id) noexcept { _baseId = id; } //! \} }; @@ -806,10 +883,8 @@ struct BaseRegTraits { kTypeId = uint32_t(TypeId::kVoid), //! RegType is not valid by default. kValid = 0, - //! Count of registers (0 if none). - kCount = 0, - //! Zero type by default (defeaults to None). + //! Zero type by default (defaults to None). kType = uint32_t(RegType::kNone), //! Zero group by default (defaults to GP). kGroup = uint32_t(RegGroup::kGp), @@ -822,7 +897,7 @@ struct BaseRegTraits { }; //! \endcond -//! Physical or virtual register operand. +//! Physical or virtual register operand (base). class BaseReg : public Operand { public: //! \name Constants @@ -848,22 +923,22 @@ public: //! \{ //! Creates a dummy register operand. - inline constexpr BaseReg() noexcept + ASMJIT_INLINE_NODEBUG constexpr BaseReg() noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kReg), kIdBad, 0, 0) {} //! Creates a new register operand which is the same as `other` . - inline constexpr BaseReg(const BaseReg& other) noexcept + ASMJIT_INLINE_NODEBUG constexpr BaseReg(const BaseReg& other) noexcept : Operand(other) {} //! Creates a new register operand compatible with `other`, but with a different `id`. - inline constexpr BaseReg(const BaseReg& other, uint32_t id) noexcept + ASMJIT_INLINE_NODEBUG constexpr BaseReg(const BaseReg& other, uint32_t id) noexcept : Operand(Globals::Init, other._signature, id, 0, 0) {} //! Creates a register initialized to the given `signature` and `id`. - inline constexpr BaseReg(const Signature& signature, uint32_t id) noexcept + ASMJIT_INLINE_NODEBUG constexpr BaseReg(const Signature& signature, uint32_t id) noexcept : Operand(Globals::Init, signature, id, 0, 0) {} - inline explicit BaseReg(Globals::NoInit_) noexcept + ASMJIT_INLINE_NODEBUG explicit BaseReg(Globals::NoInit_) noexcept : Operand(Globals::NoInit) {} //! \} @@ -871,7 +946,7 @@ public: //! \name Overloaded Operators //! \{ - inline BaseReg& operator=(const BaseReg& other) noexcept = default; + ASMJIT_INLINE_NODEBUG BaseReg& operator=(const BaseReg& other) noexcept = default; //! \} @@ -883,14 +958,14 @@ public: //! Base signature only contains the operand type, register type, register group, and register size. It doesn't //! contain element type, predicate, or other architecture-specific data. Base signature is a signature that is //! provided by architecture-specific `RegTraits`, like \ref x86::RegTraits. - inline constexpr OperandSignature baseSignature() const noexcept { return _signature & kBaseSignatureMask; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature baseSignature() const noexcept { return _signature & kBaseSignatureMask; } //! Tests whether the operand's base signature matches the given signature `sign`. - inline constexpr bool hasBaseSignature(uint32_t signature) const noexcept { return baseSignature() == signature; } + ASMJIT_INLINE_NODEBUG constexpr bool hasBaseSignature(uint32_t signature) const noexcept { return baseSignature() == signature; } //! Tests whether the operand's base signature matches the given signature `sign`. - inline constexpr bool hasBaseSignature(const OperandSignature& signature) const noexcept { return baseSignature() == signature; } + ASMJIT_INLINE_NODEBUG constexpr bool hasBaseSignature(const OperandSignature& signature) const noexcept { return baseSignature() == signature; } //! Tests whether the operand's base signature matches the base signature of the `other` operand. - inline constexpr bool hasBaseSignature(const BaseReg& other) const noexcept { return baseSignature() == other.baseSignature(); } + ASMJIT_INLINE_NODEBUG constexpr bool hasBaseSignature(const BaseReg& other) const noexcept { return baseSignature() == other.baseSignature(); } //! Tests whether this register is the same as `other`. //! @@ -899,79 +974,90 @@ public: //! both \ref equals() and \ref isSame() should give the same answer, however, if any of these two contains garbage //! or other metadata in the upper 8 bytes then \ref isSame() may return `true` in cases in which \ref equals() //! returns false. - inline constexpr bool isSame(const BaseReg& other) const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool isSame(const BaseReg& other) const noexcept { return (_signature == other._signature) & (_baseId == other._baseId); } //! Tests whether the register is valid (either virtual or physical). - inline constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); } + ASMJIT_INLINE_NODEBUG constexpr bool isValid() const noexcept { return bool(unsigned(_signature != 0) & unsigned(_baseId != kIdBad)); } //! Tests whether this is a physical register. - inline constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; } + ASMJIT_INLINE_NODEBUG constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; } //! Tests whether this is a virtual register. - inline constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; } + ASMJIT_INLINE_NODEBUG constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; } //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience. - inline constexpr bool isType(RegType type) const noexcept { return _signature.subset(Signature::kRegTypeMask) == Signature::fromRegType(type); } + ASMJIT_INLINE_NODEBUG constexpr bool isType(RegType type) const noexcept { return _signature.subset(Signature::kRegTypeMask) == Signature::fromRegType(type); } //! Tests whether the register group matches `group`. - inline constexpr bool isGroup(RegGroup group) const noexcept { return _signature.subset(Signature::kRegGroupMask) == Signature::fromRegGroup(group); } + ASMJIT_INLINE_NODEBUG constexpr bool isGroup(RegGroup group) const noexcept { return _signature.subset(Signature::kRegGroupMask) == Signature::fromRegGroup(group); } //! Tests whether the register is a general purpose register (any size). - inline constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); } - //! Tests whether the register is a vector register. - inline constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); } + ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); } + //! Tests whether the register is a vector register of any size. + ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); } + //! Tests whether the register is a mask register of any size. + ASMJIT_INLINE_NODEBUG constexpr bool isMask() const noexcept { return isGroup(RegGroup::kMask); } using Operand_::isReg; //! Same as `isType()`, provided for convenience. - inline constexpr bool isReg(RegType rType) const noexcept { return isType(rType); } + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType rType) const noexcept { return isType(rType); } //! Tests whether the register type matches `type` and register id matches `id`. - inline constexpr bool isReg(RegType rType, uint32_t id) const noexcept { return isType(rType) && this->id() == id; } + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType rType, uint32_t id) const noexcept { return isType(rType) && this->id() == id; } //! Returns the register type. - inline constexpr RegType type() const noexcept { return _signature.regType(); } + ASMJIT_INLINE_NODEBUG constexpr RegType type() const noexcept { return _signature.regType(); } //! Returns the register group. - inline constexpr RegGroup group() const noexcept { return _signature.regGroup(); } + ASMJIT_INLINE_NODEBUG constexpr RegGroup group() const noexcept { return _signature.regGroup(); } + + //! Tests whether the register specifies a size (i.e. the size is not zero). + ASMJIT_INLINE_NODEBUG constexpr bool hasSize() const noexcept { return _signature.hasField<Signature::kSizeMask>(); } + //! Tests whether the register size matches size `s`. + ASMJIT_INLINE_NODEBUG constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; } + + //! Returns the size of the register in bytes. If the register size depends on architecture (like `x86::CReg` and + //! `x86::DReg`) the size returned should be the greatest possible (so it should return 64-bit size in such case). + ASMJIT_INLINE_NODEBUG constexpr uint32_t size() const noexcept { return _signature.getField<Signature::kSizeMask>(); } //! Returns operation predicate of the register (ARM/AArch64). //! //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp //! of the register. - inline constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); } //! Sets operation predicate of the register to `predicate` (ARM/AArch64). //! //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp //! of the register. - inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); } + ASMJIT_INLINE_NODEBUG void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); } //! Resets shift operation type of the register to the default value (ARM/AArch64). - inline void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); } + ASMJIT_INLINE_NODEBUG void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); } //! Clones the register operand. - inline constexpr BaseReg clone() const noexcept { return BaseReg(*this); } + ASMJIT_INLINE_NODEBUG constexpr BaseReg clone() const noexcept { return BaseReg(*this); } //! Casts this register to `RegT` by also changing its signature. //! //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. template<typename RegT> - inline constexpr RegT cloneAs() const noexcept { return RegT(Signature(RegT::kSignature), id()); } + ASMJIT_INLINE_NODEBUG constexpr RegT cloneAs() const noexcept { return RegT(Signature(RegT::kSignature), id()); } //! Casts this register to `other` by also changing its signature. //! //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. template<typename RegT> - inline constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(other.signature(), id()); } + ASMJIT_INLINE_NODEBUG constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(other.signature(), id()); } //! Sets the register id to `id`. - inline void setId(uint32_t id) noexcept { _baseId = id; } + ASMJIT_INLINE_NODEBUG void setId(uint32_t id) noexcept { _baseId = id; } //! Sets a 32-bit operand signature based on traits of `RegT`. template<typename RegT> - inline void setSignatureT() noexcept { _signature = RegT::kSignature; } + ASMJIT_INLINE_NODEBUG void setSignatureT() noexcept { _signature = RegT::kSignature; } //! Sets the register `signature` and `id`. - inline void setSignatureAndId(const OperandSignature& signature, uint32_t id) noexcept { + ASMJIT_INLINE_NODEBUG void setSignatureAndId(const OperandSignature& signature, uint32_t id) noexcept { _signature = signature; _baseId = id; } @@ -982,21 +1068,21 @@ public: //! \{ //! Tests whether the `op` operand is a general purpose register. - static inline bool isGp(const Operand_& op) noexcept { + static ASMJIT_INLINE_NODEBUG bool isGp(const Operand_& op) noexcept { // Check operand type and register group. Not interested in register type and size. return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kGp)); } //! Tests whether the `op` operand is a vector register. - static inline bool isVec(const Operand_& op) noexcept { + static ASMJIT_INLINE_NODEBUG bool isVec(const Operand_& op) noexcept { // Check operand type and register group. Not interested in register type and size. return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kVec)); } //! Tests whether the `op` is a general purpose register of the given `id`. - static inline bool isGp(const Operand_& op, uint32_t id) noexcept { return isGp(op) & (op.id() == id); } + static ASMJIT_INLINE_NODEBUG bool isGp(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isGp(op)) & unsigned(op.id() == id)); } //! Tests whether the `op` is a vector register of the given `id`. - static inline bool isVec(const Operand_& op, uint32_t id) noexcept { return isVec(op) & (op.id() == id); } + static ASMJIT_INLINE_NODEBUG bool isVec(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVec(op)) & unsigned(op.id() == id)); } //! \} }; @@ -1021,16 +1107,16 @@ struct RegOnly { //! \{ //! Initializes the `RegOnly` instance to hold register `signature` and `id`. - inline void init(const OperandSignature& signature, uint32_t id) noexcept { + ASMJIT_INLINE_NODEBUG void init(const OperandSignature& signature, uint32_t id) noexcept { _signature = signature; _id = id; } - inline void init(const BaseReg& reg) noexcept { init(reg.signature(), reg.id()); } - inline void init(const RegOnly& reg) noexcept { init(reg.signature(), reg.id()); } + ASMJIT_INLINE_NODEBUG void init(const BaseReg& reg) noexcept { init(reg.signature(), reg.id()); } + ASMJIT_INLINE_NODEBUG void init(const RegOnly& reg) noexcept { init(reg.signature(), reg.id()); } //! Resets the `RegOnly` members to zeros (none). - inline void reset() noexcept { init(Signature::fromBits(0), 0); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { init(Signature::fromBits(0), 0); } //! \} @@ -1038,30 +1124,30 @@ struct RegOnly { //! \{ //! Tests whether this ExtraReg is none (same as calling `Operand_::isNone()`). - inline constexpr bool isNone() const noexcept { return _signature == 0; } + ASMJIT_INLINE_NODEBUG constexpr bool isNone() const noexcept { return _signature == 0; } //! Tests whether the register is valid (either virtual or physical). - inline constexpr bool isReg() const noexcept { return _signature != 0; } + ASMJIT_INLINE_NODEBUG constexpr bool isReg() const noexcept { return _signature != 0; } //! Tests whether this is a physical register. - inline constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; } //! Tests whether this is a virtual register (used by `BaseCompiler`). - inline constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; } //! Returns the register signature or 0 if no register is assigned. - inline constexpr OperandSignature signature() const noexcept { return _signature; } + ASMJIT_INLINE_NODEBUG constexpr OperandSignature signature() const noexcept { return _signature; } //! Returns the register id. //! //! \note Always check whether the register is assigned before using the returned identifier as //! non-assigned `RegOnly` instance would return zero id, which is still a valid register id. - inline constexpr uint32_t id() const noexcept { return _id; } + ASMJIT_INLINE_NODEBUG constexpr uint32_t id() const noexcept { return _id; } //! Sets the register id. - inline void setId(uint32_t id) noexcept { _id = id; } + ASMJIT_INLINE_NODEBUG void setId(uint32_t id) noexcept { _id = id; } //! Returns the register type. - inline constexpr RegType type() const noexcept { return _signature.regType(); } + ASMJIT_INLINE_NODEBUG constexpr RegType type() const noexcept { return _signature.regType(); } //! Returns the register group. - inline constexpr RegGroup group() const noexcept { return _signature.regGroup(); } + ASMJIT_INLINE_NODEBUG constexpr RegGroup group() const noexcept { return _signature.regGroup(); } //! \} @@ -1070,85 +1156,270 @@ struct RegOnly { //! Converts this ExtraReg to a real `RegT` operand. template<typename RegT> - inline constexpr RegT toReg() const noexcept { return RegT(_signature, _id); } + ASMJIT_INLINE_NODEBUG constexpr RegT toReg() const noexcept { return RegT(_signature, _id); } //! \} }; //! \cond INTERNAL //! Adds a template specialization for `REG_TYPE` into the local `RegTraits`. -#define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID) \ -template<> \ -struct RegTraits<REG_TYPE> { \ - typedef REG RegT; \ - \ - enum : uint32_t { \ - kValid = uint32_t(true), \ - kCount = uint32_t(COUNT), \ - kType = uint32_t(REG_TYPE), \ - kGroup = uint32_t(GROUP), \ - kSize = uint32_t(SIZE), \ - kTypeId = uint32_t(TYPE_ID), \ - \ - kSignature = (OperandSignature::fromOpType(OperandType::kReg) | \ - OperandSignature::fromRegType(REG_TYPE) | \ - OperandSignature::fromRegGroup(GROUP) | \ - OperandSignature::fromSize(kSize)).bits(), \ - }; \ +#define ASMJIT_DEFINE_REG_TRAITS(REG_TYPE, GROUP, SIZE, TYPE_ID) \ +template<> \ +struct RegTraits<REG_TYPE> { \ + static constexpr uint32_t kValid = 1; \ + static constexpr RegType kType = REG_TYPE; \ + static constexpr RegGroup kGroup = GROUP; \ + static constexpr uint32_t kSize = SIZE; \ + static constexpr TypeId kTypeId = TYPE_ID; \ + \ + static constexpr uint32_t kSignature = \ + (OperandSignature::fromOpType(OperandType::kReg) | \ + OperandSignature::fromRegType(kType) | \ + OperandSignature::fromRegGroup(kGroup) | \ + OperandSignature::fromSize(kSize)).bits(); \ + \ } //! Adds constructors and member functions to a class that implements abstract register. Abstract register is register //! that doesn't have type or signature yet, it's a base class like `x86::Reg` or `arm::Reg`. -#define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ -public: \ - /*! Default constructor that only setups basics. */ \ - inline constexpr REG() noexcept \ - : BASE(Signature{kSignature}, kIdBad) {} \ - \ - /*! Makes a copy of the `other` register operand. */ \ - inline constexpr REG(const REG& other) noexcept \ - : BASE(other) {} \ - \ - /*! Makes a copy of the `other` register having id set to `id` */ \ - inline constexpr REG(const BaseReg& other, uint32_t id) noexcept \ - : BASE(other, id) {} \ - \ - /*! Creates a register based on `signature` and `id`. */ \ - inline constexpr REG(const OperandSignature& sgn, uint32_t id) noexcept \ - : BASE(sgn, id) {} \ - \ - /*! Creates a completely uninitialized REG register operand (garbage). */ \ - inline explicit REG(Globals::NoInit_) noexcept \ - : BASE(Globals::NoInit) {} \ - \ - /*! Creates a new register from register type and id. */ \ - static inline REG fromTypeAndId(RegType type, uint32_t id) noexcept { \ - return REG(signatureOf(type), id); \ - } \ - \ - /*! Clones the register operand. */ \ - inline constexpr REG clone() const noexcept { return REG(*this); } \ - \ - inline REG& operator=(const REG& other) noexcept = default; +#define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ +public: \ + /*! Default constructor that only setups basics. */ \ + ASMJIT_INLINE_NODEBUG constexpr REG() noexcept \ + : BASE(Signature{kSignature}, kIdBad) {} \ + \ + /*! Makes a copy of the `other` register operand. */ \ + ASMJIT_INLINE_NODEBUG constexpr REG(const REG& other) noexcept \ + : BASE(other) {} \ + \ + /*! Makes a copy of the `other` register having id set to `id` */ \ + ASMJIT_INLINE_NODEBUG constexpr REG(const BaseReg& other, uint32_t id) noexcept \ + : BASE(other, id) {} \ + \ + /*! Creates a register based on `signature` and `id`. */ \ + ASMJIT_INLINE_NODEBUG constexpr REG(const OperandSignature& sgn, uint32_t id) noexcept \ + : BASE(sgn, id) {} \ + \ + /*! Creates a completely uninitialized REG register operand (garbage). */ \ + ASMJIT_INLINE_NODEBUG explicit REG(Globals::NoInit_) noexcept \ + : BASE(Globals::NoInit) {} \ + \ + /*! Creates a new register from register type and id. */ \ + static ASMJIT_INLINE_NODEBUG REG fromTypeAndId(RegType type, uint32_t id) noexcept { \ + return REG(signatureOf(type), id); \ + } \ + \ + /*! Clones the register operand. */ \ + ASMJIT_INLINE_NODEBUG constexpr REG clone() const noexcept { return REG(*this); } \ + \ + ASMJIT_INLINE_NODEBUG REG& operator=(const REG& other) noexcept = default; //! Adds constructors and member functions to a class that implements final register. Final registers MUST HAVE a valid //! signature. -#define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS) \ -public: \ - enum : uint32_t { \ - kThisType = TRAITS::kType, \ - kThisGroup = TRAITS::kGroup, \ - kThisSize = TRAITS::kSize, \ - kSignature = TRAITS::kSignature \ - }; \ - \ - ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ - \ - /*! Creates a register operand having its id set to `id`. */ \ - inline constexpr explicit REG(uint32_t id) noexcept \ +#define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS) \ +public: \ + static constexpr RegType kThisType = TRAITS::kType; \ + static constexpr RegGroup kThisGroup = TRAITS::kGroup; \ + static constexpr uint32_t kThisSize = TRAITS::kSize; \ + static constexpr uint32_t kSignature = TRAITS::kSignature; \ + \ + ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ + \ + /*! Creates a register operand having its id set to `id`. */ \ + ASMJIT_INLINE_NODEBUG constexpr explicit REG(uint32_t id) noexcept \ : BASE(Signature{kSignature}, id) {} //! \endcond +//! List of physical registers (base). +//! +//! \note List of registers is only used by some ARM instructions at the moment. +class BaseRegList : public Operand { +public: + //! \name Constants + //! \{ + + enum : uint32_t { + kSignature = Signature::fromOpType(OperandType::kRegList).bits() + }; + + //! \} + + //! \name Construction & Destruction + //! \{ + + //! Creates a dummy register operand. + ASMJIT_INLINE_NODEBUG constexpr BaseRegList() noexcept + : Operand(Globals::Init, Signature::fromOpType(OperandType::kRegList), 0, 0, 0) {} + + //! Creates a new register operand which is the same as `other` . + ASMJIT_INLINE_NODEBUG constexpr BaseRegList(const BaseRegList& other) noexcept + : Operand(other) {} + + //! Creates a new register operand compatible with `other`, but with a different `id`. + ASMJIT_INLINE_NODEBUG constexpr BaseRegList(const BaseRegList& other, RegMask regMask) noexcept + : Operand(Globals::Init, other._signature, regMask, 0, 0) {} + + //! Creates a register initialized to the given `signature` and `id`. + ASMJIT_INLINE_NODEBUG constexpr BaseRegList(const Signature& signature, RegMask regMask) noexcept + : Operand(Globals::Init, signature, regMask, 0, 0) {} + + ASMJIT_INLINE_NODEBUG explicit BaseRegList(Globals::NoInit_) noexcept + : Operand(Globals::NoInit) {} + + //! \} + + //! \name Overloaded Operators + //! \{ + + ASMJIT_INLINE_NODEBUG BaseRegList& operator=(const BaseRegList& other) noexcept = default; + + //! \} + + //! \name Accessors + //! \{ + + //! Tests whether the register-list is valid, which means it has a type and at least a single register in the list. + ASMJIT_INLINE_NODEBUG constexpr bool isValid() const noexcept { return bool(unsigned(_signature != 0u) & unsigned(_baseId != 0u)); } + + //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience. + ASMJIT_INLINE_NODEBUG constexpr bool isType(RegType type) const noexcept { return _signature.subset(Signature::kRegTypeMask) == Signature::fromRegType(type); } + //! Tests whether the register group matches `group`. + ASMJIT_INLINE_NODEBUG constexpr bool isGroup(RegGroup group) const noexcept { return _signature.subset(Signature::kRegGroupMask) == Signature::fromRegGroup(group); } + + //! Tests whether the register is a general purpose register (any size). + ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); } + //! Tests whether the register is a vector register. + ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); } + + //! Returns the register type. + ASMJIT_INLINE_NODEBUG constexpr RegType type() const noexcept { return _signature.regType(); } + //! Returns the register group. + ASMJIT_INLINE_NODEBUG constexpr RegGroup group() const noexcept { return _signature.regGroup(); } + //! Returns the size of a single register in this register-list or 0 if unspecified. + ASMJIT_INLINE_NODEBUG constexpr uint32_t size() const noexcept { return _signature.getField<Signature::kSizeMask>(); } + + //! Returns the register list as a mask, where each bit represents one physical register. + ASMJIT_INLINE_NODEBUG constexpr RegMask list() const noexcept { return _baseId; } + //! Sets the register list to `mask`. + ASMJIT_INLINE_NODEBUG void setList(RegMask mask) noexcept { _baseId = mask; } + //! Remoes all registers from the register-list by making the underlying register-mask zero. + ASMJIT_INLINE_NODEBUG void resetList() noexcept { _baseId = 0; } + + //! Adds registers passed by a register `mask` to the register-list. + ASMJIT_INLINE_NODEBUG void addList(RegMask mask) noexcept { _baseId |= mask; } + //! Removes registers passed by a register `mask` to the register-list. + ASMJIT_INLINE_NODEBUG void clearList(RegMask mask) noexcept { _baseId &= ~mask; } + //! Uses AND operator to combine the current register-list with other register `mask`. + ASMJIT_INLINE_NODEBUG void andList(RegMask mask) noexcept { _baseId &= mask; } + //! Uses XOR operator to combine the current register-list with other register `mask`. + ASMJIT_INLINE_NODEBUG void xorList(RegMask mask) noexcept { _baseId ^= mask; } + + //! Checks whether a physical register `physId` is in the register-list. + ASMJIT_INLINE_NODEBUG bool hasReg(uint32_t physId) const noexcept { return physId < 32u ? (_baseId & (1u << physId)) != 0 : false; } + //! Adds a physical register `physId` to the register-list. + ASMJIT_INLINE_NODEBUG void addReg(uint32_t physId) noexcept { addList(1u << physId); } + //! Removes a physical register `physId` from the register-list. + ASMJIT_INLINE_NODEBUG void clearReg(uint32_t physId) noexcept { clearList(1u << physId); } + + //! Clones the register-list operand. + ASMJIT_INLINE_NODEBUG constexpr BaseRegList clone() const noexcept { return BaseRegList(*this); } + + //! Casts this register to `RegT` by also changing its signature. + //! + //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. + template<typename RegListT> + ASMJIT_INLINE_NODEBUG constexpr RegListT cloneAs() const noexcept { return RegListT(Signature(RegListT::kSignature), list()); } + + //! Casts this register to `other` by also changing its signature. + //! + //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. + template<typename RegListT> + ASMJIT_INLINE_NODEBUG constexpr RegListT cloneAs(const RegListT& other) const noexcept { return RegListT(other.signature(), list()); } + + //! \} +}; + +template<typename RegT> +class RegListT : public BaseRegList { +public: + //! \name Construction & Destruction + //! \{ + + //! Creates a dummy register operand. + ASMJIT_INLINE_NODEBUG constexpr RegListT() noexcept + : BaseRegList() {} + + //! Creates a new register operand which is the same as `other` . + ASMJIT_INLINE_NODEBUG constexpr RegListT(const RegListT& other) noexcept + : BaseRegList(other) {} + + //! Creates a new register operand compatible with `other`, but with a different `id`. + ASMJIT_INLINE_NODEBUG constexpr RegListT(const RegListT& other, RegMask regMask) noexcept + : BaseRegList(other, regMask) {} + + //! Creates a register initialized to the given `signature` and `id`. + ASMJIT_INLINE_NODEBUG constexpr RegListT(const Signature& signature, RegMask regMask) noexcept + : BaseRegList(signature, regMask) {} + + //! Creates a register initialized to the given `signature` and `regs`. + ASMJIT_INLINE_NODEBUG RegListT(const Signature& signature, std::initializer_list<RegT> regs) noexcept + : BaseRegList(signature, RegMask(0)) { addRegs(regs); } + + ASMJIT_INLINE_NODEBUG explicit RegListT(Globals::NoInit_) noexcept + : BaseRegList(Globals::NoInit) {} + + //! \} + + //! \name Overloaded Operators + //! \{ + + ASMJIT_INLINE_NODEBUG RegListT& operator=(const RegListT& other) noexcept = default; + + //! \} + + //! \name Accessors + //! \{ + + using BaseRegList::addList; + using BaseRegList::clearList; + using BaseRegList::andList; + using BaseRegList::xorList; + + //! Adds registers to this register-list as provided by `other` register-list. + ASMJIT_INLINE_NODEBUG void addList(const RegListT<RegT>& other) noexcept { addList(other.list()); } + //! Removes registers contained in `other` register-list. + ASMJIT_INLINE_NODEBUG void clearList(const RegListT<RegT>& other) noexcept { clearList(other.list()); } + //! Uses AND operator to combine the current register-list with `other` register-list. + ASMJIT_INLINE_NODEBUG void andList(const RegListT<RegT>& other) noexcept { andList(other.list()); } + //! Uses XOR operator to combine the current register-list with `other` register-list. + ASMJIT_INLINE_NODEBUG void xorList(const RegListT<RegT>& other) noexcept { xorList(other.list()); } + + using BaseRegList::addReg; + using BaseRegList::clearReg; + + ASMJIT_INLINE_NODEBUG void addReg(const RegT& reg) noexcept { + if (reg.id() < 32u) + addReg(reg.id()); + } + + ASMJIT_INLINE_NODEBUG void addRegs(std::initializer_list<RegT> regs) noexcept { + for (const RegT& reg : regs) + addReg(reg); + } + + ASMJIT_INLINE_NODEBUG void clearReg(const RegT& reg) noexcept { + if (reg.id() < 32u) + clearReg(reg.id()); + } + + ASMJIT_INLINE_NODEBUG void clearRegs(std::initializer_list<RegT> regs) noexcept { + for (const RegT& reg : regs) + clearReg(reg); + } + + //! \} +}; + //! Base class for all memory operands. //! //! The data is split into the following parts: @@ -1174,18 +1445,18 @@ public: //! \{ //! Creates a default `BaseMem` operand, that points to [0]. - inline constexpr BaseMem() noexcept + ASMJIT_INLINE_NODEBUG constexpr BaseMem() noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kMem), 0, 0, 0) {} //! Creates a `BaseMem` operand that is a clone of `other`. - inline constexpr BaseMem(const BaseMem& other) noexcept + ASMJIT_INLINE_NODEBUG constexpr BaseMem(const BaseMem& other) noexcept : Operand(other) {} //! Creates a `BaseMem` operand from `baseReg` and `offset`. //! //! \note This is an architecture independent constructor that can be used to create an architecture //! independent memory operand to be used in portable code that can handle multiple architectures. - inline constexpr explicit BaseMem(const BaseReg& baseReg, int32_t offset = 0) noexcept + ASMJIT_INLINE_NODEBUG constexpr explicit BaseMem(const BaseReg& baseReg, int32_t offset = 0) noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(baseReg.type()), baseReg.id(), @@ -1194,16 +1465,16 @@ public: //! \cond INTERNAL //! Creates a `BaseMem` operand from 4 integers as used by `Operand_` struct. - inline constexpr BaseMem(const OperandSignature& u0, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept + ASMJIT_INLINE_NODEBUG constexpr BaseMem(const OperandSignature& u0, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept : Operand(Globals::Init, u0, baseId, indexId, uint32_t(offset)) {} //! \endcond //! Creates a completely uninitialized `BaseMem` operand. - inline explicit BaseMem(Globals::NoInit_) noexcept + ASMJIT_INLINE_NODEBUG explicit BaseMem(Globals::NoInit_) noexcept : Operand(Globals::NoInit) {} //! Resets the memory operand - after the reset the memory points to [0]. - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _signature = Signature::fromOpType(OperandType::kMem); _baseId = 0; _data[0] = 0; @@ -1215,7 +1486,7 @@ public: //! \name Overloaded Operators //! \{ - inline BaseMem& operator=(const BaseMem& other) noexcept { copyFrom(other); return *this; } + ASMJIT_INLINE_NODEBUG BaseMem& operator=(const BaseMem& other) noexcept { copyFrom(other); return *this; } //! \} @@ -1223,54 +1494,54 @@ public: //! \{ //! Clones the memory operand. - inline constexpr BaseMem clone() const noexcept { return BaseMem(*this); } + ASMJIT_INLINE_NODEBUG constexpr BaseMem clone() const noexcept { return BaseMem(*this); } //! Creates a new copy of this memory operand adjusted by `off`. - inline BaseMem cloneAdjusted(int64_t off) const noexcept { + ASMJIT_INLINE_NODEBUG BaseMem cloneAdjusted(int64_t off) const noexcept { BaseMem result(*this); result.addOffset(off); return result; } //! Tests whether this memory operand is a register home (only used by \ref asmjit_compiler) - inline constexpr bool isRegHome() const noexcept { return _signature.hasField<Signature::kMemRegHomeFlag>(); } + ASMJIT_INLINE_NODEBUG constexpr bool isRegHome() const noexcept { return _signature.hasField<Signature::kMemRegHomeFlag>(); } //! Mark this memory operand as register home (only used by \ref asmjit_compiler). - inline void setRegHome() noexcept { _signature |= Signature::kMemRegHomeFlag; } + ASMJIT_INLINE_NODEBUG void setRegHome() noexcept { _signature |= Signature::kMemRegHomeFlag; } //! Marks this operand to not be a register home (only used by \ref asmjit_compiler). - inline void clearRegHome() noexcept { _signature &= ~Signature::kMemRegHomeFlag; } + ASMJIT_INLINE_NODEBUG void clearRegHome() noexcept { _signature &= ~Signature::kMemRegHomeFlag; } //! Tests whether the memory operand has a BASE register or label specified. - inline constexpr bool hasBase() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool hasBase() const noexcept { return (_signature & Signature::kMemBaseTypeMask) != 0; } //! Tests whether the memory operand has an INDEX register specified. - inline constexpr bool hasIndex() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool hasIndex() const noexcept { return (_signature & Signature::kMemIndexTypeMask) != 0; } //! Tests whether the memory operand has BASE or INDEX register. - inline constexpr bool hasBaseOrIndex() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool hasBaseOrIndex() const noexcept { return (_signature & Signature::kMemBaseIndexMask) != 0; } //! Tests whether the memory operand has BASE and INDEX register. - inline constexpr bool hasBaseAndIndex() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool hasBaseAndIndex() const noexcept { return (_signature & Signature::kMemBaseTypeMask) != 0 && (_signature & Signature::kMemIndexTypeMask) != 0; } //! Tests whether the BASE operand is a label. - inline constexpr bool hasBaseLabel() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool hasBaseLabel() const noexcept { return _signature.subset(Signature::kMemBaseTypeMask) == Signature::fromMemBaseType(RegType::kLabelTag); } //! Tests whether the BASE operand is a register (registers start after `RegType::kLabelTag`). - inline constexpr bool hasBaseReg() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool hasBaseReg() const noexcept { return _signature.subset(Signature::kMemBaseTypeMask).bits() > Signature::fromMemBaseType(RegType::kLabelTag).bits(); } //! Tests whether the INDEX operand is a register (registers start after `RegType::kLabelTag`). - inline constexpr bool hasIndexReg() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool hasIndexReg() const noexcept { return _signature.subset(Signature::kMemIndexTypeMask).bits() > Signature::fromMemIndexType(RegType::kLabelTag).bits(); } @@ -1278,76 +1549,78 @@ public: //! //! \note If the returned type is one (a value never associated to a register type) the BASE is not register, but it //! is a label. One equals to `kLabelTag`. You should always check `hasBaseLabel()` before using `baseId()` result. - inline constexpr RegType baseType() const noexcept { return _signature.memBaseType(); } + ASMJIT_INLINE_NODEBUG constexpr RegType baseType() const noexcept { return _signature.memBaseType(); } //! Returns the type of an INDEX register (0 if this memory operand doesn't //! use the INDEX register). - inline constexpr RegType indexType() const noexcept { return _signature.memIndexType(); } + ASMJIT_INLINE_NODEBUG constexpr RegType indexType() const noexcept { return _signature.memIndexType(); } //! This is used internally for BASE+INDEX validation. - inline constexpr uint32_t baseAndIndexTypes() const noexcept { return _signature.getField<Signature::kMemBaseIndexMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t baseAndIndexTypes() const noexcept { return _signature.getField<Signature::kMemBaseIndexMask>(); } //! Returns both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a single value. //! //! \remarks Returns id of the BASE register or label (if the BASE was specified as label). - inline constexpr uint32_t baseId() const noexcept { return _baseId; } + ASMJIT_INLINE_NODEBUG constexpr uint32_t baseId() const noexcept { return _baseId; } //! Returns the id of the INDEX register. - inline constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; } + ASMJIT_INLINE_NODEBUG constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; } //! Sets the id of the BASE register (without modifying its type). - inline void setBaseId(uint32_t id) noexcept { _baseId = id; } + ASMJIT_INLINE_NODEBUG void setBaseId(uint32_t id) noexcept { _baseId = id; } + //! Sets the register type of the BASE register (without modifying its id). + ASMJIT_INLINE_NODEBUG void setBaseType(RegType regType) noexcept { _signature.setMemBaseType(regType); } + //! Sets the id of the INDEX register (without modifying its type). - inline void setIndexId(uint32_t id) noexcept { _data[kDataMemIndexId] = id; } + ASMJIT_INLINE_NODEBUG void setIndexId(uint32_t id) noexcept { _data[kDataMemIndexId] = id; } + //! Sets the register type of the INDEX register (without modifying its id). + ASMJIT_INLINE_NODEBUG void setIndexType(RegType regType) noexcept { _signature.setMemIndexType(regType); } //! Sets the base register to type and id of the given `base` operand. - inline void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); } + ASMJIT_INLINE_NODEBUG void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); } //! Sets the index register to type and id of the given `index` operand. - inline void setIndex(const BaseReg& index) noexcept { return _setIndex(index.type(), index.id()); } + ASMJIT_INLINE_NODEBUG void setIndex(const BaseReg& index) noexcept { return _setIndex(index.type(), index.id()); } //! \cond INTERNAL - inline void _setBase(RegType type, uint32_t id) noexcept { + ASMJIT_INLINE_NODEBUG void _setBase(RegType type, uint32_t id) noexcept { _signature.setField<Signature::kMemBaseTypeMask>(uint32_t(type)); _baseId = id; } - inline void _setIndex(RegType type, uint32_t id) noexcept { + ASMJIT_INLINE_NODEBUG void _setIndex(RegType type, uint32_t id) noexcept { _signature.setField<Signature::kMemIndexTypeMask>(uint32_t(type)); _data[kDataMemIndexId] = id; } //! \endcond //! Resets the memory operand's BASE register or label. - inline void resetBase() noexcept { _setBase(RegType::kNone, 0); } + ASMJIT_INLINE_NODEBUG void resetBase() noexcept { _setBase(RegType::kNone, 0); } //! Resets the memory operand's INDEX register. - inline void resetIndex() noexcept { _setIndex(RegType::kNone, 0); } - - //! Sets the memory operand size (in bytes). - inline void setSize(uint32_t size) noexcept { _signature.setField<Signature::kSizeMask>(size); } + ASMJIT_INLINE_NODEBUG void resetIndex() noexcept { _setIndex(RegType::kNone, 0); } //! Tests whether the memory operand has a 64-bit offset or absolute address. //! //! If this is true then `hasBase()` must always report false. - inline constexpr bool isOffset64Bit() const noexcept { return baseType() == RegType::kNone; } + ASMJIT_INLINE_NODEBUG constexpr bool isOffset64Bit() const noexcept { return baseType() == RegType::kNone; } //! Tests whether the memory operand has a non-zero offset or absolute address. - inline constexpr bool hasOffset() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr bool hasOffset() const noexcept { return (_data[kDataMemOffsetLo] | uint32_t(_baseId & Support::bitMaskFromBool<uint32_t>(isOffset64Bit()))) != 0; } //! Returns either relative offset or absolute address as 64-bit integer. - inline constexpr int64_t offset() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr int64_t offset() const noexcept { return isOffset64Bit() ? int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32)) : int64_t(int32_t(_data[kDataMemOffsetLo])); // Sign extend 32-bit offset. } //! Returns a 32-bit low part of a 64-bit offset or absolute address. - inline constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); } + ASMJIT_INLINE_NODEBUG constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); } //! Returns a 32-but high part of a 64-bit offset or absolute address. //! //! \note This function is UNSAFE and returns garbage if `isOffset64Bit()` //! returns false. Never use it blindly without checking it first. - inline constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); } + ASMJIT_INLINE_NODEBUG constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); } //! Sets a 64-bit offset or an absolute address to `offset`. //! @@ -1383,15 +1656,20 @@ public: } //! Adds `offset` to a low 32-bit offset part (don't use without knowing how BaseMem works). - inline void addOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] += uint32_t(offset); } + ASMJIT_INLINE_NODEBUG void addOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] += uint32_t(offset); } //! Resets the memory offset to zero. - inline void resetOffset() noexcept { setOffset(0); } + ASMJIT_INLINE_NODEBUG void resetOffset() noexcept { setOffset(0); } //! Resets the lo part of the memory offset to zero (don't use without knowing how BaseMem works). - inline void resetOffsetLo32() noexcept { setOffsetLo32(0); } + ASMJIT_INLINE_NODEBUG void resetOffsetLo32() noexcept { setOffsetLo32(0); } //! \} + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("setSize() is no longer portable - use setX86RmSize() or x86::Mem::setSize() instead, if your target is X86/X86_64") + ASMJIT_INLINE_NODEBUG void setSize(uint32_t size) noexcept { _signature.setField<Signature::kSizeMask>(size); } +#endif }; //! Type of the an immediate value. @@ -1423,15 +1701,15 @@ public: //! \{ //! Creates a new immediate value (initial value is 0). - inline constexpr Imm() noexcept + ASMJIT_INLINE_NODEBUG constexpr Imm() noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kImm), 0, 0, 0) {} //! Creates a new immediate value from `other`. - inline constexpr Imm(const Imm& other) noexcept + ASMJIT_INLINE_NODEBUG constexpr Imm(const Imm& other) noexcept : Operand(other) {} //! Creates a new immediate value from ARM/AArch64 specific `shift`. - inline constexpr Imm(const arm::Shift& shift) noexcept + ASMJIT_INLINE_NODEBUG constexpr Imm(const arm::Shift& shift) noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(uint32_t(shift.op())), 0, @@ -1443,28 +1721,28 @@ public: //! //! \note Predicate is currently only used by ARM architectures. template<typename T, typename = typename std::enable_if<IsConstexprConstructibleAsImmType<typename std::decay<T>::type>::value>::type> - inline constexpr Imm(const T& val, const uint32_t predicate = 0) noexcept + ASMJIT_INLINE_NODEBUG constexpr Imm(const T& val, const uint32_t predicate = 0) noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate), 0, Support::unpackU32At0(int64_t(val)), Support::unpackU32At1(int64_t(val))) {} - inline Imm(const float& val, const uint32_t predicate = 0) noexcept + ASMJIT_INLINE_NODEBUG Imm(const float& val, const uint32_t predicate = 0) noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate), 0, 0, 0) { setValue(val); } - inline Imm(const double& val, const uint32_t predicate = 0) noexcept + ASMJIT_INLINE_NODEBUG Imm(const double& val, const uint32_t predicate = 0) noexcept : Operand(Globals::Init, Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate), 0, 0, 0) { setValue(val); } - inline explicit Imm(Globals::NoInit_) noexcept + ASMJIT_INLINE_NODEBUG explicit Imm(Globals::NoInit_) noexcept : Operand(Globals::NoInit) {} //! \} @@ -1473,7 +1751,7 @@ public: //! \{ //! Assigns the value of the `other` operand to this immediate. - inline Imm& operator=(const Imm& other) noexcept { copyFrom(other); return *this; } + ASMJIT_INLINE_NODEBUG Imm& operator=(const Imm& other) noexcept { copyFrom(other); return *this; } //! \} @@ -1481,73 +1759,73 @@ public: //! \{ //! Returns immediate type. - inline constexpr ImmType type() const noexcept { return (ImmType)_signature.getField<Signature::kImmTypeMask>(); } + ASMJIT_INLINE_NODEBUG constexpr ImmType type() const noexcept { return (ImmType)_signature.getField<Signature::kImmTypeMask>(); } //! Sets the immediate type to `type`. - inline void setType(ImmType type) noexcept { _signature.setField<Signature::kImmTypeMask>(uint32_t(type)); } + ASMJIT_INLINE_NODEBUG void setType(ImmType type) noexcept { _signature.setField<Signature::kImmTypeMask>(uint32_t(type)); } //! Resets immediate type to \ref ImmType::kInt. - inline void resetType() noexcept { setType(ImmType::kInt); } + ASMJIT_INLINE_NODEBUG void resetType() noexcept { setType(ImmType::kInt); } //! Returns operation predicate of the immediate. //! //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp //! of the immediate. - inline constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); } //! Sets operation predicate of the immediate to `predicate`. //! //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp //! of the immediate. - inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); } + ASMJIT_INLINE_NODEBUG void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); } //! Resets the shift operation type of the immediate to the default value (no operation). - inline void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); } + ASMJIT_INLINE_NODEBUG void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); } //! Returns the immediate value as `int64_t`, which is the internal format Imm uses. - inline constexpr int64_t value() const noexcept { + ASMJIT_INLINE_NODEBUG constexpr int64_t value() const noexcept { return int64_t((uint64_t(_data[kDataImmValueHi]) << 32) | _data[kDataImmValueLo]); } //! Tests whether this immediate value is integer of any size. - inline constexpr uint32_t isInt() const noexcept { return type() == ImmType::kInt; } + ASMJIT_INLINE_NODEBUG constexpr uint32_t isInt() const noexcept { return type() == ImmType::kInt; } //! Tests whether this immediate value is a double precision floating point value. - inline constexpr uint32_t isDouble() const noexcept { return type() == ImmType::kDouble; } + ASMJIT_INLINE_NODEBUG constexpr uint32_t isDouble() const noexcept { return type() == ImmType::kDouble; } //! Tests whether the immediate can be casted to 8-bit signed integer. - inline constexpr bool isInt8() const noexcept { return type() == ImmType::kInt && Support::isInt8(value()); } + ASMJIT_INLINE_NODEBUG constexpr bool isInt8() const noexcept { return type() == ImmType::kInt && Support::isInt8(value()); } //! Tests whether the immediate can be casted to 8-bit unsigned integer. - inline constexpr bool isUInt8() const noexcept { return type() == ImmType::kInt && Support::isUInt8(value()); } + ASMJIT_INLINE_NODEBUG constexpr bool isUInt8() const noexcept { return type() == ImmType::kInt && Support::isUInt8(value()); } //! Tests whether the immediate can be casted to 16-bit signed integer. - inline constexpr bool isInt16() const noexcept { return type() == ImmType::kInt && Support::isInt16(value()); } + ASMJIT_INLINE_NODEBUG constexpr bool isInt16() const noexcept { return type() == ImmType::kInt && Support::isInt16(value()); } //! Tests whether the immediate can be casted to 16-bit unsigned integer. - inline constexpr bool isUInt16() const noexcept { return type() == ImmType::kInt && Support::isUInt16(value()); } + ASMJIT_INLINE_NODEBUG constexpr bool isUInt16() const noexcept { return type() == ImmType::kInt && Support::isUInt16(value()); } //! Tests whether the immediate can be casted to 32-bit signed integer. - inline constexpr bool isInt32() const noexcept { return type() == ImmType::kInt && Support::isInt32(value()); } + ASMJIT_INLINE_NODEBUG constexpr bool isInt32() const noexcept { return type() == ImmType::kInt && Support::isInt32(value()); } //! Tests whether the immediate can be casted to 32-bit unsigned integer. - inline constexpr bool isUInt32() const noexcept { return type() == ImmType::kInt && _data[kDataImmValueHi] == 0; } + ASMJIT_INLINE_NODEBUG constexpr bool isUInt32() const noexcept { return type() == ImmType::kInt && _data[kDataImmValueHi] == 0; } //! Returns the immediate value casted to `T`. //! //! The value is masked before it's casted to `T` so the returned value is simply the representation of `T` //! considering the original value's lowest bits. template<typename T> - inline T valueAs() const noexcept { return Support::immediateToT<T>(value()); } + ASMJIT_INLINE_NODEBUG T valueAs() const noexcept { return Support::immediateToT<T>(value()); } //! Returns low 32-bit signed integer. - inline constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); } + ASMJIT_INLINE_NODEBUG constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); } //! Returns high 32-bit signed integer. - inline constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); } + ASMJIT_INLINE_NODEBUG constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); } //! Returns low 32-bit signed integer. - inline constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; } + ASMJIT_INLINE_NODEBUG constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; } //! Returns high 32-bit signed integer. - inline constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; } + ASMJIT_INLINE_NODEBUG constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; } //! Sets immediate value to `val`, the value is casted to a signed 64-bit integer. template<typename T> - inline void setValue(const T& val) noexcept { + ASMJIT_INLINE_NODEBUG void setValue(const T& val) noexcept { _setValueInternal(Support::immediateFromT(val), std::is_floating_point<T>::value ? ImmType::kDouble : ImmType::kInt); } - inline void _setValueInternal(int64_t val, ImmType type) noexcept { + ASMJIT_INLINE_NODEBUG void _setValueInternal(int64_t val, ImmType type) noexcept { setType(type); _data[kDataImmValueHi] = uint32_t(uint64_t(val) >> 32); _data[kDataImmValueLo] = uint32_t(uint64_t(val) & 0xFFFFFFFFu); @@ -1559,22 +1837,22 @@ public: //! \{ //! Clones the immediate operand. - inline constexpr Imm clone() const noexcept { return Imm(*this); } + ASMJIT_INLINE_NODEBUG constexpr Imm clone() const noexcept { return Imm(*this); } - inline void signExtend8Bits() noexcept { setValue(int64_t(valueAs<int8_t>())); } - inline void signExtend16Bits() noexcept { setValue(int64_t(valueAs<int16_t>())); } - inline void signExtend32Bits() noexcept { setValue(int64_t(valueAs<int32_t>())); } + ASMJIT_INLINE_NODEBUG void signExtend8Bits() noexcept { setValue(int64_t(valueAs<int8_t>())); } + ASMJIT_INLINE_NODEBUG void signExtend16Bits() noexcept { setValue(int64_t(valueAs<int16_t>())); } + ASMJIT_INLINE_NODEBUG void signExtend32Bits() noexcept { setValue(int64_t(valueAs<int32_t>())); } - inline void zeroExtend8Bits() noexcept { setValue(valueAs<uint8_t>()); } - inline void zeroExtend16Bits() noexcept { setValue(valueAs<uint16_t>()); } - inline void zeroExtend32Bits() noexcept { _data[kDataImmValueHi] = 0u; } + ASMJIT_INLINE_NODEBUG void zeroExtend8Bits() noexcept { setValue(valueAs<uint8_t>()); } + ASMJIT_INLINE_NODEBUG void zeroExtend16Bits() noexcept { setValue(valueAs<uint16_t>()); } + ASMJIT_INLINE_NODEBUG void zeroExtend32Bits() noexcept { _data[kDataImmValueHi] = 0u; } //! \} }; //! Creates a new immediate operand. template<typename T> -static inline constexpr Imm imm(const T& val) noexcept { return Imm(val); } +static ASMJIT_INLINE_NODEBUG constexpr Imm imm(const T& val) noexcept { return Imm(val); } //! \} @@ -1590,12 +1868,12 @@ namespace Support { template<typename T, bool kIsImm> struct ForwardOpImpl { - static inline const T& forward(const T& value) noexcept { return value; } + static ASMJIT_INLINE_NODEBUG const T& forward(const T& value) noexcept { return value; } }; template<typename T> struct ForwardOpImpl<T, true> { - static inline Imm forward(const T& value) noexcept { return Imm(value); } + static ASMJIT_INLINE_NODEBUG Imm forward(const T& value) noexcept { return Imm(value); } }; //! Either forwards operand T or returns a new operand that wraps it if T is a type convertible to operand. diff --git a/3rdparty/asmjit/src/asmjit/core/osutils.cpp b/3rdparty/asmjit/src/asmjit/core/osutils.cpp index fa900bfbb4c..2d390697f89 100644 --- a/3rdparty/asmjit/src/asmjit/core/osutils.cpp +++ b/3rdparty/asmjit/src/asmjit/core/osutils.cpp @@ -4,81 +4,37 @@ // SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" -#include "../core/osutils.h" +#include "../core/osutils_p.h" #include "../core/support.h" -#if defined(_WIN32) - #include <atomic> -#elif defined(__APPLE__) - #include <mach/mach_time.h> -#else - #include <time.h> +#if !defined(_WIN32) + #include <fcntl.h> #include <unistd.h> #endif ASMJIT_BEGIN_NAMESPACE -uint32_t OSUtils::getTickCount() noexcept { -#if defined(_WIN32) - enum HiResStatus : uint32_t { - kHiResUnknown = 0, - kHiResAvailable = 1, - kHiResNotAvailable = 2 - }; +#if !defined(_WIN32) +Error OSUtils::readFile(const char* name, String& dst, size_t maxSize) noexcept { + char* buffer = dst.prepare(String::ModifyOp::kAssign, maxSize); + if (ASMJIT_UNLIKELY(!buffer)) + return DebugUtils::errored(kErrorOutOfMemory); - static std::atomic<uint32_t> _hiResStatus(kHiResUnknown); - static volatile double _hiResFreq(0); - - uint32_t status = _hiResStatus.load(); - LARGE_INTEGER now, qpf; - - if (status != kHiResNotAvailable && ::QueryPerformanceCounter(&now)) { - double freq = _hiResFreq; - if (status == kHiResUnknown) { - // Detects the availability of high resolution counter. - if (::QueryPerformanceFrequency(&qpf)) { - freq = double(qpf.QuadPart) / 1000.0; - _hiResFreq = freq; - _hiResStatus.compare_exchange_strong(status, kHiResAvailable); - status = kHiResAvailable; - } - else { - // High resolution not available. - _hiResStatus.compare_exchange_strong(status, kHiResNotAvailable); - } - } - - if (status == kHiResAvailable) - return uint32_t(uint64_t(int64_t(double(now.QuadPart) / freq)) & 0xFFFFFFFFu); + int fd = ASMJIT_FILE64_API(::open)(name, O_RDONLY); + if (fd < 0) { + dst.clear(); + return DebugUtils::errored(kErrorFailedToOpenFile); } - // Bail to `GetTickCount()` if we cannot use high resolution. - return ::GetTickCount(); -#elif defined(__APPLE__) - // See Apple's QA1398. - static mach_timebase_info_data_t _machTime; - - uint32_t denom = _machTime.denom; - if (ASMJIT_UNLIKELY(!denom)) { - if (mach_timebase_info(&_machTime) != KERN_SUCCESS || !(denom = _machTime.denom)) - return 0; + intptr_t len = ::read(fd, buffer, maxSize); + if (len >= 0) { + buffer[len] = '\0'; + dst._setSize(size_t(len)); } - // `mach_absolute_time()` returns nanoseconds, we want milliseconds. - uint64_t t = mach_absolute_time() / 1000000u; - t = (t * _machTime.numer) / _machTime.denom; - return uint32_t(t & 0xFFFFFFFFu); -#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 - struct timespec ts; - if (ASMJIT_UNLIKELY(clock_gettime(CLOCK_MONOTONIC, &ts) != 0)) - return 0; - - uint64_t t = (uint64_t(ts.tv_sec ) * 1000u) + (uint64_t(ts.tv_nsec) / 1000000u); - return uint32_t(t & 0xFFFFFFFFu); -#else - #pragma message("asmjit::OSUtils::getTickCount() doesn't have implementation for the target OS.") - return 0; -#endif + ::close(fd); + return kErrorOk; } +#endif ASMJIT_END_NAMESPACE diff --git a/3rdparty/asmjit/src/asmjit/core/osutils.h b/3rdparty/asmjit/src/asmjit/core/osutils.h index 3c5c3d94c1e..c6588373425 100644 --- a/3rdparty/asmjit/src/asmjit/core/osutils.h +++ b/3rdparty/asmjit/src/asmjit/core/osutils.h @@ -13,13 +13,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_utilities //! \{ -//! Operating system utilities. -namespace OSUtils { - //! Gets the current CPU tick count, used for benchmarking (1ms resolution). - ASMJIT_API uint32_t getTickCount() noexcept; -}; - - //! \cond INTERNAL //! Lock. //! @@ -46,11 +39,11 @@ public: Handle _handle; #endif - ASMJIT_FORCE_INLINE Lock() noexcept; - ASMJIT_FORCE_INLINE ~Lock() noexcept; + ASMJIT_INLINE_NODEBUG Lock() noexcept; + ASMJIT_INLINE_NODEBUG ~Lock() noexcept; - ASMJIT_FORCE_INLINE void lock() noexcept; - ASMJIT_FORCE_INLINE void unlock() noexcept; + ASMJIT_INLINE_NODEBUG void lock() noexcept; + ASMJIT_INLINE_NODEBUG void unlock() noexcept; }; //! \endcond diff --git a/3rdparty/asmjit/src/asmjit/core/osutils_p.h b/3rdparty/asmjit/src/asmjit/core/osutils_p.h index fd87e731123..0d9d36909e8 100644 --- a/3rdparty/asmjit/src/asmjit/core/osutils_p.h +++ b/3rdparty/asmjit/src/asmjit/core/osutils_p.h @@ -7,6 +7,7 @@ #define ASMJIT_CORE_OSUTILS_P_H_INCLUDED #include "../core/osutils.h" +#include "../core/string.h" ASMJIT_BEGIN_NAMESPACE @@ -20,30 +21,30 @@ ASMJIT_BEGIN_NAMESPACE static_assert(sizeof(Lock::Handle) == sizeof(CRITICAL_SECTION), "asmjit::Lock::Handle layout must match CRITICAL_SECTION"); static_assert(alignof(Lock::Handle) == alignof(CRITICAL_SECTION), "asmjit::Lock::Handle alignment must match CRITICAL_SECTION"); -ASMJIT_FORCE_INLINE Lock::Lock() noexcept { InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } -ASMJIT_FORCE_INLINE Lock::~Lock() noexcept { DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } -ASMJIT_FORCE_INLINE void Lock::lock() noexcept { EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } -ASMJIT_FORCE_INLINE void Lock::unlock() noexcept { LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } +ASMJIT_INLINE_NODEBUG Lock::Lock() noexcept { InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } +ASMJIT_INLINE_NODEBUG Lock::~Lock() noexcept { DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } +ASMJIT_INLINE_NODEBUG void Lock::lock() noexcept { EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } +ASMJIT_INLINE_NODEBUG void Lock::unlock() noexcept { LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } #elif !defined(__EMSCRIPTEN__) // PThread implementation. #ifdef PTHREAD_MUTEX_INITIALIZER -ASMJIT_FORCE_INLINE Lock::Lock() noexcept : _handle(PTHREAD_MUTEX_INITIALIZER) {} +ASMJIT_INLINE_NODEBUG Lock::Lock() noexcept : _handle(PTHREAD_MUTEX_INITIALIZER) {} #else -ASMJIT_FORCE_INLINE Lock::Lock() noexcept { pthread_mutex_init(&_handle, nullptr); } +ASMJIT_INLINE_NODEBUG Lock::Lock() noexcept { pthread_mutex_init(&_handle, nullptr); } #endif -ASMJIT_FORCE_INLINE Lock::~Lock() noexcept { pthread_mutex_destroy(&_handle); } -ASMJIT_FORCE_INLINE void Lock::lock() noexcept { pthread_mutex_lock(&_handle); } -ASMJIT_FORCE_INLINE void Lock::unlock() noexcept { pthread_mutex_unlock(&_handle); } +ASMJIT_INLINE_NODEBUG Lock::~Lock() noexcept { pthread_mutex_destroy(&_handle); } +ASMJIT_INLINE_NODEBUG void Lock::lock() noexcept { pthread_mutex_lock(&_handle); } +ASMJIT_INLINE_NODEBUG void Lock::unlock() noexcept { pthread_mutex_unlock(&_handle); } #else // Dummy implementation - Emscripten or other unsupported platform. -ASMJIT_FORCE_INLINE Lock::Lock() noexcept {} -ASMJIT_FORCE_INLINE Lock::~Lock() noexcept {} -ASMJIT_FORCE_INLINE void Lock::lock() noexcept {} -ASMJIT_FORCE_INLINE void Lock::unlock() noexcept {} +ASMJIT_INLINE_NODEBUG Lock::Lock() noexcept {} +ASMJIT_INLINE_NODEBUG Lock::~Lock() noexcept {} +ASMJIT_INLINE_NODEBUG void Lock::lock() noexcept {} +ASMJIT_INLINE_NODEBUG void Lock::unlock() noexcept {} #endif @@ -54,11 +55,20 @@ public: Lock& _target; - inline LockGuard(Lock& target) noexcept + ASMJIT_INLINE_NODEBUG LockGuard(Lock& target) noexcept : _target(target) { _target.lock(); } - inline ~LockGuard() noexcept { _target.unlock(); } + ASMJIT_INLINE_NODEBUG ~LockGuard() noexcept { _target.unlock(); } }; +#if !defined(_WIN32) +namespace OSUtils { + +//! Reads a file, only used on non-Windows platforms to access /sys or other files when necessary. +Error readFile(const char* name, String& dst, size_t maxSize) noexcept; + +} // {OSUtils} +#endif + //! \} //! \endcond diff --git a/3rdparty/asmjit/src/asmjit/core/raassignment_p.h b/3rdparty/asmjit/src/asmjit/core/raassignment_p.h index 54183293111..0865ece7548 100644 --- a/3rdparty/asmjit/src/asmjit/core/raassignment_p.h +++ b/3rdparty/asmjit/src/asmjit/core/raassignment_p.h @@ -66,7 +66,7 @@ public: //! PhysReg to WorkReg mapping. uint32_t workIds[1 /* ... */]; - static inline size_t sizeOf(size_t count) noexcept { + static ASMJIT_INLINE_NODEBUG size_t sizeOf(size_t count) noexcept { return sizeof(PhysToWorkMap) - sizeof(uint32_t) + count * sizeof(uint32_t); } @@ -163,16 +163,16 @@ public: //! \name Accessors //! \{ - inline PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; } - inline WorkToPhysMap* workToPhysMap() const noexcept { return _workToPhysMap; } + ASMJIT_INLINE_NODEBUG PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; } + ASMJIT_INLINE_NODEBUG WorkToPhysMap* workToPhysMap() const noexcept { return _workToPhysMap; } - inline RARegMask& assigned() noexcept { return _physToWorkMap->assigned; } - inline const RARegMask& assigned() const noexcept { return _physToWorkMap->assigned; } - inline uint32_t assigned(RegGroup group) const noexcept { return _physToWorkMap->assigned[group]; } + ASMJIT_INLINE_NODEBUG RARegMask& assigned() noexcept { return _physToWorkMap->assigned; } + ASMJIT_INLINE_NODEBUG const RARegMask& assigned() const noexcept { return _physToWorkMap->assigned; } + ASMJIT_INLINE_NODEBUG uint32_t assigned(RegGroup group) const noexcept { return _physToWorkMap->assigned[group]; } - inline RARegMask& dirty() noexcept { return _physToWorkMap->dirty; } - inline const RARegMask& dirty() const noexcept { return _physToWorkMap->dirty; } - inline RegMask dirty(RegGroup group) const noexcept { return _physToWorkMap->dirty[group]; } + ASMJIT_INLINE_NODEBUG RARegMask& dirty() noexcept { return _physToWorkMap->dirty; } + ASMJIT_INLINE_NODEBUG const RARegMask& dirty() const noexcept { return _physToWorkMap->dirty; } + ASMJIT_INLINE_NODEBUG RegMask dirty(RegGroup group) const noexcept { return _physToWorkMap->dirty[group]; } inline uint32_t workToPhysId(RegGroup group, uint32_t workId) const noexcept { DebugUtils::unused(group); diff --git a/3rdparty/asmjit/src/asmjit/core/rabuilders_p.h b/3rdparty/asmjit/src/asmjit/core/rabuilders_p.h index 1b763030c45..9d9b4282d2b 100644 --- a/3rdparty/asmjit/src/asmjit/core/rabuilders_p.h +++ b/3rdparty/asmjit/src/asmjit/core/rabuilders_p.h @@ -401,7 +401,7 @@ public: if (node->type() == NodeType::kSentinel) { if (node == _funcNode->endNode()) { // Make sure we didn't flow here if this is the end of the function sentinel. - if (ASMJIT_UNLIKELY(_curBlock)) + if (ASMJIT_UNLIKELY(_curBlock && _hasCode)) return DebugUtils::errored(kErrorInvalidState); break; } diff --git a/3rdparty/asmjit/src/asmjit/core/radefs_p.h b/3rdparty/asmjit/src/asmjit/core/radefs_p.h index 15c50ff728c..32503961068 100644 --- a/3rdparty/asmjit/src/asmjit/core/radefs_p.h +++ b/3rdparty/asmjit/src/asmjit/core/radefs_p.h @@ -67,7 +67,7 @@ public: uint32_t registerCount = arch == Arch::kX86 ? 8 : 16; _availableRegs[RegGroup::kGp] = Support::lsbMask<RegMask>(registerCount) & ~Support::bitMask(4u); _availableRegs[RegGroup::kVec] = Support::lsbMask<RegMask>(registerCount); - _availableRegs[RegGroup::kExtraVirt2] = Support::lsbMask<RegMask>(8); + _availableRegs[RegGroup::kMask] = Support::lsbMask<RegMask>(8); _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<RegMask>(8); return kErrorOk; } @@ -75,7 +75,7 @@ public: case Arch::kAArch64: { _availableRegs[RegGroup::kGp] = 0xFFFFFFFFu & ~Support::bitMask(18, 31u); _availableRegs[RegGroup::kVec] = 0xFFFFFFFFu; - _availableRegs[RegGroup::kExtraVirt2] = 0; + _availableRegs[RegGroup::kMask] = 0; _availableRegs[RegGroup::kExtraVirt3] = 0; return kErrorOk; } @@ -115,20 +115,20 @@ struct RAStrategy { //! \name Accessors //! \{ - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _type = RAStrategyType::kSimple; _flags = RAStrategyFlags::kNone; } - inline RAStrategyType type() const noexcept { return _type; } - inline void setType(RAStrategyType type) noexcept { _type = type; } + ASMJIT_INLINE_NODEBUG RAStrategyType type() const noexcept { return _type; } + ASMJIT_INLINE_NODEBUG void setType(RAStrategyType type) noexcept { _type = type; } - inline bool isSimple() const noexcept { return _type == RAStrategyType::kSimple; } - inline bool isComplex() const noexcept { return _type >= RAStrategyType::kComplex; } + ASMJIT_INLINE_NODEBUG bool isSimple() const noexcept { return _type == RAStrategyType::kSimple; } + ASMJIT_INLINE_NODEBUG bool isComplex() const noexcept { return _type >= RAStrategyType::kComplex; } - inline RAStrategyFlags flags() const noexcept { return _flags; } - inline bool hasFlag(RAStrategyFlags flag) const noexcept { return Support::test(_flags, flag); } - inline void addFlags(RAStrategyFlags flags) noexcept { _flags |= flags; } + ASMJIT_INLINE_NODEBUG RAStrategyFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG bool hasFlag(RAStrategyFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG void addFlags(RAStrategyFlags flags) noexcept { _flags |= flags; } //! \} }; @@ -153,7 +153,7 @@ struct RARegCount { //! \{ //! Resets all counters to zero. - inline void reset() noexcept { _packed = 0; } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _packed = 0; } //! \} @@ -170,8 +170,8 @@ struct RARegCount { return _regs[size_t(group)]; } - inline bool operator==(const RARegCount& other) const noexcept { return _packed == other._packed; } - inline bool operator!=(const RARegCount& other) const noexcept { return _packed != other._packed; } + ASMJIT_INLINE_NODEBUG bool operator==(const RARegCount& other) const noexcept { return _packed == other._packed; } + ASMJIT_INLINE_NODEBUG bool operator!=(const RARegCount& other) const noexcept { return _packed != other._packed; } //! \} @@ -233,17 +233,17 @@ struct RARegMask { //! \name Construction & Destruction //! \{ - inline void init(const RARegMask& other) noexcept { _masks = other._masks; } + ASMJIT_INLINE_NODEBUG void init(const RARegMask& other) noexcept { _masks = other._masks; } //! Reset all register masks to zero. - inline void reset() noexcept { _masks.fill(0); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _masks.fill(0); } //! \} //! \name Overloaded Operators //! \{ - inline bool operator==(const RARegMask& other) const noexcept { return _masks == other._masks; } - inline bool operator!=(const RARegMask& other) const noexcept { return _masks != other._masks; } + ASMJIT_INLINE_NODEBUG bool operator==(const RARegMask& other) const noexcept { return _masks == other._masks; } + ASMJIT_INLINE_NODEBUG bool operator!=(const RARegMask& other) const noexcept { return _masks != other._masks; } template<typename Index> inline uint32_t& operator[](const Index& index) noexcept { return _masks[index]; } @@ -315,20 +315,20 @@ public: //! \name Accessors //! \{ - inline void reset() noexcept { _packed = 0; } - inline void combineWith(const RARegsStats& other) noexcept { _packed |= other._packed; } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _packed = 0; } + ASMJIT_INLINE_NODEBUG void combineWith(const RARegsStats& other) noexcept { _packed |= other._packed; } - inline bool hasUsed() const noexcept { return (_packed & kMaskUsed) != 0u; } - inline bool hasUsed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexUsed + uint32_t(group))) != 0u; } - inline void makeUsed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexUsed + uint32_t(group)); } + ASMJIT_INLINE_NODEBUG bool hasUsed() const noexcept { return (_packed & kMaskUsed) != 0u; } + ASMJIT_INLINE_NODEBUG bool hasUsed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexUsed + uint32_t(group))) != 0u; } + ASMJIT_INLINE_NODEBUG void makeUsed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexUsed + uint32_t(group)); } - inline bool hasFixed() const noexcept { return (_packed & kMaskFixed) != 0u; } - inline bool hasFixed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexFixed + uint32_t(group))) != 0u; } - inline void makeFixed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexFixed + uint32_t(group)); } + ASMJIT_INLINE_NODEBUG bool hasFixed() const noexcept { return (_packed & kMaskFixed) != 0u; } + ASMJIT_INLINE_NODEBUG bool hasFixed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexFixed + uint32_t(group))) != 0u; } + ASMJIT_INLINE_NODEBUG void makeFixed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexFixed + uint32_t(group)); } - inline bool hasClobbered() const noexcept { return (_packed & kMaskClobbered) != 0u; } - inline bool hasClobbered(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexClobbered + uint32_t(group))) != 0u; } - inline void makeClobbered(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexClobbered + uint32_t(group)); } + ASMJIT_INLINE_NODEBUG bool hasClobbered() const noexcept { return (_packed & kMaskClobbered) != 0u; } + ASMJIT_INLINE_NODEBUG bool hasClobbered(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexClobbered + uint32_t(group))) != 0u; } + ASMJIT_INLINE_NODEBUG void makeClobbered(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexClobbered + uint32_t(group)); } //! \} }; @@ -346,18 +346,18 @@ public: //! \name Construction & Destruction //! \{ - inline RALiveCount() noexcept = default; - inline RALiveCount(const RALiveCount& other) noexcept = default; + ASMJIT_INLINE_NODEBUG RALiveCount() noexcept = default; + ASMJIT_INLINE_NODEBUG RALiveCount(const RALiveCount& other) noexcept = default; - inline void init(const RALiveCount& other) noexcept { n = other.n; } - inline void reset() noexcept { n.fill(0); } + ASMJIT_INLINE_NODEBUG void init(const RALiveCount& other) noexcept { n = other.n; } + ASMJIT_INLINE_NODEBUG void reset() noexcept { n.fill(0); } //! \} //! \name Overloaded Operators //! \{ - inline RALiveCount& operator=(const RALiveCount& other) noexcept = default; + ASMJIT_INLINE_NODEBUG RALiveCount& operator=(const RALiveCount& other) noexcept = default; inline uint32_t& operator[](RegGroup group) noexcept { return n[group]; } inline const uint32_t& operator[](RegGroup group) const noexcept { return n[group]; } @@ -394,31 +394,31 @@ struct RALiveInterval { //! \name Construction & Destruction //! \{ - inline RALiveInterval() noexcept : a(0), b(0) {} - inline RALiveInterval(uint32_t a, uint32_t b) noexcept : a(a), b(b) {} - inline RALiveInterval(const RALiveInterval& other) noexcept : a(other.a), b(other.b) {} + ASMJIT_INLINE_NODEBUG RALiveInterval() noexcept : a(0), b(0) {} + ASMJIT_INLINE_NODEBUG RALiveInterval(uint32_t a, uint32_t b) noexcept : a(a), b(b) {} + ASMJIT_INLINE_NODEBUG RALiveInterval(const RALiveInterval& other) noexcept : a(other.a), b(other.b) {} - inline void init(uint32_t aVal, uint32_t bVal) noexcept { + ASMJIT_INLINE_NODEBUG void init(uint32_t aVal, uint32_t bVal) noexcept { a = aVal; b = bVal; } - inline void init(const RALiveInterval& other) noexcept { init(other.a, other.b); } - inline void reset() noexcept { init(0, 0); } + ASMJIT_INLINE_NODEBUG void init(const RALiveInterval& other) noexcept { init(other.a, other.b); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { init(0, 0); } //! \} //! \name Overloaded Operators //! \{ - inline RALiveInterval& operator=(const RALiveInterval& other) = default; + ASMJIT_INLINE_NODEBUG RALiveInterval& operator=(const RALiveInterval& other) = default; //! \} //! \name Accessors //! \{ - inline bool isValid() const noexcept { return a < b; } - inline uint32_t width() const noexcept { return b - a; } + ASMJIT_INLINE_NODEBUG bool isValid() const noexcept { return a < b; } + ASMJIT_INLINE_NODEBUG uint32_t width() const noexcept { return b - a; } //! \} }; @@ -437,23 +437,23 @@ public: //! \name Construction & Destruction //! \{ - inline RALiveSpan() noexcept : RALiveInterval(), T() {} - inline RALiveSpan(const RALiveSpan<T>& other) noexcept : RALiveInterval(other), T() {} - inline RALiveSpan(const RALiveInterval& interval, const T& data) noexcept : RALiveInterval(interval), T(data) {} - inline RALiveSpan(uint32_t a, uint32_t b) noexcept : RALiveInterval(a, b), T() {} - inline RALiveSpan(uint32_t a, uint32_t b, const T& data) noexcept : RALiveInterval(a, b), T(data) {} + ASMJIT_INLINE_NODEBUG RALiveSpan() noexcept : RALiveInterval(), T() {} + ASMJIT_INLINE_NODEBUG RALiveSpan(const RALiveSpan<T>& other) noexcept : RALiveInterval(other), T() {} + ASMJIT_INLINE_NODEBUG RALiveSpan(const RALiveInterval& interval, const T& data) noexcept : RALiveInterval(interval), T(data) {} + ASMJIT_INLINE_NODEBUG RALiveSpan(uint32_t a, uint32_t b) noexcept : RALiveInterval(a, b), T() {} + ASMJIT_INLINE_NODEBUG RALiveSpan(uint32_t a, uint32_t b, const T& data) noexcept : RALiveInterval(a, b), T(data) {} - inline void init(const RALiveSpan<T>& other) noexcept { + ASMJIT_INLINE_NODEBUG void init(const RALiveSpan<T>& other) noexcept { RALiveInterval::init(static_cast<const RALiveInterval&>(other)); T::init(static_cast<const T&>(other)); } - inline void init(const RALiveSpan<T>& span, const T& data) noexcept { + ASMJIT_INLINE_NODEBUG void init(const RALiveSpan<T>& span, const T& data) noexcept { RALiveInterval::init(static_cast<const RALiveInterval&>(span)); T::init(data); } - inline void init(const RALiveInterval& interval, const T& data) noexcept { + ASMJIT_INLINE_NODEBUG void init(const RALiveInterval& interval, const T& data) noexcept { RALiveInterval::init(interval); T::init(data); } @@ -463,7 +463,7 @@ public: //! \name Overloaded Operators //! \{ - inline RALiveSpan& operator=(const RALiveSpan& other) { + ASMJIT_INLINE_NODEBUG RALiveSpan& operator=(const RALiveSpan& other) { init(other); return *this; } @@ -483,23 +483,23 @@ public: //! \name Construction & Destruction //! \{ - inline RALiveSpans() noexcept : _data() {} + ASMJIT_INLINE_NODEBUG RALiveSpans() noexcept : _data() {} - inline void reset() noexcept { _data.reset(); } - inline void release(ZoneAllocator* allocator) noexcept { _data.release(allocator); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _data.reset(); } + ASMJIT_INLINE_NODEBUG void release(ZoneAllocator* allocator) noexcept { _data.release(allocator); } //! \} //! \name Accessors //! \{ - inline bool empty() const noexcept { return _data.empty(); } - inline uint32_t size() const noexcept { return _data.size(); } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _data.empty(); } + ASMJIT_INLINE_NODEBUG uint32_t size() const noexcept { return _data.size(); } - inline T* data() noexcept { return _data.data(); } - inline const T* data() const noexcept { return _data.data(); } + ASMJIT_INLINE_NODEBUG T* data() noexcept { return _data.data(); } + ASMJIT_INLINE_NODEBUG const T* data() const noexcept { return _data.data(); } - inline bool isOpen() const noexcept { + ASMJIT_INLINE_NODEBUG bool isOpen() const noexcept { uint32_t size = _data.size(); return size > 0 && _data[size - 1].b == RALiveInterval::kInf; } @@ -509,7 +509,7 @@ public: //! \name Utilities //! \{ - inline void swap(RALiveSpans<T>& other) noexcept { _data.swap(other._data); } + ASMJIT_INLINE_NODEBUG void swap(RALiveSpans<T>& other) noexcept { _data.swap(other._data); } //! Open the current live span. ASMJIT_FORCE_INLINE Error openAt(ZoneAllocator* allocator, uint32_t start, uint32_t end) noexcept { @@ -550,16 +550,16 @@ public: return width; } - inline T& operator[](uint32_t index) noexcept { return _data[index]; } - inline const T& operator[](uint32_t index) const noexcept { return _data[index]; } + ASMJIT_INLINE_NODEBUG T& operator[](uint32_t index) noexcept { return _data[index]; } + ASMJIT_INLINE_NODEBUG const T& operator[](uint32_t index) const noexcept { return _data[index]; } - inline bool intersects(const RALiveSpans<T>& other) const noexcept { + ASMJIT_INLINE_NODEBUG bool intersects(const RALiveSpans<T>& other) const noexcept { return intersects(*this, other); } ASMJIT_FORCE_INLINE Error nonOverlappingUnionOf(ZoneAllocator* allocator, const RALiveSpans<T>& x, const RALiveSpans<T>& y, const DataType& yData) noexcept { uint32_t finalSize = x.size() + y.size(); - ASMJIT_PROPAGATE(_data.reserve(allocator, finalSize)); + ASMJIT_PROPAGATE(_data.growingReserve(allocator, finalSize)); T* dstPtr = _data.data(); const T* xSpan = x.data(); @@ -655,9 +655,9 @@ public: //! \name Accessors //! \{ - inline uint32_t width() const noexcept { return _width; } - inline float freq() const noexcept { return _freq; } - inline float priority() const noexcept { return _priority; } + ASMJIT_INLINE_NODEBUG uint32_t width() const noexcept { return _width; } + ASMJIT_INLINE_NODEBUG float freq() const noexcept { return _freq; } + ASMJIT_INLINE_NODEBUG float priority() const noexcept { return _priority; } //! \} }; @@ -665,13 +665,13 @@ public: struct LiveRegData { uint32_t id; - inline explicit LiveRegData(uint32_t id = BaseReg::kIdBad) noexcept : id(id) {} - inline LiveRegData(const LiveRegData& other) noexcept : id(other.id) {} + ASMJIT_INLINE_NODEBUG explicit LiveRegData(uint32_t id = BaseReg::kIdBad) noexcept : id(id) {} + ASMJIT_INLINE_NODEBUG LiveRegData(const LiveRegData& other) noexcept = default; - inline void init(const LiveRegData& other) noexcept { id = other.id; } + ASMJIT_INLINE_NODEBUG void init(const LiveRegData& other) noexcept { id = other.id; } - inline bool operator==(const LiveRegData& other) const noexcept { return id == other.id; } - inline bool operator!=(const LiveRegData& other) const noexcept { return id != other.id; } + ASMJIT_INLINE_NODEBUG bool operator==(const LiveRegData& other) const noexcept { return id == other.id; } + ASMJIT_INLINE_NODEBUG bool operator!=(const LiveRegData& other) const noexcept { return id != other.id; } }; typedef RALiveSpan<LiveRegData> LiveRegSpan; @@ -694,7 +694,7 @@ typedef RALiveSpans<LiveRegSpan> LiveRegSpans; //! - LEA x{ W|Out}, [x{R|Use} + y{R|Out}] -> {x:R|W|Use|Out y:R|Use} //! //! It should be obvious from the example above how these flags get created. Each operand contains READ/WRITE -//! information, which is then merged to RATiedReg's flags. However, we also need to represent the possitility +//! information, which is then merged to RATiedReg's flags. However, we also need to represent the possibility //! to view the operation as two independent operations - USE and OUT, because the register allocator first //! allocates USE registers, and then assigns OUT registers independently of USE registers. enum class RATiedFlags : uint32_t { @@ -740,6 +740,11 @@ enum class RATiedFlags : uint32_t { kLeadConsecutive = 0x00001000u, kConsecutiveData = 0x00006000u, + // Other Constraints + // ----------------- + + kUnique = 0x00008000u, + // Liveness Flags // -------------- @@ -762,6 +767,12 @@ enum class RATiedFlags : uint32_t { // Instruction Flags (Never used by RATiedReg) // ------------------------------------------- + //! Instruction has been patched to address a memory location instead of a register. + //! + //! This is currently only possible on X86 or X86_64 targets. It informs rewriter to rewrite the instruction if + //! necessary. + kInst_RegToMemPatched = 0x40000000u, + //! Instruction is transformable to another instruction if necessary. //! //! This is flag that is only used by \ref RAInst to inform register allocator that the instruction has some @@ -853,51 +864,54 @@ struct RATiedReg { //! \{ //! Returns the associated WorkReg id. - inline uint32_t workId() const noexcept { return _workId; } + ASMJIT_INLINE_NODEBUG uint32_t workId() const noexcept { return _workId; } - inline bool hasConsecutiveParent() const noexcept { return _consecutiveParent != Globals::kInvalidId; } - inline uint32_t consecutiveParent() const noexcept { return _consecutiveParent; } - inline uint32_t consecutiveData() const noexcept { return consecutiveDataFromFlags(_flags); } + ASMJIT_INLINE_NODEBUG bool hasConsecutiveParent() const noexcept { return _consecutiveParent != Globals::kInvalidId; } + ASMJIT_INLINE_NODEBUG uint32_t consecutiveParent() const noexcept { return _consecutiveParent; } + ASMJIT_INLINE_NODEBUG uint32_t consecutiveData() const noexcept { return consecutiveDataFromFlags(_flags); } //! Returns TiedReg flags. - inline RATiedFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG RATiedFlags flags() const noexcept { return _flags; } //! Checks if the given `flag` is set. - inline bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); } //! Adds tied register flags. - inline void addFlags(RATiedFlags flags) noexcept { _flags |= flags; } + ASMJIT_INLINE_NODEBUG void addFlags(RATiedFlags flags) noexcept { _flags |= flags; } //! Tests whether the register is read (writes `true` also if it's Read/Write). - inline bool isRead() const noexcept { return hasFlag(RATiedFlags::kRead); } + ASMJIT_INLINE_NODEBUG bool isRead() const noexcept { return hasFlag(RATiedFlags::kRead); } //! Tests whether the register is written (writes `true` also if it's Read/Write). - inline bool isWrite() const noexcept { return hasFlag(RATiedFlags::kWrite); } + ASMJIT_INLINE_NODEBUG bool isWrite() const noexcept { return hasFlag(RATiedFlags::kWrite); } //! Tests whether the register is read only. - inline bool isReadOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRead; } + ASMJIT_INLINE_NODEBUG bool isReadOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRead; } //! Tests whether the register is write only. - inline bool isWriteOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kWrite; } + ASMJIT_INLINE_NODEBUG bool isWriteOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kWrite; } //! Tests whether the register is read and written. - inline bool isReadWrite() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRW; } + ASMJIT_INLINE_NODEBUG bool isReadWrite() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRW; } //! Tests whether the tied register has use operand (Read/ReadWrite). - inline bool isUse() const noexcept { return hasFlag(RATiedFlags::kUse); } + ASMJIT_INLINE_NODEBUG bool isUse() const noexcept { return hasFlag(RATiedFlags::kUse); } //! Tests whether the tied register has out operand (Write). - inline bool isOut() const noexcept { return hasFlag(RATiedFlags::kOut); } + ASMJIT_INLINE_NODEBUG bool isOut() const noexcept { return hasFlag(RATiedFlags::kOut); } //! Tests whether the tied register has \ref RATiedFlags::kLeadConsecutive flag set. - inline bool isLeadConsecutive() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive); } + ASMJIT_INLINE_NODEBUG bool isLeadConsecutive() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive); } //! Tests whether the tied register has \ref RATiedFlags::kUseConsecutive flag set. - inline bool isUseConsecutive() const noexcept { return hasFlag(RATiedFlags::kUseConsecutive); } + ASMJIT_INLINE_NODEBUG bool isUseConsecutive() const noexcept { return hasFlag(RATiedFlags::kUseConsecutive); } //! Tests whether the tied register has \ref RATiedFlags::kOutConsecutive flag set. - inline bool isOutConsecutive() const noexcept { return hasFlag(RATiedFlags::kOutConsecutive); } + ASMJIT_INLINE_NODEBUG bool isOutConsecutive() const noexcept { return hasFlag(RATiedFlags::kOutConsecutive); } + + //! Tests whether the tied register must be unique (cannot be allocated to any other allocated register). + ASMJIT_INLINE_NODEBUG bool isUnique() const noexcept { return hasFlag(RATiedFlags::kUnique); } //! Tests whether the tied register has any consecutive flag. - inline bool hasAnyConsecutiveFlag() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive | RATiedFlags::kUseConsecutive | RATiedFlags::kOutConsecutive); } + ASMJIT_INLINE_NODEBUG bool hasAnyConsecutiveFlag() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive | RATiedFlags::kUseConsecutive | RATiedFlags::kOutConsecutive); } //! Tests whether the USE slot can be patched to memory operand. - inline bool hasUseRM() const noexcept { return hasFlag(RATiedFlags::kUseRM); } + ASMJIT_INLINE_NODEBUG bool hasUseRM() const noexcept { return hasFlag(RATiedFlags::kUseRM); } //! Tests whether the OUT slot can be patched to memory operand. - inline bool hasOutRM() const noexcept { return hasFlag(RATiedFlags::kOutRM); } + ASMJIT_INLINE_NODEBUG bool hasOutRM() const noexcept { return hasFlag(RATiedFlags::kOutRM); } - inline uint32_t rmSize() const noexcept { return _rmSize; } + ASMJIT_INLINE_NODEBUG uint32_t rmSize() const noexcept { return _rmSize; } inline void makeReadOnly() noexcept { _flags = (_flags & ~(RATiedFlags::kOut | RATiedFlags::kWrite)) | RATiedFlags::kUse; @@ -912,47 +926,47 @@ struct RATiedReg { } //! Tests whether the register would duplicate. - inline bool isDuplicate() const noexcept { return hasFlag(RATiedFlags::kDuplicate); } + ASMJIT_INLINE_NODEBUG bool isDuplicate() const noexcept { return hasFlag(RATiedFlags::kDuplicate); } //! Tests whether the register (and the instruction it's part of) appears last in the basic block. - inline bool isLast() const noexcept { return hasFlag(RATiedFlags::kLast); } + ASMJIT_INLINE_NODEBUG bool isLast() const noexcept { return hasFlag(RATiedFlags::kLast); } //! Tests whether the register should be killed after USEd and/or OUTed. - inline bool isKill() const noexcept { return hasFlag(RATiedFlags::kKill); } + ASMJIT_INLINE_NODEBUG bool isKill() const noexcept { return hasFlag(RATiedFlags::kKill); } //! Tests whether the register is OUT or KILL (used internally by local register allocator). - inline bool isOutOrKill() const noexcept { return hasFlag(RATiedFlags::kOut | RATiedFlags::kKill); } + ASMJIT_INLINE_NODEBUG bool isOutOrKill() const noexcept { return hasFlag(RATiedFlags::kOut | RATiedFlags::kKill); } //! Returns a register mask that describes allocable USE registers (Read/ReadWrite access). - inline RegMask useRegMask() const noexcept { return _useRegMask; } + ASMJIT_INLINE_NODEBUG RegMask useRegMask() const noexcept { return _useRegMask; } //! Returns a register mask that describes allocable OUT registers (WriteOnly access). - inline RegMask outRegMask() const noexcept { return _outRegMask; } + ASMJIT_INLINE_NODEBUG RegMask outRegMask() const noexcept { return _outRegMask; } - inline uint32_t refCount() const noexcept { return _refCount; } - inline void addRefCount(uint32_t n = 1) noexcept { _refCount = uint8_t(_refCount + n); } + ASMJIT_INLINE_NODEBUG uint32_t refCount() const noexcept { return _refCount; } + ASMJIT_INLINE_NODEBUG void addRefCount(uint32_t n = 1) noexcept { _refCount = uint8_t(_refCount + n); } //! Tests whether the register must be allocated to a fixed physical register before it's used. - inline bool hasUseId() const noexcept { return _useId != BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG bool hasUseId() const noexcept { return _useId != BaseReg::kIdBad; } //! Tests whether the register must be allocated to a fixed physical register before it's written. - inline bool hasOutId() const noexcept { return _outId != BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG bool hasOutId() const noexcept { return _outId != BaseReg::kIdBad; } //! Returns a physical register id used for 'use' operation. - inline uint32_t useId() const noexcept { return _useId; } + ASMJIT_INLINE_NODEBUG uint32_t useId() const noexcept { return _useId; } //! Returns a physical register id used for 'out' operation. - inline uint32_t outId() const noexcept { return _outId; } + ASMJIT_INLINE_NODEBUG uint32_t outId() const noexcept { return _outId; } - inline uint32_t useRewriteMask() const noexcept { return _useRewriteMask; } - inline uint32_t outRewriteMask() const noexcept { return _outRewriteMask; } + ASMJIT_INLINE_NODEBUG uint32_t useRewriteMask() const noexcept { return _useRewriteMask; } + ASMJIT_INLINE_NODEBUG uint32_t outRewriteMask() const noexcept { return _outRewriteMask; } //! Sets a physical register used for 'use' operation. - inline void setUseId(uint32_t index) noexcept { _useId = uint8_t(index); } + ASMJIT_INLINE_NODEBUG void setUseId(uint32_t index) noexcept { _useId = uint8_t(index); } //! Sets a physical register used for 'out' operation. - inline void setOutId(uint32_t index) noexcept { _outId = uint8_t(index); } + ASMJIT_INLINE_NODEBUG void setOutId(uint32_t index) noexcept { _outId = uint8_t(index); } - inline bool isUseDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); } - inline bool isOutDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); } + ASMJIT_INLINE_NODEBUG bool isUseDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); } + ASMJIT_INLINE_NODEBUG bool isOutDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); } - inline void markUseDone() noexcept { addFlags(RATiedFlags::kUseDone); } - inline void markOutDone() noexcept { addFlags(RATiedFlags::kUseDone); } + ASMJIT_INLINE_NODEBUG void markUseDone() noexcept { addFlags(RATiedFlags::kUseDone); } + ASMJIT_INLINE_NODEBUG void markOutDone() noexcept { addFlags(RATiedFlags::kUseDone); } //! \} }; @@ -1082,7 +1096,7 @@ public: //! \name Construction & Destruction //! \{ - inline RAWorkReg(VirtReg* vReg, uint32_t workId) noexcept + ASMJIT_INLINE_NODEBUG RAWorkReg(VirtReg* vReg, uint32_t workId) noexcept : _workId(workId), _virtId(vReg->id()), _virtReg(vReg), @@ -1093,97 +1107,97 @@ public: //! \name Accessors //! \{ - inline uint32_t workId() const noexcept { return _workId; } - inline uint32_t virtId() const noexcept { return _virtId; } + ASMJIT_INLINE_NODEBUG uint32_t workId() const noexcept { return _workId; } + ASMJIT_INLINE_NODEBUG uint32_t virtId() const noexcept { return _virtId; } - inline const char* name() const noexcept { return _virtReg->name(); } - inline uint32_t nameSize() const noexcept { return _virtReg->nameSize(); } + ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _virtReg->name(); } + ASMJIT_INLINE_NODEBUG uint32_t nameSize() const noexcept { return _virtReg->nameSize(); } - inline TypeId typeId() const noexcept { return _virtReg->typeId(); } + ASMJIT_INLINE_NODEBUG TypeId typeId() const noexcept { return _virtReg->typeId(); } - inline RAWorkRegFlags flags() const noexcept { return _flags; } - inline bool hasFlag(RAWorkRegFlags flag) const noexcept { return Support::test(_flags, flag); } - inline void addFlags(RAWorkRegFlags flags) noexcept { _flags |= flags; } + ASMJIT_INLINE_NODEBUG RAWorkRegFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG bool hasFlag(RAWorkRegFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG void addFlags(RAWorkRegFlags flags) noexcept { _flags |= flags; } - inline bool isAllocated() const noexcept { return hasFlag(RAWorkRegFlags::kAllocated); } - inline void markAllocated() noexcept { addFlags(RAWorkRegFlags::kAllocated); } + ASMJIT_INLINE_NODEBUG bool isAllocated() const noexcept { return hasFlag(RAWorkRegFlags::kAllocated); } + ASMJIT_INLINE_NODEBUG void markAllocated() noexcept { addFlags(RAWorkRegFlags::kAllocated); } - inline bool isLeadConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kLeadConsecutive); } - inline void markLeadConsecutive() noexcept { addFlags(RAWorkRegFlags::kLeadConsecutive); } + ASMJIT_INLINE_NODEBUG bool isLeadConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kLeadConsecutive); } + ASMJIT_INLINE_NODEBUG void markLeadConsecutive() noexcept { addFlags(RAWorkRegFlags::kLeadConsecutive); } - inline bool isProcessedConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kProcessedConsecutive); } - inline void markProcessedConsecutive() noexcept { addFlags(RAWorkRegFlags::kProcessedConsecutive); } + ASMJIT_INLINE_NODEBUG bool isProcessedConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kProcessedConsecutive); } + ASMJIT_INLINE_NODEBUG void markProcessedConsecutive() noexcept { addFlags(RAWorkRegFlags::kProcessedConsecutive); } - inline bool isStackUsed() const noexcept { return hasFlag(RAWorkRegFlags::kStackUsed); } - inline void markStackUsed() noexcept { addFlags(RAWorkRegFlags::kStackUsed); } + ASMJIT_INLINE_NODEBUG bool isStackUsed() const noexcept { return hasFlag(RAWorkRegFlags::kStackUsed); } + ASMJIT_INLINE_NODEBUG void markStackUsed() noexcept { addFlags(RAWorkRegFlags::kStackUsed); } - inline bool isStackPreferred() const noexcept { return hasFlag(RAWorkRegFlags::kStackPreferred); } - inline void markStackPreferred() noexcept { addFlags(RAWorkRegFlags::kStackPreferred); } + ASMJIT_INLINE_NODEBUG bool isStackPreferred() const noexcept { return hasFlag(RAWorkRegFlags::kStackPreferred); } + ASMJIT_INLINE_NODEBUG void markStackPreferred() noexcept { addFlags(RAWorkRegFlags::kStackPreferred); } //! Tests whether this RAWorkReg has been coalesced with another one (cannot be used anymore). - inline bool isCoalesced() const noexcept { return hasFlag(RAWorkRegFlags::kCoalesced); } + ASMJIT_INLINE_NODEBUG bool isCoalesced() const noexcept { return hasFlag(RAWorkRegFlags::kCoalesced); } - inline OperandSignature signature() const noexcept { return _signature; } - inline RegType type() const noexcept { return _signature.regType(); } - inline RegGroup group() const noexcept { return _signature.regGroup(); } + ASMJIT_INLINE_NODEBUG OperandSignature signature() const noexcept { return _signature; } + ASMJIT_INLINE_NODEBUG RegType type() const noexcept { return _signature.regType(); } + ASMJIT_INLINE_NODEBUG RegGroup group() const noexcept { return _signature.regGroup(); } - inline VirtReg* virtReg() const noexcept { return _virtReg; } + ASMJIT_INLINE_NODEBUG VirtReg* virtReg() const noexcept { return _virtReg; } - inline bool hasTiedReg() const noexcept { return _tiedReg != nullptr; } - inline RATiedReg* tiedReg() const noexcept { return _tiedReg; } - inline void setTiedReg(RATiedReg* tiedReg) noexcept { _tiedReg = tiedReg; } - inline void resetTiedReg() noexcept { _tiedReg = nullptr; } + ASMJIT_INLINE_NODEBUG bool hasTiedReg() const noexcept { return _tiedReg != nullptr; } + ASMJIT_INLINE_NODEBUG RATiedReg* tiedReg() const noexcept { return _tiedReg; } + ASMJIT_INLINE_NODEBUG void setTiedReg(RATiedReg* tiedReg) noexcept { _tiedReg = tiedReg; } + ASMJIT_INLINE_NODEBUG void resetTiedReg() noexcept { _tiedReg = nullptr; } - inline bool hasStackSlot() const noexcept { return _stackSlot != nullptr; } - inline RAStackSlot* stackSlot() const noexcept { return _stackSlot; } + ASMJIT_INLINE_NODEBUG bool hasStackSlot() const noexcept { return _stackSlot != nullptr; } + ASMJIT_INLINE_NODEBUG RAStackSlot* stackSlot() const noexcept { return _stackSlot; } - inline LiveRegSpans& liveSpans() noexcept { return _liveSpans; } - inline const LiveRegSpans& liveSpans() const noexcept { return _liveSpans; } + ASMJIT_INLINE_NODEBUG LiveRegSpans& liveSpans() noexcept { return _liveSpans; } + ASMJIT_INLINE_NODEBUG const LiveRegSpans& liveSpans() const noexcept { return _liveSpans; } - inline RALiveStats& liveStats() noexcept { return _liveStats; } - inline const RALiveStats& liveStats() const noexcept { return _liveStats; } + ASMJIT_INLINE_NODEBUG RALiveStats& liveStats() noexcept { return _liveStats; } + ASMJIT_INLINE_NODEBUG const RALiveStats& liveStats() const noexcept { return _liveStats; } - inline bool hasArgIndex() const noexcept { return _argIndex != kNoArgIndex; } - inline uint32_t argIndex() const noexcept { return _argIndex; } - inline uint32_t argValueIndex() const noexcept { return _argValueIndex; } + ASMJIT_INLINE_NODEBUG bool hasArgIndex() const noexcept { return _argIndex != kNoArgIndex; } + ASMJIT_INLINE_NODEBUG uint32_t argIndex() const noexcept { return _argIndex; } + ASMJIT_INLINE_NODEBUG uint32_t argValueIndex() const noexcept { return _argValueIndex; } inline void setArgIndex(uint32_t argIndex, uint32_t valueIndex) noexcept { _argIndex = uint8_t(argIndex); _argValueIndex = uint8_t(valueIndex); } - inline bool hasHomeRegId() const noexcept { return _homeRegId != BaseReg::kIdBad; } - inline uint32_t homeRegId() const noexcept { return _homeRegId; } - inline void setHomeRegId(uint32_t physId) noexcept { _homeRegId = uint8_t(physId); } + ASMJIT_INLINE_NODEBUG bool hasHomeRegId() const noexcept { return _homeRegId != BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG uint32_t homeRegId() const noexcept { return _homeRegId; } + ASMJIT_INLINE_NODEBUG void setHomeRegId(uint32_t physId) noexcept { _homeRegId = uint8_t(physId); } - inline bool hasHintRegId() const noexcept { return _hintRegId != BaseReg::kIdBad; } - inline uint32_t hintRegId() const noexcept { return _hintRegId; } - inline void setHintRegId(uint32_t physId) noexcept { _hintRegId = uint8_t(physId); } + ASMJIT_INLINE_NODEBUG bool hasHintRegId() const noexcept { return _hintRegId != BaseReg::kIdBad; } + ASMJIT_INLINE_NODEBUG uint32_t hintRegId() const noexcept { return _hintRegId; } + ASMJIT_INLINE_NODEBUG void setHintRegId(uint32_t physId) noexcept { _hintRegId = uint8_t(physId); } - inline RegMask useIdMask() const noexcept { return _useIdMask; } - inline bool hasUseIdMask() const noexcept { return _useIdMask != 0u; } - inline bool hasMultipleUseIds() const noexcept { return _useIdMask != 0u && !Support::isPowerOf2(_useIdMask); } - inline void addUseIdMask(RegMask mask) noexcept { _useIdMask |= mask; } + ASMJIT_INLINE_NODEBUG RegMask useIdMask() const noexcept { return _useIdMask; } + ASMJIT_INLINE_NODEBUG bool hasUseIdMask() const noexcept { return _useIdMask != 0u; } + ASMJIT_INLINE_NODEBUG bool hasMultipleUseIds() const noexcept { return _useIdMask != 0u && !Support::isPowerOf2(_useIdMask); } + ASMJIT_INLINE_NODEBUG void addUseIdMask(RegMask mask) noexcept { _useIdMask |= mask; } - inline RegMask preferredMask() const noexcept { return _preferredMask; } - inline bool hasPrereffedMask() const noexcept { return _preferredMask != 0xFFFFFFFFu; } - inline void restrictPreferredMask(RegMask mask) noexcept { _preferredMask &= mask; } + ASMJIT_INLINE_NODEBUG RegMask preferredMask() const noexcept { return _preferredMask; } + ASMJIT_INLINE_NODEBUG bool hasPreferredMask() const noexcept { return _preferredMask != 0xFFFFFFFFu; } + ASMJIT_INLINE_NODEBUG void restrictPreferredMask(RegMask mask) noexcept { _preferredMask &= mask; } - inline RegMask consecutiveMask() const noexcept { return _consecutiveMask; } - inline bool hasConsecutiveMask() const noexcept { return _consecutiveMask != 0xFFFFFFFFu; } - inline void restrictConsecutiveMask(RegMask mask) noexcept { _consecutiveMask &= mask; } + ASMJIT_INLINE_NODEBUG RegMask consecutiveMask() const noexcept { return _consecutiveMask; } + ASMJIT_INLINE_NODEBUG bool hasConsecutiveMask() const noexcept { return _consecutiveMask != 0xFFFFFFFFu; } + ASMJIT_INLINE_NODEBUG void restrictConsecutiveMask(RegMask mask) noexcept { _consecutiveMask &= mask; } - inline RegMask clobberSurvivalMask() const noexcept { return _clobberSurvivalMask; } - inline void addClobberSurvivalMask(RegMask mask) noexcept { _clobberSurvivalMask |= mask; } + ASMJIT_INLINE_NODEBUG RegMask clobberSurvivalMask() const noexcept { return _clobberSurvivalMask; } + ASMJIT_INLINE_NODEBUG void addClobberSurvivalMask(RegMask mask) noexcept { _clobberSurvivalMask |= mask; } - inline RegMask allocatedMask() const noexcept { return _allocatedMask; } - inline void addAllocatedMask(RegMask mask) noexcept { _allocatedMask |= mask; } + ASMJIT_INLINE_NODEBUG RegMask allocatedMask() const noexcept { return _allocatedMask; } + ASMJIT_INLINE_NODEBUG void addAllocatedMask(RegMask mask) noexcept { _allocatedMask |= mask; } - inline uint64_t regByteMask() const noexcept { return _regByteMask; } - inline void setRegByteMask(uint64_t mask) noexcept { _regByteMask = mask; } + ASMJIT_INLINE_NODEBUG uint64_t regByteMask() const noexcept { return _regByteMask; } + ASMJIT_INLINE_NODEBUG void setRegByteMask(uint64_t mask) noexcept { _regByteMask = mask; } - inline bool hasImmediateConsecutives() const noexcept { return !_immediateConsecutives.empty(); } - inline const ZoneBitVector& immediateConsecutives() const noexcept { return _immediateConsecutives; } + ASMJIT_INLINE_NODEBUG bool hasImmediateConsecutives() const noexcept { return !_immediateConsecutives.empty(); } + ASMJIT_INLINE_NODEBUG const ZoneBitVector& immediateConsecutives() const noexcept { return _immediateConsecutives; } inline Error addImmediateConsecutive(ZoneAllocator* allocator, uint32_t workId) noexcept { if (_immediateConsecutives.size() <= workId) diff --git a/3rdparty/asmjit/src/asmjit/core/ralocal.cpp b/3rdparty/asmjit/src/asmjit/core/ralocal.cpp index b4d92446b3c..358fbf58f8b 100644 --- a/3rdparty/asmjit/src/asmjit/core/ralocal.cpp +++ b/3rdparty/asmjit/src/asmjit/core/ralocal.cpp @@ -21,8 +21,8 @@ static ASMJIT_FORCE_INLINE RATiedReg* RALocal_findTiedRegByWorkId(RATiedReg* tie return nullptr; } -// RALocalAllocator - Init & Reset -// =============================== +// RALocalAllocator - Initialization & Reset +// ========================================= Error RALocalAllocator::init() noexcept { PhysToWorkMap* physToWorkMap; @@ -137,9 +137,6 @@ Error RALocalAllocator::switchToAssignment(PhysToWorkMap* dstPhysToWorkMap, cons dst.initMaps(dstPhysToWorkMap, _tmpWorkToPhysMap); dst.assignWorkIdsFromPhysIds(); - if (tryMode) - return kErrorOk; - for (RegGroup group : RegGroupVirtValues{}) { // STEP 1 // ------ @@ -597,10 +594,14 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { if (rmSize <= workReg->virtReg()->virtSize()) { Operand& op = node->operands()[opIndex]; op = _pass->workRegAsMem(workReg); - op.as<BaseMem>().setSize(rmSize); + + // NOTE: We cannot use `x86::Mem::setSize()` from here, so let's manipulate the signature directly. + op._signature.setSize(rmSize); + tiedReg->_useRewriteMask = 0; tiedReg->markUseDone(); + raInst->addFlags(RATiedFlags::kInst_RegToMemPatched); usePending--; rmAllocated = true; @@ -687,7 +688,7 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { // ------ // // ALLOCATE / SHUFFLE all registers that we marked as `willUse` and weren't allocated yet. This is a bit - // complicated as the allocation is iterative. In some cases we have to wait before allocating a particual + // complicated as the allocation is iterative. In some cases we have to wait before allocating a particular // physical register as it's still occupied by some other one, which we need to move before we can use it. // In this case we skip it and allocate another some other instead (making it free for another iteration). // @@ -836,7 +837,7 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { // STEP 9 // ------ // - // Vector registers can be cloberred partially by invoke - find if that's the case and clobber when necessary. + // Vector registers can be clobbered partially by invoke - find if that's the case and clobber when necessary. if (node->isInvoke() && group == RegGroup::kVec) { const InvokeNode* invokeNode = node->as<InvokeNode>(); @@ -927,6 +928,10 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { if (!tiedReg->isOut()) continue; + RegMask avoidOut = avoidRegs; + if (tiedReg->isUnique()) + avoidOut |= willUse; + uint32_t workId = tiedReg->workId(); uint32_t assignedId = _curAssignment.workToPhysId(group, workId); @@ -935,7 +940,7 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { uint32_t physId = tiedReg->outId(); if (physId == RAAssignment::kPhysNone) { - RegMask allocableRegs = tiedReg->outRegMask() & ~(outRegs | avoidRegs); + RegMask allocableRegs = tiedReg->outRegMask() & ~(outRegs | avoidOut); if (!(allocableRegs & ~liveRegs)) { // There are no more registers, decide which one to spill. diff --git a/3rdparty/asmjit/src/asmjit/core/ralocal_p.h b/3rdparty/asmjit/src/asmjit/core/ralocal_p.h index b40e8674274..63fd1b78aba 100644 --- a/3rdparty/asmjit/src/asmjit/core/ralocal_p.h +++ b/3rdparty/asmjit/src/asmjit/core/ralocal_p.h @@ -29,52 +29,45 @@ public: typedef RAAssignment::WorkToPhysMap WorkToPhysMap; //! Link to `BaseRAPass`. - BaseRAPass* _pass; + BaseRAPass* _pass {}; //! Link to `BaseCompiler`. - BaseCompiler* _cc; + BaseCompiler* _cc {}; //! Architecture traits. - const ArchTraits* _archTraits; + const ArchTraits* _archTraits {}; //! Registers available to the allocator. - RARegMask _availableRegs; + RARegMask _availableRegs {}; //! Registers clobbered by the allocator. - RARegMask _clobberedRegs; + RARegMask _clobberedRegs {}; //! Register assignment (current). - RAAssignment _curAssignment; + RAAssignment _curAssignment {}; //! Register assignment used temporarily during assignment switches. - RAAssignment _tmpAssignment; + RAAssignment _tmpAssignment {}; //! Link to the current `RABlock`. - RABlock* _block; + RABlock* _block {}; //! InstNode. - InstNode* _node; + InstNode* _node {}; //! RA instruction. - RAInst* _raInst; + RAInst* _raInst {}; //! Count of all TiedReg's. - uint32_t _tiedTotal; + uint32_t _tiedTotal {}; //! TiedReg's total counter. - RARegCount _tiedCount; + RARegCount _tiedCount {}; //! Temporary workToPhysMap that can be used freely by the allocator. - WorkToPhysMap* _tmpWorkToPhysMap; + WorkToPhysMap* _tmpWorkToPhysMap {}; //! \name Construction & Destruction //! \{ - inline RALocalAllocator(BaseRAPass* pass) noexcept + inline explicit RALocalAllocator(BaseRAPass* pass) noexcept : _pass(pass), _cc(pass->cc()), _archTraits(pass->_archTraits), - _availableRegs(pass->_availableRegs), - _clobberedRegs(), - _curAssignment(), - _block(nullptr), - _node(nullptr), - _raInst(nullptr), - _tiedTotal(), - _tiedCount() {} + _availableRegs(pass->_availableRegs) {} Error init() noexcept; @@ -83,31 +76,31 @@ public: //! \name Accessors //! \{ - inline RAWorkReg* workRegById(uint32_t workId) const noexcept { return _pass->workRegById(workId); } - inline PhysToWorkMap* physToWorkMap() const noexcept { return _curAssignment.physToWorkMap(); } - inline WorkToPhysMap* workToPhysMap() const noexcept { return _curAssignment.workToPhysMap(); } + ASMJIT_INLINE_NODEBUG RAWorkReg* workRegById(uint32_t workId) const noexcept { return _pass->workRegById(workId); } + ASMJIT_INLINE_NODEBUG PhysToWorkMap* physToWorkMap() const noexcept { return _curAssignment.physToWorkMap(); } + ASMJIT_INLINE_NODEBUG WorkToPhysMap* workToPhysMap() const noexcept { return _curAssignment.workToPhysMap(); } //! Returns the currently processed block. - inline RABlock* block() const noexcept { return _block; } + ASMJIT_INLINE_NODEBUG RABlock* block() const noexcept { return _block; } //! Sets the currently processed block. - inline void setBlock(RABlock* block) noexcept { _block = block; } + ASMJIT_INLINE_NODEBUG void setBlock(RABlock* block) noexcept { _block = block; } //! Returns the currently processed `InstNode`. - inline InstNode* node() const noexcept { return _node; } + ASMJIT_INLINE_NODEBUG InstNode* node() const noexcept { return _node; } //! Returns the currently processed `RAInst`. - inline RAInst* raInst() const noexcept { return _raInst; } + ASMJIT_INLINE_NODEBUG RAInst* raInst() const noexcept { return _raInst; } //! Returns all tied regs as `RATiedReg` array. - inline RATiedReg* tiedRegs() const noexcept { return _raInst->tiedRegs(); } + ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs() const noexcept { return _raInst->tiedRegs(); } //! Returns tied registers grouped by the given `group`. - inline RATiedReg* tiedRegs(RegGroup group) const noexcept { return _raInst->tiedRegs(group); } + ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs(RegGroup group) const noexcept { return _raInst->tiedRegs(group); } //! Returns count of all TiedRegs used by the instruction. - inline uint32_t tiedCount() const noexcept { return _tiedTotal; } + ASMJIT_INLINE_NODEBUG uint32_t tiedCount() const noexcept { return _tiedTotal; } //! Returns count of TiedRegs used by the given register `group`. - inline uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount.get(group); } + ASMJIT_INLINE_NODEBUG uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount.get(group); } - inline bool isGroupUsed(RegGroup group) const noexcept { return _tiedCount[group] != 0; } + ASMJIT_INLINE_NODEBUG bool isGroupUsed(RegGroup group) const noexcept { return _tiedCount[group] != 0; } //! \} @@ -126,7 +119,7 @@ public: //! a code sequence that is always executed regardless of the flow. Error switchToAssignment(PhysToWorkMap* dstPhysToWorkMap, const ZoneBitVector& liveIn, bool dstReadOnly, bool tryMode) noexcept; - inline Error spillRegsBeforeEntry(RABlock* block) noexcept { + ASMJIT_INLINE_NODEBUG Error spillRegsBeforeEntry(RABlock* block) noexcept { return spillScratchGpRegsBeforeEntry(block->entryScratchGpRegs()); } @@ -153,7 +146,7 @@ public: kCostOfDirtyFlag = kCostOfFrequency / 4 }; - inline uint32_t costByFrequency(float freq) const noexcept { + ASMJIT_INLINE_NODEBUG uint32_t costByFrequency(float freq) const noexcept { return uint32_t(int32_t(freq * float(kCostOfFrequency))); } diff --git a/3rdparty/asmjit/src/asmjit/core/rapass.cpp b/3rdparty/asmjit/src/asmjit/core/rapass.cpp index 0e87ab6a259..837cbe291cd 100644 --- a/3rdparty/asmjit/src/asmjit/core/rapass.cpp +++ b/3rdparty/asmjit/src/asmjit/core/rapass.cpp @@ -114,11 +114,14 @@ Error BaseRAPass::runOnFunction(Zone* zone, Logger* logger, FuncNode* func) { #ifndef ASMJIT_NO_LOGGING _logger = logger; _formatOptions.reset(); - _diagnosticOptions = DiagnosticOptions::kNone; + _diagnosticOptions = _cb->diagnosticOptions(); if (logger) { _formatOptions = logger->options(); - _diagnosticOptions = _cb->diagnosticOptions(); + } + else { + _diagnosticOptions &= ~(DiagnosticOptions::kRADebugCFG | + DiagnosticOptions::kRADebugUnreachable); } #else DebugUtils::unused(logger); @@ -193,6 +196,12 @@ Error BaseRAPass::onPerformAllSteps() noexcept { return kErrorOk; } +// BaseRAPass - Events +// =================== + +void BaseRAPass::onInit() noexcept {} +void BaseRAPass::onDone() noexcept {} + // BaseRAPass - CFG - Basic Block Management // ========================================= @@ -304,6 +313,11 @@ Error BaseRAPass::addBlock(RABlock* block) noexcept { // BaseRAPass - CFG - Build // ======================== +// [[pure virtual]] +Error BaseRAPass::buildCFG() noexcept { + return DebugUtils::errored(kErrorInvalidState); +} + Error BaseRAPass::initSharedAssignments(const ZoneVector<uint32_t>& sharedAssignmentsMap) noexcept { if (sharedAssignmentsMap.empty()) return kErrorOk; @@ -328,9 +342,14 @@ Error BaseRAPass::initSharedAssignments(const ZoneVector<uint32_t>& sharedAssign RABlock* firstSuccessor = successors[0]; // NOTE: Shared assignments connect all possible successors so we only need the first to propagate exit scratch // GP registers. - ASMJIT_ASSERT(firstSuccessor->hasSharedAssignmentId()); - RASharedAssignment& sa = _sharedAssignments[firstSuccessor->sharedAssignmentId()]; - sa.addEntryScratchGpRegs(block->exitScratchGpRegs()); + if (firstSuccessor->hasSharedAssignmentId()) { + RASharedAssignment& sa = _sharedAssignments[firstSuccessor->sharedAssignmentId()]; + sa.addEntryScratchGpRegs(block->exitScratchGpRegs()); + } + else { + // This is only allowed if there is a single successor - in that case shared assignment is not necessary. + ASMJIT_ASSERT(successors.size() == 1u); + } } } if (block->hasSharedAssignmentId()) { @@ -347,21 +366,18 @@ Error BaseRAPass::initSharedAssignments(const ZoneVector<uint32_t>& sharedAssign class RABlockVisitItem { public: + RABlock* _block {}; + uint32_t _index {}; + inline RABlockVisitItem(RABlock* block, uint32_t index) noexcept : _block(block), _index(index) {} - inline RABlockVisitItem(const RABlockVisitItem& other) noexcept - : _block(other._block), - _index(other._index) {} - + inline RABlockVisitItem(const RABlockVisitItem& other) noexcept = default; inline RABlockVisitItem& operator=(const RABlockVisitItem& other) noexcept = default; inline RABlock* block() const noexcept { return _block; } inline uint32_t index() const noexcept { return _index; } - - RABlock* _block; - uint32_t _index; }; Error BaseRAPass::buildCFGViews() noexcept { @@ -460,12 +476,18 @@ Error BaseRAPass::buildCFGDominators() noexcept { entryBlock->setIDom(entryBlock); bool changed = true; - uint32_t nIters = 0; + +#ifndef ASMJIT_NO_LOGGING + uint32_t numIters = 0; +#endif while (changed) { - nIters++; changed = false; +#ifndef ASMJIT_NO_LOGGING + numIters++; +#endif + uint32_t i = _pov.size(); while (i) { RABlock* block = _pov[--i]; @@ -492,7 +514,7 @@ Error BaseRAPass::buildCFGDominators() noexcept { } } - ASMJIT_RA_LOG_FORMAT(" Done (%u iterations)\n", nIters); + ASMJIT_RA_LOG_FORMAT(" Done (%u iterations)\n", numIters); return kErrorOk; } @@ -740,6 +762,13 @@ namespace LiveOps { static ASMJIT_FORCE_INLINE bool op(BitWord* dst, const BitWord* a, const BitWord* b, const BitWord* c, uint32_t n) noexcept { BitWord changed = 0; +#if defined(_MSC_VER) && _MSC_VER <= 1938 + // MSVC workaround (see #427). + // + // MSVC incorrectly auto-vectorizes this loop when used with <In> operator. For some reason it trashes a content + // of a register, which causes the result to be incorrect. It's a compiler bug we have to prevent unfortunately. + #pragma loop(no_vector) +#endif for (uint32_t i = 0; i < n; i++) { BitWord before = dst[i]; BitWord after = Operator::op(before, a[i], b[i], c[i]); @@ -751,7 +780,7 @@ namespace LiveOps { return changed != 0; } - static ASMJIT_FORCE_INLINE bool recalcInOut(RABlock* block, uint32_t numBitWords, bool initial = false) noexcept { + static ASMJIT_NOINLINE bool recalcInOut(RABlock* block, uint32_t numBitWords, bool initial = false) noexcept { bool changed = initial; const RABlocks& successors = block->successors(); @@ -782,7 +811,6 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { uint32_t numAllBlocks = blockCount(); uint32_t numReachableBlocks = reachableBlockCount(); - uint32_t numVisits = numReachableBlocks; uint32_t numWorkRegs = workRegCount(); uint32_t numBitWords = ZoneBitVector::_wordsPerBits(numWorkRegs); @@ -852,7 +880,7 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { if (tiedReg->hasConsecutiveParent()) { RAWorkReg* consecutiveParentReg = workRegById(tiedReg->consecutiveParent()); - consecutiveParentReg->addImmediateConsecutive(allocator(), workId); + ASMJIT_PROPAGATE(consecutiveParentReg->addImmediateConsecutive(allocator(), workId)); } } @@ -872,6 +900,10 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { // Calculate IN/OUT of Each Block // ------------------------------ +#ifndef ASMJIT_NO_LOGGING + uint32_t numVisits = numReachableBlocks; +#endif + { ZoneStack<RABlock*> workList; ZoneBitVector workBits; @@ -902,7 +934,9 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { } } } +#ifndef ASMJIT_NO_LOGGING numVisits++; +#endif } workList.reset(); @@ -1146,7 +1180,7 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::initGlobalLiveSpans() noexcept { return DebugUtils::errored(kErrorOutOfMemory); for (size_t physId = 0; physId < physCount; physId++) - new(&liveSpans[physId]) LiveRegSpans(); + new(Support::PlacementNew{&liveSpans[physId]}) LiveRegSpans(); } _globalLiveSpans[group] = liveSpans; @@ -1189,6 +1223,7 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(RegGroup group) noexcept { uint32_t numWorkRegs = workRegs.size(); RegMask availableRegs = _availableRegs[group]; + RegMask preservedRegs = func()->frame().preservedRegs(group); // First try to pack everything that provides register-id hint as these are most likely function arguments and fixed // (precolored) virtual registers. @@ -1320,18 +1355,30 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(RegGroup group) noexcept { if (workReg->isAllocated()) continue; - RegMask physRegs = availableRegs; - if (physRegs & workReg->preferredMask()) - physRegs &= workReg->preferredMask(); + RegMask remainingPhysRegs = availableRegs; + if (remainingPhysRegs & workReg->preferredMask()) + remainingPhysRegs &= workReg->preferredMask(); - while (physRegs) { - RegMask preferredMask = physRegs; - uint32_t physId = Support::ctz(preferredMask); + RegMask physRegs = remainingPhysRegs & ~preservedRegs; + remainingPhysRegs &= preservedRegs; + + for (;;) { + if (!physRegs) { + if (!remainingPhysRegs) + break; + physRegs = remainingPhysRegs; + remainingPhysRegs = 0; + } + + uint32_t physId = Support::ctz(physRegs); if (workReg->clobberSurvivalMask()) { - preferredMask &= workReg->clobberSurvivalMask(); - if (preferredMask) + RegMask preferredMask = (physRegs | remainingPhysRegs) & workReg->clobberSurvivalMask(); + if (preferredMask) { + if (preferredMask & ~remainingPhysRegs) + preferredMask &= ~remainingPhysRegs; physId = Support::ctz(preferredMask); + } } LiveRegSpans& live = _globalLiveSpans[group][physId]; @@ -1347,7 +1394,8 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(RegGroup group) noexcept { if (ASMJIT_UNLIKELY(err != 0xFFFFFFFFu)) return err; - physRegs ^= Support::bitMask(physId); + physRegs &= ~Support::bitMask(physId); + remainingPhysRegs &= ~Support::bitMask(physId); } // Keep it in `workRegs` if it was not allocated. @@ -1806,6 +1854,50 @@ Error BaseRAPass::rewrite() noexcept { return _rewrite(_func, _stop); } +// [[pure virtual]] +Error BaseRAPass::_rewrite(BaseNode* first, BaseNode* stop) noexcept { + DebugUtils::unused(first, stop); + return DebugUtils::errored(kErrorInvalidState); +} + +// BaseRAPass - Emit +// ================= + +// [[pure virtual]] +Error BaseRAPass::emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { + DebugUtils::unused(workId, dstPhysId, srcPhysId); + return DebugUtils::errored(kErrorInvalidState); +} + +// [[pure virtual]] +Error BaseRAPass::emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { + DebugUtils::unused(aWorkId, aPhysId, bWorkId, bPhysId); + return DebugUtils::errored(kErrorInvalidState); +} + +// [[pure virtual]] +Error BaseRAPass::emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept { + DebugUtils::unused(workId, dstPhysId); + return DebugUtils::errored(kErrorInvalidState); +} + +// [[pure virtual]] +Error BaseRAPass::emitSave(uint32_t workId, uint32_t srcPhysId) noexcept { + DebugUtils::unused(workId, srcPhysId); + return DebugUtils::errored(kErrorInvalidState); +} + +// [[pure virtual]] +Error BaseRAPass::emitJump(const Label& label) noexcept { + DebugUtils::unused(label); + return DebugUtils::errored(kErrorInvalidState); +} + +Error BaseRAPass::emitPreCall(InvokeNode* invokeNode) noexcept { + DebugUtils::unused(invokeNode); + return DebugUtils::errored(kErrorOk); +} + // BaseRAPass - Logging // ==================== diff --git a/3rdparty/asmjit/src/asmjit/core/rapass_p.h b/3rdparty/asmjit/src/asmjit/core/rapass_p.h index 94738293667..967624045c5 100644 --- a/3rdparty/asmjit/src/asmjit/core/rapass_p.h +++ b/3rdparty/asmjit/src/asmjit/core/rapass_p.h @@ -137,7 +137,7 @@ public: //! \name Construction & Destruction //! \{ - inline RABlock(BaseRAPass* ra) noexcept + ASMJIT_INLINE_NODEBUG RABlock(BaseRAPass* ra) noexcept : _ra(ra) {} //! \} @@ -145,96 +145,96 @@ public: //! \name Accessors //! \{ - inline BaseRAPass* pass() const noexcept { return _ra; } - inline ZoneAllocator* allocator() const noexcept; + ASMJIT_INLINE_NODEBUG BaseRAPass* pass() const noexcept { return _ra; } + ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept; - inline uint32_t blockId() const noexcept { return _blockId; } - inline RABlockFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG uint32_t blockId() const noexcept { return _blockId; } + ASMJIT_INLINE_NODEBUG RABlockFlags flags() const noexcept { return _flags; } - inline bool hasFlag(RABlockFlags flag) const noexcept { return Support::test(_flags, flag); } - inline void addFlags(RABlockFlags flags) noexcept { _flags |= flags; } + ASMJIT_INLINE_NODEBUG bool hasFlag(RABlockFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG void addFlags(RABlockFlags flags) noexcept { _flags |= flags; } - inline bool isAssigned() const noexcept { return _blockId != kUnassignedId; } + ASMJIT_INLINE_NODEBUG bool isAssigned() const noexcept { return _blockId != kUnassignedId; } - inline bool isConstructed() const noexcept { return hasFlag(RABlockFlags::kIsConstructed); } - inline bool isReachable() const noexcept { return hasFlag(RABlockFlags::kIsReachable); } - inline bool isTargetable() const noexcept { return hasFlag(RABlockFlags::kIsTargetable); } - inline bool isAllocated() const noexcept { return hasFlag(RABlockFlags::kIsAllocated); } - inline bool isFuncExit() const noexcept { return hasFlag(RABlockFlags::kIsFuncExit); } - inline bool hasTerminator() const noexcept { return hasFlag(RABlockFlags::kHasTerminator); } - inline bool hasConsecutive() const noexcept { return hasFlag(RABlockFlags::kHasConsecutive); } - inline bool hasJumpTable() const noexcept { return hasFlag(RABlockFlags::kHasJumpTable); } + ASMJIT_INLINE_NODEBUG bool isConstructed() const noexcept { return hasFlag(RABlockFlags::kIsConstructed); } + ASMJIT_INLINE_NODEBUG bool isReachable() const noexcept { return hasFlag(RABlockFlags::kIsReachable); } + ASMJIT_INLINE_NODEBUG bool isTargetable() const noexcept { return hasFlag(RABlockFlags::kIsTargetable); } + ASMJIT_INLINE_NODEBUG bool isAllocated() const noexcept { return hasFlag(RABlockFlags::kIsAllocated); } + ASMJIT_INLINE_NODEBUG bool isFuncExit() const noexcept { return hasFlag(RABlockFlags::kIsFuncExit); } + ASMJIT_INLINE_NODEBUG bool hasTerminator() const noexcept { return hasFlag(RABlockFlags::kHasTerminator); } + ASMJIT_INLINE_NODEBUG bool hasConsecutive() const noexcept { return hasFlag(RABlockFlags::kHasConsecutive); } + ASMJIT_INLINE_NODEBUG bool hasJumpTable() const noexcept { return hasFlag(RABlockFlags::kHasJumpTable); } - inline void makeConstructed(const RARegsStats& regStats) noexcept { + ASMJIT_INLINE_NODEBUG void makeConstructed(const RARegsStats& regStats) noexcept { _flags |= RABlockFlags::kIsConstructed; _regsStats.combineWith(regStats); } - inline void makeReachable() noexcept { _flags |= RABlockFlags::kIsReachable; } - inline void makeTargetable() noexcept { _flags |= RABlockFlags::kIsTargetable; } - inline void makeAllocated() noexcept { _flags |= RABlockFlags::kIsAllocated; } + ASMJIT_INLINE_NODEBUG void makeReachable() noexcept { _flags |= RABlockFlags::kIsReachable; } + ASMJIT_INLINE_NODEBUG void makeTargetable() noexcept { _flags |= RABlockFlags::kIsTargetable; } + ASMJIT_INLINE_NODEBUG void makeAllocated() noexcept { _flags |= RABlockFlags::kIsAllocated; } - inline const RARegsStats& regsStats() const noexcept { return _regsStats; } + ASMJIT_INLINE_NODEBUG const RARegsStats& regsStats() const noexcept { return _regsStats; } - inline bool hasPredecessors() const noexcept { return !_predecessors.empty(); } - inline bool hasSuccessors() const noexcept { return !_successors.empty(); } + ASMJIT_INLINE_NODEBUG bool hasPredecessors() const noexcept { return !_predecessors.empty(); } + ASMJIT_INLINE_NODEBUG bool hasSuccessors() const noexcept { return !_successors.empty(); } - inline bool hasSuccessor(RABlock* block) noexcept { + ASMJIT_INLINE_NODEBUG bool hasSuccessor(RABlock* block) noexcept { if (block->_predecessors.size() < _successors.size()) return block->_predecessors.contains(this); else return _successors.contains(block); } - inline const RABlocks& predecessors() const noexcept { return _predecessors; } - inline const RABlocks& successors() const noexcept { return _successors; } + ASMJIT_INLINE_NODEBUG const RABlocks& predecessors() const noexcept { return _predecessors; } + ASMJIT_INLINE_NODEBUG const RABlocks& successors() const noexcept { return _successors; } - inline BaseNode* first() const noexcept { return _first; } - inline BaseNode* last() const noexcept { return _last; } + ASMJIT_INLINE_NODEBUG BaseNode* first() const noexcept { return _first; } + ASMJIT_INLINE_NODEBUG BaseNode* last() const noexcept { return _last; } - inline void setFirst(BaseNode* node) noexcept { _first = node; } - inline void setLast(BaseNode* node) noexcept { _last = node; } + ASMJIT_INLINE_NODEBUG void setFirst(BaseNode* node) noexcept { _first = node; } + ASMJIT_INLINE_NODEBUG void setLast(BaseNode* node) noexcept { _last = node; } - inline uint32_t firstPosition() const noexcept { return _firstPosition; } - inline void setFirstPosition(uint32_t position) noexcept { _firstPosition = position; } + ASMJIT_INLINE_NODEBUG uint32_t firstPosition() const noexcept { return _firstPosition; } + ASMJIT_INLINE_NODEBUG void setFirstPosition(uint32_t position) noexcept { _firstPosition = position; } - inline uint32_t endPosition() const noexcept { return _endPosition; } - inline void setEndPosition(uint32_t position) noexcept { _endPosition = position; } + ASMJIT_INLINE_NODEBUG uint32_t endPosition() const noexcept { return _endPosition; } + ASMJIT_INLINE_NODEBUG void setEndPosition(uint32_t position) noexcept { _endPosition = position; } - inline uint32_t povOrder() const noexcept { return _povOrder; } + ASMJIT_INLINE_NODEBUG uint32_t povOrder() const noexcept { return _povOrder; } - inline RegMask entryScratchGpRegs() const noexcept; - inline RegMask exitScratchGpRegs() const noexcept { return _exitScratchGpRegs; } + ASMJIT_INLINE_NODEBUG RegMask entryScratchGpRegs() const noexcept; + ASMJIT_INLINE_NODEBUG RegMask exitScratchGpRegs() const noexcept { return _exitScratchGpRegs; } - inline void addEntryScratchGpRegs(RegMask regMask) noexcept { _entryScratchGpRegs |= regMask; } - inline void addExitScratchGpRegs(RegMask regMask) noexcept { _exitScratchGpRegs |= regMask; } + ASMJIT_INLINE_NODEBUG void addEntryScratchGpRegs(RegMask regMask) noexcept { _entryScratchGpRegs |= regMask; } + ASMJIT_INLINE_NODEBUG void addExitScratchGpRegs(RegMask regMask) noexcept { _exitScratchGpRegs |= regMask; } - inline bool hasSharedAssignmentId() const noexcept { return _sharedAssignmentId != Globals::kInvalidId; } - inline uint32_t sharedAssignmentId() const noexcept { return _sharedAssignmentId; } - inline void setSharedAssignmentId(uint32_t id) noexcept { _sharedAssignmentId = id; } + ASMJIT_INLINE_NODEBUG bool hasSharedAssignmentId() const noexcept { return _sharedAssignmentId != Globals::kInvalidId; } + ASMJIT_INLINE_NODEBUG uint32_t sharedAssignmentId() const noexcept { return _sharedAssignmentId; } + ASMJIT_INLINE_NODEBUG void setSharedAssignmentId(uint32_t id) noexcept { _sharedAssignmentId = id; } - inline uint64_t timestamp() const noexcept { return _timestamp; } - inline bool hasTimestamp(uint64_t ts) const noexcept { return _timestamp == ts; } - inline void setTimestamp(uint64_t ts) const noexcept { _timestamp = ts; } - inline void resetTimestamp() const noexcept { _timestamp = 0; } + ASMJIT_INLINE_NODEBUG uint64_t timestamp() const noexcept { return _timestamp; } + ASMJIT_INLINE_NODEBUG bool hasTimestamp(uint64_t ts) const noexcept { return _timestamp == ts; } + ASMJIT_INLINE_NODEBUG void setTimestamp(uint64_t ts) const noexcept { _timestamp = ts; } + ASMJIT_INLINE_NODEBUG void resetTimestamp() const noexcept { _timestamp = 0; } - inline RABlock* consecutive() const noexcept { return hasConsecutive() ? _successors[0] : nullptr; } + ASMJIT_INLINE_NODEBUG RABlock* consecutive() const noexcept { return hasConsecutive() ? _successors[0] : nullptr; } - inline RABlock* iDom() noexcept { return _idom; } - inline const RABlock* iDom() const noexcept { return _idom; } - inline void setIDom(RABlock* block) noexcept { _idom = block; } + ASMJIT_INLINE_NODEBUG RABlock* iDom() noexcept { return _idom; } + ASMJIT_INLINE_NODEBUG const RABlock* iDom() const noexcept { return _idom; } + ASMJIT_INLINE_NODEBUG void setIDom(RABlock* block) noexcept { _idom = block; } - inline ZoneBitVector& liveIn() noexcept { return _liveBits[kLiveIn]; } - inline const ZoneBitVector& liveIn() const noexcept { return _liveBits[kLiveIn]; } + ASMJIT_INLINE_NODEBUG ZoneBitVector& liveIn() noexcept { return _liveBits[kLiveIn]; } + ASMJIT_INLINE_NODEBUG const ZoneBitVector& liveIn() const noexcept { return _liveBits[kLiveIn]; } - inline ZoneBitVector& liveOut() noexcept { return _liveBits[kLiveOut]; } - inline const ZoneBitVector& liveOut() const noexcept { return _liveBits[kLiveOut]; } + ASMJIT_INLINE_NODEBUG ZoneBitVector& liveOut() noexcept { return _liveBits[kLiveOut]; } + ASMJIT_INLINE_NODEBUG const ZoneBitVector& liveOut() const noexcept { return _liveBits[kLiveOut]; } - inline ZoneBitVector& gen() noexcept { return _liveBits[kLiveGen]; } - inline const ZoneBitVector& gen() const noexcept { return _liveBits[kLiveGen]; } + ASMJIT_INLINE_NODEBUG ZoneBitVector& gen() noexcept { return _liveBits[kLiveGen]; } + ASMJIT_INLINE_NODEBUG const ZoneBitVector& gen() const noexcept { return _liveBits[kLiveGen]; } - inline ZoneBitVector& kill() noexcept { return _liveBits[kLiveKill]; } - inline const ZoneBitVector& kill() const noexcept { return _liveBits[kLiveKill]; } + ASMJIT_INLINE_NODEBUG ZoneBitVector& kill() noexcept { return _liveBits[kLiveKill]; } + ASMJIT_INLINE_NODEBUG const ZoneBitVector& kill() const noexcept { return _liveBits[kLiveKill]; } inline Error resizeLiveBits(uint32_t size) noexcept { ASMJIT_PROPAGATE(_liveBits[kLiveIn ].resize(allocator(), size)); @@ -244,9 +244,9 @@ public: return kErrorOk; } - inline bool hasEntryAssignment() const noexcept { return _entryPhysToWorkMap != nullptr; } - inline PhysToWorkMap* entryPhysToWorkMap() const noexcept { return _entryPhysToWorkMap; } - inline void setEntryAssignment(PhysToWorkMap* physToWorkMap) noexcept { _entryPhysToWorkMap = physToWorkMap; } + ASMJIT_INLINE_NODEBUG bool hasEntryAssignment() const noexcept { return _entryPhysToWorkMap != nullptr; } + ASMJIT_INLINE_NODEBUG PhysToWorkMap* entryPhysToWorkMap() const noexcept { return _entryPhysToWorkMap; } + ASMJIT_INLINE_NODEBUG void setEntryAssignment(PhysToWorkMap* physToWorkMap) noexcept { _entryPhysToWorkMap = physToWorkMap; } //! \} @@ -318,38 +318,40 @@ public: //! \{ //! Returns instruction RW flags. - inline InstRWFlags instRWFlags() const noexcept { return _instRWFlags; }; + ASMJIT_INLINE_NODEBUG InstRWFlags instRWFlags() const noexcept { return _instRWFlags; }; //! Tests whether the given `flag` is present in instruction RW flags. - inline bool hasInstRWFlag(InstRWFlags flag) const noexcept { return Support::test(_instRWFlags, flag); } + ASMJIT_INLINE_NODEBUG bool hasInstRWFlag(InstRWFlags flag) const noexcept { return Support::test(_instRWFlags, flag); } //! Adds `flags` to instruction RW flags. - inline void addInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags |= flags; } + ASMJIT_INLINE_NODEBUG void addInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags |= flags; } //! Returns the instruction flags. - inline RATiedFlags flags() const noexcept { return _flags; } + ASMJIT_INLINE_NODEBUG RATiedFlags flags() const noexcept { return _flags; } //! Tests whether the instruction has flag `flag`. - inline bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); } //! Replaces the existing instruction flags with `flags`. - inline void setFlags(RATiedFlags flags) noexcept { _flags = flags; } + ASMJIT_INLINE_NODEBUG void setFlags(RATiedFlags flags) noexcept { _flags = flags; } //! Adds instruction `flags` to this RAInst. - inline void addFlags(RATiedFlags flags) noexcept { _flags |= flags; } + ASMJIT_INLINE_NODEBUG void addFlags(RATiedFlags flags) noexcept { _flags |= flags; } //! Clears instruction `flags` from this RAInst. - inline void clearFlags(RATiedFlags flags) noexcept { _flags &= ~flags; } + ASMJIT_INLINE_NODEBUG void clearFlags(RATiedFlags flags) noexcept { _flags &= ~flags; } + //! Tests whether one operand of this instruction has been patched from Reg to Mem. + ASMJIT_INLINE_NODEBUG bool isRegToMemPatched() const noexcept { return hasFlag(RATiedFlags::kInst_RegToMemPatched); } //! Tests whether this instruction can be transformed to another instruction if necessary. - inline bool isTransformable() const noexcept { return hasFlag(RATiedFlags::kInst_IsTransformable); } + ASMJIT_INLINE_NODEBUG bool isTransformable() const noexcept { return hasFlag(RATiedFlags::kInst_IsTransformable); } //! Returns the associated block with this RAInst. - inline RABlock* block() const noexcept { return _block; } + ASMJIT_INLINE_NODEBUG RABlock* block() const noexcept { return _block; } //! Returns tied registers (all). - inline RATiedReg* tiedRegs() const noexcept { return const_cast<RATiedReg*>(_tiedRegs); } + ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs() const noexcept { return const_cast<RATiedReg*>(_tiedRegs); } //! Returns tied registers for a given `group`. - inline RATiedReg* tiedRegs(RegGroup group) const noexcept { return const_cast<RATiedReg*>(_tiedRegs) + _tiedIndex.get(group); } + ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs(RegGroup group) const noexcept { return const_cast<RATiedReg*>(_tiedRegs) + _tiedIndex.get(group); } //! Returns count of all tied registers. - inline uint32_t tiedCount() const noexcept { return _tiedTotal; } + ASMJIT_INLINE_NODEBUG uint32_t tiedCount() const noexcept { return _tiedTotal; } //! Returns count of tied registers of a given `group`. - inline uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount[group]; } + ASMJIT_INLINE_NODEBUG uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount[group]; } //! Returns `RATiedReg` at the given `index`. inline RATiedReg* tiedAt(uint32_t index) const noexcept { @@ -371,7 +373,7 @@ public: //! \name Static Functions //! \{ - static inline size_t sizeOf(uint32_t tiedRegCount) noexcept { + static ASMJIT_INLINE_NODEBUG size_t sizeOf(uint32_t tiedRegCount) noexcept { return sizeof(RAInst) - sizeof(RATiedReg) + tiedRegCount * sizeof(RATiedReg); } @@ -409,10 +411,10 @@ public: //! \name Construction & Destruction //! \{ - inline RAInstBuilder() noexcept { reset(); } + ASMJIT_INLINE_NODEBUG RAInstBuilder() noexcept { reset(); } - inline void init() noexcept { reset(); } - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void init() noexcept { reset(); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _instRWFlags = InstRWFlags::kNone; _aggregatedFlags = RATiedFlags::kNone; _forbiddenFlags = RATiedFlags::kNone; @@ -428,25 +430,25 @@ public: //! \name Accessors //! \{ - inline InstRWFlags instRWFlags() const noexcept { return _instRWFlags; } - inline bool hasInstRWFlag(InstRWFlags flag) const noexcept { return Support::test(_instRWFlags, flag); } - inline void addInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags |= flags; } - inline void clearInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags &= ~flags; } + ASMJIT_INLINE_NODEBUG InstRWFlags instRWFlags() const noexcept { return _instRWFlags; } + ASMJIT_INLINE_NODEBUG bool hasInstRWFlag(InstRWFlags flag) const noexcept { return Support::test(_instRWFlags, flag); } + ASMJIT_INLINE_NODEBUG void addInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags |= flags; } + ASMJIT_INLINE_NODEBUG void clearInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags &= ~flags; } - inline RATiedFlags aggregatedFlags() const noexcept { return _aggregatedFlags; } - inline void addAggregatedFlags(RATiedFlags flags) noexcept { _aggregatedFlags |= flags; } + ASMJIT_INLINE_NODEBUG RATiedFlags aggregatedFlags() const noexcept { return _aggregatedFlags; } + ASMJIT_INLINE_NODEBUG void addAggregatedFlags(RATiedFlags flags) noexcept { _aggregatedFlags |= flags; } - inline RATiedFlags forbiddenFlags() const noexcept { return _forbiddenFlags; } - inline void addForbiddenFlags(RATiedFlags flags) noexcept { _forbiddenFlags |= flags; } + ASMJIT_INLINE_NODEBUG RATiedFlags forbiddenFlags() const noexcept { return _forbiddenFlags; } + ASMJIT_INLINE_NODEBUG void addForbiddenFlags(RATiedFlags flags) noexcept { _forbiddenFlags |= flags; } //! Returns the number of tied registers added to the builder. - inline uint32_t tiedRegCount() const noexcept { return uint32_t((size_t)(_cur - _tiedRegs)); } + ASMJIT_INLINE_NODEBUG uint32_t tiedRegCount() const noexcept { return uint32_t((size_t)(_cur - _tiedRegs)); } - inline RATiedReg* begin() noexcept { return _tiedRegs; } - inline RATiedReg* end() noexcept { return _cur; } + ASMJIT_INLINE_NODEBUG RATiedReg* begin() noexcept { return _tiedRegs; } + ASMJIT_INLINE_NODEBUG RATiedReg* end() noexcept { return _cur; } - inline const RATiedReg* begin() const noexcept { return _tiedRegs; } - inline const RATiedReg* end() const noexcept { return _cur; } + ASMJIT_INLINE_NODEBUG const RATiedReg* begin() const noexcept { return _tiedRegs; } + ASMJIT_INLINE_NODEBUG const RATiedReg* end() const noexcept { return _cur; } //! Returns `RATiedReg` at the given `index`. inline RATiedReg* operator[](uint32_t index) noexcept { @@ -634,15 +636,15 @@ public: //! \name Accessors //! \{ - inline bool empty() const noexcept { return _physToWorkMap == nullptr; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _physToWorkMap == nullptr; } - inline RegMask entryScratchGpRegs() const noexcept { return _entryScratchGpRegs; } - inline void addEntryScratchGpRegs(RegMask mask) noexcept { _entryScratchGpRegs |= mask; } + ASMJIT_INLINE_NODEBUG RegMask entryScratchGpRegs() const noexcept { return _entryScratchGpRegs; } + ASMJIT_INLINE_NODEBUG void addEntryScratchGpRegs(RegMask mask) noexcept { _entryScratchGpRegs |= mask; } - inline const ZoneBitVector& liveIn() const noexcept { return _liveIn; } + ASMJIT_INLINE_NODEBUG const ZoneBitVector& liveIn() const noexcept { return _liveIn; } - inline PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; } - inline void assignPhysToWorkMap(PhysToWorkMap* physToWorkMap) noexcept { _physToWorkMap = physToWorkMap; } + ASMJIT_INLINE_NODEBUG PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; } + ASMJIT_INLINE_NODEBUG void assignPhysToWorkMap(PhysToWorkMap* physToWorkMap) noexcept { _physToWorkMap = physToWorkMap; } //! \} }; @@ -754,7 +756,7 @@ public: //! \{ BaseRAPass() noexcept; - virtual ~BaseRAPass() noexcept; + ~BaseRAPass() noexcept override; //! \} @@ -762,38 +764,38 @@ public: //! \{ //! Returns \ref Logger passed to \ref runOnFunction(). - inline Logger* logger() const noexcept { return _logger; } + ASMJIT_INLINE_NODEBUG Logger* logger() const noexcept { return _logger; } //! Returns either a valid logger if the given `option` is set and logging is enabled, or nullptr. - inline Logger* getLoggerIf(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option) ? _logger : nullptr; } + ASMJIT_INLINE_NODEBUG Logger* getLoggerIf(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option) ? _logger : nullptr; } //! Returns whether the diagnostic `option` is enabled. //! //! \note Returns false if there is no logger (as diagnostics without logging make no sense). - inline bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); } + ASMJIT_INLINE_NODEBUG bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); } //! Returns \ref Zone passed to \ref runOnFunction(). - inline Zone* zone() const noexcept { return _allocator.zone(); } + ASMJIT_INLINE_NODEBUG Zone* zone() const noexcept { return _allocator.zone(); } //! Returns \ref ZoneAllocator used by the register allocator. - inline ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); } + ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); } - inline const ZoneVector<RASharedAssignment>& sharedAssignments() const { return _sharedAssignments; } - inline uint32_t sharedAssignmentCount() const noexcept { return _sharedAssignments.size(); } + ASMJIT_INLINE_NODEBUG const ZoneVector<RASharedAssignment>& sharedAssignments() const { return _sharedAssignments; } + ASMJIT_INLINE_NODEBUG uint32_t sharedAssignmentCount() const noexcept { return _sharedAssignments.size(); } //! Returns the current function node. - inline FuncNode* func() const noexcept { return _func; } + ASMJIT_INLINE_NODEBUG FuncNode* func() const noexcept { return _func; } //! Returns the stop of the current function. - inline BaseNode* stop() const noexcept { return _stop; } + ASMJIT_INLINE_NODEBUG BaseNode* stop() const noexcept { return _stop; } //! Returns an extra block used by the current function being processed. - inline BaseNode* extraBlock() const noexcept { return _extraBlock; } + ASMJIT_INLINE_NODEBUG BaseNode* extraBlock() const noexcept { return _extraBlock; } //! Sets an extra block, see `extraBlock()`. - inline void setExtraBlock(BaseNode* node) noexcept { _extraBlock = node; } + ASMJIT_INLINE_NODEBUG void setExtraBlock(BaseNode* node) noexcept { _extraBlock = node; } - inline uint32_t endPosition() const noexcept { return _instructionCount * 2; } + ASMJIT_INLINE_NODEBUG uint32_t endPosition() const noexcept { return _instructionCount * 2; } - inline const RARegMask& availableRegs() const noexcept { return _availableRegs; } - inline const RARegMask& cloberredRegs() const noexcept { return _clobberedRegs; } + ASMJIT_INLINE_NODEBUG const RARegMask& availableRegs() const noexcept { return _availableRegs; } + ASMJIT_INLINE_NODEBUG const RARegMask& clobberedRegs() const noexcept { return _clobberedRegs; } //! \} @@ -818,11 +820,11 @@ public: //! Called by \ref runOnFunction() before the register allocation to initialize //! architecture-specific data and constraints. - virtual void onInit() noexcept = 0; + virtual void onInit() noexcept; //! Called by \ref runOnFunction(` after register allocation to clean everything //! up. Called even if the register allocation failed. - virtual void onDone() noexcept = 0; + virtual void onDone() noexcept; //! \} @@ -842,26 +844,26 @@ public: } //! Returns all basic blocks of this function. - inline RABlocks& blocks() noexcept { return _blocks; } + ASMJIT_INLINE_NODEBUG RABlocks& blocks() noexcept { return _blocks; } //! \overload - inline const RABlocks& blocks() const noexcept { return _blocks; } + ASMJIT_INLINE_NODEBUG const RABlocks& blocks() const noexcept { return _blocks; } //! Returns the count of basic blocks (returns size of `_blocks` array). - inline uint32_t blockCount() const noexcept { return _blocks.size(); } + ASMJIT_INLINE_NODEBUG uint32_t blockCount() const noexcept { return _blocks.size(); } //! Returns the count of reachable basic blocks (returns size of `_pov` array). - inline uint32_t reachableBlockCount() const noexcept { return _pov.size(); } + ASMJIT_INLINE_NODEBUG uint32_t reachableBlockCount() const noexcept { return _pov.size(); } //! Tests whether the CFG has dangling blocks - these were created by `newBlock()`, but not added to CFG through //! `addBlocks()`. If `true` is returned and the CFG is constructed it means that something is missing and it's //! incomplete. //! //! \note This is only used to check if the number of created blocks matches the number of added blocks. - inline bool hasDanglingBlocks() const noexcept { return _createdBlockCount != blockCount(); } + ASMJIT_INLINE_NODEBUG bool hasDanglingBlocks() const noexcept { return _createdBlockCount != blockCount(); } //! Gest a next timestamp to be used to mark CFG blocks. - inline uint64_t nextTimestamp() const noexcept { return ++_lastTimestamp; } + ASMJIT_INLINE_NODEBUG uint64_t nextTimestamp() const noexcept { return ++_lastTimestamp; } - //! Createss a new `RABlock` instance. + //! Creates a new `RABlock` instance. //! //! \note New blocks don't have ID assigned until they are added to the block array by calling `addBlock()`. RABlock* newBlock(BaseNode* initialNode = nullptr) noexcept; @@ -882,7 +884,7 @@ public: void* p = zone()->alloc(RAInst::sizeOf(tiedRegCount)); if (ASMJIT_UNLIKELY(!p)) return nullptr; - return new(p) RAInst(block, instRWFlags, flags, tiedRegCount, clobberedRegs); + return new(Support::PlacementNew{p}) RAInst(block, instRWFlags, flags, tiedRegCount, clobberedRegs); } ASMJIT_FORCE_INLINE Error assignRAInst(BaseNode* node, RABlock* block, RAInstBuilder& ib) noexcept { @@ -945,7 +947,7 @@ public: //! analysis and register allocation. //! //! Use `RACFGBuilderT` template that provides the necessary boilerplate. - virtual Error buildCFG() noexcept = 0; + virtual Error buildCFG() noexcept; //! Called after the CFG is built. Error initSharedAssignments(const ZoneVector<uint32_t>& sharedAssignmentsMap) noexcept; @@ -974,14 +976,14 @@ public: const RABlock* _nearestCommonDominator(const RABlock* a, const RABlock* b) const noexcept; //! Tests whether the basic block `a` dominates `b` - non-strict, returns true when `a == b`. - inline bool dominates(const RABlock* a, const RABlock* b) const noexcept { return a == b ? true : _strictlyDominates(a, b); } + ASMJIT_INLINE_NODEBUG bool dominates(const RABlock* a, const RABlock* b) const noexcept { return a == b ? true : _strictlyDominates(a, b); } //! Tests whether the basic block `a` dominates `b` - strict dominance check, returns false when `a == b`. - inline bool strictlyDominates(const RABlock* a, const RABlock* b) const noexcept { return a == b ? false : _strictlyDominates(a, b); } + ASMJIT_INLINE_NODEBUG bool strictlyDominates(const RABlock* a, const RABlock* b) const noexcept { return a == b ? false : _strictlyDominates(a, b); } //! Returns a nearest common dominator of `a` and `b`. - inline RABlock* nearestCommonDominator(RABlock* a, RABlock* b) const noexcept { return const_cast<RABlock*>(_nearestCommonDominator(a, b)); } + ASMJIT_INLINE_NODEBUG RABlock* nearestCommonDominator(RABlock* a, RABlock* b) const noexcept { return const_cast<RABlock*>(_nearestCommonDominator(a, b)); } //! Returns a nearest common dominator of `a` and `b` (const). - inline const RABlock* nearestCommonDominator(const RABlock* a, const RABlock* b) const noexcept { return _nearestCommonDominator(a, b); } + ASMJIT_INLINE_NODEBUG const RABlock* nearestCommonDominator(const RABlock* a, const RABlock* b) const noexcept { return _nearestCommonDominator(a, b); } //! \} @@ -1005,27 +1007,27 @@ public: //! \{ //! Returns a native size of the general-purpose register of the target architecture. - inline uint32_t registerSize() const noexcept { return _sp.size(); } - inline uint32_t availableRegCount(RegGroup group) const noexcept { return _availableRegCount[group]; } + ASMJIT_INLINE_NODEBUG uint32_t registerSize() const noexcept { return _sp.size(); } + ASMJIT_INLINE_NODEBUG uint32_t availableRegCount(RegGroup group) const noexcept { return _availableRegCount[group]; } - inline RAWorkReg* workRegById(uint32_t workId) const noexcept { return _workRegs[workId]; } + ASMJIT_INLINE_NODEBUG RAWorkReg* workRegById(uint32_t workId) const noexcept { return _workRegs[workId]; } - inline RAWorkRegs& workRegs() noexcept { return _workRegs; } - inline RAWorkRegs& workRegs(RegGroup group) noexcept { return _workRegsOfGroup[group]; } + ASMJIT_INLINE_NODEBUG RAWorkRegs& workRegs() noexcept { return _workRegs; } + ASMJIT_INLINE_NODEBUG RAWorkRegs& workRegs(RegGroup group) noexcept { return _workRegsOfGroup[group]; } - inline const RAWorkRegs& workRegs() const noexcept { return _workRegs; } - inline const RAWorkRegs& workRegs(RegGroup group) const noexcept { return _workRegsOfGroup[group]; } + ASMJIT_INLINE_NODEBUG const RAWorkRegs& workRegs() const noexcept { return _workRegs; } + ASMJIT_INLINE_NODEBUG const RAWorkRegs& workRegs(RegGroup group) const noexcept { return _workRegsOfGroup[group]; } - inline uint32_t workRegCount() const noexcept { return _workRegs.size(); } - inline uint32_t workRegCount(RegGroup group) const noexcept { return _workRegsOfGroup[group].size(); } + ASMJIT_INLINE_NODEBUG uint32_t workRegCount() const noexcept { return _workRegs.size(); } + ASMJIT_INLINE_NODEBUG uint32_t workRegCount(RegGroup group) const noexcept { return _workRegsOfGroup[group].size(); } inline void _buildPhysIndex() noexcept { _physRegIndex.buildIndexes(_physRegCount); _physRegTotal = uint32_t(_physRegIndex[RegGroup::kMaxVirt]) + uint32_t(_physRegCount[RegGroup::kMaxVirt]) ; } - inline uint32_t physRegIndex(RegGroup group) const noexcept { return _physRegIndex[group]; } - inline uint32_t physRegTotal() const noexcept { return _physRegTotal; } + ASMJIT_INLINE_NODEBUG uint32_t physRegIndex(RegGroup group) const noexcept { return _physRegIndex[group]; } + ASMJIT_INLINE_NODEBUG uint32_t physRegTotal() const noexcept { return _physRegTotal; } Error _asWorkReg(VirtReg* vReg, RAWorkReg** out) noexcept; @@ -1133,7 +1135,7 @@ public: //! \{ Error rewrite() noexcept; - virtual Error _rewrite(BaseNode* first, BaseNode* stop) noexcept = 0; + virtual Error _rewrite(BaseNode* first, BaseNode* stop) noexcept; //! \} @@ -1153,14 +1155,14 @@ public: //! \name Emit //! \{ - virtual Error emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept = 0; - virtual Error emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept = 0; + virtual Error emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept; + virtual Error emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept; - virtual Error emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept = 0; - virtual Error emitSave(uint32_t workId, uint32_t srcPhysId) noexcept = 0; + virtual Error emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept; + virtual Error emitSave(uint32_t workId, uint32_t srcPhysId) noexcept; - virtual Error emitJump(const Label& label) noexcept = 0; - virtual Error emitPreCall(InvokeNode* invokeNode) noexcept = 0; + virtual Error emitJump(const Label& label) noexcept; + virtual Error emitPreCall(InvokeNode* invokeNode) noexcept; //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/rastack.cpp b/3rdparty/asmjit/src/asmjit/core/rastack.cpp index 2b7ed592df5..318fbded4b3 100644 --- a/3rdparty/asmjit/src/asmjit/core/rastack.cpp +++ b/3rdparty/asmjit/src/asmjit/core/rastack.cpp @@ -62,7 +62,7 @@ Error RAStackAllocator::calculateStackFrame() noexcept { // STEP 1: // - // Update usage based on the size of the slot. We boost smaller slots in a way that 32-bit register has higher + // Update usage based on the size of the slot. We boost smaller slots in a way that 32-bit register has a higher // priority than a 128-bit register, however, if one 128-bit register is used 4 times more than some other 32-bit // register it will overweight it. for (RAStackSlot* slot : _slots) { diff --git a/3rdparty/asmjit/src/asmjit/core/rastack_p.h b/3rdparty/asmjit/src/asmjit/core/rastack_p.h index 90640b4dea8..15db8e97948 100644 --- a/3rdparty/asmjit/src/asmjit/core/rastack_p.h +++ b/3rdparty/asmjit/src/asmjit/core/rastack_p.h @@ -104,13 +104,13 @@ public: //! \{ //! Allocator used to allocate internal data. - ZoneAllocator* _allocator; + ZoneAllocator* _allocator {}; //! Count of bytes used by all slots. - uint32_t _bytesUsed; + uint32_t _bytesUsed {}; //! Calculated stack size (can be a bit greater than `_bytesUsed`). - uint32_t _stackSize; + uint32_t _stackSize {}; //! Minimum stack alignment. - uint32_t _alignment; + uint32_t _alignment = 1; //! Stack slots vector. RAStackSlots _slots; @@ -119,14 +119,9 @@ public: //! \name Construction & Destruction //! \{ - inline RAStackAllocator() noexcept - : _allocator(nullptr), - _bytesUsed(0), - _stackSize(0), - _alignment(1), - _slots() {} + ASMJIT_INLINE_NODEBUG RAStackAllocator() noexcept {} - inline void reset(ZoneAllocator* allocator) noexcept { + ASMJIT_INLINE_NODEBUG void reset(ZoneAllocator* allocator) noexcept { _allocator = allocator; _bytesUsed = 0; _stackSize = 0; @@ -139,15 +134,15 @@ public: //! \name Accessors //! \{ - inline ZoneAllocator* allocator() const noexcept { return _allocator; } + ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept { return _allocator; } - inline uint32_t bytesUsed() const noexcept { return _bytesUsed; } - inline uint32_t stackSize() const noexcept { return _stackSize; } - inline uint32_t alignment() const noexcept { return _alignment; } + ASMJIT_INLINE_NODEBUG uint32_t bytesUsed() const noexcept { return _bytesUsed; } + ASMJIT_INLINE_NODEBUG uint32_t stackSize() const noexcept { return _stackSize; } + ASMJIT_INLINE_NODEBUG uint32_t alignment() const noexcept { return _alignment; } - inline RAStackSlots& slots() noexcept { return _slots; } - inline const RAStackSlots& slots() const noexcept { return _slots; } - inline uint32_t slotCount() const noexcept { return _slots.size(); } + ASMJIT_INLINE_NODEBUG RAStackSlots& slots() noexcept { return _slots; } + ASMJIT_INLINE_NODEBUG const RAStackSlots& slots() const noexcept { return _slots; } + ASMJIT_INLINE_NODEBUG uint32_t slotCount() const noexcept { return _slots.size(); } //! \} diff --git a/3rdparty/asmjit/src/asmjit/core/string.cpp b/3rdparty/asmjit/src/asmjit/core/string.cpp index 83dc6efdaac..369d060e248 100644 --- a/3rdparty/asmjit/src/asmjit/core/string.cpp +++ b/3rdparty/asmjit/src/asmjit/core/string.cpp @@ -14,9 +14,51 @@ ASMJIT_BEGIN_NAMESPACE static const char String_baseN[] = "0123456789ABCDEF"; -constexpr size_t kMinAllocSize = 64; +constexpr size_t kMinAllocSize = 128; constexpr size_t kMaxAllocSize = SIZE_MAX - Globals::kGrowThreshold; +// Based on ZoneVector_growCapacity(). +// +// NOTE: The sizes here include null terminators - that way we can have aligned allocations that are power of 2s +// initially. +static ASMJIT_FORCE_INLINE size_t String_growCapacity(size_t byteSize, size_t minimumByteSize) noexcept { + static constexpr size_t kGrowThreshold = Globals::kGrowThreshold; + + ASMJIT_ASSERT(minimumByteSize < kMaxAllocSize); + + // This is more than exponential growth at the beginning. + if (byteSize < kMinAllocSize) { + byteSize = kMinAllocSize; + } + else if (byteSize < 512) { + byteSize = 512; + } + + if (byteSize < minimumByteSize) { + // Exponential growth before we reach `kGrowThreshold`. + byteSize = Support::alignUpPowerOf2(minimumByteSize); + + // Bail to `minimumByteSize` in case of overflow - most likely whatever that is happening afterwards would just fail. + if (byteSize < minimumByteSize) { + return minimumByteSize; + } + + // Pretty much chunked growth advancing by `kGrowThreshold` after we exceed it. + if (byteSize > kGrowThreshold) { + // Align to kGrowThreshold. + size_t remainder = minimumByteSize % kGrowThreshold; + + byteSize = minimumByteSize + remainder; + + // Bail to `minimumByteSize` in case of overflow. + if (byteSize < minimumByteSize) + return minimumByteSize; + } + } + + return Support::min<size_t>(byteSize, kMaxAllocSize); +} + // String - Clear & Reset // ====================== @@ -49,13 +91,13 @@ char* String::prepare(ModifyOp op, size_t size) noexcept { size_t curCapacity; if (isLargeOrExternal()) { - curData = this->_large.data; - curSize = this->_large.size; - curCapacity = this->_large.capacity; + curData = _large.data; + curSize = _large.size; + curCapacity = _large.capacity; } else { - curData = this->_small.data; - curSize = this->_small.type; + curData = _small.data; + curSize = _small.type; curCapacity = kSSOCapacity; } @@ -90,25 +132,20 @@ char* String::prepare(ModifyOp op, size_t size) noexcept { } else { // Prevent arithmetic overflow. - if (ASMJIT_UNLIKELY(size >= kMaxAllocSize - curSize)) + if (ASMJIT_UNLIKELY(size >= kMaxAllocSize - curSize - 1)) return nullptr; size_t newSize = size + curSize; size_t newSizePlusOne = newSize + 1; - if (newSizePlusOne > curCapacity) { - size_t newCapacity = Support::max<size_t>(curCapacity + 1, kMinAllocSize); - - if (newCapacity < newSizePlusOne && newCapacity < Globals::kGrowThreshold) - newCapacity = Support::alignUpPowerOf2(newCapacity); - - if (newCapacity < newSizePlusOne) - newCapacity = Support::alignUp(newSizePlusOne, Globals::kGrowThreshold); + if (newSize > curCapacity) { + size_t newCapacityPlusOne = String_growCapacity(size + 1u, newSizePlusOne); + ASMJIT_ASSERT(newCapacityPlusOne >= newSizePlusOne); - if (ASMJIT_UNLIKELY(newCapacity < newSizePlusOne)) + if (ASMJIT_UNLIKELY(newCapacityPlusOne < newSizePlusOne)) return nullptr; - char* newData = static_cast<char*>(::malloc(newCapacity)); + char* newData = static_cast<char*>(::malloc(newCapacityPlusOne)); if (ASMJIT_UNLIKELY(!newData)) return nullptr; @@ -119,7 +156,7 @@ char* String::prepare(ModifyOp op, size_t size) noexcept { _large.type = kTypeLarge; _large.size = newSize; - _large.capacity = newCapacity - 1; + _large.capacity = newCapacityPlusOne - 1; _large.data = newData; newData[newSize] = '\0'; @@ -463,7 +500,7 @@ Error String::truncate(size_t newSize) noexcept { return kErrorOk; } -bool String::eq(const char* other, size_t size) const noexcept { +bool String::equals(const char* other, size_t size) const noexcept { const char* aData = data(); const char* bData = other; @@ -488,71 +525,92 @@ bool String::eq(const char* other, size_t size) const noexcept { // ============== #if defined(ASMJIT_TEST) +static void test_string_grow() noexcept { + String s; + size_t c = s.capacity(); + + INFO("Testing string grow strategy (SSO capacity: %zu)", c); + for (size_t i = 0; i < 1000000; i++) { + s.append('x'); + if (s.capacity() != c) { + c = s.capacity(); + INFO(" String reallocated to new capacity: %zu", c); + } + } + + // We don't expect a 1 million character string to occupy 4MiB, for example. So verify that! + EXPECT_LT(c, size_t(4 * 1024 * 1024)); +} + UNIT(core_string) { String s; - EXPECT(s.isLargeOrExternal() == false); - EXPECT(s.isExternal() == false); - - EXPECT(s.assign('a') == kErrorOk); - EXPECT(s.size() == 1); - EXPECT(s.capacity() == String::kSSOCapacity); - EXPECT(s.data()[0] == 'a'); - EXPECT(s.data()[1] == '\0'); - EXPECT(s.eq("a") == true); - EXPECT(s.eq("a", 1) == true); - - EXPECT(s.assignChars('b', 4) == kErrorOk); - EXPECT(s.size() == 4); - EXPECT(s.capacity() == String::kSSOCapacity); - EXPECT(s.data()[0] == 'b'); - EXPECT(s.data()[1] == 'b'); - EXPECT(s.data()[2] == 'b'); - EXPECT(s.data()[3] == 'b'); - EXPECT(s.data()[4] == '\0'); - EXPECT(s.eq("bbbb") == true); - EXPECT(s.eq("bbbb", 4) == true); - - EXPECT(s.assign("abc") == kErrorOk); - EXPECT(s.size() == 3); - EXPECT(s.capacity() == String::kSSOCapacity); - EXPECT(s.data()[0] == 'a'); - EXPECT(s.data()[1] == 'b'); - EXPECT(s.data()[2] == 'c'); - EXPECT(s.data()[3] == '\0'); - EXPECT(s.eq("abc") == true); - EXPECT(s.eq("abc", 3) == true); + INFO("Testing string functionality"); + + EXPECT_FALSE(s.isLargeOrExternal()); + EXPECT_FALSE(s.isExternal()); + + EXPECT_EQ(s.assign('a'), kErrorOk); + EXPECT_EQ(s.size(), 1u); + EXPECT_EQ(s.capacity(), String::kSSOCapacity); + EXPECT_EQ(s.data()[0], 'a'); + EXPECT_EQ(s.data()[1], '\0'); + EXPECT_TRUE(s.equals("a")); + EXPECT_TRUE(s.equals("a", 1)); + + EXPECT_EQ(s.assignChars('b', 4), kErrorOk); + EXPECT_EQ(s.size(), 4u); + EXPECT_EQ(s.capacity(), String::kSSOCapacity); + EXPECT_EQ(s.data()[0], 'b'); + EXPECT_EQ(s.data()[1], 'b'); + EXPECT_EQ(s.data()[2], 'b'); + EXPECT_EQ(s.data()[3], 'b'); + EXPECT_EQ(s.data()[4], '\0'); + EXPECT_TRUE(s.equals("bbbb")); + EXPECT_TRUE(s.equals("bbbb", 4)); + + EXPECT_EQ(s.assign("abc"), kErrorOk); + EXPECT_EQ(s.size(), 3u); + EXPECT_EQ(s.capacity(), String::kSSOCapacity); + EXPECT_EQ(s.data()[0], 'a'); + EXPECT_EQ(s.data()[1], 'b'); + EXPECT_EQ(s.data()[2], 'c'); + EXPECT_EQ(s.data()[3], '\0'); + EXPECT_TRUE(s.equals("abc")); + EXPECT_TRUE(s.equals("abc", 3)); const char* large = "Large string that will not fit into SSO buffer"; - EXPECT(s.assign(large) == kErrorOk); - EXPECT(s.isLargeOrExternal() == true); - EXPECT(s.size() == strlen(large)); - EXPECT(s.capacity() > String::kSSOCapacity); - EXPECT(s.eq(large) == true); - EXPECT(s.eq(large, strlen(large)) == true); + EXPECT_EQ(s.assign(large), kErrorOk); + EXPECT_TRUE(s.isLargeOrExternal()); + EXPECT_EQ(s.size(), strlen(large)); + EXPECT_GT(s.capacity(), String::kSSOCapacity); + EXPECT_TRUE(s.equals(large)); + EXPECT_TRUE(s.equals(large, strlen(large))); const char* additional = " (additional content)"; - EXPECT(s.isLargeOrExternal() == true); - EXPECT(s.append(additional) == kErrorOk); - EXPECT(s.size() == strlen(large) + strlen(additional)); + EXPECT_TRUE(s.isLargeOrExternal()); + EXPECT_EQ(s.append(additional), kErrorOk); + EXPECT_EQ(s.size(), strlen(large) + strlen(additional)); - EXPECT(s.clear() == kErrorOk); - EXPECT(s.size() == 0); - EXPECT(s.empty() == true); - EXPECT(s.data()[0] == '\0'); - EXPECT(s.isLargeOrExternal() == true); // Clear should never release the memory. + EXPECT_EQ(s.clear(), kErrorOk); + EXPECT_EQ(s.size(), 0u); + EXPECT_TRUE(s.empty()); + EXPECT_EQ(s.data()[0], '\0'); + EXPECT_TRUE(s.isLargeOrExternal()); // Clear should never release the memory. - EXPECT(s.appendUInt(1234) == kErrorOk); - EXPECT(s.eq("1234") == true); + EXPECT_EQ(s.appendUInt(1234), kErrorOk); + EXPECT_TRUE(s.equals("1234")); - EXPECT(s.assignUInt(0xFFFF, 16, 0, StringFormatFlags::kAlternate) == kErrorOk); - EXPECT(s.eq("0xFFFF")); + EXPECT_EQ(s.assignUInt(0xFFFF, 16, 0, StringFormatFlags::kAlternate), kErrorOk); + EXPECT_TRUE(s.equals("0xFFFF")); StringTmp<64> sTmp; - EXPECT(sTmp.isLargeOrExternal()); - EXPECT(sTmp.isExternal()); - EXPECT(sTmp.appendChars(' ', 1000) == kErrorOk); - EXPECT(!sTmp.isExternal()); + EXPECT_TRUE(sTmp.isLargeOrExternal()); + EXPECT_TRUE(sTmp.isExternal()); + EXPECT_EQ(sTmp.appendChars(' ', 1000), kErrorOk); + EXPECT_FALSE(sTmp.isExternal()); + + test_string_grow(); } #endif diff --git a/3rdparty/asmjit/src/asmjit/core/string.h b/3rdparty/asmjit/src/asmjit/core/string.h index 2562e66194a..c4dee14b00e 100644 --- a/3rdparty/asmjit/src/asmjit/core/string.h +++ b/3rdparty/asmjit/src/asmjit/core/string.h @@ -53,9 +53,12 @@ union FixedString { //! \name Utilities //! \{ - inline bool eq(const char* other) const noexcept { - return strcmp(str, other) == 0; - } + inline bool equals(const char* other) const noexcept { return strcmp(str, other) == 0; } + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use FixedString::equals() instead") + inline bool eq(const char* other) const noexcept { return equals(other); } +#endif // !ASMJIT_NO_DEPRECATED //! \} }; @@ -131,16 +134,16 @@ public: //! \{ //! Creates a default-initialized string if zero length. - inline String() noexcept + ASMJIT_INLINE_NODEBUG String() noexcept : _small {} {} //! Creates a string that takes ownership of the content of the `other` string. - inline String(String&& other) noexcept { + ASMJIT_INLINE_NODEBUG String(String&& other) noexcept { _raw = other._raw; other._resetInternal(); } - inline ~String() noexcept { + ASMJIT_INLINE_NODEBUG ~String() noexcept { reset(); } @@ -158,37 +161,37 @@ public: return *this; } - inline bool operator==(const char* other) const noexcept { return eq(other); } - inline bool operator!=(const char* other) const noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const char* other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const char* other) const noexcept { return !equals(other); } - inline bool operator==(const String& other) const noexcept { return eq(other); } - inline bool operator!=(const String& other) const noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const String& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const String& other) const noexcept { return !equals(other); } //! \} //! \name Accessors //! \{ - inline bool isExternal() const noexcept { return _type == kTypeExternal; } - inline bool isLargeOrExternal() const noexcept { return _type >= kTypeLarge; } + ASMJIT_INLINE_NODEBUG bool isExternal() const noexcept { return _type == kTypeExternal; } + ASMJIT_INLINE_NODEBUG bool isLargeOrExternal() const noexcept { return _type >= kTypeLarge; } //! Tests whether the string is empty. - inline bool empty() const noexcept { return size() == 0; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return size() == 0; } //! Returns the size of the string. - inline size_t size() const noexcept { return isLargeOrExternal() ? size_t(_large.size) : size_t(_type); } + ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return isLargeOrExternal() ? size_t(_large.size) : size_t(_type); } //! Returns the capacity of the string. - inline size_t capacity() const noexcept { return isLargeOrExternal() ? _large.capacity : size_t(kSSOCapacity); } + ASMJIT_INLINE_NODEBUG size_t capacity() const noexcept { return isLargeOrExternal() ? _large.capacity : size_t(kSSOCapacity); } //! Returns the data of the string. - inline char* data() noexcept { return isLargeOrExternal() ? _large.data : _small.data; } + ASMJIT_INLINE_NODEBUG char* data() noexcept { return isLargeOrExternal() ? _large.data : _small.data; } //! \overload - inline const char* data() const noexcept { return isLargeOrExternal() ? _large.data : _small.data; } + ASMJIT_INLINE_NODEBUG const char* data() const noexcept { return isLargeOrExternal() ? _large.data : _small.data; } - inline char* start() noexcept { return data(); } - inline const char* start() const noexcept { return data(); } + ASMJIT_INLINE_NODEBUG char* start() noexcept { return data(); } + ASMJIT_INLINE_NODEBUG const char* start() const noexcept { return data(); } - inline char* end() noexcept { return data() + size(); } - inline const char* end() const noexcept { return data() + size(); } + ASMJIT_INLINE_NODEBUG char* end() noexcept { return data() + size(); } + ASMJIT_INLINE_NODEBUG const char* end() const noexcept { return data() + size(); } //! \} @@ -196,7 +199,7 @@ public: //! \{ //! Swaps the content of this string with `other`. - inline void swap(String& other) noexcept { + ASMJIT_INLINE_NODEBUG void swap(String& other) noexcept { std::swap(_raw, other._raw); } @@ -219,91 +222,91 @@ public: ASMJIT_API Error assign(const char* data, size_t size = SIZE_MAX) noexcept; //! Replaces the current of the string with `other` string. - inline Error assign(const String& other) noexcept { + ASMJIT_INLINE_NODEBUG Error assign(const String& other) noexcept { return assign(other.data(), other.size()); } //! Replaces the current of the string by a single `c` character. - inline Error assign(char c) noexcept { + ASMJIT_INLINE_NODEBUG Error assign(char c) noexcept { return _opChar(ModifyOp::kAssign, c); } //! Replaces the current of the string by a `c` character, repeated `n` times. - inline Error assignChars(char c, size_t n) noexcept { + ASMJIT_INLINE_NODEBUG Error assignChars(char c, size_t n) noexcept { return _opChars(ModifyOp::kAssign, c, n); } //! Replaces the current of the string by a formatted integer `i` (signed). - inline Error assignInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { + ASMJIT_INLINE_NODEBUG Error assignInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { return _opNumber(ModifyOp::kAssign, uint64_t(i), base, width, flags | StringFormatFlags::kSigned); } //! Replaces the current of the string by a formatted integer `i` (unsigned). - inline Error assignUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { + ASMJIT_INLINE_NODEBUG Error assignUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { return _opNumber(ModifyOp::kAssign, i, base, width, flags); } //! Replaces the current of the string by the given `data` converted to a HEX string. - inline Error assignHex(const void* data, size_t size, char separator = '\0') noexcept { + ASMJIT_INLINE_NODEBUG Error assignHex(const void* data, size_t size, char separator = '\0') noexcept { return _opHex(ModifyOp::kAssign, data, size, separator); } //! Replaces the current of the string by a formatted string `fmt`. template<typename... Args> - inline Error assignFormat(const char* fmt, Args&&... args) noexcept { + ASMJIT_INLINE_NODEBUG Error assignFormat(const char* fmt, Args&&... args) noexcept { return _opFormat(ModifyOp::kAssign, fmt, std::forward<Args>(args)...); } //! Replaces the current of the string by a formatted string `fmt` (va_list version). - inline Error assignVFormat(const char* fmt, va_list ap) noexcept { + ASMJIT_INLINE_NODEBUG Error assignVFormat(const char* fmt, va_list ap) noexcept { return _opVFormat(ModifyOp::kAssign, fmt, ap); } //! Appends `str` having the given size `size` to the string. //! //! Null terminated strings can set `size` to `SIZE_MAX`. - inline Error append(const char* str, size_t size = SIZE_MAX) noexcept { + ASMJIT_INLINE_NODEBUG Error append(const char* str, size_t size = SIZE_MAX) noexcept { return _opString(ModifyOp::kAppend, str, size); } //! Appends `other` string to this string. - inline Error append(const String& other) noexcept { + ASMJIT_INLINE_NODEBUG Error append(const String& other) noexcept { return append(other.data(), other.size()); } //! Appends a single `c` character. - inline Error append(char c) noexcept { + ASMJIT_INLINE_NODEBUG Error append(char c) noexcept { return _opChar(ModifyOp::kAppend, c); } //! Appends `c` character repeated `n` times. - inline Error appendChars(char c, size_t n) noexcept { + ASMJIT_INLINE_NODEBUG Error appendChars(char c, size_t n) noexcept { return _opChars(ModifyOp::kAppend, c, n); } //! Appends a formatted integer `i` (signed). - inline Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { + ASMJIT_INLINE_NODEBUG Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { return _opNumber(ModifyOp::kAppend, uint64_t(i), base, width, flags | StringFormatFlags::kSigned); } //! Appends a formatted integer `i` (unsigned). - inline Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { + ASMJIT_INLINE_NODEBUG Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { return _opNumber(ModifyOp::kAppend, i, base, width, flags); } //! Appends the given `data` converted to a HEX string. - inline Error appendHex(const void* data, size_t size, char separator = '\0') noexcept { + ASMJIT_INLINE_NODEBUG Error appendHex(const void* data, size_t size, char separator = '\0') noexcept { return _opHex(ModifyOp::kAppend, data, size, separator); } //! Appends a formatted string `fmt` with `args`. template<typename... Args> - inline Error appendFormat(const char* fmt, Args&&... args) noexcept { + ASMJIT_INLINE_NODEBUG Error appendFormat(const char* fmt, Args&&... args) noexcept { return _opFormat(ModifyOp::kAppend, fmt, std::forward<Args>(args)...); } //! Appends a formatted string `fmt` (va_list version). - inline Error appendVFormat(const char* fmt, va_list ap) noexcept { + ASMJIT_INLINE_NODEBUG Error appendVFormat(const char* fmt, va_list ap) noexcept { return _opVFormat(ModifyOp::kAppend, fmt, ap); } @@ -312,8 +315,16 @@ public: //! Truncate the string length into `newSize`. ASMJIT_API Error truncate(size_t newSize) noexcept; - ASMJIT_API bool eq(const char* other, size_t size = SIZE_MAX) const noexcept; - inline bool eq(const String& other) const noexcept { return eq(other.data(), other.size()); } + ASMJIT_API bool equals(const char* other, size_t size = SIZE_MAX) const noexcept; + ASMJIT_INLINE_NODEBUG bool equals(const String& other) const noexcept { return equals(other.data(), other.size()); } + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use String::equals() instead") + ASMJIT_INLINE_NODEBUG bool eq(const char* other, size_t size = SIZE_MAX) const noexcept { return equals(other, size); } + + ASMJIT_DEPRECATED("Use String::equals() instead") + ASMJIT_INLINE_NODEBUG bool eq(const String& other) const noexcept { return equals(other.data(), other.size()); } +#endif // !ASMJIT_NO_DEPRECATED //! \} @@ -351,7 +362,7 @@ public: //! \name Construction & Destruction //! \{ - inline StringTmp() noexcept { + ASMJIT_INLINE_NODEBUG StringTmp() noexcept { _resetToTemporary(); } diff --git a/3rdparty/asmjit/src/asmjit/core/support.cpp b/3rdparty/asmjit/src/asmjit/core/support.cpp index 245398fe732..bebabbcc2de 100644 --- a/3rdparty/asmjit/src/asmjit/core/support.cpp +++ b/3rdparty/asmjit/src/asmjit/core/support.cpp @@ -15,74 +15,76 @@ ASMJIT_BEGIN_NAMESPACE template<typename T> static void testArrays(const T* a, const T* b, size_t size) noexcept { for (size_t i = 0; i < size; i++) - EXPECT(a[i] == b[i], "Mismatch at %u", unsigned(i)); + EXPECT_EQ(a[i], b[i]) + .message("Mismatch at %u", unsigned(i)); } static void testAlignment() noexcept { INFO("Support::isAligned()"); - EXPECT(Support::isAligned<size_t>(0xFFFF, 4) == false); - EXPECT(Support::isAligned<size_t>(0xFFF4, 4) == true); - EXPECT(Support::isAligned<size_t>(0xFFF8, 8) == true); - EXPECT(Support::isAligned<size_t>(0xFFF0, 16) == true); + EXPECT_FALSE(Support::isAligned<size_t>(0xFFFF, 4u)); + EXPECT_TRUE(Support::isAligned<size_t>(0xFFF4, 4u)); + EXPECT_TRUE(Support::isAligned<size_t>(0xFFF8, 8u)); + EXPECT_TRUE(Support::isAligned<size_t>(0xFFF0, 16u)); INFO("Support::alignUp()"); - EXPECT(Support::alignUp<size_t>(0xFFFF, 4) == 0x10000); - EXPECT(Support::alignUp<size_t>(0xFFF4, 4) == 0x0FFF4); - EXPECT(Support::alignUp<size_t>(0xFFF8, 8) == 0x0FFF8); - EXPECT(Support::alignUp<size_t>(0xFFF0, 16) == 0x0FFF0); - EXPECT(Support::alignUp<size_t>(0xFFF0, 32) == 0x10000); + EXPECT_EQ(Support::alignUp<size_t>(0xFFFF, 4), 0x10000u); + EXPECT_EQ(Support::alignUp<size_t>(0xFFF4, 4), 0x0FFF4u); + EXPECT_EQ(Support::alignUp<size_t>(0xFFF8, 8), 0x0FFF8u); + EXPECT_EQ(Support::alignUp<size_t>(0xFFF0, 16), 0x0FFF0u); + EXPECT_EQ(Support::alignUp<size_t>(0xFFF0, 32), 0x10000u); INFO("Support::alignUpDiff()"); - EXPECT(Support::alignUpDiff<size_t>(0xFFFF, 4) == 1); - EXPECT(Support::alignUpDiff<size_t>(0xFFF4, 4) == 0); - EXPECT(Support::alignUpDiff<size_t>(0xFFF8, 8) == 0); - EXPECT(Support::alignUpDiff<size_t>(0xFFF0, 16) == 0); - EXPECT(Support::alignUpDiff<size_t>(0xFFF0, 32) == 16); + EXPECT_EQ(Support::alignUpDiff<size_t>(0xFFFF, 4), 1u); + EXPECT_EQ(Support::alignUpDiff<size_t>(0xFFF4, 4), 0u); + EXPECT_EQ(Support::alignUpDiff<size_t>(0xFFF8, 8), 0u); + EXPECT_EQ(Support::alignUpDiff<size_t>(0xFFF0, 16), 0u); + EXPECT_EQ(Support::alignUpDiff<size_t>(0xFFF0, 32), 16u); INFO("Support::alignUpPowerOf2()"); - EXPECT(Support::alignUpPowerOf2<size_t>(0x0000) == 0x00000); - EXPECT(Support::alignUpPowerOf2<size_t>(0xFFFF) == 0x10000); - EXPECT(Support::alignUpPowerOf2<size_t>(0xF123) == 0x10000); - EXPECT(Support::alignUpPowerOf2<size_t>(0x0F00) == 0x01000); - EXPECT(Support::alignUpPowerOf2<size_t>(0x0100) == 0x00100); - EXPECT(Support::alignUpPowerOf2<size_t>(0x1001) == 0x02000); + EXPECT_EQ(Support::alignUpPowerOf2<size_t>(0x0000), 0x00000u); + EXPECT_EQ(Support::alignUpPowerOf2<size_t>(0xFFFF), 0x10000u); + EXPECT_EQ(Support::alignUpPowerOf2<size_t>(0xF123), 0x10000u); + EXPECT_EQ(Support::alignUpPowerOf2<size_t>(0x0F00), 0x01000u); + EXPECT_EQ(Support::alignUpPowerOf2<size_t>(0x0100), 0x00100u); + EXPECT_EQ(Support::alignUpPowerOf2<size_t>(0x1001), 0x02000u); } static void testBitUtils() noexcept { uint32_t i; INFO("Support::shl() / shr()"); - EXPECT(Support::shl(int32_t(0x00001111), 16) == int32_t(0x11110000u)); - EXPECT(Support::shl(uint32_t(0x00001111), 16) == uint32_t(0x11110000u)); - EXPECT(Support::shr(int32_t(0x11110000u), 16) == int32_t(0x00001111u)); - EXPECT(Support::shr(uint32_t(0x11110000u), 16) == uint32_t(0x00001111u)); - EXPECT(Support::sar(int32_t(0xFFFF0000u), 16) == int32_t(0xFFFFFFFFu)); - EXPECT(Support::sar(uint32_t(0xFFFF0000u), 16) == uint32_t(0xFFFFFFFFu)); + EXPECT_EQ(Support::shl(int32_t(0x00001111), 16), int32_t(0x11110000u)); + EXPECT_EQ(Support::shl(uint32_t(0x00001111), 16), uint32_t(0x11110000u)); + EXPECT_EQ(Support::shr(int32_t(0x11110000u), 16), int32_t(0x00001111u)); + EXPECT_EQ(Support::shr(uint32_t(0x11110000u), 16), uint32_t(0x00001111u)); + EXPECT_EQ(Support::sar(int32_t(0xFFFF0000u), 16), int32_t(0xFFFFFFFFu)); + EXPECT_EQ(Support::sar(uint32_t(0xFFFF0000u), 16), uint32_t(0xFFFFFFFFu)); INFO("Support::blsi()"); - for (i = 0; i < 32; i++) EXPECT(Support::blsi(uint32_t(1) << i) == uint32_t(1) << i); - for (i = 0; i < 31; i++) EXPECT(Support::blsi(uint32_t(3) << i) == uint32_t(1) << i); - for (i = 0; i < 64; i++) EXPECT(Support::blsi(uint64_t(1) << i) == uint64_t(1) << i); - for (i = 0; i < 63; i++) EXPECT(Support::blsi(uint64_t(3) << i) == uint64_t(1) << i); + for (i = 0; i < 32; i++) EXPECT_EQ(Support::blsi(uint32_t(1) << i), uint32_t(1) << i); + for (i = 0; i < 31; i++) EXPECT_EQ(Support::blsi(uint32_t(3) << i), uint32_t(1) << i); + for (i = 0; i < 64; i++) EXPECT_EQ(Support::blsi(uint64_t(1) << i), uint64_t(1) << i); + for (i = 0; i < 63; i++) EXPECT_EQ(Support::blsi(uint64_t(3) << i), uint64_t(1) << i); INFO("Support::ctz()"); - for (i = 0; i < 32; i++) EXPECT(Support::Internal::clzFallback(uint32_t(1) << i) == 31 - i); - for (i = 0; i < 64; i++) EXPECT(Support::Internal::clzFallback(uint64_t(1) << i) == 63 - i); - for (i = 0; i < 32; i++) EXPECT(Support::Internal::ctzFallback(uint32_t(1) << i) == i); - for (i = 0; i < 64; i++) EXPECT(Support::Internal::ctzFallback(uint64_t(1) << i) == i); - for (i = 0; i < 32; i++) EXPECT(Support::clz(uint32_t(1) << i) == 31 - i); - for (i = 0; i < 64; i++) EXPECT(Support::clz(uint64_t(1) << i) == 63 - i); - for (i = 0; i < 32; i++) EXPECT(Support::ctz(uint32_t(1) << i) == i); - for (i = 0; i < 64; i++) EXPECT(Support::ctz(uint64_t(1) << i) == i); + for (i = 0; i < 32; i++) EXPECT_EQ(Support::Internal::clzFallback(uint32_t(1) << i), 31 - i); + for (i = 0; i < 64; i++) EXPECT_EQ(Support::Internal::clzFallback(uint64_t(1) << i), 63 - i); + for (i = 0; i < 32; i++) EXPECT_EQ(Support::Internal::ctzFallback(uint32_t(1) << i), i); + for (i = 0; i < 64; i++) EXPECT_EQ(Support::Internal::ctzFallback(uint64_t(1) << i), i); + for (i = 0; i < 32; i++) EXPECT_EQ(Support::clz(uint32_t(1) << i), 31 - i); + for (i = 0; i < 64; i++) EXPECT_EQ(Support::clz(uint64_t(1) << i), 63 - i); + for (i = 0; i < 32; i++) EXPECT_EQ(Support::ctz(uint32_t(1) << i), i); + for (i = 0; i < 64; i++) EXPECT_EQ(Support::ctz(uint64_t(1) << i), i); INFO("Support::bitMask()"); - EXPECT(Support::bitMask(0, 1, 7) == 0x83u); + EXPECT_EQ(Support::bitMask(0, 1, 7), 0x83u); for (i = 0; i < 32; i++) - EXPECT(Support::bitMask(i) == (1u << i)); + EXPECT_EQ(Support::bitMask(i), (1u << i)); INFO("Support::bitTest()"); for (i = 0; i < 32; i++) { - EXPECT(Support::bitTest((1 << i), i) == true, "Support::bitTest(%X, %u) should return true", (1 << i), i); + EXPECT_TRUE(Support::bitTest((1 << i), i)) + .message("Support::bitTest(%X, %u) should return true", (1 << i), i); } INFO("Support::lsbMask<uint32_t>()"); @@ -90,7 +92,7 @@ static void testBitUtils() noexcept { uint32_t expectedBits = 0; for (uint32_t b = 0; b < i; b++) expectedBits |= uint32_t(1) << b; - EXPECT(Support::lsbMask<uint32_t>(i) == expectedBits); + EXPECT_EQ(Support::lsbMask<uint32_t>(i), expectedBits); } INFO("Support::lsbMask<uint64_t>()"); @@ -98,31 +100,31 @@ static void testBitUtils() noexcept { uint64_t expectedBits = 0; for (uint32_t b = 0; b < i; b++) expectedBits |= uint64_t(1) << b; - EXPECT(Support::lsbMask<uint64_t>(i) == expectedBits); + EXPECT_EQ(Support::lsbMask<uint64_t>(i), expectedBits); } INFO("Support::popcnt()"); - for (i = 0; i < 32; i++) EXPECT(Support::popcnt((uint32_t(1) << i)) == 1); - for (i = 0; i < 64; i++) EXPECT(Support::popcnt((uint64_t(1) << i)) == 1); - EXPECT(Support::popcnt(0x000000F0) == 4); - EXPECT(Support::popcnt(0x10101010) == 4); - EXPECT(Support::popcnt(0xFF000000) == 8); - EXPECT(Support::popcnt(0xFFFFFFF7) == 31); - EXPECT(Support::popcnt(0x7FFFFFFF) == 31); + for (i = 0; i < 32; i++) EXPECT_EQ(Support::popcnt((uint32_t(1) << i)), 1u); + for (i = 0; i < 64; i++) EXPECT_EQ(Support::popcnt((uint64_t(1) << i)), 1u); + EXPECT_EQ(Support::popcnt(0x000000F0), 4u); + EXPECT_EQ(Support::popcnt(0x10101010), 4u); + EXPECT_EQ(Support::popcnt(0xFF000000), 8u); + EXPECT_EQ(Support::popcnt(0xFFFFFFF7), 31u); + EXPECT_EQ(Support::popcnt(0x7FFFFFFF), 31u); INFO("Support::isPowerOf2()"); for (i = 0; i < 64; i++) { - EXPECT(Support::isPowerOf2(uint64_t(1) << i) == true); - EXPECT(Support::isPowerOf2((uint64_t(1) << i) ^ 0x001101) == false); + EXPECT_TRUE(Support::isPowerOf2(uint64_t(1) << i)); + EXPECT_FALSE(Support::isPowerOf2((uint64_t(1) << i) ^ 0x001101)); } } static void testIntUtils() noexcept { INFO("Support::byteswap()"); - EXPECT(Support::byteswap16(int32_t(0x0102)) == int32_t(0x0201)); - EXPECT(Support::byteswap32(int32_t(0x01020304)) == int32_t(0x04030201)); - EXPECT(Support::byteswap32(uint32_t(0x01020304)) == uint32_t(0x04030201)); - EXPECT(Support::byteswap64(uint64_t(0x0102030405060708)) == uint64_t(0x0807060504030201)); + EXPECT_EQ(Support::byteswap16(0x0102), 0x0201u); + EXPECT_EQ(Support::byteswap32(0x01020304), 0x04030201u); + EXPECT_EQ(Support::byteswap32(0x01020304), 0x04030201u); + EXPECT_EQ(Support::byteswap64(uint64_t(0x0102030405060708)), uint64_t(0x0807060504030201)); INFO("Support::bytepack()"); union BytePackData { @@ -131,60 +133,60 @@ static void testIntUtils() noexcept { } bpdata; bpdata.u32 = Support::bytepack32_4x8(0x00, 0x11, 0x22, 0x33); - EXPECT(bpdata.bytes[0] == 0x00); - EXPECT(bpdata.bytes[1] == 0x11); - EXPECT(bpdata.bytes[2] == 0x22); - EXPECT(bpdata.bytes[3] == 0x33); + EXPECT_EQ(bpdata.bytes[0], 0x00); + EXPECT_EQ(bpdata.bytes[1], 0x11); + EXPECT_EQ(bpdata.bytes[2], 0x22); + EXPECT_EQ(bpdata.bytes[3], 0x33); INFO("Support::isBetween()"); - EXPECT(Support::isBetween<int>(10 , 10, 20) == true); - EXPECT(Support::isBetween<int>(11 , 10, 20) == true); - EXPECT(Support::isBetween<int>(20 , 10, 20) == true); - EXPECT(Support::isBetween<int>(9 , 10, 20) == false); - EXPECT(Support::isBetween<int>(21 , 10, 20) == false); - EXPECT(Support::isBetween<int>(101, 10, 20) == false); + EXPECT_TRUE(Support::isBetween<int>(10 , 10, 20)); + EXPECT_TRUE(Support::isBetween<int>(11 , 10, 20)); + EXPECT_TRUE(Support::isBetween<int>(20 , 10, 20)); + EXPECT_FALSE(Support::isBetween<int>(9 , 10, 20)); + EXPECT_FALSE(Support::isBetween<int>(21 , 10, 20)); + EXPECT_FALSE(Support::isBetween<int>(101, 10, 20)); INFO("Support::isInt8()"); - EXPECT(Support::isInt8(-128) == true); - EXPECT(Support::isInt8( 127) == true); - EXPECT(Support::isInt8(-129) == false); - EXPECT(Support::isInt8( 128) == false); + EXPECT_TRUE(Support::isInt8(-128)); + EXPECT_TRUE(Support::isInt8( 127)); + EXPECT_FALSE(Support::isInt8(-129)); + EXPECT_FALSE(Support::isInt8( 128)); INFO("Support::isInt16()"); - EXPECT(Support::isInt16(-32768) == true); - EXPECT(Support::isInt16( 32767) == true); - EXPECT(Support::isInt16(-32769) == false); - EXPECT(Support::isInt16( 32768) == false); + EXPECT_TRUE(Support::isInt16(-32768)); + EXPECT_TRUE(Support::isInt16( 32767)); + EXPECT_FALSE(Support::isInt16(-32769)); + EXPECT_FALSE(Support::isInt16( 32768)); INFO("Support::isInt32()"); - EXPECT(Support::isInt32( 2147483647 ) == true); - EXPECT(Support::isInt32(-2147483647 - 1) == true); - EXPECT(Support::isInt32(uint64_t(2147483648u)) == false); - EXPECT(Support::isInt32(uint64_t(0xFFFFFFFFu)) == false); - EXPECT(Support::isInt32(uint64_t(0xFFFFFFFFu) + 1) == false); + EXPECT_TRUE(Support::isInt32( 2147483647 )); + EXPECT_TRUE(Support::isInt32(-2147483647 - 1)); + EXPECT_FALSE(Support::isInt32(uint64_t(2147483648u))); + EXPECT_FALSE(Support::isInt32(uint64_t(0xFFFFFFFFu))); + EXPECT_FALSE(Support::isInt32(uint64_t(0xFFFFFFFFu) + 1)); INFO("Support::isUInt8()"); - EXPECT(Support::isUInt8(0) == true); - EXPECT(Support::isUInt8(255) == true); - EXPECT(Support::isUInt8(256) == false); - EXPECT(Support::isUInt8(-1) == false); + EXPECT_TRUE(Support::isUInt8(0) ); + EXPECT_TRUE(Support::isUInt8(255)); + EXPECT_FALSE(Support::isUInt8(256)); + EXPECT_FALSE(Support::isUInt8(-1) ); INFO("Support::isUInt12()"); - EXPECT(Support::isUInt12(0) == true); - EXPECT(Support::isUInt12(4095) == true); - EXPECT(Support::isUInt12(4096) == false); - EXPECT(Support::isUInt12(-1) == false); + EXPECT_TRUE(Support::isUInt12(0) ); + EXPECT_TRUE(Support::isUInt12(4095)); + EXPECT_FALSE(Support::isUInt12(4096)); + EXPECT_FALSE(Support::isUInt12(-1) ); INFO("Support::isUInt16()"); - EXPECT(Support::isUInt16(0) == true); - EXPECT(Support::isUInt16(65535) == true); - EXPECT(Support::isUInt16(65536) == false); - EXPECT(Support::isUInt16(-1) == false); + EXPECT_TRUE(Support::isUInt16(0) ); + EXPECT_TRUE(Support::isUInt16(65535)); + EXPECT_FALSE(Support::isUInt16(65536)); + EXPECT_FALSE(Support::isUInt16(-1) ); INFO("Support::isUInt32()"); - EXPECT(Support::isUInt32(uint64_t(0xFFFFFFFF)) == true); - EXPECT(Support::isUInt32(uint64_t(0xFFFFFFFF) + 1) == false); - EXPECT(Support::isUInt32(-1) == false); + EXPECT_TRUE(Support::isUInt32(uint64_t(0xFFFFFFFF))); + EXPECT_FALSE(Support::isUInt32(uint64_t(0xFFFFFFFF) + 1)); + EXPECT_FALSE(Support::isUInt32(-1)); } static void testReadWrite() noexcept { @@ -194,17 +196,17 @@ static void testReadWrite() noexcept { Support::writeU16uBE(arr + 1, 0x0102u); Support::writeU16uBE(arr + 3, 0x0304u); - EXPECT(Support::readU32uBE(arr + 1) == 0x01020304u); - EXPECT(Support::readU32uLE(arr + 1) == 0x04030201u); - EXPECT(Support::readU32uBE(arr + 2) == 0x02030400u); - EXPECT(Support::readU32uLE(arr + 2) == 0x00040302u); + EXPECT_EQ(Support::readU32uBE(arr + 1), 0x01020304u); + EXPECT_EQ(Support::readU32uLE(arr + 1), 0x04030201u); + EXPECT_EQ(Support::readU32uBE(arr + 2), 0x02030400u); + EXPECT_EQ(Support::readU32uLE(arr + 2), 0x00040302u); Support::writeU32uLE(arr + 5, 0x05060708u); - EXPECT(Support::readU64uBE(arr + 1) == 0x0102030408070605u); - EXPECT(Support::readU64uLE(arr + 1) == 0x0506070804030201u); + EXPECT_EQ(Support::readU64uBE(arr + 1), 0x0102030408070605u); + EXPECT_EQ(Support::readU64uLE(arr + 1), 0x0506070804030201u); Support::writeU64uLE(arr + 7, 0x1122334455667788u); - EXPECT(Support::readU32uBE(arr + 8) == 0x77665544u); + EXPECT_EQ(Support::readU32uBE(arr + 8), 0x77665544u); } static void testBitVector() noexcept { @@ -212,132 +214,132 @@ static void testBitVector() noexcept { { uint32_t vec[3] = { 0 }; Support::bitVectorFill(vec, 1, 64); - EXPECT(vec[0] == 0xFFFFFFFEu); - EXPECT(vec[1] == 0xFFFFFFFFu); - EXPECT(vec[2] == 0x00000001u); + EXPECT_EQ(vec[0], 0xFFFFFFFEu); + EXPECT_EQ(vec[1], 0xFFFFFFFFu); + EXPECT_EQ(vec[2], 0x00000001u); Support::bitVectorClear(vec, 1, 1); - EXPECT(vec[0] == 0xFFFFFFFCu); - EXPECT(vec[1] == 0xFFFFFFFFu); - EXPECT(vec[2] == 0x00000001u); + EXPECT_EQ(vec[0], 0xFFFFFFFCu); + EXPECT_EQ(vec[1], 0xFFFFFFFFu); + EXPECT_EQ(vec[2], 0x00000001u); Support::bitVectorFill(vec, 0, 32); - EXPECT(vec[0] == 0xFFFFFFFFu); - EXPECT(vec[1] == 0xFFFFFFFFu); - EXPECT(vec[2] == 0x00000001u); + EXPECT_EQ(vec[0], 0xFFFFFFFFu); + EXPECT_EQ(vec[1], 0xFFFFFFFFu); + EXPECT_EQ(vec[2], 0x00000001u); Support::bitVectorClear(vec, 0, 32); - EXPECT(vec[0] == 0x00000000u); - EXPECT(vec[1] == 0xFFFFFFFFu); - EXPECT(vec[2] == 0x00000001u); + EXPECT_EQ(vec[0], 0x00000000u); + EXPECT_EQ(vec[1], 0xFFFFFFFFu); + EXPECT_EQ(vec[2], 0x00000001u); Support::bitVectorFill(vec, 1, 30); - EXPECT(vec[0] == 0x7FFFFFFEu); - EXPECT(vec[1] == 0xFFFFFFFFu); - EXPECT(vec[2] == 0x00000001u); + EXPECT_EQ(vec[0], 0x7FFFFFFEu); + EXPECT_EQ(vec[1], 0xFFFFFFFFu); + EXPECT_EQ(vec[2], 0x00000001u); Support::bitVectorClear(vec, 1, 95); - EXPECT(vec[0] == 0x00000000u); - EXPECT(vec[1] == 0x00000000u); - EXPECT(vec[2] == 0x00000000u); + EXPECT_EQ(vec[0], 0x00000000u); + EXPECT_EQ(vec[1], 0x00000000u); + EXPECT_EQ(vec[2], 0x00000000u); Support::bitVectorFill(vec, 32, 64); - EXPECT(vec[0] == 0x00000000u); - EXPECT(vec[1] == 0xFFFFFFFFu); - EXPECT(vec[2] == 0xFFFFFFFFu); + EXPECT_EQ(vec[0], 0x00000000u); + EXPECT_EQ(vec[1], 0xFFFFFFFFu); + EXPECT_EQ(vec[2], 0xFFFFFFFFu); Support::bitVectorSetBit(vec, 1, true); - EXPECT(vec[0] == 0x00000002u); - EXPECT(vec[1] == 0xFFFFFFFFu); - EXPECT(vec[2] == 0xFFFFFFFFu); + EXPECT_EQ(vec[0], 0x00000002u); + EXPECT_EQ(vec[1], 0xFFFFFFFFu); + EXPECT_EQ(vec[2], 0xFFFFFFFFu); Support::bitVectorSetBit(vec, 95, false); - EXPECT(vec[0] == 0x00000002u); - EXPECT(vec[1] == 0xFFFFFFFFu); - EXPECT(vec[2] == 0x7FFFFFFFu); + EXPECT_EQ(vec[0], 0x00000002u); + EXPECT_EQ(vec[1], 0xFFFFFFFFu); + EXPECT_EQ(vec[2], 0x7FFFFFFFu); Support::bitVectorClear(vec, 33, 32); - EXPECT(vec[0] == 0x00000002u); - EXPECT(vec[1] == 0x00000001u); - EXPECT(vec[2] == 0x7FFFFFFEu); + EXPECT_EQ(vec[0], 0x00000002u); + EXPECT_EQ(vec[1], 0x00000001u); + EXPECT_EQ(vec[2], 0x7FFFFFFEu); } INFO("Support::bitVectorIndexOf"); { uint32_t vec1[1] = { 0x80000000 }; - EXPECT(Support::bitVectorIndexOf(vec1, 0, true) == 31); - EXPECT(Support::bitVectorIndexOf(vec1, 1, true) == 31); - EXPECT(Support::bitVectorIndexOf(vec1, 31, true) == 31); + EXPECT_EQ(Support::bitVectorIndexOf(vec1, 0, true), 31u); + EXPECT_EQ(Support::bitVectorIndexOf(vec1, 1, true), 31u); + EXPECT_EQ(Support::bitVectorIndexOf(vec1, 31, true), 31u); uint32_t vec2[2] = { 0x00000000, 0x80000000 }; - EXPECT(Support::bitVectorIndexOf(vec2, 0, true) == 63); - EXPECT(Support::bitVectorIndexOf(vec2, 1, true) == 63); - EXPECT(Support::bitVectorIndexOf(vec2, 31, true) == 63); - EXPECT(Support::bitVectorIndexOf(vec2, 32, true) == 63); - EXPECT(Support::bitVectorIndexOf(vec2, 33, true) == 63); - EXPECT(Support::bitVectorIndexOf(vec2, 63, true) == 63); + EXPECT_EQ(Support::bitVectorIndexOf(vec2, 0, true), 63u); + EXPECT_EQ(Support::bitVectorIndexOf(vec2, 1, true), 63u); + EXPECT_EQ(Support::bitVectorIndexOf(vec2, 31, true), 63u); + EXPECT_EQ(Support::bitVectorIndexOf(vec2, 32, true), 63u); + EXPECT_EQ(Support::bitVectorIndexOf(vec2, 33, true), 63u); + EXPECT_EQ(Support::bitVectorIndexOf(vec2, 63, true), 63u); uint32_t vec3[3] = { 0x00000001, 0x00000000, 0x80000000 }; - EXPECT(Support::bitVectorIndexOf(vec3, 0, true) == 0); - EXPECT(Support::bitVectorIndexOf(vec3, 1, true) == 95); - EXPECT(Support::bitVectorIndexOf(vec3, 2, true) == 95); - EXPECT(Support::bitVectorIndexOf(vec3, 31, true) == 95); - EXPECT(Support::bitVectorIndexOf(vec3, 32, true) == 95); - EXPECT(Support::bitVectorIndexOf(vec3, 63, true) == 95); - EXPECT(Support::bitVectorIndexOf(vec3, 64, true) == 95); - EXPECT(Support::bitVectorIndexOf(vec3, 95, true) == 95); + EXPECT_EQ(Support::bitVectorIndexOf(vec3, 0, true), 0u); + EXPECT_EQ(Support::bitVectorIndexOf(vec3, 1, true), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec3, 2, true), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec3, 31, true), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec3, 32, true), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec3, 63, true), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec3, 64, true), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec3, 95, true), 95u); uint32_t vec4[3] = { ~vec3[0], ~vec3[1], ~vec3[2] }; - EXPECT(Support::bitVectorIndexOf(vec4, 0, false) == 0); - EXPECT(Support::bitVectorIndexOf(vec4, 1, false) == 95); - EXPECT(Support::bitVectorIndexOf(vec4, 2, false) == 95); - EXPECT(Support::bitVectorIndexOf(vec4, 31, false) == 95); - EXPECT(Support::bitVectorIndexOf(vec4, 32, false) == 95); - EXPECT(Support::bitVectorIndexOf(vec4, 63, false) == 95); - EXPECT(Support::bitVectorIndexOf(vec4, 64, false) == 95); - EXPECT(Support::bitVectorIndexOf(vec4, 95, false) == 95); + EXPECT_EQ(Support::bitVectorIndexOf(vec4, 0, false), 0u); + EXPECT_EQ(Support::bitVectorIndexOf(vec4, 1, false), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec4, 2, false), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec4, 31, false), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec4, 32, false), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec4, 63, false), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec4, 64, false), 95u); + EXPECT_EQ(Support::bitVectorIndexOf(vec4, 95, false), 95u); } INFO("Support::BitWordIterator<uint32_t>"); { Support::BitWordIterator<uint32_t> it(0x80000F01u); - EXPECT(it.hasNext()); - EXPECT(it.next() == 0); - EXPECT(it.hasNext()); - EXPECT(it.next() == 8); - EXPECT(it.hasNext()); - EXPECT(it.next() == 9); - EXPECT(it.hasNext()); - EXPECT(it.next() == 10); - EXPECT(it.hasNext()); - EXPECT(it.next() == 11); - EXPECT(it.hasNext()); - EXPECT(it.next() == 31); - EXPECT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 0u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 8u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 9u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 10u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 11u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 31u); + EXPECT_FALSE(it.hasNext()); // No bits set. it.init(0x00000000u); - ASMJIT_ASSERT(!it.hasNext()); + EXPECT_FALSE(it.hasNext()); // Only first bit set. it.init(0x00000001u); - EXPECT(it.hasNext()); - EXPECT(it.next() == 0); - ASMJIT_ASSERT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 0u); + EXPECT_FALSE(it.hasNext()); // Only last bit set (special case). it.init(0x80000000u); - ASMJIT_ASSERT(it.hasNext()); - ASMJIT_ASSERT(it.next() == 31); - ASMJIT_ASSERT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 31u); + EXPECT_FALSE(it.hasNext()); } INFO("Support::BitWordIterator<uint64_t>"); { Support::BitWordIterator<uint64_t> it(uint64_t(1) << 63); - ASMJIT_ASSERT(it.hasNext()); - ASMJIT_ASSERT(it.next() == 63); - ASMJIT_ASSERT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 63u); + EXPECT_FALSE(it.hasNext()); } INFO("Support::BitVectorIterator<uint32_t>"); @@ -346,63 +348,63 @@ static void testBitVector() noexcept { static const uint32_t bitsNone[] = { 0xFFFFFFFFu }; Support::BitVectorIterator<uint32_t> it(bitsNone, 0); - EXPECT(!it.hasNext()); + EXPECT_FALSE(it.hasNext()); it.init(bitsNone, 0, 1); - EXPECT(!it.hasNext()); + EXPECT_FALSE(it.hasNext()); it.init(bitsNone, 0, 128); - EXPECT(!it.hasNext()); + EXPECT_FALSE(it.hasNext()); static const uint32_t bits1[] = { 0x80000008u, 0x80000001u, 0x00000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x00003000u }; it.init(bits1, ASMJIT_ARRAY_SIZE(bits1)); - EXPECT(it.hasNext()); - EXPECT(it.next() == 3); - EXPECT(it.hasNext()); - EXPECT(it.next() == 31); - EXPECT(it.hasNext()); - EXPECT(it.next() == 32); - EXPECT(it.hasNext()); - EXPECT(it.next() == 63); - EXPECT(it.hasNext()); - EXPECT(it.next() == 127); - EXPECT(it.hasNext()); - EXPECT(it.next() == 204); - EXPECT(it.hasNext()); - EXPECT(it.next() == 205); - EXPECT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 3u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 31u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 32u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 63u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 127u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 204u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 205u); + EXPECT_FALSE(it.hasNext()); it.init(bits1, ASMJIT_ARRAY_SIZE(bits1), 4); - EXPECT(it.hasNext()); - EXPECT(it.next() == 31); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 31u); it.init(bits1, ASMJIT_ARRAY_SIZE(bits1), 64); - EXPECT(it.hasNext()); - EXPECT(it.next() == 127); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 127u); it.init(bits1, ASMJIT_ARRAY_SIZE(bits1), 127); - EXPECT(it.hasNext()); - EXPECT(it.next() == 127); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 127u); static const uint32_t bits2[] = { 0x80000000u, 0x80000000u, 0x00000000u, 0x80000000u }; it.init(bits2, ASMJIT_ARRAY_SIZE(bits2)); - EXPECT(it.hasNext()); - EXPECT(it.next() == 31); - EXPECT(it.hasNext()); - EXPECT(it.next() == 63); - EXPECT(it.hasNext()); - EXPECT(it.next() == 127); - EXPECT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 31u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 63u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 127u); + EXPECT_FALSE(it.hasNext()); static const uint32_t bits3[] = { 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u }; it.init(bits3, ASMJIT_ARRAY_SIZE(bits3)); - EXPECT(!it.hasNext()); + EXPECT_FALSE(it.hasNext()); static const uint32_t bits4[] = { 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u }; it.init(bits4, ASMJIT_ARRAY_SIZE(bits4)); - EXPECT(it.hasNext()); - EXPECT(it.next() == 127); - EXPECT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 127u); + EXPECT_FALSE(it.hasNext()); } INFO("Support::BitVectorIterator<uint64_t>"); @@ -410,20 +412,20 @@ static void testBitVector() noexcept { static const uint64_t bits1[] = { 0x80000000u, 0x80000000u, 0x00000000u, 0x80000000u }; Support::BitVectorIterator<uint64_t> it(bits1, ASMJIT_ARRAY_SIZE(bits1)); - EXPECT(it.hasNext()); - EXPECT(it.next() == 31); - EXPECT(it.hasNext()); - EXPECT(it.next() == 95); - EXPECT(it.hasNext()); - EXPECT(it.next() == 223); - EXPECT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 31u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 95u); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 223u); + EXPECT_FALSE(it.hasNext()); static const uint64_t bits2[] = { 0x8000000000000000u, 0, 0, 0 }; it.init(bits2, ASMJIT_ARRAY_SIZE(bits2)); - EXPECT(it.hasNext()); - EXPECT(it.next() == 63); - EXPECT(!it.hasNext()); + EXPECT_TRUE(it.hasNext()); + EXPECT_EQ(it.next(), 63u); + EXPECT_FALSE(it.hasNext()); } } diff --git a/3rdparty/asmjit/src/asmjit/core/support.h b/3rdparty/asmjit/src/asmjit/core/support.h index e55b8084dbf..b5be91bcd3e 100644 --- a/3rdparty/asmjit/src/asmjit/core/support.h +++ b/3rdparty/asmjit/src/asmjit/core/support.h @@ -68,29 +68,29 @@ namespace Internal { //! \endcond template<typename T> -static constexpr bool isUnsigned() noexcept { return std::is_unsigned<T>::value; } +static ASMJIT_INLINE_NODEBUG constexpr bool isUnsigned() noexcept { return std::is_unsigned<T>::value; } //! Casts an integer `x` to either `int32_t` or `int64_t` depending on `T`. template<typename T> -static constexpr typename Internal::Int32Or64<T, 0>::Type asInt(const T& x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr typename Internal::Int32Or64<T, 0>::Type asInt(const T& x) noexcept { return (typename Internal::Int32Or64<T, 0>::Type)x; } //! Casts an integer `x` to either `uint32_t` or `uint64_t` depending on `T`. template<typename T> -static constexpr typename Internal::Int32Or64<T, 1>::Type asUInt(const T& x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr typename Internal::Int32Or64<T, 1>::Type asUInt(const T& x) noexcept { return (typename Internal::Int32Or64<T, 1>::Type)x; } //! Casts an integer `x` to either `int32_t`, uint32_t`, `int64_t`, or `uint64_t` depending on `T`. template<typename T> -static constexpr typename Internal::Int32Or64<T>::Type asNormalized(const T& x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr typename Internal::Int32Or64<T>::Type asNormalized(const T& x) noexcept { return (typename Internal::Int32Or64<T>::Type)x; } //! Casts an integer `x` to the same type as defined by `<stdint.h>`. template<typename T> -static constexpr typename Internal::StdInt<sizeof(T), isUnsigned<T>()>::Type asStdInt(const T& x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr typename Internal::StdInt<sizeof(T), isUnsigned<T>()>::Type asStdInt(const T& x) noexcept { return (typename Internal::StdInt<sizeof(T), isUnsigned<T>()>::Type)x; } @@ -102,15 +102,15 @@ struct EnumValues { struct Iterator { ValueType value; - inline T operator*() const { return (T)value; } - inline void operator++() { ++value; } + ASMJIT_INLINE_NODEBUG T operator*() const { return (T)value; } + ASMJIT_INLINE_NODEBUG void operator++() { ++value; } - inline bool operator==(const Iterator& other) const noexcept { return value == other.value; } - inline bool operator!=(const Iterator& other) const noexcept { return value != other.value; } + ASMJIT_INLINE_NODEBUG bool operator==(const Iterator& other) const noexcept { return value == other.value; } + ASMJIT_INLINE_NODEBUG bool operator!=(const Iterator& other) const noexcept { return value != other.value; } }; - inline Iterator begin() const noexcept { return Iterator{ValueType(from)}; } - inline Iterator end() const noexcept { return Iterator{ValueType(to) + 1}; } + ASMJIT_INLINE_NODEBUG Iterator begin() const noexcept { return Iterator{ValueType(from)}; } + ASMJIT_INLINE_NODEBUG Iterator end() const noexcept { return Iterator{ValueType(to) + 1}; } }; // Support - BitCast @@ -120,7 +120,7 @@ struct EnumValues { namespace Internal { template<typename DstT, typename SrcT> union BitCastUnion { - inline BitCastUnion(SrcT src) noexcept : src(src) {} + ASMJIT_INLINE_NODEBUG BitCastUnion(SrcT src) noexcept : src(src) {} SrcT src; DstT dst; }; @@ -131,7 +131,7 @@ namespace Internal { //! //! Useful to bit-cast between integers and floating points. template<typename Dst, typename Src> -static inline Dst bitCast(const Src& x) noexcept { return Internal::BitCastUnion<Dst, Src>(x).dst; } +static ASMJIT_INLINE_NODEBUG Dst bitCast(const Src& x) noexcept { return Internal::BitCastUnion<Dst, Src>(x).dst; } // Support - BitOps // ================ @@ -140,62 +140,62 @@ static inline Dst bitCast(const Src& x) noexcept { return Internal::BitCastUnion typedef Internal::StdInt<sizeof(uintptr_t), 1>::Type BitWord; template<typename T> -static constexpr uint32_t bitSizeOf() noexcept { return uint32_t(sizeof(T) * 8u); } +static ASMJIT_INLINE_NODEBUG constexpr uint32_t bitSizeOf() noexcept { return uint32_t(sizeof(T) * 8u); } //! Number of bits stored in a single `BitWord`. static constexpr uint32_t kBitWordSizeInBits = bitSizeOf<BitWord>(); //! Returns `0 - x` in a safe way (no undefined behavior), works for unsigned numbers as well. template<typename T> -static constexpr T neg(const T& x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr T neg(const T& x) noexcept { typedef typename std::make_unsigned<T>::type U; return T(U(0) - U(x)); } template<typename T> -static constexpr T allOnes() noexcept { return neg<T>(T(1)); } +static ASMJIT_INLINE_NODEBUG constexpr T allOnes() noexcept { return neg<T>(T(1)); } //! Returns `x << y` (shift left logical) by explicitly casting `x` to an unsigned type and back. template<typename X, typename Y> -static constexpr X shl(const X& x, const Y& y) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr X shl(const X& x, const Y& y) noexcept { typedef typename std::make_unsigned<X>::type U; return X(U(x) << y); } //! Returns `x >> y` (shift right logical) by explicitly casting `x` to an unsigned type and back. template<typename X, typename Y> -static constexpr X shr(const X& x, const Y& y) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr X shr(const X& x, const Y& y) noexcept { typedef typename std::make_unsigned<X>::type U; return X(U(x) >> y); } //! Returns `x >> y` (shift right arithmetic) by explicitly casting `x` to a signed type and back. template<typename X, typename Y> -static constexpr X sar(const X& x, const Y& y) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr X sar(const X& x, const Y& y) noexcept { typedef typename std::make_signed<X>::type S; return X(S(x) >> y); } template<typename X, typename Y> -static constexpr X ror(const X& x, const Y& y) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr X ror(const X& x, const Y& y) noexcept { typedef typename std::make_unsigned<X>::type U; - return X((U(x) >> y) | (U(x) << (bitSizeOf<U>() - y))); + return X((U(x) >> y) | (U(x) << (bitSizeOf<U>() - U(y)))); } //! Returns `x | (x >> y)` - helper used by some bit manipulation helpers. template<typename X, typename Y> -static constexpr X or_shr(const X& x, const Y& y) noexcept { return X(x | shr(x, y)); } +static ASMJIT_INLINE_NODEBUG constexpr X or_shr(const X& x, const Y& y) noexcept { return X(x | shr(x, y)); } //! Returns `x & -x` - extracts lowest set isolated bit (like BLSI instruction). template<typename T> -static constexpr T blsi(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr T blsi(T x) noexcept { typedef typename std::make_unsigned<T>::type U; return T(U(x) & neg(U(x))); } //! Tests whether the given value `x` has `n`th bit set. template<typename T, typename IndexT> -static constexpr bool bitTest(T x, IndexT n) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool bitTest(T x, IndexT n) noexcept { typedef typename std::make_unsigned<T>::type U; return (U(x) & (U(1) << asStdInt(n))) != 0; } @@ -203,7 +203,7 @@ static constexpr bool bitTest(T x, IndexT n) noexcept { // Tests whether the given `value` is a consecutive mask of bits that starts at // the least significant bit. template<typename T> -static inline constexpr bool isLsbMask(const T& value) { +static ASMJIT_INLINE_NODEBUG constexpr bool isLsbMask(const T& value) { typedef typename std::make_unsigned<T>::type U; return value && ((U(value) + 1u) & U(value)) == 0; } @@ -214,14 +214,14 @@ static inline constexpr bool isLsbMask(const T& value) { // This function is similar to \ref isLsbMask(), but the mask doesn't have to // start at a least significant bit. template<typename T> -static inline constexpr bool isConsecutiveMask(const T& value) { +static ASMJIT_INLINE_NODEBUG constexpr bool isConsecutiveMask(const T& value) { typedef typename std::make_unsigned<T>::type U; return value && isLsbMask((U(value) - 1u) | U(value)); } //! Generates a trailing bit-mask that has `n` least significant (trailing) bits set. template<typename T, typename CountT> -static constexpr T lsbMask(const CountT& n) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr T lsbMask(const CountT& n) noexcept { typedef typename std::make_unsigned<T>::type U; return (sizeof(U) < sizeof(uintptr_t)) // Prevent undefined behavior by using a larger type than T. @@ -230,9 +230,9 @@ static constexpr T lsbMask(const CountT& n) noexcept { : n ? T(shr(allOnes<T>(), bitSizeOf<T>() - size_t(n))) : T(0); } -//! Generats a leading bit-mask that has `n` most significant (leading) bits set. +//! Generates a leading bit-mask that has `n` most significant (leading) bits set. template<typename T, typename CountT> -static constexpr T msbMask(const CountT& n) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr T msbMask(const CountT& n) noexcept { typedef typename std::make_unsigned<T>::type U; return (sizeof(U) < sizeof(uintptr_t)) // Prevent undefined behavior by using a larger type than T. @@ -243,15 +243,15 @@ static constexpr T msbMask(const CountT& n) noexcept { //! Returns a bit-mask that has `x` bit set. template<typename Index> -static constexpr uint32_t bitMask(const Index& x) noexcept { return (1u << asUInt(x)); } +static ASMJIT_INLINE_NODEBUG constexpr uint32_t bitMask(const Index& x) noexcept { return (1u << asUInt(x)); } //! Returns a bit-mask that has `x` bit set (multiple arguments). template<typename Index, typename... Args> -static constexpr uint32_t bitMask(const Index& x, Args... args) noexcept { return bitMask(x) | bitMask(args...); } +static ASMJIT_INLINE_NODEBUG constexpr uint32_t bitMask(const Index& x, Args... args) noexcept { return bitMask(x) | bitMask(args...); } //! Converts a boolean value `b` to zero or full mask (all bits set). template<typename DstT, typename SrcT> -static constexpr DstT bitMaskFromBool(SrcT b) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr DstT bitMaskFromBool(SrcT b) noexcept { typedef typename std::make_unsigned<DstT>::type U; return DstT(U(0) - U(b)); } @@ -263,19 +263,19 @@ static inline constexpr bool test(A a, B b) noexcept { return (asUInt(a) & asUIn //! \cond namespace Internal { // Fills all trailing bits right from the first most significant bit set. - static constexpr uint8_t fillTrailingBitsImpl(uint8_t x) noexcept { return or_shr(or_shr(or_shr(x, 1), 2), 4); } + static ASMJIT_INLINE_NODEBUG constexpr uint8_t fillTrailingBitsImpl(uint8_t x) noexcept { return or_shr(or_shr(or_shr(x, 1), 2), 4); } // Fills all trailing bits right from the first most significant bit set. - static constexpr uint16_t fillTrailingBitsImpl(uint16_t x) noexcept { return or_shr(or_shr(or_shr(or_shr(x, 1), 2), 4), 8); } + static ASMJIT_INLINE_NODEBUG constexpr uint16_t fillTrailingBitsImpl(uint16_t x) noexcept { return or_shr(or_shr(or_shr(or_shr(x, 1), 2), 4), 8); } // Fills all trailing bits right from the first most significant bit set. - static constexpr uint32_t fillTrailingBitsImpl(uint32_t x) noexcept { return or_shr(or_shr(or_shr(or_shr(or_shr(x, 1), 2), 4), 8), 16); } + static ASMJIT_INLINE_NODEBUG constexpr uint32_t fillTrailingBitsImpl(uint32_t x) noexcept { return or_shr(or_shr(or_shr(or_shr(or_shr(x, 1), 2), 4), 8), 16); } // Fills all trailing bits right from the first most significant bit set. - static constexpr uint64_t fillTrailingBitsImpl(uint64_t x) noexcept { return or_shr(or_shr(or_shr(or_shr(or_shr(or_shr(x, 1), 2), 4), 8), 16), 32); } + static ASMJIT_INLINE_NODEBUG constexpr uint64_t fillTrailingBitsImpl(uint64_t x) noexcept { return or_shr(or_shr(or_shr(or_shr(or_shr(or_shr(x, 1), 2), 4), 8), 16), 32); } } //! \endcond // Fills all trailing bits right from the first most significant bit set. template<typename T> -static constexpr T fillTrailingBits(const T& x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr T fillTrailingBits(const T& x) noexcept { typedef typename std::make_unsigned<T>::type U; return T(Internal::fillTrailingBitsImpl(U(x))); } @@ -292,59 +292,59 @@ struct BitScanData { T x; uint32_t n; }; template<typename T, uint32_t N> struct BitScanCalc { - static constexpr BitScanData<T> advanceLeft(const BitScanData<T>& data, uint32_t n) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr BitScanData<T> advanceLeft(const BitScanData<T>& data, uint32_t n) noexcept { return BitScanData<T> { data.x << n, data.n + n }; } - static constexpr BitScanData<T> advanceRight(const BitScanData<T>& data, uint32_t n) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr BitScanData<T> advanceRight(const BitScanData<T>& data, uint32_t n) noexcept { return BitScanData<T> { data.x >> n, data.n + n }; } - static constexpr BitScanData<T> clz(const BitScanData<T>& data) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr BitScanData<T> clz(const BitScanData<T>& data) noexcept { return BitScanCalc<T, N / 2>::clz(advanceLeft(data, data.x & (allOnes<T>() << (bitSizeOf<T>() - N)) ? uint32_t(0) : N)); } - static constexpr BitScanData<T> ctz(const BitScanData<T>& data) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr BitScanData<T> ctz(const BitScanData<T>& data) noexcept { return BitScanCalc<T, N / 2>::ctz(advanceRight(data, data.x & (allOnes<T>() >> (bitSizeOf<T>() - N)) ? uint32_t(0) : N)); } }; template<typename T> struct BitScanCalc<T, 0> { - static constexpr BitScanData<T> clz(const BitScanData<T>& ctx) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr BitScanData<T> clz(const BitScanData<T>& ctx) noexcept { return BitScanData<T> { 0, ctx.n - uint32_t(ctx.x >> (bitSizeOf<T>() - 1)) }; } - static constexpr BitScanData<T> ctz(const BitScanData<T>& ctx) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr BitScanData<T> ctz(const BitScanData<T>& ctx) noexcept { return BitScanData<T> { 0, ctx.n - uint32_t(ctx.x & 0x1) }; } }; template<typename T> -constexpr uint32_t clzFallback(const T& x) noexcept { +ASMJIT_INLINE_NODEBUG constexpr uint32_t clzFallback(const T& x) noexcept { return BitScanCalc<T, bitSizeOf<T>() / 2u>::clz(BitScanData<T>{x, 1}).n; } template<typename T> -constexpr uint32_t ctzFallback(const T& x) noexcept { +ASMJIT_INLINE_NODEBUG constexpr uint32_t ctzFallback(const T& x) noexcept { return BitScanCalc<T, bitSizeOf<T>() / 2u>::ctz(BitScanData<T>{x, 1}).n; } -template<typename T> inline uint32_t clzImpl(const T& x) noexcept { return clzFallback(asUInt(x)); } -template<typename T> inline uint32_t ctzImpl(const T& x) noexcept { return ctzFallback(asUInt(x)); } +template<typename T> ASMJIT_INLINE_NODEBUG uint32_t clzImpl(const T& x) noexcept { return clzFallback(asUInt(x)); } +template<typename T> ASMJIT_INLINE_NODEBUG uint32_t ctzImpl(const T& x) noexcept { return ctzFallback(asUInt(x)); } #if !defined(ASMJIT_NO_INTRINSICS) # if defined(__GNUC__) -template<> inline uint32_t clzImpl(const uint32_t& x) noexcept { return uint32_t(__builtin_clz(x)); } -template<> inline uint32_t clzImpl(const uint64_t& x) noexcept { return uint32_t(__builtin_clzll(x)); } -template<> inline uint32_t ctzImpl(const uint32_t& x) noexcept { return uint32_t(__builtin_ctz(x)); } -template<> inline uint32_t ctzImpl(const uint64_t& x) noexcept { return uint32_t(__builtin_ctzll(x)); } +template<> ASMJIT_INLINE_NODEBUG uint32_t clzImpl(const uint32_t& x) noexcept { return uint32_t(__builtin_clz(x)); } +template<> ASMJIT_INLINE_NODEBUG uint32_t clzImpl(const uint64_t& x) noexcept { return uint32_t(__builtin_clzll(x)); } +template<> ASMJIT_INLINE_NODEBUG uint32_t ctzImpl(const uint32_t& x) noexcept { return uint32_t(__builtin_ctz(x)); } +template<> ASMJIT_INLINE_NODEBUG uint32_t ctzImpl(const uint64_t& x) noexcept { return uint32_t(__builtin_ctzll(x)); } # elif defined(_MSC_VER) -template<> inline uint32_t clzImpl(const uint32_t& x) noexcept { unsigned long i; _BitScanReverse(&i, x); return uint32_t(i ^ 31); } -template<> inline uint32_t ctzImpl(const uint32_t& x) noexcept { unsigned long i; _BitScanForward(&i, x); return uint32_t(i); } +template<> ASMJIT_INLINE_NODEBUG uint32_t clzImpl(const uint32_t& x) noexcept { unsigned long i; _BitScanReverse(&i, x); return uint32_t(i ^ 31); } +template<> ASMJIT_INLINE_NODEBUG uint32_t ctzImpl(const uint32_t& x) noexcept { unsigned long i; _BitScanForward(&i, x); return uint32_t(i); } # if ASMJIT_ARCH_X86 == 64 || ASMJIT_ARCH_ARM == 64 -template<> inline uint32_t clzImpl(const uint64_t& x) noexcept { unsigned long i; _BitScanReverse64(&i, x); return uint32_t(i ^ 63); } -template<> inline uint32_t ctzImpl(const uint64_t& x) noexcept { unsigned long i; _BitScanForward64(&i, x); return uint32_t(i); } +template<> ASMJIT_INLINE_NODEBUG uint32_t clzImpl(const uint64_t& x) noexcept { unsigned long i; _BitScanReverse64(&i, x); return uint32_t(i ^ 63); } +template<> ASMJIT_INLINE_NODEBUG uint32_t ctzImpl(const uint64_t& x) noexcept { unsigned long i; _BitScanForward64(&i, x); return uint32_t(i); } # endif # endif #endif @@ -357,13 +357,13 @@ template<> inline uint32_t ctzImpl(const uint64_t& x) noexcept { unsigned long i //! //! \note The input MUST NOT be zero, otherwise the result is undefined. template<typename T> -static inline uint32_t clz(T x) noexcept { return Internal::clzImpl(asUInt(x)); } +static ASMJIT_INLINE_NODEBUG uint32_t clz(T x) noexcept { return Internal::clzImpl(asUInt(x)); } //! Count trailing zeros in `x` (returns a position of a first bit set in `x`). //! //! \note The input MUST NOT be zero, otherwise the result is undefined. template<typename T> -static inline uint32_t ctz(T x) noexcept { return Internal::ctzImpl(asUInt(x)); } +static ASMJIT_INLINE_NODEBUG uint32_t ctz(T x) noexcept { return Internal::ctzImpl(asUInt(x)); } template<uint64_t kInput> struct ConstCTZ { @@ -450,49 +450,48 @@ struct ConstCTZ { //! \cond namespace Internal { - static inline uint32_t constPopcntImpl(uint32_t x) noexcept { + static ASMJIT_INLINE_NODEBUG uint32_t constPopcntImpl(uint32_t x) noexcept { x = x - ((x >> 1) & 0x55555555u); x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u); return (((x + (x >> 4)) & 0x0F0F0F0Fu) * 0x01010101u) >> 24; } - static inline uint32_t constPopcntImpl(uint64_t x) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - x = x - ((x >> 1) & 0x5555555555555555u); - x = (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u); - return uint32_t((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu) * 0x0101010101010101u) >> 56); - } - else { - return constPopcntImpl(uint32_t(x >> 32)) + - constPopcntImpl(uint32_t(x & 0xFFFFFFFFu)); - } + static ASMJIT_INLINE_NODEBUG uint32_t constPopcntImpl(uint64_t x) noexcept { +#if ASMJIT_ARCH_BITS >= 64 + x = x - ((x >> 1) & 0x5555555555555555u); + x = (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u); + return uint32_t((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu) * 0x0101010101010101u) >> 56); +#else + return constPopcntImpl(uint32_t(x >> 32)) + + constPopcntImpl(uint32_t(x & 0xFFFFFFFFu)); +#endif } - static inline uint32_t popcntImpl(uint32_t x) noexcept { - #if defined(__GNUC__) + static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint32_t x) noexcept { +#if defined(__GNUC__) return uint32_t(__builtin_popcount(x)); - #else +#else return constPopcntImpl(asUInt(x)); - #endif +#endif } - static inline uint32_t popcntImpl(uint64_t x) noexcept { - #if defined(__GNUC__) + static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint64_t x) noexcept { +#if defined(__GNUC__) return uint32_t(__builtin_popcountll(x)); - #else +#else return constPopcntImpl(asUInt(x)); - #endif +#endif } } //! \endcond //! Calculates count of bits in `x`. template<typename T> -static inline uint32_t popcnt(T x) noexcept { return Internal::popcntImpl(asUInt(x)); } +static ASMJIT_INLINE_NODEBUG uint32_t popcnt(T x) noexcept { return Internal::popcntImpl(asUInt(x)); } //! Calculates count of bits in `x` (useful in constant expressions). template<typename T> -static inline uint32_t constPopcnt(T x) noexcept { return Internal::constPopcntImpl(asUInt(x)); } +static ASMJIT_INLINE_NODEBUG uint32_t constPopcnt(T x) noexcept { return Internal::constPopcntImpl(asUInt(x)); } // Support - Min/Max // ================= @@ -502,16 +501,16 @@ static inline uint32_t constPopcnt(T x) noexcept { return Internal::constPopcntI // a reference to `a` or `b` but it's a new value instead. template<typename T> -static constexpr T min(const T& a, const T& b) noexcept { return b < a ? b : a; } +static ASMJIT_INLINE_NODEBUG constexpr T min(const T& a, const T& b) noexcept { return b < a ? b : a; } template<typename T, typename... Args> -static constexpr T min(const T& a, const T& b, Args&&... args) noexcept { return min(min(a, b), std::forward<Args>(args)...); } +static ASMJIT_INLINE_NODEBUG constexpr T min(const T& a, const T& b, Args&&... args) noexcept { return min(min(a, b), std::forward<Args>(args)...); } template<typename T> -static constexpr T max(const T& a, const T& b) noexcept { return a < b ? b : a; } +static ASMJIT_INLINE_NODEBUG constexpr T max(const T& a, const T& b) noexcept { return a < b ? b : a; } template<typename T, typename... Args> -static constexpr T max(const T& a, const T& b, Args&&... args) noexcept { return max(max(a, b), std::forward<Args>(args)...); } +static ASMJIT_INLINE_NODEBUG constexpr T max(const T& a, const T& b, Args&&... args) noexcept { return max(max(a, b), std::forward<Args>(args)...); } // Support - Immediate Helpers // =========================== @@ -519,22 +518,22 @@ static constexpr T max(const T& a, const T& b, Args&&... args) noexcept { return namespace Internal { template<typename T, bool IsFloat> struct ImmConv { - static inline int64_t fromT(const T& x) noexcept { return int64_t(x); } - static inline T toT(int64_t x) noexcept { return T(uint64_t(x) & Support::allOnes<typename std::make_unsigned<T>::type>()); } + static ASMJIT_INLINE_NODEBUG int64_t fromT(const T& x) noexcept { return int64_t(x); } + static ASMJIT_INLINE_NODEBUG T toT(int64_t x) noexcept { return T(uint64_t(x) & Support::allOnes<typename std::make_unsigned<T>::type>()); } }; template<typename T> struct ImmConv<T, true> { - static inline int64_t fromT(const T& x) noexcept { return int64_t(bitCast<int64_t>(double(x))); } - static inline T toT(int64_t x) noexcept { return T(bitCast<double>(x)); } + static ASMJIT_INLINE_NODEBUG int64_t fromT(const T& x) noexcept { return int64_t(bitCast<int64_t>(double(x))); } + static ASMJIT_INLINE_NODEBUG T toT(int64_t x) noexcept { return T(bitCast<double>(x)); } }; } template<typename T> -static inline int64_t immediateFromT(const T& x) noexcept { return Internal::ImmConv<T, std::is_floating_point<T>::value>::fromT(x); } +static ASMJIT_INLINE_NODEBUG int64_t immediateFromT(const T& x) noexcept { return Internal::ImmConv<T, std::is_floating_point<T>::value>::fromT(x); } template<typename T> -static inline T immediateToT(int64_t x) noexcept { return Internal::ImmConv<T, std::is_floating_point<T>::value>::toT(x); } +static ASMJIT_INLINE_NODEBUG T immediateToT(int64_t x) noexcept { return Internal::ImmConv<T, std::is_floating_point<T>::value>::toT(x); } // Support - Overflow Arithmetic // ============================= @@ -596,9 +595,9 @@ namespace Internal { template<typename T> inline T subOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return subOverflowFallback(x, y, of); } template<typename T> inline T mulOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return mulOverflowFallback(x, y, of); } - #if defined(__GNUC__) && !defined(ASMJIT_NO_INTRINSICS) - #if defined(__clang__) || __GNUC__ >= 5 - #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \ +#if defined(__GNUC__) && !defined(ASMJIT_NO_INTRINSICS) +#if defined(__clang__) || __GNUC__ >= 5 +#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \ template<> \ inline T FUNC(const T& x, const T& y, FastUInt8* of) noexcept { \ RESULT_T result; \ @@ -617,13 +616,13 @@ namespace Internal { ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, uint32_t, unsigned int , __builtin_umul_overflow ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, int64_t , long long , __builtin_smulll_overflow) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, uint64_t, unsigned long long, __builtin_umulll_overflow) - #undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE - #endif - #endif +#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE +#endif +#endif // There is a bug in MSVC that makes these specializations unusable, maybe in the future... - #if defined(_MSC_VER) && 0 - #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \ +#if defined(_MSC_VER) && 0 +#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \ template<> \ inline T FUNC(T x, T y, FastUInt8* of) noexcept { \ ALT_T result; \ @@ -632,12 +631,12 @@ namespace Internal { } ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint32_t, unsigned int , _addcarry_u32 ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint32_t, unsigned int , _subborrow_u32) - #if ARCH_BITS >= 64 +#if ARCH_BITS >= 64 ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint64_t, unsigned __int64 , _addcarry_u64 ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint64_t, unsigned __int64 , _subborrow_u64) - #endif - #undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE - #endif +#endif +#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE +#endif } // {Internal} //! \endcond @@ -654,26 +653,26 @@ static inline T mulOverflow(const T& x, const T& y, FastUInt8* of) noexcept { re // =================== template<typename X, typename Y> -static constexpr bool isAligned(X base, Y alignment) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isAligned(X base, Y alignment) noexcept { typedef typename Internal::StdInt<sizeof(X), 1>::Type U; return ((U)base % (U)alignment) == 0; } //! Tests whether the `x` is a power of two (only one bit is set). template<typename T> -static constexpr bool isPowerOf2(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isPowerOf2(T x) noexcept { typedef typename std::make_unsigned<T>::type U; return x && !(U(x) & (U(x) - U(1))); } template<typename X, typename Y> -static constexpr X alignUp(X x, Y alignment) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr X alignUp(X x, Y alignment) noexcept { typedef typename Internal::StdInt<sizeof(X), 1>::Type U; return (X)( ((U)x + ((U)(alignment) - 1u)) & ~((U)(alignment) - 1u) ); } template<typename T> -static constexpr T alignUpPowerOf2(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr T alignUpPowerOf2(T x) noexcept { typedef typename Internal::StdInt<sizeof(T), 1>::Type U; return (T)(fillTrailingBits(U(x) - 1u) + 1u); } @@ -681,13 +680,13 @@ static constexpr T alignUpPowerOf2(T x) noexcept { //! Returns either zero or a positive difference between `base` and `base` when //! aligned to `alignment`. template<typename X, typename Y> -static constexpr typename Internal::StdInt<sizeof(X), 1>::Type alignUpDiff(X base, Y alignment) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr typename Internal::StdInt<sizeof(X), 1>::Type alignUpDiff(X base, Y alignment) noexcept { typedef typename Internal::StdInt<sizeof(X), 1>::Type U; return alignUp(U(base), alignment) - U(base); } template<typename X, typename Y> -static constexpr X alignDown(X x, Y alignment) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr X alignDown(X x, Y alignment) noexcept { typedef typename Internal::StdInt<sizeof(X), 1>::Type U; return (X)( (U)x & ~((U)(alignment) - 1u) ); } @@ -699,7 +698,7 @@ static constexpr X alignDown(X x, Y alignment) noexcept { //! granularized by `granularity`. This function can be used to calculate //! the number of BitWords to represent N bits, for example. template<typename X, typename Y> -static constexpr X numGranularized(X base, Y granularity) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr X numGranularized(X base, Y granularity) noexcept { typedef typename Internal::StdInt<sizeof(X), 1>::Type U; return X((U(base) + U(granularity) - 1) / U(granularity)); } @@ -709,7 +708,7 @@ static constexpr X numGranularized(X base, Y granularity) noexcept { //! Checks whether `x` is greater than or equal to `a` and lesser than or equal to `b`. template<typename T> -static constexpr bool isBetween(const T& x, const T& a, const T& b) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isBetween(const T& x, const T& a, const T& b) noexcept { return x >= a && x <= b; } @@ -718,7 +717,7 @@ static constexpr bool isBetween(const T& x, const T& a, const T& b) noexcept { //! Checks whether the given integer `x` can be casted to a 4-bit signed integer. template<typename T> -static constexpr bool isInt4(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isInt4(T x) noexcept { typedef typename std::make_signed<T>::type S; typedef typename std::make_unsigned<T>::type U; @@ -727,7 +726,7 @@ static constexpr bool isInt4(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 7-bit signed integer. template<typename T> -static constexpr bool isInt7(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isInt7(T x) noexcept { typedef typename std::make_signed<T>::type S; typedef typename std::make_unsigned<T>::type U; @@ -736,7 +735,7 @@ static constexpr bool isInt7(T x) noexcept { //! Checks whether the given integer `x` can be casted to an 8-bit signed integer. template<typename T> -static constexpr bool isInt8(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isInt8(T x) noexcept { typedef typename std::make_signed<T>::type S; typedef typename std::make_unsigned<T>::type U; @@ -745,7 +744,7 @@ static constexpr bool isInt8(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 9-bit signed integer. template<typename T> -static constexpr bool isInt9(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isInt9(T x) noexcept { typedef typename std::make_signed<T>::type S; typedef typename std::make_unsigned<T>::type U; @@ -755,7 +754,7 @@ static constexpr bool isInt9(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 10-bit signed integer. template<typename T> -static constexpr bool isInt10(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isInt10(T x) noexcept { typedef typename std::make_signed<T>::type S; typedef typename std::make_unsigned<T>::type U; @@ -765,7 +764,7 @@ static constexpr bool isInt10(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 16-bit signed integer. template<typename T> -static constexpr bool isInt16(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isInt16(T x) noexcept { typedef typename std::make_signed<T>::type S; typedef typename std::make_unsigned<T>::type U; @@ -775,7 +774,7 @@ static constexpr bool isInt16(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 32-bit signed integer. template<typename T> -static constexpr bool isInt32(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isInt32(T x) noexcept { typedef typename std::make_signed<T>::type S; typedef typename std::make_unsigned<T>::type U; @@ -785,7 +784,7 @@ static constexpr bool isInt32(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 4-bit unsigned integer. template<typename T> -static constexpr bool isUInt4(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt4(T x) noexcept { typedef typename std::make_unsigned<T>::type U; return std::is_signed<T>::value ? x >= T(0) && x <= T(15) @@ -794,7 +793,7 @@ static constexpr bool isUInt4(T x) noexcept { //! Checks whether the given integer `x` can be casted to an 8-bit unsigned integer. template<typename T> -static constexpr bool isUInt8(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt8(T x) noexcept { typedef typename std::make_unsigned<T>::type U; return std::is_signed<T>::value ? (sizeof(T) <= 1 || T(x) <= T(255)) && x >= T(0) @@ -803,7 +802,7 @@ static constexpr bool isUInt8(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 12-bit unsigned integer (ARM specific). template<typename T> -static constexpr bool isUInt12(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt12(T x) noexcept { typedef typename std::make_unsigned<T>::type U; return std::is_signed<T>::value ? (sizeof(T) <= 1 || T(x) <= T(4095)) && x >= T(0) @@ -812,7 +811,7 @@ static constexpr bool isUInt12(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 16-bit unsigned integer. template<typename T> -static constexpr bool isUInt16(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt16(T x) noexcept { typedef typename std::make_unsigned<T>::type U; return std::is_signed<T>::value ? (sizeof(T) <= 2 || T(x) <= T(65535)) && x >= T(0) @@ -821,7 +820,7 @@ static constexpr bool isUInt16(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 32-bit unsigned integer. template<typename T> -static constexpr bool isUInt32(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt32(T x) noexcept { typedef typename std::make_unsigned<T>::type U; return std::is_signed<T>::value ? (sizeof(T) <= 4 || T(x) <= T(4294967295u)) && x >= T(0) @@ -830,16 +829,16 @@ static constexpr bool isUInt32(T x) noexcept { //! Checks whether the given integer `x` can be casted to a 32-bit unsigned integer. template<typename T> -static constexpr bool isIntOrUInt32(T x) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isIntOrUInt32(T x) noexcept { return sizeof(T) <= 4 ? true : (uint32_t(uint64_t(x) >> 32) + 1u) <= 1u; } -static bool inline isEncodableOffset32(int32_t offset, uint32_t nBits) noexcept { +static bool ASMJIT_INLINE_NODEBUG isEncodableOffset32(int32_t offset, uint32_t nBits) noexcept { uint32_t nRev = 32 - nBits; return Support::sar(Support::shl(offset, nRev), nRev) == offset; } -static bool inline isEncodableOffset64(int64_t offset, uint32_t nBits) noexcept { +static bool ASMJIT_INLINE_NODEBUG isEncodableOffset64(int64_t offset, uint32_t nBits) noexcept { uint32_t nRev = 64 - nBits; return Support::sar(Support::shl(offset, nRev), nRev) == offset; } @@ -847,15 +846,15 @@ static bool inline isEncodableOffset64(int64_t offset, uint32_t nBits) noexcept // Support - ByteSwap // ================== -static inline uint16_t byteswap16(uint16_t x) noexcept { +static ASMJIT_INLINE_NODEBUG uint16_t byteswap16(uint16_t x) noexcept { return uint16_t(((x >> 8) & 0xFFu) | ((x & 0xFFu) << 8)); } -static inline uint32_t byteswap32(uint32_t x) noexcept { +static ASMJIT_INLINE_NODEBUG uint32_t byteswap32(uint32_t x) noexcept { return (x << 24) | (x >> 24) | ((x << 8) & 0x00FF0000u) | ((x >> 8) & 0x0000FF00); } -static inline uint64_t byteswap64(uint64_t x) noexcept { +static ASMJIT_INLINE_NODEBUG uint64_t byteswap64(uint64_t x) noexcept { #if (defined(__GNUC__) || defined(__clang__)) && !defined(ASMJIT_NO_INTRINSICS) return uint64_t(__builtin_bswap64(uint64_t(x))); #elif defined(_MSC_VER) && !defined(ASMJIT_NO_INTRINSICS) @@ -870,20 +869,20 @@ static inline uint64_t byteswap64(uint64_t x) noexcept { // =========================== //! Pack four 8-bit integer into a 32-bit integer as it is an array of `{b0,b1,b2,b3}`. -static constexpr uint32_t bytepack32_4x8(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr uint32_t bytepack32_4x8(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept { return ASMJIT_ARCH_LE ? (a | (b << 8) | (c << 16) | (d << 24)) : (d | (c << 8) | (b << 16) | (a << 24)); } template<typename T> -static constexpr uint32_t unpackU32At0(T x) noexcept { return ASMJIT_ARCH_LE ? uint32_t(uint64_t(x) & 0xFFFFFFFFu) : uint32_t(uint64_t(x) >> 32); } +static ASMJIT_INLINE_NODEBUG constexpr uint32_t unpackU32At0(T x) noexcept { return ASMJIT_ARCH_LE ? uint32_t(uint64_t(x) & 0xFFFFFFFFu) : uint32_t(uint64_t(x) >> 32); } template<typename T> -static constexpr uint32_t unpackU32At1(T x) noexcept { return ASMJIT_ARCH_BE ? uint32_t(uint64_t(x) & 0xFFFFFFFFu) : uint32_t(uint64_t(x) >> 32); } +static ASMJIT_INLINE_NODEBUG constexpr uint32_t unpackU32At1(T x) noexcept { return ASMJIT_ARCH_BE ? uint32_t(uint64_t(x) & 0xFFFFFFFFu) : uint32_t(uint64_t(x) >> 32); } // Support - Position of byte (in bit-shift) // ========================================= -static inline uint32_t byteShiftOfDWordStruct(uint32_t index) noexcept { +static ASMJIT_INLINE_NODEBUG uint32_t byteShiftOfDWordStruct(uint32_t index) noexcept { return ASMJIT_ARCH_LE ? index * 8 : (uint32_t(sizeof(uint32_t)) - 1u - index) * 8; } @@ -891,31 +890,31 @@ static inline uint32_t byteShiftOfDWordStruct(uint32_t index) noexcept { // ========================== template<typename T> -static constexpr T asciiToLower(T c) noexcept { return T(c ^ T(T(c >= T('A') && c <= T('Z')) << 5)); } +static ASMJIT_INLINE_NODEBUG constexpr T asciiToLower(T c) noexcept { return T(c ^ T(T(c >= T('A') && c <= T('Z')) << 5)); } template<typename T> -static constexpr T asciiToUpper(T c) noexcept { return T(c ^ T(T(c >= T('a') && c <= T('z')) << 5)); } +static ASMJIT_INLINE_NODEBUG constexpr T asciiToUpper(T c) noexcept { return T(c ^ T(T(c >= T('a') && c <= T('z')) << 5)); } -static ASMJIT_FORCE_INLINE size_t strLen(const char* s, size_t maxSize) noexcept { +static ASMJIT_INLINE_NODEBUG size_t strLen(const char* s, size_t maxSize) noexcept { size_t i = 0; while (i < maxSize && s[i] != '\0') i++; return i; } -static constexpr uint32_t hashRound(uint32_t hash, uint32_t c) noexcept { return hash * 65599 + c; } +static ASMJIT_INLINE_NODEBUG constexpr uint32_t hashRound(uint32_t hash, uint32_t c) noexcept { return hash * 65599 + c; } // Gets a hash of the given string `data` of size `size`. Size must be valid // as this function doesn't check for a null terminator and allows it in the // middle of the string. -static inline uint32_t hashString(const char* data, size_t size) noexcept { +static ASMJIT_INLINE_NODEBUG uint32_t hashString(const char* data, size_t size) noexcept { uint32_t hashCode = 0; for (uint32_t i = 0; i < size; i++) hashCode = hashRound(hashCode, uint8_t(data[i])); return hashCode; } -static ASMJIT_FORCE_INLINE const char* findPackedString(const char* p, uint32_t id) noexcept { +static ASMJIT_INLINE_NODEBUG const char* findPackedString(const char* p, uint32_t id) noexcept { uint32_t i = 0; while (i < id) { while (p[0]) @@ -926,68 +925,68 @@ static ASMJIT_FORCE_INLINE const char* findPackedString(const char* p, uint32_t return p; } -//! Compares two instruction names. -//! -//! `a` is a null terminated instruction name from arch-specific `nameData[]` -//! table. `b` is a possibly non-null terminated instruction name passed to -//! `InstAPI::stringToInstId()`. -static ASMJIT_FORCE_INLINE int cmpInstName(const char* a, const char* b, size_t size) noexcept { +//! Compares two string views. +static ASMJIT_FORCE_INLINE int compareStringViews(const char* aData, size_t aSize, const char* bData, size_t bSize) noexcept { + size_t size = Support::min(aSize, bSize); + for (size_t i = 0; i < size; i++) { - int c = int(uint8_t(a[i])) - int(uint8_t(b[i])); - if (c != 0) return c; + int c = int(uint8_t(aData[i])) - int(uint8_t(bData[i])); + if (c != 0) + return c; } - return int(uint8_t(a[size])); + + return int(aSize) - int(bSize); } // Support - Memory Read Access - 8 Bits // ===================================== -static inline uint8_t readU8(const void* p) noexcept { return static_cast<const uint8_t*>(p)[0]; } -static inline int8_t readI8(const void* p) noexcept { return static_cast<const int8_t*>(p)[0]; } +static ASMJIT_INLINE_NODEBUG uint8_t readU8(const void* p) noexcept { return static_cast<const uint8_t*>(p)[0]; } +static ASMJIT_INLINE_NODEBUG int8_t readI8(const void* p) noexcept { return static_cast<const int8_t*>(p)[0]; } // Support - Memory Read Access - 16 Bits // ====================================== template<ByteOrder BO, size_t Alignment> -static inline uint16_t readU16x(const void* p) noexcept { +static ASMJIT_INLINE_NODEBUG uint16_t readU16x(const void* p) noexcept { typedef typename Internal::AliasedUInt<uint16_t, Alignment>::T U16AlignedToN; uint16_t x = static_cast<const U16AlignedToN*>(p)[0]; return BO == ByteOrder::kNative ? x : byteswap16(x); } template<size_t Alignment = 1> -static inline uint16_t readU16u(const void* p) noexcept { return readU16x<ByteOrder::kNative, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint16_t readU16u(const void* p) noexcept { return readU16x<ByteOrder::kNative, Alignment>(p); } template<size_t Alignment = 1> -static inline uint16_t readU16uLE(const void* p) noexcept { return readU16x<ByteOrder::kLE, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint16_t readU16uLE(const void* p) noexcept { return readU16x<ByteOrder::kLE, Alignment>(p); } template<size_t Alignment = 1> -static inline uint16_t readU16uBE(const void* p) noexcept { return readU16x<ByteOrder::kBE, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint16_t readU16uBE(const void* p) noexcept { return readU16x<ByteOrder::kBE, Alignment>(p); } -static inline uint16_t readU16a(const void* p) noexcept { return readU16x<ByteOrder::kNative, 2>(p); } -static inline uint16_t readU16aLE(const void* p) noexcept { return readU16x<ByteOrder::kLE, 2>(p); } -static inline uint16_t readU16aBE(const void* p) noexcept { return readU16x<ByteOrder::kBE, 2>(p); } +static ASMJIT_INLINE_NODEBUG uint16_t readU16a(const void* p) noexcept { return readU16x<ByteOrder::kNative, 2>(p); } +static ASMJIT_INLINE_NODEBUG uint16_t readU16aLE(const void* p) noexcept { return readU16x<ByteOrder::kLE, 2>(p); } +static ASMJIT_INLINE_NODEBUG uint16_t readU16aBE(const void* p) noexcept { return readU16x<ByteOrder::kBE, 2>(p); } template<ByteOrder BO, size_t Alignment> -static inline int16_t readI16x(const void* p) noexcept { return int16_t(readU16x<BO, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int16_t readI16x(const void* p) noexcept { return int16_t(readU16x<BO, Alignment>(p)); } template<size_t Alignment = 1> -static inline int16_t readI16u(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kNative, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int16_t readI16u(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kNative, Alignment>(p)); } template<size_t Alignment = 1> -static inline int16_t readI16uLE(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kLE, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int16_t readI16uLE(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kLE, Alignment>(p)); } template<size_t Alignment = 1> -static inline int16_t readI16uBE(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kBE, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int16_t readI16uBE(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kBE, Alignment>(p)); } -static inline int16_t readI16a(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kNative, 2>(p)); } -static inline int16_t readI16aLE(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kLE, 2>(p)); } -static inline int16_t readI16aBE(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kBE, 2>(p)); } +static ASMJIT_INLINE_NODEBUG int16_t readI16a(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kNative, 2>(p)); } +static ASMJIT_INLINE_NODEBUG int16_t readI16aLE(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kLE, 2>(p)); } +static ASMJIT_INLINE_NODEBUG int16_t readI16aBE(const void* p) noexcept { return int16_t(readU16x<ByteOrder::kBE, 2>(p)); } // Support - Memory Read Access - 24 Bits // ====================================== template<ByteOrder BO = ByteOrder::kNative> static inline uint32_t readU24u(const void* p) noexcept { - uint32_t b0 = readU8(static_cast<const uint8_t*>(p) + (BO == ByteOrder::kLE ? 2 : 0)); - uint32_t b1 = readU8(static_cast<const uint8_t*>(p) + (BO == ByteOrder::kLE ? 1 : 1)); - uint32_t b2 = readU8(static_cast<const uint8_t*>(p) + (BO == ByteOrder::kLE ? 0 : 2)); + uint32_t b0 = readU8(static_cast<const uint8_t*>(p) + (BO == ByteOrder::kLE ? 2u : 0u)); + uint32_t b1 = readU8(static_cast<const uint8_t*>(p) + 1u); + uint32_t b2 = readU8(static_cast<const uint8_t*>(p) + (BO == ByteOrder::kLE ? 0u : 2u)); return (b0 << 16) | (b1 << 8) | b2; } @@ -998,108 +997,108 @@ static inline uint32_t readU24uBE(const void* p) noexcept { return readU24u<Byte // ====================================== template<ByteOrder BO, size_t Alignment> -static inline uint32_t readU32x(const void* p) noexcept { +static ASMJIT_INLINE_NODEBUG uint32_t readU32x(const void* p) noexcept { typedef typename Internal::AliasedUInt<uint32_t, Alignment>::T U32AlignedToN; uint32_t x = static_cast<const U32AlignedToN*>(p)[0]; return BO == ByteOrder::kNative ? x : byteswap32(x); } template<size_t Alignment = 1> -static inline uint32_t readU32u(const void* p) noexcept { return readU32x<ByteOrder::kNative, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint32_t readU32u(const void* p) noexcept { return readU32x<ByteOrder::kNative, Alignment>(p); } template<size_t Alignment = 1> -static inline uint32_t readU32uLE(const void* p) noexcept { return readU32x<ByteOrder::kLE, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint32_t readU32uLE(const void* p) noexcept { return readU32x<ByteOrder::kLE, Alignment>(p); } template<size_t Alignment = 1> -static inline uint32_t readU32uBE(const void* p) noexcept { return readU32x<ByteOrder::kBE, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint32_t readU32uBE(const void* p) noexcept { return readU32x<ByteOrder::kBE, Alignment>(p); } -static inline uint32_t readU32a(const void* p) noexcept { return readU32x<ByteOrder::kNative, 4>(p); } -static inline uint32_t readU32aLE(const void* p) noexcept { return readU32x<ByteOrder::kLE, 4>(p); } -static inline uint32_t readU32aBE(const void* p) noexcept { return readU32x<ByteOrder::kBE, 4>(p); } +static ASMJIT_INLINE_NODEBUG uint32_t readU32a(const void* p) noexcept { return readU32x<ByteOrder::kNative, 4>(p); } +static ASMJIT_INLINE_NODEBUG uint32_t readU32aLE(const void* p) noexcept { return readU32x<ByteOrder::kLE, 4>(p); } +static ASMJIT_INLINE_NODEBUG uint32_t readU32aBE(const void* p) noexcept { return readU32x<ByteOrder::kBE, 4>(p); } template<ByteOrder BO, size_t Alignment> -static inline uint32_t readI32x(const void* p) noexcept { return int32_t(readU32x<BO, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG uint32_t readI32x(const void* p) noexcept { return int32_t(readU32x<BO, Alignment>(p)); } template<size_t Alignment = 1> -static inline int32_t readI32u(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kNative, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int32_t readI32u(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kNative, Alignment>(p)); } template<size_t Alignment = 1> -static inline int32_t readI32uLE(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kLE, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int32_t readI32uLE(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kLE, Alignment>(p)); } template<size_t Alignment = 1> -static inline int32_t readI32uBE(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kBE, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int32_t readI32uBE(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kBE, Alignment>(p)); } -static inline int32_t readI32a(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kNative, 4>(p)); } -static inline int32_t readI32aLE(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kLE, 4>(p)); } -static inline int32_t readI32aBE(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kBE, 4>(p)); } +static ASMJIT_INLINE_NODEBUG int32_t readI32a(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kNative, 4>(p)); } +static ASMJIT_INLINE_NODEBUG int32_t readI32aLE(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kLE, 4>(p)); } +static ASMJIT_INLINE_NODEBUG int32_t readI32aBE(const void* p) noexcept { return int32_t(readU32x<ByteOrder::kBE, 4>(p)); } // Support - Memory Read Access - 64 Bits // ====================================== template<ByteOrder BO, size_t Alignment> -static inline uint64_t readU64x(const void* p) noexcept { +static ASMJIT_INLINE_NODEBUG uint64_t readU64x(const void* p) noexcept { typedef typename Internal::AliasedUInt<uint64_t, Alignment>::T U64AlignedToN; uint64_t x = static_cast<const U64AlignedToN*>(p)[0]; return BO == ByteOrder::kNative ? x : byteswap64(x); } template<size_t Alignment = 1> -static inline uint64_t readU64u(const void* p) noexcept { return readU64x<ByteOrder::kNative, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint64_t readU64u(const void* p) noexcept { return readU64x<ByteOrder::kNative, Alignment>(p); } template<size_t Alignment = 1> -static inline uint64_t readU64uLE(const void* p) noexcept { return readU64x<ByteOrder::kLE, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint64_t readU64uLE(const void* p) noexcept { return readU64x<ByteOrder::kLE, Alignment>(p); } template<size_t Alignment = 1> -static inline uint64_t readU64uBE(const void* p) noexcept { return readU64x<ByteOrder::kBE, Alignment>(p); } +static ASMJIT_INLINE_NODEBUG uint64_t readU64uBE(const void* p) noexcept { return readU64x<ByteOrder::kBE, Alignment>(p); } -static inline uint64_t readU64a(const void* p) noexcept { return readU64x<ByteOrder::kNative, 8>(p); } -static inline uint64_t readU64aLE(const void* p) noexcept { return readU64x<ByteOrder::kLE, 8>(p); } -static inline uint64_t readU64aBE(const void* p) noexcept { return readU64x<ByteOrder::kBE, 8>(p); } +static ASMJIT_INLINE_NODEBUG uint64_t readU64a(const void* p) noexcept { return readU64x<ByteOrder::kNative, 8>(p); } +static ASMJIT_INLINE_NODEBUG uint64_t readU64aLE(const void* p) noexcept { return readU64x<ByteOrder::kLE, 8>(p); } +static ASMJIT_INLINE_NODEBUG uint64_t readU64aBE(const void* p) noexcept { return readU64x<ByteOrder::kBE, 8>(p); } template<ByteOrder BO, size_t Alignment> -static inline int64_t readI64x(const void* p) noexcept { return int64_t(readU64x<BO, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int64_t readI64x(const void* p) noexcept { return int64_t(readU64x<BO, Alignment>(p)); } template<size_t Alignment = 1> -static inline int64_t readI64u(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kNative, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int64_t readI64u(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kNative, Alignment>(p)); } template<size_t Alignment = 1> -static inline int64_t readI64uLE(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kLE, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int64_t readI64uLE(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kLE, Alignment>(p)); } template<size_t Alignment = 1> -static inline int64_t readI64uBE(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kBE, Alignment>(p)); } +static ASMJIT_INLINE_NODEBUG int64_t readI64uBE(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kBE, Alignment>(p)); } -static inline int64_t readI64a(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kNative, 8>(p)); } -static inline int64_t readI64aLE(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kLE, 8>(p)); } -static inline int64_t readI64aBE(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kBE, 8>(p)); } +static ASMJIT_INLINE_NODEBUG int64_t readI64a(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kNative, 8>(p)); } +static ASMJIT_INLINE_NODEBUG int64_t readI64aLE(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kLE, 8>(p)); } +static ASMJIT_INLINE_NODEBUG int64_t readI64aBE(const void* p) noexcept { return int64_t(readU64x<ByteOrder::kBE, 8>(p)); } // Support - Memory Write Access - 8 Bits // ====================================== -static inline void writeU8(void* p, uint8_t x) noexcept { static_cast<uint8_t*>(p)[0] = x; } -static inline void writeI8(void* p, int8_t x) noexcept { static_cast<int8_t*>(p)[0] = x; } +static ASMJIT_INLINE_NODEBUG void writeU8(void* p, uint8_t x) noexcept { static_cast<uint8_t*>(p)[0] = x; } +static ASMJIT_INLINE_NODEBUG void writeI8(void* p, int8_t x) noexcept { static_cast<int8_t*>(p)[0] = x; } // Support - Memory Write Access - 16 Bits // ======================================= template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> -static inline void writeU16x(void* p, uint16_t x) noexcept { +static ASMJIT_INLINE_NODEBUG void writeU16x(void* p, uint16_t x) noexcept { typedef typename Internal::AliasedUInt<uint16_t, Alignment>::T U16AlignedToN; static_cast<U16AlignedToN*>(p)[0] = BO == ByteOrder::kNative ? x : byteswap16(x); } template<size_t Alignment = 1> -static inline void writeU16uLE(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kLE, Alignment>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU16uLE(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kLE, Alignment>(p, x); } template<size_t Alignment = 1> -static inline void writeU16uBE(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kBE, Alignment>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU16uBE(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kBE, Alignment>(p, x); } -static inline void writeU16a(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kNative, 2>(p, x); } -static inline void writeU16aLE(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kLE, 2>(p, x); } -static inline void writeU16aBE(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kBE, 2>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU16a(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kNative, 2>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU16aLE(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kLE, 2>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU16aBE(void* p, uint16_t x) noexcept { writeU16x<ByteOrder::kBE, 2>(p, x); } template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> -static inline void writeI16x(void* p, int16_t x) noexcept { writeU16x<BO, Alignment>(p, uint16_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI16x(void* p, int16_t x) noexcept { writeU16x<BO, Alignment>(p, uint16_t(x)); } template<size_t Alignment = 1> -static inline void writeI16uLE(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kLE, Alignment>(p, uint16_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI16uLE(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kLE, Alignment>(p, uint16_t(x)); } template<size_t Alignment = 1> -static inline void writeI16uBE(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kBE, Alignment>(p, uint16_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI16uBE(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kBE, Alignment>(p, uint16_t(x)); } -static inline void writeI16a(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kNative, 2>(p, uint16_t(x)); } -static inline void writeI16aLE(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kLE, 2>(p, uint16_t(x)); } -static inline void writeI16aBE(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kBE, 2>(p, uint16_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI16a(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kNative, 2>(p, uint16_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI16aLE(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kLE, 2>(p, uint16_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI16aBE(void* p, int16_t x) noexcept { writeU16x<ByteOrder::kBE, 2>(p, uint16_t(x)); } // Support - Memory Write Access - 24 Bits // ======================================= @@ -1107,7 +1106,7 @@ static inline void writeI16aBE(void* p, int16_t x) noexcept { writeU16x<ByteOrde template<ByteOrder BO = ByteOrder::kNative> static inline void writeU24u(void* p, uint32_t v) noexcept { static_cast<uint8_t*>(p)[0] = uint8_t((v >> (BO == ByteOrder::kLE ? 0 : 16)) & 0xFFu); - static_cast<uint8_t*>(p)[1] = uint8_t((v >> (BO == ByteOrder::kLE ? 8 : 8)) & 0xFFu); + static_cast<uint8_t*>(p)[1] = uint8_t((v >> 8) & 0xFFu); static_cast<uint8_t*>(p)[2] = uint8_t((v >> (BO == ByteOrder::kLE ? 16 : 0)) & 0xFFu); } @@ -1118,85 +1117,85 @@ static inline void writeU24uBE(void* p, uint32_t v) noexcept { writeU24u<ByteOrd // ======================================= template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> -static inline void writeU32x(void* p, uint32_t x) noexcept { +static ASMJIT_INLINE_NODEBUG void writeU32x(void* p, uint32_t x) noexcept { typedef typename Internal::AliasedUInt<uint32_t, Alignment>::T U32AlignedToN; static_cast<U32AlignedToN*>(p)[0] = (BO == ByteOrder::kNative) ? x : Support::byteswap32(x); } template<size_t Alignment = 1> -static inline void writeU32u(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kNative, Alignment>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU32u(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kNative, Alignment>(p, x); } template<size_t Alignment = 1> -static inline void writeU32uLE(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kLE, Alignment>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU32uLE(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kLE, Alignment>(p, x); } template<size_t Alignment = 1> -static inline void writeU32uBE(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kBE, Alignment>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU32uBE(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kBE, Alignment>(p, x); } -static inline void writeU32a(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kNative, 4>(p, x); } -static inline void writeU32aLE(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kLE, 4>(p, x); } -static inline void writeU32aBE(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kBE, 4>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU32a(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kNative, 4>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU32aLE(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kLE, 4>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU32aBE(void* p, uint32_t x) noexcept { writeU32x<ByteOrder::kBE, 4>(p, x); } template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> -static inline void writeI32x(void* p, int32_t x) noexcept { writeU32x<BO, Alignment>(p, uint32_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI32x(void* p, int32_t x) noexcept { writeU32x<BO, Alignment>(p, uint32_t(x)); } template<size_t Alignment = 1> -static inline void writeI32u(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kNative, Alignment>(p, uint32_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI32u(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kNative, Alignment>(p, uint32_t(x)); } template<size_t Alignment = 1> -static inline void writeI32uLE(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kLE, Alignment>(p, uint32_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI32uLE(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kLE, Alignment>(p, uint32_t(x)); } template<size_t Alignment = 1> -static inline void writeI32uBE(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kBE, Alignment>(p, uint32_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI32uBE(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kBE, Alignment>(p, uint32_t(x)); } -static inline void writeI32a(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kNative, 4>(p, uint32_t(x)); } -static inline void writeI32aLE(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kLE, 4>(p, uint32_t(x)); } -static inline void writeI32aBE(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kBE, 4>(p, uint32_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI32a(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kNative, 4>(p, uint32_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI32aLE(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kLE, 4>(p, uint32_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI32aBE(void* p, int32_t x) noexcept { writeU32x<ByteOrder::kBE, 4>(p, uint32_t(x)); } // Support - Memory Write Access - 64 Bits // ======================================= template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> -static inline void writeU64x(void* p, uint64_t x) noexcept { +static ASMJIT_INLINE_NODEBUG void writeU64x(void* p, uint64_t x) noexcept { typedef typename Internal::AliasedUInt<uint64_t, Alignment>::T U64AlignedToN; static_cast<U64AlignedToN*>(p)[0] = BO == ByteOrder::kNative ? x : byteswap64(x); } template<size_t Alignment = 1> -static inline void writeU64u(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kNative, Alignment>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU64u(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kNative, Alignment>(p, x); } template<size_t Alignment = 1> -static inline void writeU64uLE(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kLE, Alignment>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU64uLE(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kLE, Alignment>(p, x); } template<size_t Alignment = 1> -static inline void writeU64uBE(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kBE, Alignment>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU64uBE(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kBE, Alignment>(p, x); } -static inline void writeU64a(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kNative, 8>(p, x); } -static inline void writeU64aLE(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kLE, 8>(p, x); } -static inline void writeU64aBE(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kBE, 8>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU64a(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kNative, 8>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU64aLE(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kLE, 8>(p, x); } +static ASMJIT_INLINE_NODEBUG void writeU64aBE(void* p, uint64_t x) noexcept { writeU64x<ByteOrder::kBE, 8>(p, x); } template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> -static inline void writeI64x(void* p, int64_t x) noexcept { writeU64x<BO, Alignment>(p, uint64_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI64x(void* p, int64_t x) noexcept { writeU64x<BO, Alignment>(p, uint64_t(x)); } template<size_t Alignment = 1> -static inline void writeI64u(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kNative, Alignment>(p, uint64_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI64u(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kNative, Alignment>(p, uint64_t(x)); } template<size_t Alignment = 1> -static inline void writeI64uLE(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kLE, Alignment>(p, uint64_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI64uLE(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kLE, Alignment>(p, uint64_t(x)); } template<size_t Alignment = 1> -static inline void writeI64uBE(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kBE, Alignment>(p, uint64_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI64uBE(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kBE, Alignment>(p, uint64_t(x)); } -static inline void writeI64a(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kNative, 8>(p, uint64_t(x)); } -static inline void writeI64aLE(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kLE, 8>(p, uint64_t(x)); } -static inline void writeI64aBE(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kBE, 8>(p, uint64_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI64a(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kNative, 8>(p, uint64_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI64aLE(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kLE, 8>(p, uint64_t(x)); } +static ASMJIT_INLINE_NODEBUG void writeI64aBE(void* p, int64_t x) noexcept { writeU64x<ByteOrder::kBE, 8>(p, uint64_t(x)); } // Support - Operators // =================== //! \cond INTERNAL -struct Set { template<typename T> static inline T op(T x, T y) noexcept { DebugUtils::unused(x); return y; } }; -struct SetNot { template<typename T> static inline T op(T x, T y) noexcept { DebugUtils::unused(x); return ~y; } }; -struct And { template<typename T> static inline T op(T x, T y) noexcept { return x & y; } }; -struct AndNot { template<typename T> static inline T op(T x, T y) noexcept { return x & ~y; } }; -struct NotAnd { template<typename T> static inline T op(T x, T y) noexcept { return ~x & y; } }; -struct Or { template<typename T> static inline T op(T x, T y) noexcept { return x | y; } }; -struct Xor { template<typename T> static inline T op(T x, T y) noexcept { return x ^ y; } }; -struct Add { template<typename T> static inline T op(T x, T y) noexcept { return x + y; } }; -struct Sub { template<typename T> static inline T op(T x, T y) noexcept { return x - y; } }; -struct Min { template<typename T> static inline T op(T x, T y) noexcept { return min<T>(x, y); } }; -struct Max { template<typename T> static inline T op(T x, T y) noexcept { return max<T>(x, y); } }; +struct Set { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { DebugUtils::unused(x); return y; } }; +struct SetNot { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { DebugUtils::unused(x); return ~y; } }; +struct And { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return x & y; } }; +struct AndNot { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return x & ~y; } }; +struct NotAnd { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return ~x & y; } }; +struct Or { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return x | y; } }; +struct Xor { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return x ^ y; } }; +struct Add { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return x + y; } }; +struct Sub { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return x - y; } }; +struct Min { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return min<T>(x, y); } }; +struct Max { template<typename T> static ASMJIT_INLINE_NODEBUG T op(T x, T y) noexcept { return max<T>(x, y); } }; //! \endcond // Support - BitWordIterator @@ -1218,43 +1217,20 @@ struct Max { template<typename T> static inline T op(T x, T y) noexcept { ret template<typename T> class BitWordIterator { public: - ASMJIT_FORCE_INLINE explicit BitWordIterator(T bitWord) noexcept + ASMJIT_INLINE_NODEBUG explicit BitWordIterator(T bitWord) noexcept : _bitWord(bitWord) {} - ASMJIT_FORCE_INLINE void init(T bitWord) noexcept { _bitWord = bitWord; } - ASMJIT_FORCE_INLINE bool hasNext() const noexcept { return _bitWord != 0; } + ASMJIT_INLINE_NODEBUG void init(T bitWord) noexcept { _bitWord = bitWord; } + ASMJIT_INLINE_NODEBUG bool hasNext() const noexcept { return _bitWord != 0; } ASMJIT_FORCE_INLINE uint32_t next() noexcept { ASMJIT_ASSERT(_bitWord != 0); uint32_t index = ctz(_bitWord); - _bitWord ^= T(1u) << index; - return index; - } - - T _bitWord; -}; - -// Support - BitWordFlipIterator -// ============================= - -template<typename T> -class BitWordFlipIterator { -public: - ASMJIT_FORCE_INLINE explicit BitWordFlipIterator(T bitWord) noexcept - : _bitWord(bitWord) {} - - ASMJIT_FORCE_INLINE void init(T bitWord) noexcept { _bitWord = bitWord; } - ASMJIT_FORCE_INLINE bool hasNext() const noexcept { return _bitWord != 0; } - - ASMJIT_FORCE_INLINE uint32_t nextAndFlip() noexcept { - ASMJIT_ASSERT(_bitWord != 0); - uint32_t index = ctz(_bitWord); - _bitWord ^= T(1u) << index; + _bitWord &= T(_bitWord - 1); return index; } T _bitWord; - T _xorMask; }; // Support - BitVectorOps @@ -1263,7 +1239,7 @@ public: //! \cond namespace Internal { template<typename T, class OperatorT, class FullWordOpT> - static inline void bitVectorOp(T* buf, size_t index, size_t count) noexcept { + static ASMJIT_FORCE_INLINE void bitVectorOp(T* buf, size_t index, size_t count) noexcept { if (count == 0) return; @@ -1297,7 +1273,7 @@ namespace Internal { //! Sets bit in a bit-vector `buf` at `index`. template<typename T> -static inline bool bitVectorGetBit(T* buf, size_t index) noexcept { +static ASMJIT_INLINE_NODEBUG bool bitVectorGetBit(T* buf, size_t index) noexcept { const size_t kTSizeInBits = bitSizeOf<T>(); size_t vecIndex = index / kTSizeInBits; @@ -1308,7 +1284,7 @@ static inline bool bitVectorGetBit(T* buf, size_t index) noexcept { //! Sets bit in a bit-vector `buf` at `index` to `value`. template<typename T> -static inline void bitVectorSetBit(T* buf, size_t index, bool value) noexcept { +static ASMJIT_INLINE_NODEBUG void bitVectorSetBit(T* buf, size_t index, bool value) noexcept { const size_t kTSizeInBits = bitSizeOf<T>(); size_t vecIndex = index / kTSizeInBits; @@ -1323,7 +1299,7 @@ static inline void bitVectorSetBit(T* buf, size_t index, bool value) noexcept { //! Sets bit in a bit-vector `buf` at `index` to `value`. template<typename T> -static inline void bitVectorFlipBit(T* buf, size_t index) noexcept { +static ASMJIT_INLINE_NODEBUG void bitVectorFlipBit(T* buf, size_t index) noexcept { const size_t kTSizeInBits = bitSizeOf<T>(); size_t vecIndex = index / kTSizeInBits; @@ -1335,14 +1311,14 @@ static inline void bitVectorFlipBit(T* buf, size_t index) noexcept { //! Fills `count` bits in bit-vector `buf` starting at bit-index `index`. template<typename T> -static inline void bitVectorFill(T* buf, size_t index, size_t count) noexcept { Internal::bitVectorOp<T, Or, Set>(buf, index, count); } +static ASMJIT_INLINE_NODEBUG void bitVectorFill(T* buf, size_t index, size_t count) noexcept { Internal::bitVectorOp<T, Or, Set>(buf, index, count); } //! Clears `count` bits in bit-vector `buf` starting at bit-index `index`. template<typename T> -static inline void bitVectorClear(T* buf, size_t index, size_t count) noexcept { Internal::bitVectorOp<T, AndNot, SetNot>(buf, index, count); } +static ASMJIT_INLINE_NODEBUG void bitVectorClear(T* buf, size_t index, size_t count) noexcept { Internal::bitVectorOp<T, AndNot, SetNot>(buf, index, count); } template<typename T> -static inline size_t bitVectorIndexOf(T* buf, size_t start, bool value) noexcept { +static ASMJIT_FORCE_INLINE size_t bitVectorIndexOf(T* buf, size_t start, bool value) noexcept { const size_t kTSizeInBits = bitSizeOf<T>(); size_t vecIndex = start / kTSizeInBits; // T[] size_t bitIndex = start % kTSizeInBits; // T[][] @@ -1373,9 +1349,9 @@ public: size_t _end; T _current; - ASMJIT_FORCE_INLINE BitVectorIterator(const BitVectorIterator& other) noexcept = default; + ASMJIT_INLINE_NODEBUG BitVectorIterator(const BitVectorIterator& other) noexcept = default; - ASMJIT_FORCE_INLINE BitVectorIterator(const T* data, size_t numBitWords, size_t start = 0) noexcept { + ASMJIT_INLINE_NODEBUG BitVectorIterator(const T* data, size_t numBitWords, size_t start = 0) noexcept { init(data, numBitWords, start); } @@ -1397,7 +1373,7 @@ public: _current = bitWord; } - ASMJIT_FORCE_INLINE bool hasNext() const noexcept { + ASMJIT_INLINE_NODEBUG bool hasNext() const noexcept { return _current != T(0); } @@ -1406,7 +1382,7 @@ public: ASMJIT_ASSERT(bitWord != T(0)); uint32_t bit = ctz(bitWord); - bitWord ^= T(1u) << bit; + bitWord &= T(bitWord - 1u); size_t n = _idx + bit; while (!bitWord && (_idx += bitSizeOf<T>()) < _end) @@ -1438,7 +1414,7 @@ public: size_t _end; T _current; - ASMJIT_FORCE_INLINE BitVectorOpIterator(const T* aData, const T* bData, size_t numBitWords, size_t start = 0) noexcept { + ASMJIT_INLINE_NODEBUG BitVectorOpIterator(const T* aData, const T* bData, size_t numBitWords, size_t start = 0) noexcept { init(aData, bData, numBitWords, start); } @@ -1462,7 +1438,7 @@ public: _current = bitWord; } - ASMJIT_FORCE_INLINE bool hasNext() noexcept { + ASMJIT_INLINE_NODEBUG bool hasNext() noexcept { return _current != T(0); } @@ -1471,7 +1447,7 @@ public: ASMJIT_ASSERT(bitWord != T(0)); uint32_t bit = ctz(bitWord); - bitWord ^= T(1u) << bit; + bitWord &= T(bitWord - 1u); size_t n = _idx + bit; while (!bitWord && (_idx += kTSizeInBits) < _end) @@ -1498,7 +1474,7 @@ enum class SortOrder : uint32_t { template<SortOrder kOrder = SortOrder::kAscending> struct Compare { template<typename A, typename B> - inline int operator()(const A& a, const B& b) const noexcept { + ASMJIT_INLINE_NODEBUG int operator()(const A& a, const B& b) const noexcept { return kOrder == SortOrder::kAscending ? int(a > b) - int(a < b) : int(a < b) - int(a > b); } }; @@ -1587,10 +1563,79 @@ namespace Internal { //! The main reason to provide a custom qsort implementation is that we needed something that will //! never throw `bad_alloc` exception. This implementation doesn't use dynamic memory allocation. template<typename T, class CompareT = Compare<SortOrder::kAscending>> -static inline void qSort(T* base, size_t size, const CompareT& cmp = CompareT()) noexcept { +static ASMJIT_INLINE_NODEBUG void qSort(T* base, size_t size, const CompareT& cmp = CompareT()) noexcept { Internal::QSortImpl<T, CompareT>::sort(base, size, cmp); } +// Support - ReverseIterator +// ========================= + +//! Reverse iterator to avoid including `<iterator>` header for iteration over arrays, specialized for +//! AsmJit use (noexcept by design). +template<typename T> +class ArrayReverseIterator { +public: + //! \name Members + //! \{ + + T* _ptr {}; + + //! \} + + //! \name Construction & Destruction + //! \{ + + ASMJIT_INLINE_NODEBUG constexpr ArrayReverseIterator() noexcept = default; + ASMJIT_INLINE_NODEBUG constexpr ArrayReverseIterator(const ArrayReverseIterator& other) noexcept = default; + ASMJIT_INLINE_NODEBUG constexpr ArrayReverseIterator(T* ptr) noexcept : _ptr(ptr) {} + + //! \} + + //! \name Overloaded Operators + //! \{ + + ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator=(const ArrayReverseIterator& other) noexcept = default; + + ASMJIT_INLINE_NODEBUG bool operator==(const T* other) const noexcept { return _ptr == other; } + ASMJIT_INLINE_NODEBUG bool operator==(const ArrayReverseIterator& other) const noexcept { return _ptr == other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator!=(const T* other) const noexcept { return _ptr != other; } + ASMJIT_INLINE_NODEBUG bool operator!=(const ArrayReverseIterator& other) const noexcept { return _ptr != other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator<(const T* other) const noexcept { return _ptr < other; } + ASMJIT_INLINE_NODEBUG bool operator<(const ArrayReverseIterator& other) const noexcept { return _ptr < other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator<=(const T* other) const noexcept { return _ptr <= other; } + ASMJIT_INLINE_NODEBUG bool operator<=(const ArrayReverseIterator& other) const noexcept { return _ptr <= other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator>(const T* other) const noexcept { return _ptr > other; } + ASMJIT_INLINE_NODEBUG bool operator>(const ArrayReverseIterator& other) const noexcept { return _ptr > other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator>=(const T* other) const noexcept { return _ptr >= other; } + ASMJIT_INLINE_NODEBUG bool operator>=(const ArrayReverseIterator& other) const noexcept { return _ptr >= other._ptr; } + + ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator++() noexcept { _ptr--; return *this; } + ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator--() noexcept { _ptr++; return *this; } + + ASMJIT_INLINE_NODEBUG ArrayReverseIterator operator++(int) noexcept { ArrayReverseIterator prev(*this); _ptr--; return prev; } + ASMJIT_INLINE_NODEBUG ArrayReverseIterator operator--(int) noexcept { ArrayReverseIterator prev(*this); _ptr++; return prev; } + + template<typename Diff> ASMJIT_INLINE_NODEBUG ArrayReverseIterator operator+(const Diff& n) noexcept { return ArrayReverseIterator(_ptr -= n); } + template<typename Diff> ASMJIT_INLINE_NODEBUG ArrayReverseIterator operator-(const Diff& n) noexcept { return ArrayReverseIterator(_ptr += n); } + + template<typename Diff> ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator+=(const Diff& n) noexcept { _ptr -= n; return *this; } + template<typename Diff> ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator-=(const Diff& n) noexcept { _ptr += n; return *this; } + + ASMJIT_INLINE_NODEBUG constexpr T& operator*() const noexcept { return _ptr[-1]; } + ASMJIT_INLINE_NODEBUG constexpr T* operator->() const noexcept { return &_ptr[-1]; } + + template<typename Diff> ASMJIT_INLINE_NODEBUG T& operator[](const Diff& n) noexcept { return *(_ptr - n - 1); } + + ASMJIT_INLINE_NODEBUG operator T*() const noexcept { return _ptr; } + + //! \} +}; + // Support - Array // =============== @@ -1656,26 +1701,26 @@ struct Array { //! \name Accessors //! \{ - inline bool empty() const noexcept { return false; } - inline size_t size() const noexcept { return N; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return false; } + ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return N; } - inline T* data() noexcept { return _data; } - inline const T* data() const noexcept { return _data; } + ASMJIT_INLINE_NODEBUG T* data() noexcept { return _data; } + ASMJIT_INLINE_NODEBUG const T* data() const noexcept { return _data; } - inline T& front() noexcept { return _data[0]; } - inline const T& front() const noexcept { return _data[0]; } + ASMJIT_INLINE_NODEBUG T& front() noexcept { return _data[0]; } + ASMJIT_INLINE_NODEBUG const T& front() const noexcept { return _data[0]; } - inline T& back() noexcept { return _data[N - 1]; } - inline const T& back() const noexcept { return _data[N - 1]; } + ASMJIT_INLINE_NODEBUG T& back() noexcept { return _data[N - 1]; } + ASMJIT_INLINE_NODEBUG const T& back() const noexcept { return _data[N - 1]; } - inline T* begin() noexcept { return _data; } - inline T* end() noexcept { return _data + N; } + ASMJIT_INLINE_NODEBUG T* begin() noexcept { return _data; } + ASMJIT_INLINE_NODEBUG T* end() noexcept { return _data + N; } - inline const T* begin() const noexcept { return _data; } - inline const T* end() const noexcept { return _data + N; } + ASMJIT_INLINE_NODEBUG const T* begin() const noexcept { return _data; } + ASMJIT_INLINE_NODEBUG const T* end() const noexcept { return _data + N; } - inline const T* cbegin() const noexcept { return _data; } - inline const T* cend() const noexcept { return _data + N; } + ASMJIT_INLINE_NODEBUG const T* cbegin() const noexcept { return _data; } + ASMJIT_INLINE_NODEBUG const T* cend() const noexcept { return _data + N; } //! \} @@ -1738,8 +1783,8 @@ struct Temporary { //! \name Construction & Destruction //! \{ - inline constexpr Temporary(const Temporary& other) noexcept = default; - inline constexpr Temporary(void* data, size_t size) noexcept + ASMJIT_INLINE_NODEBUG constexpr Temporary(const Temporary& other) noexcept = default; + ASMJIT_INLINE_NODEBUG constexpr Temporary(void* data, size_t size) noexcept : _data(data), _size(size) {} @@ -1748,7 +1793,7 @@ struct Temporary { //! \name Overloaded Operators //! \{ - inline Temporary& operator=(const Temporary& other) noexcept = default; + ASMJIT_INLINE_NODEBUG Temporary& operator=(const Temporary& other) noexcept = default; //! \} @@ -1757,9 +1802,9 @@ struct Temporary { //! Returns the data storage. template<typename T = void> - inline constexpr T* data() const noexcept { return static_cast<T*>(_data); } + ASMJIT_INLINE_NODEBUG constexpr T* data() const noexcept { return static_cast<T*>(_data); } //! Returns the data storage size in bytes. - inline constexpr size_t size() const noexcept { return _size; } + ASMJIT_INLINE_NODEBUG constexpr size_t size() const noexcept { return _size; } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/support_p.h b/3rdparty/asmjit/src/asmjit/core/support_p.h new file mode 100644 index 00000000000..1caec9344a4 --- /dev/null +++ b/3rdparty/asmjit/src/asmjit/core/support_p.h @@ -0,0 +1,27 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_CORE_SUPPORT_P_H_INCLUDED +#define ASMJIT_CORE_SUPPORT_P_H_INCLUDED + +#include "../core/support.h" + +ASMJIT_BEGIN_NAMESPACE + +//! \addtogroup asmjit_utilities +//! \{ + +namespace Support { + +//! \cond INTERNAL +//! \endcond + +} // {Support} + +//! \} + +ASMJIT_END_NAMESPACE + +#endif // ASMJIT_CORE_SUPPORT_P_H_INCLUDED diff --git a/3rdparty/asmjit/src/asmjit/core/target.cpp b/3rdparty/asmjit/src/asmjit/core/target.cpp index fef025d709a..cbc6ab51092 100644 --- a/3rdparty/asmjit/src/asmjit/core/target.cpp +++ b/3rdparty/asmjit/src/asmjit/core/target.cpp @@ -8,7 +8,9 @@ ASMJIT_BEGIN_NAMESPACE -Target::Target() noexcept : _environment() {} +Target::Target() noexcept + : _environment{}, + _cpuFeatures{} {} Target::~Target() noexcept {} ASMJIT_END_NAMESPACE diff --git a/3rdparty/asmjit/src/asmjit/core/target.h b/3rdparty/asmjit/src/asmjit/core/target.h index 23b0c6294c9..4365be14011 100644 --- a/3rdparty/asmjit/src/asmjit/core/target.h +++ b/3rdparty/asmjit/src/asmjit/core/target.h @@ -7,6 +7,7 @@ #define ASMJIT_CORE_TARGET_H_INCLUDED #include "../core/archtraits.h" +#include "../core/cpuinfo.h" #include "../core/func.h" ASMJIT_BEGIN_NAMESPACE @@ -22,6 +23,8 @@ public: //! Target environment information. Environment _environment; + //! Target CPU features. + CpuFeatures _cpuFeatures; //! \name Construction & Destruction //! \{ @@ -37,11 +40,14 @@ public: //! \{ //! Returns target's environment. - inline const Environment& environment() const noexcept { return _environment; } + ASMJIT_INLINE_NODEBUG const Environment& environment() const noexcept { return _environment; } //! Returns the target architecture. - inline Arch arch() const noexcept { return _environment.arch(); } + ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _environment.arch(); } //! Returns the target sub-architecture. - inline SubArch subArch() const noexcept { return _environment.subArch(); } + ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return _environment.subArch(); } + + //! Returns target CPU features. + ASMJIT_INLINE_NODEBUG const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/type.h b/3rdparty/asmjit/src/asmjit/core/type.h index 3754959e4c3..415fe0a421d 100644 --- a/3rdparty/asmjit/src/asmjit/core/type.h +++ b/3rdparty/asmjit/src/asmjit/core/type.h @@ -164,74 +164,98 @@ struct TypeData { ASMJIT_VARAPI const TypeData _typeData; //! Returns the scalar type of `typeId`. -static inline TypeId scalarOf(TypeId typeId) noexcept { return _typeData.scalarOf[uint32_t(typeId)]; } +static ASMJIT_INLINE_NODEBUG TypeId scalarOf(TypeId typeId) noexcept { return _typeData.scalarOf[uint32_t(typeId)]; } //! Returns the size [in bytes] of `typeId`. -static inline uint32_t sizeOf(TypeId typeId) noexcept { return _typeData.sizeOf[uint32_t(typeId)]; } +static ASMJIT_INLINE_NODEBUG uint32_t sizeOf(TypeId typeId) noexcept { return _typeData.sizeOf[uint32_t(typeId)]; } //! Tests whether a given type `typeId` is between `a` and `b`. -static inline constexpr bool isBetween(TypeId typeId, TypeId a, TypeId b) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr bool isBetween(TypeId typeId, TypeId a, TypeId b) noexcept { return Support::isBetween(uint32_t(typeId), uint32_t(a), uint32_t(b)); } //! Tests whether a given type `typeId` is \ref TypeId::kVoid. -static inline constexpr bool isVoid(TypeId typeId) noexcept { return typeId == TypeId::kVoid; } +static ASMJIT_INLINE_NODEBUG constexpr bool isVoid(TypeId typeId) noexcept { return typeId == TypeId::kVoid; } //! Tests whether a given type `typeId` is a valid non-void type. -static inline constexpr bool isValid(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kVec512End); } +static ASMJIT_INLINE_NODEBUG constexpr bool isValid(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kVec512End); } //! Tests whether a given type `typeId` is scalar (has no vector part). -static inline constexpr bool isScalar(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kBaseStart, TypeId::_kBaseEnd); } +static ASMJIT_INLINE_NODEBUG constexpr bool isScalar(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kBaseStart, TypeId::_kBaseEnd); } //! Tests whether a given type `typeId` is abstract, which means that its size depends on register size. -static inline constexpr bool isAbstract(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kIntPtr, TypeId::kUIntPtr); } +static ASMJIT_INLINE_NODEBUG constexpr bool isAbstract(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kIntPtr, TypeId::kUIntPtr); } //! Tests whether a given type is a scalar integer (signed or unsigned) of any size. -static inline constexpr bool isInt(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kIntEnd); } +static ASMJIT_INLINE_NODEBUG constexpr bool isInt(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kIntEnd); } //! Tests whether a given type is a scalar 8-bit integer (signed). -static inline constexpr bool isInt8(TypeId typeId) noexcept { return typeId == TypeId::kInt8; } +static ASMJIT_INLINE_NODEBUG constexpr bool isInt8(TypeId typeId) noexcept { return typeId == TypeId::kInt8; } //! Tests whether a given type is a scalar 8-bit integer (unsigned). -static inline constexpr bool isUInt8(TypeId typeId) noexcept { return typeId == TypeId::kUInt8; } +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt8(TypeId typeId) noexcept { return typeId == TypeId::kUInt8; } //! Tests whether a given type is a scalar 16-bit integer (signed). -static inline constexpr bool isInt16(TypeId typeId) noexcept { return typeId == TypeId::kInt16; } +static ASMJIT_INLINE_NODEBUG constexpr bool isInt16(TypeId typeId) noexcept { return typeId == TypeId::kInt16; } //! Tests whether a given type is a scalar 16-bit integer (unsigned). -static inline constexpr bool isUInt16(TypeId typeId) noexcept { return typeId == TypeId::kUInt16; } +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt16(TypeId typeId) noexcept { return typeId == TypeId::kUInt16; } //! Tests whether a given type is a scalar 32-bit integer (signed). -static inline constexpr bool isInt32(TypeId typeId) noexcept { return typeId == TypeId::kInt32; } +static ASMJIT_INLINE_NODEBUG constexpr bool isInt32(TypeId typeId) noexcept { return typeId == TypeId::kInt32; } //! Tests whether a given type is a scalar 32-bit integer (unsigned). -static inline constexpr bool isUInt32(TypeId typeId) noexcept { return typeId == TypeId::kUInt32; } +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt32(TypeId typeId) noexcept { return typeId == TypeId::kUInt32; } //! Tests whether a given type is a scalar 64-bit integer (signed). -static inline constexpr bool isInt64(TypeId typeId) noexcept { return typeId == TypeId::kInt64; } +static ASMJIT_INLINE_NODEBUG constexpr bool isInt64(TypeId typeId) noexcept { return typeId == TypeId::kInt64; } //! Tests whether a given type is a scalar 64-bit integer (unsigned). -static inline constexpr bool isUInt64(TypeId typeId) noexcept { return typeId == TypeId::kUInt64; } +static ASMJIT_INLINE_NODEBUG constexpr bool isUInt64(TypeId typeId) noexcept { return typeId == TypeId::kUInt64; } -static inline constexpr bool isGp8(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt8, TypeId::kUInt8); } -static inline constexpr bool isGp16(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt16, TypeId::kUInt16); } -static inline constexpr bool isGp32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt32, TypeId::kUInt32); } -static inline constexpr bool isGp64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt64, TypeId::kUInt64); } +//! Tests whether a given type is an 8-bit general purpose register representing either signed or unsigned 8-bit integer. +static ASMJIT_INLINE_NODEBUG constexpr bool isGp8(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt8, TypeId::kUInt8); } +//! Tests whether a given type is a 16-bit general purpose register representing either signed or unsigned 16-bit integer +static ASMJIT_INLINE_NODEBUG constexpr bool isGp16(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt16, TypeId::kUInt16); } +//! Tests whether a given type is a 32-bit general purpose register representing either signed or unsigned 32-bit integer +static ASMJIT_INLINE_NODEBUG constexpr bool isGp32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt32, TypeId::kUInt32); } +//! Tests whether a given type is a 64-bit general purpose register representing either signed or unsigned 64-bit integer +static ASMJIT_INLINE_NODEBUG constexpr bool isGp64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt64, TypeId::kUInt64); } //! Tests whether a given type is a scalar floating point of any size. -static inline constexpr bool isFloat(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kFloatStart, TypeId::_kFloatEnd); } +static ASMJIT_INLINE_NODEBUG constexpr bool isFloat(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kFloatStart, TypeId::_kFloatEnd); } //! Tests whether a given type is a scalar 32-bit float. -static inline constexpr bool isFloat32(TypeId typeId) noexcept { return typeId == TypeId::kFloat32; } +static ASMJIT_INLINE_NODEBUG constexpr bool isFloat32(TypeId typeId) noexcept { return typeId == TypeId::kFloat32; } //! Tests whether a given type is a scalar 64-bit float. -static inline constexpr bool isFloat64(TypeId typeId) noexcept { return typeId == TypeId::kFloat64; } +static ASMJIT_INLINE_NODEBUG constexpr bool isFloat64(TypeId typeId) noexcept { return typeId == TypeId::kFloat64; } //! Tests whether a given type is a scalar 80-bit float. -static inline constexpr bool isFloat80(TypeId typeId) noexcept { return typeId == TypeId::kFloat80; } - -static inline constexpr bool isMask(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMaskStart, TypeId::_kMaskEnd); } -static inline constexpr bool isMask8(TypeId typeId) noexcept { return typeId == TypeId::kMask8; } -static inline constexpr bool isMask16(TypeId typeId) noexcept { return typeId == TypeId::kMask16; } -static inline constexpr bool isMask32(TypeId typeId) noexcept { return typeId == TypeId::kMask32; } -static inline constexpr bool isMask64(TypeId typeId) noexcept { return typeId == TypeId::kMask64; } - -static inline constexpr bool isMmx(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMmxStart, TypeId::_kMmxEnd); } -static inline constexpr bool isMmx32(TypeId typeId) noexcept { return typeId == TypeId::kMmx32; } -static inline constexpr bool isMmx64(TypeId typeId) noexcept { return typeId == TypeId::kMmx64; } - -static inline constexpr bool isVec(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec512End); } -static inline constexpr bool isVec32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec32End); } -static inline constexpr bool isVec64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec64Start, TypeId::_kVec64End); } -static inline constexpr bool isVec128(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec128Start, TypeId::_kVec128End); } -static inline constexpr bool isVec256(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec256Start, TypeId::_kVec256End); } -static inline constexpr bool isVec512(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec512Start, TypeId::_kVec512End); } +static ASMJIT_INLINE_NODEBUG constexpr bool isFloat80(TypeId typeId) noexcept { return typeId == TypeId::kFloat80; } + +//! Tests whether a given type is a mask register of any size. +static ASMJIT_INLINE_NODEBUG constexpr bool isMask(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMaskStart, TypeId::_kMaskEnd); } +//! Tests whether a given type is an 8-bit mask register. +static ASMJIT_INLINE_NODEBUG constexpr bool isMask8(TypeId typeId) noexcept { return typeId == TypeId::kMask8; } +//! Tests whether a given type is an 16-bit mask register. +static ASMJIT_INLINE_NODEBUG constexpr bool isMask16(TypeId typeId) noexcept { return typeId == TypeId::kMask16; } +//! Tests whether a given type is an 32-bit mask register. +static ASMJIT_INLINE_NODEBUG constexpr bool isMask32(TypeId typeId) noexcept { return typeId == TypeId::kMask32; } +//! Tests whether a given type is an 64-bit mask register. +static ASMJIT_INLINE_NODEBUG constexpr bool isMask64(TypeId typeId) noexcept { return typeId == TypeId::kMask64; } + +//! Tests whether a given type is an MMX register. +//! +//! \note MMX functionality is in general deprecated on X86 architecture. AsmJit provides it just for completeness. +static ASMJIT_INLINE_NODEBUG constexpr bool isMmx(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMmxStart, TypeId::_kMmxEnd); } +//! Tests whether a given type is an MMX register, which only uses the low 32 bits of data (only specific cases). +//! +//! \note MMX functionality is in general deprecated on X86 architecture. AsmJit provides it just for completeness. +static ASMJIT_INLINE_NODEBUG constexpr bool isMmx32(TypeId typeId) noexcept { return typeId == TypeId::kMmx32; } +//! Tests whether a given type is an MMX register, which uses 64 bits of data (default). +//! +//! \note MMX functionality is in general deprecated on X86 architecture. AsmJit provides it just for completeness. +static ASMJIT_INLINE_NODEBUG constexpr bool isMmx64(TypeId typeId) noexcept { return typeId == TypeId::kMmx64; } + +//! Tests whether a given type is a vector register of any size. +static ASMJIT_INLINE_NODEBUG constexpr bool isVec(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec512End); } +//! Tests whether a given type is a 32-bit or 32-bit view of a vector register. +static ASMJIT_INLINE_NODEBUG constexpr bool isVec32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec32End); } +//! Tests whether a given type is a 64-bit or 64-bit view of a vector register. +static ASMJIT_INLINE_NODEBUG constexpr bool isVec64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec64Start, TypeId::_kVec64End); } +//! Tests whether a given type is a 128-bit or 128-bit view of a vector register. +static ASMJIT_INLINE_NODEBUG constexpr bool isVec128(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec128Start, TypeId::_kVec128End); } +//! Tests whether a given type is a 256-bit or 256-bit view of a vector register. +static ASMJIT_INLINE_NODEBUG constexpr bool isVec256(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec256Start, TypeId::_kVec256End); } +//! Tests whether a given type is a 512-bit or 512-bit view of a vector register. +static ASMJIT_INLINE_NODEBUG constexpr bool isVec512(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec512Start, TypeId::_kVec512End); } //! \cond enum TypeCategory : uint32_t { @@ -317,7 +341,7 @@ struct TypeIdOfT<T&> { //! Returns a corresponding \ref TypeId of `T` type. template<typename T> -static inline constexpr TypeId typeIdOfT() noexcept { return TypeId(TypeIdOfT<T>::kTypeId); } +static ASMJIT_INLINE_NODEBUG constexpr TypeId typeIdOfT() noexcept { return TypeId(TypeIdOfT<T>::kTypeId); } //! Returns offset needed to convert a `kIntPtr` and `kUIntPtr` TypeId into a type that matches `registerSize` //! (general-purpose register size). If you find such TypeId it's then only about adding the offset to it. @@ -336,18 +360,18 @@ static inline constexpr TypeId typeIdOfT() noexcept { return TypeId(TypeIdOfT<T> //! // The same, but by using TypeUtils::deabstract() function. //! typeId = TypeUtils::deabstract(typeId, deabstractDelta); //! ``` -static inline constexpr uint32_t deabstractDeltaOfSize(uint32_t registerSize) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr uint32_t deabstractDeltaOfSize(uint32_t registerSize) noexcept { return registerSize >= 8 ? uint32_t(TypeId::kInt64) - uint32_t(TypeId::kIntPtr) : uint32_t(TypeId::kInt32) - uint32_t(TypeId::kIntPtr); } //! Deabstracts a given `typeId` into a native type by using `deabstractDelta`, which was previously //! calculated by calling \ref deabstractDeltaOfSize() with a target native register size. -static inline constexpr TypeId deabstract(TypeId typeId, uint32_t deabstractDelta) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr TypeId deabstract(TypeId typeId, uint32_t deabstractDelta) noexcept { return isAbstract(typeId) ? TypeId(uint32_t(typeId) + deabstractDelta) : typeId; } -static inline constexpr TypeId scalarToVector(TypeId scalarTypeId, TypeId vecStartId) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr TypeId scalarToVector(TypeId scalarTypeId, TypeId vecStartId) noexcept { return TypeId(uint32_t(vecStartId) + uint32_t(scalarTypeId) - uint32_t(TypeId::kInt8)); } diff --git a/3rdparty/asmjit/src/asmjit/core/virtmem.cpp b/3rdparty/asmjit/src/asmjit/core/virtmem.cpp index 43766ef2cd2..743847746af 100644 --- a/3rdparty/asmjit/src/asmjit/core/virtmem.cpp +++ b/3rdparty/asmjit/src/asmjit/core/virtmem.cpp @@ -6,7 +6,7 @@ #include "../core/api-build_p.h" #ifndef ASMJIT_NO_JIT -#include "../core/osutils.h" +#include "../core/osutils_p.h" #include "../core/string.h" #include "../core/support.h" #include "../core/virtmem.h" @@ -19,9 +19,42 @@ #include <sys/types.h> #include <unistd.h> + #if !ASMJIT_ARCH_X86 + #include <sys/time.h> // required by gettimeofday() + #endif + // Linux has a `memfd_create` syscall that we would like to use, if available. #if defined(__linux__) #include <sys/syscall.h> + #include <sys/utsname.h> + + #ifndef MAP_HUGETLB + #define MAP_HUGETLB 0x40000 + #endif // MAP_HUGETLB + + #ifndef MAP_HUGE_SHIFT + #define MAP_HUGE_SHIFT 26 + #endif // MAP_HUGE_SHIFT + + #if !defined(MFD_CLOEXEC) + #define MFD_CLOEXEC 0x0001u + #endif // MFD_CLOEXEC + + #if !defined(MFD_NOEXEC_SEAL) + #define MFD_NOEXEC_SEAL 0x0008u + #endif // MFD_NOEXEC_SEAL + + #if !defined(MFD_EXEC) + #define MFD_EXEC 0x0010u + #endif // MFD_EXEC + + #ifndef MFD_HUGETLB + #define MFD_HUGETLB 0x0004 + #endif // MFD_HUGETLB + + #ifndef MFD_HUGE_SHIFT + #define MFD_HUGE_SHIFT 26 + #endif // MFD_HUGE_SHIFT #endif // Apple recently introduced MAP_JIT flag, which we want to use. @@ -42,25 +75,70 @@ #if !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON #endif + + // Android NDK doesn't provide `shm_open()` and `shm_unlink()`. + #if !defined(__BIONIC__) && !defined(ASMJIT_NO_SHM_OPEN) + #define ASMJIT_HAS_SHM_OPEN + #endif + + #if defined(__APPLE__) || defined(__BIONIC__) || !defined(ASMJIT_HAS_SHM_OPEN) + #define ASMJIT_VM_SHM_DETECT 0 + #else + #define ASMJIT_VM_SHM_DETECT 1 + #endif + + #if defined(__APPLE__) && TARGET_OS_OSX + #if ASMJIT_ARCH_X86 != 0 + #define ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP + #endif + #if ASMJIT_ARCH_ARM >= 64 + #define ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP + #endif + #endif + + #if defined(__APPLE__) && ASMJIT_ARCH_X86 == 0 + #define ASMJIT_NO_DUAL_MAPPING + #endif + + #if defined(__NetBSD__) && defined(MAP_REMAPDUP) && defined(PROT_MPROTECT) + #define ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP + #endif + + #if !defined(ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP) && \ + !defined(ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP) && \ + !defined(ASMJIT_NO_DUAL_MAPPING) + #define ASMJIT_ANONYMOUS_MEMORY_USE_FD + #endif #endif #include <atomic> -#if defined(__APPLE__) || defined(__BIONIC__) - #define ASMJIT_VM_SHM_DETECT 0 -#else - #define ASMJIT_VM_SHM_DETECT 1 -#endif +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP) +#include <mach/mach.h> +#include <mach/mach_time.h> + +extern "C" { -// Android NDK doesn't provide `shm_open()` and `shm_unlink()`. -#if defined(__BIONIC__) - #define ASMJIT_VM_SHM_AVAILABLE 0 +#ifdef mig_external +mig_external #else - #define ASMJIT_VM_SHM_AVAILABLE 1 +extern #endif - -#if defined(__APPLE__) && ASMJIT_ARCH_ARM >= 64 - #define ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP +kern_return_t mach_vm_remap( + vm_map_t target_task, + mach_vm_address_t *target_address, + mach_vm_size_t size, + mach_vm_offset_t mask, + int flags, + vm_map_t src_task, + mach_vm_address_t src_address, + boolean_t copy, + vm_prot_t *cur_protection, + vm_prot_t *max_protection, + vm_inherit_t inheritance +); + +} // {extern "C"} #endif ASMJIT_BEGIN_SUB_NAMESPACE(VirtMem) @@ -68,7 +146,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(VirtMem) // Virtual Memory Utilities // ======================== -static const MemoryFlags dualMappingFilter[2] = { +ASMJIT_MAYBE_UNUSED +static const constexpr MemoryFlags dualMappingFilter[2] = { MemoryFlags::kAccessWrite | MemoryFlags::kMMapMaxAccessWrite, MemoryFlags::kAccessExecute | MemoryFlags::kMMapMaxAccessExecute }; @@ -90,7 +169,7 @@ struct ScopedHandle { HANDLE value; }; -static void getVMInfo(Info& vmInfo) noexcept { +static void detectVMInfo(Info& vmInfo) noexcept { SYSTEM_INFO systemInfo; ::GetSystemInfo(&systemInfo); @@ -98,6 +177,15 @@ static void getVMInfo(Info& vmInfo) noexcept { vmInfo.pageGranularity = systemInfo.dwAllocationGranularity; } +static size_t detectLargePageSize() noexcept { + return ::GetLargePageMinimum(); +} + +static bool hasDualMappingSupport() noexcept { + // TODO: This assumption works on X86 platforms, this may not work on AArch64. + return true; +} + // Returns windows-specific protectFlags from \ref MemoryFlags. static DWORD protectFlagsFromMemoryFlags(MemoryFlags memoryFlags) noexcept { DWORD protectFlags; @@ -122,7 +210,12 @@ static DWORD desiredAccessFromMemoryFlags(MemoryFlags memoryFlags) noexcept { } static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { - return HardenedRuntimeFlags::kNone; + HardenedRuntimeFlags flags = HardenedRuntimeFlags::kNone; + + if (hasDualMappingSupport()) + flags |= HardenedRuntimeFlags::kDualMapping; + + return flags; } Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { @@ -130,9 +223,23 @@ Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { if (size == 0) return DebugUtils::errored(kErrorInvalidArgument); + DWORD allocationType = MEM_COMMIT | MEM_RESERVE; DWORD protectFlags = protectFlagsFromMemoryFlags(memoryFlags); - void* result = ::VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, protectFlags); + if (Support::test(memoryFlags, MemoryFlags::kMMapLargePages)) { + size_t lpSize = largePageSize(); + + // Does it make sense to call VirtualAlloc() if we failed to query large page size? + if (lpSize == 0) + return DebugUtils::errored(kErrorFeatureNotEnabled); + + if (!Support::isAligned(size, lpSize)) + return DebugUtils::errored(kErrorInvalidArgument); + + allocationType |= MEM_LARGE_PAGES; + } + + void* result = ::VirtualAlloc(nullptr, size, allocationType, protectFlags); if (!result) return DebugUtils::errored(kErrorOutOfMemory); @@ -142,7 +249,9 @@ Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { Error release(void* p, size_t size) noexcept { DebugUtils::unused(size); - if (ASMJIT_UNLIKELY(!::VirtualFree(p, 0, MEM_RELEASE))) + // NOTE: If the `dwFreeType` parameter is MEM_RELEASE, `size` parameter must be zero. + constexpr DWORD dwFreeType = MEM_RELEASE; + if (ASMJIT_UNLIKELY(!::VirtualFree(p, 0, dwFreeType))) return DebugUtils::errored(kErrorInvalidArgument); return kErrorOk; } @@ -183,7 +292,7 @@ Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) no ptr[i] = ::MapViewOfFile(handle.value, desiredAccess, 0, 0, size); if (ptr[i] == nullptr) { - if (i == 0) + if (i == 1u) ::UnmapViewOfFile(ptr[0]); return DebugUtils::errored(kErrorOutOfMemory); } @@ -214,26 +323,52 @@ Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { #endif -// Virtual Memory [Posix] -// ====================== +// Virtual Memory [Unix] +// ===================== #if !defined(_WIN32) -static void getVMInfo(Info& vmInfo) noexcept { - uint32_t pageSize = uint32_t(::getpagesize()); +// Virtual Memory [Unix] - Utilities +// ================================= - vmInfo.pageSize = pageSize; - vmInfo.pageGranularity = Support::max<uint32_t>(pageSize, 65536); -} +#if defined(__linux__) || (defined(__APPLE__) && TARGET_OS_OSX) +struct KernelVersion { + long ver[2]; -#if !defined(SHM_ANON) -static const char* getTmpDir() noexcept { - const char* tmpDir = getenv("TMPDIR"); - return tmpDir ? tmpDir : "/tmp"; + inline long major() const noexcept { return ver[0]; } + inline long minor() const noexcept { return ver[1]; } + + inline bool eq(long major, long minor) const noexcept { return ver[0] == major && ver[1] == minor; } + inline bool ge(long major, long minor) const noexcept { return ver[0] > major || (ver[0] == major && ver[1] >= minor); } +}; + +ASMJIT_MAYBE_UNUSED +static KernelVersion getKernelVersion() noexcept { + KernelVersion out {}; + struct utsname buf {}; + + uname(&buf); + + size_t i = 0; + char* p = buf.release; + + while (*p && i < 2u) { + uint8_t c = uint8_t(*p); + if (c >= uint8_t('0') && c <= uint8_t('9')) { + out.ver[i] = strtol(p, &p, 10); + i++; + continue; + } + + p++; + } + + return out; } -#endif +#endif // getKernelVersion // Translates libc errors specific to VirtualMemory mapping to `asmjit::Error`. +ASMJIT_MAYBE_UNUSED static Error asmjitErrorFromErrno(int e) noexcept { switch (e) { case EACCES: @@ -256,16 +391,149 @@ static Error asmjitErrorFromErrno(int e) noexcept { } } +ASMJIT_MAYBE_UNUSED +static MemoryFlags maxAccessFlagsToRegularAccessFlags(MemoryFlags memoryFlags) noexcept { + static constexpr uint32_t kMaxProtShift = Support::ConstCTZ<uint32_t(MemoryFlags::kMMapMaxAccessRead)>::value; + return MemoryFlags(uint32_t(memoryFlags & MemoryFlags::kMMapMaxAccessRWX) >> kMaxProtShift); +} + +ASMJIT_MAYBE_UNUSED +static MemoryFlags regularAccessFlagsToMaxAccessFlags(MemoryFlags memoryFlags) noexcept { + static constexpr uint32_t kMaxProtShift = Support::ConstCTZ<uint32_t(MemoryFlags::kMMapMaxAccessRead)>::value; + return MemoryFlags(uint32_t(memoryFlags & MemoryFlags::kAccessRWX) << kMaxProtShift); +} + +// Returns `mmap()` protection flags from \ref MemoryFlags. +ASMJIT_MAYBE_UNUSED +static int mmProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept { + int protection = 0; + if (Support::test(memoryFlags, MemoryFlags::kAccessRead)) protection |= PROT_READ; + if (Support::test(memoryFlags, MemoryFlags::kAccessWrite)) protection |= PROT_READ | PROT_WRITE; + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) protection |= PROT_READ | PROT_EXEC; + return protection; +} + +// Returns maximum protection flags from `memoryFlags`. +// +// Uses: +// - `PROT_MPROTECT()` on NetBSD. +// - `PROT_MAX()` when available on other BSDs. +ASMJIT_MAYBE_UNUSED +static inline int mmMaxProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept { + MemoryFlags acc = maxAccessFlagsToRegularAccessFlags(memoryFlags); + if (acc != MemoryFlags::kNone) { +#if defined(__NetBSD__) && defined(PROT_MPROTECT) + return PROT_MPROTECT(mmProtFromMemoryFlags(acc)); +#elif defined(PROT_MAX) + return PROT_MAX(mmProtFromMemoryFlags(acc)); +#else + return 0; +#endif + } + + return 0; +} + +static void detectVMInfo(Info& vmInfo) noexcept { + uint32_t pageSize = uint32_t(::getpagesize()); + + vmInfo.pageSize = pageSize; + vmInfo.pageGranularity = Support::max<uint32_t>(pageSize, 65536); +} + +static size_t detectLargePageSize() noexcept { +#if defined(__APPLE__) && defined(VM_FLAGS_SUPERPAGE_SIZE_2MB) && ASMJIT_ARCH_X86 + return 2u * 1024u * 1024u; +#elif defined(__FreeBSD__) + Support::Array<size_t, 2> pageSize; + // TODO: Does it return unsigned? + return (getpagesizes(pageSize.data(), 2) < 2) ? 0 : uint32_t(pageSize[1]); +#elif defined(__linux__) + StringTmp<128> storage; + if (OSUtils::readFile("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", storage, 16) != kErrorOk || storage.empty()) + return 0u; + + // The first value should be the size of the page (hpage_pmd_size). + size_t largePageSize = 0; + + const char* buf = storage.data(); + size_t bufSize = storage.size(); + + for (size_t i = 0; i < bufSize; i++) { + uint32_t digit = uint32_t(uint8_t(buf[i]) - uint8_t('0')); + if (digit >= 10u) + break; + largePageSize = largePageSize * 10 + digit; + } + + if (Support::isPowerOf2(largePageSize)) + return largePageSize; + else + return 0u; +#else + return 0u; +#endif +} + +// Virtual Memory [Posix] - Anonymous Memory +// ========================================= + +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_FD) + // Some operating systems don't allow /dev/shm to be executable. On Linux this happens when /dev/shm is mounted with // 'noexec', which is enforced by systemd. Other operating systems like MacOS also restrict executable permissions // regarding /dev/shm, so we use a runtime detection before attempting to allocate executable memory. Sometimes we -// don't need the detection as we know it would always result in `ShmStrategy::kTmpDir`. -enum class ShmStrategy : uint32_t { +// don't need the detection as we know it would always result in `AnonymousMemoryStrategy::kTmpDir`. +enum class AnonymousMemoryStrategy : uint32_t { kUnknown = 0, kDevShm = 1, kTmpDir = 2 }; +#if !defined(SHM_ANON) +static const char* getTmpDir() noexcept { + const char* tmpDir = getenv("TMPDIR"); + return tmpDir ? tmpDir : "/tmp"; +} +#endif + +#if defined(__linux__) && defined(__NR_memfd_create) +static uint32_t getMfdExecFlag() noexcept { + static std::atomic<uint32_t> cachedMfdExecSupported; + uint32_t val = cachedMfdExecSupported.load(); + + if (val == 0u) { + KernelVersion ver = getKernelVersion(); + val = uint32_t(ver.ge(6, 3)) + 1u; + cachedMfdExecSupported.store(val); + } + + return val == 2u ? uint32_t(MFD_EXEC) : uint32_t(0u); +} +#endif // __linux__ && __NR_memfd_create + + +// It's not fully random, just to avoid collisions when opening TMP or SHM file. +ASMJIT_MAYBE_UNUSED +static uint64_t generateRandomBits(uintptr_t stackPtr, uint32_t attempt) noexcept { + static std::atomic<uint32_t> internalCounter; + +#if defined(__GNUC__) && ASMJIT_ARCH_X86 + // Use RDTSC instruction to avoid gettimeofday() as we just need some "random" bits. + uint64_t mix = __builtin_ia32_rdtsc(); +#else + struct timeval tm {}; + uint64_t mix = 1; // only used when gettimeofday() fails, which is unlikely. + if (gettimeofday(&tm, nullptr) == 0) { + mix = uint64_t(tm.tv_usec) ^ uint64_t(tm.tv_sec); + } +#endif + + uint64_t bits = (uint64_t(stackPtr) & 0x1010505000055590u) - mix * 773703683; + bits = (bits >> 33) ^ (bits << 7) ^ (attempt * 87178291199); + return bits + uint64_t(++internalCounter) * 10619863; +} + class AnonymousMemory { public: enum FileType : uint32_t { @@ -294,13 +562,17 @@ public: #if defined(__linux__) && defined(__NR_memfd_create) // Linux specific 'memfd_create' - if the syscall returns `ENOSYS` it means // it's not available and we will never call it again (would be pointless). + // + // NOTE: There is also memfd_create() libc function in FreeBSD, but it internally + // uses `shm_open(SHM_ANON, ...)` so it's not needed to add support for it (it's + // not a syscall as in Linux). // Zero initialized, if ever changed to '1' that would mean the syscall is not - // available and we must use `shm_open()` and `shm_unlink()`. + // available and we must use `shm_open()` and `shm_unlink()` (or regular `open()`). static volatile uint32_t memfd_create_not_supported; if (!memfd_create_not_supported) { - _fd = (int)syscall(__NR_memfd_create, "vmem", 0); + _fd = (int)syscall(__NR_memfd_create, "vmem", MFD_CLOEXEC | getMfdExecFlag()); if (ASMJIT_LIKELY(_fd >= 0)) return kErrorOk; @@ -310,9 +582,9 @@ public: else return DebugUtils::errored(asmjitErrorFromErrno(e)); } -#endif +#endif // __linux__ && __NR_memfd_create -#if defined(SHM_ANON) +#if defined(ASMJIT_HAS_SHM_OPEN) && defined(SHM_ANON) // Originally FreeBSD extension, apparently works in other BSDs too. DebugUtils::unused(preferTmpOverDevShm); _fd = ::shm_open(SHM_ANON, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); @@ -322,32 +594,26 @@ public: else return DebugUtils::errored(asmjitErrorFromErrno(errno)); #else - // POSIX API. We have to generate somehow a unique name. This is nothing cryptographic, just using a bit from - // the stack address to always have a different base for different threads (as threads have their own stack) - // and retries for avoiding collisions. We use `shm_open()` with flags that require creation of the file so we - // never open an existing shared memory. - static std::atomic<uint32_t> internalCounter; - const char* kShmFormat = "/shm-id-%016llX"; - + // POSIX API. We have to generate somehow a unique name, so use `generateRandomBits()` helper. To prevent + // having file collisions we use `shm_open()` with flags that require creation of the file so we never open + // an existing shared memory. + static const char kShmFormat[] = "/shm-id-%016llX"; uint32_t kRetryCount = 100; - uint64_t bits = ((uintptr_t)(void*)this) & 0x55555555u; for (uint32_t i = 0; i < kRetryCount; i++) { - bits -= uint64_t(OSUtils::getTickCount()) * 773703683; - bits = ((bits >> 14) ^ (bits << 6)) + uint64_t(++internalCounter) * 10619863; - bool useTmp = !ASMJIT_VM_SHM_DETECT || preferTmpOverDevShm; + uint64_t bits = generateRandomBits((uintptr_t)this, i); if (useTmp) { _tmpName.assign(getTmpDir()); _tmpName.appendFormat(kShmFormat, (unsigned long long)bits); - _fd = ::open(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, 0); + _fd = ASMJIT_FILE64_API(::open)(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, 0); if (ASMJIT_LIKELY(_fd >= 0)) { _fileType = kFileTypeTmp; return kErrorOk; } } -#if ASMJIT_VM_SHM_AVAILABLE +#if defined(ASMJIT_HAS_SHM_OPEN) else { _tmpName.assignFormat(kShmFormat, (unsigned long long)bits); _fd = ::shm_open(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); @@ -371,7 +637,7 @@ public: FileType type = _fileType; _fileType = kFileTypeNone; -#if ASMJIT_VM_SHM_AVAILABLE +#ifdef ASMJIT_HAS_SHM_OPEN if (type == kFileTypeShm) { ::shm_unlink(_tmpName.data()); return; @@ -393,31 +659,71 @@ public: Error allocate(size_t size) noexcept { // TODO: Improve this by using `posix_fallocate()` when available. - if (ftruncate(_fd, off_t(size)) != 0) + if (ASMJIT_FILE64_API(ftruncate)(_fd, off_t(size)) != 0) return DebugUtils::errored(asmjitErrorFromErrno(errno)); return kErrorOk; } }; -// Returns `mmap()` protection flags from \ref MemoryFlags. -static int mmProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept { - int protection = 0; - if (Support::test(memoryFlags, MemoryFlags::kAccessRead)) protection |= PROT_READ; - if (Support::test(memoryFlags, MemoryFlags::kAccessWrite)) protection |= PROT_READ | PROT_WRITE; - if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) protection |= PROT_READ | PROT_EXEC; - return protection; +#if ASMJIT_VM_SHM_DETECT +static Error detectAnonymousMemoryStrategy(AnonymousMemoryStrategy* strategyOut) noexcept { + AnonymousMemory anonMem; + Info vmInfo = info(); + + ASMJIT_PROPAGATE(anonMem.open(false)); + ASMJIT_PROPAGATE(anonMem.allocate(vmInfo.pageSize)); + + void* ptr = mmap(nullptr, vmInfo.pageSize, PROT_READ | PROT_EXEC, MAP_SHARED, anonMem.fd(), 0); + if (ptr == MAP_FAILED) { + int e = errno; + if (e == EINVAL) { + *strategyOut = AnonymousMemoryStrategy::kTmpDir; + return kErrorOk; + } + return DebugUtils::errored(asmjitErrorFromErrno(e)); + } + else { + munmap(ptr, vmInfo.pageSize); + *strategyOut = AnonymousMemoryStrategy::kDevShm; + return kErrorOk; + } } +#endif -#if defined(__APPLE__) -// Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags cannot -// be allocated without MAP_JIT flag. -static inline bool hasHardenedRuntimeMacOS() noexcept { -#if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 - // MacOS on AArch64 has always hardened runtime enabled. +static Error getAnonymousMemoryStrategy(AnonymousMemoryStrategy* strategyOut) noexcept { +#if ASMJIT_VM_SHM_DETECT + // Initially don't assume anything. It has to be tested whether '/dev/shm' was mounted with 'noexec' flag or not. + static std::atomic<uint32_t> cachedStrategy; + + AnonymousMemoryStrategy strategy = static_cast<AnonymousMemoryStrategy>(cachedStrategy.load()); + if (strategy == AnonymousMemoryStrategy::kUnknown) { + ASMJIT_PROPAGATE(detectAnonymousMemoryStrategy(&strategy)); + cachedStrategy.store(static_cast<uint32_t>(strategy)); + } + + *strategyOut = strategy; + return kErrorOk; +#else + *strategyOut = AnonymousMemoryStrategy::kTmpDir; + return kErrorOk; +#endif +} + +#endif // ASMJIT_ANONYMOUS_MEMORY_USE_FD + +// Virtual Memory [Posix] - Hardened Runtime & MAP_JIT +// =================================================== + +// Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags +// cannot be normally allocated. On OSX + AArch64 such allocation requires MAP_JIT flag, other platforms don't +// support this combination. +static bool hasHardenedRuntime() noexcept { +#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 + // OSX on AArch64 has always hardened runtime enabled. return true; #else - static std::atomic<uint32_t> globalHardenedFlag; + static std::atomic<uint32_t> cachedHardenedFlag; enum HardenedFlag : uint32_t { kHardenedFlagUnknown = 0, @@ -425,11 +731,11 @@ static inline bool hasHardenedRuntimeMacOS() noexcept { kHardenedFlagEnabled = 2 }; - uint32_t flag = globalHardenedFlag.load(); + uint32_t flag = cachedHardenedFlag.load(); if (flag == kHardenedFlagUnknown) { - size_t pageSize = ::getpagesize(); + size_t pageSize = size_t(::getpagesize()); + void* ptr = mmap(nullptr, pageSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - void* ptr = mmap(nullptr, pageSize, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (ptr == MAP_FAILED) { flag = kHardenedFlagEnabled; } @@ -437,63 +743,49 @@ static inline bool hasHardenedRuntimeMacOS() noexcept { flag = kHardenedFlagDisabled; munmap(ptr, pageSize); } - globalHardenedFlag.store(flag); + + cachedHardenedFlag.store(flag); } return flag == kHardenedFlagEnabled; #endif } -static inline bool hasMapJitSupportMacOS() noexcept { -#if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 - // MacOS for 64-bit AArch architecture always uses hardened runtime. Some documentation can be found here: +// Detects whether MAP_JIT is available. +static inline bool hasMapJitSupport() noexcept { +#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_X86 == 0 + // Apple platforms always use hardened runtime + MAP_JIT on non-x86 hardware: // - https://developer.apple.com/documentation/apple_silicon/porting_just-in-time_compilers_to_apple_silicon return true; -#elif TARGET_OS_OSX - // MAP_JIT flag required to run unsigned JIT code is only supported by kernel version 10.14+ (Mojave) and IOS. - static std::atomic<uint32_t> globalVersion; - - int ver = globalVersion.load(); - if (!ver) { - struct utsname osname {}; - uname(&osname); - ver = atoi(osname.release); - globalVersion.store(ver); +#elif defined(__APPLE__) && TARGET_OS_OSX + // MAP_JIT flag required to run unsigned JIT code is only supported by kernel version 10.14+ (Mojave). + static std::atomic<uint32_t> cachedMapJitSupport; + uint32_t val = cachedMapJitSupport.load(); + + if (val == 0u) { + KernelVersion ver = getKernelVersion(); + val = uint32_t(ver.ge(18, 0)) + 1u; + cachedMapJitSupport.store(val); } - return ver >= 18; -#else - // Assume it's available. - return true; -#endif -} -#endif // __APPLE__ -// Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags -// cannot be normally allocated. On MacOS such allocation requires MAP_JIT flag. -static inline bool hasHardenedRuntime() noexcept { -#if defined(__APPLE__) - return hasHardenedRuntimeMacOS(); + return val == 2u; #else + // MAP_JIT is not available (it's only available on OSX). return false; #endif } -// Detects whether MAP_JIT is available. -static inline bool hasMapJitSupport() noexcept { -#if defined(__APPLE__) - return hasMapJitSupportMacOS(); -#else - return false; -#endif -} - -// Returns either MAP_JIT or 0 based on `flags` and the host operating system. +// Returns either MAP_JIT or 0 based on `memoryFlags` and the host operating system. static inline int mmMapJitFromMemoryFlags(MemoryFlags memoryFlags) noexcept { #if defined(__APPLE__) // Always use MAP_JIT flag if user asked for it (could be used for testing on non-hardened processes) and detect // whether it must be used when the process is actually hardened (in that case it doesn't make sense to rely on // user `memoryFlags`). - bool useMapJit = Support::test(memoryFlags, MemoryFlags::kMMapEnableMapJit) || hasHardenedRuntime(); + // + // MAP_JIT is not required when dual-mapping memory and is incompatible with MAP_SHARED, so it will not be + // added when the latter is enabled. + bool useMapJit = (Support::test(memoryFlags, MemoryFlags::kMMapEnableMapJit) || hasHardenedRuntime()) + && !Support::test(memoryFlags, MemoryFlags::kMapShared); if (useMapJit) return hasMapJitSupport() ? int(MAP_JIT) : 0; else @@ -504,121 +796,252 @@ static inline int mmMapJitFromMemoryFlags(MemoryFlags memoryFlags) noexcept { #endif } -// Returns BSD-specific `PROT_MAX()` flags. -static inline int mmMaxProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept { -#if defined(PROT_MAX) - static constexpr uint32_t kMaxProtShift = Support::ConstCTZ<uint32_t(MemoryFlags::kMMapMaxAccessRead)>::value; - - if (Support::test(memoryFlags, MemoryFlags::kMMapMaxAccessReadWrite | MemoryFlags::kMMapMaxAccessExecute)) - return PROT_MAX(mmProtFromMemoryFlags((MemoryFlags)(uint32_t(memoryFlags) >> kMaxProtShift))); - else - return 0; -#else - DebugUtils::unused(memoryFlags); - return 0; -#endif -} - -#if ASMJIT_VM_SHM_DETECT -static Error detectShmStrategy(ShmStrategy* strategyOut) noexcept { - AnonymousMemory anonMem; - Info vmInfo = info(); - - ASMJIT_PROPAGATE(anonMem.open(false)); - ASMJIT_PROPAGATE(anonMem.allocate(vmInfo.pageSize)); - - void* ptr = mmap(nullptr, vmInfo.pageSize, PROT_READ | PROT_EXEC, MAP_SHARED, anonMem.fd(), 0); - if (ptr == MAP_FAILED) { - int e = errno; - if (e == EINVAL) { - *strategyOut = ShmStrategy::kTmpDir; - return kErrorOk; - } - return DebugUtils::errored(asmjitErrorFromErrno(e)); - } - else { - munmap(ptr, vmInfo.pageSize); - *strategyOut = ShmStrategy::kDevShm; - return kErrorOk; - } -} -#endif - -static Error getShmStrategy(ShmStrategy* strategyOut) noexcept { -#if ASMJIT_VM_SHM_DETECT - // Initially don't assume anything. It has to be tested whether '/dev/shm' was mounted with 'noexec' flag or not. - static std::atomic<uint32_t> globalShmStrategy; - - ShmStrategy strategy = static_cast<ShmStrategy>(globalShmStrategy.load()); - if (strategy == ShmStrategy::kUnknown) { - ASMJIT_PROPAGATE(detectShmStrategy(&strategy)); - globalShmStrategy.store(static_cast<uint32_t>(strategy)); - } - - *strategyOut = strategy; - return kErrorOk; +static inline bool hasDualMappingSupport() noexcept { +#if defined(ASMJIT_NO_DUAL_MAPPING) + return false; #else - *strategyOut = ShmStrategy::kTmpDir; - return kErrorOk; + return true; #endif } static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { - HardenedRuntimeFlags hrFlags = HardenedRuntimeFlags::kNone; + HardenedRuntimeFlags flags = HardenedRuntimeFlags::kNone; if (hasHardenedRuntime()) - hrFlags |= HardenedRuntimeFlags::kEnabled; + flags |= HardenedRuntimeFlags::kEnabled; if (hasMapJitSupport()) - hrFlags |= HardenedRuntimeFlags::kMapJit; + flags |= HardenedRuntimeFlags::kMapJit; + + if (hasDualMappingSupport()) + flags |= HardenedRuntimeFlags::kDualMapping; - return hrFlags; + return flags; } -Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { +static Error mapMemory(void** p, size_t size, MemoryFlags memoryFlags, int fd = -1, off_t offset = 0) noexcept { *p = nullptr; if (size == 0) return DebugUtils::errored(kErrorInvalidArgument); int protection = mmProtFromMemoryFlags(memoryFlags) | mmMaxProtFromMemoryFlags(memoryFlags); - int mmFlags = MAP_PRIVATE | MAP_ANONYMOUS | mmMapJitFromMemoryFlags(memoryFlags); + int mmFlags = mmMapJitFromMemoryFlags(memoryFlags); + + mmFlags |= Support::test(memoryFlags, MemoryFlags::kMapShared) ? MAP_SHARED : MAP_PRIVATE; + if (fd == -1) + mmFlags |= MAP_ANONYMOUS; - void* ptr = mmap(nullptr, size, protection, mmFlags, -1, 0); + bool useLargePages = Support::test(memoryFlags, VirtMem::MemoryFlags::kMMapLargePages); + + if (useLargePages) { +#if defined(__linux__) + size_t lpSize = largePageSize(); + if (lpSize == 0) + return DebugUtils::errored(kErrorFeatureNotEnabled); + + if (!Support::isAligned(size, lpSize)) + return DebugUtils::errored(kErrorInvalidArgument); + + unsigned lpSizeLog2 = Support::ctz(lpSize); + mmFlags |= int(unsigned(MAP_HUGETLB) | (lpSizeLog2 << MAP_HUGE_SHIFT)); +#else + return DebugUtils::errored(kErrorFeatureNotEnabled); +#endif // __linux__ + } + + void* ptr = mmap(nullptr, size, protection, mmFlags, fd, offset); if (ptr == MAP_FAILED) - return DebugUtils::errored(kErrorOutOfMemory); + return DebugUtils::errored(asmjitErrorFromErrno(errno)); + +#if defined(MADV_HUGEPAGE) + if (useLargePages) { + madvise(ptr, size, MADV_HUGEPAGE); + } +#endif *p = ptr; return kErrorOk; } -Error release(void* p, size_t size) noexcept { +static Error unmapMemory(void* p, size_t size) noexcept { if (ASMJIT_UNLIKELY(munmap(p, size) != 0)) - return DebugUtils::errored(kErrorInvalidArgument); + return DebugUtils::errored(asmjitErrorFromErrno(errno)); return kErrorOk; } +Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { + return mapMemory(p, size, memoryFlags); +} + +Error release(void* p, size_t size) noexcept { + return unmapMemory(p, size); +} Error protect(void* p, size_t size, MemoryFlags memoryFlags) noexcept { int protection = mmProtFromMemoryFlags(memoryFlags); if (mprotect(p, size, protection) == 0) return kErrorOk; - return DebugUtils::errored(kErrorInvalidArgument); + return DebugUtils::errored(asmjitErrorFromErrno(errno)); } -Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { +// Virtual Memory [Posix] - Dual Mapping +// ===================================== + +#if !defined(ASMJIT_NO_DUAL_MAPPING) +static Error unmapDualMapping(DualMapping* dm, size_t size) noexcept { + Error err1 = unmapMemory(dm->rx, size); + Error err2 = kErrorOk; + + if (dm->rx != dm->rw) + err2 = unmapMemory(dm->rw, size); + + // We can report only one error, so report the first... + if (err1 || err2) + return DebugUtils::errored(err1 ? err1 : err2); + dm->rx = nullptr; dm->rw = nullptr; + return kErrorOk; +} +#endif // !ASMJIT_NO_DUAL_MAPPING - if (off_t(size) <= 0) - return DebugUtils::errored(size == 0 ? kErrorInvalidArgument : kErrorTooLarge); +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP) +static Error allocDualMappingUsingRemapdup(DualMapping* dmOut, size_t size, MemoryFlags memoryFlags) noexcept { + MemoryFlags maxAccessFlags = regularAccessFlagsToMaxAccessFlags(memoryFlags); + MemoryFlags finalFlags = memoryFlags | maxAccessFlags | MemoryFlags::kMapShared; + + MemoryFlags rxFlags = finalFlags & ~(MemoryFlags::kAccessWrite | MemoryFlags::kMMapMaxAccessWrite); + MemoryFlags rwFlags = finalFlags & ~(MemoryFlags::kAccessExecute); + + // Allocate RW mapping. + DualMapping dm {}; + ASMJIT_PROPAGATE(mapMemory(&dm.rw, size, rwFlags)); + + // Allocate RX mapping. + dm.rx = mremap(dm.rw, size, nullptr, size, MAP_REMAPDUP); + if (dm.rx == MAP_FAILED) { + int e = errno; + munmap(dm.rw, size); + return DebugUtils::errored(asmjitErrorFromErrno(e)); + } + + if (mprotect(dm.rx, size, mmProtFromMemoryFlags(rxFlags)) != 0) { + int e = errno; + unmapDualMapping(&dm, size); + return DebugUtils::errored(asmjitErrorFromErrno(e)); + } + + *dmOut = dm; + return kErrorOk; +} +#endif + +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP) +static Error asmjitErrorFromKernResult(kern_return_t result) noexcept { + switch (result) { + case KERN_PROTECTION_FAILURE: + return DebugUtils::errored(kErrorProtectionFailure); + case KERN_NO_SPACE: + return DebugUtils::errored(kErrorOutOfMemory); + case KERN_INVALID_ARGUMENT: + return DebugUtils::errored(kErrorInvalidArgument); + default: + return DebugUtils::errored(kErrorInvalidState); + } +} + +static Error allocDualMappingUsingMachVmRemap(DualMapping* dmOut, size_t size, MemoryFlags memoryFlags) noexcept { + DualMapping dm {}; + + MemoryFlags mmapFlags = MemoryFlags::kAccessReadWrite | (memoryFlags & MemoryFlags::kMapShared); + ASMJIT_PROPAGATE(mapMemory(&dm.rx, size, mmapFlags)); + + vm_prot_t curProt; + vm_prot_t maxProt; + + int rwProtectFlags = VM_PROT_READ | VM_PROT_WRITE; + int rxProtectFlags = VM_PROT_READ; + + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) + rxProtectFlags |= VM_PROT_EXECUTE; + + kern_return_t result {}; + do { + vm_map_t task = mach_task_self(); + mach_vm_address_t remappedAddr {}; + +#if defined(VM_FLAGS_RANDOM_ADDR) + int remapFlags = VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR; +#else + int remapFlags = VM_FLAGS_ANYWHERE; +#endif + + // Try to remap the existing memory into a different address. + result = mach_vm_remap( + task, // target_task + &remappedAddr, // target_address + size, // size + 0, // mask + remapFlags, // flags + task, // src_task + (mach_vm_address_t)dm.rx, // src_address + false, // copy + &curProt, // cur_protection + &maxProt, // max_protection + VM_INHERIT_DEFAULT); // inheritance + + if (result != KERN_SUCCESS) + break; + + dm.rw = (void*)remappedAddr; + + // Now, try to change permissions of both map regions into RW and RX. The vm_protect() + // API is used twice as we also want to set maximum permissions, so nobody would be + // allowed to change the RX region back to RW or RWX (if RWX is allowed). + uint32_t i; + for (i = 0; i < 2; i++) { + bool setMaximum = (i == 0); + + result = vm_protect( + task, // target_task + (vm_address_t)dm.rx, // address + size, // size + setMaximum, // set_maximum + rxProtectFlags); // new_protection + + if (result != KERN_SUCCESS) + break; + + result = vm_protect(task, // target_task + (vm_address_t)dm.rw, // address + size, // size + setMaximum, // set_maximum + rwProtectFlags); // new_protection + + if (result != KERN_SUCCESS) + break; + } + } while (0); + + if (result != KERN_SUCCESS) { + unmapDualMapping(&dm, size); + return DebugUtils::errored(asmjitErrorFromKernResult(result)); + } + *dmOut = dm; + return kErrorOk; +} +#endif // ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP + +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_FD) +static Error allocDualMappingUsingFile(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { bool preferTmpOverDevShm = Support::test(memoryFlags, MemoryFlags::kMappingPreferTmp); if (!preferTmpOverDevShm) { - ShmStrategy strategy; - ASMJIT_PROPAGATE(getShmStrategy(&strategy)); - preferTmpOverDevShm = (strategy == ShmStrategy::kTmpDir); + AnonymousMemoryStrategy strategy; + ASMJIT_PROPAGATE(getAnonymousMemoryStrategy(&strategy)); + preferTmpOverDevShm = (strategy == AnonymousMemoryStrategy::kTmpDir); } AnonymousMemory anonMem; @@ -627,16 +1050,12 @@ Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) no void* ptr[2]; for (uint32_t i = 0; i < 2; i++) { - MemoryFlags accessFlags = memoryFlags & ~dualMappingFilter[i]; - int protection = mmProtFromMemoryFlags(accessFlags) | mmMaxProtFromMemoryFlags(accessFlags); - - ptr[i] = mmap(nullptr, size, protection, MAP_SHARED, anonMem.fd(), 0); - if (ptr[i] == MAP_FAILED) { - // Get the error now before `munmap()` has a chance to clobber it. - int e = errno; + MemoryFlags restrictedMemoryFlags = memoryFlags & ~dualMappingFilter[i]; + Error err = mapMemory(&ptr[i], size, restrictedMemoryFlags | MemoryFlags::kMapShared, anonMem.fd(), 0); + if (err != kErrorOk) { if (i == 1) - munmap(ptr[0], size); - return DebugUtils::errored(asmjitErrorFromErrno(e)); + unmapMemory(ptr[0], size); + return err; } } @@ -644,18 +1063,38 @@ Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) no dm->rw = ptr[1]; return kErrorOk; } +#endif // ASMJIT_ANONYMOUS_MEMORY_USE_FD -Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { - Error err = release(dm->rx, size); - if (dm->rx != dm->rw) - err |= release(dm->rw, size); - - if (err) - return DebugUtils::errored(kErrorInvalidArgument); - +Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { dm->rx = nullptr; dm->rw = nullptr; - return kErrorOk; + +#if defined(ASMJIT_NO_DUAL_MAPPING) + DebugUtils::unused(size, memoryFlags); + return DebugUtils::errored(kErrorFeatureNotEnabled); +#else + if (off_t(size) <= 0) + return DebugUtils::errored(size == 0 ? kErrorInvalidArgument : kErrorTooLarge); + +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP) + return allocDualMappingUsingRemapdup(dm, size, memoryFlags); +#elif defined(ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP) + return allocDualMappingUsingMachVmRemap(dm, size, memoryFlags); +#elif defined(ASMJIT_ANONYMOUS_MEMORY_USE_FD) + return allocDualMappingUsingFile(dm, size, memoryFlags); +#else + #error "[asmjit] VirtMem::allocDualMapping() doesn't have implementation for the target OS or architecture" +#endif +#endif // ASMJIT_NO_DUAL_MAPPING +} + +Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { +#if defined(ASMJIT_NO_DUAL_MAPPING) + DebugUtils::unused(dm, size); + return DebugUtils::errored(kErrorFeatureNotEnabled); +#else + return unmapDualMapping(dm, size); +#endif // ASMJIT_NO_DUAL_MAPPING } #endif @@ -663,7 +1102,7 @@ Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { // ======================================== void flushInstructionCache(void* p, size_t size) noexcept { -#if ASMJIT_ARCH_X86 +#if ASMJIT_ARCH_X86 || defined(__EMSCRIPTEN__) // X86/X86_64 architecture doesn't require to do anything to flush instruction cache. DebugUtils::unused(p, size); #elif defined(__APPLE__) @@ -676,7 +1115,7 @@ void flushInstructionCache(void* p, size_t size) noexcept { char* end = start + size; __builtin___clear_cache(start, end); #else - #pragma message("asmjit::VirtMem::flushInstructionCache() doesn't have implementation for the target OS and compiler") + #pragma message("[asmjit] VirtMem::flushInstructionCache() doesn't have implementation for the target OS and compiler") DebugUtils::unused(p, size); #endif } @@ -690,7 +1129,7 @@ Info info() noexcept { if (!vmInfoInitialized.load()) { Info localMemInfo; - getVMInfo(localMemInfo); + detectVMInfo(localMemInfo); vmInfo = localMemInfo; vmInfoInitialized.store(1u); @@ -699,6 +1138,22 @@ Info info() noexcept { return vmInfo; } +size_t largePageSize() noexcept { + static std::atomic<size_t> largePageSize; + static constexpr size_t kNotAvailable = 1; + + size_t size = largePageSize.load(); + if (ASMJIT_LIKELY(size > kNotAvailable)) + return size; + + if (size == kNotAvailable) + return 0; + + size = detectLargePageSize(); + largePageSize.store(size != 0 ? size : kNotAvailable); + return size; +} + // Virtual Memory - Hardened Runtime Info // ====================================== @@ -711,7 +1166,7 @@ HardenedRuntimeInfo hardenedRuntimeInfo() noexcept { void protectJitMemory(ProtectJitAccess access) noexcept { #if defined(ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP) - pthread_jit_write_protect_np(static_cast<uint32_t>(access)); + pthread_jit_write_protect_np(static_cast<int>(access)); #else DebugUtils::unused(access); #endif @@ -719,4 +1174,33 @@ void protectJitMemory(ProtectJitAccess access) noexcept { ASMJIT_END_SUB_NAMESPACE -#endif +// Virtual Memory - Tests +// ====================== + +#if defined(ASMJIT_TEST) +ASMJIT_BEGIN_NAMESPACE + +UNIT(virt_mem) { + VirtMem::Info vmInfo = VirtMem::info(); + + INFO("VirtMem::info():"); + INFO(" pageSize: %zu", size_t(vmInfo.pageSize)); + INFO(" pageGranularity: %zu", size_t(vmInfo.pageGranularity)); + + INFO("VirtMem::largePageSize():"); + INFO(" largePageSize: %zu", size_t(VirtMem::largePageSize())); + + VirtMem::HardenedRuntimeInfo hardenedRtInfo = VirtMem::hardenedRuntimeInfo(); + VirtMem::HardenedRuntimeFlags hardenedFlags = hardenedRtInfo.flags; + + INFO("VirtMem::hardenedRuntimeInfo():"); + INFO(" flags:"); + INFO(" kEnabled: %s" , Support::test(hardenedFlags, VirtMem::HardenedRuntimeFlags::kEnabled ) ? "true" : "false"); + INFO(" kMapJit: %s" , Support::test(hardenedFlags, VirtMem::HardenedRuntimeFlags::kMapJit ) ? "true" : "false"); + INFO(" kDualMapping: %s", Support::test(hardenedFlags, VirtMem::HardenedRuntimeFlags::kDualMapping) ? "true" : "false"); +} + +ASMJIT_END_NAMESPACE +#endif // ASMJIT_TEST + +#endif // !ASMJIT_NO_JIT diff --git a/3rdparty/asmjit/src/asmjit/core/virtmem.h b/3rdparty/asmjit/src/asmjit/core/virtmem.h index 50f09457eba..17996dcb07e 100644 --- a/3rdparty/asmjit/src/asmjit/core/virtmem.h +++ b/3rdparty/asmjit/src/asmjit/core/virtmem.h @@ -10,6 +10,7 @@ #ifndef ASMJIT_NO_JIT #include "../core/globals.h" +#include "../core/support.h" ASMJIT_BEGIN_NAMESPACE @@ -19,6 +20,21 @@ ASMJIT_BEGIN_NAMESPACE //! Virtual memory management. namespace VirtMem { +//! Describes whether instruction cache should be flushed after a write operation. +enum class CachePolicy : uint32_t { + //! Default policy. + //! + //! In some places this would mean `kFlushAfterWrite` and in some places it would mean `kNeverFlush`. + //! For example if it's known that an address has never been used before to execute code. + kDefault = 0, + + //! Flush instruction cache after a write operation. + kFlushAfterWrite = 1, + + //! Avoid flushing instruction cache after a write operation. + kNeverFlush = 2 +}; + //! Flushes instruction cache in the given region. //! //! Only useful on non-x86 architectures, however, it's a good practice to call it on any platform to make your @@ -36,6 +52,15 @@ struct Info { //! Returns virtual memory information, see `VirtMem::Info` for more details. ASMJIT_API Info info() noexcept; +//! Returns the size of the smallest large page supported. +//! +//! AsmJit only uses the smallest large page at the moment as these are usually perfectly sized for executable +//! memory allocation (standard size is 2MB, but different sizes are possible). +//! +//! Returns either the detected large page size or 0, if large page support is either not supported by AsmJit +//! or not accessible to the process. +ASMJIT_API size_t largePageSize() noexcept; + //! Virtual memory access and mmap-specific flags. enum class MemoryFlags : uint32_t { //! No flags. @@ -50,52 +75,80 @@ enum class MemoryFlags : uint32_t { //! Memory is executable. kAccessExecute = 0x00000004u, - //! A combination of \ref MemoryFlags::kAccessRead and \ref MemoryFlags::kAccessWrite. + //! A combination of \ref kAccessRead and \ref kAccessWrite. kAccessReadWrite = kAccessRead | kAccessWrite, - //! A combination of \ref MemoryFlags::kAccessRead, \ref MemoryFlags::kAccessWrite. + //! A combination of \ref kAccessRead, \ref kAccessWrite. kAccessRW = kAccessRead | kAccessWrite, - //! A combination of \ref MemoryFlags::kAccessRead and \ref MemoryFlags::kAccessExecute. + //! A combination of \ref kAccessRead and \ref kAccessExecute. kAccessRX = kAccessRead | kAccessExecute, - //! A combination of \ref MemoryFlags::kAccessRead, \ref MemoryFlags::kAccessWrite, and - //! \ref MemoryFlags::kAccessExecute. + //! A combination of \ref kAccessRead, \ref kAccessWrite, and \ref kAccessExecute. kAccessRWX = kAccessRead | kAccessWrite | kAccessExecute, - //! Use a `MAP_JIT` flag available on Apple platforms (introduced by Mojave), which allows JIT code to be executed - //! in MAC bundles. This flag is not turned on by default, because when a process uses `fork()` the child process - //! has no access to the pages mapped with `MAP_JIT`, which could break code that doesn't expect this behavior. + //! Use a `MAP_JIT` flag available on Apple platforms (introduced by Mojave), which allows JIT code to be + //! executed in a MAC bundle. //! - //! \note This flag can only be used with \ref VirtMem::alloc(). + //! This flag may be turned on by the allocator if there is no other way of allocating executable memory. + //! + //! \note This flag can only be used with \ref VirtMem::alloc(), `MAP_JIT` only works on OSX and not on iOS. + //! When a process uses `fork()` the child process has no access to the pages mapped with `MAP_JIT`. kMMapEnableMapJit = 0x00000010u, - //! Pass `PROT_MAX(PROT_READ)` to mmap() on platforms that support `PROT_MAX`. + //! Pass `PROT_MAX(PROT_READ)` or `PROT_MPROTECT(PROT_READ)` to `mmap()` on platforms that support it. //! - //! \note This flag can only be used with \ref VirtMem::alloc(). + //! This flag allows to set a "maximum access" that the memory page can get during its lifetime. Use + //! \ref VirtMem::protect() to change the access flags. + //! + //! \note This flag can only be used with \ref VirtMem::alloc() and \ref VirtMem::allocDualMapping(). + //! However \ref VirtMem::allocDualMapping() may automatically use this if \ref kAccessRead is used. kMMapMaxAccessRead = 0x00000020u, - //! Pass `PROT_MAX(PROT_WRITE)` to mmap() on platforms that support `PROT_MAX`. + + //! Pass `PROT_MAX(PROT_WRITE)` or `PROT_MPROTECT(PROT_WRITE)` to `mmap()` on platforms that support it. //! - //! \note This flag can only be used with \ref VirtMem::alloc(). + //! This flag allows to set a "maximum access" that the memory page can get during its lifetime. Use + //! \ref VirtMem::protect() to change the access flags. + //! + //! \note This flag can only be used with \ref VirtMem::alloc() and \ref VirtMem::allocDualMapping(). + //! However \ref VirtMem::allocDualMapping() may automatically use this if \ref kAccessWrite is used. kMMapMaxAccessWrite = 0x00000040u, - //! Pass `PROT_MAX(PROT_EXEC)` to mmap() on platforms that support `PROT_MAX`. + + //! Pass `PROT_MAX(PROT_EXEC)` or `PROT_MPROTECT(PROT_EXEC)` to `mmap()` on platforms that support it. //! - //! \note This flag can only be used with \ref VirtMem::alloc(). + //! This flag allows to set a "maximum access" that the memory page can get during its lifetime. Use + //! \ref VirtMem::protect() to change the access flags. + //! + //! \note This flag can only be used with \ref VirtMem::alloc() and \ref VirtMem::allocDualMapping(). + //! However \ref VirtMem::allocDualMapping() may automatically use this if \ref kAccessExecute is used. kMMapMaxAccessExecute = 0x00000080u, - //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessWrite. + //! A combination of \ref kMMapMaxAccessRead and \ref kMMapMaxAccessWrite. kMMapMaxAccessReadWrite = kMMapMaxAccessRead | kMMapMaxAccessWrite, - //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessWrite. + //! A combination of \ref kMMapMaxAccessRead and \ref kMMapMaxAccessWrite. kMMapMaxAccessRW = kMMapMaxAccessRead | kMMapMaxAccessWrite, - //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessExecute. + //! A combination of \ref kMMapMaxAccessRead and \ref kMMapMaxAccessExecute. kMMapMaxAccessRX = kMMapMaxAccessRead | kMMapMaxAccessExecute, - //! A combination of \ref MemoryFlags::kMMapMaxAccessRead, \ref MemoryFlags::kMMapMaxAccessWrite, \ref - //! MemoryFlags::kMMapMaxAccessExecute. + //! A combination of \ref kMMapMaxAccessRead, \ref kMMapMaxAccessWrite, \ref kMMapMaxAccessExecute. kMMapMaxAccessRWX = kMMapMaxAccessRead | kMMapMaxAccessWrite | kMMapMaxAccessExecute, + //! Use `MAP_SHARED` when calling mmap(). + //! + //! \note In some cases `MAP_SHARED` may be set automatically. For example, some dual mapping implementations must + //! use `MAP_SHARED` instead of `MAP_PRIVATE` to ensure that the OS would not apply copy on write on RW page, which + //! would cause RX page not having the updated content. + kMapShared = 0x00000100u, + + //! Request large memory mapped pages. + //! + //! \remarks If this option is used and large page(s) cannot be mapped, the allocation will fail. Fallback to + //! regular pages must be done by the user in this case. Higher level API such as \ref JitAllocator provides an + //! additional mechanism to allocate regular page(s) when large page(s) allocation fails. + kMMapLargePages = 0x00000200u, + //! Not an access flag, only used by `allocDualMapping()` to override the default allocation strategy to always use //! a 'tmp' directory instead of "/dev/shm" (on POSIX platforms). Please note that this flag will be ignored if the //! operating system allows to allocate an executable memory by a different API than `open()` or `shm_open()`. For @@ -157,21 +210,37 @@ enum class HardenedRuntimeFlags : uint32_t { //! Hardened runtime is enabled - it's not possible to have "Write & Execute" memory protection. The runtime //! enforces W^X (either write or execute). //! - //! \note If the runtime is hardened it means that an operating system specific protection is used. For example on - //! MacOS platform it's possible to allocate memory with MAP_JIT flag and then use `pthread_jit_write_protect_np()` + //! \note If the runtime is hardened it means that an operating system specific protection is used. For example + //! on Apple OSX it's possible to allocate memory with MAP_JIT flag and then use `pthread_jit_write_protect_np()` //! to temporarily swap access permissions for the current thread. Dual mapping is also a possibility on X86/X64 //! architecture. kEnabled = 0x00000001u, - //! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific). - kMapJit = 0x00000002u + //! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific, only available on Apple platforms). + kMapJit = 0x00000002u, + + //! Read+Write+Execute can be allocated with dual mapping approach (one region with RW and the other with RX). + kDualMapping = 0x00000004u }; ASMJIT_DEFINE_ENUM_FLAGS(HardenedRuntimeFlags) //! Hardened runtime information. struct HardenedRuntimeInfo { + //! \name Members + //! \{ + //! Hardened runtime flags. HardenedRuntimeFlags flags; + + //! \} + + //! \name Accessors + //! \{ + + //! Tests whether the hardened runtime `flag` is set. + ASMJIT_INLINE_NODEBUG bool hasFlag(HardenedRuntimeFlags flag) const noexcept { return Support::test(flags, flag); } + + //! \} }; //! Returns runtime features provided by the OS. @@ -187,7 +256,7 @@ enum class ProtectJitAccess : uint32_t { //! Protects access of memory mapped with MAP_JIT flag for the current thread. //! -//! \note This feature is only available on Apple hardware (AArch64) at the moment and and uses a non-portable +//! \note This feature is only available on Apple hardware (AArch64) at the moment and uses a non-portable //! `pthread_jit_write_protect_np()` call when available. //! //! This function must be called before and after a memory mapped with MAP_JIT flag is modified. Example: @@ -212,24 +281,40 @@ ASMJIT_API void protectJitMemory(ProtectJitAccess access) noexcept; //! in destructor. The purpose of this class is to make writing to JIT memory easier. class ProtectJitReadWriteScope { public: + ASMJIT_NONCOPYABLE(ProtectJitReadWriteScope) + + //! \name Members + //! \{ + void* _rxPtr; size_t _size; + CachePolicy _policy; + + //! \} + + //! \name Construction & Destruction + //! \{ //! Makes the given memory block RW protected. - ASMJIT_FORCE_INLINE ProtectJitReadWriteScope(void* rxPtr, size_t size) noexcept + ASMJIT_FORCE_INLINE ProtectJitReadWriteScope( + void* rxPtr, + size_t size, + CachePolicy policy = CachePolicy::kDefault) noexcept : _rxPtr(rxPtr), - _size(size) { + _size(size), + _policy(policy) { protectJitMemory(ProtectJitAccess::kReadWrite); } - // Not copyable. - ProtectJitReadWriteScope(const ProtectJitReadWriteScope& other) = delete; - //! Makes the memory block RX protected again and flushes instruction cache. ASMJIT_FORCE_INLINE ~ProtectJitReadWriteScope() noexcept { protectJitMemory(ProtectJitAccess::kReadExecute); - flushInstructionCache(_rxPtr, _size); + + if (_policy != CachePolicy::kNeverFlush) + flushInstructionCache(_rxPtr, _size); } + + //! \} }; } // VirtMem diff --git a/3rdparty/asmjit/src/asmjit/core/zone.cpp b/3rdparty/asmjit/src/asmjit/core/zone.cpp index d68e110b48c..e1948ebb0c9 100644 --- a/3rdparty/asmjit/src/asmjit/core/zone.cpp +++ b/3rdparty/asmjit/src/asmjit/core/zone.cpp @@ -16,8 +16,8 @@ ASMJIT_BEGIN_NAMESPACE // and should never be modified. const Zone::Block Zone::_zeroBlock = { nullptr, nullptr, 0 }; -// Zone - Init & Reset -// =================== +// Zone - Initialization & Reset +// ============================= void Zone::_init(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept { ASMJIT_ASSERT(blockSize >= kMinBlockSize); @@ -215,8 +215,8 @@ static bool ZoneAllocator_hasDynamicBlock(ZoneAllocator* self, ZoneAllocator::Dy } #endif -// ZoneAllocator - Init & Reset -// ============================ +// ZoneAllocator - Initialization & Reset +// ====================================== void ZoneAllocator::reset(Zone* zone) noexcept { // Free dynamic blocks. @@ -227,9 +227,9 @@ void ZoneAllocator::reset(Zone* zone) noexcept { block = next; } - // Zero the entire class and initialize to the given `zone`. - memset(this, 0, sizeof(*this)); _zone = zone; + memset(_slots, 0, sizeof(_slots)); + _dynamicBlocks = nullptr; } // asmjit::ZoneAllocator - Alloc & Release diff --git a/3rdparty/asmjit/src/asmjit/core/zone.h b/3rdparty/asmjit/src/asmjit/core/zone.h index eaea252903e..b61a3d1292c 100644 --- a/3rdparty/asmjit/src/asmjit/core/zone.h +++ b/3rdparty/asmjit/src/asmjit/core/zone.h @@ -85,17 +85,17 @@ public: //! //! It's not required, but it's good practice to set `blockSize` to a reasonable value that depends on the usage //! of `Zone`. Greater block sizes are generally safer and perform better than unreasonably low block sizes. - inline explicit Zone(size_t blockSize, size_t blockAlignment = 1) noexcept { + ASMJIT_INLINE_NODEBUG explicit Zone(size_t blockSize, size_t blockAlignment = 1) noexcept { _init(blockSize, blockAlignment, nullptr); } //! Creates a new Zone with a first block pointing to a `temporary` memory. - inline Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary& temporary) noexcept { + ASMJIT_INLINE_NODEBUG Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary& temporary) noexcept { _init(blockSize, blockAlignment, &temporary); } //! \overload - inline Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept { + ASMJIT_INLINE_NODEBUG Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept { _init(blockSize, blockAlignment, temporary); } @@ -118,7 +118,7 @@ public: //! //! This will destroy the `Zone` instance and release all blocks of memory allocated by it. It performs implicit //! `reset(ResetPolicy::kHard)`. - inline ~Zone() noexcept { reset(ResetPolicy::kHard); } + ASMJIT_INLINE_NODEBUG ~Zone() noexcept { reset(ResetPolicy::kHard); } ASMJIT_API void _init(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept; @@ -133,24 +133,24 @@ public: //! \{ //! Tests whether this `Zone` is actually a `ZoneTmp` that uses temporary memory. - inline bool isTemporary() const noexcept { return _isTemporary != 0; } + ASMJIT_INLINE_NODEBUG bool isTemporary() const noexcept { return _isTemporary != 0; } //! Returns the default block size. - inline size_t blockSize() const noexcept { return _blockSize; } + ASMJIT_INLINE_NODEBUG size_t blockSize() const noexcept { return _blockSize; } //! Returns the default block alignment. - inline size_t blockAlignment() const noexcept { return size_t(1) << _blockAlignmentShift; } + ASMJIT_INLINE_NODEBUG size_t blockAlignment() const noexcept { return size_t(1) << _blockAlignmentShift; } //! Returns remaining size of the current block. - inline size_t remainingSize() const noexcept { return (size_t)(_end - _ptr); } + ASMJIT_INLINE_NODEBUG size_t remainingSize() const noexcept { return (size_t)(_end - _ptr); } //! Returns the current zone cursor (dangerous). //! //! This is a function that can be used to get exclusive access to the current block's memory buffer. template<typename T = uint8_t> - inline T* ptr() noexcept { return reinterpret_cast<T*>(_ptr); } + ASMJIT_INLINE_NODEBUG T* ptr() noexcept { return reinterpret_cast<T*>(_ptr); } //! Returns the end of the current zone block, only useful if you use `ptr()`. template<typename T = uint8_t> - inline T* end() noexcept { return reinterpret_cast<T*>(_end); } + ASMJIT_INLINE_NODEBUG T* end() noexcept { return reinterpret_cast<T*>(_end); } //! Sets the current zone pointer to `ptr` (must be within the current block). template<typename T> @@ -185,7 +185,7 @@ public: } //! Aligns the current pointer to `alignment`. - inline void align(size_t alignment) noexcept { + ASMJIT_INLINE_NODEBUG void align(size_t alignment) noexcept { _ptr = Support::min(Support::alignUp(_ptr, alignment), _end); } @@ -193,7 +193,7 @@ public: //! //! \note This function doesn't respect any alignment. If you need to ensure there is enough room for an aligned //! allocation you need to call `align()` before calling `ensure()`. - inline Error ensure(size_t size) noexcept { + ASMJIT_INLINE_NODEBUG Error ensure(size_t size) noexcept { if (size <= remainingSize()) return kErrorOk; else @@ -322,7 +322,7 @@ public: void* p = alloc(sizeof(T), alignof(T)); if (ASMJIT_UNLIKELY(!p)) return nullptr; - return new(p) T(); + return new(Support::PlacementNew{p}) T(); } //! Like `new(std::nothrow) T(...)`, but allocated by `Zone`. @@ -331,7 +331,7 @@ public: void* p = alloc(sizeof(T), alignof(T)); if (ASMJIT_UNLIKELY(!p)) return nullptr; - return new(p) T(std::forward<Args>(args)...); + return new(Support::PlacementNew{p}) T(std::forward<Args>(args)...); } //! \cond INTERNAL @@ -430,11 +430,11 @@ public: //! \{ //! Zone used to allocate memory that fits into slots. - Zone* _zone; + Zone* _zone {}; //! Indexed slots containing released memory. - Slot* _slots[kLoCount + kHiCount]; + Slot* _slots[kLoCount + kHiCount] {}; //! Dynamic blocks for larger allocations (no slots). - DynamicBlock* _dynamicBlocks; + DynamicBlock* _dynamicBlocks {}; //! \} @@ -444,26 +444,22 @@ public: //! Creates a new `ZoneAllocator`. //! //! \note To use it, you must first `init()` it. - inline ZoneAllocator() noexcept { - memset(this, 0, sizeof(*this)); - } + ASMJIT_INLINE_NODEBUG ZoneAllocator() noexcept {} //! Creates a new `ZoneAllocator` initialized to use `zone`. - inline explicit ZoneAllocator(Zone* zone) noexcept { - memset(this, 0, sizeof(*this)); - _zone = zone; - } + ASMJIT_INLINE_NODEBUG explicit ZoneAllocator(Zone* zone) noexcept + : _zone(zone) {} //! Destroys the `ZoneAllocator`. - inline ~ZoneAllocator() noexcept { reset(); } + ASMJIT_INLINE_NODEBUG ~ZoneAllocator() noexcept { reset(); } //! Tests whether the `ZoneAllocator` is initialized (i.e. has `Zone`). - inline bool isInitialized() const noexcept { return _zone != nullptr; } + ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _zone != nullptr; } //! Convenience function to initialize the `ZoneAllocator` with `zone`. //! //! It's the same as calling `reset(zone)`. - inline void init(Zone* zone) noexcept { reset(zone); } + ASMJIT_INLINE_NODEBUG void init(Zone* zone) noexcept { reset(zone); } //! Resets this `ZoneAllocator` and also forget about the current `Zone` which is attached (if any). Reset //! optionally attaches a new `zone` passed, or keeps the `ZoneAllocator` in an uninitialized state, if @@ -476,7 +472,7 @@ public: //! \{ //! Returns the assigned `Zone` of this allocator or null if this `ZoneAllocator` is not initialized. - inline Zone* zone() const noexcept { return _zone; } + ASMJIT_INLINE_NODEBUG Zone* zone() const noexcept { return _zone; } //! \} @@ -577,7 +573,7 @@ public: void* p = allocT<T>(); if (ASMJIT_UNLIKELY(!p)) return nullptr; - return new(p) T(); + return new(Support::PlacementNew{p}) T(); } //! Like `new(std::nothrow) T(...)`, but allocated by `Zone`. template<typename T, typename... Args> @@ -585,7 +581,7 @@ public: void* p = allocT<T>(); if (ASMJIT_UNLIKELY(!p)) return nullptr; - return new(p) T(std::forward<Args>(args)...); + return new(Support::PlacementNew{p}) T(std::forward<Args>(args)...); } //! Releases the memory previously allocated by `alloc()`. The `size` argument has to be the same as used to call diff --git a/3rdparty/asmjit/src/asmjit/core/zonehash.cpp b/3rdparty/asmjit/src/asmjit/core/zonehash.cpp index 3778fbe2260..578b083680e 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonehash.cpp +++ b/3rdparty/asmjit/src/asmjit/core/zonehash.cpp @@ -288,8 +288,8 @@ UNIT(zone_hash) { for (key = 0; key < count; key++) { node = hashTable.get(MyKeyMatcher(key)); - EXPECT(node != nullptr); - EXPECT(node->_key == key); + EXPECT_NOT_NULL(node); + EXPECT_EQ(node->_key, key); } { @@ -298,11 +298,11 @@ UNIT(zone_hash) { hashTable.remove(&allocator, node); node = hashTable.get(MyKeyMatcher(count)); - EXPECT(node == nullptr); + EXPECT_NULL(node); } } while (count); - EXPECT(hashTable.empty()); + EXPECT_TRUE(hashTable.empty()); } #endif diff --git a/3rdparty/asmjit/src/asmjit/core/zonehash.h b/3rdparty/asmjit/src/asmjit/core/zonehash.h index f332290b54d..d6cd2e31cb9 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonehash.h +++ b/3rdparty/asmjit/src/asmjit/core/zonehash.h @@ -59,7 +59,7 @@ public: //! \name Construction & Destruction //! \{ - inline ZoneHashBase() noexcept { + ASMJIT_INLINE_NODEBUG ZoneHashBase() noexcept { reset(); } @@ -99,8 +99,8 @@ public: //! \name Accessors //! \{ - inline bool empty() const noexcept { return _size == 0; } - inline size_t size() const noexcept { return _size; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; } + ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; } //! \} @@ -150,10 +150,10 @@ public: //! \name Construction & Destruction //! \{ - inline ZoneHash() noexcept + ASMJIT_INLINE_NODEBUG ZoneHash() noexcept : ZoneHashBase() {} - inline ZoneHash(ZoneHash&& other) noexcept + ASMJIT_INLINE_NODEBUG ZoneHash(ZoneHash&& other) noexcept : ZoneHash(other) {} //! \} @@ -161,7 +161,7 @@ public: //! \name Utilities //! \{ - inline void swap(ZoneHash& other) noexcept { ZoneHashBase::_swap(other); } + ASMJIT_INLINE_NODEBUG void swap(ZoneHash& other) noexcept { ZoneHashBase::_swap(other); } template<typename KeyT> inline NodeT* get(const KeyT& key) const noexcept { @@ -173,8 +173,8 @@ public: return node; } - inline NodeT* insert(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_insert(allocator, node)); } - inline NodeT* remove(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_remove(allocator, node)); } + ASMJIT_INLINE_NODEBUG NodeT* insert(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_insert(allocator, node)); } + ASMJIT_INLINE_NODEBUG NodeT* remove(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_remove(allocator, node)); } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/core/zonelist.cpp b/3rdparty/asmjit/src/asmjit/core/zonelist.cpp index d4b311d4307..ff2c2cf1540 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonelist.cpp +++ b/3rdparty/asmjit/src/asmjit/core/zonelist.cpp @@ -27,136 +27,136 @@ UNIT(zone_list) { INFO("Append / Unlink"); // [] - EXPECT(list.empty() == true); + EXPECT_TRUE(list.empty()); // [A] list.append(a); - EXPECT(list.empty() == false); - EXPECT(list.first() == a); - EXPECT(list.last() == a); - EXPECT(a->prev() == nullptr); - EXPECT(a->next() == nullptr); + EXPECT_FALSE(list.empty()); + EXPECT_EQ(list.first(), a); + EXPECT_EQ(list.last(), a); + EXPECT_NULL(a->prev()); + EXPECT_NULL(a->next()); // [A, B] list.append(b); - EXPECT(list.first() == a); - EXPECT(list.last() == b); - EXPECT(a->prev() == nullptr); - EXPECT(a->next() == b); - EXPECT(b->prev() == a); - EXPECT(b->next() == nullptr); + EXPECT_EQ(list.first(), a); + EXPECT_EQ(list.last(), b); + EXPECT_NULL(a->prev()); + EXPECT_EQ(a->next(), b); + EXPECT_EQ(b->prev(), a); + EXPECT_NULL(b->next()); // [A, B, C] list.append(c); - EXPECT(list.first() == a); - EXPECT(list.last() == c); - EXPECT(a->prev() == nullptr); - EXPECT(a->next() == b); - EXPECT(b->prev() == a); - EXPECT(b->next() == c); - EXPECT(c->prev() == b); - EXPECT(c->next() == nullptr); + EXPECT_EQ(list.first(), a); + EXPECT_EQ(list.last(), c); + EXPECT_NULL(a->prev()); + EXPECT_EQ(a->next(), b); + EXPECT_EQ(b->prev(), a); + EXPECT_EQ(b->next(), c); + EXPECT_EQ(c->prev(), b); + EXPECT_NULL(c->next()); // [B, C] list.unlink(a); - EXPECT(list.first() == b); - EXPECT(list.last() == c); - EXPECT(a->prev() == nullptr); - EXPECT(a->next() == nullptr); - EXPECT(b->prev() == nullptr); - EXPECT(b->next() == c); - EXPECT(c->prev() == b); - EXPECT(c->next() == nullptr); + EXPECT_EQ(list.first(), b); + EXPECT_EQ(list.last(), c); + EXPECT_NULL(a->prev()); + EXPECT_NULL(a->next()); + EXPECT_NULL(b->prev()); + EXPECT_EQ(b->next(), c); + EXPECT_EQ(c->prev(), b); + EXPECT_NULL(c->next()); // [B] list.unlink(c); - EXPECT(list.first() == b); - EXPECT(list.last() == b); - EXPECT(b->prev() == nullptr); - EXPECT(b->next() == nullptr); - EXPECT(c->prev() == nullptr); - EXPECT(c->next() == nullptr); + EXPECT_EQ(list.first(), b); + EXPECT_EQ(list.last(), b); + EXPECT_NULL(b->prev()); + EXPECT_NULL(b->next()); + EXPECT_NULL(c->prev()); + EXPECT_NULL(c->next()); // [] list.unlink(b); - EXPECT(list.empty() == true); - EXPECT(list.first() == nullptr); - EXPECT(list.last() == nullptr); - EXPECT(b->prev() == nullptr); - EXPECT(b->next() == nullptr); + EXPECT_TRUE(list.empty()); + EXPECT_NULL(list.first()); + EXPECT_NULL(list.last()); + EXPECT_NULL(b->prev()); + EXPECT_NULL(b->next()); INFO("Prepend / Unlink"); // [A] list.prepend(a); - EXPECT(list.empty() == false); - EXPECT(list.first() == a); - EXPECT(list.last() == a); - EXPECT(a->prev() == nullptr); - EXPECT(a->next() == nullptr); + EXPECT_FALSE(list.empty()); + EXPECT_EQ(list.first(), a); + EXPECT_EQ(list.last(), a); + EXPECT_NULL(a->prev()); + EXPECT_NULL(a->next()); // [B, A] list.prepend(b); - EXPECT(list.first() == b); - EXPECT(list.last() == a); - EXPECT(b->prev() == nullptr); - EXPECT(b->next() == a); - EXPECT(a->prev() == b); - EXPECT(a->next() == nullptr); + EXPECT_EQ(list.first(), b); + EXPECT_EQ(list.last(), a); + EXPECT_NULL(b->prev()); + EXPECT_EQ(b->next(), a); + EXPECT_EQ(a->prev(), b); + EXPECT_NULL(a->next()); INFO("InsertAfter / InsertBefore"); // [B, A, C] list.insertAfter(a, c); - EXPECT(list.first() == b); - EXPECT(list.last() == c); - EXPECT(b->prev() == nullptr); - EXPECT(b->next() == a); - EXPECT(a->prev() == b); - EXPECT(a->next() == c); - EXPECT(c->prev() == a); - EXPECT(c->next() == nullptr); + EXPECT_EQ(list.first(), b); + EXPECT_EQ(list.last(), c); + EXPECT_NULL(b->prev()); + EXPECT_EQ(b->next(), a); + EXPECT_EQ(a->prev(), b); + EXPECT_EQ(a->next(), c); + EXPECT_EQ(c->prev(), a); + EXPECT_NULL(c->next()); // [B, D, A, C] list.insertBefore(a, d); - EXPECT(list.first() == b); - EXPECT(list.last() == c); - EXPECT(b->prev() == nullptr); - EXPECT(b->next() == d); - EXPECT(d->prev() == b); - EXPECT(d->next() == a); - EXPECT(a->prev() == d); - EXPECT(a->next() == c); - EXPECT(c->prev() == a); - EXPECT(c->next() == nullptr); + EXPECT_EQ(list.first(), b); + EXPECT_EQ(list.last(), c); + EXPECT_NULL(b->prev()); + EXPECT_EQ(b->next(), d); + EXPECT_EQ(d->prev(), b); + EXPECT_EQ(d->next(), a); + EXPECT_EQ(a->prev(), d); + EXPECT_EQ(a->next(), c); + EXPECT_EQ(c->prev(), a); + EXPECT_NULL(c->next()); INFO("PopFirst / Pop"); // [D, A, C] - EXPECT(list.popFirst() == b); - EXPECT(b->prev() == nullptr); - EXPECT(b->next() == nullptr); - - EXPECT(list.first() == d); - EXPECT(list.last() == c); - EXPECT(d->prev() == nullptr); - EXPECT(d->next() == a); - EXPECT(a->prev() == d); - EXPECT(a->next() == c); - EXPECT(c->prev() == a); - EXPECT(c->next() == nullptr); + EXPECT_EQ(list.popFirst(), b); + EXPECT_NULL(b->prev()); + EXPECT_NULL(b->next()); + + EXPECT_EQ(list.first(), d); + EXPECT_EQ(list.last(), c); + EXPECT_NULL(d->prev()); + EXPECT_EQ(d->next(), a); + EXPECT_EQ(a->prev(), d); + EXPECT_EQ(a->next(), c); + EXPECT_EQ(c->prev(), a); + EXPECT_NULL(c->next()); // [D, A] - EXPECT(list.pop() == c); - EXPECT(c->prev() == nullptr); - EXPECT(c->next() == nullptr); - - EXPECT(list.first() == d); - EXPECT(list.last() == a); - EXPECT(d->prev() == nullptr); - EXPECT(d->next() == a); - EXPECT(a->prev() == d); - EXPECT(a->next() == nullptr); + EXPECT_EQ(list.pop(), c); + EXPECT_NULL(c->prev()); + EXPECT_NULL(c->next()); + + EXPECT_EQ(list.first(), d); + EXPECT_EQ(list.last(), a); + EXPECT_NULL(d->prev()); + EXPECT_EQ(d->next(), a); + EXPECT_EQ(a->prev(), d); + EXPECT_NULL(a->next()); } #endif diff --git a/3rdparty/asmjit/src/asmjit/core/zonelist.h b/3rdparty/asmjit/src/asmjit/core/zonelist.h index c5e00136589..8980240ef43 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonelist.h +++ b/3rdparty/asmjit/src/asmjit/core/zonelist.h @@ -39,10 +39,10 @@ public: //! \name Construction & Destruction //! \{ - inline ZoneListNode() noexcept + ASMJIT_INLINE_NODEBUG ZoneListNode() noexcept : _listNodes { nullptr, nullptr } {} - inline ZoneListNode(ZoneListNode&& other) noexcept + ASMJIT_INLINE_NODEBUG ZoneListNode(ZoneListNode&& other) noexcept : _listNodes { other._listNodes[0], other._listNodes[1] } {} //! \} @@ -50,11 +50,11 @@ public: //! \name Accessors //! \{ - inline bool hasPrev() const noexcept { return _listNodes[kNodeIndexPrev] != nullptr; } - inline bool hasNext() const noexcept { return _listNodes[kNodeIndexNext] != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasPrev() const noexcept { return _listNodes[kNodeIndexPrev] != nullptr; } + ASMJIT_INLINE_NODEBUG bool hasNext() const noexcept { return _listNodes[kNodeIndexNext] != nullptr; } - inline NodeT* prev() const noexcept { return _listNodes[kNodeIndexPrev]; } - inline NodeT* next() const noexcept { return _listNodes[kNodeIndexNext]; } + ASMJIT_INLINE_NODEBUG NodeT* prev() const noexcept { return _listNodes[kNodeIndexPrev]; } + ASMJIT_INLINE_NODEBUG NodeT* next() const noexcept { return _listNodes[kNodeIndexNext]; } //! \} }; @@ -78,20 +78,19 @@ public: //! \name Members //! \{ - NodeT* _nodes[2]; + NodeT* _nodes[2] {}; //! \} //! \name Construction & Destruction //! \{ - inline ZoneList() noexcept - : _nodes { nullptr, nullptr } {} + ASMJIT_INLINE_NODEBUG ZoneList() noexcept {} - inline ZoneList(ZoneList&& other) noexcept + ASMJIT_INLINE_NODEBUG ZoneList(ZoneList&& other) noexcept : _nodes { other._nodes[0], other._nodes[1] } {} - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _nodes[0] = nullptr; _nodes[1] = nullptr; } @@ -101,16 +100,16 @@ public: //! \name Accessors //! \{ - inline bool empty() const noexcept { return _nodes[0] == nullptr; } - inline NodeT* first() const noexcept { return _nodes[kNodeIndexFirst]; } - inline NodeT* last() const noexcept { return _nodes[kNodeIndexLast]; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _nodes[0] == nullptr; } + ASMJIT_INLINE_NODEBUG NodeT* first() const noexcept { return _nodes[kNodeIndexFirst]; } + ASMJIT_INLINE_NODEBUG NodeT* last() const noexcept { return _nodes[kNodeIndexLast]; } //! \} //! \name Utilities //! \{ - inline void swap(ZoneList& other) noexcept { + ASMJIT_INLINE_NODEBUG void swap(ZoneList& other) noexcept { std::swap(_nodes[0], other._nodes[0]); std::swap(_nodes[1], other._nodes[1]); } @@ -144,11 +143,11 @@ public: node->_listNodes[ dir] = next; } - inline void append(NodeT* node) noexcept { _addNode(node, kNodeIndexLast); } - inline void prepend(NodeT* node) noexcept { _addNode(node, kNodeIndexFirst); } + ASMJIT_INLINE_NODEBUG void append(NodeT* node) noexcept { _addNode(node, kNodeIndexLast); } + ASMJIT_INLINE_NODEBUG void prepend(NodeT* node) noexcept { _addNode(node, kNodeIndexFirst); } - inline void insertAfter(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexNext); } - inline void insertBefore(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexPrev); } + ASMJIT_INLINE_NODEBUG void insertAfter(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexNext); } + ASMJIT_INLINE_NODEBUG void insertBefore(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexPrev); } inline NodeT* unlink(NodeT* node) noexcept { NodeT* prev = node->prev(); diff --git a/3rdparty/asmjit/src/asmjit/core/zonestack.cpp b/3rdparty/asmjit/src/asmjit/core/zonestack.cpp index 77e6f202c7d..7d66670935b 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonestack.cpp +++ b/3rdparty/asmjit/src/asmjit/core/zonestack.cpp @@ -9,8 +9,8 @@ ASMJIT_BEGIN_NAMESPACE -// ZoneStackBase - Init & Reset -// ============================ +// ZoneStackBase - Initialization & Reset +// ====================================== Error ZoneStackBase::_init(ZoneAllocator* allocator, size_t middleIndex) noexcept { ZoneAllocator* oldAllocator = _allocator; @@ -100,18 +100,24 @@ static void test_zone_stack(ZoneAllocator* allocator, const char* typeName) { INFO("Testing ZoneStack<%s>", typeName); INFO(" (%d items per one Block)", ZoneStack<T>::kNumBlockItems); - EXPECT(stack.init(allocator) == kErrorOk); - EXPECT(stack.empty(), "Stack must be empty after `init()`"); - - EXPECT(stack.append(42) == kErrorOk); - EXPECT(!stack.empty() , "Stack must not be empty after an item has been appended"); - EXPECT(stack.pop() == 42 , "Stack.pop() must return the item that has been appended last"); - EXPECT(stack.empty() , "Stack must be empty after the last item has been removed"); - - EXPECT(stack.prepend(43) == kErrorOk); - EXPECT(!stack.empty() , "Stack must not be empty after an item has been prepended"); - EXPECT(stack.popFirst() == 43, "Stack.popFirst() must return the item that has been prepended last"); - EXPECT(stack.empty() , "Stack must be empty after the last item has been removed"); + EXPECT_EQ(stack.init(allocator), kErrorOk); + EXPECT_TRUE(stack.empty()); + + EXPECT_EQ(stack.append(42), kErrorOk); + EXPECT_FALSE(stack.empty()) + .message("Stack must not be empty after an item has been appended"); + EXPECT_EQ(stack.pop(), 42) + .message("Stack.pop() must return the item that has been appended last"); + EXPECT_TRUE(stack.empty()) + .message("Stack must be empty after the last item has been removed"); + + EXPECT_EQ(stack.prepend(43), kErrorOk); + EXPECT_FALSE(stack.empty()) + .message("Stack must not be empty after an item has been prepended"); + EXPECT_EQ(stack.popFirst(), 43) + .message("Stack.popFirst() must return the item that has been prepended last"); + EXPECT_TRUE(stack.empty()) + .message("Stack must be empty after the last item has been removed"); int i; int iMin =-100000; @@ -121,27 +127,31 @@ static void test_zone_stack(ZoneAllocator* allocator, const char* typeName) { for (i = iMax; i >= 0; i--) stack.prepend(T(i)); for (i = 0; i <= iMax; i++) { T item = stack.popFirst(); - EXPECT(i == item, "Item '%d' didn't match the item '%lld' popped", i, (long long)item); + EXPECT_EQ(i, item) + .message("Item '%d' didn't match the item '%lld' popped", i, (long long)item); if (!stack.empty()) { item = stack.popFirst(); - EXPECT(i + 1 == item, "Item '%d' didn't match the item '%lld' popped", i + 1, (long long)item); + EXPECT_EQ(i + 1, item) + .message("Item '%d' didn't match the item '%lld' popped", i + 1, (long long)item); stack.prepend(item); } } - EXPECT(stack.empty()); + EXPECT_TRUE(stack.empty()); INFO("Validating append() & pop()"); for (i = 0; i <= iMax; i++) stack.append(T(i)); for (i = iMax; i >= 0; i--) { T item = stack.pop(); - EXPECT(i == item, "Item '%d' didn't match the item '%lld' popped", i, (long long)item); + EXPECT_EQ(i, item) + .message("Item '%d' didn't match the item '%lld' popped", i, (long long)item); if (!stack.empty()) { item = stack.pop(); - EXPECT(i - 1 == item, "Item '%d' didn't match the item '%lld' popped", i - 1, (long long)item); + EXPECT_EQ(i - 1, item) + .message("Item '%d' didn't match the item '%lld' popped", i - 1, (long long)item); stack.append(item); } } - EXPECT(stack.empty()); + EXPECT_TRUE(stack.empty()); INFO("Validating append()/prepend() & popFirst()"); for (i = 1; i <= iMax; i++) stack.append(T(i)); @@ -149,9 +159,9 @@ static void test_zone_stack(ZoneAllocator* allocator, const char* typeName) { for (i = iMin; i <= iMax; i++) { T item = stack.popFirst(); - EXPECT(i == item, "Item '%d' didn't match the item '%lld' popped", i, (long long)item); + EXPECT_EQ(i, item); } - EXPECT(stack.empty()); + EXPECT_TRUE(stack.empty()); INFO("Validating append()/prepend() & pop()"); for (i = 0; i >= iMin; i--) stack.prepend(T(i)); @@ -159,9 +169,9 @@ static void test_zone_stack(ZoneAllocator* allocator, const char* typeName) { for (i = iMax; i >= iMin; i--) { T item = stack.pop(); - EXPECT(i == item, "Item '%d' didn't match the item '%lld' popped", i, (long long)item); + EXPECT_EQ(i, item); } - EXPECT(stack.empty()); + EXPECT_TRUE(stack.empty()); } UNIT(zone_stack) { diff --git a/3rdparty/asmjit/src/asmjit/core/zonestack.h b/3rdparty/asmjit/src/asmjit/core/zonestack.h index aea7b6868fa..16d5d09dbc1 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonestack.h +++ b/3rdparty/asmjit/src/asmjit/core/zonestack.h @@ -44,31 +44,33 @@ public: //! Pointer to the end of the array. void* _end; - inline bool empty() const noexcept { return _start == _end; } - inline Block* prev() const noexcept { return _link[kBlockIndexPrev]; } - inline Block* next() const noexcept { return _link[kBlockIndexNext]; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _start == _end; } + ASMJIT_INLINE_NODEBUG Block* prev() const noexcept { return _link[kBlockIndexPrev]; } + ASMJIT_INLINE_NODEBUG Block* next() const noexcept { return _link[kBlockIndexNext]; } - inline void setPrev(Block* block) noexcept { _link[kBlockIndexPrev] = block; } - inline void setNext(Block* block) noexcept { _link[kBlockIndexNext] = block; } + ASMJIT_INLINE_NODEBUG void setPrev(Block* block) noexcept { _link[kBlockIndexPrev] = block; } + ASMJIT_INLINE_NODEBUG void setNext(Block* block) noexcept { _link[kBlockIndexNext] = block; } template<typename T> - inline T* start() const noexcept { return static_cast<T*>(_start); } + ASMJIT_INLINE_NODEBUG T* start() const noexcept { return static_cast<T*>(_start); } template<typename T> - inline void setStart(T* start) noexcept { _start = static_cast<void*>(start); } + ASMJIT_INLINE_NODEBUG void setStart(T* start) noexcept { _start = static_cast<void*>(start); } template<typename T> - inline T* end() const noexcept { return (T*)_end; } + ASMJIT_INLINE_NODEBUG T* end() const noexcept { return (T*)_end; } template<typename T> - inline void setEnd(T* end) noexcept { _end = (void*)end; } + ASMJIT_INLINE_NODEBUG void setEnd(T* end) noexcept { _end = (void*)end; } template<typename T> - inline T* data() const noexcept { return (T*)((uint8_t*)(this) + sizeof(Block)); } + ASMJIT_INLINE_NODEBUG const T* data() const noexcept { return (const T*)((const uint8_t*)(this) + sizeof(Block)); } + template<typename T> + ASMJIT_INLINE_NODEBUG T* data() noexcept { return (T*)((uint8_t*)(this) + sizeof(Block)); } template<typename T> - inline bool canPrepend() const noexcept { return _start > data<void>(); } + ASMJIT_INLINE_NODEBUG bool canPrepend() const noexcept { return _start > data<void>(); } template<typename T> - inline bool canAppend() const noexcept { + ASMJIT_INLINE_NODEBUG bool canAppend() const noexcept { size_t kNumBlockItems = (kBlockSize - sizeof(Block)) / sizeof(T); size_t kStartBlockIndex = sizeof(Block); size_t kEndBlockIndex = kStartBlockIndex + kNumBlockItems * sizeof(T); @@ -83,25 +85,21 @@ public: //! \{ //! Allocator used to allocate data. - ZoneAllocator* _allocator; + ZoneAllocator* _allocator {}; //! First and last blocks. - Block* _block[2]; + Block* _block[2] {}; //! \} //! \name Construction & Destruction //! \{ - inline ZoneStackBase() noexcept { - _allocator = nullptr; - _block[0] = nullptr; - _block[1] = nullptr; - } - inline ~ZoneStackBase() noexcept { reset(); } + ASMJIT_INLINE_NODEBUG ZoneStackBase() noexcept {} + ASMJIT_INLINE_NODEBUG ~ZoneStackBase() noexcept { reset(); } - inline bool isInitialized() const noexcept { return _allocator != nullptr; } + ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _allocator != nullptr; } ASMJIT_API Error _init(ZoneAllocator* allocator, size_t middleIndex) noexcept; - inline Error reset() noexcept { return _init(nullptr, 0); } + ASMJIT_INLINE_NODEBUG Error reset() noexcept { return _init(nullptr, 0); } //! \} @@ -109,7 +107,7 @@ public: //! \{ //! Returns `ZoneAllocator` attached to this container. - inline ZoneAllocator* allocator() const noexcept { return _allocator; } + ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept { return _allocator; } inline bool empty() const noexcept { ASMJIT_ASSERT(isInitialized()); diff --git a/3rdparty/asmjit/src/asmjit/core/zonestring.h b/3rdparty/asmjit/src/asmjit/core/zonestring.h index 01f5bd89f6a..e62ac50f287 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonestring.h +++ b/3rdparty/asmjit/src/asmjit/core/zonestring.h @@ -27,7 +27,7 @@ struct ZoneStringBase { }; }; - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _dummy = nullptr; _external = nullptr; } @@ -83,8 +83,8 @@ public: //! \name Construction & Destruction //! \{ - inline ZoneString() noexcept { reset(); } - inline void reset() noexcept { _base.reset(); } + ASMJIT_INLINE_NODEBUG ZoneString() noexcept { reset(); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _base.reset(); } //! \} @@ -92,21 +92,21 @@ public: //! \{ //! Tests whether the string is empty. - inline bool empty() const noexcept { return _base._size == 0; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _base._size == 0; } //! Returns the string data. - inline const char* data() const noexcept { return _base._size <= kMaxEmbeddedSize ? _base._embedded : _base._external; } + ASMJIT_INLINE_NODEBUG const char* data() const noexcept { return _base._size <= kMaxEmbeddedSize ? _base._embedded : _base._external; } //! Returns the string size. - inline uint32_t size() const noexcept { return _base._size; } + ASMJIT_INLINE_NODEBUG uint32_t size() const noexcept { return _base._size; } //! Tests whether the string is embedded (e.g. no dynamically allocated). - inline bool isEmbedded() const noexcept { return _base._size <= kMaxEmbeddedSize; } + ASMJIT_INLINE_NODEBUG bool isEmbedded() const noexcept { return _base._size <= kMaxEmbeddedSize; } //! Copies a new `data` of the given `size` to the string. //! //! If the `size` exceeds the internal buffer the given `zone` will be used to duplicate the data, otherwise //! the internal buffer will be used as a storage. - inline Error setData(Zone* zone, const char* data, size_t size) noexcept { + ASMJIT_INLINE_NODEBUG Error setData(Zone* zone, const char* data, size_t size) noexcept { return _base.setData(zone, kMaxEmbeddedSize, data, size); } diff --git a/3rdparty/asmjit/src/asmjit/core/zonetree.cpp b/3rdparty/asmjit/src/asmjit/core/zonetree.cpp index 8c42af8c02f..e8a0e111440 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonetree.cpp +++ b/3rdparty/asmjit/src/asmjit/core/zonetree.cpp @@ -19,7 +19,7 @@ struct ZoneRBUnit { typedef ZoneTree<NodeT> Tree; static void verifyTree(Tree& tree) noexcept { - EXPECT(checkHeight(static_cast<NodeT*>(tree._root)) > 0); + EXPECT_GT(checkHeight(static_cast<NodeT*>(tree._root)), 0); } // Check whether the Red-Black tree is valid. @@ -30,17 +30,16 @@ struct ZoneRBUnit { NodeT* rn = node->right(); // Invalid tree. - EXPECT(ln == nullptr || *ln < *node); - EXPECT(rn == nullptr || *rn > *node); + EXPECT_TRUE(ln == nullptr || *ln < *node); + EXPECT_TRUE(rn == nullptr || *rn > *node); // Red violation. - EXPECT(!node->isRed() || - (!ZoneTreeNode::_isValidRed(ln) && !ZoneTreeNode::_isValidRed(rn))); + EXPECT_TRUE(!node->isRed() || (!ZoneTreeNode::_isValidRed(ln) && !ZoneTreeNode::_isValidRed(rn))); // Black violation. int lh = checkHeight(ln); int rh = checkHeight(rn); - EXPECT(!lh || !rh || lh == rh); + EXPECT_TRUE(!lh || !rh || lh == rh); // Only count black links. return (lh && rh) ? lh + !node->isRed() : 0; @@ -83,8 +82,8 @@ UNIT(zone_rbtree) { for (key = 0; key < count; key++) { node = rbTree.get(key); - EXPECT(node != nullptr); - EXPECT(node->_key == key); + EXPECT_NOT_NULL(node); + EXPECT_EQ(node->_key, key); } node = rbTree.get(--count); @@ -92,7 +91,7 @@ UNIT(zone_rbtree) { ZoneRBUnit<MyRBNode>::verifyTree(rbTree); } while (count); - EXPECT(rbTree.empty()); + EXPECT_TRUE(rbTree.empty()); } #endif diff --git a/3rdparty/asmjit/src/asmjit/core/zonetree.h b/3rdparty/asmjit/src/asmjit/core/zonetree.h index c5dbc78f496..ffeb674cfe2 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonetree.h +++ b/3rdparty/asmjit/src/asmjit/core/zonetree.h @@ -35,33 +35,32 @@ public: //! \name Members //! \{ - uintptr_t _rbNodeData[2]; + uintptr_t _rbNodeData[2] {}; //! \} //! \name Construction & Destruction //! \{ - inline ZoneTreeNode() noexcept - : _rbNodeData { 0, 0 } {} + ASMJIT_INLINE_NODEBUG ZoneTreeNode() noexcept {} //! \} //! \name Accessors //! \{ - inline bool isRed() const noexcept { return static_cast<bool>(_rbNodeData[0] & kRedMask); } + ASMJIT_INLINE_NODEBUG bool isRed() const noexcept { return static_cast<bool>(_rbNodeData[0] & kRedMask); } - inline bool hasChild(size_t i) const noexcept { return _rbNodeData[i] > kRedMask; } - inline bool hasLeft() const noexcept { return _rbNodeData[0] > kRedMask; } - inline bool hasRight() const noexcept { return _rbNodeData[1] != 0; } + ASMJIT_INLINE_NODEBUG bool hasChild(size_t i) const noexcept { return _rbNodeData[i] > kRedMask; } + ASMJIT_INLINE_NODEBUG bool hasLeft() const noexcept { return _rbNodeData[0] > kRedMask; } + ASMJIT_INLINE_NODEBUG bool hasRight() const noexcept { return _rbNodeData[1] != 0; } template<typename T = ZoneTreeNode> - inline T* child(size_t i) const noexcept { return static_cast<T*>(_getChild(i)); } + ASMJIT_INLINE_NODEBUG T* child(size_t i) const noexcept { return static_cast<T*>(_getChild(i)); } template<typename T = ZoneTreeNode> - inline T* left() const noexcept { return static_cast<T*>(_getLeft()); } + ASMJIT_INLINE_NODEBUG T* left() const noexcept { return static_cast<T*>(_getLeft()); } template<typename T = ZoneTreeNode> - inline T* right() const noexcept { return static_cast<T*>(_getRight()); } + ASMJIT_INLINE_NODEBUG T* right() const noexcept { return static_cast<T*>(_getRight()); } //! \} @@ -69,19 +68,19 @@ public: //! \name Internal //! \{ - inline ZoneTreeNode* _getChild(size_t i) const noexcept { return (ZoneTreeNode*)(_rbNodeData[i] & kPtrMask); } - inline ZoneTreeNode* _getLeft() const noexcept { return (ZoneTreeNode*)(_rbNodeData[0] & kPtrMask); } - inline ZoneTreeNode* _getRight() const noexcept { return (ZoneTreeNode*)(_rbNodeData[1]); } + ASMJIT_INLINE_NODEBUG ZoneTreeNode* _getChild(size_t i) const noexcept { return (ZoneTreeNode*)(_rbNodeData[i] & kPtrMask); } + ASMJIT_INLINE_NODEBUG ZoneTreeNode* _getLeft() const noexcept { return (ZoneTreeNode*)(_rbNodeData[0] & kPtrMask); } + ASMJIT_INLINE_NODEBUG ZoneTreeNode* _getRight() const noexcept { return (ZoneTreeNode*)(_rbNodeData[1]); } - inline void _setChild(size_t i, ZoneTreeNode* node) noexcept { _rbNodeData[i] = (_rbNodeData[i] & kRedMask) | (uintptr_t)node; } - inline void _setLeft(ZoneTreeNode* node) noexcept { _rbNodeData[0] = (_rbNodeData[0] & kRedMask) | (uintptr_t)node; } - inline void _setRight(ZoneTreeNode* node) noexcept { _rbNodeData[1] = (uintptr_t)node; } + ASMJIT_INLINE_NODEBUG void _setChild(size_t i, ZoneTreeNode* node) noexcept { _rbNodeData[i] = (_rbNodeData[i] & kRedMask) | (uintptr_t)node; } + ASMJIT_INLINE_NODEBUG void _setLeft(ZoneTreeNode* node) noexcept { _rbNodeData[0] = (_rbNodeData[0] & kRedMask) | (uintptr_t)node; } + ASMJIT_INLINE_NODEBUG void _setRight(ZoneTreeNode* node) noexcept { _rbNodeData[1] = (uintptr_t)node; } - inline void _makeRed() noexcept { _rbNodeData[0] |= kRedMask; } - inline void _makeBlack() noexcept { _rbNodeData[0] &= kPtrMask; } + ASMJIT_INLINE_NODEBUG void _makeRed() noexcept { _rbNodeData[0] |= kRedMask; } + ASMJIT_INLINE_NODEBUG void _makeBlack() noexcept { _rbNodeData[0] &= kPtrMask; } //! Tests whether the node is RED (RED node must be non-null and must have RED flag set). - static inline bool _isValidRed(ZoneTreeNode* node) noexcept { return node && node->isRed(); } + static ASMJIT_INLINE_NODEBUG bool _isValidRed(ZoneTreeNode* node) noexcept { return node && node->isRed(); } //! \} //! \endcond @@ -96,7 +95,7 @@ public: //! \name Construction & Destruction //! \{ - inline ZoneTreeNodeT() noexcept + ASMJIT_INLINE_NODEBUG ZoneTreeNodeT() noexcept : ZoneTreeNode() {} //! \} @@ -104,9 +103,9 @@ public: //! \name Accessors //! \{ - inline NodeT* child(size_t i) const noexcept { return static_cast<NodeT*>(_getChild(i)); } - inline NodeT* left() const noexcept { return static_cast<NodeT*>(_getLeft()); } - inline NodeT* right() const noexcept { return static_cast<NodeT*>(_getRight()); } + ASMJIT_INLINE_NODEBUG NodeT* child(size_t i) const noexcept { return static_cast<NodeT*>(_getChild(i)); } + ASMJIT_INLINE_NODEBUG NodeT* left() const noexcept { return static_cast<NodeT*>(_getLeft()); } + ASMJIT_INLINE_NODEBUG NodeT* right() const noexcept { return static_cast<NodeT*>(_getRight()); } //! \} }; @@ -118,33 +117,30 @@ public: ASMJIT_NONCOPYABLE(ZoneTree) typedef NodeT Node; - NodeT* _root; + NodeT* _root {}; //! \name Construction & Destruction //! \{ - inline ZoneTree() noexcept - : _root(nullptr) {} - - inline ZoneTree(ZoneTree&& other) noexcept + ASMJIT_INLINE_NODEBUG ZoneTree() noexcept {} + ASMJIT_INLINE_NODEBUG ZoneTree(ZoneTree&& other) noexcept : _root(other._root) {} - - inline void reset() noexcept { _root = nullptr; } + ASMJIT_INLINE_NODEBUG void reset() noexcept { _root = nullptr; } //! \} //! \name Accessors //! \{ - inline bool empty() const noexcept { return _root == nullptr; } - inline NodeT* root() const noexcept { return static_cast<NodeT*>(_root); } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _root == nullptr; } + ASMJIT_INLINE_NODEBUG NodeT* root() const noexcept { return static_cast<NodeT*>(_root); } //! \} //! \name Utilities //! \{ - inline void swap(ZoneTree& other) noexcept { + ASMJIT_INLINE_NODEBUG void swap(ZoneTree& other) noexcept { std::swap(_root, other._root); } diff --git a/3rdparty/asmjit/src/asmjit/core/zonevector.cpp b/3rdparty/asmjit/src/asmjit/core/zonevector.cpp index dfec5d5f795..b68e25abf65 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonevector.cpp +++ b/3rdparty/asmjit/src/asmjit/core/zonevector.cpp @@ -13,8 +13,63 @@ ASMJIT_BEGIN_NAMESPACE // ZoneVectorBase - Helpers // ======================== +// ZoneVector is used as an array to hold short-lived data structures used during code generation. The growing +// strategy is simple - use small capacity at the beginning (very good for ZoneAllocator) and then grow quicker +// to prevent successive reallocations. +static ASMJIT_FORCE_INLINE uint32_t ZoneVector_growCapacity(uint32_t current, uint32_t growMinimum, uint32_t sizeOfT) noexcept { + static constexpr size_t kGrowThreshold = Globals::kGrowThreshold; + + size_t byteSize = size_t(current) * sizeOfT; + size_t minimumByteSize = size_t(growMinimum) * sizeOfT; + + // This is more than exponential growth at the beginning. + if (byteSize < 32) { + byteSize = 32; + } + else if (byteSize < 128) { + byteSize = 128; + } + else if (byteSize < 512) { + byteSize = 512; + } + + if (byteSize < minimumByteSize) { + // Exponential growth before we reach `kGrowThreshold`. + byteSize = Support::alignUpPowerOf2(minimumByteSize); + + // Bail to `growMinimum` in case of overflow - most likely whatever that is happening afterwards would just fail. + if (byteSize < minimumByteSize) { + return growMinimum; + } + + // Pretty much chunked growth advancing by `kGrowThreshold` after we exceed it. + // This should not be a common case, so we don't really have to optimize for it. + if (byteSize > kGrowThreshold) { + // Align to kGrowThreshold. + size_t remainder = minimumByteSize % kGrowThreshold; + + byteSize = minimumByteSize + remainder; + + // Bail to `growMinimum` in case of overflow - should never happen as it's unlikely we would hit this on a 32-bit + // machine (consecutive near 4GiB allocation is impossible, and this should never happen on 64-bit machine as we + // use 32-bit size & capacity, so overflow of 64 bit integer is not possible. Added just as an extreme measure. + if (byteSize < minimumByteSize) + return growMinimum; + } + } + + size_t n = byteSize / sizeOfT; + return uint32_t(Support::min<size_t>(n, 0xFFFFFFFFu)); +} + +static ASMJIT_FORCE_INLINE bool ZoneVector_byteSizeIsSafe(size_t nBytes, uint32_t n) noexcept { + if (sizeof(uint32_t) < sizeof(size_t)) + return true; // there is no problem when running on a 64-bit machine. + else + return nBytes >= size_t(n); +}; + Error ZoneVectorBase::_grow(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept { - uint32_t threshold = Globals::kGrowThreshold / sizeOfT; uint32_t capacity = _capacity; uint32_t after = _size; @@ -25,37 +80,16 @@ Error ZoneVectorBase::_grow(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t if (capacity >= after) return kErrorOk; - // ZoneVector is used as an array to hold short-lived data structures used - // during code generation. The growing strategy is simple - use small capacity - // at the beginning (very good for ZoneAllocator) and then grow quicker to - // prevent successive reallocations. - if (capacity < 4) - capacity = 4; - else if (capacity < 8) - capacity = 8; - else if (capacity < 16) - capacity = 16; - else if (capacity < 64) - capacity = 64; - else if (capacity < 256) - capacity = 256; - - while (capacity < after) { - if (capacity < threshold) - capacity *= 2; - else - capacity += threshold; - } - - return _reserve(allocator, sizeOfT, capacity); + return _reserve(allocator, sizeOfT, ZoneVector_growCapacity(capacity, after, sizeOfT)); } Error ZoneVectorBase::_reserve(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept { uint32_t oldCapacity = _capacity; - if (oldCapacity >= n) return kErrorOk; + if (oldCapacity >= n) + return kErrorOk; - uint32_t nBytes = n * sizeOfT; - if (ASMJIT_UNLIKELY(nBytes < n)) + size_t nBytes = size_t(n) * sizeOfT; + if (ASMJIT_UNLIKELY(!ZoneVector_byteSizeIsSafe(nBytes, n))) return DebugUtils::errored(kErrorOutOfMemory); size_t allocatedBytes; @@ -64,20 +98,28 @@ Error ZoneVectorBase::_reserve(ZoneAllocator* allocator, uint32_t sizeOfT, uint3 if (ASMJIT_UNLIKELY(!newData)) return DebugUtils::errored(kErrorOutOfMemory); + uint32_t newCapacity = uint32_t(allocatedBytes / sizeOfT); + ASMJIT_ASSERT(newCapacity >= n); + void* oldData = _data; - if (_size) + if (oldData && _size) { memcpy(newData, oldData, size_t(_size) * sizeOfT); - - if (oldData) allocator->release(oldData, size_t(oldCapacity) * sizeOfT); - - _capacity = uint32_t(allocatedBytes / sizeOfT); - ASMJIT_ASSERT(_capacity >= n); + } _data = newData; + _capacity = newCapacity; + return kErrorOk; } +Error ZoneVectorBase::_growingReserve(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept { + uint32_t capacity = _capacity; + if (capacity >= n) + return kErrorOk; + return _reserve(allocator, sizeOfT, ZoneVector_growCapacity(capacity, n, sizeOfT)); +} + Error ZoneVectorBase::_resize(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept { uint32_t size = _size; @@ -266,34 +308,59 @@ Error ZoneBitVector::_append(ZoneAllocator* allocator, bool value) noexcept { #if defined(ASMJIT_TEST) template<typename T> static void test_zone_vector(ZoneAllocator* allocator, const char* typeName) { + constexpr uint32_t kMiB = 1024 * 1024; + int i; int kMax = 100000; ZoneVector<T> vec; INFO("ZoneVector<%s> basic tests", typeName); - EXPECT(vec.append(allocator, 0) == kErrorOk); - EXPECT(vec.empty() == false); - EXPECT(vec.size() == 1); - EXPECT(vec.capacity() >= 1); - EXPECT(vec.indexOf(0) == 0); - EXPECT(vec.indexOf(-11) == Globals::kNotFound); + EXPECT_EQ(vec.append(allocator, 0), kErrorOk); + EXPECT_FALSE(vec.empty()); + EXPECT_EQ(vec.size(), 1u); + EXPECT_GE(vec.capacity(), 1u); + EXPECT_EQ(vec.indexOf(0), 0u); + EXPECT_EQ(vec.indexOf(-11), Globals::kNotFound); vec.clear(); - EXPECT(vec.empty()); - EXPECT(vec.size() == 0); - EXPECT(vec.indexOf(0) == Globals::kNotFound); + EXPECT_TRUE(vec.empty()); + EXPECT_EQ(vec.size(), 0u); + EXPECT_EQ(vec.indexOf(0), Globals::kNotFound); for (i = 0; i < kMax; i++) { - EXPECT(vec.append(allocator, T(i)) == kErrorOk); + EXPECT_EQ(vec.append(allocator, T(i)), kErrorOk); } - EXPECT(vec.empty() == false); - EXPECT(vec.size() == uint32_t(kMax)); - EXPECT(vec.indexOf(T(kMax - 1)) == uint32_t(kMax - 1)); + EXPECT_FALSE(vec.empty()); + EXPECT_EQ(vec.size(), uint32_t(kMax)); + EXPECT_EQ(vec.indexOf(T(0)), uint32_t(0)); + EXPECT_EQ(vec.indexOf(T(kMax - 1)), uint32_t(kMax - 1)); + + EXPECT_EQ(vec.begin()[0], 0); + EXPECT_EQ(vec.end()[-1], kMax - 1); + + EXPECT_EQ(vec.rbegin()[0], kMax - 1); + EXPECT_EQ(vec.rend()[-1], 0); - EXPECT(vec.rbegin()[0] == kMax - 1); + int64_t fsum = 0; + int64_t rsum = 0; + + for (const T& item : vec) { + fsum += item; + } + for (auto it = vec.rbegin(); it != vec.rend(); ++it) { + rsum += *it; + } + + EXPECT_EQ(fsum, rsum); vec.release(allocator); + + INFO("ZoneBitVector::growingReserve()"); + for (uint32_t j = 0; j < 40 / sizeof(T); j += 8) { + EXPECT_EQ(vec.growingReserve(allocator, j * kMiB), kErrorOk); + EXPECT_GE(vec.capacity(), j * kMiB); + } } static void test_zone_bitvector(ZoneAllocator* allocator) { @@ -303,31 +370,31 @@ static void test_zone_bitvector(ZoneAllocator* allocator) { uint32_t kMaxCount = 100; ZoneBitVector vec; - EXPECT(vec.empty()); - EXPECT(vec.size() == 0); + EXPECT_TRUE(vec.empty()); + EXPECT_EQ(vec.size(), 0u); INFO("ZoneBitVector::resize()"); for (count = 1; count < kMaxCount; count++) { vec.clear(); - EXPECT(vec.resize(allocator, count, false) == kErrorOk); - EXPECT(vec.size() == count); + EXPECT_EQ(vec.resize(allocator, count, false), kErrorOk); + EXPECT_EQ(vec.size(), count); for (i = 0; i < count; i++) - EXPECT(vec.bitAt(i) == false); + EXPECT_FALSE(vec.bitAt(i)); vec.clear(); - EXPECT(vec.resize(allocator, count, true) == kErrorOk); - EXPECT(vec.size() == count); + EXPECT_EQ(vec.resize(allocator, count, true), kErrorOk); + EXPECT_EQ(vec.size(), count); for (i = 0; i < count; i++) - EXPECT(vec.bitAt(i) == true); + EXPECT_TRUE(vec.bitAt(i)); } INFO("ZoneBitVector::fillBits() / clearBits()"); for (count = 1; count < kMaxCount; count += 2) { vec.clear(); - EXPECT(vec.resize(allocator, count) == kErrorOk); - EXPECT(vec.size() == count); + EXPECT_EQ(vec.resize(allocator, count), kErrorOk); + EXPECT_EQ(vec.size(), count); for (i = 0; i < (count + 1) / 2; i++) { bool value = bool(i & 1); @@ -338,7 +405,7 @@ static void test_zone_bitvector(ZoneAllocator* allocator) { } for (i = 0; i < count; i++) { - EXPECT(vec.bitAt(i) == bool(i & 1)); + EXPECT_EQ(vec.bitAt(i), bool(i & 1)); } } } diff --git a/3rdparty/asmjit/src/asmjit/core/zonevector.h b/3rdparty/asmjit/src/asmjit/core/zonevector.h index 447c08cb921..f38dca583a0 100644 --- a/3rdparty/asmjit/src/asmjit/core/zonevector.h +++ b/3rdparty/asmjit/src/asmjit/core/zonevector.h @@ -58,6 +58,7 @@ protected: ASMJIT_API Error _grow(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept; ASMJIT_API Error _resize(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept; ASMJIT_API Error _reserve(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept; + ASMJIT_API Error _growingReserve(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept; inline void _swap(ZoneVectorBase& other) noexcept { std::swap(_data, other._data); @@ -73,11 +74,11 @@ public: //! \{ //! Tests whether the vector is empty. - inline bool empty() const noexcept { return _size == 0; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; } //! Returns the vector size. - inline size_type size() const noexcept { return _size; } + ASMJIT_INLINE_NODEBUG size_type size() const noexcept { return _size; } //! Returns the vector capacity. - inline size_type capacity() const noexcept { return _capacity; } + ASMJIT_INLINE_NODEBUG size_type capacity() const noexcept { return _capacity; } //! \} @@ -85,16 +86,16 @@ public: //! \{ //! Makes the vector empty (won't change the capacity or data pointer). - inline void clear() noexcept { _size = 0; } + ASMJIT_INLINE_NODEBUG void clear() noexcept { _size = 0; } //! Resets the vector data and set its `size` to zero. - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _data = nullptr; _size = 0; _capacity = 0; } //! Truncates the vector to at most `n` items. - inline void truncate(size_type n) noexcept { + ASMJIT_INLINE_NODEBUG void truncate(size_type n) noexcept { _size = Support::min(_size, n); } @@ -128,14 +129,14 @@ public: typedef T* iterator; typedef const T* const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef Support::ArrayReverseIterator<T> reverse_iterator; + typedef Support::ArrayReverseIterator<const T> const_reverse_iterator; //! \name Construction & Destruction //! \{ - inline ZoneVector() noexcept : ZoneVectorBase() {} - inline ZoneVector(ZoneVector&& other) noexcept : ZoneVector(other) {} + ASMJIT_INLINE_NODEBUG ZoneVector() noexcept : ZoneVectorBase() {} + ASMJIT_INLINE_NODEBUG ZoneVector(ZoneVector&& other) noexcept : ZoneVector(other) {} //! \} @@ -143,9 +144,9 @@ public: //! \{ //! Returns vector data. - inline T* data() noexcept { return static_cast<T*>(_data); } + ASMJIT_INLINE_NODEBUG T* data() noexcept { return static_cast<T*>(_data); } //! Returns vector data (const) - inline const T* data() const noexcept { return static_cast<const T*>(_data); } + ASMJIT_INLINE_NODEBUG const T* data() const noexcept { return static_cast<const T*>(_data); } //! Returns item at the given index `i` (const). inline const T& at(size_t i) const noexcept { @@ -163,23 +164,23 @@ public: //! \name STL Compatibility (Iterators) //! \{ - inline iterator begin() noexcept { return iterator(data()); }; - inline const_iterator begin() const noexcept { return const_iterator(data()); }; + ASMJIT_INLINE_NODEBUG iterator begin() noexcept { return iterator(data()); }; + ASMJIT_INLINE_NODEBUG const_iterator begin() const noexcept { return const_iterator(data()); }; - inline iterator end() noexcept { return iterator(data() + _size); }; - inline const_iterator end() const noexcept { return const_iterator(data() + _size); }; + ASMJIT_INLINE_NODEBUG iterator end() noexcept { return iterator(data() + _size); }; + ASMJIT_INLINE_NODEBUG const_iterator end() const noexcept { return const_iterator(data() + _size); }; - inline reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }; - inline const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }; + ASMJIT_INLINE_NODEBUG reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }; + ASMJIT_INLINE_NODEBUG const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }; - inline reverse_iterator rend() noexcept { return reverse_iterator(begin()); }; - inline const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }; + ASMJIT_INLINE_NODEBUG reverse_iterator rend() noexcept { return reverse_iterator(begin()); }; + ASMJIT_INLINE_NODEBUG const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }; - inline const_iterator cbegin() const noexcept { return const_iterator(data()); }; - inline const_iterator cend() const noexcept { return const_iterator(data() + _size); }; + ASMJIT_INLINE_NODEBUG const_iterator cbegin() const noexcept { return const_iterator(data()); }; + ASMJIT_INLINE_NODEBUG const_iterator cend() const noexcept { return const_iterator(data() + _size); }; - inline const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }; - inline const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }; + ASMJIT_INLINE_NODEBUG const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }; + ASMJIT_INLINE_NODEBUG const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }; //! \} @@ -194,8 +195,13 @@ public: if (ASMJIT_UNLIKELY(_size == _capacity)) ASMJIT_PROPAGATE(grow(allocator, 1)); - ::memmove(static_cast<T*>(_data) + 1, _data, size_t(_size) * sizeof(T)); - memcpy(_data, &item, sizeof(T)); + memmove(static_cast<void*>(static_cast<T*>(_data) + 1), + static_cast<const void*>(_data), + size_t(_size) * sizeof(T)); + + memcpy(static_cast<void*>(_data), + static_cast<const void*>(&item), + sizeof(T)); _size++; return kErrorOk; @@ -209,10 +215,15 @@ public: ASMJIT_PROPAGATE(grow(allocator, 1)); T* dst = static_cast<T*>(_data) + index; - ::memmove(dst + 1, dst, size_t(_size - index) * sizeof(T)); - memcpy(dst, &item, sizeof(T)); - _size++; + memmove(static_cast<void*>(dst + 1), + static_cast<const void*>(dst), + size_t(_size - index) * sizeof(T)); + + memcpy(static_cast<void*>(dst), + static_cast<const void*>(&item), + sizeof(T)); + _size++; return kErrorOk; } @@ -221,9 +232,11 @@ public: if (ASMJIT_UNLIKELY(_size == _capacity)) ASMJIT_PROPAGATE(grow(allocator, 1)); - memcpy(static_cast<T*>(_data) + _size, &item, sizeof(T)); - _size++; + memcpy(static_cast<void*>(static_cast<T*>(_data) + _size), + static_cast<const void*>(&item), + sizeof(T)); + _size++; return kErrorOk; } @@ -234,7 +247,9 @@ public: ASMJIT_PROPAGATE(grow(allocator, size)); if (size) { - memcpy(static_cast<T*>(_data) + _size, other._data, size_t(size) * sizeof(T)); + memcpy(static_cast<void*>(static_cast<T*>(_data) + _size), + static_cast<const void*>(other._data), + size_t(size) * sizeof(T)); _size += size; } @@ -249,10 +264,15 @@ public: ASMJIT_ASSERT(_size < _capacity); T* data = static_cast<T*>(_data); - if (_size) - ::memmove(data + 1, data, size_t(_size) * sizeof(T)); + if (_size) { + memmove(static_cast<void*>(data + 1), + static_cast<const void*>(data), + size_t(_size) * sizeof(T)); + } - memcpy(data, &item, sizeof(T)); + memcpy(static_cast<void*>(data), + static_cast<const void*>(&item), + sizeof(T)); _size++; } @@ -263,7 +283,9 @@ public: ASMJIT_FORCE_INLINE void appendUnsafe(const T& item) noexcept { ASMJIT_ASSERT(_size < _capacity); - memcpy(static_cast<T*>(_data) + _size, &item, sizeof(T)); + memcpy(static_cast<void*>(static_cast<T*>(_data) + _size), + static_cast<const void*>(&item), + sizeof(T)); _size++; } @@ -273,17 +295,26 @@ public: ASMJIT_ASSERT(index <= _size); T* dst = static_cast<T*>(_data) + index; - ::memmove(dst + 1, dst, size_t(_size - index) * sizeof(T)); - memcpy(dst, &item, sizeof(T)); + memmove(static_cast<void*>(dst + 1), + static_cast<const void*>(dst), + size_t(_size - index) * sizeof(T)); + + memcpy(static_cast<void*>(dst), + static_cast<const void*>(&item), + sizeof(T)); + _size++; } + //! Concatenates all items of `other` at the end of the vector. ASMJIT_FORCE_INLINE void concatUnsafe(const ZoneVector<T>& other) noexcept { uint32_t size = other._size; ASMJIT_ASSERT(_capacity - _size >= size); if (size) { - memcpy(static_cast<T*>(_data) + _size, other._data, size_t(size) * sizeof(T)); + memcpy(static_cast<void*>(static_cast<T*>(_data) + _size), + static_cast<const void*>(other._data), + size_t(size) * sizeof(T)); _size += size; } } @@ -311,8 +342,11 @@ public: T* data = static_cast<T*>(_data) + i; size_t size = --_size - i; - if (size) - ::memmove(data, data + 1, size_t(size) * sizeof(T)); + if (size) { + memmove(static_cast<void*>(data), + static_cast<const void*>(data + 1), + size_t(size) * sizeof(T)); + } } //! Pops the last element from the vector and returns it. @@ -344,9 +378,9 @@ public: //! //! \note The vector must have at least one element. Attempting to use `first()` on empty vector will trigger //! an assertion failure in debug builds. - inline T& first() noexcept { return operator[](0); } + ASMJIT_INLINE_NODEBUG T& first() noexcept { return operator[](0); } //! \overload - inline const T& first() const noexcept { return operator[](0); } + ASMJIT_INLINE_NODEBUG const T& first() const noexcept { return operator[](0); } //! Returns a reference to the last element of the vector. //! @@ -381,7 +415,21 @@ public: //! Reallocates the internal array to fit at least `n` items. inline Error reserve(ZoneAllocator* allocator, uint32_t n) noexcept { - return n > _capacity ? ZoneVectorBase::_reserve(allocator, sizeof(T), n) : Error(kErrorOk); + if (ASMJIT_UNLIKELY(n > _capacity)) + return ZoneVectorBase::_reserve(allocator, sizeof(T), n); + else + return Error(kErrorOk); + } + + //! Reallocates the internal array to fit at least `n` items with growing semantics. + //! + //! If the vector is smaller than `n` the same growing calculations will be used as if N items were appended + //! to an empty vector, which means reserving additional space for more append operations that could follow. + inline Error growingReserve(ZoneAllocator* allocator, uint32_t n) noexcept { + if (ASMJIT_UNLIKELY(n > _capacity)) + return ZoneVectorBase::_growingReserve(allocator, sizeof(T), n); + else + return Error(kErrorOk); } inline Error willGrow(ZoneAllocator* allocator, uint32_t n = 1) noexcept { @@ -423,21 +471,21 @@ public: //! \name Internal //! \{ - static inline uint32_t _wordsPerBits(uint32_t nBits) noexcept { + static ASMJIT_INLINE_NODEBUG uint32_t _wordsPerBits(uint32_t nBits) noexcept { return ((nBits + kBitWordSizeInBits - 1) / kBitWordSizeInBits); } - static inline void _zeroBits(BitWord* dst, uint32_t nBitWords) noexcept { + static ASMJIT_INLINE_NODEBUG void _zeroBits(BitWord* dst, uint32_t nBitWords) noexcept { for (uint32_t i = 0; i < nBitWords; i++) dst[i] = 0; } - static inline void _fillBits(BitWord* dst, uint32_t nBitWords) noexcept { + static ASMJIT_INLINE_NODEBUG void _fillBits(BitWord* dst, uint32_t nBitWords) noexcept { for (uint32_t i = 0; i < nBitWords; i++) dst[i] = ~BitWord(0); } - static inline void _copyBits(BitWord* dst, const BitWord* src, uint32_t nBitWords) noexcept { + static ASMJIT_INLINE_NODEBUG void _copyBits(BitWord* dst, const BitWord* src, uint32_t nBitWords) noexcept { for (uint32_t i = 0; i < nBitWords; i++) dst[i] = src[i]; } @@ -448,9 +496,9 @@ public: //! \name Construction & Destruction //! \{ - inline ZoneBitVector() noexcept {} + ASMJIT_INLINE_NODEBUG ZoneBitVector() noexcept {} - inline ZoneBitVector(ZoneBitVector&& other) noexcept + ASMJIT_INLINE_NODEBUG ZoneBitVector(ZoneBitVector&& other) noexcept : _data(other._data), _size(other._size), _capacity(other._capacity) {} @@ -460,8 +508,8 @@ public: //! \name Overloaded Operators //! \{ - inline bool operator==(const ZoneBitVector& other) const noexcept { return eq(other); } - inline bool operator!=(const ZoneBitVector& other) const noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const ZoneBitVector& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const ZoneBitVector& other) const noexcept { return !equals(other); } //! \} @@ -469,44 +517,44 @@ public: //! \{ //! Tests whether the bit-vector is empty (has no bits). - inline bool empty() const noexcept { return _size == 0; } + ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; } //! Returns the size of this bit-vector (in bits). - inline uint32_t size() const noexcept { return _size; } + ASMJIT_INLINE_NODEBUG uint32_t size() const noexcept { return _size; } //! Returns the capacity of this bit-vector (in bits). - inline uint32_t capacity() const noexcept { return _capacity; } + ASMJIT_INLINE_NODEBUG uint32_t capacity() const noexcept { return _capacity; } //! Returns the size of the `BitWord[]` array in `BitWord` units. - inline uint32_t sizeInBitWords() const noexcept { return _wordsPerBits(_size); } + ASMJIT_INLINE_NODEBUG uint32_t sizeInBitWords() const noexcept { return _wordsPerBits(_size); } //! Returns the capacity of the `BitWord[]` array in `BitWord` units. - inline uint32_t capacityInBitWords() const noexcept { return _wordsPerBits(_capacity); } + ASMJIT_INLINE_NODEBUG uint32_t capacityInBitWords() const noexcept { return _wordsPerBits(_capacity); } - //! REturns bit-vector data as `BitWord[]`. - inline BitWord* data() noexcept { return _data; } + //! Returns bit-vector data as `BitWord[]`. + ASMJIT_INLINE_NODEBUG BitWord* data() noexcept { return _data; } //! \overload - inline const BitWord* data() const noexcept { return _data; } + ASMJIT_INLINE_NODEBUG const BitWord* data() const noexcept { return _data; } //! \} //! \name Utilities //! \{ - inline void swap(ZoneBitVector& other) noexcept { + ASMJIT_INLINE_NODEBUG void swap(ZoneBitVector& other) noexcept { std::swap(_data, other._data); std::swap(_size, other._size); std::swap(_capacity, other._capacity); } - inline void clear() noexcept { + ASMJIT_INLINE_NODEBUG void clear() noexcept { _size = 0; } - inline void reset() noexcept { + ASMJIT_INLINE_NODEBUG void reset() noexcept { _data = nullptr; _size = 0; _capacity = 0; } - inline void truncate(uint32_t newSize) noexcept { + ASMJIT_INLINE_NODEBUG void truncate(uint32_t newSize) noexcept { _size = Support::min(_size, newSize); _clearUnusedBits(); } @@ -628,7 +676,7 @@ public: _data[idx] &= (BitWord(1) << bit) - 1u; } - ASMJIT_FORCE_INLINE bool eq(const ZoneBitVector& other) const noexcept { + ASMJIT_FORCE_INLINE bool equals(const ZoneBitVector& other) const noexcept { if (_size != other._size) return false; @@ -642,18 +690,24 @@ public: return true; } +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use ZoneVector::equals() instead") + ASMJIT_FORCE_INLINE bool eq(const ZoneBitVector& other) const noexcept { return equals(other); } +#endif // !ASMJIT_NO_DEPRECATED + //! \} //! \name Memory Management //! \{ inline void release(ZoneAllocator* allocator) noexcept { - if (!_data) return; + if (!_data) + return; allocator->release(_data, _capacity / 8); reset(); } - inline Error resize(ZoneAllocator* allocator, uint32_t newSize, bool newBitsValue = false) noexcept { + ASMJIT_INLINE_NODEBUG Error resize(ZoneAllocator* allocator, uint32_t newSize, bool newBitsValue = false) noexcept { return _resize(allocator, newSize, newSize, newBitsValue); } diff --git a/3rdparty/asmjit/src/asmjit/x86/x86assembler.cpp b/3rdparty/asmjit/src/asmjit/x86/x86assembler.cpp index f11fea00238..35c5502cc66 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86assembler.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86assembler.cpp @@ -345,6 +345,10 @@ static ASMJIT_FORCE_INLINE uint32_t x86AltOpcodeOf(const InstDB::InstInfo* info) return InstDB::_altOpcodeTable[info->_altOpcodeIndex]; } +static ASMJIT_FORCE_INLINE bool x86IsMmxOrXmm(const Reg& reg) noexcept { + return reg.type() == RegType::kX86_Mm || reg.type() == RegType::kX86_Xmm; +} + // x86::Assembler - X86BufferWriter // ================================ @@ -493,11 +497,11 @@ static ASMJIT_FORCE_INLINE uint32_t x86GetMovAbsInstSize64Bit(uint32_t regSize, static ASMJIT_FORCE_INLINE bool x86ShouldUseMovabs(Assembler* self, X86BufferWriter& writer, uint32_t regSize, InstOptions options, const Mem& rmRel) noexcept { if (self->is32Bit()) { // There is no relative addressing, just decide whether to use MOV encoded with MOD R/M or absolute. - return !Support::test(options, InstOptions::kX86_ModMR | InstOptions::kX86_ModMR); + return !Support::test(options, InstOptions::kX86_ModMR | InstOptions::kX86_ModRM); } else { // If the addressing type is REL or MOD R/M was specified then absolute mov won't be used. - if (rmRel.addrType() == Mem::AddrType::kRel || Support::test(options, InstOptions::kX86_ModMR)) + if (rmRel.addrType() == Mem::AddrType::kRel || Support::test(options, InstOptions::kX86_ModMR | InstOptions::kX86_ModRM)) return false; int64_t addrValue = rmRel.offset(); @@ -529,8 +533,6 @@ static ASMJIT_FORCE_INLINE bool x86ShouldUseMovabs(Assembler* self, X86BufferWri Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | (uint64_t(1) << uint32_t(Arch::kX64)) ; - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -560,7 +562,7 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con const Operand_* rmRel; // Memory operand or operand that holds Label|Imm. uint32_t rmInfo; // Memory operand's info based on x86MemInfo. - uint32_t rbReg; // Memory base or modRM register. + uint32_t rbReg = 0; // Memory base or modRM register. uint32_t rxReg; // Memory index register. uint32_t opReg; // ModR/M opcode or register id. @@ -610,7 +612,7 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con Operand_ opArray[Globals::kMaxOpCount]; EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); + err = _funcs.validate(BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); if (ASMJIT_UNLIKELY(err)) goto Failed; } @@ -653,7 +655,6 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con // This sequence seems to be the fastest. opcode = InstDB::_mainOpcodeTable[instInfo->_mainOpcodeIndex]; opReg = opcode.extractModO(); - rbReg = 0; opcode |= instInfo->_mainOpcodeValue; // Encoding Scope @@ -740,11 +741,11 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con case InstDB::kEncodingX86M_NoMemSize: if (o0.isReg()) - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); goto CaseX86M_NoSize; case InstDB::kEncodingX86M: - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingX86M_NoSize: @@ -783,20 +784,20 @@ CaseX86M_GPB_MulDiv: // [?DX:?AX] <- [?DX:?AX] div|mul r16|r32|r64 if (isign3 == ENC_OPS3(Reg, Reg, Reg)) { - if (ASMJIT_UNLIKELY(o0.size() != o1.size())) + if (ASMJIT_UNLIKELY(o0.x86RmSize() != o1.x86RmSize())) goto InvalidInstruction; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rbReg = o2.id(); goto EmitX86R; } // [?DX:?AX] <- [?DX:?AX] div|mul m16|m32|m64 if (isign3 == ENC_OPS3(Reg, Reg, Mem)) { - if (ASMJIT_UNLIKELY(o0.size() != o1.size())) + if (ASMJIT_UNLIKELY(o0.x86RmSize() != o1.x86RmSize())) goto InvalidInstruction; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rmRel = &o2; goto EmitX86M; } @@ -808,10 +809,10 @@ CaseX86M_GPB_MulDiv: case InstDB::kEncodingX86M_GPB: if (isign3 == ENC_OPS1(Reg)) { - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rbReg = o0.id(); - if (o0.size() != 1) + if (o0.x86RmSize() != 1) goto EmitX86R; FIXUP_GPB(o0, rbReg); @@ -819,10 +820,10 @@ CaseX86M_GPB_MulDiv: } if (isign3 == ENC_OPS1(Mem)) { - if (ASMJIT_UNLIKELY(o0.size() == 0)) + if (ASMJIT_UNLIKELY(o0.x86RmSize() == 0)) goto AmbiguousOperandSize; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rmRel = &o0; goto EmitX86M; } @@ -851,20 +852,20 @@ CaseX86M_GPB_MulDiv: opReg = 0; if (isign3 == ENC_OPS1(Reg)) { - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); rbReg = o0.id(); goto EmitX86R; } if (isign3 == ENC_OPS1(Mem)) { - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); rmRel = &o0; goto EmitX86M; } // Two operand NOP instruction "0F 1F /r". opReg = o1.id(); - opcode.addPrefixBySize(o1.size()); + opcode.addPrefixBySize(o1.x86RmSize()); if (isign3 == ENC_OPS2(Reg, Reg)) { rbReg = o0.id(); @@ -911,7 +912,7 @@ CaseX86M_GPB_MulDiv: break; case InstDB::kEncodingX86Rm: - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingX86Rm_NoSize: @@ -934,10 +935,10 @@ CaseX86M_GPB_MulDiv: opReg = o0.id(); rbReg = o1.id(); - if (o0.size() == 2) + if (o0.x86RmSize() == 2) writer.emit8(0x66); else - opcode.addWBySize(o0.size()); + opcode.addWBySize(o0.x86RmSize()); goto EmitX86R; } @@ -945,16 +946,16 @@ CaseX86M_GPB_MulDiv: opReg = o0.id(); rmRel = &o1; - if (o0.size() == 2) + if (o0.x86RmSize() == 2) writer.emit8(0x66); else - opcode.addWBySize(o0.size()); + opcode.addWBySize(o0.x86RmSize()); goto EmitX86M; } break; case InstDB::kEncodingX86Mr: - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingX86Mr_NoSize: @@ -973,15 +974,15 @@ CaseX86M_GPB_MulDiv: case InstDB::kEncodingX86Arith: if (isign3 == ENC_OPS2(Reg, Reg)) { - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); - if (o0.size() != o1.size()) + if (o0.x86RmSize() != o1.x86RmSize()) goto OperandSizeMismatch; rbReg = o0.id(); opReg = o1.id(); - if (o0.size() == 1) { + if (o0.x86RmSize() == 1) { FIXUP_GPB(o0, rbReg); FIXUP_GPB(o1, opReg); } @@ -991,19 +992,19 @@ CaseX86M_GPB_MulDiv: goto EmitX86R; // MOD/RM: Alternative encoding selected via instruction options. - opcode += 2; + opcode += 2u; std::swap(opReg, rbReg); goto EmitX86R; } if (isign3 == ENC_OPS2(Reg, Mem)) { - opcode += 2; - opcode.addArithBySize(o0.size()); + opcode += 2u; + opcode.addArithBySize(o0.x86RmSize()); opReg = o0.id(); rmRel = &o1; - if (o0.size() != 1) + if (o0.x86RmSize() != 1) goto EmitX86M; FIXUP_GPB(o0, opReg); @@ -1011,11 +1012,11 @@ CaseX86M_GPB_MulDiv: } if (isign3 == ENC_OPS2(Mem, Reg)) { - opcode.addArithBySize(o1.size()); + opcode.addArithBySize(o1.x86RmSize()); opReg = o1.id(); rmRel = &o0; - if (o1.size() != 1) + if (o1.x86RmSize() != 1) goto EmitX86M; FIXUP_GPB(o1, opReg); @@ -1026,7 +1027,7 @@ CaseX86M_GPB_MulDiv: opcode = 0x80; if (isign3 == ENC_OPS2(Reg, Imm)) { - uint32_t size = o0.size(); + uint32_t size = o0.x86RmSize(); rbReg = o0.id(); immValue = o1.as<Imm>().value(); @@ -1075,12 +1076,12 @@ CaseX86M_GPB_MulDiv: goto EmitX86Op; } - opcode += size != 1 ? (immSize != 1 ? 1 : 3) : 0; + opcode += size != 1 ? (immSize != 1 ? 1u : 3u) : 0u; goto EmitX86R; } if (isign3 == ENC_OPS2(Mem, Imm)) { - uint32_t memSize = o0.size(); + uint32_t memSize = o0.x86RmSize(); if (ASMJIT_UNLIKELY(memSize == 0)) goto AmbiguousOperandSize; @@ -1095,7 +1096,7 @@ CaseX86M_GPB_MulDiv: if (Support::isInt8(immValue) && !Support::test(options, InstOptions::kLongForm)) immSize = 1; - opcode += memSize != 1 ? (immSize != 1 ? 1 : 3) : 0; + opcode += memSize != 1 ? (immSize != 1 ? 1u : 3u) : 0u; opcode.addPrefixBySize(memSize); rmRel = &o0; @@ -1105,25 +1106,25 @@ CaseX86M_GPB_MulDiv: case InstDB::kEncodingX86Bswap: if (isign3 == ENC_OPS1(Reg)) { - if (ASMJIT_UNLIKELY(o0.size() == 1)) + if (ASMJIT_UNLIKELY(o0.x86RmSize() == 1)) goto InvalidInstruction; opReg = o0.id(); - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); goto EmitX86OpReg; } break; case InstDB::kEncodingX86Bt: if (isign3 == ENC_OPS2(Reg, Reg)) { - opcode.addPrefixBySize(o1.size()); + opcode.addPrefixBySize(o1.x86RmSize()); opReg = o1.id(); rbReg = o0.id(); goto EmitX86R; } if (isign3 == ENC_OPS2(Mem, Reg)) { - opcode.addPrefixBySize(o1.size()); + opcode.addPrefixBySize(o1.x86RmSize()); opReg = o1.id(); rmRel = &o0; goto EmitX86M; @@ -1134,7 +1135,7 @@ CaseX86M_GPB_MulDiv: immSize = 1; opcode = x86AltOpcodeOf(instInfo); - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); opReg = opcode.extractModO(); if (isign3 == ENC_OPS2(Reg, Imm)) { @@ -1143,7 +1144,7 @@ CaseX86M_GPB_MulDiv: } if (isign3 == ENC_OPS2(Mem, Imm)) { - if (ASMJIT_UNLIKELY(o0.size() == 0)) + if (ASMJIT_UNLIKELY(o0.x86RmSize() == 0)) goto AmbiguousOperandSize; rmRel = &o0; @@ -1176,14 +1177,14 @@ CaseX86M_GPB_MulDiv: } if (isign3 == ENC_OPS2(Reg, Reg)) { - if (o0.size() != o1.size()) + if (o0.x86RmSize() != o1.x86RmSize()) goto OperandSizeMismatch; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rbReg = o0.id(); opReg = o1.id(); - if (o0.size() != 1) + if (o0.x86RmSize() != 1) goto EmitX86R; FIXUP_GPB(o0, rbReg); @@ -1192,11 +1193,11 @@ CaseX86M_GPB_MulDiv: } if (isign3 == ENC_OPS2(Mem, Reg)) { - opcode.addArithBySize(o1.size()); + opcode.addArithBySize(o1.x86RmSize()); opReg = o1.id(); rmRel = &o0; - if (o1.size() != 1) + if (o1.x86RmSize() != 1) goto EmitX86M; FIXUP_GPB(o1, opReg); @@ -1225,18 +1226,18 @@ CaseX86M_GPB_MulDiv: case InstDB::kEncodingX86Crc: opReg = o0.id(); - opcode.addWBySize(o0.size()); + opcode.addWBySize(o0.x86RmSize()); if (isign3 == ENC_OPS2(Reg, Reg)) { rbReg = o1.id(); - if (o1.size() == 1) { + if (o1.x86RmSize() == 1) { FIXUP_GPB(o1, rbReg); goto EmitX86R; } else { // This seems to be the only exception of encoding '66F2' prefix. - if (o1.size() == 2) writer.emit8(0x66); + if (o1.x86RmSize() == 2) writer.emit8(0x66); opcode.add(1); goto EmitX86R; @@ -1245,13 +1246,13 @@ CaseX86M_GPB_MulDiv: if (isign3 == ENC_OPS2(Reg, Mem)) { rmRel = &o1; - if (o1.size() == 0) + if (o1.x86RmSize() == 0) goto AmbiguousOperandSize; // This seems to be the only exception of encoding '66F2' prefix. - if (o1.size() == 2) writer.emit8(0x66); + if (o1.x86RmSize() == 2) writer.emit8(0x66); - opcode += o1.size() != 1; + opcode += uint32_t(o1.x86RmSize() != 1u); goto EmitX86M; } break; @@ -1271,14 +1272,14 @@ CaseX86M_GPB_MulDiv: // First process all forms distinct of `kEncodingX86M_OptB_MulDiv`. if (isign3 == ENC_OPS3(Reg, Reg, Imm)) { opcode = 0x6B; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); immValue = o2.as<Imm>().value(); immSize = 1; if (!Support::isInt8(immValue) || Support::test(options, InstOptions::kLongForm)) { opcode -= 2; - immSize = o0.size() == 2 ? 2 : 4; + immSize = o0.x86RmSize() == 2 ? 2 : 4; } opReg = o0.id(); @@ -1289,18 +1290,18 @@ CaseX86M_GPB_MulDiv: if (isign3 == ENC_OPS3(Reg, Mem, Imm)) { opcode = 0x6B; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); immValue = o2.as<Imm>().value(); immSize = 1; // Sign extend so isInt8 returns the right result. - if (o0.size() == 4) + if (o0.x86RmSize() == 4) immValue = x86SignExtendI32<int64_t>(immValue); if (!Support::isInt8(immValue) || Support::test(options, InstOptions::kLongForm)) { opcode -= 2; - immSize = o0.size() == 2 ? 2 : 4; + immSize = o0.x86RmSize() == 2 ? 2 : 4; } opReg = o0.id(); @@ -1311,48 +1312,48 @@ CaseX86M_GPB_MulDiv: if (isign3 == ENC_OPS2(Reg, Reg)) { // Must be explicit 'ax, r8' form. - if (o1.size() == 1) + if (o1.x86RmSize() == 1) goto CaseX86M_GPB_MulDiv; - if (o0.size() != o1.size()) + if (o0.x86RmSize() != o1.x86RmSize()) goto OperandSizeMismatch; opReg = o0.id(); rbReg = o1.id(); opcode = Opcode::k000F00 | 0xAF; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); goto EmitX86R; } if (isign3 == ENC_OPS2(Reg, Mem)) { // Must be explicit 'ax, m8' form. - if (o1.size() == 1) + if (o1.x86RmSize() == 1) goto CaseX86M_GPB_MulDiv; opReg = o0.id(); rmRel = &o1; opcode = Opcode::k000F00 | 0xAF; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); goto EmitX86M; } // Shorthand to imul 'reg, reg, imm'. if (isign3 == ENC_OPS2(Reg, Imm)) { opcode = 0x6B; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); immValue = o1.as<Imm>().value(); immSize = 1; // Sign extend so isInt8 returns the right result. - if (o0.size() == 4) + if (o0.x86RmSize() == 4) immValue = x86SignExtendI32<int64_t>(immValue); if (!Support::isInt8(immValue) || Support::test(options, InstOptions::kLongForm)) { opcode -= 2; - immSize = o0.size() == 2 ? 2 : 4; + immSize = o0.x86RmSize() == 2 ? 2 : 4; } opReg = rbReg = o0.id(); @@ -1370,8 +1371,8 @@ CaseX86M_GPB_MulDiv: immValue = o1.as<Imm>().valueAs<uint8_t>(); immSize = 1; - opcode = x86AltOpcodeOf(instInfo) + (o0.size() != 1); - opcode.add66hBySize(o0.size()); + opcode = x86AltOpcodeOf(instInfo) + (o0.x86RmSize() != 1); + opcode.add66hBySize(o0.x86RmSize()); goto EmitX86Op; } @@ -1379,8 +1380,8 @@ CaseX86M_GPB_MulDiv: if (ASMJIT_UNLIKELY(o0.id() != Gp::kIdAx || o1.id() != Gp::kIdDx)) goto InvalidInstruction; - opcode += o0.size() != 1; - opcode.add66hBySize(o0.size()); + opcode += uint32_t(o0.x86RmSize() != 1u); + opcode.add66hBySize(o0.x86RmSize()); goto EmitX86Op; } break; @@ -1390,12 +1391,12 @@ CaseX86M_GPB_MulDiv: if (ASMJIT_UNLIKELY(!x86IsImplicitMem(o0, Gp::kIdDi) || o1.id() != Gp::kIdDx)) goto InvalidInstruction; - uint32_t size = o0.size(); + uint32_t size = o0.x86RmSize(); if (ASMJIT_UNLIKELY(size == 0)) goto AmbiguousOperandSize; rmRel = &o0; - opcode += (size != 1); + opcode += uint32_t(size != 1u); opcode.add66hBySize(size); goto EmitX86OpImplicitMem; @@ -1406,7 +1407,7 @@ CaseX86M_GPB_MulDiv: if (isign3 == ENC_OPS1(Reg)) { rbReg = o0.id(); - if (o0.size() == 1) { + if (o0.x86RmSize() == 1) { FIXUP_GPB(o0, rbReg); goto EmitX86R; } @@ -1414,19 +1415,19 @@ CaseX86M_GPB_MulDiv: if (is32Bit()) { // INC r16|r32 is only encodable in 32-bit mode (collides with REX). opcode = x86AltOpcodeOf(instInfo) + (rbReg & 0x07); - opcode.add66hBySize(o0.size()); + opcode.add66hBySize(o0.x86RmSize()); goto EmitX86Op; } else { - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); goto EmitX86R; } } if (isign3 == ENC_OPS1(Mem)) { - if (!o0.size()) + if (!o0.x86RmSize()) goto AmbiguousOperandSize; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rmRel = &o0; goto EmitX86M; } @@ -1457,7 +1458,7 @@ CaseX86M_GPB_MulDiv: if (ASMJIT_UNLIKELY(!Reg::isGp(o0, Gp::kIdCx))) goto InvalidInstruction; - writer.emitAddressOverride((is32Bit() && o0.size() == 2) || (is64Bit() && o0.size() == 4)); + writer.emitAddressOverride((is32Bit() && o0.x86RmSize() == 2) || (is64Bit() && o0.x86RmSize() == 4)); rmRel = &o1; } @@ -1487,7 +1488,7 @@ CaseX86M_GPB_MulDiv: case InstDB::kEncodingX86LcallLjmp: if (isign3 == ENC_OPS1(Mem)) { rmRel = &o0; - uint32_t mSize = rmRel->size(); + uint32_t mSize = rmRel->as<Mem>().size(); if (mSize == 0) { mSize = registerSize(); } @@ -1519,7 +1520,7 @@ CaseX86M_GPB_MulDiv: case InstDB::kEncodingX86Lea: if (isign3 == ENC_OPS2(Reg, Mem)) { - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); opReg = o0.id(); rmRel = &o1; goto EmitX86M; @@ -1540,8 +1541,8 @@ CaseX86M_GPB_MulDiv: // GP <- GP if (Reg::isGp(o1)) { - uint32_t opSize = o0.size(); - if (opSize != o1.size()) + uint32_t opSize = o0.x86RmSize(); + if (opSize != o1.x86RmSize()) goto InvalidInstruction; if (opSize == 1) { @@ -1552,7 +1553,7 @@ CaseX86M_GPB_MulDiv: if (!Support::test(options, InstOptions::kX86_ModRM)) goto EmitX86R; - opcode += 2; + opcode += 2u; std::swap(opReg, rbReg); goto EmitX86R; } @@ -1563,7 +1564,7 @@ CaseX86M_GPB_MulDiv: if (!Support::test(options, InstOptions::kX86_ModRM)) goto EmitX86R; - opcode += 2; + opcode += 2u; std::swap(opReg, rbReg); goto EmitX86R; } @@ -1572,7 +1573,7 @@ CaseX86M_GPB_MulDiv: // GP <- SReg if (Reg::isSReg(o1)) { opcode = 0x8C; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); opReg--; goto EmitX86R; } @@ -1606,7 +1607,7 @@ CaseX86M_GPB_MulDiv: // SReg <- GP if (Reg::isSReg(o0)) { opcode = 0x8E; - opcode.addPrefixBySize(o1.size()); + opcode.addPrefixBySize(o1.x86RmSize()); opReg--; goto EmitX86R; } @@ -1640,28 +1641,28 @@ CaseX86M_GPB_MulDiv: // SReg <- Mem if (Reg::isSReg(o0)) { opcode = 0x8E; - opcode.addPrefixBySize(o1.size()); + opcode.addPrefixBySize(o1.x86RmSize()); opReg--; goto EmitX86M; } // Reg <- Mem else { opcode = 0; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); // Handle a special form of `mov al|ax|eax|rax, [ptr64]` that doesn't use MOD. if (opReg == Gp::kIdAx && !rmRel->as<Mem>().hasBaseOrIndex()) { - if (x86ShouldUseMovabs(this, writer, o0.size(), options, rmRel->as<Mem>())) { - opcode += 0xA0; + if (x86ShouldUseMovabs(this, writer, o0.x86RmSize(), options, rmRel->as<Mem>())) { + opcode += 0xA0u; immValue = rmRel->as<Mem>().offset(); goto EmitX86OpMovAbs; } } - if (o0.size() == 1) + if (o0.x86RmSize() == 1) FIXUP_GPB(o0, opReg); - opcode += 0x8A; + opcode += 0x8Au; goto EmitX86M; } } @@ -1673,35 +1674,35 @@ CaseX86M_GPB_MulDiv: // Mem <- SReg if (Reg::isSReg(o1)) { opcode = 0x8C; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); opReg--; goto EmitX86M; } // Mem <- Reg else { opcode = 0; - opcode.addArithBySize(o1.size()); + opcode.addArithBySize(o1.x86RmSize()); // Handle a special form of `mov [ptr64], al|ax|eax|rax` that doesn't use MOD. if (opReg == Gp::kIdAx && !rmRel->as<Mem>().hasBaseOrIndex()) { - if (x86ShouldUseMovabs(this, writer, o1.size(), options, rmRel->as<Mem>())) { - opcode += 0xA2; + if (x86ShouldUseMovabs(this, writer, o1.x86RmSize(), options, rmRel->as<Mem>())) { + opcode += 0xA2u; immValue = rmRel->as<Mem>().offset(); goto EmitX86OpMovAbs; } } - if (o1.size() == 1) + if (o1.x86RmSize() == 1) FIXUP_GPB(o1, opReg); - opcode += 0x88; + opcode += 0x88u; goto EmitX86M; } } if (isign3 == ENC_OPS2(Reg, Imm)) { opReg = o0.id(); - immSize = FastUInt8(o0.size()); + immSize = FastUInt8(o0.x86RmSize()); if (immSize == 1) { FIXUP_GPB(o0, opReg); @@ -1739,7 +1740,7 @@ CaseX86M_GPB_MulDiv: } if (isign3 == ENC_OPS2(Mem, Imm)) { - uint32_t memSize = o0.size(); + uint32_t memSize = o0.x86RmSize(); if (ASMJIT_UNLIKELY(memSize == 0)) goto AmbiguousOperandSize; @@ -1761,7 +1762,7 @@ CaseX86M_GPB_MulDiv: rmRel = &o1; opcode = 0xA0; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); if (ASMJIT_UNLIKELY(!o0.as<Reg>().isGp()) || opReg != Gp::kIdAx) goto InvalidInstruction; @@ -1782,7 +1783,7 @@ CaseX86M_GPB_MulDiv: rmRel = &o0; opcode = 0xA2; - opcode.addArithBySize(o1.size()); + opcode.addArithBySize(o1.x86RmSize()); if (ASMJIT_UNLIKELY(!o1.as<Reg>().isGp()) || opReg != Gp::kIdAx) goto InvalidInstruction; @@ -1811,14 +1812,14 @@ CaseX86M_GPB_MulDiv: break; case InstDB::kEncodingX86MovsxMovzx: - opcode.add(o1.size() != 1); - opcode.addPrefixBySize(o0.size()); + opcode.add(o1.x86RmSize() != 1); + opcode.addPrefixBySize(o0.x86RmSize()); if (isign3 == ENC_OPS2(Reg, Reg)) { opReg = o0.id(); rbReg = o1.id(); - if (o1.size() != 1) + if (o1.x86RmSize() != 1) goto EmitX86R; FIXUP_GPB(o1, rbReg); @@ -1864,8 +1865,8 @@ CaseX86M_GPB_MulDiv: if (ASMJIT_UNLIKELY(o1.id() != Gp::kIdAx)) goto InvalidInstruction; - opcode = x86AltOpcodeOf(instInfo) + (o1.size() != 1); - opcode.add66hBySize(o1.size()); + opcode = x86AltOpcodeOf(instInfo) + (o1.x86RmSize() != 1); + opcode.add66hBySize(o1.x86RmSize()); immValue = o0.as<Imm>().valueAs<uint8_t>(); immSize = 1; @@ -1876,8 +1877,8 @@ CaseX86M_GPB_MulDiv: if (ASMJIT_UNLIKELY(o0.id() != Gp::kIdDx || o1.id() != Gp::kIdAx)) goto InvalidInstruction; - opcode.add(o1.size() != 1); - opcode.add66hBySize(o1.size()); + opcode.add(o1.x86RmSize() != 1); + opcode.add66hBySize(o1.x86RmSize()); goto EmitX86Op; } break; @@ -1887,7 +1888,7 @@ CaseX86M_GPB_MulDiv: if (ASMJIT_UNLIKELY(o0.id() != Gp::kIdDx || !x86IsImplicitMem(o1, Gp::kIdSi))) goto InvalidInstruction; - uint32_t size = o1.size(); + uint32_t size = o1.x86RmSize(); if (ASMJIT_UNLIKELY(size == 0)) goto AmbiguousOperandSize; @@ -1939,24 +1940,24 @@ CaseX86M_GPB_MulDiv: CaseX86PushPop_Gp: // We allow 2 byte, 4 byte, and 8 byte register sizes, although PUSH and POP only allow 2 bytes or // native size. On 64-bit we simply PUSH/POP 64-bit register even if 32-bit register was given. - if (ASMJIT_UNLIKELY(o0.size() < 2)) + if (ASMJIT_UNLIKELY(o0.x86RmSize() < 2)) goto InvalidInstruction; opcode = x86AltOpcodeOf(instInfo); - opcode.add66hBySize(o0.size()); + opcode.add66hBySize(o0.x86RmSize()); opReg = o0.id(); goto EmitX86OpReg; } } if (isign3 == ENC_OPS1(Mem)) { - if (ASMJIT_UNLIKELY(o0.size() == 0)) + if (ASMJIT_UNLIKELY(o0.x86RmSize() == 0)) goto AmbiguousOperandSize; - if (ASMJIT_UNLIKELY(o0.size() != 2 && o0.size() != registerSize())) + if (ASMJIT_UNLIKELY(o0.x86RmSize() != 2 && o0.x86RmSize() != registerSize())) goto InvalidInstruction; - opcode.add66hBySize(o0.size()); + opcode.add66hBySize(o0.x86RmSize()); rmRel = &o0; goto EmitX86M; } @@ -1985,17 +1986,17 @@ CaseX86PushPop_Gp: case InstDB::kEncodingX86Rot: if (o0.isReg()) { - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rbReg = o0.id(); - if (o0.size() == 1) + if (o0.x86RmSize() == 1) FIXUP_GPB(o0, rbReg); if (isign3 == ENC_OPS2(Reg, Reg)) { if (ASMJIT_UNLIKELY(o1.id() != Gp::kIdCx)) goto InvalidInstruction; - opcode += 2; + opcode += 2u; goto EmitX86R; } @@ -2012,15 +2013,15 @@ CaseX86PushPop_Gp: } } else { - if (ASMJIT_UNLIKELY(o0.size() == 0)) + if (ASMJIT_UNLIKELY(o0.x86RmSize() == 0)) goto AmbiguousOperandSize; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); if (isign3 == ENC_OPS2(Mem, Reg)) { if (ASMJIT_UNLIKELY(o1.id() != Gp::kIdCx)) goto InvalidInstruction; - opcode += 2; + opcode += 2u; rmRel = &o0; goto EmitX86M; } @@ -2055,7 +2056,7 @@ CaseX86PushPop_Gp: case InstDB::kEncodingX86ShldShrd: if (isign3 == ENC_OPS3(Reg, Reg, Imm)) { - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); opReg = o1.id(); rbReg = o0.id(); @@ -2065,7 +2066,7 @@ CaseX86PushPop_Gp: } if (isign3 == ENC_OPS3(Mem, Reg, Imm)) { - opcode.addPrefixBySize(o1.size()); + opcode.addPrefixBySize(o1.x86RmSize()); opReg = o1.id(); rmRel = &o0; @@ -2081,7 +2082,7 @@ CaseX86PushPop_Gp: if (ASMJIT_UNLIKELY(o2.id() != Gp::kIdCx)) goto InvalidInstruction; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); opReg = o1.id(); rbReg = o0.id(); goto EmitX86R; @@ -2091,7 +2092,7 @@ CaseX86PushPop_Gp: if (ASMJIT_UNLIKELY(o2.id() != Gp::kIdCx)) goto InvalidInstruction; - opcode.addPrefixBySize(o1.size()); + opcode.addPrefixBySize(o1.x86RmSize()); opReg = o1.id(); rmRel = &o0; goto EmitX86M; @@ -2104,8 +2105,8 @@ CaseX86PushPop_Gp: if (ASMJIT_UNLIKELY(rmRel->as<Mem>().offsetLo32() || !Reg::isGp(o0.as<Reg>(), Gp::kIdAx))) goto InvalidInstruction; - uint32_t size = o0.size(); - if (o1.hasSize() && ASMJIT_UNLIKELY(o1.size() != size)) + uint32_t size = o0.x86RmSize(); + if (o1.x86RmSize() != 0u && ASMJIT_UNLIKELY(o1.x86RmSize() != size)) goto OperandSizeMismatch; opcode.addArithBySize(size); @@ -2119,8 +2120,8 @@ CaseX86PushPop_Gp: if (ASMJIT_UNLIKELY(rmRel->as<Mem>().offsetLo32() || !Reg::isGp(o1.as<Reg>(), Gp::kIdAx))) goto InvalidInstruction; - uint32_t size = o1.size(); - if (o0.hasSize() && ASMJIT_UNLIKELY(o0.size() != size)) + uint32_t size = o1.x86RmSize(); + if (o0.x86RmSize() != 0u && ASMJIT_UNLIKELY(o0.x86RmSize() != size)) goto OperandSizeMismatch; opcode.addArithBySize(size); @@ -2138,11 +2139,11 @@ CaseX86PushPop_Gp: if (ASMJIT_UNLIKELY(o0.as<Mem>().hasOffset())) goto InvalidInstruction; - uint32_t size = o1.size(); + uint32_t size = o1.x86RmSize(); if (ASMJIT_UNLIKELY(size == 0)) goto AmbiguousOperandSize; - if (ASMJIT_UNLIKELY(o0.size() != size)) + if (ASMJIT_UNLIKELY(o0.x86RmSize() != size)) goto OperandSizeMismatch; opcode.addArithBySize(size); @@ -2152,14 +2153,14 @@ CaseX86PushPop_Gp: case InstDB::kEncodingX86Test: if (isign3 == ENC_OPS2(Reg, Reg)) { - if (o0.size() != o1.size()) + if (o0.x86RmSize() != o1.x86RmSize()) goto OperandSizeMismatch; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rbReg = o0.id(); opReg = o1.id(); - if (o0.size() != 1) + if (o0.x86RmSize() != 1) goto EmitX86R; FIXUP_GPB(o0, rbReg); @@ -2168,11 +2169,11 @@ CaseX86PushPop_Gp: } if (isign3 == ENC_OPS2(Mem, Reg)) { - opcode.addArithBySize(o1.size()); + opcode.addArithBySize(o1.x86RmSize()); opReg = o1.id(); rmRel = &o0; - if (o1.size() != 1) + if (o1.x86RmSize() != 1) goto EmitX86M; FIXUP_GPB(o1, opReg); @@ -2184,23 +2185,23 @@ CaseX86PushPop_Gp: opReg = opcode.extractModO(); if (isign3 == ENC_OPS2(Reg, Imm)) { - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rbReg = o0.id(); - if (o0.size() == 1) { + if (o0.x86RmSize() == 1) { FIXUP_GPB(o0, rbReg); immValue = o1.as<Imm>().valueAs<uint8_t>(); immSize = 1; } else { immValue = o1.as<Imm>().value(); - immSize = FastUInt8(Support::min<uint32_t>(o0.size(), 4)); + immSize = FastUInt8(Support::min<uint32_t>(o0.x86RmSize(), 4)); } // Short form - AL, AX, EAX, RAX. if (rbReg == 0 && !Support::test(options, InstOptions::kLongForm)) { opcode &= Opcode::kPP_66 | Opcode::kW; - opcode |= 0xA8 + (o0.size() != 1); + opcode |= 0xA8 + (o0.x86RmSize() != 1); goto EmitX86Op; } @@ -2208,25 +2209,25 @@ CaseX86PushPop_Gp: } if (isign3 == ENC_OPS2(Mem, Imm)) { - if (ASMJIT_UNLIKELY(o0.size() == 0)) + if (ASMJIT_UNLIKELY(o0.x86RmSize() == 0)) goto AmbiguousOperandSize; - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); rmRel = &o0; immValue = o1.as<Imm>().value(); - immSize = FastUInt8(Support::min<uint32_t>(o0.size(), 4)); + immSize = FastUInt8(Support::min<uint32_t>(o0.x86RmSize(), 4)); goto EmitX86M; } break; case InstDB::kEncodingX86Xchg: if (isign3 == ENC_OPS2(Reg, Mem)) { - opcode.addArithBySize(o0.size()); + opcode.addArithBySize(o0.x86RmSize()); opReg = o0.id(); rmRel = &o1; - if (o0.size() != 1) + if (o0.x86RmSize() != 1) goto EmitX86M; FIXUP_GPB(o0, opReg); @@ -2239,8 +2240,8 @@ CaseX86PushPop_Gp: rbReg = o0.id(); opReg = o1.id(); - uint32_t opSize = o0.size(); - if (opSize != o1.size()) + uint32_t opSize = o0.x86RmSize(); + if (opSize != o1.x86RmSize()) goto OperandSizeMismatch; if (opSize == 1) { @@ -2259,7 +2260,7 @@ CaseX86PushPop_Gp: goto EmitX86OpReg; } else { - // Encode 'xchg eax, eax' by by using a generic path. + // Encode 'xchg eax, eax' by using a generic path. } } else if (!Support::test(options, InstOptions::kLongForm)) { @@ -2278,11 +2279,11 @@ CaseX86PushPop_Gp: } if (isign3 == ENC_OPS2(Mem, Reg)) { - opcode.addArithBySize(o1.size()); + opcode.addArithBySize(o1.x86RmSize()); opReg = o1.id(); rmRel = &o0; - if (o1.size() == 1) { + if (o1.x86RmSize() == 1) { FIXUP_GPB(o1, opReg); } @@ -2356,7 +2357,7 @@ CaseFpuArith_Reg: if (isign3 == ENC_OPS1(Mem)) { CaseFpuArith_Mem: // 0xD8/0xDC, depends on the size of the memory operand; opReg is valid. - opcode = (o0.size() == 4) ? 0xD8 : 0xDC; + opcode = (o0.x86RmSize() == 4) ? 0xD8 : 0xDC; // Clear compressed displacement before going to EmitX86M. opcode &= ~uint32_t(Opcode::kCDSHL_Mask); @@ -2385,16 +2386,16 @@ CaseFpuArith_Mem: if (isign3 == ENC_OPS1(Mem)) { rmRel = &o0; - if (o0.size() == 4 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM32)) { + if (o0.x86RmSize() == 4 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM32)) { goto EmitX86M; } - if (o0.size() == 8 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM64)) { - opcode += 4; + if (o0.x86RmSize() == 8 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM64)) { + opcode += 4u; goto EmitX86M; } - if (o0.size() == 10 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM80)) { + if (o0.x86RmSize() == 10 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM80)) { opcode = x86AltOpcodeOf(instInfo); opReg = opcode.extractModO(); goto EmitX86M; @@ -2414,16 +2415,16 @@ CaseFpuArith_Mem: opcode &= ~uint32_t(Opcode::kCDSHL_Mask); rmRel = &o0; - if (o0.size() == 2 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM16)) { - opcode += 4; + if (o0.x86RmSize() == 2 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM16)) { + opcode += 4u; goto EmitX86M; } - if (o0.size() == 4 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM32)) { + if (o0.x86RmSize() == 4 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM32)) { goto EmitX86M; } - if (o0.size() == 8 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM64)) { + if (o0.x86RmSize() == 8 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM64)) { opcode = x86AltOpcodeOf(instInfo) & ~uint32_t(Opcode::kCDSHL_Mask); opReg = opcode.extractModO(); goto EmitX86M; @@ -2433,7 +2434,7 @@ CaseFpuArith_Mem: case InstDB::kEncodingFpuRDef: if (isign3 == 0) { - opcode += 1; + opcode += 1u; goto EmitFpuOp; } ASMJIT_FALLTHROUGH; @@ -2550,10 +2551,10 @@ CaseFpuArith_Mem: case InstDB::kEncodingExtMovbe: if (isign3 == ENC_OPS2(Reg, Mem)) { - if (o0.size() == 1) + if (o0.x86RmSize() == 1) goto InvalidInstruction; - opcode.addPrefixBySize(o0.size()); + opcode.addPrefixBySize(o0.x86RmSize()); opReg = o0.id(); rmRel = &o1; goto EmitX86M; @@ -2563,10 +2564,10 @@ CaseFpuArith_Mem: opcode = x86AltOpcodeOf(instInfo); if (isign3 == ENC_OPS2(Mem, Reg)) { - if (o1.size() == 1) + if (o1.x86RmSize() == 1) goto InvalidInstruction; - opcode.addPrefixBySize(o1.size()); + opcode.addPrefixBySize(o1.x86RmSize()); opReg = o1.id(); rmRel = &o0; goto EmitX86M; @@ -2575,37 +2576,41 @@ CaseFpuArith_Mem: case InstDB::kEncodingExtMovd: CaseExtMovd: - opReg = o0.id(); - opcode.add66hIf(Reg::isXmm(o0)); + if (x86IsMmxOrXmm(o0.as<Reg>())) { + opReg = o0.id(); + opcode.add66hIf(Reg::isXmm(o0)); - // MM/XMM <- Gp - if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o1)) { - rbReg = o1.id(); - goto EmitX86R; - } + // MM/XMM <- Gp + if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o1)) { + rbReg = o1.id(); + goto EmitX86R; + } - // MM/XMM <- Mem - if (isign3 == ENC_OPS2(Reg, Mem)) { - rmRel = &o1; - goto EmitX86M; + // MM/XMM <- Mem + if (isign3 == ENC_OPS2(Reg, Mem)) { + rmRel = &o1; + goto EmitX86M; + } } // The following instructions use the secondary opcode. - opcode &= Opcode::kW; - opcode |= x86AltOpcodeOf(instInfo); - opReg = o1.id(); - opcode.add66hIf(Reg::isXmm(o1)); + if (x86IsMmxOrXmm(o1.as<Reg>())) { + opcode &= Opcode::kW; + opcode |= x86AltOpcodeOf(instInfo); + opReg = o1.id(); + opcode.add66hIf(Reg::isXmm(o1)); - // GP <- MM/XMM - if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o0)) { - rbReg = o0.id(); - goto EmitX86R; - } + // GP <- MM/XMM + if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o0)) { + rbReg = o0.id(); + goto EmitX86R; + } - // Mem <- MM/XMM - if (isign3 == ENC_OPS2(Mem, Reg)) { - rmRel = &o0; - goto EmitX86M; + // Mem <- MM/XMM + if (isign3 == ENC_OPS2(Mem, Reg)) { + rmRel = &o0; + goto EmitX86M; + } } break; @@ -2621,7 +2626,7 @@ CaseExtMovd: if (!Support::test(options, InstOptions::kX86_ModMR)) goto EmitX86R; - opcode += 0x10; + opcode += 0x10u; std::swap(opReg, rbReg); goto EmitX86R; } @@ -2692,7 +2697,7 @@ CaseExtMovd: goto CaseExtRm; case InstDB::kEncodingExtRm_Wx: - opcode.addWIf(o1.size() == 8); + opcode.addWIf(o1.x86RmSize() == 8); ASMJIT_FALLTHROUGH; case InstDB::kEncodingExtRm_Wx_GpqOnly: @@ -2716,7 +2721,7 @@ CaseExtRm: case InstDB::kEncodingExtRm_P: if (isign3 == ENC_OPS2(Reg, Reg)) { - opcode.add66hIf(Reg::isXmm(o0) | Reg::isXmm(o1)); + opcode.add66hIf(unsigned(Reg::isXmm(o0)) | unsigned(Reg::isXmm(o1))); opReg = o0.id(); rbReg = o1.id(); @@ -2760,7 +2765,7 @@ CaseExtRm: case InstDB::kEncodingExtRmRi_P: if (isign3 == ENC_OPS2(Reg, Reg)) { - opcode.add66hIf(Reg::isXmm(o0) | Reg::isXmm(o1)); + opcode.add66hIf(unsigned(Reg::isXmm(o0)) | unsigned(Reg::isXmm(o1))); opReg = o0.id(); rbReg = o1.id(); @@ -2812,7 +2817,7 @@ CaseExtRm: immSize = 1; if (isign3 == ENC_OPS3(Reg, Reg, Imm)) { - opcode.add66hIf(Reg::isXmm(o0) | Reg::isXmm(o1)); + opcode.add66hIf(unsigned(Reg::isXmm(o0)) | unsigned(Reg::isXmm(o1))); opReg = o0.id(); rbReg = o1.id(); @@ -2970,7 +2975,7 @@ CaseExtRm: break; case InstDB::kEncodingVexMr_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); if (isign3 == ENC_OPS2(Reg, Reg)) { opReg = o1.id(); @@ -2987,7 +2992,7 @@ CaseExtRm: case InstDB::kEncodingVexMr_VM: if (isign3 == ENC_OPS2(Mem, Reg)) { - opcode |= Support::max(x86OpcodeLByVMem(o0), x86OpcodeLBySize(o1.size())); + opcode |= Support::max(x86OpcodeLByVMem(o0), x86OpcodeLBySize(o1.x86RmSize())); opReg = o1.id(); rmRel = &o0; @@ -3010,8 +3015,17 @@ CaseExtRm: goto CaseVexMri; + case InstDB::kEncodingVexMvr_Wx: + if (isign3 == ENC_OPS3(Mem, Reg, Reg)) { + opcode.addWIf(unsigned(Reg::isGpq(o1))); + opReg = x86PackRegAndVvvvv(o1.id(), o2.id()); + rmRel = &o0; + goto EmitVexEvexM; + } + break; + case InstDB::kEncodingVexMri_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexMri: @@ -3040,19 +3054,19 @@ CaseVexMri: goto CaseVexRm; case InstDB::kEncodingVexRm_Wx: - opcode.addWIf(Reg::isGpq(o0) | Reg::isGpq(o1)); + opcode.addWIf(unsigned(Reg::isGpq(o0)) | unsigned(Reg::isGpq(o1))); goto CaseVexRm; case InstDB::kEncodingVexRm_Lx_Narrow: - if (o1.size()) - opcode |= x86OpcodeLBySize(o1.size()); - else if (o0.size() == 32) + if (o1.x86RmSize()) + opcode |= x86OpcodeLBySize(o1.x86RmSize()); + else if (o0.x86RmSize() == 32) opcode |= Opcode::kLL_2; goto CaseVexRm; case InstDB::kEncodingVexRm_Lx_Bcst: if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o1.as<Reg>())) { - opcode = x86AltOpcodeOf(instInfo) | x86OpcodeLBySize(o0.size() | o1.size()); + opcode = x86AltOpcodeOf(instInfo) | x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); opReg = o0.id(); rbReg = o1.id(); goto EmitVexEvexR; @@ -3060,7 +3074,7 @@ CaseVexMri: ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRm_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRm: @@ -3080,7 +3094,7 @@ CaseVexRm: case InstDB::kEncodingVexRm_VM: if (isign3 == ENC_OPS2(Reg, Mem)) { - opcode |= Support::max(x86OpcodeLByVMem(o1), x86OpcodeLBySize(o0.size())); + opcode |= Support::max(x86OpcodeLByVMem(o1), x86OpcodeLBySize(o0.x86RmSize())); opReg = o0.id(); rmRel = &o1; goto EmitVexEvexM; @@ -3110,11 +3124,11 @@ CaseVexRm: } case InstDB::kEncodingVexRmi_Wx: - opcode.addWIf(Reg::isGpq(o0) | Reg::isGpq(o1)); + opcode.addWIf(unsigned(Reg::isGpq(o0)) | unsigned(Reg::isGpq(o1))); goto CaseVexRmi; case InstDB::kEncodingVexRmi_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRmi: @@ -3159,7 +3173,7 @@ CaseVexRvm_R: } case InstDB::kEncodingVexRvm_Wx: { - opcode.addWIf(Reg::isGpq(o0) | (o2.size() == 8)); + opcode.addWIf(unsigned(Reg::isGpq(o0)) | unsigned((o2.x86RmSize() == 8))); goto CaseVexRvm; } @@ -3169,7 +3183,7 @@ CaseVexRvm_R: } case InstDB::kEncodingVexRvm_Lx: { - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); goto CaseVexRvm; } @@ -3183,7 +3197,7 @@ CaseVexRvm_R: const Operand_& o3 = opExt[EmitterUtils::kOp3]; - opcode |= x86OpcodeLBySize(o2.size()); + opcode |= x86OpcodeLBySize(o2.x86RmSize()); opReg = x86PackRegAndVvvvv(o0.id(), o2.id()); if (o3.isReg()) { @@ -3200,7 +3214,7 @@ CaseVexRvm_R: } case InstDB::kEncodingVexRvmr_Lx: { - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; } @@ -3234,7 +3248,7 @@ CaseVexRvm_R: ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRvmi_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRvmi: @@ -3261,7 +3275,7 @@ VexRvmi: } case InstDB::kEncodingVexRmv_Wx: - opcode.addWIf(Reg::isGpq(o0) | Reg::isGpq(o2)); + opcode.addWIf(unsigned(Reg::isGpq(o0)) | unsigned(Reg::isGpq(o2))); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRmv: @@ -3281,7 +3295,7 @@ VexRvmi: case InstDB::kEncodingVexRmvRm_VM: if (isign3 == ENC_OPS2(Reg, Mem)) { opcode = x86AltOpcodeOf(instInfo); - opcode |= Support::max(x86OpcodeLByVMem(o1), x86OpcodeLBySize(o0.size())); + opcode |= Support::max(x86OpcodeLByVMem(o1), x86OpcodeLBySize(o0.x86RmSize())); opReg = o0.id(); rmRel = &o1; @@ -3291,7 +3305,7 @@ VexRvmi: case InstDB::kEncodingVexRmv_VM: if (isign3 == ENC_OPS3(Reg, Mem, Reg)) { - opcode |= Support::max(x86OpcodeLByVMem(o1), x86OpcodeLBySize(o0.size() | o2.size())); + opcode |= Support::max(x86OpcodeLByVMem(o1), x86OpcodeLBySize(o0.x86RmSize() | o2.x86RmSize())); opReg = x86PackRegAndVvvvv(o0.id(), o2.id()); rmRel = &o1; @@ -3325,14 +3339,14 @@ VexRvmi: if (isign3 == ENC_OPS2(Reg, Reg)) { if (Reg::isGp(o0)) { opcode = x86AltOpcodeOf(instInfo); - opcode.addWBySize(o0.size()); + opcode.addWBySize(o0.x86RmSize()); opReg = o1.id(); rbReg = o0.id(); goto EmitVexEvexR; } if (Reg::isGp(o1)) { - opcode.addWBySize(o1.size()); + opcode.addWBySize(o1.x86RmSize()); opReg = o0.id(); rbReg = o1.id(); goto EmitVexEvexR; @@ -3376,7 +3390,7 @@ VexRvmi: break; case InstDB::kEncodingVexRmMr_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRmMr: @@ -3432,7 +3446,7 @@ VexRvmi: break; case InstDB::kEncodingVexRvmRmi_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRvmRmi: @@ -3544,7 +3558,7 @@ VexRvmi: break; case InstDB::kEncodingVexRvmMvr_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRvmMvr: @@ -3576,7 +3590,7 @@ VexRvmi: ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRvmVmi_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRvmVmi: @@ -3614,7 +3628,7 @@ VexRvmi: break; case InstDB::kEncodingVexVm_Wx: - opcode.addWIf(Reg::isGpq(o0) | Reg::isGpq(o1)); + opcode.addWIf(unsigned(Reg::isGpq(o0)) | unsigned(Reg::isGpq(o1))); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexVm: @@ -3637,7 +3651,7 @@ VexRvmi: ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexVmi_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexVmi: @@ -3659,13 +3673,13 @@ CaseVexVmi_AfterImm: break; case InstDB::kEncodingVexVmi4_Wx: - opcode.addWIf(Reg::isGpq(o0) || o1.size() == 8); + opcode.addWIf(Reg::isGpq(o0) || o1.x86RmSize() == 8); immValue = o2.as<Imm>().value(); immSize = 4; goto CaseVexVmi_AfterImm; case InstDB::kEncodingVexRvrmRvmr_Lx: - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingVexRvrmRvmr: { @@ -3710,7 +3724,7 @@ CaseVexVmi_AfterImm: goto InvalidInstruction; const uint32_t isign4 = isign3 + (uint32_t(o3.opType()) << 9); - opcode |= x86OpcodeLBySize(o0.size() | o1.size() | o2.size() | o3.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize() | o2.x86RmSize() | o3.x86RmSize()); immValue = o4.as<Imm>().valueAs<uint8_t>() & 0x0F; immSize = 1; @@ -3766,7 +3780,7 @@ CaseVexVmi_AfterImm: case InstDB::kEncodingFma4_Lx: // It's fine to just check the first operand, second is just for sanity. - opcode |= x86OpcodeLBySize(o0.size() | o1.size()); + opcode |= x86OpcodeLBySize(o0.x86RmSize() | o1.x86RmSize()); ASMJIT_FALLTHROUGH; case InstDB::kEncodingFma4: { @@ -4274,7 +4288,7 @@ EmitModSib_LabelRip_X86: } else { // Non-bound label or label bound to a different section. - relOffset = -4 - immSize; + relOffset = -4 - int32_t(immSize); relSize = 4; goto EmitRel; } @@ -4950,10 +4964,7 @@ EmitDone: #endif } - resetExtraReg(); - resetInstOptions(); - resetInlineComment(); - + resetState(); writer.done(this); return kErrorOk; @@ -4987,9 +4998,7 @@ Failed: #ifndef ASMJIT_NO_LOGGING return EmitterUtils::logInstructionFailed(this, err, instId, options, o0, o1, o2, opExt); #else - resetExtraReg(); - resetInstOptions(); - resetInlineComment(); + resetState(); return reportError(err); #endif } @@ -5085,6 +5094,9 @@ Error Assembler::onAttach(CodeHolder* code) noexcept { Arch arch = code->arch(); ASMJIT_PROPAGATE(Base::onAttach(code)); + _instructionAlignment = uint8_t(1); + assignEmitterFuncs(this); + if (Environment::is32Bit(arch)) { // 32 bit architecture - X86. _forcedInstOptions |= InstOptions::kX86_InvalidRex; diff --git a/3rdparty/asmjit/src/asmjit/x86/x86assembler.h b/3rdparty/asmjit/src/asmjit/x86/x86assembler.h index dbffae62895..dd980a72692 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86assembler.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86assembler.h @@ -38,13 +38,14 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create a runtime specialized for JIT. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Decide between 32-bit CDECL, WIN64, and SysV64 calling conventions: //! // 32-BIT - passed all arguments by stack. //! // WIN64 - passes first 4 arguments by RCX, RDX, R8, and R9. -//! // UNIX64 - passes first 6 arguments by RDI, RSI, RCX, RDX, R8, and R9. +//! // UNIX64 - passes first 6 arguments by RDI, RSI, RDX, RCX, R8, and R9. //! x86::Gp arr, cnt; //! x86::Gp sum = x86::eax; // Use EAX as 'sum' as it's a return register. //! @@ -100,7 +101,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! The example should be self-explanatory. It shows how to work with labels, how to use operands, and how to emit //! instructions that can use different registers based on runtime selection. It implements 32-bit CDECL, WIN64, -//! and SysV64 caling conventions and will work on most X86/X64 environments. +//! and SysV64 calling conventions and will work on most X86/X64 environments. //! //! Although functions prologs / epilogs can be implemented manually, AsmJit provides utilities that can be used //! to create function prologs and epilogs automatically, see \ref asmjit_function for more details. @@ -131,7 +132,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create a runtime specialized for JIT. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Enable strict validation. @@ -149,7 +151,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! printf("Status: %s\n", DebugUtils::errorAsString(err)); //! //! // Ambiguous operand size - the pointer requires size. -//! err = a.inc(x86::ptr(x86::rax), 1); +//! err = a.inc(x86::ptr(x86::rax)); //! printf("Status: %s\n", DebugUtils::errorAsString(err)); //! //! return 0; @@ -187,7 +189,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create a runtime specialized for JIT. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Let's get these registers from x86::Assembler. @@ -227,6 +230,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! targets easily. If you want to create a register of native size dynamically by specifying its id it's also possible: //! //! ``` +//! #include <asmjit/x86.h> +//! using namespace asmjit; +//! //! void example(x86::Assembler& a) { //! x86::Gp zax = a.gpz(x86::Gp::kIdAx); //! x86::Gp zbx = a.gpz(x86::Gp::kIdBx); @@ -281,21 +287,21 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! #include <asmjit/x86.h> //! using namespace asmjit; //! -//! void embedData(x86::Assembler& a, const Label& L_Data) { +//! void processData(x86::Assembler& a, const Label& L_Data) { //! x86::Gp addr = a.zax(); // EAX or RAX. //! x86::Gp val = x86::edi; // Where to store some value... //! //! // Approach 1 - Load the address to register through LEA. This approach //! // is flexible as the address can be then manipulated, for //! // example if you have a data array, which would need index. -//! a.lea(addr, L_Data); // Loads the address of the label to EAX or RAX. -//! a.mov(val, dword_ptr(addr)); +//! a.lea(addr, x86::ptr(L_Data)); +//! a.mov(val, x86::dword_ptr(addr)); //! //! // Approach 2 - Load the data directly by using L_Data in address. It's //! // worth noting that this doesn't work with indexes in X64 //! // mode. It will use absolute address in 32-bit mode and //! // relative address (RIP) in 64-bit mode. -//! a.mov(val, dword_ptr(L_Data)); +//! a.mov(val, x86::dword_ptr(L_Data)); //! } //! ``` //! @@ -346,7 +352,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create JIT Runtime. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Decide which registers will be mapped to function arguments. Try changing @@ -356,18 +363,19 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! x86::Gp src_a = a.zcx(); //! x86::Gp src_b = a.zdx(); //! -//! X86::Xmm vec0 = x86::xmm0; -//! X86::Xmm vec1 = x86::xmm1; +//! x86::Xmm vec0 = x86::xmm0; +//! x86::Xmm vec1 = x86::xmm1; //! //! // Create/initialize FuncDetail and FuncFrame. //! FuncDetail func; -//! func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConvId::kHost)); +//! func.init(FuncSignature::build<void, int*, const int*, const int*>(), +//! rt.environment()); //! //! FuncFrame frame; //! frame.init(func); //! //! // Make XMM0 and XMM1 dirty - RegGroup::kVec describes XMM|YMM|ZMM registers. -//! frame.setDirtyRegs(RegGroup::kVec, IntUtils::mask(0, 1)); +//! frame.setDirtyRegs(RegGroup::kVec, Support::bitMask(0, 1)); //! //! // Alternatively, if you don't want to use register masks you can pass BaseReg //! // to addDirtyRegs(). The following code would add both xmm0 and xmm1. @@ -375,7 +383,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! FuncArgsAssignment args(&func); // Create arguments assignment context. //! args.assignAll(dst, src_a, src_b);// Assign our registers to arguments. -//! args.updateFrameInfo(frame); // Reflect our args in FuncFrame. +//! args.updateFuncFrame(frame); // Reflect our args in FuncFrame. //! frame.finalize(); // Finalize the FuncFrame (updates it). //! //! a.emitProlog(frame); // Emit function prolog. @@ -453,7 +461,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create a runtime specialized for JIT. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Let's get these registers from x86::Assembler. @@ -532,16 +541,16 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! void prefixesExample(x86::Assembler& a) { //! // Lock prefix for implementing atomics: -//! // lock add dword ptr [dst], 1 -//! a.lock().add(x86::dword_ptr(dst), 1); +//! // lock add dword ptr [rdi], 1 +//! a.lock().add(x86::dword_ptr(x86::rdi), 1); //! //! // Similarly, XAcquire/XRelease prefixes are also available: -//! // xacquire add dword ptr [dst], 1 -//! a.xacquire().add(x86::dword_ptr(dst), 1); +//! // xacquire add dword ptr [rdi], 1 +//! a.xacquire().add(x86::dword_ptr(x86::rdi), 1); //! //! // Rep prefix (see also repe/repz and repne/repnz): -//! // rep movs byte ptr [dst], byte ptr [src] -//! a.rep().movs(x86::byte_ptr(dst), x86::byte_ptr(src)); +//! // rep movs byte ptr [rdi], byte ptr [rsi] +//! a.rep().movs(x86::byte_ptr(x86::rdi), x86::byte_ptr(x86::rsi)); //! //! // Forcing REX prefix in 64-bit mode. //! // rex mov eax, 1 @@ -605,12 +614,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! // ----------------- //! // //! // - Broadcast data is part of memory operand. -//! // - Use x86::Mem::_1toN(), which returns a new x86::Mem operand. +//! // - Use x86::Mem::_1to2(), x86::Mem::_1to4(), etc..., which returns a new x86::Mem operand with broadcast. //! //! // vaddpd zmm0 {k1} {z}, zmm1, [rcx] {1to8} -//! a.k(k1).z().vaddpd(zmm0, zmm1, x86::mem(rcx)._1to8()); +//! a.k(k1).z().vaddpd(zmm0, zmm1, x86::ptr(rcx)._1to8()); //! -//! // Embedded Rounding & Suppress-All-Exceptoins +//! // Embedded Rounding & Suppress-All-Exceptions //! // ------------------------------------------- //! // //! // - Rounding mode and {sae} are part of instruction options. @@ -637,7 +646,7 @@ public: //! \{ ASMJIT_API explicit Assembler(CodeHolder* code = nullptr) noexcept; - ASMJIT_API virtual ~Assembler() noexcept; + ASMJIT_API ~Assembler() noexcept override; //! \} @@ -648,12 +657,13 @@ public: // NOTE: x86::Assembler uses _privateData to store 'address-override' bit that is used to decide whether to emit // address-override (67H) prefix based on the memory BASE+INDEX registers. It's either `kX86MemInfo_67H_X86` or // `kX86MemInfo_67H_X64`. - inline uint32_t _addressOverrideMask() const noexcept { return _privateData; } - inline void _setAddressOverrideMask(uint32_t m) noexcept { _privateData = m; } + ASMJIT_INLINE_NODEBUG uint32_t _addressOverrideMask() const noexcept { return _privateData; } + ASMJIT_INLINE_NODEBUG void _setAddressOverrideMask(uint32_t m) noexcept { _privateData = m; } //! \} //! \endcond + //! \cond INTERNAL //! \name Emit //! \{ diff --git a/3rdparty/asmjit/src/asmjit/x86/x86builder.cpp b/3rdparty/asmjit/src/asmjit/x86/x86builder.cpp index a27948b65d4..9f025a15bc0 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86builder.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86builder.cpp @@ -18,8 +18,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() { _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | (uint64_t(1) << uint32_t(Arch::kX64)) ; - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -29,7 +27,12 @@ Builder::~Builder() noexcept {} // ===================== Error Builder::onAttach(CodeHolder* code) noexcept { - return Base::onAttach(code); + ASMJIT_PROPAGATE(Base::onAttach(code)); + + _instructionAlignment = uint8_t(1); + assignEmitterFuncs(this); + + return kErrorOk; } Error Builder::onDetach(CodeHolder* code) noexcept { diff --git a/3rdparty/asmjit/src/asmjit/x86/x86builder.h b/3rdparty/asmjit/src/asmjit/x86/x86builder.h index f3bb11a0ca2..194c1402f11 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86builder.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86builder.h @@ -36,7 +36,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! // Small helper function to print the current content of `cb`. //! static void dumpCode(BaseBuilder& builder, const char* phase) { //! String sb; -//! builder.dump(sb); +//! formatOptions formatOptions {}; +//! +//! Formatter::formatNodeList(sb, formatOptions, &builder); //! printf("%s:\n%s\n", phase, sb.data()); //! } //! @@ -44,7 +46,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create JIT Runtime. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Builder cb(&code); // Create and attach x86::Builder to `code`. //! //! // Decide which registers will be mapped to function arguments. Try changing registers @@ -58,7 +61,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! // Create and initialize `FuncDetail`. //! FuncDetail func; -//! func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConvId::kHost)); +//! func.init(FuncSignature::build<void, int*, const int*, const int*>()); //! //! // Remember prolog insertion point. //! BaseNode* prologInsertionPoint = cb.cursor(); @@ -323,7 +326,7 @@ public: //! \{ ASMJIT_API explicit Builder(CodeHolder* code = nullptr) noexcept; - ASMJIT_API virtual ~Builder() noexcept; + ASMJIT_API ~Builder() noexcept override; //! \} diff --git a/3rdparty/asmjit/src/asmjit/x86/x86compiler.cpp b/3rdparty/asmjit/src/asmjit/x86/x86compiler.cpp index 04d09807076..830600edabc 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86compiler.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86compiler.cpp @@ -19,8 +19,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() { _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | (uint64_t(1) << uint32_t(Arch::kX64)) ; - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -38,6 +36,9 @@ Error Compiler::onAttach(CodeHolder* code) noexcept { return err; } + _instructionAlignment = uint8_t(1); + assignEmitterFuncs(this); + return kErrorOk; } diff --git a/3rdparty/asmjit/src/asmjit/x86/x86compiler.h b/3rdparty/asmjit/src/asmjit/x86/x86compiler.h index d89aea02519..b281e208879 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86compiler.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86compiler.h @@ -35,31 +35,32 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef int (*Func)(void); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! cc.addFunc(FuncSignatureT<int>());// Begin a function of `int fn(void)` signature. +//! cc.addFunc(FuncSignature::build<int>()); // Begin a function of `int fn(void)` signature. //! -//! x86::Gp vReg = cc.newGpd(); // Create a 32-bit general purpose register. -//! cc.mov(vReg, 1); // Move one to our virtual register `vReg`. -//! cc.ret(vReg); // Return `vReg` from the function. +//! x86::Gp vReg = cc.newGpd(); // Create a 32-bit general purpose register. +//! cc.mov(vReg, 1); // Move one to our virtual register `vReg`. +//! cc.ret(vReg); // Return `vReg` from the function. //! -//! cc.endFunc(); // End of the function body. -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.endFunc(); // End of the function body. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! Func fn; -//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. +//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. +//! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ----> CodeHolder is no longer needed from here and can be destroyed <---- //! -//! int result = fn(); // Execute the generated code. -//! printf("%d\n", result); // Print the resulting "1". +//! int result = fn(); // Execute the generated code. +//! printf("%d\n", result); // Print the resulting "1". //! -//! rt.release(fn); // Explicitly remove the function from the runtime. +//! rt.release(fn); // Explicitly remove the function from the runtime. //! return 0; //! } //! ``` @@ -79,48 +80,49 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef void (*MemCpy32)(uint32_t* dst, const uint32_t* src, size_t count); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! FuncNode* funcNode = cc.addFunc( // Begin the function of the following signature: -//! FuncSignatureT<void, // Return value - void (no return value). -//! uint32_t*, // 1st argument - uint32_t* (machine reg-size). -//! const uint32_t*, // 2nd argument - uint32_t* (machine reg-size). -//! size_t>()); // 3rd argument - size_t (machine reg-size). +//! FuncNode* funcNode = cc.addFunc ( // Begin the function of the following signature: +//! FuncSignature::build<void, // Return value - void (no return value). +//! uint32_t*, // 1st argument - uint32_t* (machine reg-size). +//! const uint32_t*, // 2nd argument - uint32_t* (machine reg-size). +//! size_t>()); // 3rd argument - size_t (machine reg-size). //! -//! Label L_Loop = cc.newLabel(); // Start of the loop. -//! Label L_Exit = cc.newLabel(); // Used to exit early. +//! Label L_Loop = cc.newLabel(); // Start of the loop. +//! Label L_Exit = cc.newLabel(); // Used to exit early. //! -//! x86::Gp dst = cc.newIntPtr("dst");// Create `dst` register (destination pointer). -//! x86::Gp src = cc.newIntPtr("src");// Create `src` register (source pointer). -//! x86::Gp i = cc.newUIntPtr("i"); // Create `i` register (loop counter). +//! x86::Gp dst = cc.newIntPtr("dst"); // Create `dst` register (destination pointer). +//! x86::Gp src = cc.newIntPtr("src"); // Create `src` register (source pointer). +//! x86::Gp i = cc.newUIntPtr("i"); // Create `i` register (loop counter). //! -//! funcNode->setArg(0, dst); // Assign `dst` argument. -//! funcNode->setArg(1, src); // Assign `src` argument. -//! funcNode->setArg(2, i); // Assign `i` argument. +//! funcNode->setArg(0, dst); // Assign `dst` argument. +//! funcNode->setArg(1, src); // Assign `src` argument. +//! funcNode->setArg(2, i); // Assign `i` argument. //! -//! cc.test(i, i); // Early exit if length is zero. +//! cc.test(i, i); // Early exit if length is zero. //! cc.jz(L_Exit); //! -//! cc.bind(L_Loop); // Bind the beginning of the loop here. +//! cc.bind(L_Loop); // Bind the beginning of the loop here. //! -//! x86::Gp tmp = cc.newInt32("tmp"); // Copy a single dword (4 bytes). -//! cc.mov(tmp, x86::dword_ptr(src)); // Load DWORD from [src] address. -//! cc.mov(x86::dword_ptr(dst), tmp); // Store DWORD to [dst] address. +//! x86::Gp tmp = cc.newInt32("tmp"); // Copy a single dword (4 bytes). +//! cc.mov(tmp, x86::dword_ptr(src)); // Load DWORD from [src] address. +//! cc.mov(x86::dword_ptr(dst), tmp); // Store DWORD to [dst] address. //! -//! cc.add(src, 4); // Increment `src`. -//! cc.add(dst, 4); // Increment `dst`. +//! cc.add(src, 4); // Increment `src`. +//! cc.add(dst, 4); // Increment `dst`. //! -//! cc.dec(i); // Loop until `i` is non-zero. +//! cc.dec(i); // Loop until `i` is non-zero. //! cc.jnz(L_Loop); //! -//! cc.bind(L_Exit); // Label used by early exit. -//! cc.endFunc(); // End of the function body. +//! cc.bind(L_Exit); // Label used by early exit. +//! cc.endFunc(); // End of the function body. //! -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! // Add the generated code to the runtime. @@ -161,13 +163,14 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef void (*Func)(void*); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*>()); +//! FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, void*>()); //! //! // Use the following to enable AVX and/or AVX-512. //! funcNode->frame().setAvxEnabled(); @@ -183,13 +186,13 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! cc.vpaddq(vreg, vreg, vreg); //! cc.vmovdqu32(x86::ptr(addr), vreg); //! -//! cc.endFunc(); // End of the function body. -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.endFunc(); // End of the function body. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! Func fn; -//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. +//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. +//! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ----> CodeHolder is no longer needed from here and can be destroyed <---- //! //! // Execute the generated code and print some output. @@ -197,7 +200,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! fn(data); //! printf("%llu\n", (unsigned long long)data[0]); //! -//! rt.release(fn); // Explicitly remove the function from the runtime. +//! rt.release(fn); // Explicitly remove the function from the runtime. //! return 0; //! } //! ``` @@ -219,47 +222,48 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef uint32_t (*Fibonacci)(uint32_t x); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc() -//! FuncSignatureT<int, int>()); // Returns a pointer to the FuncNode node. +//! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc() +//! FuncSignature::build<int, int>()); // Returns a pointer to the FuncNode node. //! -//! Label L_Exit = cc.newLabel() // Exit label. -//! x86::Gp x = cc.newUInt32(); // Function x argument. -//! x86::Gp y = cc.newUInt32(); // Temporary. +//! Label L_Exit = cc.newLabel(); // Exit label. +//! x86::Gp x = cc.newUInt32(); // Function x argument. +//! x86::Gp y = cc.newUInt32(); // Temporary. //! //! funcNode->setArg(0, x); //! -//! cc.cmp(x, 3); // Return x if less than 3. +//! cc.cmp(x, 3); // Return x if less than 3. //! cc.jb(L_Exit); //! -//! cc.mov(y, x); // Make copy of the original x. -//! cc.dec(x); // Decrease x. +//! cc.mov(y, x); // Make copy of the original x. +//! cc.dec(x); // Decrease x. //! -//! InvokeNode* invokeNode; // Function invocation: -//! cc.invoke(&invokeNode, // - InvokeNode (output). -//! funcNode->label(), // - Function address or Label. -//! FuncSignatureT<int, int>()); // - Function signature. +//! InvokeNode* invokeNode; // Function invocation: +//! cc.invoke(&invokeNode, // - InvokeNode (output). +//! funcNode->label(), // - Function address or Label. +//! FuncSignature::build<int, int>()); // - Function signature. //! -//! invokeNode->setArg(0, x); // Assign x as the first argument. -//! invokeNode->setRet(0, x); // Assign x as a return value as well. +//! invokeNode->setArg(0, x); // Assign x as the first argument. +//! invokeNode->setRet(0, x); // Assign x as a return value as well. //! -//! cc.add(x, y); // Combine the return value with y. +//! cc.add(x, y); // Combine the return value with y. //! //! cc.bind(L_Exit); -//! cc.ret(x); // Return x. -//! cc.endFunc(); // End of the function body. +//! cc.ret(x); // Return x. +//! cc.endFunc(); // End of the function body. //! -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! Fibonacci fib; -//! Error err = rt.add(&fib, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. +//! Error err = rt.add(&fib, &code); // Add the generated code to the runtime. +//! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ----> CodeHolder is no longer needed from here and can be destroyed <---- //! //! // Test the generated code. @@ -287,13 +291,14 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef int (*Func)(void); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! cc.addFunc(FuncSignatureT<int>());// Create a function that returns int. +//! cc.addFunc(FuncSignature::build<int>()); // Create a function that returns int. //! //! x86::Gp p = cc.newIntPtr("p"); //! x86::Gp i = cc.newIntPtr("i"); @@ -301,9 +306,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! // Allocate 256 bytes on the stack aligned to 4 bytes. //! x86::Mem stack = cc.newStack(256, 4); //! -//! x86::Mem stackIdx(stack); // Copy of stack with i added. -//! stackIdx.setIndex(i); // stackIdx <- stack[i]. -//! stackIdx.setSize(1); // stackIdx <- byte ptr stack[i]. +//! x86::Mem stackIdx(stack); // Copy of stack with i added. +//! stackIdx.setIndex(i); // stackIdx <- stack[i]. +//! stackIdx.setSize(1); // stackIdx <- byte ptr stack[i]. //! //! // Load a stack address to `p`. This step is purely optional and shows //! // that `lea` is useful to load a memory operands address (even absolute) @@ -316,12 +321,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! Label L1 = cc.newLabel(); //! Label L2 = cc.newLabel(); //! -//! cc.bind(L1); // First loop, fill the stack. -//! cc.mov(stackIdx, i.r8()); // stack[i] = uint8_t(i). +//! cc.bind(L1); // First loop, fill the stack. +//! cc.mov(stackIdx, i.r8()); // stack[i] = uint8_t(i). //! -//! cc.inc(i); // i++; -//! cc.cmp(i, 256); // if (i < 256) -//! cc.jb(L1); // goto L1; +//! cc.inc(i); // i++; +//! cc.cmp(i, 256); // if (i < 256) +//! cc.jb(L1); // goto L1; //! //! // Second loop, sum all bytes stored in `stack`. //! x86::Gp sum = cc.newInt32("sum"); @@ -332,25 +337,25 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! cc.bind(L2); //! -//! cc.movzx(val, stackIdx); // val = uint32_t(stack[i]); -//! cc.add(sum, val); // sum += val; +//! cc.movzx(val, stackIdx); // val = uint32_t(stack[i]); +//! cc.add(sum, val); // sum += val; //! -//! cc.inc(i); // i++; -//! cc.cmp(i, 256); // if (i < 256) -//! cc.jb(L2); // goto L2; +//! cc.inc(i); // i++; +//! cc.cmp(i, 256); // if (i < 256) +//! cc.jb(L2); // goto L2; //! -//! cc.ret(sum); // Return the `sum` of all values. -//! cc.endFunc(); // End of the function body. +//! cc.ret(sum); // Return the `sum` of all values. +//! cc.endFunc(); // End of the function body. //! -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! Func func; -//! Error err = rt.add(&func, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. +//! Error err = rt.add(&func, &code); // Add the generated code to the runtime. +//! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ----> CodeHolder is no longer needed from here and can be destroyed <---- //! -//! printf("Func() -> %d\n", func()); // Test the generated code. +//! printf("Func() -> %d\n", func()); // Test the generated code. //! //! rt.release(func); //! return 0; @@ -375,7 +380,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! using namespace asmjit; //! //! static void exampleUseOfConstPool(x86::Compiler& cc) { -//! cc.addFunc(FuncSignatureT<int>()); +//! cc.addFunc(FuncSignature::build<int>()); //! //! x86::Gp v0 = cc.newGpd("v0"); //! x86::Gp v1 = cc.newGpd("v1"); @@ -409,7 +414,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! using namespace asmjit; //! //! static void exampleUseOfIndirectJump(x86::Compiler& cc) { -//! FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float, uint32_t>(CallConvId::kHost)); +//! FuncNode* funcNode = cc.addFunc(FuncSignature::build<float, float, float, uint32_t>()); //! //! // Function arguments //! x86::Xmm a = cc.newXmmSs("a"); @@ -489,7 +494,7 @@ public: //! \{ ASMJIT_API explicit Compiler(CodeHolder* code = nullptr) noexcept; - ASMJIT_API virtual ~Compiler() noexcept; + ASMJIT_API ~Compiler() noexcept override; //! \} @@ -497,52 +502,52 @@ public: //! \{ #ifndef ASMJIT_NO_LOGGING -# define ASMJIT_NEW_REG_FMT(OUT, PARAM, FORMAT, ARGS) \ +# define ASMJIT_NEW_REG_FMT(OUT, PARAM, FORMAT, ARGS) \ _newRegFmt(&OUT, PARAM, FORMAT, ARGS) #else -# define ASMJIT_NEW_REG_FMT(OUT, PARAM, FORMAT, ARGS) \ - DebugUtils::unused(FORMAT); \ - DebugUtils::unused(std::forward<Args>(args)...); \ +# define ASMJIT_NEW_REG_FMT(OUT, PARAM, FORMAT, ARGS) \ + DebugUtils::unused(FORMAT); \ + DebugUtils::unused(std::forward<Args>(args)...); \ _newReg(&OUT, PARAM) #endif -#define ASMJIT_NEW_REG_CUSTOM(FUNC, REG) \ - inline REG FUNC(TypeId typeId) { \ - REG reg(Globals::NoInit); \ - _newReg(®, typeId); \ - return reg; \ - } \ - \ - template<typename... Args> \ - inline REG FUNC(TypeId typeId, const char* fmt, Args&&... args) { \ - REG reg(Globals::NoInit); \ - ASMJIT_NEW_REG_FMT(reg, typeId, fmt, std::forward<Args>(args)...); \ - return reg; \ +#define ASMJIT_NEW_REG_CUSTOM(FUNC, REG) \ + ASMJIT_INLINE_NODEBUG REG FUNC(TypeId typeId) { \ + REG reg(Globals::NoInit); \ + _newReg(®, typeId); \ + return reg; \ + } \ + \ + template<typename... Args> \ + ASMJIT_INLINE_NODEBUG REG FUNC(TypeId typeId, const char* fmt, Args&&... args) { \ + REG reg(Globals::NoInit); \ + ASMJIT_NEW_REG_FMT(reg, typeId, fmt, std::forward<Args>(args)...); \ + return reg; \ } -#define ASMJIT_NEW_REG_TYPED(FUNC, REG, TYPE_ID) \ - inline REG FUNC() { \ - REG reg(Globals::NoInit); \ - _newReg(®, TYPE_ID); \ - return reg; \ - } \ - \ - template<typename... Args> \ - inline REG FUNC(const char* fmt, Args&&... args) { \ - REG reg(Globals::NoInit); \ - ASMJIT_NEW_REG_FMT(reg, TYPE_ID, fmt, std::forward<Args>(args)...); \ - return reg; \ +#define ASMJIT_NEW_REG_TYPED(FUNC, REG, TYPE_ID) \ + ASMJIT_INLINE_NODEBUG REG FUNC() { \ + REG reg(Globals::NoInit); \ + _newReg(®, TYPE_ID); \ + return reg; \ + } \ + \ + template<typename... Args> \ + ASMJIT_INLINE_NODEBUG REG FUNC(const char* fmt, Args&&... args) { \ + REG reg(Globals::NoInit); \ + ASMJIT_NEW_REG_FMT(reg, TYPE_ID, fmt, std::forward<Args>(args)...); \ + return reg; \ } template<typename RegT> - inline RegT newSimilarReg(const RegT& ref) { + ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref) { RegT reg(Globals::NoInit); - _newReg(reg, ref); + _newReg(®, ref); return reg; } template<typename RegT, typename... Args> - inline RegT newSimilarReg(const RegT& ref, const char* fmt, Args&&... args) { + ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref, const char* fmt, Args&&... args) { RegT reg(Globals::NoInit); ASMJIT_NEW_REG_FMT(reg, ref, fmt, std::forward<Args>(args)...); return reg; @@ -596,7 +601,7 @@ public: //! \{ //! Creates a new memory chunk allocated on the current function's stack. - inline Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) { + ASMJIT_INLINE_NODEBUG Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) { Mem m(Globals::NoInit); _newStack(&m, size, alignment, name); return m; @@ -608,38 +613,38 @@ public: //! \{ //! Put data to a constant-pool and get a memory reference to it. - inline Mem newConst(ConstPoolScope scope, const void* data, size_t size) { + ASMJIT_INLINE_NODEBUG Mem newConst(ConstPoolScope scope, const void* data, size_t size) { Mem m(Globals::NoInit); _newConst(&m, scope, data, size); return m; } //! Put a BYTE `val` to a constant-pool. - inline Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); } + ASMJIT_INLINE_NODEBUG Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); } //! Put a WORD `val` to a constant-pool. - inline Mem newWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } + ASMJIT_INLINE_NODEBUG Mem newWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a DWORD `val` to a constant-pool. - inline Mem newDWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } + ASMJIT_INLINE_NODEBUG Mem newDWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a QWORD `val` to a constant-pool. - inline Mem newQWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } + ASMJIT_INLINE_NODEBUG Mem newQWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a WORD `val` to a constant-pool. - inline Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); } + ASMJIT_INLINE_NODEBUG Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a WORD `val` to a constant-pool. - inline Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } + ASMJIT_INLINE_NODEBUG Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a DWORD `val` to a constant-pool. - inline Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); } + ASMJIT_INLINE_NODEBUG Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a DWORD `val` to a constant-pool. - inline Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } + ASMJIT_INLINE_NODEBUG Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a QWORD `val` to a constant-pool. - inline Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); } + ASMJIT_INLINE_NODEBUG Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a QWORD `val` to a constant-pool. - inline Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } + ASMJIT_INLINE_NODEBUG Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a SP-FP `val` to a constant-pool. - inline Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); } + ASMJIT_INLINE_NODEBUG Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); } //! Put a DP-FP `val` to a constant-pool. - inline Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); } + ASMJIT_INLINE_NODEBUG Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); } //! \} @@ -647,9 +652,9 @@ public: //! \{ //! Force the compiler to not follow the conditional or unconditional jump. - inline Compiler& unfollow() noexcept { addInstOptions(InstOptions::kUnfollow); return *this; } + ASMJIT_INLINE_NODEBUG Compiler& unfollow() noexcept { addInstOptions(InstOptions::kUnfollow); return *this; } //! Tell the compiler that the destination variable will be overwritten. - inline Compiler& overwrite() noexcept { addInstOptions(InstOptions::kOverwrite); return *this; } + ASMJIT_INLINE_NODEBUG Compiler& overwrite() noexcept { addInstOptions(InstOptions::kOverwrite); return *this; } //! \} @@ -657,7 +662,7 @@ public: //! \{ //! Invoke a function call without `target` type enforcement. - inline Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) { + ASMJIT_INLINE_NODEBUG Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) { return addInvokeNode(out, Inst::kIdCall, target, signature); } @@ -666,22 +671,22 @@ public: //! Creates a new \ref InvokeNode, initializes all the necessary members to match the given function `signature`, //! adds the node to the compiler, and stores its pointer to `out`. The operation is atomic, if anything fails //! nullptr is stored in `out` and error code is returned. - inline Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload - inline Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload - inline Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload - inline Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload - inline Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); } + ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); } //! Return from function. - inline Error ret() { return addRet(Operand(), Operand()); } + ASMJIT_INLINE_NODEBUG Error ret() { return addRet(Operand(), Operand()); } //! \overload - inline Error ret(const BaseReg& o0) { return addRet(o0, Operand()); } + ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0) { return addRet(o0, Operand()); } //! \overload - inline Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); } + ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); } //! \} @@ -691,9 +696,9 @@ public: using EmitterExplicitT<Compiler>::jmp; //! Adds a jump to the given `target` with the provided jump `annotation`. - inline Error jmp(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); } + ASMJIT_INLINE_NODEBUG Error jmp(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); } //! \overload - inline Error jmp(const BaseMem& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); } + ASMJIT_INLINE_NODEBUG Error jmp(const BaseMem& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); } //! \} diff --git a/3rdparty/asmjit/src/asmjit/x86/x86emithelper.cpp b/3rdparty/asmjit/src/asmjit/x86/x86emithelper.cpp index b541c048b04..9cd1db68423 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86emithelper.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86emithelper.cpp @@ -22,6 +22,18 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) // x86::EmitHelper - Utilities // =========================== +static constexpr OperandSignature regSizeToGpSignature[8 + 1] = { + OperandSignature{0}, + OperandSignature{RegTraits<RegType::kX86_GpbLo>::kSignature}, + OperandSignature{RegTraits<RegType::kX86_Gpw>::kSignature}, + OperandSignature{0}, + OperandSignature{RegTraits<RegType::kX86_Gpd>::kSignature}, + OperandSignature{0}, + OperandSignature{0}, + OperandSignature{0}, + OperandSignature{RegTraits<RegType::kX86_Gpq>::kSignature} +}; + static inline uint32_t getXmmMovInst(const FuncFrame& frame) { bool avx = frame.isAvxEnabled(); bool aligned = frame.hasAlignedVecSR(); @@ -70,8 +82,8 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitRegMove( // Detect memory operands and patch them to have the same size as the register. BaseCompiler always sets memory size // of allocs and spills, so it shouldn't be really necessary, however, after this function was separated from Compiler // it's better to make sure that the size is always specified, as we can use 'movzx' and 'movsx' that rely on it. - if (dst.isMem()) { memFlags |= kDstMem; dst.as<Mem>().setSize(src.size()); } - if (src.isMem()) { memFlags |= kSrcMem; src.as<Mem>().setSize(dst.size()); } + if (dst.isMem()) { memFlags |= kDstMem; dst.as<Mem>().setSize(src.as<Mem>().size()); } + if (src.isMem()) { memFlags |= kSrcMem; src.as<Mem>().setSize(dst.as<Mem>().size()); } switch (typeId) { case TypeId::kInt8: @@ -182,41 +194,42 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( // Not a real loop, just 'break' is nicer than 'goto'. for (;;) { if (TypeUtils::isInt(dstTypeId)) { + // Sign extend. if (TypeUtils::isInt(srcTypeId)) { - instId = Inst::kIdMovsx; uint32_t castOp = makeCastOp(dstTypeId, srcTypeId); - // Sign extend by using 'movsx'. if (castOp == makeCastOp(TypeId::kInt16, TypeId::kInt8 ) || castOp == makeCastOp(TypeId::kInt32, TypeId::kInt8 ) || - castOp == makeCastOp(TypeId::kInt32, TypeId::kInt16) || castOp == makeCastOp(TypeId::kInt64, TypeId::kInt8 ) || - castOp == makeCastOp(TypeId::kInt64, TypeId::kInt16)) - break; - - // Sign extend by using 'movsxd'. - instId = Inst::kIdMovsxd; - if (castOp == makeCastOp(TypeId::kInt64, TypeId::kInt32)) + castOp == makeCastOp(TypeId::kInt32, TypeId::kInt16) || + castOp == makeCastOp(TypeId::kInt64, TypeId::kInt16) || + castOp == makeCastOp(TypeId::kInt64, TypeId::kInt32)) { + // Sign extend by using 'movsx' or 'movsxd'. + instId = + castOp == makeCastOp(TypeId::kInt64, TypeId::kInt32) + ? Inst::kIdMovsxd + : Inst::kIdMovsx; + + dst.setSignature(regSizeToGpSignature[dstSize]); + if (src.isReg()) + src.setSignature(regSizeToGpSignature[srcSize]); break; + } } + // Zero extend. if (TypeUtils::isInt(srcTypeId) || src_.isMem()) { + uint32_t movSize = Support::min(srcSize, dstSize); + if (movSize <= 4) + dstSize = 4; + // Zero extend by using 'movzx' or 'mov'. - if (dstSize <= 4 && srcSize < 4) { - instId = Inst::kIdMovzx; - dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); - } - else { - // We should have caught all possibilities where `srcSize` is less than 4, so we don't have to worry - // about 'movzx' anymore. Minimum size is enough to determine if we want 32-bit or 64-bit move. - instId = Inst::kIdMov; - srcSize = Support::min(srcSize, dstSize); - - dst.setSignature(srcSize == 4 ? Reg::signatureOfT<RegType::kX86_Gpd>() - : Reg::signatureOfT<RegType::kX86_Gpq>()); - if (src.isReg()) - src.setSignature(dst.signature()); - } + instId = movSize < 4 ? Inst::kIdMovzx : Inst::kIdMov; + srcSize = Support::min(srcSize, movSize); + + dst.setSignature(regSizeToGpSignature[dstSize]); + if (src.isReg()) + src.setSignature(regSizeToGpSignature[srcSize]); break; } @@ -394,25 +407,29 @@ Error EmitHelper::emitRegSwap( // x86::EmitHelper - Emit Prolog & Epilog // ====================================== -static inline void X86Internal_setupSaveRestoreInfo(RegGroup group, const FuncFrame& frame, Reg& xReg, uint32_t& xInst, uint32_t& xSize) noexcept { +static inline Error X86Internal_setupSaveRestoreInfo(RegGroup group, const FuncFrame& frame, Reg& xReg, uint32_t& xInst, uint32_t& xSize) noexcept { switch (group) { case RegGroup::kVec: xReg = xmm(0); xInst = getXmmMovInst(frame); xSize = xReg.size(); - break; + return kErrorOk; + case RegGroup::kX86_K: xReg = k(0); xInst = Inst::kIdKmovq; xSize = xReg.size(); - break; + return kErrorOk; + case RegGroup::kX86_MM: xReg = mm(0); xInst = Inst::kIdMovq; xSize = xReg.size(); - break; + return kErrorOk; + default: - break; + // This would be a bug in AsmJit if hit. + return DebugUtils::errored(kErrorInvalidState); } } @@ -425,6 +442,12 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { Gp gpReg = zsp; // General purpose register (temporary). Gp saReg = zsp; // Stack-arguments base pointer. + // Emit: 'endbr32' or 'endbr64' (indirect branch protection). + if (frame.hasIndirectBranchProtection()) { + InstId instId = emitter->is32Bit() ? Inst::kIdEndbr32 : Inst::kIdEndbr64; + ASMJIT_PROPAGATE(emitter->emit(instId)); + } + // Emit: 'push zbp' // 'mov zbp, zsp'. if (frame.hasPreservedFP()) { @@ -473,16 +496,15 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { // Emit 'movxxx [zsp + X], {[x|y|z]mm, k}'. { - Reg xReg; Mem xBase = ptr(zsp, int32_t(frame.extraRegSaveOffset())); - uint32_t xInst; - uint32_t xSize; - for (RegGroup group : Support::EnumValues<RegGroup, RegGroup(1), RegGroup::kMaxVirt>{}) { Support::BitWordIterator<RegMask> it(frame.savedRegs(group)); if (it.hasNext()) { - X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize); + Reg xReg; + uint32_t xInst = 0; + uint32_t xSize = 0; + ASMJIT_PROPAGATE(X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize)); do { xReg.setId(it.next()); ASMJIT_PROPAGATE(emitter->emit(xInst, xBase, xReg)); @@ -514,16 +536,15 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) { // Emit 'movxxx {[x|y|z]mm, k}, [zsp + X]'. { - Reg xReg; Mem xBase = ptr(zsp, int32_t(frame.extraRegSaveOffset())); - uint32_t xInst; - uint32_t xSize; - for (RegGroup group : Support::EnumValues<RegGroup, RegGroup(1), RegGroup::kMaxVirt>{}) { Support::BitWordIterator<RegMask> it(frame.savedRegs(group)); if (it.hasNext()) { - X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize); + Reg xReg; + uint32_t xInst; + uint32_t xSize; + ASMJIT_PROPAGATE(X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize)); do { xReg.setId(it.next()); ASMJIT_PROPAGATE(emitter->emit(xInst, xReg, xBase)); @@ -610,7 +631,7 @@ void assignEmitterFuncs(BaseEmitter* emitter) { #endif #ifndef ASMJIT_NO_VALIDATION - emitter->_funcs.validate = InstInternal::validate; + emitter->_funcs.validate = emitter->is32Bit() ? InstInternal::validateX86 : InstInternal::validateX64; #endif } diff --git a/3rdparty/asmjit/src/asmjit/x86/x86emithelper_p.h b/3rdparty/asmjit/src/asmjit/x86/x86emithelper_p.h index e71d9afe7db..e09d084a097 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86emithelper_p.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86emithelper_p.h @@ -19,7 +19,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -static inline RegType vecTypeIdToRegType(TypeId typeId) noexcept { +static ASMJIT_INLINE_NODEBUG RegType vecTypeIdToRegType(TypeId typeId) noexcept { return uint32_t(typeId) <= uint32_t(TypeId::_kVec128End) ? RegType::kX86_Xmm : uint32_t(typeId) <= uint32_t(TypeId::_kVec256End) ? RegType::kX86_Ymm : RegType::kX86_Zmm; } @@ -29,7 +29,7 @@ public: bool _avxEnabled; bool _avx512Enabled; - inline explicit EmitHelper(BaseEmitter* emitter = nullptr, bool avxEnabled = false, bool avx512Enabled = false) noexcept + ASMJIT_INLINE_NODEBUG explicit EmitHelper(BaseEmitter* emitter = nullptr, bool avxEnabled = false, bool avx512Enabled = false) noexcept : BaseEmitHelper(emitter), _avxEnabled(avxEnabled || avx512Enabled), _avx512Enabled(avx512Enabled) {} diff --git a/3rdparty/asmjit/src/asmjit/x86/x86emitter.h b/3rdparty/asmjit/src/asmjit/x86/x86emitter.h index 1f85dec4fd9..60881d3ff93 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86emitter.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86emitter.h @@ -139,16 +139,18 @@ struct EmitterExplicitT { // These two are unfortunately reported by the sanitizer. We know what we do, however, the sanitizer doesn't. // I have tried to use reinterpret_cast instead, but that would generate bad code when compiled by MSC. - ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline This* _emitter() noexcept { return static_cast<This*>(this); } - ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline const This* _emitter() const noexcept { return static_cast<const This*>(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF ASMJIT_INLINE_NODEBUG This* _emitter() noexcept { return static_cast<This*>(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF ASMJIT_INLINE_NODEBUG const This* _emitter() const noexcept { return static_cast<const This*>(this); } //! \endcond //! \name Native Registers //! \{ - //! Returns either GPD or GPQ register of the given `id` depending on the emitter's architecture. + //! Returns either 32-bit or 64-bit GP register of the given `id` depending on the emitter's architecture. inline Gp gpz(uint32_t id) const noexcept { return Gp(_emitter()->_gpSignature, id); } + //! Clones the given `reg` to either 32-bit or 64-bit GP register depending on the emitter's architecture. + inline Gp gpz(const Gp& reg) const noexcept { return Gp(_emitter()->_gpSignature, reg.id()); } inline Gp zax() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdAx); } inline Gp zcx() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdCx); } @@ -471,7 +473,6 @@ public: ASMJIT_INST_3x(idiv, Idiv, Gp, Gp, Mem) // ANY [EXPLICIT] xDX[Rem]:xAX[Quot] <- xDX:xAX / m16|m32|m64 ASMJIT_INST_2x(imul, Imul, Gp, Gp) // ANY [EXPLICIT] AX <- AL * r8 | ra <- ra * rb ASMJIT_INST_2x(imul, Imul, Gp, Mem) // ANY [EXPLICIT] AX <- AL * m8 | ra <- ra * m16|m32|m64 - ASMJIT_INST_2x(imul, Imul, Gp, Imm) // ANY ASMJIT_INST_3x(imul, Imul, Gp, Gp, Imm) // ANY ASMJIT_INST_3x(imul, Imul, Gp, Mem, Imm) // ANY ASMJIT_INST_3x(imul, Imul, Gp, Gp, Gp) // ANY [EXPLICIT] xDX:xAX <- xAX * r16|r32|r64 @@ -633,6 +634,14 @@ public: //! \} + //! \name Core Instructions (Aliases) + //! \{ + + //! The `imul(Gp, Imm)` instruction is an alias of `imul(Gp, Gp, Imm)` instruction. + inline Error imul(const Gp& o0, const Imm& o1) { return _emitter()->_emitI(Inst::kIdImul, o0, o0, o1); } + + //! \} + //! \name Deprecated 32-bit Instructions //! \{ @@ -657,7 +666,6 @@ public: //! \{ // NOTE: For some reason Doxygen is messed up here and thinks we are in cond. - //! \endcond ASMJIT_INST_2x(in, In, Gp_ZAX, Imm) // ANY ASMJIT_INST_2x(in, In, Gp_ZAX, Gp_DX) // ANY @@ -679,14 +687,6 @@ public: //! \} - //! \name LAHF/SAHF Instructions - //! \{ - - ASMJIT_INST_1x(lahf, Lahf, Gp_AH) // LAHFSAHF [EXPLICIT] AH <- EFL - ASMJIT_INST_1x(sahf, Sahf, Gp_AH) // LAHFSAHF [EXPLICIT] EFL <- AH - - //! \} - //! \name ADX Instructions //! \{ @@ -697,13 +697,18 @@ public: //! \} - //! \name LZCNT/POPCNT Instructions + //! \name CPUID Instruction //! \{ - ASMJIT_INST_2x(lzcnt, Lzcnt, Gp, Gp) // LZCNT - ASMJIT_INST_2x(lzcnt, Lzcnt, Gp, Mem) // LZCNT - ASMJIT_INST_2x(popcnt, Popcnt, Gp, Gp) // POPCNT - ASMJIT_INST_2x(popcnt, Popcnt, Gp, Mem) // POPCNT + ASMJIT_INST_4x(cpuid, Cpuid, Gp_EAX, Gp_EBX, Gp_ECX, Gp_EDX) // I486 [EXPLICIT] EAX:EBX:ECX:EDX <- CPUID[EAX:ECX] + + //! \} + + //! \name LAHF/SAHF Instructions + //! \{ + + ASMJIT_INST_1x(lahf, Lahf, Gp_AH) // LAHFSAHF [EXPLICIT] AH <- EFL + ASMJIT_INST_1x(sahf, Sahf, Gp_AH) // LAHFSAHF [EXPLICIT] EFL <- AH //! \} @@ -747,27 +752,36 @@ public: //! \} - //! \name TBM Instructions + //! \name CMPCCXADD Instructions //! \{ - ASMJIT_INST_2x(blcfill, Blcfill, Gp, Gp) // TBM - ASMJIT_INST_2x(blcfill, Blcfill, Gp, Mem) // TBM - ASMJIT_INST_2x(blci, Blci, Gp, Gp) // TBM - ASMJIT_INST_2x(blci, Blci, Gp, Mem) // TBM - ASMJIT_INST_2x(blcic, Blcic, Gp, Gp) // TBM - ASMJIT_INST_2x(blcic, Blcic, Gp, Mem) // TBM - ASMJIT_INST_2x(blcmsk, Blcmsk, Gp, Gp) // TBM - ASMJIT_INST_2x(blcmsk, Blcmsk, Gp, Mem) // TBM - ASMJIT_INST_2x(blcs, Blcs, Gp, Gp) // TBM - ASMJIT_INST_2x(blcs, Blcs, Gp, Mem) // TBM - ASMJIT_INST_2x(blsfill, Blsfill, Gp, Gp) // TBM - ASMJIT_INST_2x(blsfill, Blsfill, Gp, Mem) // TBM - ASMJIT_INST_2x(blsic, Blsic, Gp, Gp) // TBM - ASMJIT_INST_2x(blsic, Blsic, Gp, Mem) // TBM - ASMJIT_INST_2x(t1mskc, T1mskc, Gp, Gp) // TBM - ASMJIT_INST_2x(t1mskc, T1mskc, Gp, Mem) // TBM - ASMJIT_INST_2x(tzmsk, Tzmsk, Gp, Gp) // TBM - ASMJIT_INST_2x(tzmsk, Tzmsk, Gp, Mem) // TBM + ASMJIT_INST_3x(cmpbexadd, Cmpbexadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpbxadd, Cmpbxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmplexadd, Cmplexadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmplxadd, Cmplxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpnbexadd, Cmpnbexadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpnbxadd, Cmpnbxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpnlexadd, Cmpnlexadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpnlxadd, Cmpnlxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpnoxadd, Cmpnoxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpnpxadd, Cmpnpxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpnsxadd, Cmpnsxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpnzxadd, Cmpnzxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpoxadd, Cmpoxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmppxadd, Cmppxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpsxadd, Cmpsxadd, Mem, Gp, Gp) + ASMJIT_INST_3x(cmpzxadd, Cmpzxadd, Mem, Gp, Gp) + + //! \} + + //! \name CacheLine Instructions + //! \{ + + ASMJIT_INST_1x(cldemote, Cldemote, Mem) // CLDEMOTE + ASMJIT_INST_1x(clflush, Clflush, Mem) // CLFLUSH + ASMJIT_INST_1x(clflushopt, Clflushopt, Mem) // CLFLUSH_OPT + ASMJIT_INST_1x(clwb, Clwb, Mem) // CLWB + ASMJIT_INST_1x(clzero, Clzero, DS_ZAX) // CLZERO [EXPLICIT] //! \} @@ -779,6 +793,23 @@ public: //! \} + //! \name FENCE Instructions (SSE and SSE2) + //! \{ + + ASMJIT_INST_0x(lfence, Lfence) // SSE2 + ASMJIT_INST_0x(mfence, Mfence) // SSE2 + ASMJIT_INST_0x(sfence, Sfence) // SSE + + //! \} + + //! \name LZCNT Instructions + //! \{ + + ASMJIT_INST_2x(lzcnt, Lzcnt, Gp, Gp) // LZCNT + ASMJIT_INST_2x(lzcnt, Lzcnt, Gp, Mem) // LZCNT + + //! \} + //! \name MOVBE Instructions //! \{ @@ -803,12 +834,11 @@ public: //! \} - //! \name FENCE Instructions (SSE and SSE2) + //! \name POPCNT Instructions //! \{ - ASMJIT_INST_0x(lfence, Lfence) // SSE2 - ASMJIT_INST_0x(mfence, Mfence) // SSE2 - ASMJIT_INST_0x(sfence, Sfence) // SSE + ASMJIT_INST_2x(popcnt, Popcnt, Gp, Gp) // POPCNT + ASMJIT_INST_2x(popcnt, Popcnt, Gp, Mem) // POPCNT //! \} @@ -825,28 +855,21 @@ public: //! \} - //! \name CPUID Instruction - //! \{ - - ASMJIT_INST_4x(cpuid, Cpuid, Gp_EAX, Gp_EBX, Gp_ECX, Gp_EDX) // I486 [EXPLICIT] EAX:EBX:ECX:EDX <- CPUID[EAX:ECX] - - //! \} - - //! \name CacheLine Instructions + //! \name PREFETCHI Instructions //! \{ - ASMJIT_INST_1x(cldemote, Cldemote, Mem) // CLDEMOTE - ASMJIT_INST_1x(clflush, Clflush, Mem) // CLFLUSH - ASMJIT_INST_1x(clflushopt, Clflushopt, Mem) // CLFLUSH_OPT - ASMJIT_INST_1x(clwb, Clwb, Mem) // CLWB - ASMJIT_INST_1x(clzero, Clzero, DS_ZAX) // CLZERO [EXPLICIT] + ASMJIT_INST_1x(prefetchit0, Prefetchit0, Mem) + ASMJIT_INST_1x(prefetchit1, Prefetchit1, Mem) //! \} - //! \name SERIALIZE Instruction + //! \name RAO_INT Instructions //! \{ - ASMJIT_INST_0x(serialize, Serialize) // SERIALIZE + ASMJIT_INST_2x(aadd, Aadd, Mem, Gp) + ASMJIT_INST_2x(aand, Aand, Mem, Gp) + ASMJIT_INST_2x(aor, Aor, Mem, Gp) + ASMJIT_INST_2x(axor, Axor, Mem, Gp) //! \} @@ -873,6 +896,37 @@ public: //! \} + //! \name SERIALIZE Instruction + //! \{ + + ASMJIT_INST_0x(serialize, Serialize) // SERIALIZE + + //! \} + + //! \name TBM Instructions + //! \{ + + ASMJIT_INST_2x(blcfill, Blcfill, Gp, Gp) // TBM + ASMJIT_INST_2x(blcfill, Blcfill, Gp, Mem) // TBM + ASMJIT_INST_2x(blci, Blci, Gp, Gp) // TBM + ASMJIT_INST_2x(blci, Blci, Gp, Mem) // TBM + ASMJIT_INST_2x(blcic, Blcic, Gp, Gp) // TBM + ASMJIT_INST_2x(blcic, Blcic, Gp, Mem) // TBM + ASMJIT_INST_2x(blcmsk, Blcmsk, Gp, Gp) // TBM + ASMJIT_INST_2x(blcmsk, Blcmsk, Gp, Mem) // TBM + ASMJIT_INST_2x(blcs, Blcs, Gp, Gp) // TBM + ASMJIT_INST_2x(blcs, Blcs, Gp, Mem) // TBM + ASMJIT_INST_2x(blsfill, Blsfill, Gp, Gp) // TBM + ASMJIT_INST_2x(blsfill, Blsfill, Gp, Mem) // TBM + ASMJIT_INST_2x(blsic, Blsic, Gp, Gp) // TBM + ASMJIT_INST_2x(blsic, Blsic, Gp, Mem) // TBM + ASMJIT_INST_2x(t1mskc, T1mskc, Gp, Gp) // TBM + ASMJIT_INST_2x(t1mskc, T1mskc, Gp, Mem) // TBM + ASMJIT_INST_2x(tzmsk, Tzmsk, Gp, Gp) // TBM + ASMJIT_INST_2x(tzmsk, Tzmsk, Gp, Mem) // TBM + + //! \} + //! \name Other User-Mode Instructions //! \{ @@ -1122,6 +1176,14 @@ public: //! \} + //! \name INVLPGB Instructions + //! \{ + + ASMJIT_INST_3x(invlpgb, Invlpgb, Gp_EAX, Gp_EDX, Gp_ECX) + ASMJIT_INST_0x(tlbsync, Tlbsync) + + //! \} + //! \name MONITOR Instructions (Privileged) //! \{ @@ -1172,6 +1234,7 @@ public: ASMJIT_INST_0x(vmresume, Vmresume) // VMX ASMJIT_INST_2x(vmwrite, Vmwrite, Gp, Mem) // VMX ASMJIT_INST_2x(vmwrite, Vmwrite, Gp, Gp) // VMX + ASMJIT_INST_0x(vmxoff, Vmxoff) // VMX ASMJIT_INST_1x(vmxon, Vmxon, Mem) // VMX //! \} @@ -1188,6 +1251,13 @@ public: //! \} + //! \name SEV_ES Instructions + //! \{ + + ASMJIT_INST_0x(vmgexit, Vmgexit) + + //! \} + //! \name FPU Instructions //! \{ @@ -2092,9 +2162,6 @@ public: //! \name GFNI Instructions //! \{ - // NOTE: For some reason Doxygen is messed up here and thinks we are in cond. - //! \endcond - ASMJIT_INST_3x(gf2p8affineinvqb, Gf2p8affineinvqb, Xmm, Xmm, Imm) // GFNI ASMJIT_INST_3x(gf2p8affineinvqb, Gf2p8affineinvqb, Xmm, Mem, Imm) // GFNI ASMJIT_INST_3x(gf2p8affineqb, Gf2p8affineqb, Xmm, Xmm, Imm) // GFNI @@ -2762,7 +2829,7 @@ public: ASMJIT_INST_3x(vpand, Vpand, Vec, Vec, Mem) // AVX+ ASMJIT_INST_3x(vpandd, Vpandd, Vec, Vec, Vec) // AVX512_F{kz|b32} ASMJIT_INST_3x(vpandd, Vpandd, Vec, Vec, Mem) // AVX512_F{kz|b32} - ASMJIT_INST_3x(vpandn, Vpandn, Vec, Vec, Vec) // AV+ + ASMJIT_INST_3x(vpandn, Vpandn, Vec, Vec, Vec) // AVX+ ASMJIT_INST_3x(vpandn, Vpandn, Vec, Vec, Mem) // AVX+ ASMJIT_INST_3x(vpandnd, Vpandnd, Vec, Vec, Vec) // AVX512_F{kz|b32} ASMJIT_INST_3x(vpandnd, Vpandnd, Vec, Vec, Mem) // AVX512_F{kz|b32} @@ -3121,7 +3188,7 @@ public: ASMJIT_INST_2x(vpopcntq, Vpopcntq, Vec, Mem) // AVX512_VPOPCNTDQ{kz|b64} ASMJIT_INST_2x(vpopcntw, Vpopcntw, Vec, Vec) // AVX512_BITALG{kz|b32} ASMJIT_INST_2x(vpopcntw, Vpopcntw, Vec, Mem) // AVX512_BITALG{kz|b32} - ASMJIT_INST_3x(vpor, Vpor, Vec, Vec, Vec) // AV+ + ASMJIT_INST_3x(vpor, Vpor, Vec, Vec, Vec) // AVX+ ASMJIT_INST_3x(vpor, Vpor, Vec, Vec, Mem) // AVX+ ASMJIT_INST_3x(vpord, Vpord, Vec, Vec, Vec) // AVX512_F{kz|b32} ASMJIT_INST_3x(vpord, Vpord, Vec, Vec, Mem) // AVX512_F{kz|b32} @@ -3659,6 +3726,83 @@ public: //! \} + //! \name AVX_NE_CONVERT Instructions + //! \{ + + ASMJIT_INST_2x(vbcstnebf162ps, Vbcstnebf162ps, Vec, Mem) + ASMJIT_INST_2x(vbcstnesh2ps, Vbcstnesh2ps, Vec, Mem) + ASMJIT_INST_2x(vcvtneebf162ps, Vcvtneebf162ps, Vec, Mem) + ASMJIT_INST_2x(vcvtneeph2ps, Vcvtneeph2ps, Vec, Mem) + ASMJIT_INST_2x(vcvtneobf162ps, Vcvtneobf162ps, Vec, Mem) + ASMJIT_INST_2x(vcvtneoph2ps, Vcvtneoph2ps, Vec, Mem) + + //! \} + + //! \name AVX_VNNI_INT8 Instructions + //! \{ + + ASMJIT_INST_3x(vpdpbssd, Vpdpbssd, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpbssd, Vpdpbssd, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpbssds, Vpdpbssds, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpbssds, Vpdpbssds, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpbsud, Vpdpbsud, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpbsud, Vpdpbsud, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpbsuds, Vpdpbsuds, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpbsuds, Vpdpbsuds, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpbuud, Vpdpbuud, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpbuud, Vpdpbuud, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpbuuds, Vpdpbuuds, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpbuuds, Vpdpbuuds, Vec, Vec, Mem) + + //! \} + + //! \name AVX_VNNI_INT16 Instructions + //! \{ + + ASMJIT_INST_3x(vpdpwsud, Vpdpwsud, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpwsud, Vpdpwsud, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpwsuds, Vpdpwsuds, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpwsuds, Vpdpwsuds, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpwusd, Vpdpwusd, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpwusd, Vpdpwusd, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpwusds, Vpdpwusds, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpwusds, Vpdpwusds, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpwuud, Vpdpwuud, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpwuud, Vpdpwuud, Vec, Vec, Mem) + ASMJIT_INST_3x(vpdpwuuds, Vpdpwuuds, Vec, Vec, Vec) + ASMJIT_INST_3x(vpdpwuuds, Vpdpwuuds, Vec, Vec, Mem) + + //! \} + + //! \name AVX+SHA512 Instructions + //! \{ + ASMJIT_INST_2x(vsha512msg1, Vsha512msg1, Vec, Vec) + ASMJIT_INST_2x(vsha512msg2, Vsha512msg2, Vec, Vec) + ASMJIT_INST_3x(vsha512rnds2, Vsha512rnds2, Vec, Vec, Vec) + //! \} + + //! \name AVX+SM3 Instructions + //! \{ + + ASMJIT_INST_3x(vsm3msg1, Vsm3msg1, Vec, Vec, Vec) + ASMJIT_INST_3x(vsm3msg1, Vsm3msg1, Vec, Vec, Mem) + ASMJIT_INST_3x(vsm3msg2, Vsm3msg2, Vec, Vec, Vec) + ASMJIT_INST_3x(vsm3msg2, Vsm3msg2, Vec, Vec, Mem) + ASMJIT_INST_4x(vsm3rnds2, Vsm3rnds2, Vec, Vec, Vec, Imm) + ASMJIT_INST_4x(vsm3rnds2, Vsm3rnds2, Vec, Vec, Mem, Imm) + + //! \} + + //! \name AVX+SM4 Instructions + //! \{ + + ASMJIT_INST_3x(vsm4key4, Vsm4key4, Vec, Vec, Vec) + ASMJIT_INST_3x(vsm4key4, Vsm4key4, Vec, Vec, Mem) + ASMJIT_INST_3x(vsm4rnds4, Vsm4rnds4, Vec, Vec, Vec) + ASMJIT_INST_3x(vsm4rnds4, Vsm4rnds4, Vec, Vec, Mem) + + //! \} + //! \name AVX512_FP16 Instructions //! \{ @@ -3880,22 +4024,48 @@ public: //! \} - //! \name AMX Instructions + //! \name AMX_TILE Instructions //! \{ - ASMJIT_INST_1x(ldtilecfg, Ldtilecfg, Mem) // AMX_TILE - ASMJIT_INST_1x(sttilecfg, Sttilecfg, Mem) // AMX_TILE - ASMJIT_INST_2x(tileloadd, Tileloadd, Tmm, Mem) // AMX_TILE - ASMJIT_INST_2x(tileloaddt1, Tileloaddt1, Tmm, Mem) // AMX_TILE - ASMJIT_INST_0x(tilerelease, Tilerelease) // AMX_TILE - ASMJIT_INST_2x(tilestored, Tilestored, Mem, Tmm) // AMX_TILE - ASMJIT_INST_1x(tilezero, Tilezero, Tmm) // AMX_TILE + ASMJIT_INST_1x(ldtilecfg, Ldtilecfg, Mem) + ASMJIT_INST_1x(sttilecfg, Sttilecfg, Mem) + ASMJIT_INST_2x(tileloadd, Tileloadd, Tmm, Mem) + ASMJIT_INST_2x(tileloaddt1, Tileloaddt1, Tmm, Mem) + ASMJIT_INST_0x(tilerelease, Tilerelease) + ASMJIT_INST_2x(tilestored, Tilestored, Mem, Tmm) + ASMJIT_INST_1x(tilezero, Tilezero, Tmm) - ASMJIT_INST_3x(tdpbf16ps, Tdpbf16ps, Tmm, Tmm, Tmm) // AMX_BF16 - ASMJIT_INST_3x(tdpbssd, Tdpbssd, Tmm, Tmm, Tmm) // AMX_INT8 - ASMJIT_INST_3x(tdpbsud, Tdpbsud, Tmm, Tmm, Tmm) // AMX_INT8 - ASMJIT_INST_3x(tdpbusd, Tdpbusd, Tmm, Tmm, Tmm) // AMX_INT8 - ASMJIT_INST_3x(tdpbuud, Tdpbuud, Tmm, Tmm, Tmm) // AMX_INT8 + //! \} + + //! \name AMX_BF16 Instructions + //! \{ + + ASMJIT_INST_3x(tdpbf16ps, Tdpbf16ps, Tmm, Tmm, Tmm) + + //! \} + + //! \name AMX_COMPLEX Instructions + //! \{ + + ASMJIT_INST_3x(tcmmimfp16ps, Tcmmimfp16ps, Tmm, Tmm, Tmm) + ASMJIT_INST_3x(tcmmrlfp16ps, Tcmmrlfp16ps, Tmm, Tmm, Tmm) + + //! \} + + //! \name AMX_FP16 Instructions + //! \{ + + ASMJIT_INST_3x(tdpfp16ps, Tdpfp16ps, Tmm, Tmm, Tmm) + + //! \} + + //! \name AMX_INT8 Instructions + //! \{ + + ASMJIT_INST_3x(tdpbssd, Tdpbssd, Tmm, Tmm, Tmm) + ASMJIT_INST_3x(tdpbsud, Tdpbsud, Tmm, Tmm, Tmm) + ASMJIT_INST_3x(tdpbusd, Tdpbusd, Tmm, Tmm, Tmm) + ASMJIT_INST_3x(tdpbuud, Tdpbuud, Tmm, Tmm, Tmm) //! \} }; @@ -4167,6 +4337,16 @@ struct EmitterImplicitT : public EmitterExplicitT<This> { //! \} + //! \name SEAM Instructions + //! \{ + + ASMJIT_INST_0x(seamcall, Seamcall) + ASMJIT_INST_0x(seamops, Seamops) + ASMJIT_INST_0x(seamret, Seamret) + ASMJIT_INST_0x(tdcall, Tdcall) + + //! \} + //! \name Privileged Instructions //! \{ diff --git a/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp b/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp index d62dd18b638..67b38dfa779 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp @@ -4,7 +4,7 @@ // SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" -#ifndef ASMJIT_NO_LOGGING +#if !defined(ASMJIT_NO_X86) && !defined(ASMJIT_NO_LOGGING) #include "../core/cpuinfo.h" #include "../core/misc_p.h" @@ -95,6 +95,24 @@ struct RegFormatInfo_T { X == uint32_t(RegType::kX86_Gpd ) ? 8 : X == uint32_t(RegType::kX86_Gpq ) ? 8 : X == uint32_t(RegType::kX86_SReg ) ? 7 : + X == uint32_t(RegType::kX86_Rip ) ? 1 : 0, + + kRegCount = X == uint32_t(RegType::kX86_GpbLo) ? 32 : + X == uint32_t(RegType::kX86_GpbHi) ? 4 : + X == uint32_t(RegType::kX86_Gpw ) ? 32 : + X == uint32_t(RegType::kX86_Gpd ) ? 32 : + X == uint32_t(RegType::kX86_Gpq ) ? 32 : + X == uint32_t(RegType::kX86_Xmm ) ? 32 : + X == uint32_t(RegType::kX86_Ymm ) ? 32 : + X == uint32_t(RegType::kX86_Zmm ) ? 32 : + X == uint32_t(RegType::kX86_Mm ) ? 8 : + X == uint32_t(RegType::kX86_KReg ) ? 8 : + X == uint32_t(RegType::kX86_SReg ) ? 7 : + X == uint32_t(RegType::kX86_CReg ) ? 16 : + X == uint32_t(RegType::kX86_DReg ) ? 16 : + X == uint32_t(RegType::kX86_St ) ? 8 : + X == uint32_t(RegType::kX86_Bnd ) ? 4 : + X == uint32_t(RegType::kX86_Tmm ) ? 8 : X == uint32_t(RegType::kX86_Rip ) ? 1 : 0 }; }; @@ -104,7 +122,7 @@ struct RegFormatInfo_T { } #define ASMJIT_REG_NAME_ENTRY(TYPE) { \ - RegTraits<RegType(TYPE)>::kCount, \ + RegFormatInfo_T<TYPE>::kRegCount, \ RegFormatInfo_T<TYPE>::kFormatIndex, \ RegFormatInfo_T<TYPE>::kSpecialIndex, \ RegFormatInfo_T<TYPE>::kSpecialCount \ @@ -198,8 +216,11 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "AESNI\0" "ALTMOVCR8\0" "AMX_BF16\0" + "AMX_COMPLEX\0" + "AMX_FP16\0" "AMX_INT8\0" "AMX_TILE\0" + "APX_F\0" "AVX\0" "AVX2\0" "AVX512_4FMAPS\0" @@ -207,30 +228,36 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "AVX512_BF16\0" "AVX512_BITALG\0" "AVX512_BW\0" - "AVX512_CDI\0" + "AVX512_CD\0" "AVX512_DQ\0" - "AVX512_ERI\0" + "AVX512_ER\0" "AVX512_F\0" "AVX512_FP16\0" "AVX512_IFMA\0" - "AVX512_PFI\0" + "AVX512_PF\0" "AVX512_VBMI\0" "AVX512_VBMI2\0" "AVX512_VL\0" "AVX512_VNNI\0" "AVX512_VP2INTERSECT\0" "AVX512_VPOPCNTDQ\0" + "AVX_IFMA\0" + "AVX_NE_CONVERT\0" "AVX_VNNI\0" + "AVX_VNNI_INT16\0" + "AVX_VNNI_INT8\0" "BMI\0" "BMI2\0" "CET_IBT\0" "CET_SS\0" + "CET_SSS\0" "CLDEMOTE\0" "CLFLUSH\0" "CLFLUSHOPT\0" "CLWB\0" "CLZERO\0" "CMOV\0" + "CMPCCXADD\0" "CMPXCHG16B\0" "CMPXCHG8B\0" "ENCLV\0" @@ -241,14 +268,20 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "FMA4\0" "FPU\0" "FSGSBASE\0" + "FSRM\0" + "FSRC\0" + "FSRS\0" "FXSR\0" "FXSROPT\0" + "FZRM\0" "GEODE\0" "GFNI\0" "HLE\0" "HRESET\0" "I486\0" + "INVLPGB\0" "LAHFSAHF\0" + "LAM\0" "LWP\0" "LZCNT\0" "MCOMMIT\0" @@ -261,15 +294,19 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "MOVDIRI\0" "MPX\0" "MSR\0" + "MSRLIST\0" "MSSE\0" "OSXSAVE\0" "OSPKE\0" "PCLMULQDQ\0" "PCONFIG\0" "POPCNT\0" + "PREFETCHI\0" "PREFETCHW\0" "PREFETCHWT1\0" "PTWRITE\0" + "RAO_INT\0" + "RMPQUERY\0" "RDPID\0" "RDPRU\0" "RDRAND\0" @@ -277,13 +314,20 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "RDTSC\0" "RDTSCP\0" "RTM\0" + "SEAM\0" "SERIALIZE\0" + "SEV\0" + "SEV_ES\0" + "SEV_SNP\0" "SHA\0" + "SHA512\0" "SKINIT\0" + "SM3\0" + "SM4\0" "SMAP\0" + "SME\0" "SMEP\0" "SMX\0" - "SNP\0" "SSE\0" "SSE2\0" "SSE3\0" @@ -293,6 +337,7 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "SSSE3\0" "SVM\0" "TBM\0" + "TSE\0" "TSX\0" "TSXLDTRK\0" "UINTR\0" @@ -301,6 +346,7 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "VPCLMULQDQ\0" "WAITPKG\0" "WBNOINVD\0" + "WRMSRNS\0" "XOP\0" "XSAVE\0" "XSAVEC\0" @@ -309,14 +355,16 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "<Unknown>\0"; static const uint16_t sFeatureIndex[] = { - 0, 5, 8, 11, 17, 24, 28, 34, 44, 53, 62, 71, 75, 80, 94, 108, 120, 134, 144, - 155, 165, 176, 185, 197, 209, 220, 232, 245, 255, 267, 287, 304, 313, 317, - 322, 330, 337, 346, 354, 365, 370, 377, 382, 393, 403, 409, 416, 421, 426, - 430, 435, 439, 448, 453, 461, 467, 472, 476, 483, 488, 497, 501, 507, 515, - 519, 524, 532, 541, 547, 557, 565, 569, 573, 578, 586, 592, 602, 610, 617, - 627, 639, 647, 653, 659, 666, 673, 679, 686, 690, 700, 704, 711, 716, 721, - 725, 729, 733, 738, 743, 750, 757, 763, 769, 773, 777, 781, 790, 796, 801, - 805, 816, 824, 833, 837, 843, 850, 859, 866 + 0, 5, 8, 11, 17, 24, 28, 34, 44, 53, 65, 74, 83, 92, 98, 102, 107, 121, 135, + 147, 161, 171, 181, 191, 201, 210, 222, 234, 244, 256, 269, 279, 291, 311, + 328, 337, 352, 361, 376, 390, 394, 399, 407, 414, 422, 431, 439, 450, 455, + 462, 467, 477, 488, 498, 504, 511, 516, 521, 525, 530, 534, 543, 548, 553, + 558, 563, 571, 576, 582, 587, 591, 598, 603, 611, 620, 624, 628, 634, 642, + 646, 651, 659, 668, 674, 684, 692, 696, 700, 708, 713, 721, 727, 737, 745, + 752, 762, 772, 784, 792, 800, 809, 815, 821, 828, 835, 841, 848, 852, 857, + 867, 871, 878, 886, 890, 897, 904, 908, 912, 917, 921, 926, 930, 934, 939, + 944, 951, 958, 964, 970, 974, 978, 982, 986, 995, 1001, 1006, 1010, 1021, + 1029, 1038, 1046, 1050, 1056, 1063, 1072, 1079 }; // @EnumStringEnd@ @@ -344,7 +392,10 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(String& sb, FormatFlag else ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(id)))); - if (vReg->type() != type && uint32_t(type) <= uint32_t(RegType::kMaxValue) && Support::test(formatFlags, FormatFlags::kRegCasts)) { + bool formatType = (Support::test(formatFlags, FormatFlags::kRegType)) || + (Support::test(formatFlags, FormatFlags::kRegCasts) && vReg->type() != type); + + if (formatType && uint32_t(type) <= uint32_t(RegType::kMaxValue)) { const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[size_t(type)]; if (typeEntry.index) ASMJIT_PROPAGATE(sb.appendFormat("@%s", info.typeStrings + typeEntry.index)); @@ -481,8 +532,8 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( // ===================================================== static constexpr char kImmCharStart = '{'; -static constexpr char kImmCharEnd = '}'; -static constexpr char kImmCharOr = '|'; +static constexpr char kImmCharEnd = '}'; +static constexpr char kImmCharOr = '|'; struct ImmBits { enum Mode : uint32_t { @@ -496,29 +547,29 @@ struct ImmBits { char text[48 - 3]; }; -ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmShuf(String& sb, uint32_t u8, uint32_t bits, uint32_t count) noexcept { +ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmShuf(String& sb, uint32_t imm8, uint32_t bits, uint32_t count) noexcept { uint32_t mask = (1 << bits) - 1; + uint32_t lastPredicateShift = bits * (count - 1u); - for (uint32_t i = 0; i < count; i++, u8 >>= bits) { - uint32_t value = u8 & mask; + for (uint32_t i = 0; i < count; i++, imm8 <<= bits) { + uint32_t index = (imm8 >> lastPredicateShift) & mask; ASMJIT_PROPAGATE(sb.append(i == 0 ? kImmCharStart : kImmCharOr)); - ASMJIT_PROPAGATE(sb.appendUInt(value)); + ASMJIT_PROPAGATE(sb.appendUInt(index)); } - if (kImmCharEnd) - ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); + ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); return kErrorOk; } -ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint32_t u8, const ImmBits* bits, uint32_t count) noexcept { +ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint32_t imm8, const ImmBits* bits, uint32_t count) noexcept { uint32_t n = 0; char buf[64]; for (uint32_t i = 0; i < count; i++) { const ImmBits& spec = bits[i]; - uint32_t value = (u8 & uint32_t(spec.mask)) >> spec.shift; + uint32_t value = (imm8 & uint32_t(spec.mask)) >> spec.shift; const char* str = nullptr; switch (spec.mode) { @@ -542,26 +593,23 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint3 ASMJIT_PROPAGATE(sb.append(str)); } - if (n && kImmCharEnd) + if (n) ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); return kErrorOk; } -ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint32_t u8, uint32_t bits, uint32_t advance, const char* text, uint32_t count = 1) noexcept { +ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint32_t imm8, uint32_t bits, uint32_t advance, const char* text, uint32_t count = 1) noexcept { uint32_t mask = (1u << bits) - 1; uint32_t pos = 0; - for (uint32_t i = 0; i < count; i++, u8 >>= bits, pos += advance) { - uint32_t value = (u8 & mask) + pos; + for (uint32_t i = 0; i < count; i++, imm8 >>= bits, pos += advance) { + uint32_t value = (imm8 & mask) + pos; ASMJIT_PROPAGATE(sb.append(i == 0 ? kImmCharStart : kImmCharOr)); ASMJIT_PROPAGATE(sb.append(Support::findPackedString(text, value))); } - if (kImmCharEnd) - ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); - - return kErrorOk; + return sb.append(kImmCharEnd); } ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( @@ -583,8 +631,8 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( static const char vpcmpx[] = "EQ\0" "LT\0" "LE\0" "FALSE\0" "NEQ\0" "GE\0" "GT\0" "TRUE\0"; static const char vpcomx[] = "LT\0" "LE\0" "GT\0" "GE\0" "EQ\0" "NEQ\0" "FALSE\0" "TRUE\0"; - static const char vshufpd[] = "A0\0A1\0B0\0B1\0A2\0A3\0B2\0B3\0A4\0A5\0B4\0B5\0A6\0A7\0B6\0B7\0"; - static const char vshufps[] = "A0\0A1\0A2\0A3\0A0\0A1\0A2\0A3\0B0\0B1\0B2\0B3\0B0\0B1\0B2\0B3\0"; + static const char vshufpd[] = "A0\0" "A1\0" "B0\0" "B1\0" "A2\0" "A3\0" "B2\0" "B3\0" "A4\0" "A5\0" "B4\0" "B5\0" "A6\0" "A7\0" "B6\0" "B7\0"; + static const char vshufps[] = "A0\0" "A1\0" "A2\0" "A3\0" "A0\0" "A1\0" "A2\0" "A3\0" "B0\0" "B1\0" "B2\0" "B3\0" "B0\0" "B1\0" "B2\0" "B3\0"; static const ImmBits vfpclassxx[] = { { 0x07u, 0, ImmBits::kModeLookup, "QNAN\0" "+0\0" "-0\0" "+INF\0" "-INF\0" "DENORMAL\0" "-FINITE\0" "SNAN\0" } @@ -608,25 +656,25 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( }; static const ImmBits vmpsadbw[] = { - { 0x04u, 2, ImmBits::kModeLookup, "BLK1[0]\0" "BLK1[1]\0" }, - { 0x03u, 0, ImmBits::kModeLookup, "BLK2[0]\0" "BLK2[1]\0" "BLK2[2]\0" "BLK2[3]\0" }, { 0x40u, 6, ImmBits::kModeLookup, "BLK1[4]\0" "BLK1[5]\0" }, - { 0x30u, 4, ImmBits::kModeLookup, "BLK2[4]\0" "BLK2[5]\0" "BLK2[6]\0" "BLK2[7]\0" } + { 0x30u, 4, ImmBits::kModeLookup, "BLK2[4]\0" "BLK2[5]\0" "BLK2[6]\0" "BLK2[7]\0" }, + { 0x04u, 2, ImmBits::kModeLookup, "BLK1[0]\0" "BLK1[1]\0" }, + { 0x03u, 0, ImmBits::kModeLookup, "BLK2[0]\0" "BLK2[1]\0" "BLK2[2]\0" "BLK2[3]\0" } }; static const ImmBits vpclmulqdq[] = { - { 0x01u, 0, ImmBits::kModeLookup, "LQ\0" "HQ\0" }, - { 0x10u, 4, ImmBits::kModeLookup, "LQ\0" "HQ\0" } + { 0x10u, 4, ImmBits::kModeLookup, "LQ\0" "HQ\0" }, + { 0x01u, 0, ImmBits::kModeLookup, "LQ\0" "HQ\0" } }; static const ImmBits vperm2x128[] = { - { 0x0Bu, 0, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" }, - { 0xB0u, 4, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" } + { 0xB0u, 4, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" }, + { 0x0Bu, 0, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" } }; static const ImmBits vrangexx[] = { - { 0x03u, 0, ImmBits::kModeLookup, "MIN\0" "MAX\0" "MIN_ABS\0" "MAX_ABS\0" }, - { 0x0Cu, 2, ImmBits::kModeLookup, "SIGN_A\0" "SIGN_B\0" "SIGN_0\0" "SIGN_1\0" } + { 0x0Cu, 2, ImmBits::kModeLookup, "SIGN_A\0" "SIGN_B\0" "SIGN_0\0" "SIGN_1\0" }, + { 0x03u, 0, ImmBits::kModeLookup, "MIN\0" "MAX\0" "MIN_ABS\0" "MAX_ABS\0" } }; static const ImmBits vreducexx_vrndscalexx[] = { @@ -881,7 +929,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( } } - ASMJIT_PROPAGATE(InstInternal::instIdToString(arch, instId, sb)); + ASMJIT_PROPAGATE(InstInternal::instIdToString(instId, sb)); } else { ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); @@ -898,7 +946,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( uint32_t vecSize = 16; for (uint32_t j = 0; j < opCount; j++) if (operands[j].isReg()) - vecSize = Support::max<uint32_t>(vecSize, operands[j].size()); + vecSize = Support::max<uint32_t>(vecSize, operands[j].as<Reg>().size()); ASMJIT_PROPAGATE(FormatterInternal_explainConst(sb, formatFlags, instId, vecSize, op.as<Imm>())); } @@ -941,4 +989,4 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( ASMJIT_END_SUB_NAMESPACE -#endif // !ASMJIT_NO_LOGGING +#endif // !ASMJIT_NO_X86 && !ASMJIT_NO_LOGGING diff --git a/3rdparty/asmjit/src/asmjit/x86/x86func.cpp b/3rdparty/asmjit/src/asmjit/x86/x86func.cpp index bba9eef148c..ac73aff8bdd 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86func.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86func.cpp @@ -14,7 +14,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) namespace FuncInternal { -static inline bool shouldThreatAsCDeclIn64BitMode(CallConvId ccId) noexcept { +static inline bool shouldTreatAsCDeclIn64BitMode(CallConvId ccId) noexcept { return ccId == CallConvId::kCDecl || ccId == CallConvId::kStdCall || ccId == CallConvId::kThisCall || @@ -143,7 +143,7 @@ ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Enviro // Preprocess the calling convention into a common id as many conventions are normally ignored even by C/C++ // compilers and treated as `__cdecl`. - if (shouldThreatAsCDeclIn64BitMode(ccId)) + if (shouldTreatAsCDeclIn64BitMode(ccId)) ccId = winABI ? CallConvId::kX64Windows : CallConvId::kX64SystemV; switch (ccId) { @@ -327,7 +327,8 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si } switch (cc.strategy()) { - case CallConvStrategy::kDefault: { + case CallConvStrategy::kDefault: + default: { uint32_t gpzPos = 0; uint32_t vecPos = 0; diff --git a/3rdparty/asmjit/src/asmjit/x86/x86globals.h b/3rdparty/asmjit/src/asmjit/x86/x86globals.h index 803c813ac53..21ed41e87d1 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86globals.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86globals.h @@ -53,20 +53,23 @@ enum class CondCode : uint8_t { kNLE = 0x0Fu, //!< ZF==0 & SF==OF (signed > ) kZero = kZ, //!< Zero flag. - kNotZero = kNZ, //!< Non-zero flag. + kNotZero = kNZ, //!< Not zero. + + kEqual = kE, //!< `a == b` (equal). + kNotEqual = kNE, //!< `a != b` (not equal). + + kCarry = kC, //!< Carry flag. + kNotCarry = kNC, //!< Not carry. kSign = kS, //!< Sign flag. - kNotSign = kNS, //!< No sign flag. + kNotSign = kNS, //!< Not sign. kNegative = kS, //!< Sign flag. - kPositive = kNS, //!< No sign flag. + kPositive = kNS, //!< Not sign. kOverflow = kO, //!< Overflow (signed). kNotOverflow = kNO, //!< Not overflow (signed). - kEqual = kE, //!< `a == b` (equal). - kNotEqual = kNE, //!< `a != b` (not equal). - kSignedLT = kL, //!< `a < b` (signed). kSignedLE = kLE, //!< `a <= b` (signed). kSignedGT = kG, //!< `a > b` (signed). @@ -77,6 +80,9 @@ enum class CondCode : uint8_t { kUnsignedGT = kA, //!< `a > b` (unsigned). kUnsignedGE = kAE, //!< `a >= b` (unsigned). + kBTZero = kNC, //!< Tested bit is zero. + kBTNotZero = kC, //!< Tested bit is non-zero. + kParityEven = kP, //!< Even parity flag. kParityOdd = kPO, //!< Odd parity flag. @@ -105,9 +111,9 @@ static constexpr CondCode _reverseCondTable[] = { //! \endcond //! Reverses a condition code (reverses the corresponding operands of a comparison). -static inline constexpr CondCode reverseCond(CondCode cond) noexcept { return _reverseCondTable[uint8_t(cond)]; } +static ASMJIT_INLINE_NODEBUG constexpr CondCode reverseCond(CondCode cond) noexcept { return _reverseCondTable[uint8_t(cond)]; } //! Negates a condition code. -static inline constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ 1u); } +static ASMJIT_INLINE_NODEBUG constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ 1u); } //! Instruction. //! @@ -119,7 +125,9 @@ namespace Inst { kIdNone = 0, //!< Invalid instruction id. kIdAaa, //!< Instruction 'aaa' (X86). kIdAad, //!< Instruction 'aad' (X86). + kIdAadd, //!< Instruction 'aadd' {RAO_INT}. kIdAam, //!< Instruction 'aam' (X86). + kIdAand, //!< Instruction 'aand' {RAO_INT}. kIdAas, //!< Instruction 'aas' (X86). kIdAdc, //!< Instruction 'adc'. kIdAdcx, //!< Instruction 'adcx' {ADX}. @@ -143,7 +151,9 @@ namespace Inst { kIdAndnps, //!< Instruction 'andnps' {SSE}. kIdAndpd, //!< Instruction 'andpd' {SSE2}. kIdAndps, //!< Instruction 'andps' {SSE}. + kIdAor, //!< Instruction 'aor' {RAO_INT}. kIdArpl, //!< Instruction 'arpl' (X86). + kIdAxor, //!< Instruction 'axor' {RAO_INT}. kIdBextr, //!< Instruction 'bextr' {BMI}. kIdBlcfill, //!< Instruction 'blcfill' {TBM}. kIdBlci, //!< Instruction 'blci' {TBM}. @@ -224,14 +234,30 @@ namespace Inst { kIdCmovs, //!< Instruction 'cmovs' {CMOV}. kIdCmovz, //!< Instruction 'cmovz' {CMOV}. kIdCmp, //!< Instruction 'cmp'. + kIdCmpbexadd, //!< Instruction 'cmpbexadd' {CMPCCXADD}. + kIdCmpbxadd, //!< Instruction 'cmpbxadd' {CMPCCXADD}. + kIdCmplexadd, //!< Instruction 'cmplexadd' {CMPCCXADD}. + kIdCmplxadd, //!< Instruction 'cmplxadd' {CMPCCXADD}. + kIdCmpnbexadd, //!< Instruction 'cmpnbexadd' {CMPCCXADD}. + kIdCmpnbxadd, //!< Instruction 'cmpnbxadd' {CMPCCXADD}. + kIdCmpnlexadd, //!< Instruction 'cmpnlexadd' {CMPCCXADD}. + kIdCmpnlxadd, //!< Instruction 'cmpnlxadd' {CMPCCXADD}. + kIdCmpnoxadd, //!< Instruction 'cmpnoxadd' {CMPCCXADD}. + kIdCmpnpxadd, //!< Instruction 'cmpnpxadd' {CMPCCXADD}. + kIdCmpnsxadd, //!< Instruction 'cmpnsxadd' {CMPCCXADD}. + kIdCmpnzxadd, //!< Instruction 'cmpnzxadd' {CMPCCXADD}. + kIdCmpoxadd, //!< Instruction 'cmpoxadd' {CMPCCXADD}. kIdCmppd, //!< Instruction 'cmppd' {SSE2}. kIdCmpps, //!< Instruction 'cmpps' {SSE}. + kIdCmppxadd, //!< Instruction 'cmppxadd' {CMPCCXADD}. kIdCmps, //!< Instruction 'cmps'. kIdCmpsd, //!< Instruction 'cmpsd' {SSE2}. kIdCmpss, //!< Instruction 'cmpss' {SSE}. + kIdCmpsxadd, //!< Instruction 'cmpsxadd' {CMPCCXADD}. kIdCmpxchg, //!< Instruction 'cmpxchg' {I486}. kIdCmpxchg16b, //!< Instruction 'cmpxchg16b' {CMPXCHG16B} (X64). kIdCmpxchg8b, //!< Instruction 'cmpxchg8b' {CMPXCHG8B}. + kIdCmpzxadd, //!< Instruction 'cmpzxadd' {CMPCCXADD}. kIdComisd, //!< Instruction 'comisd' {SSE2}. kIdComiss, //!< Instruction 'comiss' {SSE}. kIdCpuid, //!< Instruction 'cpuid' {I486}. @@ -279,104 +305,104 @@ namespace Inst { kIdEnter, //!< Instruction 'enter'. kIdExtractps, //!< Instruction 'extractps' {SSE4_1}. kIdExtrq, //!< Instruction 'extrq' {SSE4A}. - kIdF2xm1, //!< Instruction 'f2xm1'. - kIdFabs, //!< Instruction 'fabs'. - kIdFadd, //!< Instruction 'fadd'. - kIdFaddp, //!< Instruction 'faddp'. - kIdFbld, //!< Instruction 'fbld'. - kIdFbstp, //!< Instruction 'fbstp'. - kIdFchs, //!< Instruction 'fchs'. - kIdFclex, //!< Instruction 'fclex'. - kIdFcmovb, //!< Instruction 'fcmovb' {CMOV}. - kIdFcmovbe, //!< Instruction 'fcmovbe' {CMOV}. - kIdFcmove, //!< Instruction 'fcmove' {CMOV}. - kIdFcmovnb, //!< Instruction 'fcmovnb' {CMOV}. - kIdFcmovnbe, //!< Instruction 'fcmovnbe' {CMOV}. - kIdFcmovne, //!< Instruction 'fcmovne' {CMOV}. - kIdFcmovnu, //!< Instruction 'fcmovnu' {CMOV}. - kIdFcmovu, //!< Instruction 'fcmovu' {CMOV}. - kIdFcom, //!< Instruction 'fcom'. - kIdFcomi, //!< Instruction 'fcomi'. - kIdFcomip, //!< Instruction 'fcomip'. - kIdFcomp, //!< Instruction 'fcomp'. - kIdFcompp, //!< Instruction 'fcompp'. - kIdFcos, //!< Instruction 'fcos'. - kIdFdecstp, //!< Instruction 'fdecstp'. - kIdFdiv, //!< Instruction 'fdiv'. - kIdFdivp, //!< Instruction 'fdivp'. - kIdFdivr, //!< Instruction 'fdivr'. - kIdFdivrp, //!< Instruction 'fdivrp'. + kIdF2xm1, //!< Instruction 'f2xm1' {FPU}. + kIdFabs, //!< Instruction 'fabs' {FPU}. + kIdFadd, //!< Instruction 'fadd' {FPU}. + kIdFaddp, //!< Instruction 'faddp' {FPU}. + kIdFbld, //!< Instruction 'fbld' {FPU}. + kIdFbstp, //!< Instruction 'fbstp' {FPU}. + kIdFchs, //!< Instruction 'fchs' {FPU}. + kIdFclex, //!< Instruction 'fclex' {FPU}. + kIdFcmovb, //!< Instruction 'fcmovb' {CMOV|FPU}. + kIdFcmovbe, //!< Instruction 'fcmovbe' {CMOV|FPU}. + kIdFcmove, //!< Instruction 'fcmove' {CMOV|FPU}. + kIdFcmovnb, //!< Instruction 'fcmovnb' {CMOV|FPU}. + kIdFcmovnbe, //!< Instruction 'fcmovnbe' {CMOV|FPU}. + kIdFcmovne, //!< Instruction 'fcmovne' {CMOV|FPU}. + kIdFcmovnu, //!< Instruction 'fcmovnu' {CMOV|FPU}. + kIdFcmovu, //!< Instruction 'fcmovu' {CMOV|FPU}. + kIdFcom, //!< Instruction 'fcom' {FPU}. + kIdFcomi, //!< Instruction 'fcomi' {FPU}. + kIdFcomip, //!< Instruction 'fcomip' {FPU}. + kIdFcomp, //!< Instruction 'fcomp' {FPU}. + kIdFcompp, //!< Instruction 'fcompp' {FPU}. + kIdFcos, //!< Instruction 'fcos' {FPU}. + kIdFdecstp, //!< Instruction 'fdecstp' {FPU}. + kIdFdiv, //!< Instruction 'fdiv' {FPU}. + kIdFdivp, //!< Instruction 'fdivp' {FPU}. + kIdFdivr, //!< Instruction 'fdivr' {FPU}. + kIdFdivrp, //!< Instruction 'fdivrp' {FPU}. kIdFemms, //!< Instruction 'femms' {3DNOW}. - kIdFfree, //!< Instruction 'ffree'. - kIdFiadd, //!< Instruction 'fiadd'. - kIdFicom, //!< Instruction 'ficom'. - kIdFicomp, //!< Instruction 'ficomp'. - kIdFidiv, //!< Instruction 'fidiv'. - kIdFidivr, //!< Instruction 'fidivr'. - kIdFild, //!< Instruction 'fild'. - kIdFimul, //!< Instruction 'fimul'. - kIdFincstp, //!< Instruction 'fincstp'. - kIdFinit, //!< Instruction 'finit'. - kIdFist, //!< Instruction 'fist'. - kIdFistp, //!< Instruction 'fistp'. - kIdFisttp, //!< Instruction 'fisttp' {SSE3}. - kIdFisub, //!< Instruction 'fisub'. - kIdFisubr, //!< Instruction 'fisubr'. - kIdFld, //!< Instruction 'fld'. - kIdFld1, //!< Instruction 'fld1'. - kIdFldcw, //!< Instruction 'fldcw'. - kIdFldenv, //!< Instruction 'fldenv'. - kIdFldl2e, //!< Instruction 'fldl2e'. - kIdFldl2t, //!< Instruction 'fldl2t'. - kIdFldlg2, //!< Instruction 'fldlg2'. - kIdFldln2, //!< Instruction 'fldln2'. - kIdFldpi, //!< Instruction 'fldpi'. - kIdFldz, //!< Instruction 'fldz'. - kIdFmul, //!< Instruction 'fmul'. - kIdFmulp, //!< Instruction 'fmulp'. - kIdFnclex, //!< Instruction 'fnclex'. - kIdFninit, //!< Instruction 'fninit'. - kIdFnop, //!< Instruction 'fnop'. - kIdFnsave, //!< Instruction 'fnsave'. - kIdFnstcw, //!< Instruction 'fnstcw'. - kIdFnstenv, //!< Instruction 'fnstenv'. - kIdFnstsw, //!< Instruction 'fnstsw'. - kIdFpatan, //!< Instruction 'fpatan'. - kIdFprem, //!< Instruction 'fprem'. - kIdFprem1, //!< Instruction 'fprem1'. - kIdFptan, //!< Instruction 'fptan'. - kIdFrndint, //!< Instruction 'frndint'. - kIdFrstor, //!< Instruction 'frstor'. - kIdFsave, //!< Instruction 'fsave'. - kIdFscale, //!< Instruction 'fscale'. - kIdFsin, //!< Instruction 'fsin'. - kIdFsincos, //!< Instruction 'fsincos'. - kIdFsqrt, //!< Instruction 'fsqrt'. - kIdFst, //!< Instruction 'fst'. - kIdFstcw, //!< Instruction 'fstcw'. - kIdFstenv, //!< Instruction 'fstenv'. - kIdFstp, //!< Instruction 'fstp'. - kIdFstsw, //!< Instruction 'fstsw'. - kIdFsub, //!< Instruction 'fsub'. - kIdFsubp, //!< Instruction 'fsubp'. - kIdFsubr, //!< Instruction 'fsubr'. - kIdFsubrp, //!< Instruction 'fsubrp'. - kIdFtst, //!< Instruction 'ftst'. - kIdFucom, //!< Instruction 'fucom'. - kIdFucomi, //!< Instruction 'fucomi'. - kIdFucomip, //!< Instruction 'fucomip'. - kIdFucomp, //!< Instruction 'fucomp'. - kIdFucompp, //!< Instruction 'fucompp'. - kIdFwait, //!< Instruction 'fwait'. - kIdFxam, //!< Instruction 'fxam'. - kIdFxch, //!< Instruction 'fxch'. + kIdFfree, //!< Instruction 'ffree' {FPU}. + kIdFiadd, //!< Instruction 'fiadd' {FPU}. + kIdFicom, //!< Instruction 'ficom' {FPU}. + kIdFicomp, //!< Instruction 'ficomp' {FPU}. + kIdFidiv, //!< Instruction 'fidiv' {FPU}. + kIdFidivr, //!< Instruction 'fidivr' {FPU}. + kIdFild, //!< Instruction 'fild' {FPU}. + kIdFimul, //!< Instruction 'fimul' {FPU}. + kIdFincstp, //!< Instruction 'fincstp' {FPU}. + kIdFinit, //!< Instruction 'finit' {FPU}. + kIdFist, //!< Instruction 'fist' {FPU}. + kIdFistp, //!< Instruction 'fistp' {FPU}. + kIdFisttp, //!< Instruction 'fisttp' {SSE3|FPU}. + kIdFisub, //!< Instruction 'fisub' {FPU}. + kIdFisubr, //!< Instruction 'fisubr' {FPU}. + kIdFld, //!< Instruction 'fld' {FPU}. + kIdFld1, //!< Instruction 'fld1' {FPU}. + kIdFldcw, //!< Instruction 'fldcw' {FPU}. + kIdFldenv, //!< Instruction 'fldenv' {FPU}. + kIdFldl2e, //!< Instruction 'fldl2e' {FPU}. + kIdFldl2t, //!< Instruction 'fldl2t' {FPU}. + kIdFldlg2, //!< Instruction 'fldlg2' {FPU}. + kIdFldln2, //!< Instruction 'fldln2' {FPU}. + kIdFldpi, //!< Instruction 'fldpi' {FPU}. + kIdFldz, //!< Instruction 'fldz' {FPU}. + kIdFmul, //!< Instruction 'fmul' {FPU}. + kIdFmulp, //!< Instruction 'fmulp' {FPU}. + kIdFnclex, //!< Instruction 'fnclex' {FPU}. + kIdFninit, //!< Instruction 'fninit' {FPU}. + kIdFnop, //!< Instruction 'fnop' {FPU}. + kIdFnsave, //!< Instruction 'fnsave' {FPU}. + kIdFnstcw, //!< Instruction 'fnstcw' {FPU}. + kIdFnstenv, //!< Instruction 'fnstenv' {FPU}. + kIdFnstsw, //!< Instruction 'fnstsw' {FPU}. + kIdFpatan, //!< Instruction 'fpatan' {FPU}. + kIdFprem, //!< Instruction 'fprem' {FPU}. + kIdFprem1, //!< Instruction 'fprem1' {FPU}. + kIdFptan, //!< Instruction 'fptan' {FPU}. + kIdFrndint, //!< Instruction 'frndint' {FPU}. + kIdFrstor, //!< Instruction 'frstor' {FPU}. + kIdFsave, //!< Instruction 'fsave' {FPU}. + kIdFscale, //!< Instruction 'fscale' {FPU}. + kIdFsin, //!< Instruction 'fsin' {FPU}. + kIdFsincos, //!< Instruction 'fsincos' {FPU}. + kIdFsqrt, //!< Instruction 'fsqrt' {FPU}. + kIdFst, //!< Instruction 'fst' {FPU}. + kIdFstcw, //!< Instruction 'fstcw' {FPU}. + kIdFstenv, //!< Instruction 'fstenv' {FPU}. + kIdFstp, //!< Instruction 'fstp' {FPU}. + kIdFstsw, //!< Instruction 'fstsw' {FPU}. + kIdFsub, //!< Instruction 'fsub' {FPU}. + kIdFsubp, //!< Instruction 'fsubp' {FPU}. + kIdFsubr, //!< Instruction 'fsubr' {FPU}. + kIdFsubrp, //!< Instruction 'fsubrp' {FPU}. + kIdFtst, //!< Instruction 'ftst' {FPU}. + kIdFucom, //!< Instruction 'fucom' {FPU}. + kIdFucomi, //!< Instruction 'fucomi' {FPU}. + kIdFucomip, //!< Instruction 'fucomip' {FPU}. + kIdFucomp, //!< Instruction 'fucomp' {FPU}. + kIdFucompp, //!< Instruction 'fucompp' {FPU}. + kIdFwait, //!< Instruction 'fwait' {FPU}. + kIdFxam, //!< Instruction 'fxam' {FPU}. + kIdFxch, //!< Instruction 'fxch' {FPU}. kIdFxrstor, //!< Instruction 'fxrstor' {FXSR}. kIdFxrstor64, //!< Instruction 'fxrstor64' {FXSR} (X64). kIdFxsave, //!< Instruction 'fxsave' {FXSR}. kIdFxsave64, //!< Instruction 'fxsave64' {FXSR} (X64). - kIdFxtract, //!< Instruction 'fxtract'. - kIdFyl2x, //!< Instruction 'fyl2x'. - kIdFyl2xp1, //!< Instruction 'fyl2xp1'. + kIdFxtract, //!< Instruction 'fxtract' {FPU}. + kIdFyl2x, //!< Instruction 'fyl2x' {FPU}. + kIdFyl2xp1, //!< Instruction 'fyl2xp1' {FPU}. kIdGetsec, //!< Instruction 'getsec' {SMX}. kIdGf2p8affineinvqb, //!< Instruction 'gf2p8affineinvqb' {GFNI}. kIdGf2p8affineqb, //!< Instruction 'gf2p8affineqb' {GFNI}. @@ -403,6 +429,7 @@ namespace Inst { kIdInvept, //!< Instruction 'invept' {VMX}. kIdInvlpg, //!< Instruction 'invlpg' {I486}. kIdInvlpga, //!< Instruction 'invlpga' {SVM}. + kIdInvlpgb, //!< Instruction 'invlpgb' {INVLPGB}. kIdInvpcid, //!< Instruction 'invpcid' {I486}. kIdInvvpid, //!< Instruction 'invvpid' {VMX}. kIdIret, //!< Instruction 'iret'. @@ -535,7 +562,7 @@ namespace Inst { kIdMonitor, //!< Instruction 'monitor' {MONITOR}. kIdMonitorx, //!< Instruction 'monitorx' {MONITORX}. kIdMov, //!< Instruction 'mov'. - kIdMovabs, //!< Instruction 'movabs' (X64). + kIdMovabs, //!< Instruction 'movabs'. kIdMovapd, //!< Instruction 'movapd' {SSE2}. kIdMovaps, //!< Instruction 'movaps' {SSE}. kIdMovbe, //!< Instruction 'movbe' {MOVBE}. @@ -606,7 +633,7 @@ namespace Inst { kIdPaddusb, //!< Instruction 'paddusb' {MMX|SSE2}. kIdPaddusw, //!< Instruction 'paddusw' {MMX|SSE2}. kIdPaddw, //!< Instruction 'paddw' {MMX|SSE2}. - kIdPalignr, //!< Instruction 'palignr' {SSE3}. + kIdPalignr, //!< Instruction 'palignr' {SSSE3}. kIdPand, //!< Instruction 'pand' {MMX|SSE2}. kIdPandn, //!< Instruction 'pandn' {MMX|SSE2}. kIdPause, //!< Instruction 'pause'. @@ -713,10 +740,12 @@ namespace Inst { kIdPopfq, //!< Instruction 'popfq' (X64). kIdPor, //!< Instruction 'por' {MMX|SSE2}. kIdPrefetch, //!< Instruction 'prefetch' {3DNOW}. - kIdPrefetchnta, //!< Instruction 'prefetchnta' {MMX2}. - kIdPrefetcht0, //!< Instruction 'prefetcht0' {MMX2}. - kIdPrefetcht1, //!< Instruction 'prefetcht1' {MMX2}. - kIdPrefetcht2, //!< Instruction 'prefetcht2' {MMX2}. + kIdPrefetchit0, //!< Instruction 'prefetchit0' {PREFETCHI} (X64). + kIdPrefetchit1, //!< Instruction 'prefetchit1' {PREFETCHI} (X64). + kIdPrefetchnta, //!< Instruction 'prefetchnta' {SSE}. + kIdPrefetcht0, //!< Instruction 'prefetcht0' {SSE}. + kIdPrefetcht1, //!< Instruction 'prefetcht1' {SSE}. + kIdPrefetcht2, //!< Instruction 'prefetcht2' {SSE}. kIdPrefetchw, //!< Instruction 'prefetchw' {PREFETCHW}. kIdPrefetchwt1, //!< Instruction 'prefetchwt1' {PREFETCHWT1}. kIdPsadbw, //!< Instruction 'psadbw' {MMX2|SSE2}. @@ -732,7 +761,7 @@ namespace Inst { kIdPslldq, //!< Instruction 'pslldq' {SSE2}. kIdPsllq, //!< Instruction 'psllq' {MMX|SSE2}. kIdPsllw, //!< Instruction 'psllw' {MMX|SSE2}. - kIdPsmash, //!< Instruction 'psmash' {SNP} (X64). + kIdPsmash, //!< Instruction 'psmash' {SEV_SNP} (X64). kIdPsrad, //!< Instruction 'psrad' {MMX|SSE2}. kIdPsraw, //!< Instruction 'psraw' {MMX|SSE2}. kIdPsrld, //!< Instruction 'psrld' {MMX|SSE2}. @@ -764,7 +793,7 @@ namespace Inst { kIdPushf, //!< Instruction 'pushf'. kIdPushfd, //!< Instruction 'pushfd' (X86). kIdPushfq, //!< Instruction 'pushfq' (X64). - kIdPvalidate, //!< Instruction 'pvalidate' {SNP}. + kIdPvalidate, //!< Instruction 'pvalidate' {SEV_SNP}. kIdPxor, //!< Instruction 'pxor' {MMX|SSE2}. kIdRcl, //!< Instruction 'rcl'. kIdRcpps, //!< Instruction 'rcpps' {SSE}. @@ -785,8 +814,8 @@ namespace Inst { kIdRdtscp, //!< Instruction 'rdtscp' {RDTSCP}. kIdRet, //!< Instruction 'ret'. kIdRetf, //!< Instruction 'retf'. - kIdRmpadjust, //!< Instruction 'rmpadjust' {SNP} (X64). - kIdRmpupdate, //!< Instruction 'rmpupdate' {SNP} (X64). + kIdRmpadjust, //!< Instruction 'rmpadjust' {SEV_SNP} (X64). + kIdRmpupdate, //!< Instruction 'rmpupdate' {SEV_SNP} (X64). kIdRol, //!< Instruction 'rol'. kIdRor, //!< Instruction 'ror'. kIdRorx, //!< Instruction 'rorx' {BMI2}. @@ -805,6 +834,9 @@ namespace Inst { kIdSaveprevssp, //!< Instruction 'saveprevssp' {CET_SS}. kIdSbb, //!< Instruction 'sbb'. kIdScas, //!< Instruction 'scas'. + kIdSeamcall, //!< Instruction 'seamcall' {SEAM}. + kIdSeamops, //!< Instruction 'seamops' {SEAM}. + kIdSeamret, //!< Instruction 'seamret' {SEAM}. kIdSenduipi, //!< Instruction 'senduipi' {UINTR} (X64). kIdSerialize, //!< Instruction 'serialize' {SERIALIZE}. kIdSeta, //!< Instruction 'seta'. @@ -838,7 +870,7 @@ namespace Inst { kIdSets, //!< Instruction 'sets'. kIdSetssbsy, //!< Instruction 'setssbsy' {CET_SS}. kIdSetz, //!< Instruction 'setz'. - kIdSfence, //!< Instruction 'sfence' {MMX2}. + kIdSfence, //!< Instruction 'sfence' {SSE}. kIdSgdt, //!< Instruction 'sgdt'. kIdSha1msg1, //!< Instruction 'sha1msg1' {SHA}. kIdSha1msg2, //!< Instruction 'sha1msg2' {SHA}. @@ -883,15 +915,19 @@ namespace Inst { kIdSyscall, //!< Instruction 'syscall' (X64). kIdSysenter, //!< Instruction 'sysenter'. kIdSysexit, //!< Instruction 'sysexit'. - kIdSysexitq, //!< Instruction 'sysexitq'. + kIdSysexitq, //!< Instruction 'sysexitq' (X64). kIdSysret, //!< Instruction 'sysret' (X64). kIdSysretq, //!< Instruction 'sysretq' (X64). kIdT1mskc, //!< Instruction 't1mskc' {TBM}. + kIdTcmmimfp16ps, //!< Instruction 'tcmmimfp16ps' {AMX_COMPLEX} (X64). + kIdTcmmrlfp16ps, //!< Instruction 'tcmmrlfp16ps' {AMX_COMPLEX} (X64). + kIdTdcall, //!< Instruction 'tdcall' {SEAM}. kIdTdpbf16ps, //!< Instruction 'tdpbf16ps' {AMX_BF16} (X64). kIdTdpbssd, //!< Instruction 'tdpbssd' {AMX_INT8} (X64). kIdTdpbsud, //!< Instruction 'tdpbsud' {AMX_INT8} (X64). kIdTdpbusd, //!< Instruction 'tdpbusd' {AMX_INT8} (X64). kIdTdpbuud, //!< Instruction 'tdpbuud' {AMX_INT8} (X64). + kIdTdpfp16ps, //!< Instruction 'tdpfp16ps' {AMX_FP16} (X64). kIdTest, //!< Instruction 'test'. kIdTestui, //!< Instruction 'testui' {UINTR} (X64). kIdTileloadd, //!< Instruction 'tileloadd' {AMX_TILE} (X64). @@ -899,6 +935,7 @@ namespace Inst { kIdTilerelease, //!< Instruction 'tilerelease' {AMX_TILE} (X64). kIdTilestored, //!< Instruction 'tilestored' {AMX_TILE} (X64). kIdTilezero, //!< Instruction 'tilezero' {AMX_TILE} (X64). + kIdTlbsync, //!< Instruction 'tlbsync' {INVLPGB}. kIdTpause, //!< Instruction 'tpause' {WAITPKG}. kIdTzcnt, //!< Instruction 'tzcnt' {BMI}. kIdTzmsk, //!< Instruction 'tzmsk' {TBM}. @@ -938,6 +975,8 @@ namespace Inst { kIdVandnps, //!< Instruction 'vandnps' {AVX|AVX512_DQ+VL}. kIdVandpd, //!< Instruction 'vandpd' {AVX|AVX512_DQ+VL}. kIdVandps, //!< Instruction 'vandps' {AVX|AVX512_DQ+VL}. + kIdVbcstnebf162ps, //!< Instruction 'vbcstnebf162ps' {AVX_NE_CONVERT}. + kIdVbcstnesh2ps, //!< Instruction 'vbcstnesh2ps' {AVX_NE_CONVERT}. kIdVblendmpd, //!< Instruction 'vblendmpd' {AVX512_F+VL}. kIdVblendmps, //!< Instruction 'vblendmps' {AVX512_F+VL}. kIdVblendpd, //!< Instruction 'vblendpd' {AVX}. @@ -973,7 +1012,11 @@ namespace Inst { kIdVcvtdq2ph, //!< Instruction 'vcvtdq2ph' {AVX512_FP16+VL}. kIdVcvtdq2ps, //!< Instruction 'vcvtdq2ps' {AVX|AVX512_F+VL}. kIdVcvtne2ps2bf16, //!< Instruction 'vcvtne2ps2bf16' {AVX512_BF16+VL}. - kIdVcvtneps2bf16, //!< Instruction 'vcvtneps2bf16' {AVX512_BF16+VL}. + kIdVcvtneebf162ps, //!< Instruction 'vcvtneebf162ps' {AVX_NE_CONVERT}. + kIdVcvtneeph2ps, //!< Instruction 'vcvtneeph2ps' {AVX_NE_CONVERT}. + kIdVcvtneobf162ps, //!< Instruction 'vcvtneobf162ps' {AVX_NE_CONVERT}. + kIdVcvtneoph2ps, //!< Instruction 'vcvtneoph2ps' {AVX_NE_CONVERT}. + kIdVcvtneps2bf16, //!< Instruction 'vcvtneps2bf16' {AVX_NE_CONVERT|AVX512_BF16+VL}. kIdVcvtpd2dq, //!< Instruction 'vcvtpd2dq' {AVX|AVX512_F+VL}. kIdVcvtpd2ph, //!< Instruction 'vcvtpd2ph' {AVX512_FP16+VL}. kIdVcvtpd2ps, //!< Instruction 'vcvtpd2ps' {AVX|AVX512_F+VL}. @@ -1057,8 +1100,8 @@ namespace Inst { kIdVdpps, //!< Instruction 'vdpps' {AVX}. kIdVerr, //!< Instruction 'verr'. kIdVerw, //!< Instruction 'verw'. - kIdVexp2pd, //!< Instruction 'vexp2pd' {AVX512_ERI}. - kIdVexp2ps, //!< Instruction 'vexp2ps' {AVX512_ERI}. + kIdVexp2pd, //!< Instruction 'vexp2pd' {AVX512_ER}. + kIdVexp2ps, //!< Instruction 'vexp2ps' {AVX512_ER}. kIdVexpandpd, //!< Instruction 'vexpandpd' {AVX512_F+VL}. kIdVexpandps, //!< Instruction 'vexpandps' {AVX512_F+VL}. kIdVextractf128, //!< Instruction 'vextractf128' {AVX}. @@ -1073,9 +1116,9 @@ namespace Inst { kIdVextracti64x4, //!< Instruction 'vextracti64x4' {AVX512_F}. kIdVextractps, //!< Instruction 'vextractps' {AVX|AVX512_F}. kIdVfcmaddcph, //!< Instruction 'vfcmaddcph' {AVX512_FP16+VL}. - kIdVfcmaddcsh, //!< Instruction 'vfcmaddcsh' {AVX512_FP16+VL}. + kIdVfcmaddcsh, //!< Instruction 'vfcmaddcsh' {AVX512_FP16}. kIdVfcmulcph, //!< Instruction 'vfcmulcph' {AVX512_FP16+VL}. - kIdVfcmulcsh, //!< Instruction 'vfcmulcsh' {AVX512_FP16+VL}. + kIdVfcmulcsh, //!< Instruction 'vfcmulcsh' {AVX512_FP16}. kIdVfixupimmpd, //!< Instruction 'vfixupimmpd' {AVX512_F+VL}. kIdVfixupimmps, //!< Instruction 'vfixupimmps' {AVX512_F+VL}. kIdVfixupimmsd, //!< Instruction 'vfixupimmsd' {AVX512_F}. @@ -1099,7 +1142,7 @@ namespace Inst { kIdVfmadd231sh, //!< Instruction 'vfmadd231sh' {AVX512_FP16}. kIdVfmadd231ss, //!< Instruction 'vfmadd231ss' {FMA|AVX512_F}. kIdVfmaddcph, //!< Instruction 'vfmaddcph' {AVX512_FP16+VL}. - kIdVfmaddcsh, //!< Instruction 'vfmaddcsh' {AVX512_FP16+VL}. + kIdVfmaddcsh, //!< Instruction 'vfmaddcsh' {AVX512_FP16}. kIdVfmaddpd, //!< Instruction 'vfmaddpd' {FMA4}. kIdVfmaddps, //!< Instruction 'vfmaddps' {FMA4}. kIdVfmaddsd, //!< Instruction 'vfmaddsd' {FMA4}. @@ -1206,14 +1249,14 @@ namespace Inst { kIdVfrczss, //!< Instruction 'vfrczss' {XOP}. kIdVgatherdpd, //!< Instruction 'vgatherdpd' {AVX2|AVX512_F+VL}. kIdVgatherdps, //!< Instruction 'vgatherdps' {AVX2|AVX512_F+VL}. - kIdVgatherpf0dpd, //!< Instruction 'vgatherpf0dpd' {AVX512_PFI}. - kIdVgatherpf0dps, //!< Instruction 'vgatherpf0dps' {AVX512_PFI}. - kIdVgatherpf0qpd, //!< Instruction 'vgatherpf0qpd' {AVX512_PFI}. - kIdVgatherpf0qps, //!< Instruction 'vgatherpf0qps' {AVX512_PFI}. - kIdVgatherpf1dpd, //!< Instruction 'vgatherpf1dpd' {AVX512_PFI}. - kIdVgatherpf1dps, //!< Instruction 'vgatherpf1dps' {AVX512_PFI}. - kIdVgatherpf1qpd, //!< Instruction 'vgatherpf1qpd' {AVX512_PFI}. - kIdVgatherpf1qps, //!< Instruction 'vgatherpf1qps' {AVX512_PFI}. + kIdVgatherpf0dpd, //!< Instruction 'vgatherpf0dpd' {AVX512_PF}. + kIdVgatherpf0dps, //!< Instruction 'vgatherpf0dps' {AVX512_PF}. + kIdVgatherpf0qpd, //!< Instruction 'vgatherpf0qpd' {AVX512_PF}. + kIdVgatherpf0qps, //!< Instruction 'vgatherpf0qps' {AVX512_PF}. + kIdVgatherpf1dpd, //!< Instruction 'vgatherpf1dpd' {AVX512_PF}. + kIdVgatherpf1dps, //!< Instruction 'vgatherpf1dps' {AVX512_PF}. + kIdVgatherpf1qpd, //!< Instruction 'vgatherpf1qpd' {AVX512_PF}. + kIdVgatherpf1qps, //!< Instruction 'vgatherpf1qps' {AVX512_PF}. kIdVgatherqpd, //!< Instruction 'vgatherqpd' {AVX2|AVX512_F+VL}. kIdVgatherqps, //!< Instruction 'vgatherqps' {AVX2|AVX512_F+VL}. kIdVgetexppd, //!< Instruction 'vgetexppd' {AVX512_F+VL}. @@ -1254,18 +1297,19 @@ namespace Inst { kIdVmaxpd, //!< Instruction 'vmaxpd' {AVX|AVX512_F+VL}. kIdVmaxph, //!< Instruction 'vmaxph' {AVX512_FP16+VL}. kIdVmaxps, //!< Instruction 'vmaxps' {AVX|AVX512_F+VL}. - kIdVmaxsd, //!< Instruction 'vmaxsd' {AVX|AVX512_F+VL}. + kIdVmaxsd, //!< Instruction 'vmaxsd' {AVX|AVX512_F}. kIdVmaxsh, //!< Instruction 'vmaxsh' {AVX512_FP16}. - kIdVmaxss, //!< Instruction 'vmaxss' {AVX|AVX512_F+VL}. + kIdVmaxss, //!< Instruction 'vmaxss' {AVX|AVX512_F}. kIdVmcall, //!< Instruction 'vmcall' {VMX}. kIdVmclear, //!< Instruction 'vmclear' {VMX}. kIdVmfunc, //!< Instruction 'vmfunc' {VMX}. + kIdVmgexit, //!< Instruction 'vmgexit' {SEV_ES}. kIdVminpd, //!< Instruction 'vminpd' {AVX|AVX512_F+VL}. kIdVminph, //!< Instruction 'vminph' {AVX512_FP16+VL}. kIdVminps, //!< Instruction 'vminps' {AVX|AVX512_F+VL}. - kIdVminsd, //!< Instruction 'vminsd' {AVX|AVX512_F+VL}. + kIdVminsd, //!< Instruction 'vminsd' {AVX|AVX512_F}. kIdVminsh, //!< Instruction 'vminsh' {AVX512_FP16}. - kIdVminss, //!< Instruction 'vminss' {AVX|AVX512_F+VL}. + kIdVminss, //!< Instruction 'vminss' {AVX|AVX512_F}. kIdVmlaunch, //!< Instruction 'vmlaunch' {VMX}. kIdVmload, //!< Instruction 'vmload' {SVM}. kIdVmmcall, //!< Instruction 'vmmcall' {SVM}. @@ -1316,11 +1360,12 @@ namespace Inst { kIdVmulsh, //!< Instruction 'vmulsh' {AVX512_FP16}. kIdVmulss, //!< Instruction 'vmulss' {AVX|AVX512_F}. kIdVmwrite, //!< Instruction 'vmwrite' {VMX}. + kIdVmxoff, //!< Instruction 'vmxoff' {VMX}. kIdVmxon, //!< Instruction 'vmxon' {VMX}. kIdVorpd, //!< Instruction 'vorpd' {AVX|AVX512_DQ+VL}. kIdVorps, //!< Instruction 'vorps' {AVX|AVX512_DQ+VL}. - kIdVp2intersectd, //!< Instruction 'vp2intersectd' {AVX512_VP2INTERSECT}. - kIdVp2intersectq, //!< Instruction 'vp2intersectq' {AVX512_VP2INTERSECT}. + kIdVp2intersectd, //!< Instruction 'vp2intersectd' {AVX512_VP2INTERSECT+VL}. + kIdVp2intersectq, //!< Instruction 'vp2intersectq' {AVX512_VP2INTERSECT+VL}. kIdVp4dpwssd, //!< Instruction 'vp4dpwssd' {AVX512_4VNNIW}. kIdVp4dpwssds, //!< Instruction 'vp4dpwssds' {AVX512_4VNNIW}. kIdVpabsb, //!< Instruction 'vpabsb' {AVX|AVX2|AVX512_BW+VL}. @@ -1357,8 +1402,8 @@ namespace Inst { kIdVpblendw, //!< Instruction 'vpblendw' {AVX|AVX2}. kIdVpbroadcastb, //!< Instruction 'vpbroadcastb' {AVX2|AVX512_BW+VL}. kIdVpbroadcastd, //!< Instruction 'vpbroadcastd' {AVX2|AVX512_F+VL}. - kIdVpbroadcastmb2q, //!< Instruction 'vpbroadcastmb2q' {AVX512_CDI+VL}. - kIdVpbroadcastmw2d, //!< Instruction 'vpbroadcastmw2d' {AVX512_CDI+VL}. + kIdVpbroadcastmb2q, //!< Instruction 'vpbroadcastmb2q' {AVX512_CD+VL}. + kIdVpbroadcastmw2d, //!< Instruction 'vpbroadcastmw2d' {AVX512_CD+VL}. kIdVpbroadcastq, //!< Instruction 'vpbroadcastq' {AVX2|AVX512_F+VL}. kIdVpbroadcastw, //!< Instruction 'vpbroadcastw' {AVX2|AVX512_BW+VL}. kIdVpclmulqdq, //!< Instruction 'vpclmulqdq' {AVX|AVX512_F+VL & PCLMULQDQ|VPCLMULQDQ}. @@ -1395,12 +1440,24 @@ namespace Inst { kIdVpcomuq, //!< Instruction 'vpcomuq' {XOP}. kIdVpcomuw, //!< Instruction 'vpcomuw' {XOP}. kIdVpcomw, //!< Instruction 'vpcomw' {XOP}. - kIdVpconflictd, //!< Instruction 'vpconflictd' {AVX512_CDI+VL}. - kIdVpconflictq, //!< Instruction 'vpconflictq' {AVX512_CDI+VL}. + kIdVpconflictd, //!< Instruction 'vpconflictd' {AVX512_CD+VL}. + kIdVpconflictq, //!< Instruction 'vpconflictq' {AVX512_CD+VL}. + kIdVpdpbssd, //!< Instruction 'vpdpbssd' {AVX_VNNI_INT8}. + kIdVpdpbssds, //!< Instruction 'vpdpbssds' {AVX_VNNI_INT8}. + kIdVpdpbsud, //!< Instruction 'vpdpbsud' {AVX_VNNI_INT8}. + kIdVpdpbsuds, //!< Instruction 'vpdpbsuds' {AVX_VNNI_INT8}. kIdVpdpbusd, //!< Instruction 'vpdpbusd' {AVX_VNNI|AVX512_VNNI+VL}. kIdVpdpbusds, //!< Instruction 'vpdpbusds' {AVX_VNNI|AVX512_VNNI+VL}. + kIdVpdpbuud, //!< Instruction 'vpdpbuud' {AVX_VNNI_INT8}. + kIdVpdpbuuds, //!< Instruction 'vpdpbuuds' {AVX_VNNI_INT8}. kIdVpdpwssd, //!< Instruction 'vpdpwssd' {AVX_VNNI|AVX512_VNNI+VL}. kIdVpdpwssds, //!< Instruction 'vpdpwssds' {AVX_VNNI|AVX512_VNNI+VL}. + kIdVpdpwsud, //!< Instruction 'vpdpwsud' {AVX_VNNI_INT16}. + kIdVpdpwsuds, //!< Instruction 'vpdpwsuds' {AVX_VNNI_INT16}. + kIdVpdpwusd, //!< Instruction 'vpdpwusd' {AVX_VNNI_INT16}. + kIdVpdpwusds, //!< Instruction 'vpdpwusds' {AVX_VNNI_INT16}. + kIdVpdpwuud, //!< Instruction 'vpdpwuud' {AVX_VNNI_INT16}. + kIdVpdpwuuds, //!< Instruction 'vpdpwuuds' {AVX_VNNI_INT16}. kIdVperm2f128, //!< Instruction 'vperm2f128' {AVX}. kIdVperm2i128, //!< Instruction 'vperm2i128' {AVX2}. kIdVpermb, //!< Instruction 'vpermb' {AVX512_VBMI+VL}. @@ -1463,8 +1520,8 @@ namespace Inst { kIdVpinsrd, //!< Instruction 'vpinsrd' {AVX|AVX512_DQ}. kIdVpinsrq, //!< Instruction 'vpinsrq' {AVX|AVX512_DQ} (X64). kIdVpinsrw, //!< Instruction 'vpinsrw' {AVX|AVX512_BW}. - kIdVplzcntd, //!< Instruction 'vplzcntd' {AVX512_CDI+VL}. - kIdVplzcntq, //!< Instruction 'vplzcntq' {AVX512_CDI+VL}. + kIdVplzcntd, //!< Instruction 'vplzcntd' {AVX512_CD+VL}. + kIdVplzcntq, //!< Instruction 'vplzcntq' {AVX512_CD+VL}. kIdVpmacsdd, //!< Instruction 'vpmacsdd' {XOP}. kIdVpmacsdqh, //!< Instruction 'vpmacsdqh' {XOP}. kIdVpmacsdql, //!< Instruction 'vpmacsdql' {XOP}. @@ -1477,8 +1534,8 @@ namespace Inst { kIdVpmacsww, //!< Instruction 'vpmacsww' {XOP}. kIdVpmadcsswd, //!< Instruction 'vpmadcsswd' {XOP}. kIdVpmadcswd, //!< Instruction 'vpmadcswd' {XOP}. - kIdVpmadd52huq, //!< Instruction 'vpmadd52huq' {AVX512_IFMA+VL}. - kIdVpmadd52luq, //!< Instruction 'vpmadd52luq' {AVX512_IFMA+VL}. + kIdVpmadd52huq, //!< Instruction 'vpmadd52huq' {AVX_IFMA|AVX512_IFMA+VL}. + kIdVpmadd52luq, //!< Instruction 'vpmadd52luq' {AVX_IFMA|AVX512_IFMA+VL}. kIdVpmaddubsw, //!< Instruction 'vpmaddubsw' {AVX|AVX2|AVX512_BW+VL}. kIdVpmaddwd, //!< Instruction 'vpmaddwd' {AVX|AVX2|AVX512_BW+VL}. kIdVpmaskmovd, //!< Instruction 'vpmaskmovd' {AVX2}. @@ -1658,10 +1715,10 @@ namespace Inst { kIdVrcp14ps, //!< Instruction 'vrcp14ps' {AVX512_F+VL}. kIdVrcp14sd, //!< Instruction 'vrcp14sd' {AVX512_F}. kIdVrcp14ss, //!< Instruction 'vrcp14ss' {AVX512_F}. - kIdVrcp28pd, //!< Instruction 'vrcp28pd' {AVX512_ERI}. - kIdVrcp28ps, //!< Instruction 'vrcp28ps' {AVX512_ERI}. - kIdVrcp28sd, //!< Instruction 'vrcp28sd' {AVX512_ERI}. - kIdVrcp28ss, //!< Instruction 'vrcp28ss' {AVX512_ERI}. + kIdVrcp28pd, //!< Instruction 'vrcp28pd' {AVX512_ER}. + kIdVrcp28ps, //!< Instruction 'vrcp28ps' {AVX512_ER}. + kIdVrcp28sd, //!< Instruction 'vrcp28sd' {AVX512_ER}. + kIdVrcp28ss, //!< Instruction 'vrcp28ss' {AVX512_ER}. kIdVrcpph, //!< Instruction 'vrcpph' {AVX512_FP16}. kIdVrcpps, //!< Instruction 'vrcpps' {AVX}. kIdVrcpsh, //!< Instruction 'vrcpsh' {AVX512_FP16}. @@ -1686,10 +1743,10 @@ namespace Inst { kIdVrsqrt14ps, //!< Instruction 'vrsqrt14ps' {AVX512_F+VL}. kIdVrsqrt14sd, //!< Instruction 'vrsqrt14sd' {AVX512_F}. kIdVrsqrt14ss, //!< Instruction 'vrsqrt14ss' {AVX512_F}. - kIdVrsqrt28pd, //!< Instruction 'vrsqrt28pd' {AVX512_ERI}. - kIdVrsqrt28ps, //!< Instruction 'vrsqrt28ps' {AVX512_ERI}. - kIdVrsqrt28sd, //!< Instruction 'vrsqrt28sd' {AVX512_ERI}. - kIdVrsqrt28ss, //!< Instruction 'vrsqrt28ss' {AVX512_ERI}. + kIdVrsqrt28pd, //!< Instruction 'vrsqrt28pd' {AVX512_ER}. + kIdVrsqrt28ps, //!< Instruction 'vrsqrt28ps' {AVX512_ER}. + kIdVrsqrt28sd, //!< Instruction 'vrsqrt28sd' {AVX512_ER}. + kIdVrsqrt28ss, //!< Instruction 'vrsqrt28ss' {AVX512_ER}. kIdVrsqrtph, //!< Instruction 'vrsqrtph' {AVX512_FP16+VL}. kIdVrsqrtps, //!< Instruction 'vrsqrtps' {AVX}. kIdVrsqrtsh, //!< Instruction 'vrsqrtsh' {AVX512_FP16}. @@ -1702,22 +1759,30 @@ namespace Inst { kIdVscalefss, //!< Instruction 'vscalefss' {AVX512_F}. kIdVscatterdpd, //!< Instruction 'vscatterdpd' {AVX512_F+VL}. kIdVscatterdps, //!< Instruction 'vscatterdps' {AVX512_F+VL}. - kIdVscatterpf0dpd, //!< Instruction 'vscatterpf0dpd' {AVX512_PFI}. - kIdVscatterpf0dps, //!< Instruction 'vscatterpf0dps' {AVX512_PFI}. - kIdVscatterpf0qpd, //!< Instruction 'vscatterpf0qpd' {AVX512_PFI}. - kIdVscatterpf0qps, //!< Instruction 'vscatterpf0qps' {AVX512_PFI}. - kIdVscatterpf1dpd, //!< Instruction 'vscatterpf1dpd' {AVX512_PFI}. - kIdVscatterpf1dps, //!< Instruction 'vscatterpf1dps' {AVX512_PFI}. - kIdVscatterpf1qpd, //!< Instruction 'vscatterpf1qpd' {AVX512_PFI}. - kIdVscatterpf1qps, //!< Instruction 'vscatterpf1qps' {AVX512_PFI}. + kIdVscatterpf0dpd, //!< Instruction 'vscatterpf0dpd' {AVX512_PF}. + kIdVscatterpf0dps, //!< Instruction 'vscatterpf0dps' {AVX512_PF}. + kIdVscatterpf0qpd, //!< Instruction 'vscatterpf0qpd' {AVX512_PF}. + kIdVscatterpf0qps, //!< Instruction 'vscatterpf0qps' {AVX512_PF}. + kIdVscatterpf1dpd, //!< Instruction 'vscatterpf1dpd' {AVX512_PF}. + kIdVscatterpf1dps, //!< Instruction 'vscatterpf1dps' {AVX512_PF}. + kIdVscatterpf1qpd, //!< Instruction 'vscatterpf1qpd' {AVX512_PF}. + kIdVscatterpf1qps, //!< Instruction 'vscatterpf1qps' {AVX512_PF}. kIdVscatterqpd, //!< Instruction 'vscatterqpd' {AVX512_F+VL}. kIdVscatterqps, //!< Instruction 'vscatterqps' {AVX512_F+VL}. + kIdVsha512msg1, //!< Instruction 'vsha512msg1' {AVX & SHA512}. + kIdVsha512msg2, //!< Instruction 'vsha512msg2' {AVX & SHA512}. + kIdVsha512rnds2, //!< Instruction 'vsha512rnds2' {AVX & SHA512}. kIdVshuff32x4, //!< Instruction 'vshuff32x4' {AVX512_F+VL}. kIdVshuff64x2, //!< Instruction 'vshuff64x2' {AVX512_F+VL}. kIdVshufi32x4, //!< Instruction 'vshufi32x4' {AVX512_F+VL}. kIdVshufi64x2, //!< Instruction 'vshufi64x2' {AVX512_F+VL}. kIdVshufpd, //!< Instruction 'vshufpd' {AVX|AVX512_F+VL}. kIdVshufps, //!< Instruction 'vshufps' {AVX|AVX512_F+VL}. + kIdVsm3msg1, //!< Instruction 'vsm3msg1' {AVX & SM3}. + kIdVsm3msg2, //!< Instruction 'vsm3msg2' {AVX & SM3}. + kIdVsm3rnds2, //!< Instruction 'vsm3rnds2' {AVX & SM3}. + kIdVsm4key4, //!< Instruction 'vsm4key4' {AVX & SM4}. + kIdVsm4rnds4, //!< Instruction 'vsm4rnds4' {AVX & SM4}. kIdVsqrtpd, //!< Instruction 'vsqrtpd' {AVX|AVX512_F+VL}. kIdVsqrtph, //!< Instruction 'vsqrtph' {AVX512_FP16+VL}. kIdVsqrtps, //!< Instruction 'vsqrtps' {AVX|AVX512_F+VL}. @@ -1744,7 +1809,7 @@ namespace Inst { kIdVxorps, //!< Instruction 'vxorps' {AVX|AVX512_DQ+VL}. kIdVzeroall, //!< Instruction 'vzeroall' {AVX}. kIdVzeroupper, //!< Instruction 'vzeroupper' {AVX}. - kIdWbinvd, //!< Instruction 'wbinvd'. + kIdWbinvd, //!< Instruction 'wbinvd' {I486}. kIdWbnoinvd, //!< Instruction 'wbnoinvd' {WBNOINVD}. kIdWrfsbase, //!< Instruction 'wrfsbase' {FSGSBASE} (X64). kIdWrgsbase, //!< Instruction 'wrgsbase' {FSGSBASE} (X64). @@ -1784,7 +1849,7 @@ namespace Inst { }; //! Tests whether the `instId` is defined. - static inline constexpr bool isDefinedId(InstId instId) noexcept { return instId < _kIdCount; } + static ASMJIT_INLINE_NODEBUG constexpr bool isDefinedId(InstId instId) noexcept { return instId < _kIdCount; } //! \cond #define ASMJIT_INST_FROM_COND(ID) \ @@ -1801,11 +1866,11 @@ namespace Inst { //! \endcond //! Translates a condition code `cond` to a `jcc` instruction id. - static constexpr InstId jccFromCond(CondCode cond) noexcept { return _jccTable[uint8_t(cond)]; } + static ASMJIT_INLINE_NODEBUG constexpr InstId jccFromCond(CondCode cond) noexcept { return _jccTable[uint8_t(cond)]; } //! Translates a condition code `cond` to a `setcc` instruction id. - static constexpr InstId setccFromCond(CondCode cond) noexcept { return _setccTable[uint8_t(cond)]; } + static ASMJIT_INLINE_NODEBUG constexpr InstId setccFromCond(CondCode cond) noexcept { return _setccTable[uint8_t(cond)]; } //! Translates a condition code `cond` to a `cmovcc` instruction id. - static constexpr InstId cmovccFromCond(CondCode cond) noexcept { return _cmovccTable[uint8_t(cond)]; } + static ASMJIT_INLINE_NODEBUG constexpr InstId cmovccFromCond(CondCode cond) noexcept { return _cmovccTable[uint8_t(cond)]; } } // {Inst} //! FPU status word bits. @@ -1933,7 +1998,7 @@ enum class RoundImm : uint8_t { kUp = 0x02u, //!< Round to up toward +INF (ceil). kTrunc = 0x03u, //!< Round toward zero (truncate). kCurrent = 0x04u, //!< Round to the current rounding mode set (ignores other RC bits). - kSuppress = 0x08u //!< Supress exceptions (avoids inexact exception, if set). + kSuppress = 0x08u //!< Suppress exceptions (avoids inexact exception, if set). }; ASMJIT_DEFINE_ENUM_FLAGS(RoundImm) @@ -2085,7 +2150,7 @@ enum class VReduceImm : uint8_t { ASMJIT_DEFINE_ENUM_FLAGS(VReduceImm) //! Creates a \ref VReduceImm from a combination of `flags` and `fixedPointLength`. -static inline constexpr VReduceImm vReduceImm(VReduceImm flags, uint32_t fixedPointLength) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr VReduceImm vReduceImm(VReduceImm flags, uint32_t fixedPointLength) noexcept { return flags | VReduceImm(fixedPointLength << 4); } @@ -2120,7 +2185,7 @@ enum class TLogImm : uint8_t { ASMJIT_DEFINE_ENUM_FLAGS(TLogImm) //! Creates an immediate that can be used by VPTERNLOG[D|Q] instructions. -static inline constexpr TLogImm tLogFromBits(uint8_t b000, uint8_t b001, uint8_t b010, uint8_t b011, uint8_t b100, uint8_t b101, uint8_t b110, uint8_t b111) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr TLogImm tLogFromBits(uint8_t b000, uint8_t b001, uint8_t b010, uint8_t b011, uint8_t b100, uint8_t b101, uint8_t b110, uint8_t b111) noexcept { return TLogImm(uint8_t(b000 << 0) | uint8_t(b001 << 1) | uint8_t(b010 << 2) | @@ -2132,7 +2197,7 @@ static inline constexpr TLogImm tLogFromBits(uint8_t b000, uint8_t b001, uint8_t } //! Creates an if/else logic that can be used by VPTERNLOG[D|Q] instructions. -static inline constexpr TLogImm fLogIfElse(TLogImm condition, TLogImm a, TLogImm b) noexcept { return (condition & a) | (~condition & b); } +static ASMJIT_INLINE_NODEBUG constexpr TLogImm fLogIfElse(TLogImm condition, TLogImm a, TLogImm b) noexcept { return (condition & a) | (~condition & b); } //! Creates a shuffle immediate value that be used with SSE/AVX/AVX-512 instructions to shuffle 2 elements in a vector. //! @@ -2141,7 +2206,7 @@ static inline constexpr TLogImm fLogIfElse(TLogImm condition, TLogImm a, TLogImm //! //! Shuffle constants can be used to encode an immediate for these instructions: //! - `shufpd|vshufpd` -static inline constexpr uint32_t shuffleImm(uint32_t a, uint32_t b) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr uint32_t shuffleImm(uint32_t a, uint32_t b) noexcept { return (a << 1) | b; } @@ -2158,7 +2223,7 @@ static inline constexpr uint32_t shuffleImm(uint32_t a, uint32_t b) noexcept { //! - `pshufhw|vpshufhw` //! - `pshufd|vpshufd` //! - `shufps|vshufps` -static inline constexpr uint32_t shuffleImm(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr uint32_t shuffleImm(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept { return (a << 6) | (b << 4) | (c << 2) | d; } diff --git a/3rdparty/asmjit/src/asmjit/x86/x86instapi.cpp b/3rdparty/asmjit/src/asmjit/x86/x86instapi.cpp index 3857cc12127..fc17b5cdaea 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86instapi.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86instapi.cpp @@ -3,30 +3,12 @@ // See asmjit.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib -// ---------------------------------------------------------------------------- -// IMPORTANT: AsmJit now uses an external instruction database to populate -// static tables within this file. Perform the following steps to regenerate -// all tables enclosed by ${...}: -// -// 1. Install node.js environment <https://nodejs.org> -// 2. Go to asmjit/tools directory -// 3. Get the latest asmdb from <https://github.com/asmjit/asmdb> and -// copy/link the `asmdb` directory to `asmjit/tools/asmdb`. -// 4. Execute `node tablegen-x86.js` -// -// Instruction encoding and opcodes were added to the `x86inst.cpp` database -// manually in the past and they are not updated by the script as it became -// tricky. However, everything else is updated including instruction operands -// and tables required to validate them, instruction read/write information -// (including registers and flags), and all indexes to all tables. -// ---------------------------------------------------------------------------- - #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) #include "../core/cpuinfo.h" +#include "../core/instdb_p.h" #include "../core/misc_p.h" -#include "../core/support.h" #include "../x86/x86instapi_p.h" #include "../x86/x86instdb_p.h" #include "../x86/x86opcode_p.h" @@ -34,63 +16,21 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) +namespace InstInternal { + // x86::InstInternal - Text // ======================== #ifndef ASMJIT_NO_TEXT -Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noexcept { - DebugUtils::unused(arch); - +Error instIdToString(InstId instId, String& output) noexcept { if (ASMJIT_UNLIKELY(!Inst::isDefinedId(instId))) return DebugUtils::errored(kErrorInvalidInstruction); - const InstDB::InstInfo& info = InstDB::infoById(instId); - return output.append(InstDB::_nameData + info._nameDataIndex); + return InstNameUtils::decode(output, InstDB::_instNameIndexTable[instId], InstDB::_instNameStringTable); } -InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept { - DebugUtils::unused(arch); - - if (ASMJIT_UNLIKELY(!s)) - return Inst::kIdNone; - - if (len == SIZE_MAX) - len = strlen(s); - - if (ASMJIT_UNLIKELY(len == 0 || len > InstDB::kMaxNameSize)) - return Inst::kIdNone; - - uint32_t prefix = uint32_t(s[0]) - 'a'; - if (ASMJIT_UNLIKELY(prefix > 'z' - 'a')) - return Inst::kIdNone; - - uint32_t index = InstDB::instNameIndex[prefix].start; - if (ASMJIT_UNLIKELY(!index)) - return Inst::kIdNone; - - const char* nameData = InstDB::_nameData; - const InstDB::InstInfo* table = InstDB::_instInfoTable; - - const InstDB::InstInfo* base = table + index; - const InstDB::InstInfo* end = table + InstDB::instNameIndex[prefix].end; - - for (size_t lim = (size_t)(end - base); lim != 0; lim >>= 1) { - const InstDB::InstInfo* cur = base + (lim >> 1); - int result = Support::cmpInstName(nameData + cur[0]._nameDataIndex, s, len); - - if (result < 0) { - base = cur + 1; - lim--; - continue; - } - - if (result > 0) - continue; - - return InstId((size_t)(cur - table)); - } - - return Inst::kIdNone; +InstId stringToInstId(const char* s, size_t len) noexcept { + return InstNameUtils::find(s, len, InstDB::instNameIndex, InstDB::_instNameIndexTable, InstDB::_instNameStringTable); } #endif // !ASMJIT_NO_TEXT @@ -184,7 +124,7 @@ static const X86ValidationData _x64ValidationData = { #undef REG_MASK_FROM_REG_TYPE_X86 static ASMJIT_FORCE_INLINE bool x86IsZmmOrM512(const Operand_& op) noexcept { - return Reg::isZmm(op) || (op.isMem() && op.size() == 64); + return Reg::isZmm(op) || (op.isMem() && op.x86RmSize() == 64); } static ASMJIT_FORCE_INLINE bool x86CheckOSig(const InstDB::OpSignature& op, const InstDB::OpSignature& ref, bool& immOutOfRange) noexcept { @@ -216,20 +156,11 @@ static ASMJIT_FORCE_INLINE bool x86CheckOSig(const InstDB::OpSignature& op, cons return true; } -ASMJIT_FAVOR_SIZE Error InstInternal::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { - // Only called when `arch` matches X86 family. - ASMJIT_ASSERT(Environment::isFamilyX86(arch)); - - const X86ValidationData* vd; - if (arch == Arch::kX86) - vd = &_x86ValidationData; - else - vd = &_x64ValidationData; - +static ASMJIT_FAVOR_SIZE Error validate(InstDB::Mode mode, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { uint32_t i; - InstDB::Mode mode = InstDB::modeFromArch(arch); // Get the instruction data. + const X86ValidationData* vd = (mode == InstDB::Mode::kX86) ? &_x86ValidationData : &_x64ValidationData; InstId instId = inst.id(); InstOptions options = inst.options(); @@ -717,6 +648,15 @@ Next: return kErrorOk; } + +Error validateX86(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { + return validate(InstDB::Mode::kX86, inst, operands, opCount, validationFlags); +} + +Error validateX64(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { + return validate(InstDB::Mode::kX64, inst, operands, opCount, validationFlags); +} + #endif // !ASMJIT_NO_VALIDATION // x86::InstInternal - QueryRWInfo @@ -785,7 +725,7 @@ static ASMJIT_FORCE_INLINE bool hasSameRegType(const BaseReg* regs, size_t opCou return true; } -Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { +Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { // Only called when `arch` matches X86 family. ASMJIT_ASSERT(Environment::isFamilyX86(arch)); @@ -827,7 +767,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* constexpr OpRWFlags RegPhys = OpRWFlags::kRegPhysId; constexpr OpRWFlags MibRead = OpRWFlags::kMemBaseRead | OpRWFlags::kMemIndexRead; - if (instRwInfo.category == InstDB::RWInfo::kCategoryGeneric) { + if (instRwInfo.category <= uint32_t(InstDB::RWInfo::kCategoryGenericEx)) { uint32_t i; uint32_t rmOpsMask = 0; uint32_t rmMaxSize = 0; @@ -852,8 +792,8 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* uint64_t rByteMask = rwOpData.rByteMask; uint64_t wByteMask = rwOpData.wByteMask; - if (op.isRead() && !rByteMask) rByteMask = Support::lsbMask<uint64_t>(srcOp.size()); - if (op.isWrite() && !wByteMask) wByteMask = Support::lsbMask<uint64_t>(srcOp.size()); + if (op.isRead() && !rByteMask) rByteMask = Support::lsbMask<uint64_t>(srcOp.x86RmSize()); + if (op.isWrite() && !wByteMask) wByteMask = Support::lsbMask<uint64_t>(srcOp.x86RmSize()); op._readByteMask = rByteMask; op._writeByteMask = wByteMask; @@ -876,7 +816,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } // Aggregate values required to calculate valid Reg/M info. - rmMaxSize = Support::max(rmMaxSize, srcOp.size()); + rmMaxSize = Support::max(rmMaxSize, srcOp.x86RmSize()); rmOpsMask |= Support::bitMask<uint32_t>(i); } else { @@ -919,8 +859,8 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } } - rmOpsMask &= instRmInfo.rmOpsMask; - if (rmOpsMask) { + rmOpsMask &= uint32_t(instRmInfo.rmOpsMask); + if (rmOpsMask && !inst.hasOption(InstOptions::kX86_ER)) { Support::BitWordIterator<uint32_t> it(rmOpsMask); do { i = it.next(); @@ -933,7 +873,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* op.setRmSize(instRmInfo.fixedSize); break; case InstDB::RWInfoRm::kCategoryConsistent: - op.setRmSize(operands[i].size()); + op.setRmSize(operands[i].x86RmSize()); break; case InstDB::RWInfoRm::kCategoryHalf: op.setRmSize(rmMaxSize / 2u); @@ -948,6 +888,27 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } while (it.hasNext()); } + // Special cases per instruction. + if (instRwInfo.category == InstDB::RWInfo::kCategoryGenericEx) { + switch (inst.id()) { + case Inst::kIdVpternlogd: + case Inst::kIdVpternlogq: { + if (opCount == 4 && operands[3].isImm()) { + uint32_t predicate = operands[3].as<Imm>().valueAs<uint8_t>(); + + if ((predicate >> 4) == (predicate & 0xF)) { + out->_operands[0].clearOpFlags(OpRWFlags::kRead); + out->_operands[0].setReadByteMask(0); + } + } + break; + } + + default: + break; + } + } + return rwHandleAVX512(inst, commonInfo, out); } @@ -966,8 +927,8 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* const Reg& o1 = operands[1].as<Reg>(); if (o0.isGp() && o1.isGp()) { - out->_operands[0].reset(W | RegM, operands[0].size()); - out->_operands[1].reset(R | RegM, operands[1].size()); + out->_operands[0].reset(W | RegM, operands[0].x86RmSize()); + out->_operands[1].reset(R | RegM, operands[1].x86RmSize()); rwZeroExtendGp(out->_operands[0], operands[0].as<Gp>(), nativeGpSize); out->_instFlags |= InstRWFlags::kMovOp; @@ -1114,14 +1075,14 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* if (opCount == 2) { if (operands[0].isReg() && operands[1].isImm()) { - out->_operands[0].reset(X, operands[0].size()); + out->_operands[0].reset(X, operands[0].as<Reg>().size()); out->_operands[1].reset(); rwZeroExtendGp(out->_operands[0], operands[0].as<Gp>(), nativeGpSize); return kErrorOk; } - if (Reg::isGpw(operands[0]) && operands[1].size() == 1) { + if (Reg::isGpw(operands[0]) && operands[1].x86RmSize() == 1) { // imul ax, r8/m8 <- AX = AL * r8/m8 out->_operands[0].reset(X | RegPhys, 2, Gp::kIdAx); out->_operands[0].setReadByteMask(Support::lsbMask<uint64_t>(1)); @@ -1129,8 +1090,8 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } else { // imul r?, r?/m? - out->_operands[0].reset(X, operands[0].size()); - out->_operands[1].reset(R | RegM, operands[0].size()); + out->_operands[0].reset(X, operands[0].as<Gp>().size()); + out->_operands[1].reset(R | RegM, operands[0].as<Gp>().size()); rwZeroExtendGp(out->_operands[0], operands[0].as<Gp>(), nativeGpSize); } @@ -1141,8 +1102,8 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* if (opCount == 3) { if (operands[2].isImm()) { - out->_operands[0].reset(W, operands[0].size()); - out->_operands[1].reset(R | RegM, operands[1].size()); + out->_operands[0].reset(W, operands[0].x86RmSize()); + out->_operands[1].reset(R | RegM, operands[1].x86RmSize()); out->_operands[2].reset(); rwZeroExtendGp(out->_operands[0], operands[0].as<Gp>(), nativeGpSize); @@ -1151,9 +1112,9 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* return kErrorOk; } else { - out->_operands[0].reset(W | RegPhys, operands[0].size(), Gp::kIdDx); - out->_operands[1].reset(X | RegPhys, operands[1].size(), Gp::kIdAx); - out->_operands[2].reset(R | RegM, operands[2].size()); + out->_operands[0].reset(W | RegPhys, operands[0].x86RmSize(), Gp::kIdDx); + out->_operands[1].reset(X | RegPhys, operands[1].x86RmSize(), Gp::kIdAx); + out->_operands[2].reset(R | RegM, operands[2].x86RmSize()); rwZeroExtendGp(out->_operands[0], operands[0].as<Gp>(), nativeGpSize); rwZeroExtendGp(out->_operands[1], operands[1].as<Gp>(), nativeGpSize); @@ -1230,18 +1191,18 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* // Special case for 'vmaskmovpd|vmaskmovps|vpmaskmovd|vpmaskmovq' instructions. if (opCount == 3) { if (BaseReg::isVec(operands[0]) && BaseReg::isVec(operands[1]) && operands[2].isMem()) { - out->_operands[0].reset(W, operands[0].size()); - out->_operands[1].reset(R, operands[1].size()); - out->_operands[2].reset(R | MibRead, operands[1].size()); + out->_operands[0].reset(W, operands[0].x86RmSize()); + out->_operands[1].reset(R, operands[1].x86RmSize()); + out->_operands[2].reset(R | MibRead, operands[1].x86RmSize()); rwZeroExtendAvxVec(out->_operands[0], operands[0].as<Vec>()); return kErrorOk; } if (operands[0].isMem() && BaseReg::isVec(operands[1]) && BaseReg::isVec(operands[2])) { - out->_operands[0].reset(X | MibRead, operands[1].size()); - out->_operands[1].reset(R, operands[1].size()); - out->_operands[2].reset(R, operands[2].size()); + out->_operands[0].reset(X | MibRead, operands[1].x86RmSize()); + out->_operands[1].reset(R, operands[1].x86RmSize()); + out->_operands[2].reset(R, operands[2].x86RmSize()); return kErrorOk; } } @@ -1254,7 +1215,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* // operand, respectively. if (opCount == 2) { if (BaseReg::isVec(operands[0]) && BaseReg::isVec(operands[1])) { - uint32_t o0Size = operands[0].size(); + uint32_t o0Size = operands[0].x86RmSize(); uint32_t o1Size = o0Size == 16 ? 8 : o0Size; out->_operands[0].reset(W, o0Size); @@ -1266,7 +1227,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } if (BaseReg::isVec(operands[0]) && operands[1].isMem()) { - uint32_t o0Size = operands[0].size(); + uint32_t o0Size = operands[0].x86RmSize(); uint32_t o1Size = o0Size == 16 ? 8 : o0Size; out->_operands[0].reset(W, o0Size); @@ -1286,7 +1247,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* if (BaseReg::isGp(operands[0]) && BaseReg::isVec(operands[1])) { out->_operands[0].reset(W, 1); out->_operands[0].setExtendByteMask(Support::lsbMask<uint32_t>(nativeGpSize - 1) << 1); - out->_operands[1].reset(R, operands[1].size()); + out->_operands[1].reset(R, operands[1].x86RmSize()); return kErrorOk; } } @@ -1324,7 +1285,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } if (operands[0].isReg() && operands[1].isReg()) { - uint32_t size1 = operands[1].size(); + uint32_t size1 = operands[1].x86RmSize(); uint32_t size0 = size1 >> shift; out->_operands[0].reset(W, size0); @@ -1351,16 +1312,20 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } if (operands[0].isReg() && operands[1].isMem()) { - uint32_t size1 = operands[1].size() ? operands[1].size() : uint32_t(16); + uint32_t size1 = operands[1].x86RmSize() ? operands[1].x86RmSize() : uint32_t(16); uint32_t size0 = size1 >> shift; out->_operands[0].reset(W, size0); out->_operands[1].reset(R | MibRead, size1); + + if (BaseReg::isVec(operands[0])) + rwZeroExtendAvxVec(out->_operands[0], operands[0].as<Vec>()); + return kErrorOk; } if (operands[0].isMem() && operands[1].isReg()) { - uint32_t size1 = operands[1].size(); + uint32_t size1 = operands[1].x86RmSize(); uint32_t size0 = size1 >> shift; out->_operands[0].reset(W | MibRead, size0); @@ -1401,12 +1366,15 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* out->_operands[2].reset(); } - uint32_t size0 = operands[0].size(); + uint32_t size0 = operands[0].x86RmSize(); uint32_t size1 = size0 >> shift; out->_operands[0].reset(W, size0); out->_operands[1].reset(R, size1); + if (BaseReg::isVec(operands[0])) + rwZeroExtendAvxVec(out->_operands[0], operands[0].as<Vec>()); + if (operands[0].isReg() && operands[1].isReg()) { if (instRmInfo.rmOpsMask & 0x1) { out->_operands[0].addOpFlags(RegM); @@ -1481,7 +1449,9 @@ static inline uint32_t InstInternal_usesAvx512(InstOptions instOptions, const Re return hasEvex | hasKMask | hasKOrZmm; } -Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { +Error queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { + typedef CpuFeatures::X86 Ext; + // Only called when `arch` matches X86 family. DebugUtils::unused(arch); ASMJIT_ASSERT(Environment::isFamilyX86(arch)); @@ -1514,19 +1484,19 @@ Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand RegAnalysis regAnalysis = InstInternal_regAnalysis(operands, opCount); // Handle MMX vs SSE overlap. - if (out->has(CpuFeatures::X86::kMMX) || out->has(CpuFeatures::X86::kMMX2)) { + if (out->has(Ext::kMMX) || out->has(Ext::kMMX2)) { // Only instructions defined by SSE and SSE2 overlap. Instructions introduced by newer instruction sets like // SSE3+ don't state MMX as they require SSE3+. - if (out->has(CpuFeatures::X86::kSSE) || out->has(CpuFeatures::X86::kSSE2)) { + if (out->has(Ext::kSSE) || out->has(Ext::kSSE2)) { if (!regAnalysis.hasRegType(RegType::kX86_Xmm)) { // The instruction doesn't use XMM register(s), thus it's MMX/MMX2 only. - out->remove(CpuFeatures::X86::kSSE); - out->remove(CpuFeatures::X86::kSSE2); - out->remove(CpuFeatures::X86::kSSE4_1); + out->remove(Ext::kSSE); + out->remove(Ext::kSSE2); + out->remove(Ext::kSSE4_1); } else { - out->remove(CpuFeatures::X86::kMMX); - out->remove(CpuFeatures::X86::kMMX2); + out->remove(Ext::kMMX); + out->remove(Ext::kMMX2); } // Special case: PEXTRW instruction is MMX/SSE2 instruction. However, MMX/SSE version cannot access memory @@ -1535,30 +1505,30 @@ Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand // is, of course, not compatible with MMX/SSE2 and would #UD if SSE4.1 is not supported. if (instId == Inst::kIdPextrw) { if (opCount >= 1 && operands[0].isMem()) - out->remove(CpuFeatures::X86::kSSE2); + out->remove(Ext::kSSE2); else - out->remove(CpuFeatures::X86::kSSE4_1); + out->remove(Ext::kSSE4_1); } } } // Handle PCLMULQDQ vs VPCLMULQDQ. - if (out->has(CpuFeatures::X86::kVPCLMULQDQ)) { + if (out->has(Ext::kVPCLMULQDQ)) { if (regAnalysis.hasRegType(RegType::kX86_Zmm) || Support::test(options, InstOptions::kX86_Evex)) { // AVX512_F & VPCLMULQDQ. - out->remove(CpuFeatures::X86::kAVX, CpuFeatures::X86::kPCLMULQDQ); + out->remove(Ext::kAVX, Ext::kPCLMULQDQ); } else if (regAnalysis.hasRegType(RegType::kX86_Ymm)) { - out->remove(CpuFeatures::X86::kAVX512_F, CpuFeatures::X86::kAVX512_VL); + out->remove(Ext::kAVX512_F, Ext::kAVX512_VL); } else { // AVX & PCLMULQDQ. - out->remove(CpuFeatures::X86::kAVX512_F, CpuFeatures::X86::kAVX512_VL, CpuFeatures::X86::kVPCLMULQDQ); + out->remove(Ext::kAVX512_F, Ext::kAVX512_VL, Ext::kVPCLMULQDQ); } } // Handle AVX vs AVX2 overlap. - if (out->has(CpuFeatures::X86::kAVX) && out->has(CpuFeatures::X86::kAVX2)) { + if (out->has(Ext::kAVX) && out->has(Ext::kAVX2)) { bool isAVX2 = true; // Special case: VBROADCASTSS and VBROADCASTSD were introduced in AVX, but only version that uses memory as a // source operand. AVX2 then added support for register source operand. @@ -1575,157 +1545,287 @@ Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand } if (isAVX2) - out->remove(CpuFeatures::X86::kAVX); + out->remove(Ext::kAVX); else - out->remove(CpuFeatures::X86::kAVX2); + out->remove(Ext::kAVX2); } - // Handle AVX|AVX2|FMA|F16C vs AVX512 overlap. - if (out->has(CpuFeatures::X86::kAVX) || out->has(CpuFeatures::X86::kAVX2) || out->has(CpuFeatures::X86::kFMA) || out->has(CpuFeatures::X86::kF16C)) { - // Only AVX512-F|BW|DQ allow to encode AVX/AVX2/FMA/F16C instructions - if (out->has(CpuFeatures::X86::kAVX512_F) || out->has(CpuFeatures::X86::kAVX512_BW) || out->has(CpuFeatures::X86::kAVX512_DQ)) { - uint32_t usesAvx512 = InstInternal_usesAvx512(options, inst.extraReg(), regAnalysis); - uint32_t mustUseEvex = 0; - - switch (instId) { - // Special case: VPSLLDQ and VPSRLDQ instructions only allow `reg, reg. imm` combination in AVX|AVX2 mode, - // then AVX-512 introduced `reg, reg/mem, imm` combination that uses EVEX prefix. This means that if the - // second operand is memory then this is AVX-512_BW instruction and not AVX/AVX2 instruction. - case Inst::kIdVpslldq: - case Inst::kIdVpsrldq: - mustUseEvex = opCount >= 2 && operands[1].isMem(); - break; + // Handle AVX vs AVX512 overlap. + // + // In general, non-AVX encoding is preferred, however, AVX encoded instructions that were initially provided + // as AVX-512 instructions must naturally prefer AVX-512 encoding, as that was the first one provided. + if (out->hasAny(Ext::kAVX, + Ext::kAVX_IFMA, + Ext::kAVX_NE_CONVERT, + Ext::kAVX_VNNI, + Ext::kAVX2, + Ext::kF16C, + Ext::kFMA) + && + out->hasAny(Ext::kAVX512_BF16, + Ext::kAVX512_BW, + Ext::kAVX512_DQ, + Ext::kAVX512_F, + Ext::kAVX512_IFMA, + Ext::kAVX512_VNNI)) { + + uint32_t useEvex = InstInternal_usesAvx512(options, inst.extraReg(), regAnalysis) | regAnalysis.highVecUsed; + switch (instId) { + // Special case: VPBROADCAST[B|D|Q|W] only supports r32/r64 with EVEX prefix. + case Inst::kIdVpbroadcastb: + case Inst::kIdVpbroadcastd: + case Inst::kIdVpbroadcastq: + case Inst::kIdVpbroadcastw: + useEvex |= uint32_t(opCount >= 2 && x86::Reg::isGp(operands[1])); + break; - // Special case: VPBROADCAST[B|D|Q|W] only supports r32/r64 with EVEX prefix. - case Inst::kIdVpbroadcastb: - case Inst::kIdVpbroadcastd: - case Inst::kIdVpbroadcastq: - case Inst::kIdVpbroadcastw: - mustUseEvex = opCount >= 2 && x86::Reg::isGp(operands[1]); - break; + case Inst::kIdVcvtpd2dq: + case Inst::kIdVcvtpd2ps: + case Inst::kIdVcvttpd2dq: + useEvex |= uint32_t(opCount >= 2 && Reg::isYmm(operands[0])); + break; - // Special case: VPERMPD - AVX2 vs AVX512-F case. - case Inst::kIdVpermpd: - mustUseEvex = opCount >= 3 && !operands[2].isImm(); - break; + case Inst::kIdVgatherdpd: + case Inst::kIdVgatherdps: + case Inst::kIdVgatherqpd: + case Inst::kIdVgatherqps: + case Inst::kIdVpgatherdd: + case Inst::kIdVpgatherdq: + case Inst::kIdVpgatherqd: + case Inst::kIdVpgatherqq: + useEvex |= uint32_t(opCount == 2); + break; - // Special case: VPERMQ - AVX2 vs AVX512-F case. - case Inst::kIdVpermq: - mustUseEvex = opCount >= 3 && (operands[1].isMem() || !operands[2].isImm()); - break; - } + // Special case: These instructions only allow `reg, reg. imm` combination in AVX|AVX2 mode, then + // AVX-512 introduced `reg, reg/mem, imm` combination that uses EVEX prefix. This means that if + // the second operand is memory then this is AVX-512_BW instruction and not AVX/AVX2 instruction. + case Inst::kIdVpslldq: + case Inst::kIdVpslld: + case Inst::kIdVpsllq: + case Inst::kIdVpsllw: + case Inst::kIdVpsrad: + case Inst::kIdVpsraq: + case Inst::kIdVpsraw: + case Inst::kIdVpsrld: + case Inst::kIdVpsrldq: + case Inst::kIdVpsrlq: + case Inst::kIdVpsrlw: + useEvex |= uint32_t(opCount >= 2 && operands[1].isMem()); + break; - if (!(usesAvx512 | mustUseEvex | regAnalysis.highVecUsed)) - out->remove(CpuFeatures::X86::kAVX512_F, CpuFeatures::X86::kAVX512_BW, CpuFeatures::X86::kAVX512_DQ, CpuFeatures::X86::kAVX512_VL); - else - out->remove(CpuFeatures::X86::kAVX, CpuFeatures::X86::kAVX2, CpuFeatures::X86::kFMA, CpuFeatures::X86::kF16C); - } - } + // Special case: VPERMPD - AVX2 vs AVX512-F case. + case Inst::kIdVpermpd: + useEvex |= uint32_t(opCount >= 3 && !operands[2].isImm()); + break; - // Handle AVX_VNNI vs AVX512_VNNI overlap. - if (out->has(CpuFeatures::X86::kAVX512_VNNI)) { - // By default the AVX512_VNNI instruction should be used, because it was introduced first. However, VEX|VEX3 - // prefix can be used to force AVX_VNNI instead. - uint32_t usesAvx512 = InstInternal_usesAvx512(options, inst.extraReg(), regAnalysis); + // Special case: VPERMQ - AVX2 vs AVX512-F case. + case Inst::kIdVpermq: + useEvex |= uint32_t(opCount >= 3 && (operands[1].isMem() || !operands[2].isImm())); + break; + } - if (!usesAvx512 && Support::test(options, InstOptions::kX86_Vex | InstOptions::kX86_Vex3)) - out->remove(CpuFeatures::X86::kAVX512_VNNI, CpuFeatures::X86::kAVX512_VL); - else - out->remove(CpuFeatures::X86::kAVX_VNNI); + if (instInfo.commonInfo().preferEvex() && !Support::test(options, InstOptions::kX86_Vex | InstOptions::kX86_Vex3)) + useEvex = 1; + + if (useEvex) { + out->remove(Ext::kAVX, + Ext::kAVX_IFMA, + Ext::kAVX_NE_CONVERT, + Ext::kAVX_VNNI, + Ext::kAVX2, + Ext::kF16C, + Ext::kFMA); + } + else { + out->remove(Ext::kAVX512_BF16, + Ext::kAVX512_BW, + Ext::kAVX512_DQ, + Ext::kAVX512_F, + Ext::kAVX512_IFMA, + Ext::kAVX512_VL, + Ext::kAVX512_VNNI); + } } // Clear AVX512_VL if ZMM register is used. if (regAnalysis.hasRegType(RegType::kX86_Zmm)) - out->remove(CpuFeatures::X86::kAVX512_VL); + out->remove(Ext::kAVX512_VL); } return kErrorOk; } #endif // !ASMJIT_NO_INTROSPECTION +} // {InstInternal} + // x86::InstInternal - Tests // ========================= #if defined(ASMJIT_TEST) +#ifndef ASMJIT_NO_TEXT UNIT(x86_inst_api_text) { // All known instructions should be matched. INFO("Matching all X86 instructions"); for (uint32_t a = 1; a < Inst::_kIdCount; a++) { StringTmp<128> aName; - EXPECT(InstInternal::instIdToString(Arch::kX86, a, aName) == kErrorOk, - "Failed to get the name of instruction #%u", a); + EXPECT_EQ(InstInternal::instIdToString(a, aName), kErrorOk) + .message("Failed to get the name of instruction #%u", a); - uint32_t b = InstInternal::stringToInstId(Arch::kX86, aName.data(), aName.size()); + uint32_t b = InstInternal::stringToInstId(aName.data(), aName.size()); StringTmp<128> bName; - InstInternal::instIdToString(Arch::kX86, b, bName); + InstInternal::instIdToString(b, bName); + EXPECT_EQ(a, b) + .message("Instructions do not match \"%s\" (#%u) != \"%s\" (#%u)", aName.data(), a, bName.data(), b); + } +} +#endif // !ASMJIT_NO_TEXT + +#ifndef ASMJIT_NO_INTROSPECTION +template<typename... Args> +static Error queryFeaturesInline(CpuFeatures* out, Arch arch, BaseInst inst, Args&&... args) { + Operand_ opArray[] = { std::forward<Args>(args)... }; + return InstInternal::queryFeatures(arch, inst, opArray, sizeof...(args), out); +} + +UNIT(x86_inst_api_cpu_features) { + INFO("Verifying whether SSE2+ features are reported correctly for legacy instructions"); + { + CpuFeatures f; + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdPaddd), xmm1, xmm2); + EXPECT_TRUE(f.x86().hasSSE2()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdAddsubpd), xmm1, xmm2); + EXPECT_TRUE(f.x86().hasSSE3()); - EXPECT(a == b, - "Instructions do not match \"%s\" (#%u) != \"%s\" (#%u)", aName.data(), a, bName.data(), b); + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdPshufb), xmm1, xmm2); + EXPECT_TRUE(f.x86().hasSSSE3()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdBlendpd), xmm1, xmm2, Imm(1)); + EXPECT_TRUE(f.x86().hasSSE4_1()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdCrc32), eax, al); + EXPECT_TRUE(f.x86().hasSSE4_2()); + } + + INFO("Verifying whether AVX+ features are reported correctly for AVX instructions"); + { + CpuFeatures f; + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpaddd), xmm1, xmm2, xmm3); + EXPECT_TRUE(f.x86().hasAVX()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpaddd), ymm1, ymm2, ymm3); + EXPECT_TRUE(f.x86().hasAVX2()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVaddsubpd), xmm1, xmm2, xmm3); + EXPECT_TRUE(f.x86().hasAVX()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVaddsubpd), ymm1, ymm2, ymm3); + EXPECT_TRUE(f.x86().hasAVX()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpshufb), xmm1, xmm2, xmm3); + EXPECT_TRUE(f.x86().hasAVX()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpshufb), ymm1, ymm2, ymm3); + EXPECT_TRUE(f.x86().hasAVX2()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVblendpd), xmm1, xmm2, xmm3, Imm(1)); + EXPECT_TRUE(f.x86().hasAVX()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVblendpd), ymm1, ymm2, ymm3, Imm(1)); + EXPECT_TRUE(f.x86().hasAVX()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpunpcklbw), xmm1, xmm2, xmm3); + EXPECT_TRUE(f.x86().hasAVX()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpunpcklbw), ymm1, ymm2, ymm3); + EXPECT_TRUE(f.x86().hasAVX2()); + } + + INFO("Verifying whether AVX2 / AVX512 features are reported correctly for vpgatherxx instructions"); + { + CpuFeatures f; + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpgatherdd), xmm1, ptr(rax, xmm2), xmm3); + EXPECT_TRUE(f.x86().hasAVX2()); + EXPECT_FALSE(f.x86().hasAVX512_F()); + + // NOTE: This instruction is unencodable, but sometimes this signature is used to check the support (without the {k}). + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpgatherdd), xmm1, ptr(rax, xmm2)); + EXPECT_FALSE(f.x86().hasAVX2()); + EXPECT_TRUE(f.x86().hasAVX512_F()); + + queryFeaturesInline(&f, Arch::kX64, BaseInst(Inst::kIdVpgatherdd, InstOptions::kNone, k1), xmm1, ptr(rax, xmm2)); + EXPECT_FALSE(f.x86().hasAVX2()); + EXPECT_TRUE(f.x86().hasAVX512_F()); } } +#endif // !ASMJIT_NO_INTROSPECTION +#ifndef ASMJIT_NO_INTROSPECTION template<typename... Args> -static Error queryRWInfoSimple(InstRWInfo* out, Arch arch, InstId instId, InstOptions options, Args&&... args) { - BaseInst inst(instId); - inst.addOptions(options); +static Error queryRWInfoInline(InstRWInfo* out, Arch arch, BaseInst inst, Args&&... args) { Operand_ opArray[] = { std::forward<Args>(args)... }; return InstInternal::queryRWInfo(arch, inst, opArray, sizeof...(args), out); } -UNIT(x86_inst_api_rm_feature) { +UNIT(x86_inst_api_rm_features) { INFO("Verifying whether RM/feature is reported correctly for PEXTRW instruction"); { InstRWInfo rwi; - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdPextrw, InstOptions::kNone, eax, mm1, imm(1)); - EXPECT(rwi.rmFeature() == 0); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdPextrw), eax, mm1, imm(1)); + EXPECT_EQ(rwi.rmFeature(), 0u); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdPextrw, InstOptions::kNone, eax, xmm1, imm(1)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kSSE4_1); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdPextrw), eax, xmm1, imm(1)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kSSE4_1); } INFO("Verifying whether RM/feature is reported correctly for AVX512 shift instructions"); { InstRWInfo rwi; - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpslld, InstOptions::kNone, xmm1, xmm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_F); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpslld), xmm1, xmm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_F); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsllq, InstOptions::kNone, ymm1, ymm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_F); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsllq), ymm1, ymm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_F); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsrad, InstOptions::kNone, xmm1, xmm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_F); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsrad), xmm1, xmm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_F); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsrld, InstOptions::kNone, ymm1, ymm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_F); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsrld), ymm1, ymm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_F); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsrlq, InstOptions::kNone, xmm1, xmm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_F); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsrlq), xmm1, xmm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_F); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpslldq, InstOptions::kNone, xmm1, xmm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_BW); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpslldq), xmm1, xmm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_BW); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsllw, InstOptions::kNone, ymm1, ymm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_BW); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsllw), ymm1, ymm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_BW); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsraw, InstOptions::kNone, xmm1, xmm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_BW); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsraw), xmm1, xmm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_BW); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsrldq, InstOptions::kNone, ymm1, ymm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_BW); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsrldq), ymm1, ymm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_BW); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsrlw, InstOptions::kNone, xmm1, xmm2, imm(8)); - EXPECT(rwi.rmFeature() == CpuFeatures::X86::kAVX512_BW); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsrlw), xmm1, xmm2, imm(8)); + EXPECT_EQ(rwi.rmFeature(), CpuFeatures::X86::kAVX512_BW); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpslld, InstOptions::kNone, xmm1, xmm2, xmm3); - EXPECT(rwi.rmFeature() == 0); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpslld), xmm1, xmm2, xmm3); + EXPECT_EQ(rwi.rmFeature(), 0u); - queryRWInfoSimple(&rwi, Arch::kX64, Inst::kIdVpsllw, InstOptions::kNone, xmm1, xmm2, xmm3); - EXPECT(rwi.rmFeature() == 0); + queryRWInfoInline(&rwi, Arch::kX64, BaseInst(Inst::kIdVpsllw), xmm1, xmm2, xmm3); + EXPECT_EQ(rwi.rmFeature(), 0u); } } -#endif +#endif // !ASMJIT_NO_INTROSPECTION + +#endif // ASMJIT_TEST ASMJIT_END_SUB_NAMESPACE diff --git a/3rdparty/asmjit/src/asmjit/x86/x86instapi_p.h b/3rdparty/asmjit/src/asmjit/x86/x86instapi_p.h index 56f7fb928f2..e0866ea702e 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86instapi_p.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86instapi_p.h @@ -18,12 +18,13 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) namespace InstInternal { #ifndef ASMJIT_NO_TEXT -Error ASMJIT_CDECL instIdToString(Arch arch, InstId instId, String& output) noexcept; -InstId ASMJIT_CDECL stringToInstId(Arch arch, const char* s, size_t len) noexcept; +Error ASMJIT_CDECL instIdToString(InstId instId, String& output) noexcept; +InstId ASMJIT_CDECL stringToInstId(const char* s, size_t len) noexcept; #endif // !ASMJIT_NO_TEXT #ifndef ASMJIT_NO_VALIDATION -Error ASMJIT_CDECL validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; +Error ASMJIT_CDECL validateX86(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; +Error ASMJIT_CDECL validateX64(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; #endif // !ASMJIT_NO_VALIDATION #ifndef ASMJIT_NO_INTROSPECTION diff --git a/3rdparty/asmjit/src/asmjit/x86/x86instdb.cpp b/3rdparty/asmjit/src/asmjit/x86/x86instdb.cpp index ee22526c348..c31ce91019a 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86instdb.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86instdb.cpp @@ -3,24 +3,6 @@ // See asmjit.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib -// ---------------------------------------------------------------------------- -// IMPORTANT: AsmJit now uses an external instruction database to populate -// static tables within this file. Perform the following steps to regenerate -// all tables enclosed by ${...}: -// -// 1. Install node.js environment <https://nodejs.org> -// 2. Go to asmjit/tools directory -// 3. Get the latest asmdb from <https://github.com/asmjit/asmdb> and -// copy/link the `asmdb` directory to `asmjit/tools/asmdb`. -// 4. Execute `node tablegen-x86.js` -// -// Instruction encoding and opcodes were added to the `x86inst.cpp` database -// manually in the past and they are not updated by the script as it became -// tricky. However, everything else is updated including instruction operands -// and tables required to validate them, instruction read/write information -// (including registers and flags), and all indexes to all tables. -// ---------------------------------------------------------------------------- - #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) @@ -47,17 +29,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) #define E(PREFIX, OPCODE, ModO, LL, W, EvexW, N, TT) (O_ENCODE(Opcode::k##PREFIX, 0x##OPCODE, Opcode::kModO_##ModO, Opcode::kLL_##LL, Opcode::kW_##W, Opcode::kEvex_W_##EvexW, Opcode::kCDSHL_##N, Opcode::kCDTT_##TT) | Opcode::kMM_ForceEvex) #define O_FPU(PREFIX, OPCODE, ModO) (Opcode::kFPU_##PREFIX | (0x##OPCODE & 0xFFu) | ((0x##OPCODE >> 8) << Opcode::kFPU_2B_Shift) | Opcode::kModO_##ModO) -// Don't store `_nameDataIndex` if instruction names are disabled. Since some -// APIs can use `_nameDataIndex` it's much safer if it's zero if it's not defined. -#ifndef ASMJIT_NO_TEXT - #define NAME_DATA_INDEX(Index) Index -#else - #define NAME_DATA_INDEX(Index) 0 -#endif - // Defines an X86 instruction. -#define INST(id, encoding, opcode0, opcode1, mainOpcodeIndex, altOpcodeIndex, nameDataIndex, commomInfoIndex, additionalInfoIndex) { \ - uint32_t(NAME_DATA_INDEX(nameDataIndex)), \ +#define INST(id, encoding, opcode0, opcode1, mainOpcodeIndex, altOpcodeIndex, commomInfoIndex, additionalInfoIndex) { \ + uint32_t(0), \ uint32_t(commomInfoIndex), \ uint32_t(additionalInfoIndex), \ uint8_t(InstDB::kEncoding##encoding), \ @@ -67,1674 +41,1733 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) } const InstDB::InstInfo InstDB::_instInfoTable[] = { - /*--------------------+--------------------+------------------+--------+------------------+--------+----+----+------+----+----+ - | Instruction | Instruction | Main Opcode | EVEX |Alternative Opcode| EVEX |Op0X|Op1X|Name-X|IdxA|IdxB| - | Id & Name | Encoding | (pp+mmm|op/o|L|w|W|N|TT.)|--(pp+mmm|op/o|L|w|W|N|TT.)| (auto-generated) | - +---------------------+--------------------+---------+----+-+-+-+-+----+---------+----+-+-+-+-+----+----+----+------+----+---*/ + /*--------------------+--------------------+------------------+--------+------------------+--------+----+----+----+----+ + | Instruction | Instruction | Main Opcode | EVEX |Alternative Opcode| EVEX |Op0X|Op1X|IdxA|IdxB| + | Id & Name | Encoding | (pp+mmm|op/o|L|w|W|N|TT.)|--(pp+mmm|op/o|L|w|W|N|TT.)| (auto-generated) | + +---------------------+--------------------+---------+----+-+-+-+-+----+---------+----+-+-+-+-+----+----+----+----+---*/ // ${InstInfo:Begin} - INST(None , None , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), // #0 - INST(Aaa , X86Op_xAX , O(000000,37,_,_,_,_,_,_ ), 0 , 0 , 0 , 1 , 1 , 1 ), // #1 - INST(Aad , X86I_xAX , O(000000,D5,_,_,_,_,_,_ ), 0 , 0 , 0 , 5 , 2 , 1 ), // #2 - INST(Aam , X86I_xAX , O(000000,D4,_,_,_,_,_,_ ), 0 , 0 , 0 , 9 , 2 , 1 ), // #3 - INST(Aas , X86Op_xAX , O(000000,3F,_,_,_,_,_,_ ), 0 , 0 , 0 , 13 , 1 , 1 ), // #4 - INST(Adc , X86Arith , O(000000,10,2,_,x,_,_,_ ), 0 , 1 , 0 , 17 , 3 , 2 ), // #5 - INST(Adcx , X86Rm , O(660F38,F6,_,_,x,_,_,_ ), 0 , 2 , 0 , 21 , 4 , 3 ), // #6 - INST(Add , X86Arith , O(000000,00,0,_,x,_,_,_ ), 0 , 0 , 0 , 3146 , 3 , 1 ), // #7 - INST(Addpd , ExtRm , O(660F00,58,_,_,_,_,_,_ ), 0 , 3 , 0 , 5788 , 5 , 4 ), // #8 - INST(Addps , ExtRm , O(000F00,58,_,_,_,_,_,_ ), 0 , 4 , 0 , 5800 , 5 , 5 ), // #9 - INST(Addsd , ExtRm , O(F20F00,58,_,_,_,_,_,_ ), 0 , 5 , 0 , 6118 , 6 , 4 ), // #10 - INST(Addss , ExtRm , O(F30F00,58,_,_,_,_,_,_ ), 0 , 6 , 0 , 3283 , 7 , 5 ), // #11 - INST(Addsubpd , ExtRm , O(660F00,D0,_,_,_,_,_,_ ), 0 , 3 , 0 , 5410 , 5 , 6 ), // #12 - INST(Addsubps , ExtRm , O(F20F00,D0,_,_,_,_,_,_ ), 0 , 5 , 0 , 5422 , 5 , 6 ), // #13 - INST(Adox , X86Rm , O(F30F38,F6,_,_,x,_,_,_ ), 0 , 7 , 0 , 26 , 4 , 7 ), // #14 - INST(Aesdec , ExtRm , O(660F38,DE,_,_,_,_,_,_ ), 0 , 2 , 0 , 3352 , 5 , 8 ), // #15 - INST(Aesdeclast , ExtRm , O(660F38,DF,_,_,_,_,_,_ ), 0 , 2 , 0 , 3360 , 5 , 8 ), // #16 - INST(Aesenc , ExtRm , O(660F38,DC,_,_,_,_,_,_ ), 0 , 2 , 0 , 3372 , 5 , 8 ), // #17 - INST(Aesenclast , ExtRm , O(660F38,DD,_,_,_,_,_,_ ), 0 , 2 , 0 , 3380 , 5 , 8 ), // #18 - INST(Aesimc , ExtRm , O(660F38,DB,_,_,_,_,_,_ ), 0 , 2 , 0 , 3392 , 5 , 8 ), // #19 - INST(Aeskeygenassist , ExtRmi , O(660F3A,DF,_,_,_,_,_,_ ), 0 , 8 , 0 , 3400 , 8 , 8 ), // #20 - INST(And , X86Arith , O(000000,20,4,_,x,_,_,_ ), 0 , 9 , 0 , 2525 , 9 , 1 ), // #21 - INST(Andn , VexRvm_Wx , V(000F38,F2,_,0,x,_,_,_ ), 0 , 10 , 0 , 7789 , 10 , 9 ), // #22 - INST(Andnpd , ExtRm , O(660F00,55,_,_,_,_,_,_ ), 0 , 3 , 0 , 3433 , 5 , 4 ), // #23 - INST(Andnps , ExtRm , O(000F00,55,_,_,_,_,_,_ ), 0 , 4 , 0 , 3441 , 5 , 5 ), // #24 - INST(Andpd , ExtRm , O(660F00,54,_,_,_,_,_,_ ), 0 , 3 , 0 , 4745 , 11 , 4 ), // #25 - INST(Andps , ExtRm , O(000F00,54,_,_,_,_,_,_ ), 0 , 4 , 0 , 4755 , 11 , 5 ), // #26 - INST(Arpl , X86Mr_NoSize , O(000000,63,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 12 , 10 ), // #27 - INST(Bextr , VexRmv_Wx , V(000F38,F7,_,0,x,_,_,_ ), 0 , 10 , 0 , 36 , 13 , 9 ), // #28 - INST(Blcfill , VexVm_Wx , V(XOP_M9,01,1,0,x,_,_,_ ), 0 , 11 , 0 , 42 , 14 , 11 ), // #29 - INST(Blci , VexVm_Wx , V(XOP_M9,02,6,0,x,_,_,_ ), 0 , 12 , 0 , 50 , 14 , 11 ), // #30 - INST(Blcic , VexVm_Wx , V(XOP_M9,01,5,0,x,_,_,_ ), 0 , 13 , 0 , 55 , 14 , 11 ), // #31 - INST(Blcmsk , VexVm_Wx , V(XOP_M9,02,1,0,x,_,_,_ ), 0 , 11 , 0 , 61 , 14 , 11 ), // #32 - INST(Blcs , VexVm_Wx , V(XOP_M9,01,3,0,x,_,_,_ ), 0 , 14 , 0 , 68 , 14 , 11 ), // #33 - INST(Blendpd , ExtRmi , O(660F3A,0D,_,_,_,_,_,_ ), 0 , 8 , 0 , 3483 , 8 , 12 ), // #34 - INST(Blendps , ExtRmi , O(660F3A,0C,_,_,_,_,_,_ ), 0 , 8 , 0 , 3492 , 8 , 12 ), // #35 - INST(Blendvpd , ExtRm_XMM0 , O(660F38,15,_,_,_,_,_,_ ), 0 , 2 , 0 , 3501 , 15 , 12 ), // #36 - INST(Blendvps , ExtRm_XMM0 , O(660F38,14,_,_,_,_,_,_ ), 0 , 2 , 0 , 3511 , 15 , 12 ), // #37 - INST(Blsfill , VexVm_Wx , V(XOP_M9,01,2,0,x,_,_,_ ), 0 , 15 , 0 , 73 , 14 , 11 ), // #38 - INST(Blsi , VexVm_Wx , V(000F38,F3,3,0,x,_,_,_ ), 0 , 16 , 0 , 81 , 14 , 9 ), // #39 - INST(Blsic , VexVm_Wx , V(XOP_M9,01,6,0,x,_,_,_ ), 0 , 12 , 0 , 86 , 14 , 11 ), // #40 - INST(Blsmsk , VexVm_Wx , V(000F38,F3,2,0,x,_,_,_ ), 0 , 17 , 0 , 92 , 14 , 9 ), // #41 - INST(Blsr , VexVm_Wx , V(000F38,F3,1,0,x,_,_,_ ), 0 , 18 , 0 , 99 , 14 , 9 ), // #42 - INST(Bndcl , X86Rm , O(F30F00,1A,_,_,_,_,_,_ ), 0 , 6 , 0 , 104 , 16 , 13 ), // #43 - INST(Bndcn , X86Rm , O(F20F00,1B,_,_,_,_,_,_ ), 0 , 5 , 0 , 110 , 16 , 13 ), // #44 - INST(Bndcu , X86Rm , O(F20F00,1A,_,_,_,_,_,_ ), 0 , 5 , 0 , 116 , 16 , 13 ), // #45 - INST(Bndldx , X86Rm , O(000F00,1A,_,_,_,_,_,_ ), 0 , 4 , 0 , 122 , 17 , 13 ), // #46 - INST(Bndmk , X86Rm , O(F30F00,1B,_,_,_,_,_,_ ), 0 , 6 , 0 , 129 , 18 , 13 ), // #47 - INST(Bndmov , X86Bndmov , O(660F00,1A,_,_,_,_,_,_ ), O(660F00,1B,_,_,_,_,_,_ ), 3 , 1 , 135 , 19 , 13 ), // #48 - INST(Bndstx , X86Mr , O(000F00,1B,_,_,_,_,_,_ ), 0 , 4 , 0 , 142 , 20 , 13 ), // #49 - INST(Bound , X86Rm , O(000000,62,_,_,_,_,_,_ ), 0 , 0 , 0 , 149 , 21 , 0 ), // #50 - INST(Bsf , X86Rm , O(000F00,BC,_,_,x,_,_,_ ), 0 , 4 , 0 , 155 , 22 , 1 ), // #51 - INST(Bsr , X86Rm , O(000F00,BD,_,_,x,_,_,_ ), 0 , 4 , 0 , 159 , 22 , 1 ), // #52 - INST(Bswap , X86Bswap , O(000F00,C8,_,_,x,_,_,_ ), 0 , 4 , 0 , 163 , 23 , 0 ), // #53 - INST(Bt , X86Bt , O(000F00,A3,_,_,x,_,_,_ ), O(000F00,BA,4,_,x,_,_,_ ), 4 , 2 , 169 , 24 , 14 ), // #54 - INST(Btc , X86Bt , O(000F00,BB,_,_,x,_,_,_ ), O(000F00,BA,7,_,x,_,_,_ ), 4 , 3 , 172 , 25 , 14 ), // #55 - INST(Btr , X86Bt , O(000F00,B3,_,_,x,_,_,_ ), O(000F00,BA,6,_,x,_,_,_ ), 4 , 4 , 176 , 25 , 14 ), // #56 - INST(Bts , X86Bt , O(000F00,AB,_,_,x,_,_,_ ), O(000F00,BA,5,_,x,_,_,_ ), 4 , 5 , 180 , 25 , 14 ), // #57 - INST(Bzhi , VexRmv_Wx , V(000F38,F5,_,0,x,_,_,_ ), 0 , 10 , 0 , 184 , 13 , 15 ), // #58 - INST(Call , X86Call , O(000000,FF,2,_,_,_,_,_ ), 0 , 1 , 0 , 3038 , 26 , 1 ), // #59 - INST(Cbw , X86Op_xAX , O(660000,98,_,_,_,_,_,_ ), 0 , 19 , 0 , 189 , 27 , 0 ), // #60 - INST(Cdq , X86Op_xDX_xAX , O(000000,99,_,_,_,_,_,_ ), 0 , 0 , 0 , 193 , 28 , 0 ), // #61 - INST(Cdqe , X86Op_xAX , O(000000,98,_,_,1,_,_,_ ), 0 , 20 , 0 , 197 , 29 , 0 ), // #62 - INST(Clac , X86Op , O(000F01,CA,_,_,_,_,_,_ ), 0 , 21 , 0 , 202 , 30 , 16 ), // #63 - INST(Clc , X86Op , O(000000,F8,_,_,_,_,_,_ ), 0 , 0 , 0 , 207 , 30 , 17 ), // #64 - INST(Cld , X86Op , O(000000,FC,_,_,_,_,_,_ ), 0 , 0 , 0 , 211 , 30 , 18 ), // #65 - INST(Cldemote , X86M_Only , O(000F00,1C,0,_,_,_,_,_ ), 0 , 4 , 0 , 215 , 31 , 19 ), // #66 - INST(Clflush , X86M_Only , O(000F00,AE,7,_,_,_,_,_ ), 0 , 22 , 0 , 224 , 31 , 20 ), // #67 - INST(Clflushopt , X86M_Only , O(660F00,AE,7,_,_,_,_,_ ), 0 , 23 , 0 , 232 , 31 , 21 ), // #68 - INST(Clgi , X86Op , O(000F01,DD,_,_,_,_,_,_ ), 0 , 21 , 0 , 243 , 30 , 22 ), // #69 - INST(Cli , X86Op , O(000000,FA,_,_,_,_,_,_ ), 0 , 0 , 0 , 248 , 30 , 23 ), // #70 - INST(Clrssbsy , X86M_Only , O(F30F00,AE,6,_,_,_,_,_ ), 0 , 24 , 0 , 252 , 32 , 24 ), // #71 - INST(Clts , X86Op , O(000F00,06,_,_,_,_,_,_ ), 0 , 4 , 0 , 261 , 30 , 0 ), // #72 - INST(Clui , X86Op , O(F30F01,EE,_,_,_,_,_,_ ), 0 , 25 , 0 , 266 , 33 , 25 ), // #73 - INST(Clwb , X86M_Only , O(660F00,AE,6,_,_,_,_,_ ), 0 , 26 , 0 , 271 , 31 , 26 ), // #74 - INST(Clzero , X86Op_MemZAX , O(000F01,FC,_,_,_,_,_,_ ), 0 , 21 , 0 , 276 , 34 , 27 ), // #75 - INST(Cmc , X86Op , O(000000,F5,_,_,_,_,_,_ ), 0 , 0 , 0 , 283 , 30 , 28 ), // #76 - INST(Cmova , X86Rm , O(000F00,47,_,_,x,_,_,_ ), 0 , 4 , 0 , 287 , 22 , 29 ), // #77 - INST(Cmovae , X86Rm , O(000F00,43,_,_,x,_,_,_ ), 0 , 4 , 0 , 293 , 22 , 30 ), // #78 - INST(Cmovb , X86Rm , O(000F00,42,_,_,x,_,_,_ ), 0 , 4 , 0 , 648 , 22 , 30 ), // #79 - INST(Cmovbe , X86Rm , O(000F00,46,_,_,x,_,_,_ ), 0 , 4 , 0 , 655 , 22 , 29 ), // #80 - INST(Cmovc , X86Rm , O(000F00,42,_,_,x,_,_,_ ), 0 , 4 , 0 , 300 , 22 , 30 ), // #81 - INST(Cmove , X86Rm , O(000F00,44,_,_,x,_,_,_ ), 0 , 4 , 0 , 663 , 22 , 31 ), // #82 - INST(Cmovg , X86Rm , O(000F00,4F,_,_,x,_,_,_ ), 0 , 4 , 0 , 306 , 22 , 32 ), // #83 - INST(Cmovge , X86Rm , O(000F00,4D,_,_,x,_,_,_ ), 0 , 4 , 0 , 312 , 22 , 33 ), // #84 - INST(Cmovl , X86Rm , O(000F00,4C,_,_,x,_,_,_ ), 0 , 4 , 0 , 319 , 22 , 33 ), // #85 - INST(Cmovle , X86Rm , O(000F00,4E,_,_,x,_,_,_ ), 0 , 4 , 0 , 325 , 22 , 32 ), // #86 - INST(Cmovna , X86Rm , O(000F00,46,_,_,x,_,_,_ ), 0 , 4 , 0 , 332 , 22 , 29 ), // #87 - INST(Cmovnae , X86Rm , O(000F00,42,_,_,x,_,_,_ ), 0 , 4 , 0 , 339 , 22 , 30 ), // #88 - INST(Cmovnb , X86Rm , O(000F00,43,_,_,x,_,_,_ ), 0 , 4 , 0 , 670 , 22 , 30 ), // #89 - INST(Cmovnbe , X86Rm , O(000F00,47,_,_,x,_,_,_ ), 0 , 4 , 0 , 678 , 22 , 29 ), // #90 - INST(Cmovnc , X86Rm , O(000F00,43,_,_,x,_,_,_ ), 0 , 4 , 0 , 347 , 22 , 30 ), // #91 - INST(Cmovne , X86Rm , O(000F00,45,_,_,x,_,_,_ ), 0 , 4 , 0 , 687 , 22 , 31 ), // #92 - INST(Cmovng , X86Rm , O(000F00,4E,_,_,x,_,_,_ ), 0 , 4 , 0 , 354 , 22 , 32 ), // #93 - INST(Cmovnge , X86Rm , O(000F00,4C,_,_,x,_,_,_ ), 0 , 4 , 0 , 361 , 22 , 33 ), // #94 - INST(Cmovnl , X86Rm , O(000F00,4D,_,_,x,_,_,_ ), 0 , 4 , 0 , 369 , 22 , 33 ), // #95 - INST(Cmovnle , X86Rm , O(000F00,4F,_,_,x,_,_,_ ), 0 , 4 , 0 , 376 , 22 , 32 ), // #96 - INST(Cmovno , X86Rm , O(000F00,41,_,_,x,_,_,_ ), 0 , 4 , 0 , 384 , 22 , 34 ), // #97 - INST(Cmovnp , X86Rm , O(000F00,4B,_,_,x,_,_,_ ), 0 , 4 , 0 , 391 , 22 , 35 ), // #98 - INST(Cmovns , X86Rm , O(000F00,49,_,_,x,_,_,_ ), 0 , 4 , 0 , 398 , 22 , 36 ), // #99 - INST(Cmovnz , X86Rm , O(000F00,45,_,_,x,_,_,_ ), 0 , 4 , 0 , 405 , 22 , 31 ), // #100 - INST(Cmovo , X86Rm , O(000F00,40,_,_,x,_,_,_ ), 0 , 4 , 0 , 412 , 22 , 34 ), // #101 - INST(Cmovp , X86Rm , O(000F00,4A,_,_,x,_,_,_ ), 0 , 4 , 0 , 418 , 22 , 35 ), // #102 - INST(Cmovpe , X86Rm , O(000F00,4A,_,_,x,_,_,_ ), 0 , 4 , 0 , 424 , 22 , 35 ), // #103 - INST(Cmovpo , X86Rm , O(000F00,4B,_,_,x,_,_,_ ), 0 , 4 , 0 , 431 , 22 , 35 ), // #104 - INST(Cmovs , X86Rm , O(000F00,48,_,_,x,_,_,_ ), 0 , 4 , 0 , 438 , 22 , 36 ), // #105 - INST(Cmovz , X86Rm , O(000F00,44,_,_,x,_,_,_ ), 0 , 4 , 0 , 444 , 22 , 31 ), // #106 - INST(Cmp , X86Arith , O(000000,38,7,_,x,_,_,_ ), 0 , 27 , 0 , 450 , 35 , 1 ), // #107 - INST(Cmppd , ExtRmi , O(660F00,C2,_,_,_,_,_,_ ), 0 , 3 , 0 , 3737 , 8 , 4 ), // #108 - INST(Cmpps , ExtRmi , O(000F00,C2,_,_,_,_,_,_ ), 0 , 4 , 0 , 3751 , 8 , 5 ), // #109 - INST(Cmps , X86StrMm , O(000000,A6,_,_,_,_,_,_ ), 0 , 0 , 0 , 454 , 36 , 37 ), // #110 - INST(Cmpsd , ExtRmi , O(F20F00,C2,_,_,_,_,_,_ ), 0 , 5 , 0 , 3758 , 37 , 4 ), // #111 - INST(Cmpss , ExtRmi , O(F30F00,C2,_,_,_,_,_,_ ), 0 , 6 , 0 , 3772 , 38 , 5 ), // #112 - INST(Cmpxchg , X86Cmpxchg , O(000F00,B0,_,_,x,_,_,_ ), 0 , 4 , 0 , 459 , 39 , 38 ), // #113 - INST(Cmpxchg16b , X86Cmpxchg8b_16b , O(000F00,C7,1,_,1,_,_,_ ), 0 , 28 , 0 , 467 , 40 , 39 ), // #114 - INST(Cmpxchg8b , X86Cmpxchg8b_16b , O(000F00,C7,1,_,_,_,_,_ ), 0 , 29 , 0 , 478 , 41 , 40 ), // #115 - INST(Comisd , ExtRm , O(660F00,2F,_,_,_,_,_,_ ), 0 , 3 , 0 , 11391, 6 , 41 ), // #116 - INST(Comiss , ExtRm , O(000F00,2F,_,_,_,_,_,_ ), 0 , 4 , 0 , 11409, 7 , 42 ), // #117 - INST(Cpuid , X86Op , O(000F00,A2,_,_,_,_,_,_ ), 0 , 4 , 0 , 488 , 42 , 43 ), // #118 - INST(Cqo , X86Op_xDX_xAX , O(000000,99,_,_,1,_,_,_ ), 0 , 20 , 0 , 494 , 43 , 0 ), // #119 - INST(Crc32 , X86Crc , O(F20F38,F0,_,_,x,_,_,_ ), 0 , 30 , 0 , 498 , 44 , 44 ), // #120 - INST(Cvtdq2pd , ExtRm , O(F30F00,E6,_,_,_,_,_,_ ), 0 , 6 , 0 , 3827 , 6 , 4 ), // #121 - INST(Cvtdq2ps , ExtRm , O(000F00,5B,_,_,_,_,_,_ ), 0 , 4 , 0 , 3847 , 5 , 4 ), // #122 - INST(Cvtpd2dq , ExtRm , O(F20F00,E6,_,_,_,_,_,_ ), 0 , 5 , 0 , 3886 , 5 , 4 ), // #123 - INST(Cvtpd2pi , ExtRm , O(660F00,2D,_,_,_,_,_,_ ), 0 , 3 , 0 , 504 , 45 , 4 ), // #124 - INST(Cvtpd2ps , ExtRm , O(660F00,5A,_,_,_,_,_,_ ), 0 , 3 , 0 , 3906 , 5 , 4 ), // #125 - INST(Cvtpi2pd , ExtRm , O(660F00,2A,_,_,_,_,_,_ ), 0 , 3 , 0 , 513 , 46 , 4 ), // #126 - INST(Cvtpi2ps , ExtRm , O(000F00,2A,_,_,_,_,_,_ ), 0 , 4 , 0 , 522 , 46 , 5 ), // #127 - INST(Cvtps2dq , ExtRm , O(660F00,5B,_,_,_,_,_,_ ), 0 , 3 , 0 , 4040 , 5 , 4 ), // #128 - INST(Cvtps2pd , ExtRm , O(000F00,5A,_,_,_,_,_,_ ), 0 , 4 , 0 , 4050 , 6 , 4 ), // #129 - INST(Cvtps2pi , ExtRm , O(000F00,2D,_,_,_,_,_,_ ), 0 , 4 , 0 , 531 , 47 , 5 ), // #130 - INST(Cvtsd2si , ExtRm_Wx_GpqOnly , O(F20F00,2D,_,_,x,_,_,_ ), 0 , 5 , 0 , 4153 , 48 , 4 ), // #131 - INST(Cvtsd2ss , ExtRm , O(F20F00,5A,_,_,_,_,_,_ ), 0 , 5 , 0 , 4163 , 6 , 4 ), // #132 - INST(Cvtsi2sd , ExtRm_Wx , O(F20F00,2A,_,_,x,_,_,_ ), 0 , 5 , 0 , 4225 , 49 , 4 ), // #133 - INST(Cvtsi2ss , ExtRm_Wx , O(F30F00,2A,_,_,x,_,_,_ ), 0 , 6 , 0 , 4245 , 49 , 5 ), // #134 - INST(Cvtss2sd , ExtRm , O(F30F00,5A,_,_,_,_,_,_ ), 0 , 6 , 0 , 4255 , 7 , 4 ), // #135 - INST(Cvtss2si , ExtRm_Wx_GpqOnly , O(F30F00,2D,_,_,x,_,_,_ ), 0 , 6 , 0 , 4275 , 50 , 5 ), // #136 - INST(Cvttpd2dq , ExtRm , O(660F00,E6,_,_,_,_,_,_ ), 0 , 3 , 0 , 4296 , 5 , 4 ), // #137 - INST(Cvttpd2pi , ExtRm , O(660F00,2C,_,_,_,_,_,_ ), 0 , 3 , 0 , 540 , 45 , 4 ), // #138 - INST(Cvttps2dq , ExtRm , O(F30F00,5B,_,_,_,_,_,_ ), 0 , 6 , 0 , 4409 , 5 , 4 ), // #139 - INST(Cvttps2pi , ExtRm , O(000F00,2C,_,_,_,_,_,_ ), 0 , 4 , 0 , 550 , 47 , 5 ), // #140 - INST(Cvttsd2si , ExtRm_Wx_GpqOnly , O(F20F00,2C,_,_,x,_,_,_ ), 0 , 5 , 0 , 4455 , 48 , 4 ), // #141 - INST(Cvttss2si , ExtRm_Wx_GpqOnly , O(F30F00,2C,_,_,x,_,_,_ ), 0 , 6 , 0 , 4501 , 50 , 5 ), // #142 - INST(Cwd , X86Op_xDX_xAX , O(660000,99,_,_,_,_,_,_ ), 0 , 19 , 0 , 560 , 51 , 0 ), // #143 - INST(Cwde , X86Op_xAX , O(000000,98,_,_,_,_,_,_ ), 0 , 0 , 0 , 564 , 52 , 0 ), // #144 - INST(Daa , X86Op , O(000000,27,_,_,_,_,_,_ ), 0 , 0 , 0 , 569 , 1 , 1 ), // #145 - INST(Das , X86Op , O(000000,2F,_,_,_,_,_,_ ), 0 , 0 , 0 , 573 , 1 , 1 ), // #146 - INST(Dec , X86IncDec , O(000000,FE,1,_,x,_,_,_ ), O(000000,48,_,_,x,_,_,_ ), 31 , 6 , 3355 , 53 , 45 ), // #147 - INST(Div , X86M_GPB_MulDiv , O(000000,F6,6,_,x,_,_,_ ), 0 , 32 , 0 , 810 , 54 , 1 ), // #148 - INST(Divpd , ExtRm , O(660F00,5E,_,_,_,_,_,_ ), 0 , 3 , 0 , 4652 , 5 , 4 ), // #149 - INST(Divps , ExtRm , O(000F00,5E,_,_,_,_,_,_ ), 0 , 4 , 0 , 4666 , 5 , 5 ), // #150 - INST(Divsd , ExtRm , O(F20F00,5E,_,_,_,_,_,_ ), 0 , 5 , 0 , 4673 , 6 , 4 ), // #151 - INST(Divss , ExtRm , O(F30F00,5E,_,_,_,_,_,_ ), 0 , 6 , 0 , 4687 , 7 , 5 ), // #152 - INST(Dppd , ExtRmi , O(660F3A,41,_,_,_,_,_,_ ), 0 , 8 , 0 , 4704 , 8 , 12 ), // #153 - INST(Dpps , ExtRmi , O(660F3A,40,_,_,_,_,_,_ ), 0 , 8 , 0 , 4710 , 8 , 12 ), // #154 - INST(Emms , X86Op , O(000F00,77,_,_,_,_,_,_ ), 0 , 4 , 0 , 778 , 55 , 46 ), // #155 - INST(Endbr32 , X86Op_Mod11RM , O(F30F00,1E,7,_,_,_,_,3 ), 0 , 33 , 0 , 577 , 30 , 47 ), // #156 - INST(Endbr64 , X86Op_Mod11RM , O(F30F00,1E,7,_,_,_,_,2 ), 0 , 34 , 0 , 585 , 30 , 47 ), // #157 - INST(Enqcmd , X86EnqcmdMovdir64b , O(F20F38,F8,_,_,_,_,_,_ ), 0 , 30 , 0 , 593 , 56 , 48 ), // #158 - INST(Enqcmds , X86EnqcmdMovdir64b , O(F30F38,F8,_,_,_,_,_,_ ), 0 , 7 , 0 , 600 , 56 , 48 ), // #159 - INST(Enter , X86Enter , O(000000,C8,_,_,_,_,_,_ ), 0 , 0 , 0 , 3046 , 57 , 0 ), // #160 - INST(Extractps , ExtExtract , O(660F3A,17,_,_,_,_,_,_ ), 0 , 8 , 0 , 4900 , 58 , 12 ), // #161 - INST(Extrq , ExtExtrq , O(660F00,79,_,_,_,_,_,_ ), O(660F00,78,0,_,_,_,_,_ ), 3 , 7 , 8625 , 59 , 49 ), // #162 - INST(F2xm1 , FpuOp , O_FPU(00,D9F0,_) , 0 , 35 , 0 , 608 , 30 , 0 ), // #163 - INST(Fabs , FpuOp , O_FPU(00,D9E1,_) , 0 , 35 , 0 , 614 , 30 , 0 ), // #164 - INST(Fadd , FpuArith , O_FPU(00,C0C0,0) , 0 , 36 , 0 , 2121 , 60 , 0 ), // #165 - INST(Faddp , FpuRDef , O_FPU(00,DEC0,_) , 0 , 37 , 0 , 619 , 61 , 0 ), // #166 - INST(Fbld , X86M_Only , O_FPU(00,00DF,4) , 0 , 38 , 0 , 625 , 62 , 0 ), // #167 - INST(Fbstp , X86M_Only , O_FPU(00,00DF,6) , 0 , 39 , 0 , 630 , 62 , 0 ), // #168 - INST(Fchs , FpuOp , O_FPU(00,D9E0,_) , 0 , 35 , 0 , 636 , 30 , 0 ), // #169 - INST(Fclex , FpuOp , O_FPU(9B,DBE2,_) , 0 , 40 , 0 , 641 , 30 , 0 ), // #170 - INST(Fcmovb , FpuR , O_FPU(00,DAC0,_) , 0 , 41 , 0 , 647 , 63 , 30 ), // #171 - INST(Fcmovbe , FpuR , O_FPU(00,DAD0,_) , 0 , 41 , 0 , 654 , 63 , 29 ), // #172 - INST(Fcmove , FpuR , O_FPU(00,DAC8,_) , 0 , 41 , 0 , 662 , 63 , 31 ), // #173 - INST(Fcmovnb , FpuR , O_FPU(00,DBC0,_) , 0 , 42 , 0 , 669 , 63 , 30 ), // #174 - INST(Fcmovnbe , FpuR , O_FPU(00,DBD0,_) , 0 , 42 , 0 , 677 , 63 , 29 ), // #175 - INST(Fcmovne , FpuR , O_FPU(00,DBC8,_) , 0 , 42 , 0 , 686 , 63 , 31 ), // #176 - INST(Fcmovnu , FpuR , O_FPU(00,DBD8,_) , 0 , 42 , 0 , 694 , 63 , 35 ), // #177 - INST(Fcmovu , FpuR , O_FPU(00,DAD8,_) , 0 , 41 , 0 , 702 , 63 , 35 ), // #178 - INST(Fcom , FpuCom , O_FPU(00,D0D0,2) , 0 , 43 , 0 , 709 , 64 , 0 ), // #179 - INST(Fcomi , FpuR , O_FPU(00,DBF0,_) , 0 , 42 , 0 , 714 , 63 , 50 ), // #180 - INST(Fcomip , FpuR , O_FPU(00,DFF0,_) , 0 , 44 , 0 , 720 , 63 , 50 ), // #181 - INST(Fcomp , FpuCom , O_FPU(00,D8D8,3) , 0 , 45 , 0 , 727 , 64 , 0 ), // #182 - INST(Fcompp , FpuOp , O_FPU(00,DED9,_) , 0 , 37 , 0 , 733 , 30 , 0 ), // #183 - INST(Fcos , FpuOp , O_FPU(00,D9FF,_) , 0 , 35 , 0 , 740 , 30 , 0 ), // #184 - INST(Fdecstp , FpuOp , O_FPU(00,D9F6,_) , 0 , 35 , 0 , 745 , 30 , 0 ), // #185 - INST(Fdiv , FpuArith , O_FPU(00,F0F8,6) , 0 , 46 , 0 , 753 , 60 , 0 ), // #186 - INST(Fdivp , FpuRDef , O_FPU(00,DEF8,_) , 0 , 37 , 0 , 758 , 61 , 0 ), // #187 - INST(Fdivr , FpuArith , O_FPU(00,F8F0,7) , 0 , 47 , 0 , 764 , 60 , 0 ), // #188 - INST(Fdivrp , FpuRDef , O_FPU(00,DEF0,_) , 0 , 37 , 0 , 770 , 61 , 0 ), // #189 - INST(Femms , X86Op , O(000F00,0E,_,_,_,_,_,_ ), 0 , 4 , 0 , 777 , 30 , 51 ), // #190 - INST(Ffree , FpuR , O_FPU(00,DDC0,_) , 0 , 48 , 0 , 783 , 63 , 0 ), // #191 - INST(Fiadd , FpuM , O_FPU(00,00DA,0) , 0 , 49 , 0 , 789 , 65 , 0 ), // #192 - INST(Ficom , FpuM , O_FPU(00,00DA,2) , 0 , 50 , 0 , 795 , 65 , 0 ), // #193 - INST(Ficomp , FpuM , O_FPU(00,00DA,3) , 0 , 51 , 0 , 801 , 65 , 0 ), // #194 - INST(Fidiv , FpuM , O_FPU(00,00DA,6) , 0 , 39 , 0 , 808 , 65 , 0 ), // #195 - INST(Fidivr , FpuM , O_FPU(00,00DA,7) , 0 , 52 , 0 , 814 , 65 , 0 ), // #196 - INST(Fild , FpuM , O_FPU(00,00DB,0) , O_FPU(00,00DF,5) , 49 , 8 , 821 , 66 , 0 ), // #197 - INST(Fimul , FpuM , O_FPU(00,00DA,1) , 0 , 53 , 0 , 826 , 65 , 0 ), // #198 - INST(Fincstp , FpuOp , O_FPU(00,D9F7,_) , 0 , 35 , 0 , 832 , 30 , 0 ), // #199 - INST(Finit , FpuOp , O_FPU(9B,DBE3,_) , 0 , 40 , 0 , 840 , 30 , 0 ), // #200 - INST(Fist , FpuM , O_FPU(00,00DB,2) , 0 , 50 , 0 , 846 , 65 , 0 ), // #201 - INST(Fistp , FpuM , O_FPU(00,00DB,3) , O_FPU(00,00DF,7) , 51 , 9 , 851 , 66 , 0 ), // #202 - INST(Fisttp , FpuM , O_FPU(00,00DB,1) , O_FPU(00,00DD,1) , 53 , 10 , 857 , 66 , 6 ), // #203 - INST(Fisub , FpuM , O_FPU(00,00DA,4) , 0 , 38 , 0 , 864 , 65 , 0 ), // #204 - INST(Fisubr , FpuM , O_FPU(00,00DA,5) , 0 , 54 , 0 , 870 , 65 , 0 ), // #205 - INST(Fld , FpuFldFst , O_FPU(00,00D9,0) , O_FPU(00,00DB,5) , 49 , 11 , 877 , 67 , 0 ), // #206 - INST(Fld1 , FpuOp , O_FPU(00,D9E8,_) , 0 , 35 , 0 , 881 , 30 , 0 ), // #207 - INST(Fldcw , X86M_Only , O_FPU(00,00D9,5) , 0 , 54 , 0 , 886 , 68 , 0 ), // #208 - INST(Fldenv , X86M_Only , O_FPU(00,00D9,4) , 0 , 38 , 0 , 892 , 69 , 0 ), // #209 - INST(Fldl2e , FpuOp , O_FPU(00,D9EA,_) , 0 , 35 , 0 , 899 , 30 , 0 ), // #210 - INST(Fldl2t , FpuOp , O_FPU(00,D9E9,_) , 0 , 35 , 0 , 906 , 30 , 0 ), // #211 - INST(Fldlg2 , FpuOp , O_FPU(00,D9EC,_) , 0 , 35 , 0 , 913 , 30 , 0 ), // #212 - INST(Fldln2 , FpuOp , O_FPU(00,D9ED,_) , 0 , 35 , 0 , 920 , 30 , 0 ), // #213 - INST(Fldpi , FpuOp , O_FPU(00,D9EB,_) , 0 , 35 , 0 , 927 , 30 , 0 ), // #214 - INST(Fldz , FpuOp , O_FPU(00,D9EE,_) , 0 , 35 , 0 , 933 , 30 , 0 ), // #215 - INST(Fmul , FpuArith , O_FPU(00,C8C8,1) , 0 , 55 , 0 , 2163 , 60 , 0 ), // #216 - INST(Fmulp , FpuRDef , O_FPU(00,DEC8,_) , 0 , 37 , 0 , 938 , 61 , 0 ), // #217 - INST(Fnclex , FpuOp , O_FPU(00,DBE2,_) , 0 , 42 , 0 , 944 , 30 , 0 ), // #218 - INST(Fninit , FpuOp , O_FPU(00,DBE3,_) , 0 , 42 , 0 , 951 , 30 , 0 ), // #219 - INST(Fnop , FpuOp , O_FPU(00,D9D0,_) , 0 , 35 , 0 , 958 , 30 , 0 ), // #220 - INST(Fnsave , X86M_Only , O_FPU(00,00DD,6) , 0 , 39 , 0 , 963 , 69 , 0 ), // #221 - INST(Fnstcw , X86M_Only , O_FPU(00,00D9,7) , 0 , 52 , 0 , 970 , 68 , 0 ), // #222 - INST(Fnstenv , X86M_Only , O_FPU(00,00D9,6) , 0 , 39 , 0 , 977 , 69 , 0 ), // #223 - INST(Fnstsw , FpuStsw , O_FPU(00,00DD,7) , O_FPU(00,DFE0,_) , 52 , 12 , 985 , 70 , 0 ), // #224 - INST(Fpatan , FpuOp , O_FPU(00,D9F3,_) , 0 , 35 , 0 , 992 , 30 , 0 ), // #225 - INST(Fprem , FpuOp , O_FPU(00,D9F8,_) , 0 , 35 , 0 , 999 , 30 , 0 ), // #226 - INST(Fprem1 , FpuOp , O_FPU(00,D9F5,_) , 0 , 35 , 0 , 1005 , 30 , 0 ), // #227 - INST(Fptan , FpuOp , O_FPU(00,D9F2,_) , 0 , 35 , 0 , 1012 , 30 , 0 ), // #228 - INST(Frndint , FpuOp , O_FPU(00,D9FC,_) , 0 , 35 , 0 , 1018 , 30 , 0 ), // #229 - INST(Frstor , X86M_Only , O_FPU(00,00DD,4) , 0 , 38 , 0 , 1026 , 69 , 0 ), // #230 - INST(Fsave , X86M_Only , O_FPU(9B,00DD,6) , 0 , 56 , 0 , 1033 , 69 , 0 ), // #231 - INST(Fscale , FpuOp , O_FPU(00,D9FD,_) , 0 , 35 , 0 , 1039 , 30 , 0 ), // #232 - INST(Fsin , FpuOp , O_FPU(00,D9FE,_) , 0 , 35 , 0 , 1046 , 30 , 0 ), // #233 - INST(Fsincos , FpuOp , O_FPU(00,D9FB,_) , 0 , 35 , 0 , 1051 , 30 , 0 ), // #234 - INST(Fsqrt , FpuOp , O_FPU(00,D9FA,_) , 0 , 35 , 0 , 1059 , 30 , 0 ), // #235 - INST(Fst , FpuFldFst , O_FPU(00,00D9,2) , 0 , 50 , 0 , 1065 , 71 , 0 ), // #236 - INST(Fstcw , X86M_Only , O_FPU(9B,00D9,7) , 0 , 57 , 0 , 1069 , 68 , 0 ), // #237 - INST(Fstenv , X86M_Only , O_FPU(9B,00D9,6) , 0 , 56 , 0 , 1075 , 69 , 0 ), // #238 - INST(Fstp , FpuFldFst , O_FPU(00,00D9,3) , O(000000,DB,7,_,_,_,_,_ ), 51 , 13 , 1082 , 67 , 0 ), // #239 - INST(Fstsw , FpuStsw , O_FPU(9B,00DD,7) , O_FPU(9B,DFE0,_) , 57 , 14 , 1087 , 70 , 0 ), // #240 - INST(Fsub , FpuArith , O_FPU(00,E0E8,4) , 0 , 58 , 0 , 2241 , 60 , 0 ), // #241 - INST(Fsubp , FpuRDef , O_FPU(00,DEE8,_) , 0 , 37 , 0 , 1093 , 61 , 0 ), // #242 - INST(Fsubr , FpuArith , O_FPU(00,E8E0,5) , 0 , 59 , 0 , 2247 , 60 , 0 ), // #243 - INST(Fsubrp , FpuRDef , O_FPU(00,DEE0,_) , 0 , 37 , 0 , 1099 , 61 , 0 ), // #244 - INST(Ftst , FpuOp , O_FPU(00,D9E4,_) , 0 , 35 , 0 , 1106 , 30 , 0 ), // #245 - INST(Fucom , FpuRDef , O_FPU(00,DDE0,_) , 0 , 48 , 0 , 1111 , 61 , 0 ), // #246 - INST(Fucomi , FpuR , O_FPU(00,DBE8,_) , 0 , 42 , 0 , 1117 , 63 , 50 ), // #247 - INST(Fucomip , FpuR , O_FPU(00,DFE8,_) , 0 , 44 , 0 , 1124 , 63 , 50 ), // #248 - INST(Fucomp , FpuRDef , O_FPU(00,DDE8,_) , 0 , 48 , 0 , 1132 , 61 , 0 ), // #249 - INST(Fucompp , FpuOp , O_FPU(00,DAE9,_) , 0 , 41 , 0 , 1139 , 30 , 0 ), // #250 - INST(Fwait , X86Op , O_FPU(00,009B,_) , 0 , 49 , 0 , 1147 , 30 , 0 ), // #251 - INST(Fxam , FpuOp , O_FPU(00,D9E5,_) , 0 , 35 , 0 , 1153 , 30 , 0 ), // #252 - INST(Fxch , FpuR , O_FPU(00,D9C8,_) , 0 , 35 , 0 , 1158 , 61 , 0 ), // #253 - INST(Fxrstor , X86M_Only , O(000F00,AE,1,_,_,_,_,_ ), 0 , 29 , 0 , 1163 , 69 , 52 ), // #254 - INST(Fxrstor64 , X86M_Only , O(000F00,AE,1,_,1,_,_,_ ), 0 , 28 , 0 , 1171 , 72 , 52 ), // #255 - INST(Fxsave , X86M_Only , O(000F00,AE,0,_,_,_,_,_ ), 0 , 4 , 0 , 1181 , 69 , 52 ), // #256 - INST(Fxsave64 , X86M_Only , O(000F00,AE,0,_,1,_,_,_ ), 0 , 60 , 0 , 1188 , 72 , 52 ), // #257 - INST(Fxtract , FpuOp , O_FPU(00,D9F4,_) , 0 , 35 , 0 , 1197 , 30 , 0 ), // #258 - INST(Fyl2x , FpuOp , O_FPU(00,D9F1,_) , 0 , 35 , 0 , 1205 , 30 , 0 ), // #259 - INST(Fyl2xp1 , FpuOp , O_FPU(00,D9F9,_) , 0 , 35 , 0 , 1211 , 30 , 0 ), // #260 - INST(Getsec , X86Op , O(000F00,37,_,_,_,_,_,_ ), 0 , 4 , 0 , 1219 , 30 , 53 ), // #261 - INST(Gf2p8affineinvqb , ExtRmi , O(660F3A,CF,_,_,_,_,_,_ ), 0 , 8 , 0 , 6789 , 8 , 54 ), // #262 - INST(Gf2p8affineqb , ExtRmi , O(660F3A,CE,_,_,_,_,_,_ ), 0 , 8 , 0 , 6807 , 8 , 54 ), // #263 - INST(Gf2p8mulb , ExtRm , O(660F38,CF,_,_,_,_,_,_ ), 0 , 2 , 0 , 6822 , 5 , 54 ), // #264 - INST(Haddpd , ExtRm , O(660F00,7C,_,_,_,_,_,_ ), 0 , 3 , 0 , 6833 , 5 , 6 ), // #265 - INST(Haddps , ExtRm , O(F20F00,7C,_,_,_,_,_,_ ), 0 , 5 , 0 , 6841 , 5 , 6 ), // #266 - INST(Hlt , X86Op , O(000000,F4,_,_,_,_,_,_ ), 0 , 0 , 0 , 1226 , 30 , 0 ), // #267 - INST(Hreset , X86Op_Mod11RM_I8 , O(F30F3A,F0,0,_,_,_,_,_ ), 0 , 61 , 0 , 1230 , 73 , 55 ), // #268 - INST(Hsubpd , ExtRm , O(660F00,7D,_,_,_,_,_,_ ), 0 , 3 , 0 , 6849 , 5 , 6 ), // #269 - INST(Hsubps , ExtRm , O(F20F00,7D,_,_,_,_,_,_ ), 0 , 5 , 0 , 6857 , 5 , 6 ), // #270 - INST(Idiv , X86M_GPB_MulDiv , O(000000,F6,7,_,x,_,_,_ ), 0 , 27 , 0 , 809 , 54 , 1 ), // #271 - INST(Imul , X86Imul , O(000000,F6,5,_,x,_,_,_ ), 0 , 62 , 0 , 827 , 74 , 1 ), // #272 - INST(In , X86In , O(000000,EC,_,_,_,_,_,_ ), O(000000,E4,_,_,_,_,_,_ ), 0 , 15 , 11572, 75 , 0 ), // #273 - INST(Inc , X86IncDec , O(000000,FE,0,_,x,_,_,_ ), O(000000,40,_,_,x,_,_,_ ), 0 , 16 , 1237 , 53 , 45 ), // #274 - INST(Incsspd , X86M , O(F30F00,AE,5,_,0,_,_,_ ), 0 , 63 , 0 , 1241 , 76 , 56 ), // #275 - INST(Incsspq , X86M , O(F30F00,AE,5,_,1,_,_,_ ), 0 , 64 , 0 , 1249 , 77 , 56 ), // #276 - INST(Ins , X86Ins , O(000000,6C,_,_,_,_,_,_ ), 0 , 0 , 0 , 1916 , 78 , 0 ), // #277 - INST(Insertps , ExtRmi , O(660F3A,21,_,_,_,_,_,_ ), 0 , 8 , 0 , 6993 , 38 , 12 ), // #278 - INST(Insertq , ExtInsertq , O(F20F00,79,_,_,_,_,_,_ ), O(F20F00,78,_,_,_,_,_,_ ), 5 , 17 , 1257 , 79 , 49 ), // #279 - INST(Int , X86Int , O(000000,CD,_,_,_,_,_,_ ), 0 , 0 , 0 , 1022 , 80 , 0 ), // #280 - INST(Int3 , X86Op , O(000000,CC,_,_,_,_,_,_ ), 0 , 0 , 0 , 1265 , 30 , 0 ), // #281 - INST(Into , X86Op , O(000000,CE,_,_,_,_,_,_ ), 0 , 0 , 0 , 1270 , 81 , 57 ), // #282 - INST(Invd , X86Op , O(000F00,08,_,_,_,_,_,_ ), 0 , 4 , 0 , 11501, 30 , 43 ), // #283 - INST(Invept , X86Rm_NoSize , O(660F38,80,_,_,_,_,_,_ ), 0 , 2 , 0 , 1275 , 82 , 58 ), // #284 - INST(Invlpg , X86M_Only , O(000F00,01,7,_,_,_,_,_ ), 0 , 22 , 0 , 1282 , 69 , 43 ), // #285 - INST(Invlpga , X86Op_xAddr , O(000F01,DF,_,_,_,_,_,_ ), 0 , 21 , 0 , 1289 , 83 , 22 ), // #286 - INST(Invpcid , X86Rm_NoSize , O(660F38,82,_,_,_,_,_,_ ), 0 , 2 , 0 , 1297 , 82 , 43 ), // #287 - INST(Invvpid , X86Rm_NoSize , O(660F38,81,_,_,_,_,_,_ ), 0 , 2 , 0 , 1305 , 82 , 58 ), // #288 - INST(Iret , X86Op , O(660000,CF,_,_,_,_,_,_ ), 0 , 19 , 0 , 3226 , 84 , 1 ), // #289 - INST(Iretd , X86Op , O(000000,CF,_,_,_,_,_,_ ), 0 , 0 , 0 , 1313 , 84 , 1 ), // #290 - INST(Iretq , X86Op , O(000000,CF,_,_,1,_,_,_ ), 0 , 20 , 0 , 1319 , 85 , 1 ), // #291 - INST(Ja , X86Jcc , O(000F00,87,_,_,_,_,_,_ ), O(000000,77,_,_,_,_,_,_ ), 4 , 18 , 1325 , 86 , 59 ), // #292 - INST(Jae , X86Jcc , O(000F00,83,_,_,_,_,_,_ ), O(000000,73,_,_,_,_,_,_ ), 4 , 19 , 1328 , 86 , 60 ), // #293 - INST(Jb , X86Jcc , O(000F00,82,_,_,_,_,_,_ ), O(000000,72,_,_,_,_,_,_ ), 4 , 20 , 1332 , 86 , 60 ), // #294 - INST(Jbe , X86Jcc , O(000F00,86,_,_,_,_,_,_ ), O(000000,76,_,_,_,_,_,_ ), 4 , 21 , 1335 , 86 , 59 ), // #295 - INST(Jc , X86Jcc , O(000F00,82,_,_,_,_,_,_ ), O(000000,72,_,_,_,_,_,_ ), 4 , 20 , 1339 , 86 , 60 ), // #296 - INST(Je , X86Jcc , O(000F00,84,_,_,_,_,_,_ ), O(000000,74,_,_,_,_,_,_ ), 4 , 22 , 1342 , 86 , 61 ), // #297 - INST(Jecxz , X86JecxzLoop , 0 , O(000000,E3,_,_,_,_,_,_ ), 0 , 23 , 1345 , 87 , 0 ), // #298 - INST(Jg , X86Jcc , O(000F00,8F,_,_,_,_,_,_ ), O(000000,7F,_,_,_,_,_,_ ), 4 , 24 , 1351 , 86 , 62 ), // #299 - INST(Jge , X86Jcc , O(000F00,8D,_,_,_,_,_,_ ), O(000000,7D,_,_,_,_,_,_ ), 4 , 25 , 1354 , 86 , 63 ), // #300 - INST(Jl , X86Jcc , O(000F00,8C,_,_,_,_,_,_ ), O(000000,7C,_,_,_,_,_,_ ), 4 , 26 , 1358 , 86 , 63 ), // #301 - INST(Jle , X86Jcc , O(000F00,8E,_,_,_,_,_,_ ), O(000000,7E,_,_,_,_,_,_ ), 4 , 27 , 1361 , 86 , 62 ), // #302 - INST(Jmp , X86Jmp , O(000000,FF,4,_,_,_,_,_ ), O(000000,EB,_,_,_,_,_,_ ), 9 , 28 , 1861 , 88 , 0 ), // #303 - INST(Jna , X86Jcc , O(000F00,86,_,_,_,_,_,_ ), O(000000,76,_,_,_,_,_,_ ), 4 , 21 , 1365 , 86 , 59 ), // #304 - INST(Jnae , X86Jcc , O(000F00,82,_,_,_,_,_,_ ), O(000000,72,_,_,_,_,_,_ ), 4 , 20 , 1369 , 86 , 60 ), // #305 - INST(Jnb , X86Jcc , O(000F00,83,_,_,_,_,_,_ ), O(000000,73,_,_,_,_,_,_ ), 4 , 19 , 1374 , 86 , 60 ), // #306 - INST(Jnbe , X86Jcc , O(000F00,87,_,_,_,_,_,_ ), O(000000,77,_,_,_,_,_,_ ), 4 , 18 , 1378 , 86 , 59 ), // #307 - INST(Jnc , X86Jcc , O(000F00,83,_,_,_,_,_,_ ), O(000000,73,_,_,_,_,_,_ ), 4 , 19 , 1383 , 86 , 60 ), // #308 - INST(Jne , X86Jcc , O(000F00,85,_,_,_,_,_,_ ), O(000000,75,_,_,_,_,_,_ ), 4 , 29 , 1387 , 86 , 61 ), // #309 - INST(Jng , X86Jcc , O(000F00,8E,_,_,_,_,_,_ ), O(000000,7E,_,_,_,_,_,_ ), 4 , 27 , 1391 , 86 , 62 ), // #310 - INST(Jnge , X86Jcc , O(000F00,8C,_,_,_,_,_,_ ), O(000000,7C,_,_,_,_,_,_ ), 4 , 26 , 1395 , 86 , 63 ), // #311 - INST(Jnl , X86Jcc , O(000F00,8D,_,_,_,_,_,_ ), O(000000,7D,_,_,_,_,_,_ ), 4 , 25 , 1400 , 86 , 63 ), // #312 - INST(Jnle , X86Jcc , O(000F00,8F,_,_,_,_,_,_ ), O(000000,7F,_,_,_,_,_,_ ), 4 , 24 , 1404 , 86 , 62 ), // #313 - INST(Jno , X86Jcc , O(000F00,81,_,_,_,_,_,_ ), O(000000,71,_,_,_,_,_,_ ), 4 , 30 , 1409 , 86 , 57 ), // #314 - INST(Jnp , X86Jcc , O(000F00,8B,_,_,_,_,_,_ ), O(000000,7B,_,_,_,_,_,_ ), 4 , 31 , 1413 , 86 , 64 ), // #315 - INST(Jns , X86Jcc , O(000F00,89,_,_,_,_,_,_ ), O(000000,79,_,_,_,_,_,_ ), 4 , 32 , 1417 , 86 , 65 ), // #316 - INST(Jnz , X86Jcc , O(000F00,85,_,_,_,_,_,_ ), O(000000,75,_,_,_,_,_,_ ), 4 , 29 , 1421 , 86 , 61 ), // #317 - INST(Jo , X86Jcc , O(000F00,80,_,_,_,_,_,_ ), O(000000,70,_,_,_,_,_,_ ), 4 , 33 , 1425 , 86 , 57 ), // #318 - INST(Jp , X86Jcc , O(000F00,8A,_,_,_,_,_,_ ), O(000000,7A,_,_,_,_,_,_ ), 4 , 34 , 1428 , 86 , 64 ), // #319 - INST(Jpe , X86Jcc , O(000F00,8A,_,_,_,_,_,_ ), O(000000,7A,_,_,_,_,_,_ ), 4 , 34 , 1431 , 86 , 64 ), // #320 - INST(Jpo , X86Jcc , O(000F00,8B,_,_,_,_,_,_ ), O(000000,7B,_,_,_,_,_,_ ), 4 , 31 , 1435 , 86 , 64 ), // #321 - INST(Js , X86Jcc , O(000F00,88,_,_,_,_,_,_ ), O(000000,78,_,_,_,_,_,_ ), 4 , 35 , 1439 , 86 , 65 ), // #322 - INST(Jz , X86Jcc , O(000F00,84,_,_,_,_,_,_ ), O(000000,74,_,_,_,_,_,_ ), 4 , 22 , 1442 , 86 , 61 ), // #323 - INST(Kaddb , VexRvm , V(660F00,4A,_,1,0,_,_,_ ), 0 , 65 , 0 , 1445 , 89 , 66 ), // #324 - INST(Kaddd , VexRvm , V(660F00,4A,_,1,1,_,_,_ ), 0 , 66 , 0 , 1451 , 89 , 67 ), // #325 - INST(Kaddq , VexRvm , V(000F00,4A,_,1,1,_,_,_ ), 0 , 67 , 0 , 1457 , 89 , 67 ), // #326 - INST(Kaddw , VexRvm , V(000F00,4A,_,1,0,_,_,_ ), 0 , 68 , 0 , 1463 , 89 , 66 ), // #327 - INST(Kandb , VexRvm , V(660F00,41,_,1,0,_,_,_ ), 0 , 65 , 0 , 1469 , 89 , 66 ), // #328 - INST(Kandd , VexRvm , V(660F00,41,_,1,1,_,_,_ ), 0 , 66 , 0 , 1475 , 89 , 67 ), // #329 - INST(Kandnb , VexRvm , V(660F00,42,_,1,0,_,_,_ ), 0 , 65 , 0 , 1481 , 89 , 66 ), // #330 - INST(Kandnd , VexRvm , V(660F00,42,_,1,1,_,_,_ ), 0 , 66 , 0 , 1488 , 89 , 67 ), // #331 - INST(Kandnq , VexRvm , V(000F00,42,_,1,1,_,_,_ ), 0 , 67 , 0 , 1495 , 89 , 67 ), // #332 - INST(Kandnw , VexRvm , V(000F00,42,_,1,0,_,_,_ ), 0 , 68 , 0 , 1502 , 89 , 68 ), // #333 - INST(Kandq , VexRvm , V(000F00,41,_,1,1,_,_,_ ), 0 , 67 , 0 , 1509 , 89 , 67 ), // #334 - INST(Kandw , VexRvm , V(000F00,41,_,1,0,_,_,_ ), 0 , 68 , 0 , 1515 , 89 , 68 ), // #335 - INST(Kmovb , VexKmov , V(660F00,90,_,0,0,_,_,_ ), V(660F00,92,_,0,0,_,_,_ ), 69 , 36 , 1521 , 90 , 69 ), // #336 - INST(Kmovd , VexKmov , V(660F00,90,_,0,1,_,_,_ ), V(F20F00,92,_,0,0,_,_,_ ), 70 , 37 , 9105 , 91 , 70 ), // #337 - INST(Kmovq , VexKmov , V(000F00,90,_,0,1,_,_,_ ), V(F20F00,92,_,0,1,_,_,_ ), 71 , 38 , 9116 , 92 , 70 ), // #338 - INST(Kmovw , VexKmov , V(000F00,90,_,0,0,_,_,_ ), V(000F00,92,_,0,0,_,_,_ ), 72 , 39 , 1527 , 93 , 71 ), // #339 - INST(Knotb , VexRm , V(660F00,44,_,0,0,_,_,_ ), 0 , 69 , 0 , 1533 , 94 , 66 ), // #340 - INST(Knotd , VexRm , V(660F00,44,_,0,1,_,_,_ ), 0 , 70 , 0 , 1539 , 94 , 67 ), // #341 - INST(Knotq , VexRm , V(000F00,44,_,0,1,_,_,_ ), 0 , 71 , 0 , 1545 , 94 , 67 ), // #342 - INST(Knotw , VexRm , V(000F00,44,_,0,0,_,_,_ ), 0 , 72 , 0 , 1551 , 94 , 68 ), // #343 - INST(Korb , VexRvm , V(660F00,45,_,1,0,_,_,_ ), 0 , 65 , 0 , 1557 , 89 , 66 ), // #344 - INST(Kord , VexRvm , V(660F00,45,_,1,1,_,_,_ ), 0 , 66 , 0 , 1562 , 89 , 67 ), // #345 - INST(Korq , VexRvm , V(000F00,45,_,1,1,_,_,_ ), 0 , 67 , 0 , 1567 , 89 , 67 ), // #346 - INST(Kortestb , VexRm , V(660F00,98,_,0,0,_,_,_ ), 0 , 69 , 0 , 1572 , 94 , 72 ), // #347 - INST(Kortestd , VexRm , V(660F00,98,_,0,1,_,_,_ ), 0 , 70 , 0 , 1581 , 94 , 73 ), // #348 - INST(Kortestq , VexRm , V(000F00,98,_,0,1,_,_,_ ), 0 , 71 , 0 , 1590 , 94 , 73 ), // #349 - INST(Kortestw , VexRm , V(000F00,98,_,0,0,_,_,_ ), 0 , 72 , 0 , 1599 , 94 , 74 ), // #350 - INST(Korw , VexRvm , V(000F00,45,_,1,0,_,_,_ ), 0 , 68 , 0 , 1608 , 89 , 68 ), // #351 - INST(Kshiftlb , VexRmi , V(660F3A,32,_,0,0,_,_,_ ), 0 , 73 , 0 , 1613 , 95 , 66 ), // #352 - INST(Kshiftld , VexRmi , V(660F3A,33,_,0,0,_,_,_ ), 0 , 73 , 0 , 1622 , 95 , 67 ), // #353 - INST(Kshiftlq , VexRmi , V(660F3A,33,_,0,1,_,_,_ ), 0 , 74 , 0 , 1631 , 95 , 67 ), // #354 - INST(Kshiftlw , VexRmi , V(660F3A,32,_,0,1,_,_,_ ), 0 , 74 , 0 , 1640 , 95 , 68 ), // #355 - INST(Kshiftrb , VexRmi , V(660F3A,30,_,0,0,_,_,_ ), 0 , 73 , 0 , 1649 , 95 , 66 ), // #356 - INST(Kshiftrd , VexRmi , V(660F3A,31,_,0,0,_,_,_ ), 0 , 73 , 0 , 1658 , 95 , 67 ), // #357 - INST(Kshiftrq , VexRmi , V(660F3A,31,_,0,1,_,_,_ ), 0 , 74 , 0 , 1667 , 95 , 67 ), // #358 - INST(Kshiftrw , VexRmi , V(660F3A,30,_,0,1,_,_,_ ), 0 , 74 , 0 , 1676 , 95 , 68 ), // #359 - INST(Ktestb , VexRm , V(660F00,99,_,0,0,_,_,_ ), 0 , 69 , 0 , 1685 , 94 , 72 ), // #360 - INST(Ktestd , VexRm , V(660F00,99,_,0,1,_,_,_ ), 0 , 70 , 0 , 1692 , 94 , 73 ), // #361 - INST(Ktestq , VexRm , V(000F00,99,_,0,1,_,_,_ ), 0 , 71 , 0 , 1699 , 94 , 73 ), // #362 - INST(Ktestw , VexRm , V(000F00,99,_,0,0,_,_,_ ), 0 , 72 , 0 , 1706 , 94 , 72 ), // #363 - INST(Kunpckbw , VexRvm , V(660F00,4B,_,1,0,_,_,_ ), 0 , 65 , 0 , 1713 , 89 , 68 ), // #364 - INST(Kunpckdq , VexRvm , V(000F00,4B,_,1,1,_,_,_ ), 0 , 67 , 0 , 1722 , 89 , 67 ), // #365 - INST(Kunpckwd , VexRvm , V(000F00,4B,_,1,0,_,_,_ ), 0 , 68 , 0 , 1731 , 89 , 67 ), // #366 - INST(Kxnorb , VexRvm , V(660F00,46,_,1,0,_,_,_ ), 0 , 65 , 0 , 1740 , 96 , 66 ), // #367 - INST(Kxnord , VexRvm , V(660F00,46,_,1,1,_,_,_ ), 0 , 66 , 0 , 1747 , 96 , 67 ), // #368 - INST(Kxnorq , VexRvm , V(000F00,46,_,1,1,_,_,_ ), 0 , 67 , 0 , 1754 , 96 , 67 ), // #369 - INST(Kxnorw , VexRvm , V(000F00,46,_,1,0,_,_,_ ), 0 , 68 , 0 , 1761 , 96 , 68 ), // #370 - INST(Kxorb , VexRvm , V(660F00,47,_,1,0,_,_,_ ), 0 , 65 , 0 , 1768 , 96 , 66 ), // #371 - INST(Kxord , VexRvm , V(660F00,47,_,1,1,_,_,_ ), 0 , 66 , 0 , 1774 , 96 , 67 ), // #372 - INST(Kxorq , VexRvm , V(000F00,47,_,1,1,_,_,_ ), 0 , 67 , 0 , 1780 , 96 , 67 ), // #373 - INST(Kxorw , VexRvm , V(000F00,47,_,1,0,_,_,_ ), 0 , 68 , 0 , 1786 , 96 , 68 ), // #374 - INST(Lahf , X86Op , O(000000,9F,_,_,_,_,_,_ ), 0 , 0 , 0 , 1792 , 97 , 75 ), // #375 - INST(Lar , X86Rm , O(000F00,02,_,_,_,_,_,_ ), 0 , 4 , 0 , 1797 , 98 , 10 ), // #376 - INST(Lcall , X86LcallLjmp , O(000000,FF,3,_,_,_,_,_ ), O(000000,9A,_,_,_,_,_,_ ), 75 , 40 , 1801 , 99 , 1 ), // #377 - INST(Lddqu , ExtRm , O(F20F00,F0,_,_,_,_,_,_ ), 0 , 5 , 0 , 7003 , 100, 6 ), // #378 - INST(Ldmxcsr , X86M_Only , O(000F00,AE,2,_,_,_,_,_ ), 0 , 76 , 0 , 7010 , 101, 5 ), // #379 - INST(Lds , X86Rm , O(000000,C5,_,_,_,_,_,_ ), 0 , 0 , 0 , 1807 , 102, 0 ), // #380 - INST(Ldtilecfg , AmxCfg , V(000F38,49,_,0,0,_,_,_ ), 0 , 10 , 0 , 1811 , 103, 76 ), // #381 - INST(Lea , X86Lea , O(000000,8D,_,_,x,_,_,_ ), 0 , 0 , 0 , 1821 , 104, 0 ), // #382 - INST(Leave , X86Op , O(000000,C9,_,_,_,_,_,_ ), 0 , 0 , 0 , 1825 , 30 , 0 ), // #383 - INST(Les , X86Rm , O(000000,C4,_,_,_,_,_,_ ), 0 , 0 , 0 , 1831 , 102, 0 ), // #384 - INST(Lfence , X86Fence , O(000F00,AE,5,_,_,_,_,_ ), 0 , 77 , 0 , 1835 , 30 , 4 ), // #385 - INST(Lfs , X86Rm , O(000F00,B4,_,_,_,_,_,_ ), 0 , 4 , 0 , 1842 , 105, 0 ), // #386 - INST(Lgdt , X86M_Only , O(000F00,01,2,_,_,_,_,_ ), 0 , 76 , 0 , 1846 , 69 , 0 ), // #387 - INST(Lgs , X86Rm , O(000F00,B5,_,_,_,_,_,_ ), 0 , 4 , 0 , 1851 , 105, 0 ), // #388 - INST(Lidt , X86M_Only , O(000F00,01,3,_,_,_,_,_ ), 0 , 78 , 0 , 1855 , 69 , 0 ), // #389 - INST(Ljmp , X86LcallLjmp , O(000000,FF,5,_,_,_,_,_ ), O(000000,EA,_,_,_,_,_,_ ), 62 , 41 , 1860 , 106, 0 ), // #390 - INST(Lldt , X86M_NoSize , O(000F00,00,2,_,_,_,_,_ ), 0 , 76 , 0 , 1865 , 107, 0 ), // #391 - INST(Llwpcb , VexR_Wx , V(XOP_M9,12,0,0,x,_,_,_ ), 0 , 79 , 0 , 1870 , 108, 77 ), // #392 - INST(Lmsw , X86M_NoSize , O(000F00,01,6,_,_,_,_,_ ), 0 , 80 , 0 , 1877 , 107, 0 ), // #393 - INST(Lods , X86StrRm , O(000000,AC,_,_,_,_,_,_ ), 0 , 0 , 0 , 1882 , 109, 78 ), // #394 - INST(Loop , X86JecxzLoop , 0 , O(000000,E2,_,_,_,_,_,_ ), 0 , 42 , 1887 , 110, 0 ), // #395 - INST(Loope , X86JecxzLoop , 0 , O(000000,E1,_,_,_,_,_,_ ), 0 , 43 , 1892 , 110, 61 ), // #396 - INST(Loopne , X86JecxzLoop , 0 , O(000000,E0,_,_,_,_,_,_ ), 0 , 44 , 1898 , 110, 61 ), // #397 - INST(Lsl , X86Rm , O(000F00,03,_,_,_,_,_,_ ), 0 , 4 , 0 , 1905 , 111, 10 ), // #398 - INST(Lss , X86Rm , O(000F00,B2,_,_,_,_,_,_ ), 0 , 4 , 0 , 7556 , 105, 0 ), // #399 - INST(Ltr , X86M_NoSize , O(000F00,00,3,_,_,_,_,_ ), 0 , 78 , 0 , 1909 , 107, 0 ), // #400 - INST(Lwpins , VexVmi4_Wx , V(XOP_MA,12,0,0,x,_,_,_ ), 0 , 81 , 0 , 1913 , 112, 77 ), // #401 - INST(Lwpval , VexVmi4_Wx , V(XOP_MA,12,1,0,x,_,_,_ ), 0 , 82 , 0 , 1920 , 112, 77 ), // #402 - INST(Lzcnt , X86Rm_Raw66H , O(F30F00,BD,_,_,x,_,_,_ ), 0 , 6 , 0 , 1927 , 22 , 79 ), // #403 - INST(Maskmovdqu , ExtRm_ZDI , O(660F00,F7,_,_,_,_,_,_ ), 0 , 3 , 0 , 7019 , 113, 4 ), // #404 - INST(Maskmovq , ExtRm_ZDI , O(000F00,F7,_,_,_,_,_,_ ), 0 , 4 , 0 , 9113 , 114, 80 ), // #405 - INST(Maxpd , ExtRm , O(660F00,5F,_,_,_,_,_,_ ), 0 , 3 , 0 , 7053 , 5 , 4 ), // #406 - INST(Maxps , ExtRm , O(000F00,5F,_,_,_,_,_,_ ), 0 , 4 , 0 , 7067 , 5 , 5 ), // #407 - INST(Maxsd , ExtRm , O(F20F00,5F,_,_,_,_,_,_ ), 0 , 5 , 0 , 9132 , 6 , 4 ), // #408 - INST(Maxss , ExtRm , O(F30F00,5F,_,_,_,_,_,_ ), 0 , 6 , 0 , 7088 , 7 , 5 ), // #409 - INST(Mcommit , X86Op , O(F30F01,FA,_,_,_,_,_,_ ), 0 , 25 , 0 , 1933 , 30 , 81 ), // #410 - INST(Mfence , X86Fence , O(000F00,AE,6,_,_,_,_,_ ), 0 , 80 , 0 , 1941 , 30 , 4 ), // #411 - INST(Minpd , ExtRm , O(660F00,5D,_,_,_,_,_,_ ), 0 , 3 , 0 , 7117 , 5 , 4 ), // #412 - INST(Minps , ExtRm , O(000F00,5D,_,_,_,_,_,_ ), 0 , 4 , 0 , 7131 , 5 , 5 ), // #413 - INST(Minsd , ExtRm , O(F20F00,5D,_,_,_,_,_,_ ), 0 , 5 , 0 , 9196 , 6 , 4 ), // #414 - INST(Minss , ExtRm , O(F30F00,5D,_,_,_,_,_,_ ), 0 , 6 , 0 , 7152 , 7 , 5 ), // #415 - INST(Monitor , X86Op , O(000F01,C8,_,_,_,_,_,_ ), 0 , 21 , 0 , 3232 , 115, 82 ), // #416 - INST(Monitorx , X86Op , O(000F01,FA,_,_,_,_,_,_ ), 0 , 21 , 0 , 1948 , 115, 83 ), // #417 - INST(Mov , X86Mov , 0 , 0 , 0 , 0 , 138 , 116, 84 ), // #418 - INST(Movabs , X86Movabs , 0 , 0 , 0 , 0 , 1957 , 117, 0 ), // #419 - INST(Movapd , ExtMov , O(660F00,28,_,_,_,_,_,_ ), O(660F00,29,_,_,_,_,_,_ ), 3 , 45 , 7183 , 118, 85 ), // #420 - INST(Movaps , ExtMov , O(000F00,28,_,_,_,_,_,_ ), O(000F00,29,_,_,_,_,_,_ ), 4 , 46 , 7191 , 118, 86 ), // #421 - INST(Movbe , ExtMovbe , O(000F38,F0,_,_,x,_,_,_ ), O(000F38,F1,_,_,x,_,_,_ ), 83 , 47 , 656 , 119, 87 ), // #422 - INST(Movd , ExtMovd , O(000F00,6E,_,_,_,_,_,_ ), O(000F00,7E,_,_,_,_,_,_ ), 4 , 48 , 9106 , 120, 88 ), // #423 - INST(Movddup , ExtMov , O(F20F00,12,_,_,_,_,_,_ ), 0 , 5 , 0 , 7205 , 6 , 6 ), // #424 - INST(Movdir64b , X86EnqcmdMovdir64b , O(660F38,F8,_,_,_,_,_,_ ), 0 , 2 , 0 , 1964 , 121, 89 ), // #425 - INST(Movdiri , X86MovntiMovdiri , O(000F38,F9,_,_,_,_,_,_ ), 0 , 83 , 0 , 1974 , 122, 90 ), // #426 - INST(Movdq2q , ExtMov , O(F20F00,D6,_,_,_,_,_,_ ), 0 , 5 , 0 , 1982 , 123, 4 ), // #427 - INST(Movdqa , ExtMov , O(660F00,6F,_,_,_,_,_,_ ), O(660F00,7F,_,_,_,_,_,_ ), 3 , 49 , 7214 , 118, 85 ), // #428 - INST(Movdqu , ExtMov , O(F30F00,6F,_,_,_,_,_,_ ), O(F30F00,7F,_,_,_,_,_,_ ), 6 , 50 , 7023 , 118, 85 ), // #429 - INST(Movhlps , ExtMov , O(000F00,12,_,_,_,_,_,_ ), 0 , 4 , 0 , 7289 , 124, 5 ), // #430 - INST(Movhpd , ExtMov , O(660F00,16,_,_,_,_,_,_ ), O(660F00,17,_,_,_,_,_,_ ), 3 , 51 , 7298 , 125, 4 ), // #431 - INST(Movhps , ExtMov , O(000F00,16,_,_,_,_,_,_ ), O(000F00,17,_,_,_,_,_,_ ), 4 , 52 , 7306 , 125, 5 ), // #432 - INST(Movlhps , ExtMov , O(000F00,16,_,_,_,_,_,_ ), 0 , 4 , 0 , 7314 , 124, 5 ), // #433 - INST(Movlpd , ExtMov , O(660F00,12,_,_,_,_,_,_ ), O(660F00,13,_,_,_,_,_,_ ), 3 , 53 , 7323 , 125, 4 ), // #434 - INST(Movlps , ExtMov , O(000F00,12,_,_,_,_,_,_ ), O(000F00,13,_,_,_,_,_,_ ), 4 , 54 , 7331 , 125, 5 ), // #435 - INST(Movmskpd , ExtMov , O(660F00,50,_,_,_,_,_,_ ), 0 , 3 , 0 , 7339 , 126, 4 ), // #436 - INST(Movmskps , ExtMov , O(000F00,50,_,_,_,_,_,_ ), 0 , 4 , 0 , 7349 , 126, 5 ), // #437 - INST(Movntdq , ExtMov , 0 , O(660F00,E7,_,_,_,_,_,_ ), 0 , 55 , 7359 , 127, 4 ), // #438 - INST(Movntdqa , ExtMov , O(660F38,2A,_,_,_,_,_,_ ), 0 , 2 , 0 , 7368 , 100, 12 ), // #439 - INST(Movnti , X86MovntiMovdiri , O(000F00,C3,_,_,x,_,_,_ ), 0 , 4 , 0 , 1990 , 122, 4 ), // #440 - INST(Movntpd , ExtMov , 0 , O(660F00,2B,_,_,_,_,_,_ ), 0 , 56 , 7378 , 127, 4 ), // #441 - INST(Movntps , ExtMov , 0 , O(000F00,2B,_,_,_,_,_,_ ), 0 , 57 , 7387 , 127, 5 ), // #442 - INST(Movntq , ExtMov , 0 , O(000F00,E7,_,_,_,_,_,_ ), 0 , 58 , 1997 , 128, 80 ), // #443 - INST(Movntsd , ExtMov , 0 , O(F20F00,2B,_,_,_,_,_,_ ), 0 , 59 , 2004 , 129, 49 ), // #444 - INST(Movntss , ExtMov , 0 , O(F30F00,2B,_,_,_,_,_,_ ), 0 , 60 , 2012 , 130, 49 ), // #445 - INST(Movq , ExtMovq , O(000F00,6E,_,_,x,_,_,_ ), O(000F00,7E,_,_,x,_,_,_ ), 4 , 48 , 9117 , 131, 91 ), // #446 - INST(Movq2dq , ExtRm , O(F30F00,D6,_,_,_,_,_,_ ), 0 , 6 , 0 , 2020 , 132, 4 ), // #447 - INST(Movs , X86StrMm , O(000000,A4,_,_,_,_,_,_ ), 0 , 0 , 0 , 439 , 133, 78 ), // #448 - INST(Movsd , ExtMov , O(F20F00,10,_,_,_,_,_,_ ), O(F20F00,11,_,_,_,_,_,_ ), 5 , 61 , 7402 , 134, 85 ), // #449 - INST(Movshdup , ExtRm , O(F30F00,16,_,_,_,_,_,_ ), 0 , 6 , 0 , 7416 , 5 , 6 ), // #450 - INST(Movsldup , ExtRm , O(F30F00,12,_,_,_,_,_,_ ), 0 , 6 , 0 , 7426 , 5 , 6 ), // #451 - INST(Movss , ExtMov , O(F30F00,10,_,_,_,_,_,_ ), O(F30F00,11,_,_,_,_,_,_ ), 6 , 62 , 7436 , 135, 86 ), // #452 - INST(Movsx , X86MovsxMovzx , O(000F00,BE,_,_,x,_,_,_ ), 0 , 4 , 0 , 2028 , 136, 0 ), // #453 - INST(Movsxd , X86Rm , O(000000,63,_,_,x,_,_,_ ), 0 , 0 , 0 , 2034 , 137, 0 ), // #454 - INST(Movupd , ExtMov , O(660F00,10,_,_,_,_,_,_ ), O(660F00,11,_,_,_,_,_,_ ), 3 , 63 , 7443 , 118, 85 ), // #455 - INST(Movups , ExtMov , O(000F00,10,_,_,_,_,_,_ ), O(000F00,11,_,_,_,_,_,_ ), 4 , 64 , 7451 , 118, 86 ), // #456 - INST(Movzx , X86MovsxMovzx , O(000F00,B6,_,_,x,_,_,_ ), 0 , 4 , 0 , 2041 , 136, 0 ), // #457 - INST(Mpsadbw , ExtRmi , O(660F3A,42,_,_,_,_,_,_ ), 0 , 8 , 0 , 7465 , 8 , 12 ), // #458 - INST(Mul , X86M_GPB_MulDiv , O(000000,F6,4,_,x,_,_,_ ), 0 , 9 , 0 , 828 , 54 , 1 ), // #459 - INST(Mulpd , ExtRm , O(660F00,59,_,_,_,_,_,_ ), 0 , 3 , 0 , 7519 , 5 , 4 ), // #460 - INST(Mulps , ExtRm , O(000F00,59,_,_,_,_,_,_ ), 0 , 4 , 0 , 7533 , 5 , 5 ), // #461 - INST(Mulsd , ExtRm , O(F20F00,59,_,_,_,_,_,_ ), 0 , 5 , 0 , 7540 , 6 , 4 ), // #462 - INST(Mulss , ExtRm , O(F30F00,59,_,_,_,_,_,_ ), 0 , 6 , 0 , 7554 , 7 , 5 ), // #463 - INST(Mulx , VexRvm_ZDX_Wx , V(F20F38,F6,_,0,x,_,_,_ ), 0 , 84 , 0 , 2047 , 138, 92 ), // #464 - INST(Mwait , X86Op , O(000F01,C9,_,_,_,_,_,_ ), 0 , 21 , 0 , 3241 , 139, 82 ), // #465 - INST(Mwaitx , X86Op , O(000F01,FB,_,_,_,_,_,_ ), 0 , 21 , 0 , 2052 , 140, 83 ), // #466 - INST(Neg , X86M_GPB , O(000000,F6,3,_,x,_,_,_ ), 0 , 75 , 0 , 2059 , 141, 1 ), // #467 - INST(Nop , X86M_Nop , O(000000,90,_,_,_,_,_,_ ), 0 , 0 , 0 , 959 , 142, 0 ), // #468 - INST(Not , X86M_GPB , O(000000,F6,2,_,x,_,_,_ ), 0 , 1 , 0 , 2063 , 141, 0 ), // #469 - INST(Or , X86Arith , O(000000,08,1,_,x,_,_,_ ), 0 , 31 , 0 , 3237 , 143, 1 ), // #470 - INST(Orpd , ExtRm , O(660F00,56,_,_,_,_,_,_ ), 0 , 3 , 0 , 11458, 11 , 4 ), // #471 - INST(Orps , ExtRm , O(000F00,56,_,_,_,_,_,_ ), 0 , 4 , 0 , 11465, 11 , 5 ), // #472 - INST(Out , X86Out , O(000000,EE,_,_,_,_,_,_ ), O(000000,E6,_,_,_,_,_,_ ), 0 , 65 , 2067 , 144, 0 ), // #473 - INST(Outs , X86Outs , O(000000,6E,_,_,_,_,_,_ ), 0 , 0 , 0 , 2071 , 145, 0 ), // #474 - INST(Pabsb , ExtRm_P , O(000F38,1C,_,_,_,_,_,_ ), 0 , 83 , 0 , 7636 , 146, 93 ), // #475 - INST(Pabsd , ExtRm_P , O(000F38,1E,_,_,_,_,_,_ ), 0 , 83 , 0 , 7643 , 146, 93 ), // #476 - INST(Pabsw , ExtRm_P , O(000F38,1D,_,_,_,_,_,_ ), 0 , 83 , 0 , 7657 , 146, 93 ), // #477 - INST(Packssdw , ExtRm_P , O(000F00,6B,_,_,_,_,_,_ ), 0 , 4 , 0 , 7664 , 146, 88 ), // #478 - INST(Packsswb , ExtRm_P , O(000F00,63,_,_,_,_,_,_ ), 0 , 4 , 0 , 7674 , 146, 88 ), // #479 - INST(Packusdw , ExtRm , O(660F38,2B,_,_,_,_,_,_ ), 0 , 2 , 0 , 7684 , 5 , 12 ), // #480 - INST(Packuswb , ExtRm_P , O(000F00,67,_,_,_,_,_,_ ), 0 , 4 , 0 , 7694 , 146, 88 ), // #481 - INST(Paddb , ExtRm_P , O(000F00,FC,_,_,_,_,_,_ ), 0 , 4 , 0 , 7704 , 146, 88 ), // #482 - INST(Paddd , ExtRm_P , O(000F00,FE,_,_,_,_,_,_ ), 0 , 4 , 0 , 7711 , 146, 88 ), // #483 - INST(Paddq , ExtRm_P , O(000F00,D4,_,_,_,_,_,_ ), 0 , 4 , 0 , 7718 , 146, 4 ), // #484 - INST(Paddsb , ExtRm_P , O(000F00,EC,_,_,_,_,_,_ ), 0 , 4 , 0 , 7725 , 146, 88 ), // #485 - INST(Paddsw , ExtRm_P , O(000F00,ED,_,_,_,_,_,_ ), 0 , 4 , 0 , 7733 , 146, 88 ), // #486 - INST(Paddusb , ExtRm_P , O(000F00,DC,_,_,_,_,_,_ ), 0 , 4 , 0 , 7741 , 146, 88 ), // #487 - INST(Paddusw , ExtRm_P , O(000F00,DD,_,_,_,_,_,_ ), 0 , 4 , 0 , 7750 , 146, 88 ), // #488 - INST(Paddw , ExtRm_P , O(000F00,FD,_,_,_,_,_,_ ), 0 , 4 , 0 , 7759 , 146, 88 ), // #489 - INST(Palignr , ExtRmi_P , O(000F3A,0F,_,_,_,_,_,_ ), 0 , 85 , 0 , 7766 , 147, 6 ), // #490 - INST(Pand , ExtRm_P , O(000F00,DB,_,_,_,_,_,_ ), 0 , 4 , 0 , 7775 , 148, 88 ), // #491 - INST(Pandn , ExtRm_P , O(000F00,DF,_,_,_,_,_,_ ), 0 , 4 , 0 , 7788 , 149, 88 ), // #492 - INST(Pause , X86Op , O(F30000,90,_,_,_,_,_,_ ), 0 , 86 , 0 , 3195 , 30 , 0 ), // #493 - INST(Pavgb , ExtRm_P , O(000F00,E0,_,_,_,_,_,_ ), 0 , 4 , 0 , 7818 , 146, 94 ), // #494 - INST(Pavgusb , Ext3dNow , O(000F0F,BF,_,_,_,_,_,_ ), 0 , 87 , 0 , 2076 , 150, 51 ), // #495 - INST(Pavgw , ExtRm_P , O(000F00,E3,_,_,_,_,_,_ ), 0 , 4 , 0 , 7825 , 146, 94 ), // #496 - INST(Pblendvb , ExtRm_XMM0 , O(660F38,10,_,_,_,_,_,_ ), 0 , 2 , 0 , 7881 , 15 , 12 ), // #497 - INST(Pblendw , ExtRmi , O(660F3A,0E,_,_,_,_,_,_ ), 0 , 8 , 0 , 7891 , 8 , 12 ), // #498 - INST(Pclmulqdq , ExtRmi , O(660F3A,44,_,_,_,_,_,_ ), 0 , 8 , 0 , 7984 , 8 , 95 ), // #499 - INST(Pcmpeqb , ExtRm_P , O(000F00,74,_,_,_,_,_,_ ), 0 , 4 , 0 , 8016 , 149, 88 ), // #500 - INST(Pcmpeqd , ExtRm_P , O(000F00,76,_,_,_,_,_,_ ), 0 , 4 , 0 , 8025 , 149, 88 ), // #501 - INST(Pcmpeqq , ExtRm , O(660F38,29,_,_,_,_,_,_ ), 0 , 2 , 0 , 8034 , 151, 12 ), // #502 - INST(Pcmpeqw , ExtRm_P , O(000F00,75,_,_,_,_,_,_ ), 0 , 4 , 0 , 8043 , 149, 88 ), // #503 - INST(Pcmpestri , ExtRmi , O(660F3A,61,_,_,_,_,_,_ ), 0 , 8 , 0 , 8052 , 152, 96 ), // #504 - INST(Pcmpestrm , ExtRmi , O(660F3A,60,_,_,_,_,_,_ ), 0 , 8 , 0 , 8063 , 153, 96 ), // #505 - INST(Pcmpgtb , ExtRm_P , O(000F00,64,_,_,_,_,_,_ ), 0 , 4 , 0 , 8074 , 149, 88 ), // #506 - INST(Pcmpgtd , ExtRm_P , O(000F00,66,_,_,_,_,_,_ ), 0 , 4 , 0 , 8083 , 149, 88 ), // #507 - INST(Pcmpgtq , ExtRm , O(660F38,37,_,_,_,_,_,_ ), 0 , 2 , 0 , 8092 , 151, 44 ), // #508 - INST(Pcmpgtw , ExtRm_P , O(000F00,65,_,_,_,_,_,_ ), 0 , 4 , 0 , 8101 , 149, 88 ), // #509 - INST(Pcmpistri , ExtRmi , O(660F3A,63,_,_,_,_,_,_ ), 0 , 8 , 0 , 8110 , 154, 96 ), // #510 - INST(Pcmpistrm , ExtRmi , O(660F3A,62,_,_,_,_,_,_ ), 0 , 8 , 0 , 8121 , 155, 96 ), // #511 - INST(Pconfig , X86Op , O(000F01,C5,_,_,_,_,_,_ ), 0 , 21 , 0 , 2084 , 30 , 97 ), // #512 - INST(Pdep , VexRvm_Wx , V(F20F38,F5,_,0,x,_,_,_ ), 0 , 84 , 0 , 2092 , 10 , 92 ), // #513 - INST(Pext , VexRvm_Wx , V(F30F38,F5,_,0,x,_,_,_ ), 0 , 88 , 0 , 2097 , 10 , 92 ), // #514 - INST(Pextrb , ExtExtract , O(000F3A,14,_,_,_,_,_,_ ), 0 , 85 , 0 , 8608 , 156, 12 ), // #515 - INST(Pextrd , ExtExtract , O(000F3A,16,_,_,_,_,_,_ ), 0 , 85 , 0 , 8616 , 58 , 12 ), // #516 - INST(Pextrq , ExtExtract , O(000F3A,16,_,_,1,_,_,_ ), 0 , 89 , 0 , 8624 , 157, 12 ), // #517 - INST(Pextrw , ExtPextrw , O(000F00,C5,_,_,_,_,_,_ ), O(000F3A,15,_,_,_,_,_,_ ), 4 , 66 , 8632 , 158, 98 ), // #518 - INST(Pf2id , Ext3dNow , O(000F0F,1D,_,_,_,_,_,_ ), 0 , 87 , 0 , 2102 , 150, 51 ), // #519 - INST(Pf2iw , Ext3dNow , O(000F0F,1C,_,_,_,_,_,_ ), 0 , 87 , 0 , 2108 , 150, 99 ), // #520 - INST(Pfacc , Ext3dNow , O(000F0F,AE,_,_,_,_,_,_ ), 0 , 87 , 0 , 2114 , 150, 51 ), // #521 - INST(Pfadd , Ext3dNow , O(000F0F,9E,_,_,_,_,_,_ ), 0 , 87 , 0 , 2120 , 150, 51 ), // #522 - INST(Pfcmpeq , Ext3dNow , O(000F0F,B0,_,_,_,_,_,_ ), 0 , 87 , 0 , 2126 , 150, 51 ), // #523 - INST(Pfcmpge , Ext3dNow , O(000F0F,90,_,_,_,_,_,_ ), 0 , 87 , 0 , 2134 , 150, 51 ), // #524 - INST(Pfcmpgt , Ext3dNow , O(000F0F,A0,_,_,_,_,_,_ ), 0 , 87 , 0 , 2142 , 150, 51 ), // #525 - INST(Pfmax , Ext3dNow , O(000F0F,A4,_,_,_,_,_,_ ), 0 , 87 , 0 , 2150 , 150, 51 ), // #526 - INST(Pfmin , Ext3dNow , O(000F0F,94,_,_,_,_,_,_ ), 0 , 87 , 0 , 2156 , 150, 51 ), // #527 - INST(Pfmul , Ext3dNow , O(000F0F,B4,_,_,_,_,_,_ ), 0 , 87 , 0 , 2162 , 150, 51 ), // #528 - INST(Pfnacc , Ext3dNow , O(000F0F,8A,_,_,_,_,_,_ ), 0 , 87 , 0 , 2168 , 150, 99 ), // #529 - INST(Pfpnacc , Ext3dNow , O(000F0F,8E,_,_,_,_,_,_ ), 0 , 87 , 0 , 2175 , 150, 99 ), // #530 - INST(Pfrcp , Ext3dNow , O(000F0F,96,_,_,_,_,_,_ ), 0 , 87 , 0 , 2183 , 150, 51 ), // #531 - INST(Pfrcpit1 , Ext3dNow , O(000F0F,A6,_,_,_,_,_,_ ), 0 , 87 , 0 , 2189 , 150, 51 ), // #532 - INST(Pfrcpit2 , Ext3dNow , O(000F0F,B6,_,_,_,_,_,_ ), 0 , 87 , 0 , 2198 , 150, 51 ), // #533 - INST(Pfrcpv , Ext3dNow , O(000F0F,86,_,_,_,_,_,_ ), 0 , 87 , 0 , 2207 , 150, 100), // #534 - INST(Pfrsqit1 , Ext3dNow , O(000F0F,A7,_,_,_,_,_,_ ), 0 , 87 , 0 , 2214 , 150, 51 ), // #535 - INST(Pfrsqrt , Ext3dNow , O(000F0F,97,_,_,_,_,_,_ ), 0 , 87 , 0 , 2223 , 150, 51 ), // #536 - INST(Pfrsqrtv , Ext3dNow , O(000F0F,87,_,_,_,_,_,_ ), 0 , 87 , 0 , 2231 , 150, 100), // #537 - INST(Pfsub , Ext3dNow , O(000F0F,9A,_,_,_,_,_,_ ), 0 , 87 , 0 , 2240 , 150, 51 ), // #538 - INST(Pfsubr , Ext3dNow , O(000F0F,AA,_,_,_,_,_,_ ), 0 , 87 , 0 , 2246 , 150, 51 ), // #539 - INST(Phaddd , ExtRm_P , O(000F38,02,_,_,_,_,_,_ ), 0 , 83 , 0 , 8711 , 146, 93 ), // #540 - INST(Phaddsw , ExtRm_P , O(000F38,03,_,_,_,_,_,_ ), 0 , 83 , 0 , 8728 , 146, 93 ), // #541 - INST(Phaddw , ExtRm_P , O(000F38,01,_,_,_,_,_,_ ), 0 , 83 , 0 , 8797 , 146, 93 ), // #542 - INST(Phminposuw , ExtRm , O(660F38,41,_,_,_,_,_,_ ), 0 , 2 , 0 , 8823 , 5 , 12 ), // #543 - INST(Phsubd , ExtRm_P , O(000F38,06,_,_,_,_,_,_ ), 0 , 83 , 0 , 8844 , 146, 93 ), // #544 - INST(Phsubsw , ExtRm_P , O(000F38,07,_,_,_,_,_,_ ), 0 , 83 , 0 , 8861 , 146, 93 ), // #545 - INST(Phsubw , ExtRm_P , O(000F38,05,_,_,_,_,_,_ ), 0 , 83 , 0 , 8870 , 146, 93 ), // #546 - INST(Pi2fd , Ext3dNow , O(000F0F,0D,_,_,_,_,_,_ ), 0 , 87 , 0 , 2253 , 150, 51 ), // #547 - INST(Pi2fw , Ext3dNow , O(000F0F,0C,_,_,_,_,_,_ ), 0 , 87 , 0 , 2259 , 150, 99 ), // #548 - INST(Pinsrb , ExtRmi , O(660F3A,20,_,_,_,_,_,_ ), 0 , 8 , 0 , 8887 , 159, 12 ), // #549 - INST(Pinsrd , ExtRmi , O(660F3A,22,_,_,_,_,_,_ ), 0 , 8 , 0 , 8895 , 160, 12 ), // #550 - INST(Pinsrq , ExtRmi , O(660F3A,22,_,_,1,_,_,_ ), 0 , 90 , 0 , 8903 , 161, 12 ), // #551 - INST(Pinsrw , ExtRmi_P , O(000F00,C4,_,_,_,_,_,_ ), 0 , 4 , 0 , 8911 , 162, 94 ), // #552 - INST(Pmaddubsw , ExtRm_P , O(000F38,04,_,_,_,_,_,_ ), 0 , 83 , 0 , 9081 , 146, 93 ), // #553 - INST(Pmaddwd , ExtRm_P , O(000F00,F5,_,_,_,_,_,_ ), 0 , 4 , 0 , 9092 , 146, 88 ), // #554 - INST(Pmaxsb , ExtRm , O(660F38,3C,_,_,_,_,_,_ ), 0 , 2 , 0 , 9123 , 11 , 12 ), // #555 - INST(Pmaxsd , ExtRm , O(660F38,3D,_,_,_,_,_,_ ), 0 , 2 , 0 , 9131 , 11 , 12 ), // #556 - INST(Pmaxsw , ExtRm_P , O(000F00,EE,_,_,_,_,_,_ ), 0 , 4 , 0 , 9147 , 148, 94 ), // #557 - INST(Pmaxub , ExtRm_P , O(000F00,DE,_,_,_,_,_,_ ), 0 , 4 , 0 , 9155 , 148, 94 ), // #558 - INST(Pmaxud , ExtRm , O(660F38,3F,_,_,_,_,_,_ ), 0 , 2 , 0 , 9163 , 11 , 12 ), // #559 - INST(Pmaxuw , ExtRm , O(660F38,3E,_,_,_,_,_,_ ), 0 , 2 , 0 , 9179 , 11 , 12 ), // #560 - INST(Pminsb , ExtRm , O(660F38,38,_,_,_,_,_,_ ), 0 , 2 , 0 , 9187 , 11 , 12 ), // #561 - INST(Pminsd , ExtRm , O(660F38,39,_,_,_,_,_,_ ), 0 , 2 , 0 , 9195 , 11 , 12 ), // #562 - INST(Pminsw , ExtRm_P , O(000F00,EA,_,_,_,_,_,_ ), 0 , 4 , 0 , 9211 , 148, 94 ), // #563 - INST(Pminub , ExtRm_P , O(000F00,DA,_,_,_,_,_,_ ), 0 , 4 , 0 , 9219 , 148, 94 ), // #564 - INST(Pminud , ExtRm , O(660F38,3B,_,_,_,_,_,_ ), 0 , 2 , 0 , 9227 , 11 , 12 ), // #565 - INST(Pminuw , ExtRm , O(660F38,3A,_,_,_,_,_,_ ), 0 , 2 , 0 , 9243 , 11 , 12 ), // #566 - INST(Pmovmskb , ExtRm_P , O(000F00,D7,_,_,_,_,_,_ ), 0 , 4 , 0 , 9321 , 163, 94 ), // #567 - INST(Pmovsxbd , ExtRm , O(660F38,21,_,_,_,_,_,_ ), 0 , 2 , 0 , 9418 , 7 , 12 ), // #568 - INST(Pmovsxbq , ExtRm , O(660F38,22,_,_,_,_,_,_ ), 0 , 2 , 0 , 9428 , 164, 12 ), // #569 - INST(Pmovsxbw , ExtRm , O(660F38,20,_,_,_,_,_,_ ), 0 , 2 , 0 , 9438 , 6 , 12 ), // #570 - INST(Pmovsxdq , ExtRm , O(660F38,25,_,_,_,_,_,_ ), 0 , 2 , 0 , 9448 , 6 , 12 ), // #571 - INST(Pmovsxwd , ExtRm , O(660F38,23,_,_,_,_,_,_ ), 0 , 2 , 0 , 9458 , 6 , 12 ), // #572 - INST(Pmovsxwq , ExtRm , O(660F38,24,_,_,_,_,_,_ ), 0 , 2 , 0 , 9468 , 7 , 12 ), // #573 - INST(Pmovzxbd , ExtRm , O(660F38,31,_,_,_,_,_,_ ), 0 , 2 , 0 , 9555 , 7 , 12 ), // #574 - INST(Pmovzxbq , ExtRm , O(660F38,32,_,_,_,_,_,_ ), 0 , 2 , 0 , 9565 , 164, 12 ), // #575 - INST(Pmovzxbw , ExtRm , O(660F38,30,_,_,_,_,_,_ ), 0 , 2 , 0 , 9575 , 6 , 12 ), // #576 - INST(Pmovzxdq , ExtRm , O(660F38,35,_,_,_,_,_,_ ), 0 , 2 , 0 , 9585 , 6 , 12 ), // #577 - INST(Pmovzxwd , ExtRm , O(660F38,33,_,_,_,_,_,_ ), 0 , 2 , 0 , 9595 , 6 , 12 ), // #578 - INST(Pmovzxwq , ExtRm , O(660F38,34,_,_,_,_,_,_ ), 0 , 2 , 0 , 9605 , 7 , 12 ), // #579 - INST(Pmuldq , ExtRm , O(660F38,28,_,_,_,_,_,_ ), 0 , 2 , 0 , 9615 , 5 , 12 ), // #580 - INST(Pmulhrsw , ExtRm_P , O(000F38,0B,_,_,_,_,_,_ ), 0 , 83 , 0 , 9623 , 146, 93 ), // #581 - INST(Pmulhrw , Ext3dNow , O(000F0F,B7,_,_,_,_,_,_ ), 0 , 87 , 0 , 2265 , 150, 51 ), // #582 - INST(Pmulhuw , ExtRm_P , O(000F00,E4,_,_,_,_,_,_ ), 0 , 4 , 0 , 9633 , 146, 94 ), // #583 - INST(Pmulhw , ExtRm_P , O(000F00,E5,_,_,_,_,_,_ ), 0 , 4 , 0 , 9642 , 146, 88 ), // #584 - INST(Pmulld , ExtRm , O(660F38,40,_,_,_,_,_,_ ), 0 , 2 , 0 , 9650 , 5 , 12 ), // #585 - INST(Pmullw , ExtRm_P , O(000F00,D5,_,_,_,_,_,_ ), 0 , 4 , 0 , 9666 , 146, 88 ), // #586 - INST(Pmuludq , ExtRm_P , O(000F00,F4,_,_,_,_,_,_ ), 0 , 4 , 0 , 9689 , 146, 4 ), // #587 - INST(Pop , X86Pop , O(000000,8F,0,_,_,_,_,_ ), O(000000,58,_,_,_,_,_,_ ), 0 , 67 , 2273 , 165, 0 ), // #588 - INST(Popa , X86Op , O(660000,61,_,_,_,_,_,_ ), 0 , 19 , 0 , 2277 , 81 , 0 ), // #589 - INST(Popad , X86Op , O(000000,61,_,_,_,_,_,_ ), 0 , 0 , 0 , 2282 , 81 , 0 ), // #590 - INST(Popcnt , X86Rm_Raw66H , O(F30F00,B8,_,_,x,_,_,_ ), 0 , 6 , 0 , 2288 , 22 , 101), // #591 - INST(Popf , X86Op , O(660000,9D,_,_,_,_,_,_ ), 0 , 19 , 0 , 2295 , 30 , 102), // #592 - INST(Popfd , X86Op , O(000000,9D,_,_,_,_,_,_ ), 0 , 0 , 0 , 2300 , 81 , 102), // #593 - INST(Popfq , X86Op , O(000000,9D,_,_,_,_,_,_ ), 0 , 0 , 0 , 2306 , 33 , 102), // #594 - INST(Por , ExtRm_P , O(000F00,EB,_,_,_,_,_,_ ), 0 , 4 , 0 , 9734 , 148, 88 ), // #595 - INST(Prefetch , X86M_Only , O(000F00,0D,0,_,_,_,_,_ ), 0 , 4 , 0 , 2312 , 31 , 51 ), // #596 - INST(Prefetchnta , X86M_Only , O(000F00,18,0,_,_,_,_,_ ), 0 , 4 , 0 , 2321 , 31 , 80 ), // #597 - INST(Prefetcht0 , X86M_Only , O(000F00,18,1,_,_,_,_,_ ), 0 , 29 , 0 , 2333 , 31 , 80 ), // #598 - INST(Prefetcht1 , X86M_Only , O(000F00,18,2,_,_,_,_,_ ), 0 , 76 , 0 , 2344 , 31 , 80 ), // #599 - INST(Prefetcht2 , X86M_Only , O(000F00,18,3,_,_,_,_,_ ), 0 , 78 , 0 , 2355 , 31 , 80 ), // #600 - INST(Prefetchw , X86M_Only , O(000F00,0D,1,_,_,_,_,_ ), 0 , 29 , 0 , 2366 , 31 , 103), // #601 - INST(Prefetchwt1 , X86M_Only , O(000F00,0D,2,_,_,_,_,_ ), 0 , 76 , 0 , 2376 , 31 , 104), // #602 - INST(Psadbw , ExtRm_P , O(000F00,F6,_,_,_,_,_,_ ), 0 , 4 , 0 , 4644 , 146, 94 ), // #603 - INST(Pshufb , ExtRm_P , O(000F38,00,_,_,_,_,_,_ ), 0 , 83 , 0 , 10060, 146, 93 ), // #604 - INST(Pshufd , ExtRmi , O(660F00,70,_,_,_,_,_,_ ), 0 , 3 , 0 , 10081, 8 , 4 ), // #605 - INST(Pshufhw , ExtRmi , O(F30F00,70,_,_,_,_,_,_ ), 0 , 6 , 0 , 10089, 8 , 4 ), // #606 - INST(Pshuflw , ExtRmi , O(F20F00,70,_,_,_,_,_,_ ), 0 , 5 , 0 , 10098, 8 , 4 ), // #607 - INST(Pshufw , ExtRmi_P , O(000F00,70,_,_,_,_,_,_ ), 0 , 4 , 0 , 2388 , 166, 80 ), // #608 - INST(Psignb , ExtRm_P , O(000F38,08,_,_,_,_,_,_ ), 0 , 83 , 0 , 10107, 146, 93 ), // #609 - INST(Psignd , ExtRm_P , O(000F38,0A,_,_,_,_,_,_ ), 0 , 83 , 0 , 10115, 146, 93 ), // #610 - INST(Psignw , ExtRm_P , O(000F38,09,_,_,_,_,_,_ ), 0 , 83 , 0 , 10123, 146, 93 ), // #611 - INST(Pslld , ExtRmRi_P , O(000F00,F2,_,_,_,_,_,_ ), O(000F00,72,6,_,_,_,_,_ ), 4 , 68 , 10131, 167, 88 ), // #612 - INST(Pslldq , ExtRmRi , 0 , O(660F00,73,7,_,_,_,_,_ ), 0 , 69 , 10138, 168, 4 ), // #613 - INST(Psllq , ExtRmRi_P , O(000F00,F3,_,_,_,_,_,_ ), O(000F00,73,6,_,_,_,_,_ ), 4 , 70 , 10146, 167, 88 ), // #614 - INST(Psllw , ExtRmRi_P , O(000F00,F1,_,_,_,_,_,_ ), O(000F00,71,6,_,_,_,_,_ ), 4 , 71 , 10177, 167, 88 ), // #615 - INST(Psmash , X86Op , O(F30F01,FF,_,_,_,_,_,_ ), 0 , 25 , 0 , 2395 , 33 , 105), // #616 - INST(Psrad , ExtRmRi_P , O(000F00,E2,_,_,_,_,_,_ ), O(000F00,72,4,_,_,_,_,_ ), 4 , 72 , 10184, 167, 88 ), // #617 - INST(Psraw , ExtRmRi_P , O(000F00,E1,_,_,_,_,_,_ ), O(000F00,71,4,_,_,_,_,_ ), 4 , 73 , 10222, 167, 88 ), // #618 - INST(Psrld , ExtRmRi_P , O(000F00,D2,_,_,_,_,_,_ ), O(000F00,72,2,_,_,_,_,_ ), 4 , 74 , 10229, 167, 88 ), // #619 - INST(Psrldq , ExtRmRi , 0 , O(660F00,73,3,_,_,_,_,_ ), 0 , 75 , 10236, 168, 4 ), // #620 - INST(Psrlq , ExtRmRi_P , O(000F00,D3,_,_,_,_,_,_ ), O(000F00,73,2,_,_,_,_,_ ), 4 , 76 , 10244, 167, 88 ), // #621 - INST(Psrlw , ExtRmRi_P , O(000F00,D1,_,_,_,_,_,_ ), O(000F00,71,2,_,_,_,_,_ ), 4 , 77 , 10275, 167, 88 ), // #622 - INST(Psubb , ExtRm_P , O(000F00,F8,_,_,_,_,_,_ ), 0 , 4 , 0 , 10282, 149, 88 ), // #623 - INST(Psubd , ExtRm_P , O(000F00,FA,_,_,_,_,_,_ ), 0 , 4 , 0 , 10289, 149, 88 ), // #624 - INST(Psubq , ExtRm_P , O(000F00,FB,_,_,_,_,_,_ ), 0 , 4 , 0 , 10296, 149, 4 ), // #625 - INST(Psubsb , ExtRm_P , O(000F00,E8,_,_,_,_,_,_ ), 0 , 4 , 0 , 10303, 149, 88 ), // #626 - INST(Psubsw , ExtRm_P , O(000F00,E9,_,_,_,_,_,_ ), 0 , 4 , 0 , 10311, 149, 88 ), // #627 - INST(Psubusb , ExtRm_P , O(000F00,D8,_,_,_,_,_,_ ), 0 , 4 , 0 , 10319, 149, 88 ), // #628 - INST(Psubusw , ExtRm_P , O(000F00,D9,_,_,_,_,_,_ ), 0 , 4 , 0 , 10328, 149, 88 ), // #629 - INST(Psubw , ExtRm_P , O(000F00,F9,_,_,_,_,_,_ ), 0 , 4 , 0 , 10337, 149, 88 ), // #630 - INST(Pswapd , Ext3dNow , O(000F0F,BB,_,_,_,_,_,_ ), 0 , 87 , 0 , 2402 , 150, 99 ), // #631 - INST(Ptest , ExtRm , O(660F38,17,_,_,_,_,_,_ ), 0 , 2 , 0 , 10366, 5 , 106), // #632 - INST(Ptwrite , X86M , O(F30F00,AE,4,_,_,_,_,_ ), 0 , 91 , 0 , 2409 , 169, 107), // #633 - INST(Punpckhbw , ExtRm_P , O(000F00,68,_,_,_,_,_,_ ), 0 , 4 , 0 , 10449, 146, 88 ), // #634 - INST(Punpckhdq , ExtRm_P , O(000F00,6A,_,_,_,_,_,_ ), 0 , 4 , 0 , 10460, 146, 88 ), // #635 - INST(Punpckhqdq , ExtRm , O(660F00,6D,_,_,_,_,_,_ ), 0 , 3 , 0 , 10471, 5 , 4 ), // #636 - INST(Punpckhwd , ExtRm_P , O(000F00,69,_,_,_,_,_,_ ), 0 , 4 , 0 , 10483, 146, 88 ), // #637 - INST(Punpcklbw , ExtRm_P , O(000F00,60,_,_,_,_,_,_ ), 0 , 4 , 0 , 10494, 170, 88 ), // #638 - INST(Punpckldq , ExtRm_P , O(000F00,62,_,_,_,_,_,_ ), 0 , 4 , 0 , 10505, 170, 88 ), // #639 - INST(Punpcklqdq , ExtRm , O(660F00,6C,_,_,_,_,_,_ ), 0 , 3 , 0 , 10516, 5 , 4 ), // #640 - INST(Punpcklwd , ExtRm_P , O(000F00,61,_,_,_,_,_,_ ), 0 , 4 , 0 , 10528, 170, 88 ), // #641 - INST(Push , X86Push , O(000000,FF,6,_,_,_,_,_ ), O(000000,50,_,_,_,_,_,_ ), 32 , 78 , 2417 , 171, 0 ), // #642 - INST(Pusha , X86Op , O(660000,60,_,_,_,_,_,_ ), 0 , 19 , 0 , 2422 , 81 , 0 ), // #643 - INST(Pushad , X86Op , O(000000,60,_,_,_,_,_,_ ), 0 , 0 , 0 , 2428 , 81 , 0 ), // #644 - INST(Pushf , X86Op , O(660000,9C,_,_,_,_,_,_ ), 0 , 19 , 0 , 2435 , 30 , 108), // #645 - INST(Pushfd , X86Op , O(000000,9C,_,_,_,_,_,_ ), 0 , 0 , 0 , 2441 , 81 , 108), // #646 - INST(Pushfq , X86Op , O(000000,9C,_,_,_,_,_,_ ), 0 , 0 , 0 , 2448 , 33 , 108), // #647 - INST(Pvalidate , X86Op , O(F20F01,FF,_,_,_,_,_,_ ), 0 , 92 , 0 , 2455 , 30 , 109), // #648 - INST(Pxor , ExtRm_P , O(000F00,EF,_,_,_,_,_,_ ), 0 , 4 , 0 , 10539, 149, 88 ), // #649 - INST(Rcl , X86Rot , O(000000,D0,2,_,x,_,_,_ ), 0 , 1 , 0 , 2465 , 172, 110), // #650 - INST(Rcpps , ExtRm , O(000F00,53,_,_,_,_,_,_ ), 0 , 4 , 0 , 10674, 5 , 5 ), // #651 - INST(Rcpss , ExtRm , O(F30F00,53,_,_,_,_,_,_ ), 0 , 6 , 0 , 10688, 7 , 5 ), // #652 - INST(Rcr , X86Rot , O(000000,D0,3,_,x,_,_,_ ), 0 , 75 , 0 , 2469 , 172, 110), // #653 - INST(Rdfsbase , X86M , O(F30F00,AE,0,_,x,_,_,_ ), 0 , 6 , 0 , 2473 , 173, 111), // #654 - INST(Rdgsbase , X86M , O(F30F00,AE,1,_,x,_,_,_ ), 0 , 93 , 0 , 2482 , 173, 111), // #655 - INST(Rdmsr , X86Op , O(000F00,32,_,_,_,_,_,_ ), 0 , 4 , 0 , 2491 , 174, 112), // #656 - INST(Rdpid , X86R_Native , O(F30F00,C7,7,_,_,_,_,_ ), 0 , 94 , 0 , 2497 , 175, 113), // #657 - INST(Rdpkru , X86Op , O(000F01,EE,_,_,_,_,_,_ ), 0 , 21 , 0 , 2503 , 174, 114), // #658 - INST(Rdpmc , X86Op , O(000F00,33,_,_,_,_,_,_ ), 0 , 4 , 0 , 2510 , 174, 0 ), // #659 - INST(Rdpru , X86Op , O(000F01,FD,_,_,_,_,_,_ ), 0 , 21 , 0 , 2516 , 174, 115), // #660 - INST(Rdrand , X86M , O(000F00,C7,6,_,x,_,_,_ ), 0 , 80 , 0 , 2522 , 23 , 116), // #661 - INST(Rdseed , X86M , O(000F00,C7,7,_,x,_,_,_ ), 0 , 22 , 0 , 2529 , 23 , 117), // #662 - INST(Rdsspd , X86M , O(F30F00,1E,1,_,_,_,_,_ ), 0 , 93 , 0 , 2536 , 76 , 56 ), // #663 - INST(Rdsspq , X86M , O(F30F00,1E,1,_,_,_,_,_ ), 0 , 93 , 0 , 2543 , 77 , 56 ), // #664 - INST(Rdtsc , X86Op , O(000F00,31,_,_,_,_,_,_ ), 0 , 4 , 0 , 2550 , 28 , 118), // #665 - INST(Rdtscp , X86Op , O(000F01,F9,_,_,_,_,_,_ ), 0 , 21 , 0 , 2556 , 174, 119), // #666 - INST(Ret , X86Ret , O(000000,C2,_,_,_,_,_,_ ), 0 , 0 , 0 , 3072 , 176, 0 ), // #667 - INST(Retf , X86Ret , O(000000,CA,_,_,x,_,_,_ ), 0 , 0 , 0 , 2563 , 177, 0 ), // #668 - INST(Rmpadjust , X86Op , O(F30F01,FE,_,_,_,_,_,_ ), 0 , 25 , 0 , 2568 , 33 , 105), // #669 - INST(Rmpupdate , X86Op , O(F20F01,FE,_,_,_,_,_,_ ), 0 , 92 , 0 , 2578 , 33 , 105), // #670 - INST(Rol , X86Rot , O(000000,D0,0,_,x,_,_,_ ), 0 , 0 , 0 , 2588 , 172, 120), // #671 - INST(Ror , X86Rot , O(000000,D0,1,_,x,_,_,_ ), 0 , 31 , 0 , 2592 , 172, 120), // #672 - INST(Rorx , VexRmi_Wx , V(F20F3A,F0,_,0,x,_,_,_ ), 0 , 95 , 0 , 2596 , 178, 92 ), // #673 - INST(Roundpd , ExtRmi , O(660F3A,09,_,_,_,_,_,_ ), 0 , 8 , 0 , 10827, 8 , 12 ), // #674 - INST(Roundps , ExtRmi , O(660F3A,08,_,_,_,_,_,_ ), 0 , 8 , 0 , 10836, 8 , 12 ), // #675 - INST(Roundsd , ExtRmi , O(660F3A,0B,_,_,_,_,_,_ ), 0 , 8 , 0 , 10845, 37 , 12 ), // #676 - INST(Roundss , ExtRmi , O(660F3A,0A,_,_,_,_,_,_ ), 0 , 8 , 0 , 10854, 38 , 12 ), // #677 - INST(Rsm , X86Op , O(000F00,AA,_,_,_,_,_,_ ), 0 , 4 , 0 , 2601 , 81 , 1 ), // #678 - INST(Rsqrtps , ExtRm , O(000F00,52,_,_,_,_,_,_ ), 0 , 4 , 0 , 10960, 5 , 5 ), // #679 - INST(Rsqrtss , ExtRm , O(F30F00,52,_,_,_,_,_,_ ), 0 , 6 , 0 , 10978, 7 , 5 ), // #680 - INST(Rstorssp , X86M_Only , O(F30F00,01,5,_,_,_,_,_ ), 0 , 63 , 0 , 2605 , 32 , 24 ), // #681 - INST(Sahf , X86Op , O(000000,9E,_,_,_,_,_,_ ), 0 , 0 , 0 , 2614 , 97 , 121), // #682 - INST(Sal , X86Rot , O(000000,D0,4,_,x,_,_,_ ), 0 , 9 , 0 , 2619 , 172, 1 ), // #683 - INST(Sar , X86Rot , O(000000,D0,7,_,x,_,_,_ ), 0 , 27 , 0 , 2623 , 172, 1 ), // #684 - INST(Sarx , VexRmv_Wx , V(F30F38,F7,_,0,x,_,_,_ ), 0 , 88 , 0 , 2627 , 13 , 92 ), // #685 - INST(Saveprevssp , X86Op , O(F30F01,EA,_,_,_,_,_,_ ), 0 , 25 , 0 , 2632 , 30 , 24 ), // #686 - INST(Sbb , X86Arith , O(000000,18,3,_,x,_,_,_ ), 0 , 75 , 0 , 2644 , 179, 2 ), // #687 - INST(Scas , X86StrRm , O(000000,AE,_,_,_,_,_,_ ), 0 , 0 , 0 , 2648 , 180, 37 ), // #688 - INST(Senduipi , X86M_NoSize , O(F30F00,C7,6,_,_,_,_,_ ), 0 , 24 , 0 , 2653 , 77 , 25 ), // #689 - INST(Serialize , X86Op , O(000F01,E8,_,_,_,_,_,_ ), 0 , 21 , 0 , 2662 , 30 , 122), // #690 - INST(Seta , X86Set , O(000F00,97,_,_,_,_,_,_ ), 0 , 4 , 0 , 2672 , 181, 59 ), // #691 - INST(Setae , X86Set , O(000F00,93,_,_,_,_,_,_ ), 0 , 4 , 0 , 2677 , 181, 60 ), // #692 - INST(Setb , X86Set , O(000F00,92,_,_,_,_,_,_ ), 0 , 4 , 0 , 2683 , 181, 60 ), // #693 - INST(Setbe , X86Set , O(000F00,96,_,_,_,_,_,_ ), 0 , 4 , 0 , 2688 , 181, 59 ), // #694 - INST(Setc , X86Set , O(000F00,92,_,_,_,_,_,_ ), 0 , 4 , 0 , 2694 , 181, 60 ), // #695 - INST(Sete , X86Set , O(000F00,94,_,_,_,_,_,_ ), 0 , 4 , 0 , 2699 , 181, 61 ), // #696 - INST(Setg , X86Set , O(000F00,9F,_,_,_,_,_,_ ), 0 , 4 , 0 , 2704 , 181, 62 ), // #697 - INST(Setge , X86Set , O(000F00,9D,_,_,_,_,_,_ ), 0 , 4 , 0 , 2709 , 181, 63 ), // #698 - INST(Setl , X86Set , O(000F00,9C,_,_,_,_,_,_ ), 0 , 4 , 0 , 2715 , 181, 63 ), // #699 - INST(Setle , X86Set , O(000F00,9E,_,_,_,_,_,_ ), 0 , 4 , 0 , 2720 , 181, 62 ), // #700 - INST(Setna , X86Set , O(000F00,96,_,_,_,_,_,_ ), 0 , 4 , 0 , 2726 , 181, 59 ), // #701 - INST(Setnae , X86Set , O(000F00,92,_,_,_,_,_,_ ), 0 , 4 , 0 , 2732 , 181, 60 ), // #702 - INST(Setnb , X86Set , O(000F00,93,_,_,_,_,_,_ ), 0 , 4 , 0 , 2739 , 181, 60 ), // #703 - INST(Setnbe , X86Set , O(000F00,97,_,_,_,_,_,_ ), 0 , 4 , 0 , 2745 , 181, 59 ), // #704 - INST(Setnc , X86Set , O(000F00,93,_,_,_,_,_,_ ), 0 , 4 , 0 , 2752 , 181, 60 ), // #705 - INST(Setne , X86Set , O(000F00,95,_,_,_,_,_,_ ), 0 , 4 , 0 , 2758 , 181, 61 ), // #706 - INST(Setng , X86Set , O(000F00,9E,_,_,_,_,_,_ ), 0 , 4 , 0 , 2764 , 181, 62 ), // #707 - INST(Setnge , X86Set , O(000F00,9C,_,_,_,_,_,_ ), 0 , 4 , 0 , 2770 , 181, 63 ), // #708 - INST(Setnl , X86Set , O(000F00,9D,_,_,_,_,_,_ ), 0 , 4 , 0 , 2777 , 181, 63 ), // #709 - INST(Setnle , X86Set , O(000F00,9F,_,_,_,_,_,_ ), 0 , 4 , 0 , 2783 , 181, 62 ), // #710 - INST(Setno , X86Set , O(000F00,91,_,_,_,_,_,_ ), 0 , 4 , 0 , 2790 , 181, 57 ), // #711 - INST(Setnp , X86Set , O(000F00,9B,_,_,_,_,_,_ ), 0 , 4 , 0 , 2796 , 181, 64 ), // #712 - INST(Setns , X86Set , O(000F00,99,_,_,_,_,_,_ ), 0 , 4 , 0 , 2802 , 181, 65 ), // #713 - INST(Setnz , X86Set , O(000F00,95,_,_,_,_,_,_ ), 0 , 4 , 0 , 2808 , 181, 61 ), // #714 - INST(Seto , X86Set , O(000F00,90,_,_,_,_,_,_ ), 0 , 4 , 0 , 2814 , 181, 57 ), // #715 - INST(Setp , X86Set , O(000F00,9A,_,_,_,_,_,_ ), 0 , 4 , 0 , 2819 , 181, 64 ), // #716 - INST(Setpe , X86Set , O(000F00,9A,_,_,_,_,_,_ ), 0 , 4 , 0 , 2824 , 181, 64 ), // #717 - INST(Setpo , X86Set , O(000F00,9B,_,_,_,_,_,_ ), 0 , 4 , 0 , 2830 , 181, 64 ), // #718 - INST(Sets , X86Set , O(000F00,98,_,_,_,_,_,_ ), 0 , 4 , 0 , 2836 , 181, 65 ), // #719 - INST(Setssbsy , X86Op , O(F30F01,E8,_,_,_,_,_,_ ), 0 , 25 , 0 , 2841 , 30 , 56 ), // #720 - INST(Setz , X86Set , O(000F00,94,_,_,_,_,_,_ ), 0 , 4 , 0 , 2850 , 181, 61 ), // #721 - INST(Sfence , X86Fence , O(000F00,AE,7,_,_,_,_,_ ), 0 , 22 , 0 , 2855 , 30 , 80 ), // #722 - INST(Sgdt , X86M_Only , O(000F00,01,0,_,_,_,_,_ ), 0 , 4 , 0 , 2862 , 69 , 0 ), // #723 - INST(Sha1msg1 , ExtRm , O(000F38,C9,_,_,_,_,_,_ ), 0 , 83 , 0 , 2867 , 5 , 123), // #724 - INST(Sha1msg2 , ExtRm , O(000F38,CA,_,_,_,_,_,_ ), 0 , 83 , 0 , 2876 , 5 , 123), // #725 - INST(Sha1nexte , ExtRm , O(000F38,C8,_,_,_,_,_,_ ), 0 , 83 , 0 , 2885 , 5 , 123), // #726 - INST(Sha1rnds4 , ExtRmi , O(000F3A,CC,_,_,_,_,_,_ ), 0 , 85 , 0 , 2895 , 8 , 123), // #727 - INST(Sha256msg1 , ExtRm , O(000F38,CC,_,_,_,_,_,_ ), 0 , 83 , 0 , 2905 , 5 , 123), // #728 - INST(Sha256msg2 , ExtRm , O(000F38,CD,_,_,_,_,_,_ ), 0 , 83 , 0 , 2916 , 5 , 123), // #729 - INST(Sha256rnds2 , ExtRm_XMM0 , O(000F38,CB,_,_,_,_,_,_ ), 0 , 83 , 0 , 2927 , 15 , 123), // #730 - INST(Shl , X86Rot , O(000000,D0,4,_,x,_,_,_ ), 0 , 9 , 0 , 2939 , 172, 1 ), // #731 - INST(Shld , X86ShldShrd , O(000F00,A4,_,_,x,_,_,_ ), 0 , 4 , 0 , 9938 , 182, 1 ), // #732 - INST(Shlx , VexRmv_Wx , V(660F38,F7,_,0,x,_,_,_ ), 0 , 96 , 0 , 2943 , 13 , 92 ), // #733 - INST(Shr , X86Rot , O(000000,D0,5,_,x,_,_,_ ), 0 , 62 , 0 , 2948 , 172, 1 ), // #734 - INST(Shrd , X86ShldShrd , O(000F00,AC,_,_,x,_,_,_ ), 0 , 4 , 0 , 2952 , 182, 1 ), // #735 - INST(Shrx , VexRmv_Wx , V(F20F38,F7,_,0,x,_,_,_ ), 0 , 84 , 0 , 2957 , 13 , 92 ), // #736 - INST(Shufpd , ExtRmi , O(660F00,C6,_,_,_,_,_,_ ), 0 , 3 , 0 , 11259, 8 , 4 ), // #737 - INST(Shufps , ExtRmi , O(000F00,C6,_,_,_,_,_,_ ), 0 , 4 , 0 , 11267, 8 , 5 ), // #738 - INST(Sidt , X86M_Only , O(000F00,01,1,_,_,_,_,_ ), 0 , 29 , 0 , 2962 , 69 , 0 ), // #739 - INST(Skinit , X86Op_xAX , O(000F01,DE,_,_,_,_,_,_ ), 0 , 21 , 0 , 2967 , 52 , 124), // #740 - INST(Sldt , X86M_NoMemSize , O(000F00,00,0,_,_,_,_,_ ), 0 , 4 , 0 , 2974 , 183, 0 ), // #741 - INST(Slwpcb , VexR_Wx , V(XOP_M9,12,1,0,x,_,_,_ ), 0 , 11 , 0 , 2979 , 108, 77 ), // #742 - INST(Smsw , X86M_NoMemSize , O(000F00,01,4,_,_,_,_,_ ), 0 , 97 , 0 , 2986 , 183, 0 ), // #743 - INST(Sqrtpd , ExtRm , O(660F00,51,_,_,_,_,_,_ ), 0 , 3 , 0 , 11275, 5 , 4 ), // #744 - INST(Sqrtps , ExtRm , O(000F00,51,_,_,_,_,_,_ ), 0 , 4 , 0 , 10961, 5 , 5 ), // #745 - INST(Sqrtsd , ExtRm , O(F20F00,51,_,_,_,_,_,_ ), 0 , 5 , 0 , 11299, 6 , 4 ), // #746 - INST(Sqrtss , ExtRm , O(F30F00,51,_,_,_,_,_,_ ), 0 , 6 , 0 , 10979, 7 , 5 ), // #747 - INST(Stac , X86Op , O(000F01,CB,_,_,_,_,_,_ ), 0 , 21 , 0 , 2991 , 30 , 16 ), // #748 - INST(Stc , X86Op , O(000000,F9,_,_,_,_,_,_ ), 0 , 0 , 0 , 2996 , 30 , 17 ), // #749 - INST(Std , X86Op , O(000000,FD,_,_,_,_,_,_ ), 0 , 0 , 0 , 7921 , 30 , 18 ), // #750 - INST(Stgi , X86Op , O(000F01,DC,_,_,_,_,_,_ ), 0 , 21 , 0 , 3000 , 30 , 124), // #751 - INST(Sti , X86Op , O(000000,FB,_,_,_,_,_,_ ), 0 , 0 , 0 , 3005 , 30 , 23 ), // #752 - INST(Stmxcsr , X86M_Only , O(000F00,AE,3,_,_,_,_,_ ), 0 , 78 , 0 , 11323, 101, 5 ), // #753 - INST(Stos , X86StrMr , O(000000,AA,_,_,_,_,_,_ ), 0 , 0 , 0 , 3009 , 184, 78 ), // #754 - INST(Str , X86M_NoMemSize , O(000F00,00,1,_,_,_,_,_ ), 0 , 29 , 0 , 3014 , 183, 0 ), // #755 - INST(Sttilecfg , AmxCfg , V(660F38,49,_,0,0,_,_,_ ), 0 , 96 , 0 , 3018 , 103, 76 ), // #756 - INST(Stui , X86Op , O(F30F01,EF,_,_,_,_,_,_ ), 0 , 25 , 0 , 3135 , 33 , 25 ), // #757 - INST(Sub , X86Arith , O(000000,28,5,_,x,_,_,_ ), 0 , 62 , 0 , 866 , 179, 1 ), // #758 - INST(Subpd , ExtRm , O(660F00,5C,_,_,_,_,_,_ ), 0 , 3 , 0 , 5413 , 5 , 4 ), // #759 - INST(Subps , ExtRm , O(000F00,5C,_,_,_,_,_,_ ), 0 , 4 , 0 , 5425 , 5 , 5 ), // #760 - INST(Subsd , ExtRm , O(F20F00,5C,_,_,_,_,_,_ ), 0 , 5 , 0 , 6392 , 6 , 4 ), // #761 - INST(Subss , ExtRm , O(F30F00,5C,_,_,_,_,_,_ ), 0 , 6 , 0 , 6402 , 7 , 5 ), // #762 - INST(Swapgs , X86Op , O(000F01,F8,_,_,_,_,_,_ ), 0 , 21 , 0 , 3028 , 33 , 0 ), // #763 - INST(Syscall , X86Op , O(000F00,05,_,_,_,_,_,_ ), 0 , 4 , 0 , 3035 , 33 , 0 ), // #764 - INST(Sysenter , X86Op , O(000F00,34,_,_,_,_,_,_ ), 0 , 4 , 0 , 3043 , 30 , 0 ), // #765 - INST(Sysexit , X86Op , O(000F00,35,_,_,_,_,_,_ ), 0 , 4 , 0 , 3052 , 30 , 0 ), // #766 - INST(Sysexitq , X86Op , O(000F00,35,_,_,1,_,_,_ ), 0 , 60 , 0 , 3060 , 30 , 0 ), // #767 - INST(Sysret , X86Op , O(000F00,07,_,_,_,_,_,_ ), 0 , 4 , 0 , 3069 , 33 , 0 ), // #768 - INST(Sysretq , X86Op , O(000F00,07,_,_,1,_,_,_ ), 0 , 60 , 0 , 3076 , 33 , 0 ), // #769 - INST(T1mskc , VexVm_Wx , V(XOP_M9,01,7,0,x,_,_,_ ), 0 , 98 , 0 , 3084 , 14 , 11 ), // #770 - INST(Tdpbf16ps , AmxRmv , V(F30F38,5C,_,0,0,_,_,_ ), 0 , 88 , 0 , 3091 , 185, 125), // #771 - INST(Tdpbssd , AmxRmv , V(F20F38,5E,_,0,0,_,_,_ ), 0 , 84 , 0 , 3101 , 185, 126), // #772 - INST(Tdpbsud , AmxRmv , V(F30F38,5E,_,0,0,_,_,_ ), 0 , 88 , 0 , 3109 , 185, 126), // #773 - INST(Tdpbusd , AmxRmv , V(660F38,5E,_,0,0,_,_,_ ), 0 , 96 , 0 , 3117 , 185, 126), // #774 - INST(Tdpbuud , AmxRmv , V(000F38,5E,_,0,0,_,_,_ ), 0 , 10 , 0 , 3125 , 185, 126), // #775 - INST(Test , X86Test , O(000000,84,_,_,x,_,_,_ ), O(000000,F6,_,_,x,_,_,_ ), 0 , 79 , 10367, 186, 1 ), // #776 - INST(Testui , X86Op , O(F30F01,ED,_,_,_,_,_,_ ), 0 , 25 , 0 , 3133 , 33 , 127), // #777 - INST(Tileloadd , AmxRm , V(F20F38,4B,_,0,0,_,_,_ ), 0 , 84 , 0 , 3140 , 187, 76 ), // #778 - INST(Tileloaddt1 , AmxRm , V(660F38,4B,_,0,0,_,_,_ ), 0 , 96 , 0 , 3150 , 187, 76 ), // #779 - INST(Tilerelease , VexOpMod , V(000F38,49,0,0,0,_,_,_ ), 0 , 10 , 0 , 3162 , 188, 76 ), // #780 - INST(Tilestored , AmxMr , V(F30F38,4B,_,0,0,_,_,_ ), 0 , 88 , 0 , 3174 , 189, 76 ), // #781 - INST(Tilezero , AmxR , V(F20F38,49,_,0,0,_,_,_ ), 0 , 84 , 0 , 3185 , 190, 76 ), // #782 - INST(Tpause , X86R32_EDX_EAX , O(660F00,AE,6,_,_,_,_,_ ), 0 , 26 , 0 , 3194 , 191, 128), // #783 - INST(Tzcnt , X86Rm_Raw66H , O(F30F00,BC,_,_,x,_,_,_ ), 0 , 6 , 0 , 3201 , 22 , 9 ), // #784 - INST(Tzmsk , VexVm_Wx , V(XOP_M9,01,4,0,x,_,_,_ ), 0 , 99 , 0 , 3207 , 14 , 11 ), // #785 - INST(Ucomisd , ExtRm , O(660F00,2E,_,_,_,_,_,_ ), 0 , 3 , 0 , 11390, 6 , 41 ), // #786 - INST(Ucomiss , ExtRm , O(000F00,2E,_,_,_,_,_,_ ), 0 , 4 , 0 , 11408, 7 , 42 ), // #787 - INST(Ud0 , X86Rm , O(000F00,FF,_,_,_,_,_,_ ), 0 , 4 , 0 , 3213 , 192, 0 ), // #788 - INST(Ud1 , X86Rm , O(000F00,B9,_,_,_,_,_,_ ), 0 , 4 , 0 , 3217 , 192, 0 ), // #789 - INST(Ud2 , X86Op , O(000F00,0B,_,_,_,_,_,_ ), 0 , 4 , 0 , 3221 , 30 , 0 ), // #790 - INST(Uiret , X86Op , O(F30F01,EC,_,_,_,_,_,_ ), 0 , 25 , 0 , 3225 , 33 , 25 ), // #791 - INST(Umonitor , X86R_FromM , O(F30F00,AE,6,_,_,_,_,_ ), 0 , 24 , 0 , 3231 , 193, 129), // #792 - INST(Umwait , X86R32_EDX_EAX , O(F20F00,AE,6,_,_,_,_,_ ), 0 , 100, 0 , 3240 , 191, 128), // #793 - INST(Unpckhpd , ExtRm , O(660F00,15,_,_,_,_,_,_ ), 0 , 3 , 0 , 11417, 5 , 4 ), // #794 - INST(Unpckhps , ExtRm , O(000F00,15,_,_,_,_,_,_ ), 0 , 4 , 0 , 11427, 5 , 5 ), // #795 - INST(Unpcklpd , ExtRm , O(660F00,14,_,_,_,_,_,_ ), 0 , 3 , 0 , 11437, 5 , 4 ), // #796 - INST(Unpcklps , ExtRm , O(000F00,14,_,_,_,_,_,_ ), 0 , 4 , 0 , 11447, 5 , 5 ), // #797 - INST(V4fmaddps , VexRm_T1_4X , E(F20F38,9A,_,2,_,0,4,T4X), 0 , 101, 0 , 3247 , 194, 130), // #798 - INST(V4fmaddss , VexRm_T1_4X , E(F20F38,9B,_,0,_,0,4,T4X), 0 , 102, 0 , 3257 , 195, 130), // #799 - INST(V4fnmaddps , VexRm_T1_4X , E(F20F38,AA,_,2,_,0,4,T4X), 0 , 101, 0 , 3267 , 194, 130), // #800 - INST(V4fnmaddss , VexRm_T1_4X , E(F20F38,AB,_,0,_,0,4,T4X), 0 , 102, 0 , 3278 , 195, 130), // #801 - INST(Vaddpd , VexRvm_Lx , V(660F00,58,_,x,I,1,4,FV ), 0 , 103, 0 , 3289 , 196, 131), // #802 - INST(Vaddph , VexRvm_Lx , E(00MAP5,58,_,_,_,0,4,FV ), 0 , 104, 0 , 3296 , 197, 132), // #803 - INST(Vaddps , VexRvm_Lx , V(000F00,58,_,x,I,0,4,FV ), 0 , 105, 0 , 3303 , 198, 131), // #804 - INST(Vaddsd , VexRvm , V(F20F00,58,_,I,I,1,3,T1S), 0 , 106, 0 , 3310 , 199, 133), // #805 - INST(Vaddsh , VexRvm , E(F3MAP5,58,_,_,_,0,1,T1S), 0 , 107, 0 , 3317 , 200, 134), // #806 - INST(Vaddss , VexRvm , V(F30F00,58,_,I,I,0,2,T1S), 0 , 108, 0 , 3324 , 201, 133), // #807 - INST(Vaddsubpd , VexRvm_Lx , V(660F00,D0,_,x,I,_,_,_ ), 0 , 69 , 0 , 3331 , 202, 135), // #808 - INST(Vaddsubps , VexRvm_Lx , V(F20F00,D0,_,x,I,_,_,_ ), 0 , 109, 0 , 3341 , 202, 135), // #809 - INST(Vaesdec , VexRvm_Lx , V(660F38,DE,_,x,I,_,4,FVM), 0 , 110, 0 , 3351 , 203, 136), // #810 - INST(Vaesdeclast , VexRvm_Lx , V(660F38,DF,_,x,I,_,4,FVM), 0 , 110, 0 , 3359 , 203, 136), // #811 - INST(Vaesenc , VexRvm_Lx , V(660F38,DC,_,x,I,_,4,FVM), 0 , 110, 0 , 3371 , 203, 136), // #812 - INST(Vaesenclast , VexRvm_Lx , V(660F38,DD,_,x,I,_,4,FVM), 0 , 110, 0 , 3379 , 203, 136), // #813 - INST(Vaesimc , VexRm , V(660F38,DB,_,0,I,_,_,_ ), 0 , 96 , 0 , 3391 , 204, 137), // #814 - INST(Vaeskeygenassist , VexRmi , V(660F3A,DF,_,0,I,_,_,_ ), 0 , 73 , 0 , 3399 , 205, 137), // #815 - INST(Valignd , VexRvmi_Lx , E(660F3A,03,_,x,_,0,4,FV ), 0 , 111, 0 , 3416 , 206, 138), // #816 - INST(Valignq , VexRvmi_Lx , E(660F3A,03,_,x,_,1,4,FV ), 0 , 112, 0 , 3424 , 207, 138), // #817 - INST(Vandnpd , VexRvm_Lx , V(660F00,55,_,x,I,1,4,FV ), 0 , 103, 0 , 3432 , 208, 139), // #818 - INST(Vandnps , VexRvm_Lx , V(000F00,55,_,x,I,0,4,FV ), 0 , 105, 0 , 3440 , 209, 139), // #819 - INST(Vandpd , VexRvm_Lx , V(660F00,54,_,x,I,1,4,FV ), 0 , 103, 0 , 3448 , 210, 139), // #820 - INST(Vandps , VexRvm_Lx , V(000F00,54,_,x,I,0,4,FV ), 0 , 105, 0 , 3455 , 211, 139), // #821 - INST(Vblendmpd , VexRvm_Lx , E(660F38,65,_,x,_,1,4,FV ), 0 , 113, 0 , 3462 , 212, 138), // #822 - INST(Vblendmps , VexRvm_Lx , E(660F38,65,_,x,_,0,4,FV ), 0 , 114, 0 , 3472 , 213, 138), // #823 - INST(Vblendpd , VexRvmi_Lx , V(660F3A,0D,_,x,I,_,_,_ ), 0 , 73 , 0 , 3482 , 214, 135), // #824 - INST(Vblendps , VexRvmi_Lx , V(660F3A,0C,_,x,I,_,_,_ ), 0 , 73 , 0 , 3491 , 214, 135), // #825 - INST(Vblendvpd , VexRvmr_Lx , V(660F3A,4B,_,x,0,_,_,_ ), 0 , 73 , 0 , 3500 , 215, 135), // #826 - INST(Vblendvps , VexRvmr_Lx , V(660F3A,4A,_,x,0,_,_,_ ), 0 , 73 , 0 , 3510 , 215, 135), // #827 - INST(Vbroadcastf128 , VexRm , V(660F38,1A,_,1,0,_,_,_ ), 0 , 115, 0 , 3520 , 216, 135), // #828 - INST(Vbroadcastf32x2 , VexRm_Lx , E(660F38,19,_,x,_,0,3,T2 ), 0 , 116, 0 , 3535 , 217, 140), // #829 - INST(Vbroadcastf32x4 , VexRm_Lx , E(660F38,1A,_,x,_,0,4,T4 ), 0 , 117, 0 , 3551 , 218, 68 ), // #830 - INST(Vbroadcastf32x8 , VexRm , E(660F38,1B,_,2,_,0,5,T8 ), 0 , 118, 0 , 3567 , 219, 66 ), // #831 - INST(Vbroadcastf64x2 , VexRm_Lx , E(660F38,1A,_,x,_,1,4,T2 ), 0 , 119, 0 , 3583 , 218, 140), // #832 - INST(Vbroadcastf64x4 , VexRm , E(660F38,1B,_,2,_,1,5,T4 ), 0 , 120, 0 , 3599 , 219, 68 ), // #833 - INST(Vbroadcasti128 , VexRm , V(660F38,5A,_,1,0,_,_,_ ), 0 , 115, 0 , 3615 , 216, 141), // #834 - INST(Vbroadcasti32x2 , VexRm_Lx , E(660F38,59,_,x,_,0,3,T2 ), 0 , 116, 0 , 3630 , 220, 140), // #835 - INST(Vbroadcasti32x4 , VexRm_Lx , E(660F38,5A,_,x,_,0,4,T4 ), 0 , 117, 0 , 3646 , 218, 138), // #836 - INST(Vbroadcasti32x8 , VexRm , E(660F38,5B,_,2,_,0,5,T8 ), 0 , 118, 0 , 3662 , 219, 66 ), // #837 - INST(Vbroadcasti64x2 , VexRm_Lx , E(660F38,5A,_,x,_,1,4,T2 ), 0 , 119, 0 , 3678 , 218, 140), // #838 - INST(Vbroadcasti64x4 , VexRm , E(660F38,5B,_,2,_,1,5,T4 ), 0 , 120, 0 , 3694 , 219, 68 ), // #839 - INST(Vbroadcastsd , VexRm_Lx , V(660F38,19,_,x,0,1,3,T1S), 0 , 121, 0 , 3710 , 221, 142), // #840 - INST(Vbroadcastss , VexRm_Lx , V(660F38,18,_,x,0,0,2,T1S), 0 , 122, 0 , 3723 , 222, 142), // #841 - INST(Vcmppd , VexRvmi_Lx_KEvex , V(660F00,C2,_,x,I,1,4,FV ), 0 , 103, 0 , 3736 , 223, 131), // #842 - INST(Vcmpph , VexRvmi_Lx_KEvex , E(000F3A,C2,_,_,_,0,4,FV ), 0 , 123, 0 , 3743 , 224, 132), // #843 - INST(Vcmpps , VexRvmi_Lx_KEvex , V(000F00,C2,_,x,I,0,4,FV ), 0 , 105, 0 , 3750 , 225, 131), // #844 - INST(Vcmpsd , VexRvmi_KEvex , V(F20F00,C2,_,I,I,1,3,T1S), 0 , 106, 0 , 3757 , 226, 133), // #845 - INST(Vcmpsh , VexRvmi_KEvex , E(F30F3A,C2,_,_,_,0,1,T1S), 0 , 124, 0 , 3764 , 227, 134), // #846 - INST(Vcmpss , VexRvmi_KEvex , V(F30F00,C2,_,I,I,0,2,T1S), 0 , 108, 0 , 3771 , 228, 133), // #847 - INST(Vcomisd , VexRm , V(660F00,2F,_,I,I,1,3,T1S), 0 , 125, 0 , 3778 , 229, 143), // #848 - INST(Vcomish , VexRm , E(00MAP5,2F,_,_,_,0,1,T1S), 0 , 126, 0 , 3786 , 230, 134), // #849 - INST(Vcomiss , VexRm , V(000F00,2F,_,I,I,0,2,T1S), 0 , 127, 0 , 3794 , 231, 143), // #850 - INST(Vcompresspd , VexMr_Lx , E(660F38,8A,_,x,_,1,3,T1S), 0 , 128, 0 , 3802 , 232, 138), // #851 - INST(Vcompressps , VexMr_Lx , E(660F38,8A,_,x,_,0,2,T1S), 0 , 129, 0 , 3814 , 232, 138), // #852 - INST(Vcvtdq2pd , VexRm_Lx , V(F30F00,E6,_,x,I,0,3,HV ), 0 , 130, 0 , 3826 , 233, 131), // #853 - INST(Vcvtdq2ph , VexRm_Lx , E(00MAP5,5B,_,_,_,0,4,FV ), 0 , 104, 0 , 3836 , 234, 132), // #854 - INST(Vcvtdq2ps , VexRm_Lx , V(000F00,5B,_,x,I,0,4,FV ), 0 , 105, 0 , 3846 , 235, 131), // #855 - INST(Vcvtne2ps2bf16 , VexRvm_Lx , E(F20F38,72,_,_,_,0,4,FV ), 0 , 131, 0 , 3856 , 213, 144), // #856 - INST(Vcvtneps2bf16 , VexRm_Lx_Narrow , E(F30F38,72,_,_,_,0,4,FV ), 0 , 132, 0 , 3871 , 236, 144), // #857 - INST(Vcvtpd2dq , VexRm_Lx_Narrow , V(F20F00,E6,_,x,I,1,4,FV ), 0 , 133, 0 , 3885 , 237, 131), // #858 - INST(Vcvtpd2ph , VexRm_Lx , E(66MAP5,5A,_,_,_,1,4,FV ), 0 , 134, 0 , 3895 , 238, 132), // #859 - INST(Vcvtpd2ps , VexRm_Lx_Narrow , V(660F00,5A,_,x,I,1,4,FV ), 0 , 103, 0 , 3905 , 237, 131), // #860 - INST(Vcvtpd2qq , VexRm_Lx , E(660F00,7B,_,x,_,1,4,FV ), 0 , 135, 0 , 3915 , 239, 140), // #861 - INST(Vcvtpd2udq , VexRm_Lx_Narrow , E(000F00,79,_,x,_,1,4,FV ), 0 , 136, 0 , 3925 , 240, 138), // #862 - INST(Vcvtpd2uqq , VexRm_Lx , E(660F00,79,_,x,_,1,4,FV ), 0 , 135, 0 , 3936 , 239, 140), // #863 - INST(Vcvtph2dq , VexRm_Lx , E(66MAP5,5B,_,_,_,0,3,HV ), 0 , 137, 0 , 3947 , 241, 132), // #864 - INST(Vcvtph2pd , VexRm_Lx , E(00MAP5,5A,_,_,_,0,2,QV ), 0 , 138, 0 , 3957 , 242, 132), // #865 - INST(Vcvtph2ps , VexRm_Lx , V(660F38,13,_,x,0,0,3,HVM), 0 , 139, 0 , 3967 , 243, 145), // #866 - INST(Vcvtph2psx , VexRm_Lx , E(66MAP6,13,_,_,_,0,3,HV ), 0 , 140, 0 , 3977 , 244, 132), // #867 - INST(Vcvtph2qq , VexRm_Lx , E(66MAP5,7B,_,_,_,0,2,QV ), 0 , 141, 0 , 3988 , 245, 132), // #868 - INST(Vcvtph2udq , VexRm_Lx , E(00MAP5,79,_,_,_,0,3,HV ), 0 , 142, 0 , 3998 , 241, 132), // #869 - INST(Vcvtph2uqq , VexRm_Lx , E(66MAP5,79,_,_,_,0,2,QV ), 0 , 141, 0 , 4009 , 245, 132), // #870 - INST(Vcvtph2uw , VexRm_Lx , E(00MAP5,7D,_,_,_,0,4,FV ), 0 , 104, 0 , 4020 , 246, 132), // #871 - INST(Vcvtph2w , VexRm_Lx , E(66MAP5,7D,_,_,_,0,4,FV ), 0 , 143, 0 , 4030 , 246, 132), // #872 - INST(Vcvtps2dq , VexRm_Lx , V(660F00,5B,_,x,I,0,4,FV ), 0 , 144, 0 , 4039 , 235, 131), // #873 - INST(Vcvtps2pd , VexRm_Lx , V(000F00,5A,_,x,I,0,3,HV ), 0 , 145, 0 , 4049 , 247, 131), // #874 - INST(Vcvtps2ph , VexMri_Lx , V(660F3A,1D,_,x,0,0,3,HVM), 0 , 146, 0 , 4059 , 248, 145), // #875 - INST(Vcvtps2phx , VexRm_Lx , E(66MAP5,1D,_,_,_,0,4,FV ), 0 , 143, 0 , 4069 , 234, 132), // #876 - INST(Vcvtps2qq , VexRm_Lx , E(660F00,7B,_,x,_,0,3,HV ), 0 , 147, 0 , 4080 , 249, 140), // #877 - INST(Vcvtps2udq , VexRm_Lx , E(000F00,79,_,x,_,0,4,FV ), 0 , 148, 0 , 4090 , 250, 138), // #878 - INST(Vcvtps2uqq , VexRm_Lx , E(660F00,79,_,x,_,0,3,HV ), 0 , 147, 0 , 4101 , 249, 140), // #879 - INST(Vcvtqq2pd , VexRm_Lx , E(F30F00,E6,_,x,_,1,4,FV ), 0 , 149, 0 , 4112 , 239, 140), // #880 - INST(Vcvtqq2ph , VexRm_Lx , E(00MAP5,5B,_,_,_,1,4,FV ), 0 , 150, 0 , 4122 , 238, 132), // #881 - INST(Vcvtqq2ps , VexRm_Lx_Narrow , E(000F00,5B,_,x,_,1,4,FV ), 0 , 136, 0 , 4132 , 240, 140), // #882 - INST(Vcvtsd2sh , VexRvm , E(F2MAP5,5A,_,_,_,1,3,T1S), 0 , 151, 0 , 4142 , 251, 134), // #883 - INST(Vcvtsd2si , VexRm_Wx , V(F20F00,2D,_,I,x,x,3,T1F), 0 , 152, 0 , 4152 , 252, 133), // #884 - INST(Vcvtsd2ss , VexRvm , V(F20F00,5A,_,I,I,1,3,T1S), 0 , 106, 0 , 4162 , 199, 133), // #885 - INST(Vcvtsd2usi , VexRm_Wx , E(F20F00,79,_,I,_,x,3,T1F), 0 , 153, 0 , 4172 , 253, 68 ), // #886 - INST(Vcvtsh2sd , VexRvm , E(F3MAP5,5A,_,_,_,0,1,T1S), 0 , 107, 0 , 4183 , 254, 134), // #887 - INST(Vcvtsh2si , VexRm_Wx , E(F3MAP5,2D,_,_,_,x,1,T1S), 0 , 107, 0 , 4193 , 255, 134), // #888 - INST(Vcvtsh2ss , VexRvm , E(00MAP6,13,_,_,_,0,1,T1S), 0 , 154, 0 , 4203 , 254, 134), // #889 - INST(Vcvtsh2usi , VexRm_Wx , E(F3MAP5,79,_,_,_,x,1,T1S), 0 , 107, 0 , 4213 , 255, 134), // #890 - INST(Vcvtsi2sd , VexRvm_Wx , V(F20F00,2A,_,I,x,x,2,T1W), 0 , 155, 0 , 4224 , 256, 133), // #891 - INST(Vcvtsi2sh , VexRvm_Wx , E(F3MAP5,2A,_,_,_,x,2,T1W), 0 , 156, 0 , 4234 , 257, 134), // #892 - INST(Vcvtsi2ss , VexRvm_Wx , V(F30F00,2A,_,I,x,x,2,T1W), 0 , 157, 0 , 4244 , 256, 133), // #893 - INST(Vcvtss2sd , VexRvm , V(F30F00,5A,_,I,I,0,2,T1S), 0 , 108, 0 , 4254 , 258, 133), // #894 - INST(Vcvtss2sh , VexRvm , E(00MAP5,1D,_,_,_,0,2,T1S), 0 , 158, 0 , 4264 , 259, 134), // #895 - INST(Vcvtss2si , VexRm_Wx , V(F30F00,2D,_,I,x,x,2,T1F), 0 , 108, 0 , 4274 , 260, 133), // #896 - INST(Vcvtss2usi , VexRm_Wx , E(F30F00,79,_,I,_,x,2,T1F), 0 , 159, 0 , 4284 , 261, 68 ), // #897 - INST(Vcvttpd2dq , VexRm_Lx_Narrow , V(660F00,E6,_,x,I,1,4,FV ), 0 , 103, 0 , 4295 , 262, 131), // #898 - INST(Vcvttpd2qq , VexRm_Lx , E(660F00,7A,_,x,_,1,4,FV ), 0 , 135, 0 , 4306 , 263, 138), // #899 - INST(Vcvttpd2udq , VexRm_Lx_Narrow , E(000F00,78,_,x,_,1,4,FV ), 0 , 136, 0 , 4317 , 264, 138), // #900 - INST(Vcvttpd2uqq , VexRm_Lx , E(660F00,78,_,x,_,1,4,FV ), 0 , 135, 0 , 4329 , 263, 140), // #901 - INST(Vcvttph2dq , VexRm_Lx , E(F3MAP5,5B,_,_,_,0,3,HV ), 0 , 160, 0 , 4341 , 244, 132), // #902 - INST(Vcvttph2qq , VexRm_Lx , E(66MAP5,7A,_,_,_,0,2,QV ), 0 , 141, 0 , 4352 , 242, 132), // #903 - INST(Vcvttph2udq , VexRm_Lx , E(00MAP5,78,_,_,_,0,3,HV ), 0 , 142, 0 , 4363 , 244, 132), // #904 - INST(Vcvttph2uqq , VexRm_Lx , E(66MAP5,78,_,_,_,0,2,QV ), 0 , 141, 0 , 4375 , 242, 132), // #905 - INST(Vcvttph2uw , VexRm_Lx , E(00MAP5,7C,_,_,_,0,4,FV ), 0 , 104, 0 , 4387 , 265, 132), // #906 - INST(Vcvttph2w , VexRm_Lx , E(66MAP5,7C,_,_,_,0,4,FV ), 0 , 143, 0 , 4398 , 265, 132), // #907 - INST(Vcvttps2dq , VexRm_Lx , V(F30F00,5B,_,x,I,0,4,FV ), 0 , 161, 0 , 4408 , 266, 131), // #908 - INST(Vcvttps2qq , VexRm_Lx , E(660F00,7A,_,x,_,0,3,HV ), 0 , 147, 0 , 4419 , 267, 140), // #909 - INST(Vcvttps2udq , VexRm_Lx , E(000F00,78,_,x,_,0,4,FV ), 0 , 148, 0 , 4430 , 268, 138), // #910 - INST(Vcvttps2uqq , VexRm_Lx , E(660F00,78,_,x,_,0,3,HV ), 0 , 147, 0 , 4442 , 267, 140), // #911 - INST(Vcvttsd2si , VexRm_Wx , V(F20F00,2C,_,I,x,x,3,T1F), 0 , 152, 0 , 4454 , 269, 133), // #912 - INST(Vcvttsd2usi , VexRm_Wx , E(F20F00,78,_,I,_,x,3,T1F), 0 , 153, 0 , 4465 , 270, 68 ), // #913 - INST(Vcvttsh2si , VexRm_Wx , E(F3MAP5,2C,_,_,_,x,1,T1S), 0 , 107, 0 , 4477 , 271, 134), // #914 - INST(Vcvttsh2usi , VexRm_Wx , E(F3MAP5,78,_,_,_,x,1,T1S), 0 , 107, 0 , 4488 , 271, 134), // #915 - INST(Vcvttss2si , VexRm_Wx , V(F30F00,2C,_,I,x,x,2,T1F), 0 , 108, 0 , 4500 , 272, 133), // #916 - INST(Vcvttss2usi , VexRm_Wx , E(F30F00,78,_,I,_,x,2,T1F), 0 , 159, 0 , 4511 , 273, 68 ), // #917 - INST(Vcvtudq2pd , VexRm_Lx , E(F30F00,7A,_,x,_,0,3,HV ), 0 , 162, 0 , 4523 , 274, 138), // #918 - INST(Vcvtudq2ph , VexRm_Lx , E(F2MAP5,7A,_,_,_,0,4,FV ), 0 , 163, 0 , 4534 , 234, 132), // #919 - INST(Vcvtudq2ps , VexRm_Lx , E(F20F00,7A,_,x,_,0,4,FV ), 0 , 164, 0 , 4545 , 250, 138), // #920 - INST(Vcvtuqq2pd , VexRm_Lx , E(F30F00,7A,_,x,_,1,4,FV ), 0 , 149, 0 , 4556 , 239, 140), // #921 - INST(Vcvtuqq2ph , VexRm_Lx , E(F2MAP5,7A,_,_,_,1,4,FV ), 0 , 165, 0 , 4567 , 238, 132), // #922 - INST(Vcvtuqq2ps , VexRm_Lx_Narrow , E(F20F00,7A,_,x,_,1,4,FV ), 0 , 166, 0 , 4578 , 240, 140), // #923 - INST(Vcvtusi2sd , VexRvm_Wx , E(F20F00,7B,_,I,_,x,2,T1W), 0 , 167, 0 , 4589 , 257, 68 ), // #924 - INST(Vcvtusi2sh , VexRvm_Wx , E(F3MAP5,7B,_,_,_,x,2,T1W), 0 , 156, 0 , 4600 , 257, 134), // #925 - INST(Vcvtusi2ss , VexRvm_Wx , E(F30F00,7B,_,I,_,x,2,T1W), 0 , 168, 0 , 4611 , 257, 68 ), // #926 - INST(Vcvtuw2ph , VexRm_Lx , E(F2MAP5,7D,_,_,_,0,4,FV ), 0 , 163, 0 , 4622 , 246, 132), // #927 - INST(Vcvtw2ph , VexRm_Lx , E(F3MAP5,7D,_,_,_,0,4,FV ), 0 , 169, 0 , 4632 , 246, 132), // #928 - INST(Vdbpsadbw , VexRvmi_Lx , E(660F3A,42,_,x,_,0,4,FVM), 0 , 111, 0 , 4641 , 275, 146), // #929 - INST(Vdivpd , VexRvm_Lx , V(660F00,5E,_,x,I,1,4,FV ), 0 , 103, 0 , 4651 , 196, 131), // #930 - INST(Vdivph , VexRvm_Lx , E(00MAP5,5E,_,_,_,0,4,FV ), 0 , 104, 0 , 4658 , 197, 132), // #931 - INST(Vdivps , VexRvm_Lx , V(000F00,5E,_,x,I,0,4,FV ), 0 , 105, 0 , 4665 , 198, 131), // #932 - INST(Vdivsd , VexRvm , V(F20F00,5E,_,I,I,1,3,T1S), 0 , 106, 0 , 4672 , 199, 133), // #933 - INST(Vdivsh , VexRvm , E(F3MAP5,5E,_,_,_,0,1,T1S), 0 , 107, 0 , 4679 , 200, 134), // #934 - INST(Vdivss , VexRvm , V(F30F00,5E,_,I,I,0,2,T1S), 0 , 108, 0 , 4686 , 201, 133), // #935 - INST(Vdpbf16ps , VexRvm_Lx , E(F30F38,52,_,_,_,0,4,FV ), 0 , 132, 0 , 4693 , 213, 144), // #936 - INST(Vdppd , VexRvmi_Lx , V(660F3A,41,_,x,I,_,_,_ ), 0 , 73 , 0 , 4703 , 276, 135), // #937 - INST(Vdpps , VexRvmi_Lx , V(660F3A,40,_,x,I,_,_,_ ), 0 , 73 , 0 , 4709 , 214, 135), // #938 - INST(Verr , X86M_NoSize , O(000F00,00,4,_,_,_,_,_ ), 0 , 97 , 0 , 4715 , 107, 10 ), // #939 - INST(Verw , X86M_NoSize , O(000F00,00,5,_,_,_,_,_ ), 0 , 77 , 0 , 4720 , 107, 10 ), // #940 - INST(Vexp2pd , VexRm , E(660F38,C8,_,2,_,1,4,FV ), 0 , 170, 0 , 4725 , 277, 147), // #941 - INST(Vexp2ps , VexRm , E(660F38,C8,_,2,_,0,4,FV ), 0 , 171, 0 , 4733 , 278, 147), // #942 - INST(Vexpandpd , VexRm_Lx , E(660F38,88,_,x,_,1,3,T1S), 0 , 128, 0 , 4741 , 279, 138), // #943 - INST(Vexpandps , VexRm_Lx , E(660F38,88,_,x,_,0,2,T1S), 0 , 129, 0 , 4751 , 279, 138), // #944 - INST(Vextractf128 , VexMri , V(660F3A,19,_,1,0,_,_,_ ), 0 , 172, 0 , 4761 , 280, 135), // #945 - INST(Vextractf32x4 , VexMri_Lx , E(660F3A,19,_,x,_,0,4,T4 ), 0 , 173, 0 , 4774 , 281, 138), // #946 - INST(Vextractf32x8 , VexMri , E(660F3A,1B,_,2,_,0,5,T8 ), 0 , 174, 0 , 4788 , 282, 66 ), // #947 - INST(Vextractf64x2 , VexMri_Lx , E(660F3A,19,_,x,_,1,4,T2 ), 0 , 175, 0 , 4802 , 281, 140), // #948 - INST(Vextractf64x4 , VexMri , E(660F3A,1B,_,2,_,1,5,T4 ), 0 , 176, 0 , 4816 , 282, 68 ), // #949 - INST(Vextracti128 , VexMri , V(660F3A,39,_,1,0,_,_,_ ), 0 , 172, 0 , 4830 , 280, 141), // #950 - INST(Vextracti32x4 , VexMri_Lx , E(660F3A,39,_,x,_,0,4,T4 ), 0 , 173, 0 , 4843 , 281, 138), // #951 - INST(Vextracti32x8 , VexMri , E(660F3A,3B,_,2,_,0,5,T8 ), 0 , 174, 0 , 4857 , 282, 66 ), // #952 - INST(Vextracti64x2 , VexMri_Lx , E(660F3A,39,_,x,_,1,4,T2 ), 0 , 175, 0 , 4871 , 281, 140), // #953 - INST(Vextracti64x4 , VexMri , E(660F3A,3B,_,2,_,1,5,T4 ), 0 , 176, 0 , 4885 , 282, 68 ), // #954 - INST(Vextractps , VexMri , V(660F3A,17,_,0,I,I,2,T1S), 0 , 177, 0 , 4899 , 283, 133), // #955 - INST(Vfcmaddcph , VexRvm_Lx , E(F2MAP6,56,_,_,_,0,4,FV ), 0 , 178, 0 , 4910 , 284, 132), // #956 - INST(Vfcmaddcsh , VexRvm , E(F2MAP6,57,_,_,_,0,2,T1S), 0 , 179, 0 , 4921 , 259, 132), // #957 - INST(Vfcmulcph , VexRvm_Lx , E(F2MAP6,D6,_,_,_,0,4,FV ), 0 , 178, 0 , 4932 , 284, 132), // #958 - INST(Vfcmulcsh , VexRvm , E(F2MAP6,D7,_,_,_,0,2,T1S), 0 , 179, 0 , 4942 , 259, 132), // #959 - INST(Vfixupimmpd , VexRvmi_Lx , E(660F3A,54,_,x,_,1,4,FV ), 0 , 112, 0 , 4952 , 285, 138), // #960 - INST(Vfixupimmps , VexRvmi_Lx , E(660F3A,54,_,x,_,0,4,FV ), 0 , 111, 0 , 4964 , 286, 138), // #961 - INST(Vfixupimmsd , VexRvmi , E(660F3A,55,_,I,_,1,3,T1S), 0 , 180, 0 , 4976 , 287, 68 ), // #962 - INST(Vfixupimmss , VexRvmi , E(660F3A,55,_,I,_,0,2,T1S), 0 , 181, 0 , 4988 , 288, 68 ), // #963 - INST(Vfmadd132pd , VexRvm_Lx , V(660F38,98,_,x,1,1,4,FV ), 0 , 182, 0 , 5000 , 196, 148), // #964 - INST(Vfmadd132ph , VexRvm_Lx , E(66MAP6,98,_,_,_,0,4,FV ), 0 , 183, 0 , 5012 , 197, 132), // #965 - INST(Vfmadd132ps , VexRvm_Lx , V(660F38,98,_,x,0,0,4,FV ), 0 , 110, 0 , 5024 , 198, 148), // #966 - INST(Vfmadd132sd , VexRvm , V(660F38,99,_,I,1,1,3,T1S), 0 , 184, 0 , 5036 , 199, 149), // #967 - INST(Vfmadd132sh , VexRvm , E(66MAP6,99,_,_,_,0,1,T1S), 0 , 185, 0 , 5048 , 200, 134), // #968 - INST(Vfmadd132ss , VexRvm , V(660F38,99,_,I,0,0,2,T1S), 0 , 122, 0 , 5060 , 201, 149), // #969 - INST(Vfmadd213pd , VexRvm_Lx , V(660F38,A8,_,x,1,1,4,FV ), 0 , 182, 0 , 5072 , 196, 148), // #970 - INST(Vfmadd213ph , VexRvm_Lx , E(66MAP6,A8,_,_,_,0,4,FV ), 0 , 183, 0 , 5084 , 197, 132), // #971 - INST(Vfmadd213ps , VexRvm_Lx , V(660F38,A8,_,x,0,0,4,FV ), 0 , 110, 0 , 5096 , 198, 148), // #972 - INST(Vfmadd213sd , VexRvm , V(660F38,A9,_,I,1,1,3,T1S), 0 , 184, 0 , 5108 , 199, 149), // #973 - INST(Vfmadd213sh , VexRvm , E(66MAP6,A9,_,_,_,0,1,T1S), 0 , 185, 0 , 5120 , 200, 134), // #974 - INST(Vfmadd213ss , VexRvm , V(660F38,A9,_,I,0,0,2,T1S), 0 , 122, 0 , 5132 , 201, 149), // #975 - INST(Vfmadd231pd , VexRvm_Lx , V(660F38,B8,_,x,1,1,4,FV ), 0 , 182, 0 , 5144 , 196, 148), // #976 - INST(Vfmadd231ph , VexRvm_Lx , E(66MAP6,B8,_,_,_,0,4,FV ), 0 , 183, 0 , 5156 , 197, 132), // #977 - INST(Vfmadd231ps , VexRvm_Lx , V(660F38,B8,_,x,0,0,4,FV ), 0 , 110, 0 , 5168 , 198, 148), // #978 - INST(Vfmadd231sd , VexRvm , V(660F38,B9,_,I,1,1,3,T1S), 0 , 184, 0 , 5180 , 199, 149), // #979 - INST(Vfmadd231sh , VexRvm , E(66MAP6,B9,_,_,_,0,1,T1S), 0 , 185, 0 , 5192 , 200, 134), // #980 - INST(Vfmadd231ss , VexRvm , V(660F38,B9,_,I,0,0,2,T1S), 0 , 122, 0 , 5204 , 201, 149), // #981 - INST(Vfmaddcph , VexRvm_Lx , E(F3MAP6,56,_,_,_,0,4,FV ), 0 , 186, 0 , 5216 , 284, 132), // #982 - INST(Vfmaddcsh , VexRvm , E(F3MAP6,57,_,_,_,0,2,T1S), 0 , 187, 0 , 5226 , 259, 132), // #983 - INST(Vfmaddpd , Fma4_Lx , V(660F3A,69,_,x,x,_,_,_ ), 0 , 73 , 0 , 5236 , 289, 150), // #984 - INST(Vfmaddps , Fma4_Lx , V(660F3A,68,_,x,x,_,_,_ ), 0 , 73 , 0 , 5245 , 289, 150), // #985 - INST(Vfmaddsd , Fma4 , V(660F3A,6B,_,0,x,_,_,_ ), 0 , 73 , 0 , 5254 , 290, 150), // #986 - INST(Vfmaddss , Fma4 , V(660F3A,6A,_,0,x,_,_,_ ), 0 , 73 , 0 , 5263 , 291, 150), // #987 - INST(Vfmaddsub132pd , VexRvm_Lx , V(660F38,96,_,x,1,1,4,FV ), 0 , 182, 0 , 5272 , 196, 148), // #988 - INST(Vfmaddsub132ph , VexRvm_Lx , E(66MAP6,96,_,_,_,0,4,FV ), 0 , 183, 0 , 5287 , 197, 132), // #989 - INST(Vfmaddsub132ps , VexRvm_Lx , V(660F38,96,_,x,0,0,4,FV ), 0 , 110, 0 , 5302 , 198, 148), // #990 - INST(Vfmaddsub213pd , VexRvm_Lx , V(660F38,A6,_,x,1,1,4,FV ), 0 , 182, 0 , 5317 , 196, 148), // #991 - INST(Vfmaddsub213ph , VexRvm_Lx , E(66MAP6,A6,_,_,_,0,4,FV ), 0 , 183, 0 , 5332 , 197, 132), // #992 - INST(Vfmaddsub213ps , VexRvm_Lx , V(660F38,A6,_,x,0,0,4,FV ), 0 , 110, 0 , 5347 , 198, 148), // #993 - INST(Vfmaddsub231pd , VexRvm_Lx , V(660F38,B6,_,x,1,1,4,FV ), 0 , 182, 0 , 5362 , 196, 148), // #994 - INST(Vfmaddsub231ph , VexRvm_Lx , E(66MAP6,B6,_,_,_,0,4,FV ), 0 , 183, 0 , 5377 , 197, 132), // #995 - INST(Vfmaddsub231ps , VexRvm_Lx , V(660F38,B6,_,x,0,0,4,FV ), 0 , 110, 0 , 5392 , 198, 148), // #996 - INST(Vfmaddsubpd , Fma4_Lx , V(660F3A,5D,_,x,x,_,_,_ ), 0 , 73 , 0 , 5407 , 289, 150), // #997 - INST(Vfmaddsubps , Fma4_Lx , V(660F3A,5C,_,x,x,_,_,_ ), 0 , 73 , 0 , 5419 , 289, 150), // #998 - INST(Vfmsub132pd , VexRvm_Lx , V(660F38,9A,_,x,1,1,4,FV ), 0 , 182, 0 , 5431 , 196, 148), // #999 - INST(Vfmsub132ph , VexRvm_Lx , E(66MAP6,9A,_,_,_,0,4,FV ), 0 , 183, 0 , 5443 , 197, 132), // #1000 - INST(Vfmsub132ps , VexRvm_Lx , V(660F38,9A,_,x,0,0,4,FV ), 0 , 110, 0 , 5455 , 198, 148), // #1001 - INST(Vfmsub132sd , VexRvm , V(660F38,9B,_,I,1,1,3,T1S), 0 , 184, 0 , 5467 , 199, 149), // #1002 - INST(Vfmsub132sh , VexRvm , E(66MAP6,9B,_,_,_,0,1,T1S), 0 , 185, 0 , 5479 , 200, 134), // #1003 - INST(Vfmsub132ss , VexRvm , V(660F38,9B,_,I,0,0,2,T1S), 0 , 122, 0 , 5491 , 201, 149), // #1004 - INST(Vfmsub213pd , VexRvm_Lx , V(660F38,AA,_,x,1,1,4,FV ), 0 , 182, 0 , 5503 , 196, 148), // #1005 - INST(Vfmsub213ph , VexRvm_Lx , E(66MAP6,AA,_,_,_,0,4,FV ), 0 , 183, 0 , 5515 , 197, 132), // #1006 - INST(Vfmsub213ps , VexRvm_Lx , V(660F38,AA,_,x,0,0,4,FV ), 0 , 110, 0 , 5527 , 198, 148), // #1007 - INST(Vfmsub213sd , VexRvm , V(660F38,AB,_,I,1,1,3,T1S), 0 , 184, 0 , 5539 , 199, 149), // #1008 - INST(Vfmsub213sh , VexRvm , E(66MAP6,AB,_,_,_,0,1,T1S), 0 , 185, 0 , 5551 , 200, 134), // #1009 - INST(Vfmsub213ss , VexRvm , V(660F38,AB,_,I,0,0,2,T1S), 0 , 122, 0 , 5563 , 201, 149), // #1010 - INST(Vfmsub231pd , VexRvm_Lx , V(660F38,BA,_,x,1,1,4,FV ), 0 , 182, 0 , 5575 , 196, 148), // #1011 - INST(Vfmsub231ph , VexRvm_Lx , E(66MAP6,BA,_,_,_,0,4,FV ), 0 , 183, 0 , 5587 , 197, 132), // #1012 - INST(Vfmsub231ps , VexRvm_Lx , V(660F38,BA,_,x,0,0,4,FV ), 0 , 110, 0 , 5599 , 198, 148), // #1013 - INST(Vfmsub231sd , VexRvm , V(660F38,BB,_,I,1,1,3,T1S), 0 , 184, 0 , 5611 , 199, 149), // #1014 - INST(Vfmsub231sh , VexRvm , E(66MAP6,BB,_,_,_,0,1,T1S), 0 , 185, 0 , 5623 , 200, 134), // #1015 - INST(Vfmsub231ss , VexRvm , V(660F38,BB,_,I,0,0,2,T1S), 0 , 122, 0 , 5635 , 201, 149), // #1016 - INST(Vfmsubadd132pd , VexRvm_Lx , V(660F38,97,_,x,1,1,4,FV ), 0 , 182, 0 , 5647 , 196, 148), // #1017 - INST(Vfmsubadd132ph , VexRvm_Lx , E(66MAP6,97,_,_,_,0,4,FV ), 0 , 183, 0 , 5662 , 197, 132), // #1018 - INST(Vfmsubadd132ps , VexRvm_Lx , V(660F38,97,_,x,0,0,4,FV ), 0 , 110, 0 , 5677 , 198, 148), // #1019 - INST(Vfmsubadd213pd , VexRvm_Lx , V(660F38,A7,_,x,1,1,4,FV ), 0 , 182, 0 , 5692 , 196, 148), // #1020 - INST(Vfmsubadd213ph , VexRvm_Lx , E(66MAP6,A7,_,_,_,0,4,FV ), 0 , 183, 0 , 5707 , 197, 132), // #1021 - INST(Vfmsubadd213ps , VexRvm_Lx , V(660F38,A7,_,x,0,0,4,FV ), 0 , 110, 0 , 5722 , 198, 148), // #1022 - INST(Vfmsubadd231pd , VexRvm_Lx , V(660F38,B7,_,x,1,1,4,FV ), 0 , 182, 0 , 5737 , 196, 148), // #1023 - INST(Vfmsubadd231ph , VexRvm_Lx , E(66MAP6,B7,_,_,_,0,4,FV ), 0 , 183, 0 , 5752 , 197, 132), // #1024 - INST(Vfmsubadd231ps , VexRvm_Lx , V(660F38,B7,_,x,0,0,4,FV ), 0 , 110, 0 , 5767 , 198, 148), // #1025 - INST(Vfmsubaddpd , Fma4_Lx , V(660F3A,5F,_,x,x,_,_,_ ), 0 , 73 , 0 , 5782 , 289, 150), // #1026 - INST(Vfmsubaddps , Fma4_Lx , V(660F3A,5E,_,x,x,_,_,_ ), 0 , 73 , 0 , 5794 , 289, 150), // #1027 - INST(Vfmsubpd , Fma4_Lx , V(660F3A,6D,_,x,x,_,_,_ ), 0 , 73 , 0 , 5806 , 289, 150), // #1028 - INST(Vfmsubps , Fma4_Lx , V(660F3A,6C,_,x,x,_,_,_ ), 0 , 73 , 0 , 5815 , 289, 150), // #1029 - INST(Vfmsubsd , Fma4 , V(660F3A,6F,_,0,x,_,_,_ ), 0 , 73 , 0 , 5824 , 290, 150), // #1030 - INST(Vfmsubss , Fma4 , V(660F3A,6E,_,0,x,_,_,_ ), 0 , 73 , 0 , 5833 , 291, 150), // #1031 - INST(Vfmulcph , VexRvm_Lx , E(F3MAP6,D6,_,_,_,0,4,FV ), 0 , 186, 0 , 5842 , 284, 132), // #1032 - INST(Vfmulcsh , VexRvm , E(F3MAP6,D7,_,_,_,0,2,T1S), 0 , 187, 0 , 5851 , 259, 132), // #1033 - INST(Vfnmadd132pd , VexRvm_Lx , V(660F38,9C,_,x,1,1,4,FV ), 0 , 182, 0 , 5860 , 196, 148), // #1034 - INST(Vfnmadd132ph , VexRvm_Lx , E(66MAP6,9C,_,_,_,0,4,FV ), 0 , 183, 0 , 5873 , 197, 132), // #1035 - INST(Vfnmadd132ps , VexRvm_Lx , V(660F38,9C,_,x,0,0,4,FV ), 0 , 110, 0 , 5886 , 198, 148), // #1036 - INST(Vfnmadd132sd , VexRvm , V(660F38,9D,_,I,1,1,3,T1S), 0 , 184, 0 , 5899 , 199, 149), // #1037 - INST(Vfnmadd132sh , VexRvm , E(66MAP6,9D,_,_,_,0,1,T1S), 0 , 185, 0 , 5912 , 200, 134), // #1038 - INST(Vfnmadd132ss , VexRvm , V(660F38,9D,_,I,0,0,2,T1S), 0 , 122, 0 , 5925 , 201, 149), // #1039 - INST(Vfnmadd213pd , VexRvm_Lx , V(660F38,AC,_,x,1,1,4,FV ), 0 , 182, 0 , 5938 , 196, 148), // #1040 - INST(Vfnmadd213ph , VexRvm_Lx , E(66MAP6,AC,_,_,_,0,4,FV ), 0 , 183, 0 , 5951 , 197, 132), // #1041 - INST(Vfnmadd213ps , VexRvm_Lx , V(660F38,AC,_,x,0,0,4,FV ), 0 , 110, 0 , 5964 , 198, 148), // #1042 - INST(Vfnmadd213sd , VexRvm , V(660F38,AD,_,I,1,1,3,T1S), 0 , 184, 0 , 5977 , 199, 149), // #1043 - INST(Vfnmadd213sh , VexRvm , E(66MAP6,AD,_,_,_,0,1,T1S), 0 , 185, 0 , 5990 , 200, 134), // #1044 - INST(Vfnmadd213ss , VexRvm , V(660F38,AD,_,I,0,0,2,T1S), 0 , 122, 0 , 6003 , 201, 149), // #1045 - INST(Vfnmadd231pd , VexRvm_Lx , V(660F38,BC,_,x,1,1,4,FV ), 0 , 182, 0 , 6016 , 196, 148), // #1046 - INST(Vfnmadd231ph , VexRvm_Lx , E(66MAP6,BC,_,_,_,0,4,FV ), 0 , 183, 0 , 6029 , 197, 132), // #1047 - INST(Vfnmadd231ps , VexRvm_Lx , V(660F38,BC,_,x,0,0,4,FV ), 0 , 110, 0 , 6042 , 198, 148), // #1048 - INST(Vfnmadd231sd , VexRvm , V(660F38,BD,_,I,1,1,3,T1S), 0 , 184, 0 , 6055 , 199, 149), // #1049 - INST(Vfnmadd231sh , VexRvm , E(66MAP6,BD,_,_,_,0,1,T1S), 0 , 185, 0 , 6068 , 200, 134), // #1050 - INST(Vfnmadd231ss , VexRvm , V(660F38,BD,_,I,0,0,2,T1S), 0 , 122, 0 , 6081 , 201, 149), // #1051 - INST(Vfnmaddpd , Fma4_Lx , V(660F3A,79,_,x,x,_,_,_ ), 0 , 73 , 0 , 6094 , 289, 150), // #1052 - INST(Vfnmaddps , Fma4_Lx , V(660F3A,78,_,x,x,_,_,_ ), 0 , 73 , 0 , 6104 , 289, 150), // #1053 - INST(Vfnmaddsd , Fma4 , V(660F3A,7B,_,0,x,_,_,_ ), 0 , 73 , 0 , 6114 , 290, 150), // #1054 - INST(Vfnmaddss , Fma4 , V(660F3A,7A,_,0,x,_,_,_ ), 0 , 73 , 0 , 6124 , 291, 150), // #1055 - INST(Vfnmsub132pd , VexRvm_Lx , V(660F38,9E,_,x,1,1,4,FV ), 0 , 182, 0 , 6134 , 196, 148), // #1056 - INST(Vfnmsub132ph , VexRvm_Lx , E(66MAP6,9E,_,_,_,0,4,FV ), 0 , 183, 0 , 6147 , 197, 132), // #1057 - INST(Vfnmsub132ps , VexRvm_Lx , V(660F38,9E,_,x,0,0,4,FV ), 0 , 110, 0 , 6160 , 198, 148), // #1058 - INST(Vfnmsub132sd , VexRvm , V(660F38,9F,_,I,1,1,3,T1S), 0 , 184, 0 , 6173 , 199, 149), // #1059 - INST(Vfnmsub132sh , VexRvm , E(66MAP6,9F,_,_,_,0,1,T1S), 0 , 185, 0 , 6186 , 200, 134), // #1060 - INST(Vfnmsub132ss , VexRvm , V(660F38,9F,_,I,0,0,2,T1S), 0 , 122, 0 , 6199 , 201, 149), // #1061 - INST(Vfnmsub213pd , VexRvm_Lx , V(660F38,AE,_,x,1,1,4,FV ), 0 , 182, 0 , 6212 , 196, 148), // #1062 - INST(Vfnmsub213ph , VexRvm_Lx , E(66MAP6,AE,_,_,_,0,4,FV ), 0 , 183, 0 , 6225 , 197, 132), // #1063 - INST(Vfnmsub213ps , VexRvm_Lx , V(660F38,AE,_,x,0,0,4,FV ), 0 , 110, 0 , 6238 , 198, 148), // #1064 - INST(Vfnmsub213sd , VexRvm , V(660F38,AF,_,I,1,1,3,T1S), 0 , 184, 0 , 6251 , 199, 149), // #1065 - INST(Vfnmsub213sh , VexRvm , E(66MAP6,AF,_,_,_,0,1,T1S), 0 , 185, 0 , 6264 , 200, 134), // #1066 - INST(Vfnmsub213ss , VexRvm , V(660F38,AF,_,I,0,0,2,T1S), 0 , 122, 0 , 6277 , 201, 149), // #1067 - INST(Vfnmsub231pd , VexRvm_Lx , V(660F38,BE,_,x,1,1,4,FV ), 0 , 182, 0 , 6290 , 196, 148), // #1068 - INST(Vfnmsub231ph , VexRvm_Lx , E(66MAP6,BE,_,_,_,0,4,FV ), 0 , 183, 0 , 6303 , 197, 132), // #1069 - INST(Vfnmsub231ps , VexRvm_Lx , V(660F38,BE,_,x,0,0,4,FV ), 0 , 110, 0 , 6316 , 198, 148), // #1070 - INST(Vfnmsub231sd , VexRvm , V(660F38,BF,_,I,1,1,3,T1S), 0 , 184, 0 , 6329 , 199, 149), // #1071 - INST(Vfnmsub231sh , VexRvm , E(66MAP6,BF,_,_,_,0,1,T1S), 0 , 185, 0 , 6342 , 200, 134), // #1072 - INST(Vfnmsub231ss , VexRvm , V(660F38,BF,_,I,0,0,2,T1S), 0 , 122, 0 , 6355 , 201, 149), // #1073 - INST(Vfnmsubpd , Fma4_Lx , V(660F3A,7D,_,x,x,_,_,_ ), 0 , 73 , 0 , 6368 , 289, 150), // #1074 - INST(Vfnmsubps , Fma4_Lx , V(660F3A,7C,_,x,x,_,_,_ ), 0 , 73 , 0 , 6378 , 289, 150), // #1075 - INST(Vfnmsubsd , Fma4 , V(660F3A,7F,_,0,x,_,_,_ ), 0 , 73 , 0 , 6388 , 290, 150), // #1076 - INST(Vfnmsubss , Fma4 , V(660F3A,7E,_,0,x,_,_,_ ), 0 , 73 , 0 , 6398 , 291, 150), // #1077 - INST(Vfpclasspd , VexRmi_Lx , E(660F3A,66,_,x,_,1,4,FV ), 0 , 112, 0 , 6408 , 292, 140), // #1078 - INST(Vfpclassph , VexRmi_Lx , E(000F3A,66,_,_,_,0,4,FV ), 0 , 123, 0 , 6419 , 293, 132), // #1079 - INST(Vfpclassps , VexRmi_Lx , E(660F3A,66,_,x,_,0,4,FV ), 0 , 111, 0 , 6430 , 294, 140), // #1080 - INST(Vfpclasssd , VexRmi , E(660F3A,67,_,I,_,1,3,T1S), 0 , 180, 0 , 6441 , 295, 66 ), // #1081 - INST(Vfpclasssh , VexRmi , E(000F3A,67,_,_,_,0,1,T1S), 0 , 188, 0 , 6452 , 296, 134), // #1082 - INST(Vfpclassss , VexRmi , E(660F3A,67,_,I,_,0,2,T1S), 0 , 181, 0 , 6463 , 297, 66 ), // #1083 - INST(Vfrczpd , VexRm_Lx , V(XOP_M9,81,_,x,0,_,_,_ ), 0 , 79 , 0 , 6474 , 298, 151), // #1084 - INST(Vfrczps , VexRm_Lx , V(XOP_M9,80,_,x,0,_,_,_ ), 0 , 79 , 0 , 6482 , 298, 151), // #1085 - INST(Vfrczsd , VexRm , V(XOP_M9,83,_,0,0,_,_,_ ), 0 , 79 , 0 , 6490 , 299, 151), // #1086 - INST(Vfrczss , VexRm , V(XOP_M9,82,_,0,0,_,_,_ ), 0 , 79 , 0 , 6498 , 300, 151), // #1087 - INST(Vgatherdpd , VexRmvRm_VM , V(660F38,92,_,x,1,_,_,_ ), E(660F38,92,_,x,_,1,3,T1S), 189, 80 , 6506 , 301, 152), // #1088 - INST(Vgatherdps , VexRmvRm_VM , V(660F38,92,_,x,0,_,_,_ ), E(660F38,92,_,x,_,0,2,T1S), 96 , 81 , 6517 , 302, 152), // #1089 - INST(Vgatherpf0dpd , VexM_VM , E(660F38,C6,1,2,_,1,3,T1S), 0 , 190, 0 , 6528 , 303, 153), // #1090 - INST(Vgatherpf0dps , VexM_VM , E(660F38,C6,1,2,_,0,2,T1S), 0 , 191, 0 , 6542 , 304, 153), // #1091 - INST(Vgatherpf0qpd , VexM_VM , E(660F38,C7,1,2,_,1,3,T1S), 0 , 190, 0 , 6556 , 305, 153), // #1092 - INST(Vgatherpf0qps , VexM_VM , E(660F38,C7,1,2,_,0,2,T1S), 0 , 191, 0 , 6570 , 305, 153), // #1093 - INST(Vgatherpf1dpd , VexM_VM , E(660F38,C6,2,2,_,1,3,T1S), 0 , 192, 0 , 6584 , 303, 153), // #1094 - INST(Vgatherpf1dps , VexM_VM , E(660F38,C6,2,2,_,0,2,T1S), 0 , 193, 0 , 6598 , 304, 153), // #1095 - INST(Vgatherpf1qpd , VexM_VM , E(660F38,C7,2,2,_,1,3,T1S), 0 , 192, 0 , 6612 , 305, 153), // #1096 - INST(Vgatherpf1qps , VexM_VM , E(660F38,C7,2,2,_,0,2,T1S), 0 , 193, 0 , 6626 , 305, 153), // #1097 - INST(Vgatherqpd , VexRmvRm_VM , V(660F38,93,_,x,1,_,_,_ ), E(660F38,93,_,x,_,1,3,T1S), 189, 82 , 6640 , 306, 152), // #1098 - INST(Vgatherqps , VexRmvRm_VM , V(660F38,93,_,x,0,_,_,_ ), E(660F38,93,_,x,_,0,2,T1S), 96 , 83 , 6651 , 307, 152), // #1099 - INST(Vgetexppd , VexRm_Lx , E(660F38,42,_,x,_,1,4,FV ), 0 , 113, 0 , 6662 , 263, 138), // #1100 - INST(Vgetexpph , VexRm_Lx , E(66MAP6,42,_,_,_,0,4,FV ), 0 , 183, 0 , 6672 , 265, 132), // #1101 - INST(Vgetexpps , VexRm_Lx , E(660F38,42,_,x,_,0,4,FV ), 0 , 114, 0 , 6682 , 268, 138), // #1102 - INST(Vgetexpsd , VexRvm , E(660F38,43,_,I,_,1,3,T1S), 0 , 128, 0 , 6692 , 308, 68 ), // #1103 - INST(Vgetexpsh , VexRvm , E(66MAP6,43,_,_,_,0,1,T1S), 0 , 185, 0 , 6702 , 254, 134), // #1104 - INST(Vgetexpss , VexRvm , E(660F38,43,_,I,_,0,2,T1S), 0 , 129, 0 , 6712 , 309, 68 ), // #1105 - INST(Vgetmantpd , VexRmi_Lx , E(660F3A,26,_,x,_,1,4,FV ), 0 , 112, 0 , 6722 , 310, 138), // #1106 - INST(Vgetmantph , VexRmi_Lx , E(000F3A,26,_,_,_,0,4,FV ), 0 , 123, 0 , 6733 , 311, 132), // #1107 - INST(Vgetmantps , VexRmi_Lx , E(660F3A,26,_,x,_,0,4,FV ), 0 , 111, 0 , 6744 , 312, 138), // #1108 - INST(Vgetmantsd , VexRvmi , E(660F3A,27,_,I,_,1,3,T1S), 0 , 180, 0 , 6755 , 287, 68 ), // #1109 - INST(Vgetmantsh , VexRvmi , E(000F3A,27,_,_,_,0,1,T1S), 0 , 188, 0 , 6766 , 313, 134), // #1110 - INST(Vgetmantss , VexRvmi , E(660F3A,27,_,I,_,0,2,T1S), 0 , 181, 0 , 6777 , 288, 68 ), // #1111 - INST(Vgf2p8affineinvqb, VexRvmi_Lx , V(660F3A,CF,_,x,1,1,4,FV ), 0 , 194, 0 , 6788 , 314, 154), // #1112 - INST(Vgf2p8affineqb , VexRvmi_Lx , V(660F3A,CE,_,x,1,1,4,FV ), 0 , 194, 0 , 6806 , 314, 154), // #1113 - INST(Vgf2p8mulb , VexRvm_Lx , V(660F38,CF,_,x,0,0,4,FV ), 0 , 110, 0 , 6821 , 315, 154), // #1114 - INST(Vhaddpd , VexRvm_Lx , V(660F00,7C,_,x,I,_,_,_ ), 0 , 69 , 0 , 6832 , 202, 135), // #1115 - INST(Vhaddps , VexRvm_Lx , V(F20F00,7C,_,x,I,_,_,_ ), 0 , 109, 0 , 6840 , 202, 135), // #1116 - INST(Vhsubpd , VexRvm_Lx , V(660F00,7D,_,x,I,_,_,_ ), 0 , 69 , 0 , 6848 , 202, 135), // #1117 - INST(Vhsubps , VexRvm_Lx , V(F20F00,7D,_,x,I,_,_,_ ), 0 , 109, 0 , 6856 , 202, 135), // #1118 - INST(Vinsertf128 , VexRvmi , V(660F3A,18,_,1,0,_,_,_ ), 0 , 172, 0 , 6864 , 316, 135), // #1119 - INST(Vinsertf32x4 , VexRvmi_Lx , E(660F3A,18,_,x,_,0,4,T4 ), 0 , 173, 0 , 6876 , 317, 138), // #1120 - INST(Vinsertf32x8 , VexRvmi , E(660F3A,1A,_,2,_,0,5,T8 ), 0 , 174, 0 , 6889 , 318, 66 ), // #1121 - INST(Vinsertf64x2 , VexRvmi_Lx , E(660F3A,18,_,x,_,1,4,T2 ), 0 , 175, 0 , 6902 , 317, 140), // #1122 - INST(Vinsertf64x4 , VexRvmi , E(660F3A,1A,_,2,_,1,5,T4 ), 0 , 176, 0 , 6915 , 318, 68 ), // #1123 - INST(Vinserti128 , VexRvmi , V(660F3A,38,_,1,0,_,_,_ ), 0 , 172, 0 , 6928 , 316, 141), // #1124 - INST(Vinserti32x4 , VexRvmi_Lx , E(660F3A,38,_,x,_,0,4,T4 ), 0 , 173, 0 , 6940 , 317, 138), // #1125 - INST(Vinserti32x8 , VexRvmi , E(660F3A,3A,_,2,_,0,5,T8 ), 0 , 174, 0 , 6953 , 318, 66 ), // #1126 - INST(Vinserti64x2 , VexRvmi_Lx , E(660F3A,38,_,x,_,1,4,T2 ), 0 , 175, 0 , 6966 , 317, 140), // #1127 - INST(Vinserti64x4 , VexRvmi , E(660F3A,3A,_,2,_,1,5,T4 ), 0 , 176, 0 , 6979 , 318, 68 ), // #1128 - INST(Vinsertps , VexRvmi , V(660F3A,21,_,0,I,0,2,T1S), 0 , 177, 0 , 6992 , 319, 133), // #1129 - INST(Vlddqu , VexRm_Lx , V(F20F00,F0,_,x,I,_,_,_ ), 0 , 109, 0 , 7002 , 320, 135), // #1130 - INST(Vldmxcsr , VexM , V(000F00,AE,2,0,I,_,_,_ ), 0 , 195, 0 , 7009 , 321, 135), // #1131 - INST(Vmaskmovdqu , VexRm_ZDI , V(660F00,F7,_,0,I,_,_,_ ), 0 , 69 , 0 , 7018 , 322, 135), // #1132 - INST(Vmaskmovpd , VexRvmMvr_Lx , V(660F38,2D,_,x,0,_,_,_ ), V(660F38,2F,_,x,0,_,_,_ ), 96 , 84 , 7030 , 323, 135), // #1133 - INST(Vmaskmovps , VexRvmMvr_Lx , V(660F38,2C,_,x,0,_,_,_ ), V(660F38,2E,_,x,0,_,_,_ ), 96 , 85 , 7041 , 323, 135), // #1134 - INST(Vmaxpd , VexRvm_Lx , V(660F00,5F,_,x,I,1,4,FV ), 0 , 103, 0 , 7052 , 324, 131), // #1135 - INST(Vmaxph , VexRvm_Lx , E(00MAP5,5F,_,_,_,0,4,FV ), 0 , 104, 0 , 7059 , 325, 132), // #1136 - INST(Vmaxps , VexRvm_Lx , V(000F00,5F,_,x,I,0,4,FV ), 0 , 105, 0 , 7066 , 326, 131), // #1137 - INST(Vmaxsd , VexRvm , V(F20F00,5F,_,I,I,1,3,T1S), 0 , 106, 0 , 7073 , 327, 131), // #1138 - INST(Vmaxsh , VexRvm , E(F3MAP5,5F,_,_,_,0,1,T1S), 0 , 107, 0 , 7080 , 254, 134), // #1139 - INST(Vmaxss , VexRvm , V(F30F00,5F,_,I,I,0,2,T1S), 0 , 108, 0 , 7087 , 258, 131), // #1140 - INST(Vmcall , X86Op , O(000F01,C1,_,_,_,_,_,_ ), 0 , 21 , 0 , 7094 , 30 , 58 ), // #1141 - INST(Vmclear , X86M_Only , O(660F00,C7,6,_,_,_,_,_ ), 0 , 26 , 0 , 7101 , 32 , 58 ), // #1142 - INST(Vmfunc , X86Op , O(000F01,D4,_,_,_,_,_,_ ), 0 , 21 , 0 , 7109 , 30 , 58 ), // #1143 - INST(Vminpd , VexRvm_Lx , V(660F00,5D,_,x,I,1,4,FV ), 0 , 103, 0 , 7116 , 324, 131), // #1144 - INST(Vminph , VexRvm_Lx , E(00MAP5,5D,_,_,_,0,4,FV ), 0 , 104, 0 , 7123 , 325, 132), // #1145 - INST(Vminps , VexRvm_Lx , V(000F00,5D,_,x,I,0,4,FV ), 0 , 105, 0 , 7130 , 326, 131), // #1146 - INST(Vminsd , VexRvm , V(F20F00,5D,_,I,I,1,3,T1S), 0 , 106, 0 , 7137 , 327, 131), // #1147 - INST(Vminsh , VexRvm , E(F3MAP5,5D,_,_,_,0,1,T1S), 0 , 107, 0 , 7144 , 254, 134), // #1148 - INST(Vminss , VexRvm , V(F30F00,5D,_,I,I,0,2,T1S), 0 , 108, 0 , 7151 , 258, 131), // #1149 - INST(Vmlaunch , X86Op , O(000F01,C2,_,_,_,_,_,_ ), 0 , 21 , 0 , 7158 , 30 , 58 ), // #1150 - INST(Vmload , X86Op_xAX , O(000F01,DA,_,_,_,_,_,_ ), 0 , 21 , 0 , 7167 , 328, 22 ), // #1151 - INST(Vmmcall , X86Op , O(000F01,D9,_,_,_,_,_,_ ), 0 , 21 , 0 , 7174 , 30 , 22 ), // #1152 - INST(Vmovapd , VexRmMr_Lx , V(660F00,28,_,x,I,1,4,FVM), V(660F00,29,_,x,I,1,4,FVM), 103, 86 , 7182 , 329, 155), // #1153 - INST(Vmovaps , VexRmMr_Lx , V(000F00,28,_,x,I,0,4,FVM), V(000F00,29,_,x,I,0,4,FVM), 105, 87 , 7190 , 329, 155), // #1154 - INST(Vmovd , VexMovdMovq , V(660F00,6E,_,0,0,0,2,T1S), V(660F00,7E,_,0,0,0,2,T1S), 196, 88 , 7198 , 330, 133), // #1155 - INST(Vmovddup , VexRm_Lx , V(F20F00,12,_,x,I,1,3,DUP), 0 , 197, 0 , 7204 , 331, 131), // #1156 - INST(Vmovdqa , VexRmMr_Lx , V(660F00,6F,_,x,I,_,_,_ ), V(660F00,7F,_,x,I,_,_,_ ), 69 , 89 , 7213 , 332, 156), // #1157 - INST(Vmovdqa32 , VexRmMr_Lx , E(660F00,6F,_,x,_,0,4,FVM), E(660F00,7F,_,x,_,0,4,FVM), 198, 90 , 7221 , 333, 157), // #1158 - INST(Vmovdqa64 , VexRmMr_Lx , E(660F00,6F,_,x,_,1,4,FVM), E(660F00,7F,_,x,_,1,4,FVM), 135, 91 , 7231 , 333, 157), // #1159 - INST(Vmovdqu , VexRmMr_Lx , V(F30F00,6F,_,x,I,_,_,_ ), V(F30F00,7F,_,x,I,_,_,_ ), 199, 92 , 7241 , 332, 156), // #1160 - INST(Vmovdqu16 , VexRmMr_Lx , E(F20F00,6F,_,x,_,1,4,FVM), E(F20F00,7F,_,x,_,1,4,FVM), 166, 93 , 7249 , 333, 158), // #1161 - INST(Vmovdqu32 , VexRmMr_Lx , E(F30F00,6F,_,x,_,0,4,FVM), E(F30F00,7F,_,x,_,0,4,FVM), 200, 94 , 7259 , 333, 157), // #1162 - INST(Vmovdqu64 , VexRmMr_Lx , E(F30F00,6F,_,x,_,1,4,FVM), E(F30F00,7F,_,x,_,1,4,FVM), 149, 95 , 7269 , 333, 157), // #1163 - INST(Vmovdqu8 , VexRmMr_Lx , E(F20F00,6F,_,x,_,0,4,FVM), E(F20F00,7F,_,x,_,0,4,FVM), 164, 96 , 7279 , 333, 158), // #1164 - INST(Vmovhlps , VexRvm , V(000F00,12,_,0,I,0,_,_ ), 0 , 72 , 0 , 7288 , 334, 133), // #1165 - INST(Vmovhpd , VexRvmMr , V(660F00,16,_,0,I,1,3,T1S), V(660F00,17,_,0,I,1,3,T1S), 125, 97 , 7297 , 335, 133), // #1166 - INST(Vmovhps , VexRvmMr , V(000F00,16,_,0,I,0,3,T2 ), V(000F00,17,_,0,I,0,3,T2 ), 201, 98 , 7305 , 335, 133), // #1167 - INST(Vmovlhps , VexRvm , V(000F00,16,_,0,I,0,_,_ ), 0 , 72 , 0 , 7313 , 334, 133), // #1168 - INST(Vmovlpd , VexRvmMr , V(660F00,12,_,0,I,1,3,T1S), V(660F00,13,_,0,I,1,3,T1S), 125, 99 , 7322 , 335, 133), // #1169 - INST(Vmovlps , VexRvmMr , V(000F00,12,_,0,I,0,3,T2 ), V(000F00,13,_,0,I,0,3,T2 ), 201, 100, 7330 , 335, 133), // #1170 - INST(Vmovmskpd , VexRm_Lx , V(660F00,50,_,x,I,_,_,_ ), 0 , 69 , 0 , 7338 , 336, 135), // #1171 - INST(Vmovmskps , VexRm_Lx , V(000F00,50,_,x,I,_,_,_ ), 0 , 72 , 0 , 7348 , 336, 135), // #1172 - INST(Vmovntdq , VexMr_Lx , V(660F00,E7,_,x,I,0,4,FVM), 0 , 144, 0 , 7358 , 337, 131), // #1173 - INST(Vmovntdqa , VexRm_Lx , V(660F38,2A,_,x,I,0,4,FVM), 0 , 110, 0 , 7367 , 338, 142), // #1174 - INST(Vmovntpd , VexMr_Lx , V(660F00,2B,_,x,I,1,4,FVM), 0 , 103, 0 , 7377 , 337, 131), // #1175 - INST(Vmovntps , VexMr_Lx , V(000F00,2B,_,x,I,0,4,FVM), 0 , 105, 0 , 7386 , 337, 131), // #1176 - INST(Vmovq , VexMovdMovq , V(660F00,6E,_,0,I,1,3,T1S), V(660F00,7E,_,0,I,1,3,T1S), 125, 101, 7395 , 339, 159), // #1177 - INST(Vmovsd , VexMovssMovsd , V(F20F00,10,_,I,I,1,3,T1S), V(F20F00,11,_,I,I,1,3,T1S), 106, 102, 7401 , 340, 159), // #1178 - INST(Vmovsh , VexMovssMovsd , E(F3MAP5,10,_,I,_,0,1,T1S), E(F3MAP5,11,_,I,_,0,1,T1S), 107, 103, 7408 , 341, 134), // #1179 - INST(Vmovshdup , VexRm_Lx , V(F30F00,16,_,x,I,0,4,FVM), 0 , 161, 0 , 7415 , 342, 131), // #1180 - INST(Vmovsldup , VexRm_Lx , V(F30F00,12,_,x,I,0,4,FVM), 0 , 161, 0 , 7425 , 342, 131), // #1181 - INST(Vmovss , VexMovssMovsd , V(F30F00,10,_,I,I,0,2,T1S), V(F30F00,11,_,I,I,0,2,T1S), 108, 104, 7435 , 343, 159), // #1182 - INST(Vmovupd , VexRmMr_Lx , V(660F00,10,_,x,I,1,4,FVM), V(660F00,11,_,x,I,1,4,FVM), 103, 105, 7442 , 329, 155), // #1183 - INST(Vmovups , VexRmMr_Lx , V(000F00,10,_,x,I,0,4,FVM), V(000F00,11,_,x,I,0,4,FVM), 105, 106, 7450 , 329, 155), // #1184 - INST(Vmovw , VexMovdMovq , E(66MAP5,6E,_,0,_,I,1,T1S), E(66MAP5,7E,_,0,_,I,1,T1S), 202, 107, 7458 , 344, 134), // #1185 - INST(Vmpsadbw , VexRvmi_Lx , V(660F3A,42,_,x,I,_,_,_ ), 0 , 73 , 0 , 7464 , 214, 160), // #1186 - INST(Vmptrld , X86M_Only , O(000F00,C7,6,_,_,_,_,_ ), 0 , 80 , 0 , 7473 , 32 , 58 ), // #1187 - INST(Vmptrst , X86M_Only , O(000F00,C7,7,_,_,_,_,_ ), 0 , 22 , 0 , 7481 , 32 , 58 ), // #1188 - INST(Vmread , X86Mr_NoSize , O(000F00,78,_,_,_,_,_,_ ), 0 , 4 , 0 , 7489 , 345, 58 ), // #1189 - INST(Vmresume , X86Op , O(000F01,C3,_,_,_,_,_,_ ), 0 , 21 , 0 , 7496 , 30 , 58 ), // #1190 - INST(Vmrun , X86Op_xAX , O(000F01,D8,_,_,_,_,_,_ ), 0 , 21 , 0 , 7505 , 328, 22 ), // #1191 - INST(Vmsave , X86Op_xAX , O(000F01,DB,_,_,_,_,_,_ ), 0 , 21 , 0 , 7511 , 328, 22 ), // #1192 - INST(Vmulpd , VexRvm_Lx , V(660F00,59,_,x,I,1,4,FV ), 0 , 103, 0 , 7518 , 196, 131), // #1193 - INST(Vmulph , VexRvm_Lx , E(00MAP5,59,_,_,_,0,4,FV ), 0 , 104, 0 , 7525 , 197, 132), // #1194 - INST(Vmulps , VexRvm_Lx , V(000F00,59,_,x,I,0,4,FV ), 0 , 105, 0 , 7532 , 198, 131), // #1195 - INST(Vmulsd , VexRvm , V(F20F00,59,_,I,I,1,3,T1S), 0 , 106, 0 , 7539 , 199, 133), // #1196 - INST(Vmulsh , VexRvm , E(F3MAP5,59,_,_,_,0,1,T1S), 0 , 107, 0 , 7546 , 200, 134), // #1197 - INST(Vmulss , VexRvm , V(F30F00,59,_,I,I,0,2,T1S), 0 , 108, 0 , 7553 , 201, 133), // #1198 - INST(Vmwrite , X86Rm_NoSize , O(000F00,79,_,_,_,_,_,_ ), 0 , 4 , 0 , 7560 , 346, 58 ), // #1199 - INST(Vmxon , X86M_Only , O(F30F00,C7,6,_,_,_,_,_ ), 0 , 24 , 0 , 7568 , 32 , 58 ), // #1200 - INST(Vorpd , VexRvm_Lx , V(660F00,56,_,x,I,1,4,FV ), 0 , 103, 0 , 7574 , 210, 139), // #1201 - INST(Vorps , VexRvm_Lx , V(000F00,56,_,x,I,0,4,FV ), 0 , 105, 0 , 7580 , 211, 139), // #1202 - INST(Vp2intersectd , VexRvm_Lx_2xK , E(F20F38,68,_,_,_,0,4,FV ), 0 , 131, 0 , 7586 , 347, 161), // #1203 - INST(Vp2intersectq , VexRvm_Lx_2xK , E(F20F38,68,_,_,_,1,4,FV ), 0 , 203, 0 , 7600 , 348, 161), // #1204 - INST(Vp4dpwssd , VexRm_T1_4X , E(F20F38,52,_,2,_,0,4,T4X), 0 , 101, 0 , 7614 , 194, 162), // #1205 - INST(Vp4dpwssds , VexRm_T1_4X , E(F20F38,53,_,2,_,0,4,T4X), 0 , 101, 0 , 7624 , 194, 162), // #1206 - INST(Vpabsb , VexRm_Lx , V(660F38,1C,_,x,I,_,4,FVM), 0 , 110, 0 , 7635 , 342, 163), // #1207 - INST(Vpabsd , VexRm_Lx , V(660F38,1E,_,x,I,0,4,FV ), 0 , 110, 0 , 7642 , 349, 142), // #1208 - INST(Vpabsq , VexRm_Lx , E(660F38,1F,_,x,_,1,4,FV ), 0 , 113, 0 , 7649 , 350, 138), // #1209 - INST(Vpabsw , VexRm_Lx , V(660F38,1D,_,x,I,_,4,FVM), 0 , 110, 0 , 7656 , 342, 163), // #1210 - INST(Vpackssdw , VexRvm_Lx , V(660F00,6B,_,x,I,0,4,FV ), 0 , 144, 0 , 7663 , 209, 163), // #1211 - INST(Vpacksswb , VexRvm_Lx , V(660F00,63,_,x,I,I,4,FVM), 0 , 144, 0 , 7673 , 315, 163), // #1212 - INST(Vpackusdw , VexRvm_Lx , V(660F38,2B,_,x,I,0,4,FV ), 0 , 110, 0 , 7683 , 209, 163), // #1213 - INST(Vpackuswb , VexRvm_Lx , V(660F00,67,_,x,I,I,4,FVM), 0 , 144, 0 , 7693 , 315, 163), // #1214 - INST(Vpaddb , VexRvm_Lx , V(660F00,FC,_,x,I,I,4,FVM), 0 , 144, 0 , 7703 , 315, 163), // #1215 - INST(Vpaddd , VexRvm_Lx , V(660F00,FE,_,x,I,0,4,FV ), 0 , 144, 0 , 7710 , 209, 142), // #1216 - INST(Vpaddq , VexRvm_Lx , V(660F00,D4,_,x,I,1,4,FV ), 0 , 103, 0 , 7717 , 208, 142), // #1217 - INST(Vpaddsb , VexRvm_Lx , V(660F00,EC,_,x,I,I,4,FVM), 0 , 144, 0 , 7724 , 315, 163), // #1218 - INST(Vpaddsw , VexRvm_Lx , V(660F00,ED,_,x,I,I,4,FVM), 0 , 144, 0 , 7732 , 315, 163), // #1219 - INST(Vpaddusb , VexRvm_Lx , V(660F00,DC,_,x,I,I,4,FVM), 0 , 144, 0 , 7740 , 315, 163), // #1220 - INST(Vpaddusw , VexRvm_Lx , V(660F00,DD,_,x,I,I,4,FVM), 0 , 144, 0 , 7749 , 315, 163), // #1221 - INST(Vpaddw , VexRvm_Lx , V(660F00,FD,_,x,I,I,4,FVM), 0 , 144, 0 , 7758 , 315, 163), // #1222 - INST(Vpalignr , VexRvmi_Lx , V(660F3A,0F,_,x,I,I,4,FVM), 0 , 204, 0 , 7765 , 314, 163), // #1223 - INST(Vpand , VexRvm_Lx , V(660F00,DB,_,x,I,_,_,_ ), 0 , 69 , 0 , 7774 , 351, 160), // #1224 - INST(Vpandd , VexRvm_Lx , E(660F00,DB,_,x,_,0,4,FV ), 0 , 198, 0 , 7780 , 352, 138), // #1225 - INST(Vpandn , VexRvm_Lx , V(660F00,DF,_,x,I,_,_,_ ), 0 , 69 , 0 , 7787 , 353, 160), // #1226 - INST(Vpandnd , VexRvm_Lx , E(660F00,DF,_,x,_,0,4,FV ), 0 , 198, 0 , 7794 , 354, 138), // #1227 - INST(Vpandnq , VexRvm_Lx , E(660F00,DF,_,x,_,1,4,FV ), 0 , 135, 0 , 7802 , 355, 138), // #1228 - INST(Vpandq , VexRvm_Lx , E(660F00,DB,_,x,_,1,4,FV ), 0 , 135, 0 , 7810 , 356, 138), // #1229 - INST(Vpavgb , VexRvm_Lx , V(660F00,E0,_,x,I,I,4,FVM), 0 , 144, 0 , 7817 , 315, 163), // #1230 - INST(Vpavgw , VexRvm_Lx , V(660F00,E3,_,x,I,I,4,FVM), 0 , 144, 0 , 7824 , 315, 163), // #1231 - INST(Vpblendd , VexRvmi_Lx , V(660F3A,02,_,x,0,_,_,_ ), 0 , 73 , 0 , 7831 , 214, 141), // #1232 - INST(Vpblendmb , VexRvm_Lx , E(660F38,66,_,x,_,0,4,FVM), 0 , 114, 0 , 7840 , 357, 146), // #1233 - INST(Vpblendmd , VexRvm_Lx , E(660F38,64,_,x,_,0,4,FV ), 0 , 114, 0 , 7850 , 213, 138), // #1234 - INST(Vpblendmq , VexRvm_Lx , E(660F38,64,_,x,_,1,4,FV ), 0 , 113, 0 , 7860 , 212, 138), // #1235 - INST(Vpblendmw , VexRvm_Lx , E(660F38,66,_,x,_,1,4,FVM), 0 , 113, 0 , 7870 , 357, 146), // #1236 - INST(Vpblendvb , VexRvmr_Lx , V(660F3A,4C,_,x,0,_,_,_ ), 0 , 73 , 0 , 7880 , 215, 160), // #1237 - INST(Vpblendw , VexRvmi_Lx , V(660F3A,0E,_,x,I,_,_,_ ), 0 , 73 , 0 , 7890 , 214, 160), // #1238 - INST(Vpbroadcastb , VexRm_Lx_Bcst , V(660F38,78,_,x,0,0,0,T1S), E(660F38,7A,_,x,0,0,0,T1S), 96 , 108, 7899 , 358, 164), // #1239 - INST(Vpbroadcastd , VexRm_Lx_Bcst , V(660F38,58,_,x,0,0,2,T1S), E(660F38,7C,_,x,0,0,0,T1S), 122, 109, 7912 , 359, 152), // #1240 - INST(Vpbroadcastmb2q , VexRm_Lx , E(F30F38,2A,_,x,_,1,_,_ ), 0 , 205, 0 , 7925 , 360, 165), // #1241 - INST(Vpbroadcastmw2d , VexRm_Lx , E(F30F38,3A,_,x,_,0,_,_ ), 0 , 206, 0 , 7941 , 360, 165), // #1242 - INST(Vpbroadcastq , VexRm_Lx_Bcst , V(660F38,59,_,x,0,1,3,T1S), E(660F38,7C,_,x,0,1,0,T1S), 121, 110, 7957 , 361, 152), // #1243 - INST(Vpbroadcastw , VexRm_Lx_Bcst , V(660F38,79,_,x,0,0,1,T1S), E(660F38,7B,_,x,0,0,0,T1S), 207, 111, 7970 , 362, 164), // #1244 - INST(Vpclmulqdq , VexRvmi_Lx , V(660F3A,44,_,x,I,_,4,FVM), 0 , 204, 0 , 7983 , 363, 166), // #1245 - INST(Vpcmov , VexRvrmRvmr_Lx , V(XOP_M8,A2,_,x,x,_,_,_ ), 0 , 208, 0 , 7994 , 289, 151), // #1246 - INST(Vpcmpb , VexRvmi_Lx , E(660F3A,3F,_,x,_,0,4,FVM), 0 , 111, 0 , 8001 , 364, 146), // #1247 - INST(Vpcmpd , VexRvmi_Lx , E(660F3A,1F,_,x,_,0,4,FV ), 0 , 111, 0 , 8008 , 365, 138), // #1248 - INST(Vpcmpeqb , VexRvm_Lx_KEvex , V(660F00,74,_,x,I,I,4,FV ), 0 , 144, 0 , 8015 , 366, 163), // #1249 - INST(Vpcmpeqd , VexRvm_Lx_KEvex , V(660F00,76,_,x,I,0,4,FVM), 0 , 144, 0 , 8024 , 367, 142), // #1250 - INST(Vpcmpeqq , VexRvm_Lx_KEvex , V(660F38,29,_,x,I,1,4,FVM), 0 , 209, 0 , 8033 , 368, 142), // #1251 - INST(Vpcmpeqw , VexRvm_Lx_KEvex , V(660F00,75,_,x,I,I,4,FV ), 0 , 144, 0 , 8042 , 366, 163), // #1252 - INST(Vpcmpestri , VexRmi , V(660F3A,61,_,0,I,_,_,_ ), 0 , 73 , 0 , 8051 , 369, 167), // #1253 - INST(Vpcmpestrm , VexRmi , V(660F3A,60,_,0,I,_,_,_ ), 0 , 73 , 0 , 8062 , 370, 167), // #1254 - INST(Vpcmpgtb , VexRvm_Lx_KEvex , V(660F00,64,_,x,I,I,4,FV ), 0 , 144, 0 , 8073 , 366, 163), // #1255 - INST(Vpcmpgtd , VexRvm_Lx_KEvex , V(660F00,66,_,x,I,0,4,FVM), 0 , 144, 0 , 8082 , 367, 142), // #1256 - INST(Vpcmpgtq , VexRvm_Lx_KEvex , V(660F38,37,_,x,I,1,4,FVM), 0 , 209, 0 , 8091 , 368, 142), // #1257 - INST(Vpcmpgtw , VexRvm_Lx_KEvex , V(660F00,65,_,x,I,I,4,FV ), 0 , 144, 0 , 8100 , 366, 163), // #1258 - INST(Vpcmpistri , VexRmi , V(660F3A,63,_,0,I,_,_,_ ), 0 , 73 , 0 , 8109 , 371, 167), // #1259 - INST(Vpcmpistrm , VexRmi , V(660F3A,62,_,0,I,_,_,_ ), 0 , 73 , 0 , 8120 , 372, 167), // #1260 - INST(Vpcmpq , VexRvmi_Lx , E(660F3A,1F,_,x,_,1,4,FV ), 0 , 112, 0 , 8131 , 373, 138), // #1261 - INST(Vpcmpub , VexRvmi_Lx , E(660F3A,3E,_,x,_,0,4,FVM), 0 , 111, 0 , 8138 , 364, 146), // #1262 - INST(Vpcmpud , VexRvmi_Lx , E(660F3A,1E,_,x,_,0,4,FV ), 0 , 111, 0 , 8146 , 365, 138), // #1263 - INST(Vpcmpuq , VexRvmi_Lx , E(660F3A,1E,_,x,_,1,4,FV ), 0 , 112, 0 , 8154 , 373, 138), // #1264 - INST(Vpcmpuw , VexRvmi_Lx , E(660F3A,3E,_,x,_,1,4,FVM), 0 , 112, 0 , 8162 , 373, 146), // #1265 - INST(Vpcmpw , VexRvmi_Lx , E(660F3A,3F,_,x,_,1,4,FVM), 0 , 112, 0 , 8170 , 373, 146), // #1266 - INST(Vpcomb , VexRvmi , V(XOP_M8,CC,_,0,0,_,_,_ ), 0 , 208, 0 , 8177 , 276, 151), // #1267 - INST(Vpcomd , VexRvmi , V(XOP_M8,CE,_,0,0,_,_,_ ), 0 , 208, 0 , 8184 , 276, 151), // #1268 - INST(Vpcompressb , VexMr_Lx , E(660F38,63,_,x,_,0,0,T1S), 0 , 210, 0 , 8191 , 232, 168), // #1269 - INST(Vpcompressd , VexMr_Lx , E(660F38,8B,_,x,_,0,2,T1S), 0 , 129, 0 , 8203 , 232, 138), // #1270 - INST(Vpcompressq , VexMr_Lx , E(660F38,8B,_,x,_,1,3,T1S), 0 , 128, 0 , 8215 , 232, 138), // #1271 - INST(Vpcompressw , VexMr_Lx , E(660F38,63,_,x,_,1,1,T1S), 0 , 211, 0 , 8227 , 232, 168), // #1272 - INST(Vpcomq , VexRvmi , V(XOP_M8,CF,_,0,0,_,_,_ ), 0 , 208, 0 , 8239 , 276, 151), // #1273 - INST(Vpcomub , VexRvmi , V(XOP_M8,EC,_,0,0,_,_,_ ), 0 , 208, 0 , 8246 , 276, 151), // #1274 - INST(Vpcomud , VexRvmi , V(XOP_M8,EE,_,0,0,_,_,_ ), 0 , 208, 0 , 8254 , 276, 151), // #1275 - INST(Vpcomuq , VexRvmi , V(XOP_M8,EF,_,0,0,_,_,_ ), 0 , 208, 0 , 8262 , 276, 151), // #1276 - INST(Vpcomuw , VexRvmi , V(XOP_M8,ED,_,0,0,_,_,_ ), 0 , 208, 0 , 8270 , 276, 151), // #1277 - INST(Vpcomw , VexRvmi , V(XOP_M8,CD,_,0,0,_,_,_ ), 0 , 208, 0 , 8278 , 276, 151), // #1278 - INST(Vpconflictd , VexRm_Lx , E(660F38,C4,_,x,_,0,4,FV ), 0 , 114, 0 , 8285 , 374, 165), // #1279 - INST(Vpconflictq , VexRm_Lx , E(660F38,C4,_,x,_,1,4,FV ), 0 , 113, 0 , 8297 , 374, 165), // #1280 - INST(Vpdpbusd , VexRvm_Lx , V(660F38,50,_,x,_,0,4,FV ), 0 , 110, 0 , 8309 , 375, 169), // #1281 - INST(Vpdpbusds , VexRvm_Lx , V(660F38,51,_,x,_,0,4,FV ), 0 , 110, 0 , 8318 , 375, 169), // #1282 - INST(Vpdpwssd , VexRvm_Lx , V(660F38,52,_,x,_,0,4,FV ), 0 , 110, 0 , 8328 , 375, 169), // #1283 - INST(Vpdpwssds , VexRvm_Lx , V(660F38,53,_,x,_,0,4,FV ), 0 , 110, 0 , 8337 , 375, 169), // #1284 - INST(Vperm2f128 , VexRvmi , V(660F3A,06,_,1,0,_,_,_ ), 0 , 172, 0 , 8347 , 376, 135), // #1285 - INST(Vperm2i128 , VexRvmi , V(660F3A,46,_,1,0,_,_,_ ), 0 , 172, 0 , 8358 , 376, 141), // #1286 - INST(Vpermb , VexRvm_Lx , E(660F38,8D,_,x,_,0,4,FVM), 0 , 114, 0 , 8369 , 357, 170), // #1287 - INST(Vpermd , VexRvm_Lx , V(660F38,36,_,x,0,0,4,FV ), 0 , 110, 0 , 8376 , 377, 152), // #1288 - INST(Vpermi2b , VexRvm_Lx , E(660F38,75,_,x,_,0,4,FVM), 0 , 114, 0 , 8383 , 357, 170), // #1289 - INST(Vpermi2d , VexRvm_Lx , E(660F38,76,_,x,_,0,4,FV ), 0 , 114, 0 , 8392 , 213, 138), // #1290 - INST(Vpermi2pd , VexRvm_Lx , E(660F38,77,_,x,_,1,4,FV ), 0 , 113, 0 , 8401 , 212, 138), // #1291 - INST(Vpermi2ps , VexRvm_Lx , E(660F38,77,_,x,_,0,4,FV ), 0 , 114, 0 , 8411 , 213, 138), // #1292 - INST(Vpermi2q , VexRvm_Lx , E(660F38,76,_,x,_,1,4,FV ), 0 , 113, 0 , 8421 , 212, 138), // #1293 - INST(Vpermi2w , VexRvm_Lx , E(660F38,75,_,x,_,1,4,FVM), 0 , 113, 0 , 8430 , 357, 146), // #1294 - INST(Vpermil2pd , VexRvrmiRvmri_Lx , V(660F3A,49,_,x,x,_,_,_ ), 0 , 73 , 0 , 8439 , 378, 151), // #1295 - INST(Vpermil2ps , VexRvrmiRvmri_Lx , V(660F3A,48,_,x,x,_,_,_ ), 0 , 73 , 0 , 8450 , 378, 151), // #1296 - INST(Vpermilpd , VexRvmRmi_Lx , V(660F38,0D,_,x,0,1,4,FV ), V(660F3A,05,_,x,0,1,4,FV ), 209, 112, 8461 , 379, 131), // #1297 - INST(Vpermilps , VexRvmRmi_Lx , V(660F38,0C,_,x,0,0,4,FV ), V(660F3A,04,_,x,0,0,4,FV ), 110, 113, 8471 , 380, 131), // #1298 - INST(Vpermpd , VexRvmRmi_Lx , E(660F38,16,_,x,1,1,4,FV ), V(660F3A,01,_,x,1,1,4,FV ), 212, 114, 8481 , 381, 152), // #1299 - INST(Vpermps , VexRvm_Lx , V(660F38,16,_,x,0,0,4,FV ), 0 , 110, 0 , 8489 , 377, 152), // #1300 - INST(Vpermq , VexRvmRmi_Lx , E(660F38,36,_,x,_,1,4,FV ), V(660F3A,00,_,x,1,1,4,FV ), 113, 115, 8497 , 381, 152), // #1301 - INST(Vpermt2b , VexRvm_Lx , E(660F38,7D,_,x,_,0,4,FVM), 0 , 114, 0 , 8504 , 357, 170), // #1302 - INST(Vpermt2d , VexRvm_Lx , E(660F38,7E,_,x,_,0,4,FV ), 0 , 114, 0 , 8513 , 213, 138), // #1303 - INST(Vpermt2pd , VexRvm_Lx , E(660F38,7F,_,x,_,1,4,FV ), 0 , 113, 0 , 8522 , 212, 138), // #1304 - INST(Vpermt2ps , VexRvm_Lx , E(660F38,7F,_,x,_,0,4,FV ), 0 , 114, 0 , 8532 , 213, 138), // #1305 - INST(Vpermt2q , VexRvm_Lx , E(660F38,7E,_,x,_,1,4,FV ), 0 , 113, 0 , 8542 , 212, 138), // #1306 - INST(Vpermt2w , VexRvm_Lx , E(660F38,7D,_,x,_,1,4,FVM), 0 , 113, 0 , 8551 , 357, 146), // #1307 - INST(Vpermw , VexRvm_Lx , E(660F38,8D,_,x,_,1,4,FVM), 0 , 113, 0 , 8560 , 357, 146), // #1308 - INST(Vpexpandb , VexRm_Lx , E(660F38,62,_,x,_,0,0,T1S), 0 , 210, 0 , 8567 , 279, 168), // #1309 - INST(Vpexpandd , VexRm_Lx , E(660F38,89,_,x,_,0,2,T1S), 0 , 129, 0 , 8577 , 279, 138), // #1310 - INST(Vpexpandq , VexRm_Lx , E(660F38,89,_,x,_,1,3,T1S), 0 , 128, 0 , 8587 , 279, 138), // #1311 - INST(Vpexpandw , VexRm_Lx , E(660F38,62,_,x,_,1,1,T1S), 0 , 211, 0 , 8597 , 279, 168), // #1312 - INST(Vpextrb , VexMri , V(660F3A,14,_,0,0,I,0,T1S), 0 , 73 , 0 , 8607 , 382, 171), // #1313 - INST(Vpextrd , VexMri , V(660F3A,16,_,0,0,0,2,T1S), 0 , 177, 0 , 8615 , 283, 172), // #1314 - INST(Vpextrq , VexMri , V(660F3A,16,_,0,1,1,3,T1S), 0 , 213, 0 , 8623 , 383, 172), // #1315 - INST(Vpextrw , VexMri_Vpextrw , V(660F3A,15,_,0,0,I,1,T1S), 0 , 214, 0 , 8631 , 384, 171), // #1316 - INST(Vpgatherdd , VexRmvRm_VM , V(660F38,90,_,x,0,_,_,_ ), E(660F38,90,_,x,_,0,2,T1S), 96 , 116, 8639 , 302, 152), // #1317 - INST(Vpgatherdq , VexRmvRm_VM , V(660F38,90,_,x,1,_,_,_ ), E(660F38,90,_,x,_,1,3,T1S), 189, 117, 8650 , 301, 152), // #1318 - INST(Vpgatherqd , VexRmvRm_VM , V(660F38,91,_,x,0,_,_,_ ), E(660F38,91,_,x,_,0,2,T1S), 96 , 118, 8661 , 307, 152), // #1319 - INST(Vpgatherqq , VexRmvRm_VM , V(660F38,91,_,x,1,_,_,_ ), E(660F38,91,_,x,_,1,3,T1S), 189, 119, 8672 , 306, 152), // #1320 - INST(Vphaddbd , VexRm , V(XOP_M9,C2,_,0,0,_,_,_ ), 0 , 79 , 0 , 8683 , 204, 151), // #1321 - INST(Vphaddbq , VexRm , V(XOP_M9,C3,_,0,0,_,_,_ ), 0 , 79 , 0 , 8692 , 204, 151), // #1322 - INST(Vphaddbw , VexRm , V(XOP_M9,C1,_,0,0,_,_,_ ), 0 , 79 , 0 , 8701 , 204, 151), // #1323 - INST(Vphaddd , VexRvm_Lx , V(660F38,02,_,x,I,_,_,_ ), 0 , 96 , 0 , 8710 , 202, 160), // #1324 - INST(Vphadddq , VexRm , V(XOP_M9,CB,_,0,0,_,_,_ ), 0 , 79 , 0 , 8718 , 204, 151), // #1325 - INST(Vphaddsw , VexRvm_Lx , V(660F38,03,_,x,I,_,_,_ ), 0 , 96 , 0 , 8727 , 202, 160), // #1326 - INST(Vphaddubd , VexRm , V(XOP_M9,D2,_,0,0,_,_,_ ), 0 , 79 , 0 , 8736 , 204, 151), // #1327 - INST(Vphaddubq , VexRm , V(XOP_M9,D3,_,0,0,_,_,_ ), 0 , 79 , 0 , 8746 , 204, 151), // #1328 - INST(Vphaddubw , VexRm , V(XOP_M9,D1,_,0,0,_,_,_ ), 0 , 79 , 0 , 8756 , 204, 151), // #1329 - INST(Vphaddudq , VexRm , V(XOP_M9,DB,_,0,0,_,_,_ ), 0 , 79 , 0 , 8766 , 204, 151), // #1330 - INST(Vphadduwd , VexRm , V(XOP_M9,D6,_,0,0,_,_,_ ), 0 , 79 , 0 , 8776 , 204, 151), // #1331 - INST(Vphadduwq , VexRm , V(XOP_M9,D7,_,0,0,_,_,_ ), 0 , 79 , 0 , 8786 , 204, 151), // #1332 - INST(Vphaddw , VexRvm_Lx , V(660F38,01,_,x,I,_,_,_ ), 0 , 96 , 0 , 8796 , 202, 160), // #1333 - INST(Vphaddwd , VexRm , V(XOP_M9,C6,_,0,0,_,_,_ ), 0 , 79 , 0 , 8804 , 204, 151), // #1334 - INST(Vphaddwq , VexRm , V(XOP_M9,C7,_,0,0,_,_,_ ), 0 , 79 , 0 , 8813 , 204, 151), // #1335 - INST(Vphminposuw , VexRm , V(660F38,41,_,0,I,_,_,_ ), 0 , 96 , 0 , 8822 , 204, 135), // #1336 - INST(Vphsubbw , VexRm , V(XOP_M9,E1,_,0,0,_,_,_ ), 0 , 79 , 0 , 8834 , 204, 151), // #1337 - INST(Vphsubd , VexRvm_Lx , V(660F38,06,_,x,I,_,_,_ ), 0 , 96 , 0 , 8843 , 202, 160), // #1338 - INST(Vphsubdq , VexRm , V(XOP_M9,E3,_,0,0,_,_,_ ), 0 , 79 , 0 , 8851 , 204, 151), // #1339 - INST(Vphsubsw , VexRvm_Lx , V(660F38,07,_,x,I,_,_,_ ), 0 , 96 , 0 , 8860 , 202, 160), // #1340 - INST(Vphsubw , VexRvm_Lx , V(660F38,05,_,x,I,_,_,_ ), 0 , 96 , 0 , 8869 , 202, 160), // #1341 - INST(Vphsubwd , VexRm , V(XOP_M9,E2,_,0,0,_,_,_ ), 0 , 79 , 0 , 8877 , 204, 151), // #1342 - INST(Vpinsrb , VexRvmi , V(660F3A,20,_,0,0,I,0,T1S), 0 , 73 , 0 , 8886 , 385, 171), // #1343 - INST(Vpinsrd , VexRvmi , V(660F3A,22,_,0,0,0,2,T1S), 0 , 177, 0 , 8894 , 386, 172), // #1344 - INST(Vpinsrq , VexRvmi , V(660F3A,22,_,0,1,1,3,T1S), 0 , 213, 0 , 8902 , 387, 172), // #1345 - INST(Vpinsrw , VexRvmi , V(660F00,C4,_,0,0,I,1,T1S), 0 , 215, 0 , 8910 , 388, 171), // #1346 - INST(Vplzcntd , VexRm_Lx , E(660F38,44,_,x,_,0,4,FV ), 0 , 114, 0 , 8918 , 374, 165), // #1347 - INST(Vplzcntq , VexRm_Lx , E(660F38,44,_,x,_,1,4,FV ), 0 , 113, 0 , 8927 , 350, 165), // #1348 - INST(Vpmacsdd , VexRvmr , V(XOP_M8,9E,_,0,0,_,_,_ ), 0 , 208, 0 , 8936 , 389, 151), // #1349 - INST(Vpmacsdqh , VexRvmr , V(XOP_M8,9F,_,0,0,_,_,_ ), 0 , 208, 0 , 8945 , 389, 151), // #1350 - INST(Vpmacsdql , VexRvmr , V(XOP_M8,97,_,0,0,_,_,_ ), 0 , 208, 0 , 8955 , 389, 151), // #1351 - INST(Vpmacssdd , VexRvmr , V(XOP_M8,8E,_,0,0,_,_,_ ), 0 , 208, 0 , 8965 , 389, 151), // #1352 - INST(Vpmacssdqh , VexRvmr , V(XOP_M8,8F,_,0,0,_,_,_ ), 0 , 208, 0 , 8975 , 389, 151), // #1353 - INST(Vpmacssdql , VexRvmr , V(XOP_M8,87,_,0,0,_,_,_ ), 0 , 208, 0 , 8986 , 389, 151), // #1354 - INST(Vpmacsswd , VexRvmr , V(XOP_M8,86,_,0,0,_,_,_ ), 0 , 208, 0 , 8997 , 389, 151), // #1355 - INST(Vpmacssww , VexRvmr , V(XOP_M8,85,_,0,0,_,_,_ ), 0 , 208, 0 , 9007 , 389, 151), // #1356 - INST(Vpmacswd , VexRvmr , V(XOP_M8,96,_,0,0,_,_,_ ), 0 , 208, 0 , 9017 , 389, 151), // #1357 - INST(Vpmacsww , VexRvmr , V(XOP_M8,95,_,0,0,_,_,_ ), 0 , 208, 0 , 9026 , 389, 151), // #1358 - INST(Vpmadcsswd , VexRvmr , V(XOP_M8,A6,_,0,0,_,_,_ ), 0 , 208, 0 , 9035 , 389, 151), // #1359 - INST(Vpmadcswd , VexRvmr , V(XOP_M8,B6,_,0,0,_,_,_ ), 0 , 208, 0 , 9046 , 389, 151), // #1360 - INST(Vpmadd52huq , VexRvm_Lx , E(660F38,B5,_,x,_,1,4,FV ), 0 , 113, 0 , 9056 , 212, 173), // #1361 - INST(Vpmadd52luq , VexRvm_Lx , E(660F38,B4,_,x,_,1,4,FV ), 0 , 113, 0 , 9068 , 212, 173), // #1362 - INST(Vpmaddubsw , VexRvm_Lx , V(660F38,04,_,x,I,I,4,FVM), 0 , 110, 0 , 9080 , 315, 163), // #1363 - INST(Vpmaddwd , VexRvm_Lx , V(660F00,F5,_,x,I,I,4,FVM), 0 , 144, 0 , 9091 , 315, 163), // #1364 - INST(Vpmaskmovd , VexRvmMvr_Lx , V(660F38,8C,_,x,0,_,_,_ ), V(660F38,8E,_,x,0,_,_,_ ), 96 , 120, 9100 , 323, 141), // #1365 - INST(Vpmaskmovq , VexRvmMvr_Lx , V(660F38,8C,_,x,1,_,_,_ ), V(660F38,8E,_,x,1,_,_,_ ), 189, 121, 9111 , 323, 141), // #1366 - INST(Vpmaxsb , VexRvm_Lx , V(660F38,3C,_,x,I,I,4,FVM), 0 , 110, 0 , 9122 , 390, 163), // #1367 - INST(Vpmaxsd , VexRvm_Lx , V(660F38,3D,_,x,I,0,4,FV ), 0 , 110, 0 , 9130 , 211, 142), // #1368 - INST(Vpmaxsq , VexRvm_Lx , E(660F38,3D,_,x,_,1,4,FV ), 0 , 113, 0 , 9138 , 212, 138), // #1369 - INST(Vpmaxsw , VexRvm_Lx , V(660F00,EE,_,x,I,I,4,FVM), 0 , 144, 0 , 9146 , 390, 163), // #1370 - INST(Vpmaxub , VexRvm_Lx , V(660F00,DE,_,x,I,I,4,FVM), 0 , 144, 0 , 9154 , 390, 163), // #1371 - INST(Vpmaxud , VexRvm_Lx , V(660F38,3F,_,x,I,0,4,FV ), 0 , 110, 0 , 9162 , 211, 142), // #1372 - INST(Vpmaxuq , VexRvm_Lx , E(660F38,3F,_,x,_,1,4,FV ), 0 , 113, 0 , 9170 , 212, 138), // #1373 - INST(Vpmaxuw , VexRvm_Lx , V(660F38,3E,_,x,I,I,4,FVM), 0 , 110, 0 , 9178 , 390, 163), // #1374 - INST(Vpminsb , VexRvm_Lx , V(660F38,38,_,x,I,I,4,FVM), 0 , 110, 0 , 9186 , 390, 163), // #1375 - INST(Vpminsd , VexRvm_Lx , V(660F38,39,_,x,I,0,4,FV ), 0 , 110, 0 , 9194 , 211, 142), // #1376 - INST(Vpminsq , VexRvm_Lx , E(660F38,39,_,x,_,1,4,FV ), 0 , 113, 0 , 9202 , 212, 138), // #1377 - INST(Vpminsw , VexRvm_Lx , V(660F00,EA,_,x,I,I,4,FVM), 0 , 144, 0 , 9210 , 390, 163), // #1378 - INST(Vpminub , VexRvm_Lx , V(660F00,DA,_,x,I,_,4,FVM), 0 , 144, 0 , 9218 , 390, 163), // #1379 - INST(Vpminud , VexRvm_Lx , V(660F38,3B,_,x,I,0,4,FV ), 0 , 110, 0 , 9226 , 211, 142), // #1380 - INST(Vpminuq , VexRvm_Lx , E(660F38,3B,_,x,_,1,4,FV ), 0 , 113, 0 , 9234 , 212, 138), // #1381 - INST(Vpminuw , VexRvm_Lx , V(660F38,3A,_,x,I,_,4,FVM), 0 , 110, 0 , 9242 , 390, 163), // #1382 - INST(Vpmovb2m , VexRm_Lx , E(F30F38,29,_,x,_,0,_,_ ), 0 , 206, 0 , 9250 , 391, 146), // #1383 - INST(Vpmovd2m , VexRm_Lx , E(F30F38,39,_,x,_,0,_,_ ), 0 , 206, 0 , 9259 , 391, 140), // #1384 - INST(Vpmovdb , VexMr_Lx , E(F30F38,31,_,x,_,0,2,QVM), 0 , 216, 0 , 9268 , 392, 138), // #1385 - INST(Vpmovdw , VexMr_Lx , E(F30F38,33,_,x,_,0,3,HVM), 0 , 217, 0 , 9276 , 393, 138), // #1386 - INST(Vpmovm2b , VexRm_Lx , E(F30F38,28,_,x,_,0,_,_ ), 0 , 206, 0 , 9284 , 360, 146), // #1387 - INST(Vpmovm2d , VexRm_Lx , E(F30F38,38,_,x,_,0,_,_ ), 0 , 206, 0 , 9293 , 360, 140), // #1388 - INST(Vpmovm2q , VexRm_Lx , E(F30F38,38,_,x,_,1,_,_ ), 0 , 205, 0 , 9302 , 360, 140), // #1389 - INST(Vpmovm2w , VexRm_Lx , E(F30F38,28,_,x,_,1,_,_ ), 0 , 205, 0 , 9311 , 360, 146), // #1390 - INST(Vpmovmskb , VexRm_Lx , V(660F00,D7,_,x,I,_,_,_ ), 0 , 69 , 0 , 9320 , 336, 160), // #1391 - INST(Vpmovq2m , VexRm_Lx , E(F30F38,39,_,x,_,1,_,_ ), 0 , 205, 0 , 9330 , 391, 140), // #1392 - INST(Vpmovqb , VexMr_Lx , E(F30F38,32,_,x,_,0,1,OVM), 0 , 218, 0 , 9339 , 394, 138), // #1393 - INST(Vpmovqd , VexMr_Lx , E(F30F38,35,_,x,_,0,3,HVM), 0 , 217, 0 , 9347 , 393, 138), // #1394 - INST(Vpmovqw , VexMr_Lx , E(F30F38,34,_,x,_,0,2,QVM), 0 , 216, 0 , 9355 , 392, 138), // #1395 - INST(Vpmovsdb , VexMr_Lx , E(F30F38,21,_,x,_,0,2,QVM), 0 , 216, 0 , 9363 , 392, 138), // #1396 - INST(Vpmovsdw , VexMr_Lx , E(F30F38,23,_,x,_,0,3,HVM), 0 , 217, 0 , 9372 , 393, 138), // #1397 - INST(Vpmovsqb , VexMr_Lx , E(F30F38,22,_,x,_,0,1,OVM), 0 , 218, 0 , 9381 , 394, 138), // #1398 - INST(Vpmovsqd , VexMr_Lx , E(F30F38,25,_,x,_,0,3,HVM), 0 , 217, 0 , 9390 , 393, 138), // #1399 - INST(Vpmovsqw , VexMr_Lx , E(F30F38,24,_,x,_,0,2,QVM), 0 , 216, 0 , 9399 , 392, 138), // #1400 - INST(Vpmovswb , VexMr_Lx , E(F30F38,20,_,x,_,0,3,HVM), 0 , 217, 0 , 9408 , 393, 146), // #1401 - INST(Vpmovsxbd , VexRm_Lx , V(660F38,21,_,x,I,I,2,QVM), 0 , 219, 0 , 9417 , 395, 142), // #1402 - INST(Vpmovsxbq , VexRm_Lx , V(660F38,22,_,x,I,I,1,OVM), 0 , 220, 0 , 9427 , 396, 142), // #1403 - INST(Vpmovsxbw , VexRm_Lx , V(660F38,20,_,x,I,I,3,HVM), 0 , 139, 0 , 9437 , 397, 163), // #1404 - INST(Vpmovsxdq , VexRm_Lx , V(660F38,25,_,x,I,0,3,HVM), 0 , 139, 0 , 9447 , 397, 142), // #1405 - INST(Vpmovsxwd , VexRm_Lx , V(660F38,23,_,x,I,I,3,HVM), 0 , 139, 0 , 9457 , 397, 142), // #1406 - INST(Vpmovsxwq , VexRm_Lx , V(660F38,24,_,x,I,I,2,QVM), 0 , 219, 0 , 9467 , 395, 142), // #1407 - INST(Vpmovusdb , VexMr_Lx , E(F30F38,11,_,x,_,0,2,QVM), 0 , 216, 0 , 9477 , 392, 138), // #1408 - INST(Vpmovusdw , VexMr_Lx , E(F30F38,13,_,x,_,0,3,HVM), 0 , 217, 0 , 9487 , 393, 138), // #1409 - INST(Vpmovusqb , VexMr_Lx , E(F30F38,12,_,x,_,0,1,OVM), 0 , 218, 0 , 9497 , 394, 138), // #1410 - INST(Vpmovusqd , VexMr_Lx , E(F30F38,15,_,x,_,0,3,HVM), 0 , 217, 0 , 9507 , 393, 138), // #1411 - INST(Vpmovusqw , VexMr_Lx , E(F30F38,14,_,x,_,0,2,QVM), 0 , 216, 0 , 9517 , 392, 138), // #1412 - INST(Vpmovuswb , VexMr_Lx , E(F30F38,10,_,x,_,0,3,HVM), 0 , 217, 0 , 9527 , 393, 146), // #1413 - INST(Vpmovw2m , VexRm_Lx , E(F30F38,29,_,x,_,1,_,_ ), 0 , 205, 0 , 9537 , 391, 146), // #1414 - INST(Vpmovwb , VexMr_Lx , E(F30F38,30,_,x,_,0,3,HVM), 0 , 217, 0 , 9546 , 393, 146), // #1415 - INST(Vpmovzxbd , VexRm_Lx , V(660F38,31,_,x,I,I,2,QVM), 0 , 219, 0 , 9554 , 395, 142), // #1416 - INST(Vpmovzxbq , VexRm_Lx , V(660F38,32,_,x,I,I,1,OVM), 0 , 220, 0 , 9564 , 396, 142), // #1417 - INST(Vpmovzxbw , VexRm_Lx , V(660F38,30,_,x,I,I,3,HVM), 0 , 139, 0 , 9574 , 397, 163), // #1418 - INST(Vpmovzxdq , VexRm_Lx , V(660F38,35,_,x,I,0,3,HVM), 0 , 139, 0 , 9584 , 397, 142), // #1419 - INST(Vpmovzxwd , VexRm_Lx , V(660F38,33,_,x,I,I,3,HVM), 0 , 139, 0 , 9594 , 397, 142), // #1420 - INST(Vpmovzxwq , VexRm_Lx , V(660F38,34,_,x,I,I,2,QVM), 0 , 219, 0 , 9604 , 395, 142), // #1421 - INST(Vpmuldq , VexRvm_Lx , V(660F38,28,_,x,I,1,4,FV ), 0 , 209, 0 , 9614 , 208, 142), // #1422 - INST(Vpmulhrsw , VexRvm_Lx , V(660F38,0B,_,x,I,I,4,FVM), 0 , 110, 0 , 9622 , 315, 163), // #1423 - INST(Vpmulhuw , VexRvm_Lx , V(660F00,E4,_,x,I,I,4,FVM), 0 , 144, 0 , 9632 , 315, 163), // #1424 - INST(Vpmulhw , VexRvm_Lx , V(660F00,E5,_,x,I,I,4,FVM), 0 , 144, 0 , 9641 , 315, 163), // #1425 - INST(Vpmulld , VexRvm_Lx , V(660F38,40,_,x,I,0,4,FV ), 0 , 110, 0 , 9649 , 209, 142), // #1426 - INST(Vpmullq , VexRvm_Lx , E(660F38,40,_,x,_,1,4,FV ), 0 , 113, 0 , 9657 , 212, 140), // #1427 - INST(Vpmullw , VexRvm_Lx , V(660F00,D5,_,x,I,I,4,FVM), 0 , 144, 0 , 9665 , 315, 163), // #1428 - INST(Vpmultishiftqb , VexRvm_Lx , E(660F38,83,_,x,_,1,4,FV ), 0 , 113, 0 , 9673 , 212, 170), // #1429 - INST(Vpmuludq , VexRvm_Lx , V(660F00,F4,_,x,I,1,4,FV ), 0 , 103, 0 , 9688 , 208, 142), // #1430 - INST(Vpopcntb , VexRm_Lx , E(660F38,54,_,x,_,0,4,FV ), 0 , 114, 0 , 9697 , 279, 174), // #1431 - INST(Vpopcntd , VexRm_Lx , E(660F38,55,_,x,_,0,4,FVM), 0 , 114, 0 , 9706 , 374, 175), // #1432 - INST(Vpopcntq , VexRm_Lx , E(660F38,55,_,x,_,1,4,FVM), 0 , 113, 0 , 9715 , 350, 175), // #1433 - INST(Vpopcntw , VexRm_Lx , E(660F38,54,_,x,_,1,4,FV ), 0 , 113, 0 , 9724 , 279, 174), // #1434 - INST(Vpor , VexRvm_Lx , V(660F00,EB,_,x,I,_,_,_ ), 0 , 69 , 0 , 9733 , 351, 160), // #1435 - INST(Vpord , VexRvm_Lx , E(660F00,EB,_,x,_,0,4,FV ), 0 , 198, 0 , 9738 , 352, 138), // #1436 - INST(Vporq , VexRvm_Lx , E(660F00,EB,_,x,_,1,4,FV ), 0 , 135, 0 , 9744 , 356, 138), // #1437 - INST(Vpperm , VexRvrmRvmr , V(XOP_M8,A3,_,0,x,_,_,_ ), 0 , 208, 0 , 9750 , 398, 151), // #1438 - INST(Vprold , VexVmi_Lx , E(660F00,72,1,x,_,0,4,FV ), 0 , 221, 0 , 9757 , 399, 138), // #1439 - INST(Vprolq , VexVmi_Lx , E(660F00,72,1,x,_,1,4,FV ), 0 , 222, 0 , 9764 , 400, 138), // #1440 - INST(Vprolvd , VexRvm_Lx , E(660F38,15,_,x,_,0,4,FV ), 0 , 114, 0 , 9771 , 213, 138), // #1441 - INST(Vprolvq , VexRvm_Lx , E(660F38,15,_,x,_,1,4,FV ), 0 , 113, 0 , 9779 , 212, 138), // #1442 - INST(Vprord , VexVmi_Lx , E(660F00,72,0,x,_,0,4,FV ), 0 , 198, 0 , 9787 , 399, 138), // #1443 - INST(Vprorq , VexVmi_Lx , E(660F00,72,0,x,_,1,4,FV ), 0 , 135, 0 , 9794 , 400, 138), // #1444 - INST(Vprorvd , VexRvm_Lx , E(660F38,14,_,x,_,0,4,FV ), 0 , 114, 0 , 9801 , 213, 138), // #1445 - INST(Vprorvq , VexRvm_Lx , E(660F38,14,_,x,_,1,4,FV ), 0 , 113, 0 , 9809 , 212, 138), // #1446 - INST(Vprotb , VexRvmRmvRmi , V(XOP_M9,90,_,0,x,_,_,_ ), V(XOP_M8,C0,_,0,x,_,_,_ ), 79 , 122, 9817 , 401, 151), // #1447 - INST(Vprotd , VexRvmRmvRmi , V(XOP_M9,92,_,0,x,_,_,_ ), V(XOP_M8,C2,_,0,x,_,_,_ ), 79 , 123, 9824 , 401, 151), // #1448 - INST(Vprotq , VexRvmRmvRmi , V(XOP_M9,93,_,0,x,_,_,_ ), V(XOP_M8,C3,_,0,x,_,_,_ ), 79 , 124, 9831 , 401, 151), // #1449 - INST(Vprotw , VexRvmRmvRmi , V(XOP_M9,91,_,0,x,_,_,_ ), V(XOP_M8,C1,_,0,x,_,_,_ ), 79 , 125, 9838 , 401, 151), // #1450 - INST(Vpsadbw , VexRvm_Lx , V(660F00,F6,_,x,I,I,4,FVM), 0 , 144, 0 , 9845 , 203, 163), // #1451 - INST(Vpscatterdd , VexMr_VM , E(660F38,A0,_,x,_,0,2,T1S), 0 , 129, 0 , 9853 , 402, 138), // #1452 - INST(Vpscatterdq , VexMr_VM , E(660F38,A0,_,x,_,1,3,T1S), 0 , 128, 0 , 9865 , 403, 138), // #1453 - INST(Vpscatterqd , VexMr_VM , E(660F38,A1,_,x,_,0,2,T1S), 0 , 129, 0 , 9877 , 404, 138), // #1454 - INST(Vpscatterqq , VexMr_VM , E(660F38,A1,_,x,_,1,3,T1S), 0 , 128, 0 , 9889 , 405, 138), // #1455 - INST(Vpshab , VexRvmRmv , V(XOP_M9,98,_,0,x,_,_,_ ), 0 , 79 , 0 , 9901 , 406, 151), // #1456 - INST(Vpshad , VexRvmRmv , V(XOP_M9,9A,_,0,x,_,_,_ ), 0 , 79 , 0 , 9908 , 406, 151), // #1457 - INST(Vpshaq , VexRvmRmv , V(XOP_M9,9B,_,0,x,_,_,_ ), 0 , 79 , 0 , 9915 , 406, 151), // #1458 - INST(Vpshaw , VexRvmRmv , V(XOP_M9,99,_,0,x,_,_,_ ), 0 , 79 , 0 , 9922 , 406, 151), // #1459 - INST(Vpshlb , VexRvmRmv , V(XOP_M9,94,_,0,x,_,_,_ ), 0 , 79 , 0 , 9929 , 406, 151), // #1460 - INST(Vpshld , VexRvmRmv , V(XOP_M9,96,_,0,x,_,_,_ ), 0 , 79 , 0 , 9936 , 406, 151), // #1461 - INST(Vpshldd , VexRvmi_Lx , E(660F3A,71,_,x,_,0,4,FV ), 0 , 111, 0 , 9943 , 206, 168), // #1462 - INST(Vpshldq , VexRvmi_Lx , E(660F3A,71,_,x,_,1,4,FV ), 0 , 112, 0 , 9951 , 207, 168), // #1463 - INST(Vpshldvd , VexRvm_Lx , E(660F38,71,_,x,_,0,4,FV ), 0 , 114, 0 , 9959 , 213, 168), // #1464 - INST(Vpshldvq , VexRvm_Lx , E(660F38,71,_,x,_,1,4,FV ), 0 , 113, 0 , 9968 , 212, 168), // #1465 - INST(Vpshldvw , VexRvm_Lx , E(660F38,70,_,x,_,1,4,FVM), 0 , 113, 0 , 9977 , 357, 168), // #1466 - INST(Vpshldw , VexRvmi_Lx , E(660F3A,70,_,x,_,1,4,FVM), 0 , 112, 0 , 9986 , 275, 168), // #1467 - INST(Vpshlq , VexRvmRmv , V(XOP_M9,97,_,0,x,_,_,_ ), 0 , 79 , 0 , 9994 , 406, 151), // #1468 - INST(Vpshlw , VexRvmRmv , V(XOP_M9,95,_,0,x,_,_,_ ), 0 , 79 , 0 , 10001, 406, 151), // #1469 - INST(Vpshrdd , VexRvmi_Lx , E(660F3A,73,_,x,_,0,4,FV ), 0 , 111, 0 , 10008, 206, 168), // #1470 - INST(Vpshrdq , VexRvmi_Lx , E(660F3A,73,_,x,_,1,4,FV ), 0 , 112, 0 , 10016, 207, 168), // #1471 - INST(Vpshrdvd , VexRvm_Lx , E(660F38,73,_,x,_,0,4,FV ), 0 , 114, 0 , 10024, 213, 168), // #1472 - INST(Vpshrdvq , VexRvm_Lx , E(660F38,73,_,x,_,1,4,FV ), 0 , 113, 0 , 10033, 212, 168), // #1473 - INST(Vpshrdvw , VexRvm_Lx , E(660F38,72,_,x,_,1,4,FVM), 0 , 113, 0 , 10042, 357, 168), // #1474 - INST(Vpshrdw , VexRvmi_Lx , E(660F3A,72,_,x,_,1,4,FVM), 0 , 112, 0 , 10051, 275, 168), // #1475 - INST(Vpshufb , VexRvm_Lx , V(660F38,00,_,x,I,I,4,FVM), 0 , 110, 0 , 10059, 315, 163), // #1476 - INST(Vpshufbitqmb , VexRvm_Lx , E(660F38,8F,_,x,0,0,4,FVM), 0 , 114, 0 , 10067, 407, 174), // #1477 - INST(Vpshufd , VexRmi_Lx , V(660F00,70,_,x,I,0,4,FV ), 0 , 144, 0 , 10080, 408, 142), // #1478 - INST(Vpshufhw , VexRmi_Lx , V(F30F00,70,_,x,I,I,4,FVM), 0 , 161, 0 , 10088, 409, 163), // #1479 - INST(Vpshuflw , VexRmi_Lx , V(F20F00,70,_,x,I,I,4,FVM), 0 , 223, 0 , 10097, 409, 163), // #1480 - INST(Vpsignb , VexRvm_Lx , V(660F38,08,_,x,I,_,_,_ ), 0 , 96 , 0 , 10106, 202, 160), // #1481 - INST(Vpsignd , VexRvm_Lx , V(660F38,0A,_,x,I,_,_,_ ), 0 , 96 , 0 , 10114, 202, 160), // #1482 - INST(Vpsignw , VexRvm_Lx , V(660F38,09,_,x,I,_,_,_ ), 0 , 96 , 0 , 10122, 202, 160), // #1483 - INST(Vpslld , VexRvmVmi_Lx_MEvex , V(660F00,F2,_,x,I,0,4,128), V(660F00,72,6,x,I,0,4,FV ), 224, 126, 10130, 410, 142), // #1484 - INST(Vpslldq , VexVmi_Lx_MEvex , V(660F00,73,7,x,I,I,4,FVM), 0 , 225, 0 , 10137, 411, 163), // #1485 - INST(Vpsllq , VexRvmVmi_Lx_MEvex , V(660F00,F3,_,x,I,1,4,128), V(660F00,73,6,x,I,1,4,FV ), 226, 127, 10145, 412, 142), // #1486 - INST(Vpsllvd , VexRvm_Lx , V(660F38,47,_,x,0,0,4,FV ), 0 , 110, 0 , 10152, 209, 152), // #1487 - INST(Vpsllvq , VexRvm_Lx , V(660F38,47,_,x,1,1,4,FV ), 0 , 182, 0 , 10160, 208, 152), // #1488 - INST(Vpsllvw , VexRvm_Lx , E(660F38,12,_,x,_,1,4,FVM), 0 , 113, 0 , 10168, 357, 146), // #1489 - INST(Vpsllw , VexRvmVmi_Lx_MEvex , V(660F00,F1,_,x,I,I,4,128), V(660F00,71,6,x,I,I,4,FVM), 224, 128, 10176, 413, 163), // #1490 - INST(Vpsrad , VexRvmVmi_Lx_MEvex , V(660F00,E2,_,x,I,0,4,128), V(660F00,72,4,x,I,0,4,FV ), 224, 129, 10183, 410, 142), // #1491 - INST(Vpsraq , VexRvmVmi_Lx_MEvex , E(660F00,E2,_,x,_,1,4,128), E(660F00,72,4,x,_,1,4,FV ), 227, 130, 10190, 414, 138), // #1492 - INST(Vpsravd , VexRvm_Lx , V(660F38,46,_,x,0,0,4,FV ), 0 , 110, 0 , 10197, 209, 152), // #1493 - INST(Vpsravq , VexRvm_Lx , E(660F38,46,_,x,_,1,4,FV ), 0 , 113, 0 , 10205, 212, 138), // #1494 - INST(Vpsravw , VexRvm_Lx , E(660F38,11,_,x,_,1,4,FVM), 0 , 113, 0 , 10213, 357, 146), // #1495 - INST(Vpsraw , VexRvmVmi_Lx_MEvex , V(660F00,E1,_,x,I,I,4,128), V(660F00,71,4,x,I,I,4,FVM), 224, 131, 10221, 413, 163), // #1496 - INST(Vpsrld , VexRvmVmi_Lx_MEvex , V(660F00,D2,_,x,I,0,4,128), V(660F00,72,2,x,I,0,4,FV ), 224, 132, 10228, 410, 142), // #1497 - INST(Vpsrldq , VexVmi_Lx_MEvex , V(660F00,73,3,x,I,I,4,FVM), 0 , 228, 0 , 10235, 411, 163), // #1498 - INST(Vpsrlq , VexRvmVmi_Lx_MEvex , V(660F00,D3,_,x,I,1,4,128), V(660F00,73,2,x,I,1,4,FV ), 226, 133, 10243, 412, 142), // #1499 - INST(Vpsrlvd , VexRvm_Lx , V(660F38,45,_,x,0,0,4,FV ), 0 , 110, 0 , 10250, 209, 152), // #1500 - INST(Vpsrlvq , VexRvm_Lx , V(660F38,45,_,x,1,1,4,FV ), 0 , 182, 0 , 10258, 208, 152), // #1501 - INST(Vpsrlvw , VexRvm_Lx , E(660F38,10,_,x,_,1,4,FVM), 0 , 113, 0 , 10266, 357, 146), // #1502 - INST(Vpsrlw , VexRvmVmi_Lx_MEvex , V(660F00,D1,_,x,I,I,4,128), V(660F00,71,2,x,I,I,4,FVM), 224, 134, 10274, 413, 163), // #1503 - INST(Vpsubb , VexRvm_Lx , V(660F00,F8,_,x,I,I,4,FVM), 0 , 144, 0 , 10281, 415, 163), // #1504 - INST(Vpsubd , VexRvm_Lx , V(660F00,FA,_,x,I,0,4,FV ), 0 , 144, 0 , 10288, 416, 142), // #1505 - INST(Vpsubq , VexRvm_Lx , V(660F00,FB,_,x,I,1,4,FV ), 0 , 103, 0 , 10295, 417, 142), // #1506 - INST(Vpsubsb , VexRvm_Lx , V(660F00,E8,_,x,I,I,4,FVM), 0 , 144, 0 , 10302, 415, 163), // #1507 - INST(Vpsubsw , VexRvm_Lx , V(660F00,E9,_,x,I,I,4,FVM), 0 , 144, 0 , 10310, 415, 163), // #1508 - INST(Vpsubusb , VexRvm_Lx , V(660F00,D8,_,x,I,I,4,FVM), 0 , 144, 0 , 10318, 415, 163), // #1509 - INST(Vpsubusw , VexRvm_Lx , V(660F00,D9,_,x,I,I,4,FVM), 0 , 144, 0 , 10327, 415, 163), // #1510 - INST(Vpsubw , VexRvm_Lx , V(660F00,F9,_,x,I,I,4,FVM), 0 , 144, 0 , 10336, 415, 163), // #1511 - INST(Vpternlogd , VexRvmi_Lx , E(660F3A,25,_,x,_,0,4,FV ), 0 , 111, 0 , 10343, 206, 138), // #1512 - INST(Vpternlogq , VexRvmi_Lx , E(660F3A,25,_,x,_,1,4,FV ), 0 , 112, 0 , 10354, 207, 138), // #1513 - INST(Vptest , VexRm_Lx , V(660F38,17,_,x,I,_,_,_ ), 0 , 96 , 0 , 10365, 298, 167), // #1514 - INST(Vptestmb , VexRvm_Lx , E(660F38,26,_,x,_,0,4,FVM), 0 , 114, 0 , 10372, 407, 146), // #1515 - INST(Vptestmd , VexRvm_Lx , E(660F38,27,_,x,_,0,4,FV ), 0 , 114, 0 , 10381, 418, 138), // #1516 - INST(Vptestmq , VexRvm_Lx , E(660F38,27,_,x,_,1,4,FV ), 0 , 113, 0 , 10390, 419, 138), // #1517 - INST(Vptestmw , VexRvm_Lx , E(660F38,26,_,x,_,1,4,FVM), 0 , 113, 0 , 10399, 407, 146), // #1518 - INST(Vptestnmb , VexRvm_Lx , E(F30F38,26,_,x,_,0,4,FVM), 0 , 132, 0 , 10408, 407, 146), // #1519 - INST(Vptestnmd , VexRvm_Lx , E(F30F38,27,_,x,_,0,4,FV ), 0 , 132, 0 , 10418, 418, 138), // #1520 - INST(Vptestnmq , VexRvm_Lx , E(F30F38,27,_,x,_,1,4,FV ), 0 , 229, 0 , 10428, 419, 138), // #1521 - INST(Vptestnmw , VexRvm_Lx , E(F30F38,26,_,x,_,1,4,FVM), 0 , 229, 0 , 10438, 407, 146), // #1522 - INST(Vpunpckhbw , VexRvm_Lx , V(660F00,68,_,x,I,I,4,FVM), 0 , 144, 0 , 10448, 315, 163), // #1523 - INST(Vpunpckhdq , VexRvm_Lx , V(660F00,6A,_,x,I,0,4,FV ), 0 , 144, 0 , 10459, 209, 142), // #1524 - INST(Vpunpckhqdq , VexRvm_Lx , V(660F00,6D,_,x,I,1,4,FV ), 0 , 103, 0 , 10470, 208, 142), // #1525 - INST(Vpunpckhwd , VexRvm_Lx , V(660F00,69,_,x,I,I,4,FVM), 0 , 144, 0 , 10482, 315, 163), // #1526 - INST(Vpunpcklbw , VexRvm_Lx , V(660F00,60,_,x,I,I,4,FVM), 0 , 144, 0 , 10493, 315, 163), // #1527 - INST(Vpunpckldq , VexRvm_Lx , V(660F00,62,_,x,I,0,4,FV ), 0 , 144, 0 , 10504, 209, 142), // #1528 - INST(Vpunpcklqdq , VexRvm_Lx , V(660F00,6C,_,x,I,1,4,FV ), 0 , 103, 0 , 10515, 208, 142), // #1529 - INST(Vpunpcklwd , VexRvm_Lx , V(660F00,61,_,x,I,I,4,FVM), 0 , 144, 0 , 10527, 315, 163), // #1530 - INST(Vpxor , VexRvm_Lx , V(660F00,EF,_,x,I,_,_,_ ), 0 , 69 , 0 , 10538, 353, 160), // #1531 - INST(Vpxord , VexRvm_Lx , E(660F00,EF,_,x,_,0,4,FV ), 0 , 198, 0 , 10544, 354, 138), // #1532 - INST(Vpxorq , VexRvm_Lx , E(660F00,EF,_,x,_,1,4,FV ), 0 , 135, 0 , 10551, 355, 138), // #1533 - INST(Vrangepd , VexRvmi_Lx , E(660F3A,50,_,x,_,1,4,FV ), 0 , 112, 0 , 10558, 285, 140), // #1534 - INST(Vrangeps , VexRvmi_Lx , E(660F3A,50,_,x,_,0,4,FV ), 0 , 111, 0 , 10567, 286, 140), // #1535 - INST(Vrangesd , VexRvmi , E(660F3A,51,_,I,_,1,3,T1S), 0 , 180, 0 , 10576, 287, 66 ), // #1536 - INST(Vrangess , VexRvmi , E(660F3A,51,_,I,_,0,2,T1S), 0 , 181, 0 , 10585, 288, 66 ), // #1537 - INST(Vrcp14pd , VexRm_Lx , E(660F38,4C,_,x,_,1,4,FV ), 0 , 113, 0 , 10594, 350, 138), // #1538 - INST(Vrcp14ps , VexRm_Lx , E(660F38,4C,_,x,_,0,4,FV ), 0 , 114, 0 , 10603, 374, 138), // #1539 - INST(Vrcp14sd , VexRvm , E(660F38,4D,_,I,_,1,3,T1S), 0 , 128, 0 , 10612, 420, 68 ), // #1540 - INST(Vrcp14ss , VexRvm , E(660F38,4D,_,I,_,0,2,T1S), 0 , 129, 0 , 10621, 421, 68 ), // #1541 - INST(Vrcp28pd , VexRm , E(660F38,CA,_,2,_,1,4,FV ), 0 , 170, 0 , 10630, 277, 147), // #1542 - INST(Vrcp28ps , VexRm , E(660F38,CA,_,2,_,0,4,FV ), 0 , 171, 0 , 10639, 278, 147), // #1543 - INST(Vrcp28sd , VexRvm , E(660F38,CB,_,I,_,1,3,T1S), 0 , 128, 0 , 10648, 308, 147), // #1544 - INST(Vrcp28ss , VexRvm , E(660F38,CB,_,I,_,0,2,T1S), 0 , 129, 0 , 10657, 309, 147), // #1545 - INST(Vrcpph , VexRm_Lx , E(66MAP6,4C,_,_,_,0,4,FV ), 0 , 183, 0 , 10666, 422, 134), // #1546 - INST(Vrcpps , VexRm_Lx , V(000F00,53,_,x,I,_,_,_ ), 0 , 72 , 0 , 10673, 298, 135), // #1547 - INST(Vrcpsh , VexRvm , E(66MAP6,4D,_,_,_,0,1,T1S), 0 , 185, 0 , 10680, 423, 134), // #1548 - INST(Vrcpss , VexRvm , V(F30F00,53,_,I,I,_,_,_ ), 0 , 199, 0 , 10687, 424, 135), // #1549 - INST(Vreducepd , VexRmi_Lx , E(660F3A,56,_,x,_,1,4,FV ), 0 , 112, 0 , 10694, 400, 140), // #1550 - INST(Vreduceph , VexRmi_Lx , E(000F3A,56,_,_,_,0,4,FV ), 0 , 123, 0 , 10704, 311, 132), // #1551 - INST(Vreduceps , VexRmi_Lx , E(660F3A,56,_,x,_,0,4,FV ), 0 , 111, 0 , 10714, 399, 140), // #1552 - INST(Vreducesd , VexRvmi , E(660F3A,57,_,I,_,1,3,T1S), 0 , 180, 0 , 10724, 425, 66 ), // #1553 - INST(Vreducesh , VexRvmi , E(000F3A,57,_,_,_,0,1,T1S), 0 , 188, 0 , 10734, 313, 134), // #1554 - INST(Vreducess , VexRvmi , E(660F3A,57,_,I,_,0,2,T1S), 0 , 181, 0 , 10744, 426, 66 ), // #1555 - INST(Vrndscalepd , VexRmi_Lx , E(660F3A,09,_,x,_,1,4,FV ), 0 , 112, 0 , 10754, 310, 138), // #1556 - INST(Vrndscaleph , VexRmi_Lx , E(000F3A,08,_,_,_,0,4,FV ), 0 , 123, 0 , 10766, 311, 132), // #1557 - INST(Vrndscaleps , VexRmi_Lx , E(660F3A,08,_,x,_,0,4,FV ), 0 , 111, 0 , 10778, 312, 138), // #1558 - INST(Vrndscalesd , VexRvmi , E(660F3A,0B,_,I,_,1,3,T1S), 0 , 180, 0 , 10790, 287, 68 ), // #1559 - INST(Vrndscalesh , VexRvmi , E(000F3A,0A,_,_,_,0,1,T1S), 0 , 188, 0 , 10802, 313, 134), // #1560 - INST(Vrndscaless , VexRvmi , E(660F3A,0A,_,I,_,0,2,T1S), 0 , 181, 0 , 10814, 288, 68 ), // #1561 - INST(Vroundpd , VexRmi_Lx , V(660F3A,09,_,x,I,_,_,_ ), 0 , 73 , 0 , 10826, 427, 135), // #1562 - INST(Vroundps , VexRmi_Lx , V(660F3A,08,_,x,I,_,_,_ ), 0 , 73 , 0 , 10835, 427, 135), // #1563 - INST(Vroundsd , VexRvmi , V(660F3A,0B,_,I,I,_,_,_ ), 0 , 73 , 0 , 10844, 428, 135), // #1564 - INST(Vroundss , VexRvmi , V(660F3A,0A,_,I,I,_,_,_ ), 0 , 73 , 0 , 10853, 429, 135), // #1565 - INST(Vrsqrt14pd , VexRm_Lx , E(660F38,4E,_,x,_,1,4,FV ), 0 , 113, 0 , 10862, 350, 138), // #1566 - INST(Vrsqrt14ps , VexRm_Lx , E(660F38,4E,_,x,_,0,4,FV ), 0 , 114, 0 , 10873, 374, 138), // #1567 - INST(Vrsqrt14sd , VexRvm , E(660F38,4F,_,I,_,1,3,T1S), 0 , 128, 0 , 10884, 420, 68 ), // #1568 - INST(Vrsqrt14ss , VexRvm , E(660F38,4F,_,I,_,0,2,T1S), 0 , 129, 0 , 10895, 421, 68 ), // #1569 - INST(Vrsqrt28pd , VexRm , E(660F38,CC,_,2,_,1,4,FV ), 0 , 170, 0 , 10906, 277, 147), // #1570 - INST(Vrsqrt28ps , VexRm , E(660F38,CC,_,2,_,0,4,FV ), 0 , 171, 0 , 10917, 278, 147), // #1571 - INST(Vrsqrt28sd , VexRvm , E(660F38,CD,_,I,_,1,3,T1S), 0 , 128, 0 , 10928, 308, 147), // #1572 - INST(Vrsqrt28ss , VexRvm , E(660F38,CD,_,I,_,0,2,T1S), 0 , 129, 0 , 10939, 309, 147), // #1573 - INST(Vrsqrtph , VexRm_Lx , E(66MAP6,4E,_,_,_,0,4,FV ), 0 , 183, 0 , 10950, 422, 132), // #1574 - INST(Vrsqrtps , VexRm_Lx , V(000F00,52,_,x,I,_,_,_ ), 0 , 72 , 0 , 10959, 298, 135), // #1575 - INST(Vrsqrtsh , VexRvm , E(66MAP6,4F,_,_,_,0,1,T1S), 0 , 185, 0 , 10968, 423, 134), // #1576 - INST(Vrsqrtss , VexRvm , V(F30F00,52,_,I,I,_,_,_ ), 0 , 199, 0 , 10977, 424, 135), // #1577 - INST(Vscalefpd , VexRvm_Lx , E(660F38,2C,_,x,_,1,4,FV ), 0 , 113, 0 , 10986, 430, 138), // #1578 - INST(Vscalefph , VexRvm_Lx , E(66MAP6,2C,_,_,_,0,4,FV ), 0 , 183, 0 , 10996, 197, 132), // #1579 - INST(Vscalefps , VexRvm_Lx , E(660F38,2C,_,x,_,0,4,FV ), 0 , 114, 0 , 11006, 284, 138), // #1580 - INST(Vscalefsd , VexRvm , E(660F38,2D,_,I,_,1,3,T1S), 0 , 128, 0 , 11016, 251, 68 ), // #1581 - INST(Vscalefsh , VexRvm , E(66MAP6,2D,_,_,_,0,1,T1S), 0 , 185, 0 , 11026, 200, 134), // #1582 - INST(Vscalefss , VexRvm , E(660F38,2D,_,I,_,0,2,T1S), 0 , 129, 0 , 11036, 259, 68 ), // #1583 - INST(Vscatterdpd , VexMr_VM , E(660F38,A2,_,x,_,1,3,T1S), 0 , 128, 0 , 11046, 403, 138), // #1584 - INST(Vscatterdps , VexMr_VM , E(660F38,A2,_,x,_,0,2,T1S), 0 , 129, 0 , 11058, 402, 138), // #1585 - INST(Vscatterpf0dpd , VexM_VM , E(660F38,C6,5,2,_,1,3,T1S), 0 , 230, 0 , 11070, 303, 153), // #1586 - INST(Vscatterpf0dps , VexM_VM , E(660F38,C6,5,2,_,0,2,T1S), 0 , 231, 0 , 11085, 304, 153), // #1587 - INST(Vscatterpf0qpd , VexM_VM , E(660F38,C7,5,2,_,1,3,T1S), 0 , 230, 0 , 11100, 305, 153), // #1588 - INST(Vscatterpf0qps , VexM_VM , E(660F38,C7,5,2,_,0,2,T1S), 0 , 231, 0 , 11115, 305, 153), // #1589 - INST(Vscatterpf1dpd , VexM_VM , E(660F38,C6,6,2,_,1,3,T1S), 0 , 232, 0 , 11130, 303, 153), // #1590 - INST(Vscatterpf1dps , VexM_VM , E(660F38,C6,6,2,_,0,2,T1S), 0 , 233, 0 , 11145, 304, 153), // #1591 - INST(Vscatterpf1qpd , VexM_VM , E(660F38,C7,6,2,_,1,3,T1S), 0 , 232, 0 , 11160, 305, 153), // #1592 - INST(Vscatterpf1qps , VexM_VM , E(660F38,C7,6,2,_,0,2,T1S), 0 , 233, 0 , 11175, 305, 153), // #1593 - INST(Vscatterqpd , VexMr_VM , E(660F38,A3,_,x,_,1,3,T1S), 0 , 128, 0 , 11190, 405, 138), // #1594 - INST(Vscatterqps , VexMr_VM , E(660F38,A3,_,x,_,0,2,T1S), 0 , 129, 0 , 11202, 404, 138), // #1595 - INST(Vshuff32x4 , VexRvmi_Lx , E(660F3A,23,_,x,_,0,4,FV ), 0 , 111, 0 , 11214, 431, 138), // #1596 - INST(Vshuff64x2 , VexRvmi_Lx , E(660F3A,23,_,x,_,1,4,FV ), 0 , 112, 0 , 11225, 432, 138), // #1597 - INST(Vshufi32x4 , VexRvmi_Lx , E(660F3A,43,_,x,_,0,4,FV ), 0 , 111, 0 , 11236, 431, 138), // #1598 - INST(Vshufi64x2 , VexRvmi_Lx , E(660F3A,43,_,x,_,1,4,FV ), 0 , 112, 0 , 11247, 432, 138), // #1599 - INST(Vshufpd , VexRvmi_Lx , V(660F00,C6,_,x,I,1,4,FV ), 0 , 103, 0 , 11258, 433, 131), // #1600 - INST(Vshufps , VexRvmi_Lx , V(000F00,C6,_,x,I,0,4,FV ), 0 , 105, 0 , 11266, 434, 131), // #1601 - INST(Vsqrtpd , VexRm_Lx , V(660F00,51,_,x,I,1,4,FV ), 0 , 103, 0 , 11274, 435, 131), // #1602 - INST(Vsqrtph , VexRm_Lx , E(00MAP5,51,_,_,_,0,4,FV ), 0 , 104, 0 , 11282, 246, 132), // #1603 - INST(Vsqrtps , VexRm_Lx , V(000F00,51,_,x,I,0,4,FV ), 0 , 105, 0 , 11290, 235, 131), // #1604 - INST(Vsqrtsd , VexRvm , V(F20F00,51,_,I,I,1,3,T1S), 0 , 106, 0 , 11298, 199, 133), // #1605 - INST(Vsqrtsh , VexRvm , E(F3MAP5,51,_,_,_,0,1,T1S), 0 , 107, 0 , 11306, 200, 134), // #1606 - INST(Vsqrtss , VexRvm , V(F30F00,51,_,I,I,0,2,T1S), 0 , 108, 0 , 11314, 201, 133), // #1607 - INST(Vstmxcsr , VexM , V(000F00,AE,3,0,I,_,_,_ ), 0 , 234, 0 , 11322, 321, 135), // #1608 - INST(Vsubpd , VexRvm_Lx , V(660F00,5C,_,x,I,1,4,FV ), 0 , 103, 0 , 11331, 196, 131), // #1609 - INST(Vsubph , VexRvm_Lx , E(00MAP5,5C,_,_,_,0,4,FV ), 0 , 104, 0 , 11338, 197, 132), // #1610 - INST(Vsubps , VexRvm_Lx , V(000F00,5C,_,x,I,0,4,FV ), 0 , 105, 0 , 11345, 198, 131), // #1611 - INST(Vsubsd , VexRvm , V(F20F00,5C,_,I,I,1,3,T1S), 0 , 106, 0 , 11352, 199, 133), // #1612 - INST(Vsubsh , VexRvm , E(F3MAP5,5C,_,_,_,0,1,T1S), 0 , 107, 0 , 11359, 200, 134), // #1613 - INST(Vsubss , VexRvm , V(F30F00,5C,_,I,I,0,2,T1S), 0 , 108, 0 , 11366, 201, 133), // #1614 - INST(Vtestpd , VexRm_Lx , V(660F38,0F,_,x,0,_,_,_ ), 0 , 96 , 0 , 11373, 298, 167), // #1615 - INST(Vtestps , VexRm_Lx , V(660F38,0E,_,x,0,_,_,_ ), 0 , 96 , 0 , 11381, 298, 167), // #1616 - INST(Vucomisd , VexRm , V(660F00,2E,_,I,I,1,3,T1S), 0 , 125, 0 , 11389, 229, 143), // #1617 - INST(Vucomish , VexRm , E(00MAP5,2E,_,_,_,0,1,T1S), 0 , 126, 0 , 11398, 230, 134), // #1618 - INST(Vucomiss , VexRm , V(000F00,2E,_,I,I,0,2,T1S), 0 , 127, 0 , 11407, 231, 143), // #1619 - INST(Vunpckhpd , VexRvm_Lx , V(660F00,15,_,x,I,1,4,FV ), 0 , 103, 0 , 11416, 208, 131), // #1620 - INST(Vunpckhps , VexRvm_Lx , V(000F00,15,_,x,I,0,4,FV ), 0 , 105, 0 , 11426, 209, 131), // #1621 - INST(Vunpcklpd , VexRvm_Lx , V(660F00,14,_,x,I,1,4,FV ), 0 , 103, 0 , 11436, 208, 131), // #1622 - INST(Vunpcklps , VexRvm_Lx , V(000F00,14,_,x,I,0,4,FV ), 0 , 105, 0 , 11446, 209, 131), // #1623 - INST(Vxorpd , VexRvm_Lx , V(660F00,57,_,x,I,1,4,FV ), 0 , 103, 0 , 11456, 417, 139), // #1624 - INST(Vxorps , VexRvm_Lx , V(000F00,57,_,x,I,0,4,FV ), 0 , 105, 0 , 11463, 416, 139), // #1625 - INST(Vzeroall , VexOp , V(000F00,77,_,1,I,_,_,_ ), 0 , 68 , 0 , 11470, 436, 135), // #1626 - INST(Vzeroupper , VexOp , V(000F00,77,_,0,I,_,_,_ ), 0 , 72 , 0 , 11479, 436, 135), // #1627 - INST(Wbinvd , X86Op , O(000F00,09,_,_,_,_,_,_ ), 0 , 4 , 0 , 11490, 30 , 0 ), // #1628 - INST(Wbnoinvd , X86Op , O(F30F00,09,_,_,_,_,_,_ ), 0 , 6 , 0 , 11497, 30 , 176), // #1629 - INST(Wrfsbase , X86M , O(F30F00,AE,2,_,x,_,_,_ ), 0 , 235, 0 , 11506, 173, 111), // #1630 - INST(Wrgsbase , X86M , O(F30F00,AE,3,_,x,_,_,_ ), 0 , 236, 0 , 11515, 173, 111), // #1631 - INST(Wrmsr , X86Op , O(000F00,30,_,_,_,_,_,_ ), 0 , 4 , 0 , 11524, 174, 112), // #1632 - INST(Wrssd , X86Mr , O(000F38,F6,_,_,_,_,_,_ ), 0 , 83 , 0 , 11530, 437, 56 ), // #1633 - INST(Wrssq , X86Mr , O(000F38,F6,_,_,1,_,_,_ ), 0 , 237, 0 , 11536, 438, 56 ), // #1634 - INST(Wrussd , X86Mr , O(660F38,F5,_,_,_,_,_,_ ), 0 , 2 , 0 , 11542, 437, 56 ), // #1635 - INST(Wrussq , X86Mr , O(660F38,F5,_,_,1,_,_,_ ), 0 , 238, 0 , 11549, 438, 56 ), // #1636 - INST(Xabort , X86Op_Mod11RM_I8 , O(000000,C6,7,_,_,_,_,_ ), 0 , 27 , 0 , 11556, 80 , 177), // #1637 - INST(Xadd , X86Xadd , O(000F00,C0,_,_,x,_,_,_ ), 0 , 4 , 0 , 11563, 439, 38 ), // #1638 - INST(Xbegin , X86JmpRel , O(000000,C7,7,_,_,_,_,_ ), 0 , 27 , 0 , 11568, 440, 177), // #1639 - INST(Xchg , X86Xchg , O(000000,86,_,_,x,_,_,_ ), 0 , 0 , 0 , 462 , 441, 0 ), // #1640 - INST(Xend , X86Op , O(000F01,D5,_,_,_,_,_,_ ), 0 , 21 , 0 , 11575, 30 , 177), // #1641 - INST(Xgetbv , X86Op , O(000F01,D0,_,_,_,_,_,_ ), 0 , 21 , 0 , 11580, 174, 178), // #1642 - INST(Xlatb , X86Op , O(000000,D7,_,_,_,_,_,_ ), 0 , 0 , 0 , 11587, 30 , 0 ), // #1643 - INST(Xor , X86Arith , O(000000,30,6,_,x,_,_,_ ), 0 , 32 , 0 , 10540, 179, 1 ), // #1644 - INST(Xorpd , ExtRm , O(660F00,57,_,_,_,_,_,_ ), 0 , 3 , 0 , 11457, 151, 4 ), // #1645 - INST(Xorps , ExtRm , O(000F00,57,_,_,_,_,_,_ ), 0 , 4 , 0 , 11464, 151, 5 ), // #1646 - INST(Xresldtrk , X86Op , O(F20F01,E9,_,_,_,_,_,_ ), 0 , 92 , 0 , 11593, 30 , 179), // #1647 - INST(Xrstor , X86M_Only_EDX_EAX , O(000F00,AE,5,_,_,_,_,_ ), 0 , 77 , 0 , 1164 , 442, 178), // #1648 - INST(Xrstor64 , X86M_Only_EDX_EAX , O(000F00,AE,5,_,1,_,_,_ ), 0 , 239, 0 , 1172 , 443, 178), // #1649 - INST(Xrstors , X86M_Only_EDX_EAX , O(000F00,C7,3,_,_,_,_,_ ), 0 , 78 , 0 , 11603, 442, 180), // #1650 - INST(Xrstors64 , X86M_Only_EDX_EAX , O(000F00,C7,3,_,1,_,_,_ ), 0 , 240, 0 , 11611, 443, 180), // #1651 - INST(Xsave , X86M_Only_EDX_EAX , O(000F00,AE,4,_,_,_,_,_ ), 0 , 97 , 0 , 1182 , 442, 178), // #1652 - INST(Xsave64 , X86M_Only_EDX_EAX , O(000F00,AE,4,_,1,_,_,_ ), 0 , 241, 0 , 1189 , 443, 178), // #1653 - INST(Xsavec , X86M_Only_EDX_EAX , O(000F00,C7,4,_,_,_,_,_ ), 0 , 97 , 0 , 11621, 442, 181), // #1654 - INST(Xsavec64 , X86M_Only_EDX_EAX , O(000F00,C7,4,_,1,_,_,_ ), 0 , 241, 0 , 11628, 443, 181), // #1655 - INST(Xsaveopt , X86M_Only_EDX_EAX , O(000F00,AE,6,_,_,_,_,_ ), 0 , 80 , 0 , 11637, 442, 182), // #1656 - INST(Xsaveopt64 , X86M_Only_EDX_EAX , O(000F00,AE,6,_,1,_,_,_ ), 0 , 242, 0 , 11646, 443, 182), // #1657 - INST(Xsaves , X86M_Only_EDX_EAX , O(000F00,C7,5,_,_,_,_,_ ), 0 , 77 , 0 , 11657, 442, 180), // #1658 - INST(Xsaves64 , X86M_Only_EDX_EAX , O(000F00,C7,5,_,1,_,_,_ ), 0 , 239, 0 , 11664, 443, 180), // #1659 - INST(Xsetbv , X86Op , O(000F01,D1,_,_,_,_,_,_ ), 0 , 21 , 0 , 11673, 174, 178), // #1660 - INST(Xsusldtrk , X86Op , O(F20F01,E8,_,_,_,_,_,_ ), 0 , 92 , 0 , 11680, 30 , 179), // #1661 - INST(Xtest , X86Op , O(000F01,D6,_,_,_,_,_,_ ), 0 , 21 , 0 , 11690, 30 , 183) // #1662 + INST(None , None , 0 , 0 , 0 , 0 , 0 , 0 ), // #0 + INST(Aaa , X86Op_xAX , O(000000,37,_,_,_,_,_,_ ), 0 , 0 , 0 , 1 , 1 ), // #1 + INST(Aad , X86I_xAX , O(000000,D5,_,_,_,_,_,_ ), 0 , 0 , 0 , 2 , 1 ), // #2 + INST(Aadd , X86Mr , O(000F38,FC,_,_,_,_,_,_ ), 0 , 1 , 0 , 3 , 2 ), // #3 + INST(Aam , X86I_xAX , O(000000,D4,_,_,_,_,_,_ ), 0 , 0 , 0 , 2 , 1 ), // #4 + INST(Aand , X86Mr , O(660F38,FC,_,_,_,_,_,_ ), 0 , 2 , 0 , 3 , 2 ), // #5 + INST(Aas , X86Op_xAX , O(000000,3F,_,_,_,_,_,_ ), 0 , 0 , 0 , 1 , 1 ), // #6 + INST(Adc , X86Arith , O(000000,10,2,_,x,_,_,_ ), 0 , 3 , 0 , 4 , 3 ), // #7 + INST(Adcx , X86Rm , O(660F38,F6,_,_,x,_,_,_ ), 0 , 2 , 0 , 5 , 4 ), // #8 + INST(Add , X86Arith , O(000000,00,0,_,x,_,_,_ ), 0 , 0 , 0 , 4 , 1 ), // #9 + INST(Addpd , ExtRm , O(660F00,58,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #10 + INST(Addps , ExtRm , O(000F00,58,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #11 + INST(Addsd , ExtRm , O(F20F00,58,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 5 ), // #12 + INST(Addss , ExtRm , O(F30F00,58,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #13 + INST(Addsubpd , ExtRm , O(660F00,D0,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 7 ), // #14 + INST(Addsubps , ExtRm , O(F20F00,D0,_,_,_,_,_,_ ), 0 , 6 , 0 , 6 , 7 ), // #15 + INST(Adox , X86Rm , O(F30F38,F6,_,_,x,_,_,_ ), 0 , 8 , 0 , 5 , 8 ), // #16 + INST(Aesdec , ExtRm , O(660F38,DE,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 9 ), // #17 + INST(Aesdeclast , ExtRm , O(660F38,DF,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 9 ), // #18 + INST(Aesenc , ExtRm , O(660F38,DC,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 9 ), // #19 + INST(Aesenclast , ExtRm , O(660F38,DD,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 9 ), // #20 + INST(Aesimc , ExtRm , O(660F38,DB,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 9 ), // #21 + INST(Aeskeygenassist , ExtRmi , O(660F3A,DF,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 9 ), // #22 + INST(And , X86Arith , O(000000,20,4,_,x,_,_,_ ), 0 , 10 , 0 , 10 , 1 ), // #23 + INST(Andn , VexRvm_Wx , V(000F38,F2,_,0,x,_,_,_ ), 0 , 11 , 0 , 11 , 10 ), // #24 + INST(Andnpd , ExtRm , O(660F00,55,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #25 + INST(Andnps , ExtRm , O(000F00,55,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #26 + INST(Andpd , ExtRm , O(660F00,54,_,_,_,_,_,_ ), 0 , 4 , 0 , 12 , 5 ), // #27 + INST(Andps , ExtRm , O(000F00,54,_,_,_,_,_,_ ), 0 , 5 , 0 , 12 , 6 ), // #28 + INST(Aor , X86Mr , O(F20F38,FC,_,_,_,_,_,_ ), 0 , 12 , 0 , 3 , 2 ), // #29 + INST(Arpl , X86Mr_NoSize , O(000000,63,_,_,_,_,_,_ ), 0 , 0 , 0 , 13 , 11 ), // #30 + INST(Axor , X86Mr , O(F30F38,FC,_,_,_,_,_,_ ), 0 , 8 , 0 , 3 , 2 ), // #31 + INST(Bextr , VexRmv_Wx , V(000F38,F7,_,0,x,_,_,_ ), 0 , 11 , 0 , 14 , 10 ), // #32 + INST(Blcfill , VexVm_Wx , V(XOP_M9,01,1,0,x,_,_,_ ), 0 , 13 , 0 , 15 , 12 ), // #33 + INST(Blci , VexVm_Wx , V(XOP_M9,02,6,0,x,_,_,_ ), 0 , 14 , 0 , 15 , 12 ), // #34 + INST(Blcic , VexVm_Wx , V(XOP_M9,01,5,0,x,_,_,_ ), 0 , 15 , 0 , 15 , 12 ), // #35 + INST(Blcmsk , VexVm_Wx , V(XOP_M9,02,1,0,x,_,_,_ ), 0 , 13 , 0 , 15 , 12 ), // #36 + INST(Blcs , VexVm_Wx , V(XOP_M9,01,3,0,x,_,_,_ ), 0 , 16 , 0 , 15 , 12 ), // #37 + INST(Blendpd , ExtRmi , O(660F3A,0D,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 13 ), // #38 + INST(Blendps , ExtRmi , O(660F3A,0C,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 13 ), // #39 + INST(Blendvpd , ExtRm_XMM0 , O(660F38,15,_,_,_,_,_,_ ), 0 , 2 , 0 , 16 , 13 ), // #40 + INST(Blendvps , ExtRm_XMM0 , O(660F38,14,_,_,_,_,_,_ ), 0 , 2 , 0 , 16 , 13 ), // #41 + INST(Blsfill , VexVm_Wx , V(XOP_M9,01,2,0,x,_,_,_ ), 0 , 17 , 0 , 15 , 12 ), // #42 + INST(Blsi , VexVm_Wx , V(000F38,F3,3,0,x,_,_,_ ), 0 , 18 , 0 , 15 , 10 ), // #43 + INST(Blsic , VexVm_Wx , V(XOP_M9,01,6,0,x,_,_,_ ), 0 , 14 , 0 , 15 , 12 ), // #44 + INST(Blsmsk , VexVm_Wx , V(000F38,F3,2,0,x,_,_,_ ), 0 , 19 , 0 , 15 , 10 ), // #45 + INST(Blsr , VexVm_Wx , V(000F38,F3,1,0,x,_,_,_ ), 0 , 20 , 0 , 15 , 10 ), // #46 + INST(Bndcl , X86Rm , O(F30F00,1A,_,_,_,_,_,_ ), 0 , 7 , 0 , 17 , 14 ), // #47 + INST(Bndcn , X86Rm , O(F20F00,1B,_,_,_,_,_,_ ), 0 , 6 , 0 , 17 , 14 ), // #48 + INST(Bndcu , X86Rm , O(F20F00,1A,_,_,_,_,_,_ ), 0 , 6 , 0 , 17 , 14 ), // #49 + INST(Bndldx , X86Rm , O(000F00,1A,_,_,_,_,_,_ ), 0 , 5 , 0 , 18 , 14 ), // #50 + INST(Bndmk , X86Rm , O(F30F00,1B,_,_,_,_,_,_ ), 0 , 7 , 0 , 19 , 14 ), // #51 + INST(Bndmov , X86Bndmov , O(660F00,1A,_,_,_,_,_,_ ), O(660F00,1B,_,_,_,_,_,_ ), 4 , 1 , 20 , 14 ), // #52 + INST(Bndstx , X86Mr , O(000F00,1B,_,_,_,_,_,_ ), 0 , 5 , 0 , 21 , 14 ), // #53 + INST(Bound , X86Rm , O(000000,62,_,_,_,_,_,_ ), 0 , 0 , 0 , 22 , 0 ), // #54 + INST(Bsf , X86Rm , O(000F00,BC,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 1 ), // #55 + INST(Bsr , X86Rm , O(000F00,BD,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 1 ), // #56 + INST(Bswap , X86Bswap , O(000F00,C8,_,_,x,_,_,_ ), 0 , 5 , 0 , 24 , 0 ), // #57 + INST(Bt , X86Bt , O(000F00,A3,_,_,x,_,_,_ ), O(000F00,BA,4,_,x,_,_,_ ), 5 , 2 , 25 , 15 ), // #58 + INST(Btc , X86Bt , O(000F00,BB,_,_,x,_,_,_ ), O(000F00,BA,7,_,x,_,_,_ ), 5 , 3 , 26 , 15 ), // #59 + INST(Btr , X86Bt , O(000F00,B3,_,_,x,_,_,_ ), O(000F00,BA,6,_,x,_,_,_ ), 5 , 4 , 26 , 15 ), // #60 + INST(Bts , X86Bt , O(000F00,AB,_,_,x,_,_,_ ), O(000F00,BA,5,_,x,_,_,_ ), 5 , 5 , 26 , 15 ), // #61 + INST(Bzhi , VexRmv_Wx , V(000F38,F5,_,0,x,_,_,_ ), 0 , 11 , 0 , 14 , 16 ), // #62 + INST(Call , X86Call , O(000000,FF,2,_,_,_,_,_ ), 0 , 3 , 0 , 27 , 1 ), // #63 + INST(Cbw , X86Op_xAX , O(660000,98,_,_,_,_,_,_ ), 0 , 21 , 0 , 28 , 0 ), // #64 + INST(Cdq , X86Op_xDX_xAX , O(000000,99,_,_,_,_,_,_ ), 0 , 0 , 0 , 29 , 0 ), // #65 + INST(Cdqe , X86Op_xAX , O(000000,98,_,_,1,_,_,_ ), 0 , 22 , 0 , 30 , 0 ), // #66 + INST(Clac , X86Op , O(000F01,CA,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 17 ), // #67 + INST(Clc , X86Op , O(000000,F8,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 18 ), // #68 + INST(Cld , X86Op , O(000000,FC,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 19 ), // #69 + INST(Cldemote , X86M_Only , O(000F00,1C,0,_,_,_,_,_ ), 0 , 5 , 0 , 32 , 20 ), // #70 + INST(Clflush , X86M_Only , O(000F00,AE,7,_,_,_,_,_ ), 0 , 24 , 0 , 32 , 21 ), // #71 + INST(Clflushopt , X86M_Only , O(660F00,AE,7,_,_,_,_,_ ), 0 , 25 , 0 , 32 , 22 ), // #72 + INST(Clgi , X86Op , O(000F01,DD,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 23 ), // #73 + INST(Cli , X86Op , O(000000,FA,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 24 ), // #74 + INST(Clrssbsy , X86M_Only , O(F30F00,AE,6,_,_,_,_,_ ), 0 , 26 , 0 , 33 , 25 ), // #75 + INST(Clts , X86Op , O(000F00,06,_,_,_,_,_,_ ), 0 , 5 , 0 , 31 , 0 ), // #76 + INST(Clui , X86Op , O(F30F01,EE,_,_,_,_,_,_ ), 0 , 27 , 0 , 34 , 26 ), // #77 + INST(Clwb , X86M_Only , O(660F00,AE,6,_,_,_,_,_ ), 0 , 28 , 0 , 32 , 27 ), // #78 + INST(Clzero , X86Op_MemZAX , O(000F01,FC,_,_,_,_,_,_ ), 0 , 23 , 0 , 35 , 28 ), // #79 + INST(Cmc , X86Op , O(000000,F5,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 29 ), // #80 + INST(Cmova , X86Rm , O(000F00,47,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 30 ), // #81 + INST(Cmovae , X86Rm , O(000F00,43,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 31 ), // #82 + INST(Cmovb , X86Rm , O(000F00,42,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 31 ), // #83 + INST(Cmovbe , X86Rm , O(000F00,46,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 30 ), // #84 + INST(Cmovc , X86Rm , O(000F00,42,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 31 ), // #85 + INST(Cmove , X86Rm , O(000F00,44,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 32 ), // #86 + INST(Cmovg , X86Rm , O(000F00,4F,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 33 ), // #87 + INST(Cmovge , X86Rm , O(000F00,4D,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 34 ), // #88 + INST(Cmovl , X86Rm , O(000F00,4C,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 34 ), // #89 + INST(Cmovle , X86Rm , O(000F00,4E,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 33 ), // #90 + INST(Cmovna , X86Rm , O(000F00,46,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 30 ), // #91 + INST(Cmovnae , X86Rm , O(000F00,42,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 31 ), // #92 + INST(Cmovnb , X86Rm , O(000F00,43,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 31 ), // #93 + INST(Cmovnbe , X86Rm , O(000F00,47,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 30 ), // #94 + INST(Cmovnc , X86Rm , O(000F00,43,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 31 ), // #95 + INST(Cmovne , X86Rm , O(000F00,45,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 32 ), // #96 + INST(Cmovng , X86Rm , O(000F00,4E,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 33 ), // #97 + INST(Cmovnge , X86Rm , O(000F00,4C,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 34 ), // #98 + INST(Cmovnl , X86Rm , O(000F00,4D,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 34 ), // #99 + INST(Cmovnle , X86Rm , O(000F00,4F,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 33 ), // #100 + INST(Cmovno , X86Rm , O(000F00,41,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 35 ), // #101 + INST(Cmovnp , X86Rm , O(000F00,4B,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 36 ), // #102 + INST(Cmovns , X86Rm , O(000F00,49,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 37 ), // #103 + INST(Cmovnz , X86Rm , O(000F00,45,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 32 ), // #104 + INST(Cmovo , X86Rm , O(000F00,40,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 35 ), // #105 + INST(Cmovp , X86Rm , O(000F00,4A,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 36 ), // #106 + INST(Cmovpe , X86Rm , O(000F00,4A,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 36 ), // #107 + INST(Cmovpo , X86Rm , O(000F00,4B,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 36 ), // #108 + INST(Cmovs , X86Rm , O(000F00,48,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 37 ), // #109 + INST(Cmovz , X86Rm , O(000F00,44,_,_,x,_,_,_ ), 0 , 5 , 0 , 23 , 32 ), // #110 + INST(Cmp , X86Arith , O(000000,38,7,_,x,_,_,_ ), 0 , 29 , 0 , 36 , 1 ), // #111 + INST(Cmpbexadd , VexMvr_Wx , V(660F38,E6,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #112 + INST(Cmpbxadd , VexMvr_Wx , V(660F38,E2,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #113 + INST(Cmplexadd , VexMvr_Wx , V(660F38,EE,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #114 + INST(Cmplxadd , VexMvr_Wx , V(660F38,EC,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #115 + INST(Cmpnbexadd , VexMvr_Wx , V(660F38,E7,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #116 + INST(Cmpnbxadd , VexMvr_Wx , V(660F38,E3,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #117 + INST(Cmpnlexadd , VexMvr_Wx , V(660F38,EF,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #118 + INST(Cmpnlxadd , VexMvr_Wx , V(660F38,ED,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #119 + INST(Cmpnoxadd , VexMvr_Wx , V(660F38,E1,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #120 + INST(Cmpnpxadd , VexMvr_Wx , V(660F38,EB,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #121 + INST(Cmpnsxadd , VexMvr_Wx , V(660F38,E9,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #122 + INST(Cmpnzxadd , VexMvr_Wx , V(660F38,E5,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #123 + INST(Cmpoxadd , VexMvr_Wx , V(660F38,E0,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #124 + INST(Cmppd , ExtRmi , O(660F00,C2,_,_,_,_,_,_ ), 0 , 4 , 0 , 9 , 5 ), // #125 + INST(Cmpps , ExtRmi , O(000F00,C2,_,_,_,_,_,_ ), 0 , 5 , 0 , 9 , 6 ), // #126 + INST(Cmppxadd , VexMvr_Wx , V(660F38,EA,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #127 + INST(Cmps , X86StrMm , O(000000,A6,_,_,_,_,_,_ ), 0 , 0 , 0 , 38 , 39 ), // #128 + INST(Cmpsd , ExtRmi , O(F20F00,C2,_,_,_,_,_,_ ), 0 , 6 , 0 , 39 , 5 ), // #129 + INST(Cmpss , ExtRmi , O(F30F00,C2,_,_,_,_,_,_ ), 0 , 7 , 0 , 40 , 6 ), // #130 + INST(Cmpsxadd , VexMvr_Wx , V(660F38,E8,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #131 + INST(Cmpxchg , X86Cmpxchg , O(000F00,B0,_,_,x,_,_,_ ), 0 , 5 , 0 , 41 , 40 ), // #132 + INST(Cmpxchg16b , X86Cmpxchg8b_16b , O(000F00,C7,1,_,1,_,_,_ ), 0 , 31 , 0 , 42 , 41 ), // #133 + INST(Cmpxchg8b , X86Cmpxchg8b_16b , O(000F00,C7,1,_,_,_,_,_ ), 0 , 32 , 0 , 43 , 42 ), // #134 + INST(Cmpzxadd , VexMvr_Wx , V(660F38,E4,_,0,x,_,_,_ ), 0 , 30 , 0 , 37 , 38 ), // #135 + INST(Comisd , ExtRm , O(660F00,2F,_,_,_,_,_,_ ), 0 , 4 , 0 , 7 , 43 ), // #136 + INST(Comiss , ExtRm , O(000F00,2F,_,_,_,_,_,_ ), 0 , 5 , 0 , 8 , 44 ), // #137 + INST(Cpuid , X86Op , O(000F00,A2,_,_,_,_,_,_ ), 0 , 5 , 0 , 44 , 45 ), // #138 + INST(Cqo , X86Op_xDX_xAX , O(000000,99,_,_,1,_,_,_ ), 0 , 22 , 0 , 45 , 0 ), // #139 + INST(Crc32 , X86Crc , O(F20F38,F0,_,_,x,_,_,_ ), 0 , 12 , 0 , 46 , 46 ), // #140 + INST(Cvtdq2pd , ExtRm , O(F30F00,E6,_,_,_,_,_,_ ), 0 , 7 , 0 , 7 , 5 ), // #141 + INST(Cvtdq2ps , ExtRm , O(000F00,5B,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 5 ), // #142 + INST(Cvtpd2dq , ExtRm , O(F20F00,E6,_,_,_,_,_,_ ), 0 , 6 , 0 , 6 , 5 ), // #143 + INST(Cvtpd2pi , ExtRm , O(660F00,2D,_,_,_,_,_,_ ), 0 , 4 , 0 , 47 , 5 ), // #144 + INST(Cvtpd2ps , ExtRm , O(660F00,5A,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #145 + INST(Cvtpi2pd , ExtRm , O(660F00,2A,_,_,_,_,_,_ ), 0 , 4 , 0 , 48 , 5 ), // #146 + INST(Cvtpi2ps , ExtRm , O(000F00,2A,_,_,_,_,_,_ ), 0 , 5 , 0 , 48 , 6 ), // #147 + INST(Cvtps2dq , ExtRm , O(660F00,5B,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #148 + INST(Cvtps2pd , ExtRm , O(000F00,5A,_,_,_,_,_,_ ), 0 , 5 , 0 , 7 , 5 ), // #149 + INST(Cvtps2pi , ExtRm , O(000F00,2D,_,_,_,_,_,_ ), 0 , 5 , 0 , 49 , 6 ), // #150 + INST(Cvtsd2si , ExtRm_Wx_GpqOnly , O(F20F00,2D,_,_,x,_,_,_ ), 0 , 6 , 0 , 50 , 5 ), // #151 + INST(Cvtsd2ss , ExtRm , O(F20F00,5A,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 5 ), // #152 + INST(Cvtsi2sd , ExtRm_Wx , O(F20F00,2A,_,_,x,_,_,_ ), 0 , 6 , 0 , 51 , 5 ), // #153 + INST(Cvtsi2ss , ExtRm_Wx , O(F30F00,2A,_,_,x,_,_,_ ), 0 , 7 , 0 , 52 , 6 ), // #154 + INST(Cvtss2sd , ExtRm , O(F30F00,5A,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 5 ), // #155 + INST(Cvtss2si , ExtRm_Wx_GpqOnly , O(F30F00,2D,_,_,x,_,_,_ ), 0 , 7 , 0 , 53 , 6 ), // #156 + INST(Cvttpd2dq , ExtRm , O(660F00,E6,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #157 + INST(Cvttpd2pi , ExtRm , O(660F00,2C,_,_,_,_,_,_ ), 0 , 4 , 0 , 47 , 5 ), // #158 + INST(Cvttps2dq , ExtRm , O(F30F00,5B,_,_,_,_,_,_ ), 0 , 7 , 0 , 6 , 5 ), // #159 + INST(Cvttps2pi , ExtRm , O(000F00,2C,_,_,_,_,_,_ ), 0 , 5 , 0 , 49 , 6 ), // #160 + INST(Cvttsd2si , ExtRm_Wx_GpqOnly , O(F20F00,2C,_,_,x,_,_,_ ), 0 , 6 , 0 , 50 , 5 ), // #161 + INST(Cvttss2si , ExtRm_Wx_GpqOnly , O(F30F00,2C,_,_,x,_,_,_ ), 0 , 7 , 0 , 54 , 6 ), // #162 + INST(Cwd , X86Op_xDX_xAX , O(660000,99,_,_,_,_,_,_ ), 0 , 21 , 0 , 55 , 0 ), // #163 + INST(Cwde , X86Op_xAX , O(000000,98,_,_,_,_,_,_ ), 0 , 0 , 0 , 56 , 0 ), // #164 + INST(Daa , X86Op , O(000000,27,_,_,_,_,_,_ ), 0 , 0 , 0 , 1 , 1 ), // #165 + INST(Das , X86Op , O(000000,2F,_,_,_,_,_,_ ), 0 , 0 , 0 , 1 , 1 ), // #166 + INST(Dec , X86IncDec , O(000000,FE,1,_,x,_,_,_ ), O(000000,48,_,_,x,_,_,_ ), 33 , 6 , 57 , 47 ), // #167 + INST(Div , X86M_GPB_MulDiv , O(000000,F6,6,_,x,_,_,_ ), 0 , 34 , 0 , 58 , 1 ), // #168 + INST(Divpd , ExtRm , O(660F00,5E,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #169 + INST(Divps , ExtRm , O(000F00,5E,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #170 + INST(Divsd , ExtRm , O(F20F00,5E,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 5 ), // #171 + INST(Divss , ExtRm , O(F30F00,5E,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #172 + INST(Dppd , ExtRmi , O(660F3A,41,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 13 ), // #173 + INST(Dpps , ExtRmi , O(660F3A,40,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 13 ), // #174 + INST(Emms , X86Op , O(000F00,77,_,_,_,_,_,_ ), 0 , 5 , 0 , 59 , 48 ), // #175 + INST(Endbr32 , X86Op_Mod11RM , O(F30F00,1E,7,_,_,_,_,3 ), 0 , 35 , 0 , 31 , 49 ), // #176 + INST(Endbr64 , X86Op_Mod11RM , O(F30F00,1E,7,_,_,_,_,2 ), 0 , 36 , 0 , 31 , 49 ), // #177 + INST(Enqcmd , X86EnqcmdMovdir64b , O(F20F38,F8,_,_,_,_,_,_ ), 0 , 12 , 0 , 60 , 50 ), // #178 + INST(Enqcmds , X86EnqcmdMovdir64b , O(F30F38,F8,_,_,_,_,_,_ ), 0 , 8 , 0 , 60 , 50 ), // #179 + INST(Enter , X86Enter , O(000000,C8,_,_,_,_,_,_ ), 0 , 0 , 0 , 61 , 0 ), // #180 + INST(Extractps , ExtExtract , O(660F3A,17,_,_,_,_,_,_ ), 0 , 9 , 0 , 62 , 13 ), // #181 + INST(Extrq , ExtExtrq , O(660F00,79,_,_,_,_,_,_ ), O(660F00,78,0,_,_,_,_,_ ), 4 , 7 , 63 , 51 ), // #182 + INST(F2xm1 , FpuOp , O_FPU(00,D9F0,_) , 0 , 37 , 0 , 31 , 52 ), // #183 + INST(Fabs , FpuOp , O_FPU(00,D9E1,_) , 0 , 37 , 0 , 31 , 52 ), // #184 + INST(Fadd , FpuArith , O_FPU(00,C0C0,0) , 0 , 38 , 0 , 64 , 52 ), // #185 + INST(Faddp , FpuRDef , O_FPU(00,DEC0,_) , 0 , 39 , 0 , 65 , 52 ), // #186 + INST(Fbld , X86M_Only , O_FPU(00,00DF,4) , 0 , 40 , 0 , 66 , 52 ), // #187 + INST(Fbstp , X86M_Only , O_FPU(00,00DF,6) , 0 , 41 , 0 , 66 , 52 ), // #188 + INST(Fchs , FpuOp , O_FPU(00,D9E0,_) , 0 , 37 , 0 , 31 , 52 ), // #189 + INST(Fclex , FpuOp , O_FPU(9B,DBE2,_) , 0 , 42 , 0 , 31 , 52 ), // #190 + INST(Fcmovb , FpuR , O_FPU(00,DAC0,_) , 0 , 43 , 0 , 67 , 53 ), // #191 + INST(Fcmovbe , FpuR , O_FPU(00,DAD0,_) , 0 , 43 , 0 , 67 , 54 ), // #192 + INST(Fcmove , FpuR , O_FPU(00,DAC8,_) , 0 , 43 , 0 , 67 , 55 ), // #193 + INST(Fcmovnb , FpuR , O_FPU(00,DBC0,_) , 0 , 44 , 0 , 67 , 53 ), // #194 + INST(Fcmovnbe , FpuR , O_FPU(00,DBD0,_) , 0 , 44 , 0 , 67 , 54 ), // #195 + INST(Fcmovne , FpuR , O_FPU(00,DBC8,_) , 0 , 44 , 0 , 67 , 55 ), // #196 + INST(Fcmovnu , FpuR , O_FPU(00,DBD8,_) , 0 , 44 , 0 , 67 , 56 ), // #197 + INST(Fcmovu , FpuR , O_FPU(00,DAD8,_) , 0 , 43 , 0 , 67 , 56 ), // #198 + INST(Fcom , FpuCom , O_FPU(00,D0D0,2) , 0 , 45 , 0 , 68 , 52 ), // #199 + INST(Fcomi , FpuR , O_FPU(00,DBF0,_) , 0 , 44 , 0 , 67 , 57 ), // #200 + INST(Fcomip , FpuR , O_FPU(00,DFF0,_) , 0 , 46 , 0 , 67 , 57 ), // #201 + INST(Fcomp , FpuCom , O_FPU(00,D8D8,3) , 0 , 47 , 0 , 68 , 52 ), // #202 + INST(Fcompp , FpuOp , O_FPU(00,DED9,_) , 0 , 39 , 0 , 31 , 52 ), // #203 + INST(Fcos , FpuOp , O_FPU(00,D9FF,_) , 0 , 37 , 0 , 31 , 52 ), // #204 + INST(Fdecstp , FpuOp , O_FPU(00,D9F6,_) , 0 , 37 , 0 , 31 , 52 ), // #205 + INST(Fdiv , FpuArith , O_FPU(00,F0F8,6) , 0 , 48 , 0 , 64 , 52 ), // #206 + INST(Fdivp , FpuRDef , O_FPU(00,DEF8,_) , 0 , 39 , 0 , 65 , 52 ), // #207 + INST(Fdivr , FpuArith , O_FPU(00,F8F0,7) , 0 , 49 , 0 , 64 , 52 ), // #208 + INST(Fdivrp , FpuRDef , O_FPU(00,DEF0,_) , 0 , 39 , 0 , 65 , 52 ), // #209 + INST(Femms , X86Op , O(000F00,0E,_,_,_,_,_,_ ), 0 , 5 , 0 , 31 , 58 ), // #210 + INST(Ffree , FpuR , O_FPU(00,DDC0,_) , 0 , 50 , 0 , 67 , 52 ), // #211 + INST(Fiadd , FpuM , O_FPU(00,00DA,0) , 0 , 51 , 0 , 69 , 52 ), // #212 + INST(Ficom , FpuM , O_FPU(00,00DA,2) , 0 , 52 , 0 , 69 , 52 ), // #213 + INST(Ficomp , FpuM , O_FPU(00,00DA,3) , 0 , 53 , 0 , 69 , 52 ), // #214 + INST(Fidiv , FpuM , O_FPU(00,00DA,6) , 0 , 41 , 0 , 69 , 52 ), // #215 + INST(Fidivr , FpuM , O_FPU(00,00DA,7) , 0 , 54 , 0 , 69 , 52 ), // #216 + INST(Fild , FpuM , O_FPU(00,00DB,0) , O_FPU(00,00DF,5) , 51 , 8 , 70 , 52 ), // #217 + INST(Fimul , FpuM , O_FPU(00,00DA,1) , 0 , 55 , 0 , 69 , 52 ), // #218 + INST(Fincstp , FpuOp , O_FPU(00,D9F7,_) , 0 , 37 , 0 , 31 , 52 ), // #219 + INST(Finit , FpuOp , O_FPU(9B,DBE3,_) , 0 , 42 , 0 , 31 , 52 ), // #220 + INST(Fist , FpuM , O_FPU(00,00DB,2) , 0 , 52 , 0 , 69 , 52 ), // #221 + INST(Fistp , FpuM , O_FPU(00,00DB,3) , O_FPU(00,00DF,7) , 53 , 9 , 70 , 52 ), // #222 + INST(Fisttp , FpuM , O_FPU(00,00DB,1) , O_FPU(00,00DD,1) , 55 , 10 , 70 , 59 ), // #223 + INST(Fisub , FpuM , O_FPU(00,00DA,4) , 0 , 40 , 0 , 69 , 52 ), // #224 + INST(Fisubr , FpuM , O_FPU(00,00DA,5) , 0 , 56 , 0 , 69 , 52 ), // #225 + INST(Fld , FpuFldFst , O_FPU(00,00D9,0) , O_FPU(00,00DB,5) , 51 , 11 , 71 , 52 ), // #226 + INST(Fld1 , FpuOp , O_FPU(00,D9E8,_) , 0 , 37 , 0 , 31 , 52 ), // #227 + INST(Fldcw , X86M_Only , O_FPU(00,00D9,5) , 0 , 56 , 0 , 72 , 52 ), // #228 + INST(Fldenv , X86M_Only , O_FPU(00,00D9,4) , 0 , 40 , 0 , 32 , 52 ), // #229 + INST(Fldl2e , FpuOp , O_FPU(00,D9EA,_) , 0 , 37 , 0 , 31 , 52 ), // #230 + INST(Fldl2t , FpuOp , O_FPU(00,D9E9,_) , 0 , 37 , 0 , 31 , 52 ), // #231 + INST(Fldlg2 , FpuOp , O_FPU(00,D9EC,_) , 0 , 37 , 0 , 31 , 52 ), // #232 + INST(Fldln2 , FpuOp , O_FPU(00,D9ED,_) , 0 , 37 , 0 , 31 , 52 ), // #233 + INST(Fldpi , FpuOp , O_FPU(00,D9EB,_) , 0 , 37 , 0 , 31 , 52 ), // #234 + INST(Fldz , FpuOp , O_FPU(00,D9EE,_) , 0 , 37 , 0 , 31 , 52 ), // #235 + INST(Fmul , FpuArith , O_FPU(00,C8C8,1) , 0 , 57 , 0 , 64 , 52 ), // #236 + INST(Fmulp , FpuRDef , O_FPU(00,DEC8,_) , 0 , 39 , 0 , 65 , 52 ), // #237 + INST(Fnclex , FpuOp , O_FPU(00,DBE2,_) , 0 , 44 , 0 , 31 , 52 ), // #238 + INST(Fninit , FpuOp , O_FPU(00,DBE3,_) , 0 , 44 , 0 , 31 , 52 ), // #239 + INST(Fnop , FpuOp , O_FPU(00,D9D0,_) , 0 , 37 , 0 , 31 , 52 ), // #240 + INST(Fnsave , X86M_Only , O_FPU(00,00DD,6) , 0 , 41 , 0 , 32 , 52 ), // #241 + INST(Fnstcw , X86M_Only , O_FPU(00,00D9,7) , 0 , 54 , 0 , 72 , 52 ), // #242 + INST(Fnstenv , X86M_Only , O_FPU(00,00D9,6) , 0 , 41 , 0 , 32 , 52 ), // #243 + INST(Fnstsw , FpuStsw , O_FPU(00,00DD,7) , O_FPU(00,DFE0,_) , 54 , 12 , 73 , 52 ), // #244 + INST(Fpatan , FpuOp , O_FPU(00,D9F3,_) , 0 , 37 , 0 , 31 , 52 ), // #245 + INST(Fprem , FpuOp , O_FPU(00,D9F8,_) , 0 , 37 , 0 , 31 , 52 ), // #246 + INST(Fprem1 , FpuOp , O_FPU(00,D9F5,_) , 0 , 37 , 0 , 31 , 52 ), // #247 + INST(Fptan , FpuOp , O_FPU(00,D9F2,_) , 0 , 37 , 0 , 31 , 52 ), // #248 + INST(Frndint , FpuOp , O_FPU(00,D9FC,_) , 0 , 37 , 0 , 31 , 52 ), // #249 + INST(Frstor , X86M_Only , O_FPU(00,00DD,4) , 0 , 40 , 0 , 32 , 52 ), // #250 + INST(Fsave , X86M_Only , O_FPU(9B,00DD,6) , 0 , 58 , 0 , 32 , 52 ), // #251 + INST(Fscale , FpuOp , O_FPU(00,D9FD,_) , 0 , 37 , 0 , 31 , 52 ), // #252 + INST(Fsin , FpuOp , O_FPU(00,D9FE,_) , 0 , 37 , 0 , 31 , 52 ), // #253 + INST(Fsincos , FpuOp , O_FPU(00,D9FB,_) , 0 , 37 , 0 , 31 , 52 ), // #254 + INST(Fsqrt , FpuOp , O_FPU(00,D9FA,_) , 0 , 37 , 0 , 31 , 52 ), // #255 + INST(Fst , FpuFldFst , O_FPU(00,00D9,2) , 0 , 52 , 0 , 74 , 52 ), // #256 + INST(Fstcw , X86M_Only , O_FPU(9B,00D9,7) , 0 , 59 , 0 , 72 , 52 ), // #257 + INST(Fstenv , X86M_Only , O_FPU(9B,00D9,6) , 0 , 58 , 0 , 32 , 52 ), // #258 + INST(Fstp , FpuFldFst , O_FPU(00,00D9,3) , O(000000,DB,7,_,_,_,_,_ ), 53 , 13 , 71 , 52 ), // #259 + INST(Fstsw , FpuStsw , O_FPU(9B,00DD,7) , O_FPU(9B,DFE0,_) , 59 , 14 , 73 , 52 ), // #260 + INST(Fsub , FpuArith , O_FPU(00,E0E8,4) , 0 , 60 , 0 , 64 , 52 ), // #261 + INST(Fsubp , FpuRDef , O_FPU(00,DEE8,_) , 0 , 39 , 0 , 65 , 52 ), // #262 + INST(Fsubr , FpuArith , O_FPU(00,E8E0,5) , 0 , 61 , 0 , 64 , 52 ), // #263 + INST(Fsubrp , FpuRDef , O_FPU(00,DEE0,_) , 0 , 39 , 0 , 65 , 52 ), // #264 + INST(Ftst , FpuOp , O_FPU(00,D9E4,_) , 0 , 37 , 0 , 31 , 52 ), // #265 + INST(Fucom , FpuRDef , O_FPU(00,DDE0,_) , 0 , 50 , 0 , 65 , 52 ), // #266 + INST(Fucomi , FpuR , O_FPU(00,DBE8,_) , 0 , 44 , 0 , 67 , 57 ), // #267 + INST(Fucomip , FpuR , O_FPU(00,DFE8,_) , 0 , 46 , 0 , 67 , 57 ), // #268 + INST(Fucomp , FpuRDef , O_FPU(00,DDE8,_) , 0 , 50 , 0 , 65 , 52 ), // #269 + INST(Fucompp , FpuOp , O_FPU(00,DAE9,_) , 0 , 43 , 0 , 31 , 52 ), // #270 + INST(Fwait , X86Op , O_FPU(00,009B,_) , 0 , 51 , 0 , 31 , 52 ), // #271 + INST(Fxam , FpuOp , O_FPU(00,D9E5,_) , 0 , 37 , 0 , 31 , 52 ), // #272 + INST(Fxch , FpuR , O_FPU(00,D9C8,_) , 0 , 37 , 0 , 65 , 52 ), // #273 + INST(Fxrstor , X86M_Only , O(000F00,AE,1,_,_,_,_,_ ), 0 , 32 , 0 , 32 , 60 ), // #274 + INST(Fxrstor64 , X86M_Only , O(000F00,AE,1,_,1,_,_,_ ), 0 , 31 , 0 , 75 , 60 ), // #275 + INST(Fxsave , X86M_Only , O(000F00,AE,0,_,_,_,_,_ ), 0 , 5 , 0 , 32 , 61 ), // #276 + INST(Fxsave64 , X86M_Only , O(000F00,AE,0,_,1,_,_,_ ), 0 , 62 , 0 , 75 , 61 ), // #277 + INST(Fxtract , FpuOp , O_FPU(00,D9F4,_) , 0 , 37 , 0 , 31 , 52 ), // #278 + INST(Fyl2x , FpuOp , O_FPU(00,D9F1,_) , 0 , 37 , 0 , 31 , 52 ), // #279 + INST(Fyl2xp1 , FpuOp , O_FPU(00,D9F9,_) , 0 , 37 , 0 , 31 , 52 ), // #280 + INST(Getsec , X86Op , O(000F00,37,_,_,_,_,_,_ ), 0 , 5 , 0 , 56 , 62 ), // #281 + INST(Gf2p8affineinvqb , ExtRmi , O(660F3A,CF,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 63 ), // #282 + INST(Gf2p8affineqb , ExtRmi , O(660F3A,CE,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 63 ), // #283 + INST(Gf2p8mulb , ExtRm , O(660F38,CF,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 63 ), // #284 + INST(Haddpd , ExtRm , O(660F00,7C,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 7 ), // #285 + INST(Haddps , ExtRm , O(F20F00,7C,_,_,_,_,_,_ ), 0 , 6 , 0 , 6 , 7 ), // #286 + INST(Hlt , X86Op , O(000000,F4,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 0 ), // #287 + INST(Hreset , X86Op_Mod11RM_I8 , O(F30F3A,F0,0,_,_,_,_,_ ), 0 , 63 , 0 , 76 , 64 ), // #288 + INST(Hsubpd , ExtRm , O(660F00,7D,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 7 ), // #289 + INST(Hsubps , ExtRm , O(F20F00,7D,_,_,_,_,_,_ ), 0 , 6 , 0 , 6 , 7 ), // #290 + INST(Idiv , X86M_GPB_MulDiv , O(000000,F6,7,_,x,_,_,_ ), 0 , 29 , 0 , 58 , 1 ), // #291 + INST(Imul , X86Imul , O(000000,F6,5,_,x,_,_,_ ), 0 , 64 , 0 , 77 , 1 ), // #292 + INST(In , X86In , O(000000,EC,_,_,_,_,_,_ ), O(000000,E4,_,_,_,_,_,_ ), 0 , 15 , 78 , 0 ), // #293 + INST(Inc , X86IncDec , O(000000,FE,0,_,x,_,_,_ ), O(000000,40,_,_,x,_,_,_ ), 0 , 16 , 79 , 47 ), // #294 + INST(Incsspd , X86M , O(F30F00,AE,5,_,0,_,_,_ ), 0 , 65 , 0 , 80 , 65 ), // #295 + INST(Incsspq , X86M , O(F30F00,AE,5,_,1,_,_,_ ), 0 , 66 , 0 , 81 , 65 ), // #296 + INST(Ins , X86Ins , O(000000,6C,_,_,_,_,_,_ ), 0 , 0 , 0 , 82 , 0 ), // #297 + INST(Insertps , ExtRmi , O(660F3A,21,_,_,_,_,_,_ ), 0 , 9 , 0 , 40 , 13 ), // #298 + INST(Insertq , ExtInsertq , O(F20F00,79,_,_,_,_,_,_ ), O(F20F00,78,_,_,_,_,_,_ ), 6 , 17 , 83 , 51 ), // #299 + INST(Int , X86Int , O(000000,CD,_,_,_,_,_,_ ), 0 , 0 , 0 , 84 , 0 ), // #300 + INST(Int3 , X86Op , O(000000,CC,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 0 ), // #301 + INST(Into , X86Op , O(000000,CE,_,_,_,_,_,_ ), 0 , 0 , 0 , 85 , 66 ), // #302 + INST(Invd , X86Op , O(000F00,08,_,_,_,_,_,_ ), 0 , 5 , 0 , 31 , 45 ), // #303 + INST(Invept , X86Rm_NoSize , O(660F38,80,_,_,_,_,_,_ ), 0 , 2 , 0 , 86 , 67 ), // #304 + INST(Invlpg , X86M_Only , O(000F00,01,7,_,_,_,_,_ ), 0 , 24 , 0 , 32 , 45 ), // #305 + INST(Invlpga , X86Op_xAddr , O(000F01,DF,_,_,_,_,_,_ ), 0 , 23 , 0 , 87 , 23 ), // #306 + INST(Invlpgb , X86Op , O(000F01,FE,_,_,_,_,_,_ ), 0 , 23 , 0 , 88 , 68 ), // #307 + INST(Invpcid , X86Rm_NoSize , O(660F38,82,_,_,_,_,_,_ ), 0 , 2 , 0 , 86 , 45 ), // #308 + INST(Invvpid , X86Rm_NoSize , O(660F38,81,_,_,_,_,_,_ ), 0 , 2 , 0 , 86 , 67 ), // #309 + INST(Iret , X86Op , O(660000,CF,_,_,_,_,_,_ ), 0 , 21 , 0 , 89 , 1 ), // #310 + INST(Iretd , X86Op , O(000000,CF,_,_,_,_,_,_ ), 0 , 0 , 0 , 89 , 1 ), // #311 + INST(Iretq , X86Op , O(000000,CF,_,_,1,_,_,_ ), 0 , 22 , 0 , 90 , 1 ), // #312 + INST(Ja , X86Jcc , O(000F00,87,_,_,_,_,_,_ ), O(000000,77,_,_,_,_,_,_ ), 5 , 18 , 91 , 69 ), // #313 + INST(Jae , X86Jcc , O(000F00,83,_,_,_,_,_,_ ), O(000000,73,_,_,_,_,_,_ ), 5 , 19 , 91 , 70 ), // #314 + INST(Jb , X86Jcc , O(000F00,82,_,_,_,_,_,_ ), O(000000,72,_,_,_,_,_,_ ), 5 , 20 , 91 , 70 ), // #315 + INST(Jbe , X86Jcc , O(000F00,86,_,_,_,_,_,_ ), O(000000,76,_,_,_,_,_,_ ), 5 , 21 , 91 , 69 ), // #316 + INST(Jc , X86Jcc , O(000F00,82,_,_,_,_,_,_ ), O(000000,72,_,_,_,_,_,_ ), 5 , 20 , 91 , 70 ), // #317 + INST(Je , X86Jcc , O(000F00,84,_,_,_,_,_,_ ), O(000000,74,_,_,_,_,_,_ ), 5 , 22 , 91 , 71 ), // #318 + INST(Jecxz , X86JecxzLoop , 0 , O(000000,E3,_,_,_,_,_,_ ), 0 , 23 , 92 , 0 ), // #319 + INST(Jg , X86Jcc , O(000F00,8F,_,_,_,_,_,_ ), O(000000,7F,_,_,_,_,_,_ ), 5 , 24 , 91 , 72 ), // #320 + INST(Jge , X86Jcc , O(000F00,8D,_,_,_,_,_,_ ), O(000000,7D,_,_,_,_,_,_ ), 5 , 25 , 91 , 73 ), // #321 + INST(Jl , X86Jcc , O(000F00,8C,_,_,_,_,_,_ ), O(000000,7C,_,_,_,_,_,_ ), 5 , 26 , 91 , 73 ), // #322 + INST(Jle , X86Jcc , O(000F00,8E,_,_,_,_,_,_ ), O(000000,7E,_,_,_,_,_,_ ), 5 , 27 , 91 , 72 ), // #323 + INST(Jmp , X86Jmp , O(000000,FF,4,_,_,_,_,_ ), O(000000,EB,_,_,_,_,_,_ ), 10 , 28 , 93 , 0 ), // #324 + INST(Jna , X86Jcc , O(000F00,86,_,_,_,_,_,_ ), O(000000,76,_,_,_,_,_,_ ), 5 , 21 , 91 , 69 ), // #325 + INST(Jnae , X86Jcc , O(000F00,82,_,_,_,_,_,_ ), O(000000,72,_,_,_,_,_,_ ), 5 , 20 , 91 , 70 ), // #326 + INST(Jnb , X86Jcc , O(000F00,83,_,_,_,_,_,_ ), O(000000,73,_,_,_,_,_,_ ), 5 , 19 , 91 , 70 ), // #327 + INST(Jnbe , X86Jcc , O(000F00,87,_,_,_,_,_,_ ), O(000000,77,_,_,_,_,_,_ ), 5 , 18 , 91 , 69 ), // #328 + INST(Jnc , X86Jcc , O(000F00,83,_,_,_,_,_,_ ), O(000000,73,_,_,_,_,_,_ ), 5 , 19 , 91 , 70 ), // #329 + INST(Jne , X86Jcc , O(000F00,85,_,_,_,_,_,_ ), O(000000,75,_,_,_,_,_,_ ), 5 , 29 , 91 , 71 ), // #330 + INST(Jng , X86Jcc , O(000F00,8E,_,_,_,_,_,_ ), O(000000,7E,_,_,_,_,_,_ ), 5 , 27 , 91 , 72 ), // #331 + INST(Jnge , X86Jcc , O(000F00,8C,_,_,_,_,_,_ ), O(000000,7C,_,_,_,_,_,_ ), 5 , 26 , 91 , 73 ), // #332 + INST(Jnl , X86Jcc , O(000F00,8D,_,_,_,_,_,_ ), O(000000,7D,_,_,_,_,_,_ ), 5 , 25 , 91 , 73 ), // #333 + INST(Jnle , X86Jcc , O(000F00,8F,_,_,_,_,_,_ ), O(000000,7F,_,_,_,_,_,_ ), 5 , 24 , 91 , 72 ), // #334 + INST(Jno , X86Jcc , O(000F00,81,_,_,_,_,_,_ ), O(000000,71,_,_,_,_,_,_ ), 5 , 30 , 91 , 66 ), // #335 + INST(Jnp , X86Jcc , O(000F00,8B,_,_,_,_,_,_ ), O(000000,7B,_,_,_,_,_,_ ), 5 , 31 , 91 , 74 ), // #336 + INST(Jns , X86Jcc , O(000F00,89,_,_,_,_,_,_ ), O(000000,79,_,_,_,_,_,_ ), 5 , 32 , 91 , 75 ), // #337 + INST(Jnz , X86Jcc , O(000F00,85,_,_,_,_,_,_ ), O(000000,75,_,_,_,_,_,_ ), 5 , 29 , 91 , 71 ), // #338 + INST(Jo , X86Jcc , O(000F00,80,_,_,_,_,_,_ ), O(000000,70,_,_,_,_,_,_ ), 5 , 33 , 91 , 66 ), // #339 + INST(Jp , X86Jcc , O(000F00,8A,_,_,_,_,_,_ ), O(000000,7A,_,_,_,_,_,_ ), 5 , 34 , 91 , 74 ), // #340 + INST(Jpe , X86Jcc , O(000F00,8A,_,_,_,_,_,_ ), O(000000,7A,_,_,_,_,_,_ ), 5 , 34 , 91 , 74 ), // #341 + INST(Jpo , X86Jcc , O(000F00,8B,_,_,_,_,_,_ ), O(000000,7B,_,_,_,_,_,_ ), 5 , 31 , 91 , 74 ), // #342 + INST(Js , X86Jcc , O(000F00,88,_,_,_,_,_,_ ), O(000000,78,_,_,_,_,_,_ ), 5 , 35 , 91 , 75 ), // #343 + INST(Jz , X86Jcc , O(000F00,84,_,_,_,_,_,_ ), O(000000,74,_,_,_,_,_,_ ), 5 , 22 , 91 , 71 ), // #344 + INST(Kaddb , VexRvm , V(660F00,4A,_,1,0,_,_,_ ), 0 , 67 , 0 , 94 , 76 ), // #345 + INST(Kaddd , VexRvm , V(660F00,4A,_,1,1,_,_,_ ), 0 , 68 , 0 , 94 , 77 ), // #346 + INST(Kaddq , VexRvm , V(000F00,4A,_,1,1,_,_,_ ), 0 , 69 , 0 , 94 , 77 ), // #347 + INST(Kaddw , VexRvm , V(000F00,4A,_,1,0,_,_,_ ), 0 , 70 , 0 , 94 , 76 ), // #348 + INST(Kandb , VexRvm , V(660F00,41,_,1,0,_,_,_ ), 0 , 67 , 0 , 94 , 76 ), // #349 + INST(Kandd , VexRvm , V(660F00,41,_,1,1,_,_,_ ), 0 , 68 , 0 , 94 , 77 ), // #350 + INST(Kandnb , VexRvm , V(660F00,42,_,1,0,_,_,_ ), 0 , 67 , 0 , 94 , 76 ), // #351 + INST(Kandnd , VexRvm , V(660F00,42,_,1,1,_,_,_ ), 0 , 68 , 0 , 94 , 77 ), // #352 + INST(Kandnq , VexRvm , V(000F00,42,_,1,1,_,_,_ ), 0 , 69 , 0 , 94 , 77 ), // #353 + INST(Kandnw , VexRvm , V(000F00,42,_,1,0,_,_,_ ), 0 , 70 , 0 , 94 , 78 ), // #354 + INST(Kandq , VexRvm , V(000F00,41,_,1,1,_,_,_ ), 0 , 69 , 0 , 94 , 77 ), // #355 + INST(Kandw , VexRvm , V(000F00,41,_,1,0,_,_,_ ), 0 , 70 , 0 , 94 , 78 ), // #356 + INST(Kmovb , VexKmov , V(660F00,90,_,0,0,_,_,_ ), V(660F00,92,_,0,0,_,_,_ ), 71 , 36 , 95 , 79 ), // #357 + INST(Kmovd , VexKmov , V(660F00,90,_,0,1,_,_,_ ), V(F20F00,92,_,0,0,_,_,_ ), 72 , 37 , 96 , 80 ), // #358 + INST(Kmovq , VexKmov , V(000F00,90,_,0,1,_,_,_ ), V(F20F00,92,_,0,1,_,_,_ ), 73 , 38 , 97 , 80 ), // #359 + INST(Kmovw , VexKmov , V(000F00,90,_,0,0,_,_,_ ), V(000F00,92,_,0,0,_,_,_ ), 74 , 39 , 98 , 81 ), // #360 + INST(Knotb , VexRm , V(660F00,44,_,0,0,_,_,_ ), 0 , 71 , 0 , 99 , 76 ), // #361 + INST(Knotd , VexRm , V(660F00,44,_,0,1,_,_,_ ), 0 , 72 , 0 , 99 , 77 ), // #362 + INST(Knotq , VexRm , V(000F00,44,_,0,1,_,_,_ ), 0 , 73 , 0 , 99 , 77 ), // #363 + INST(Knotw , VexRm , V(000F00,44,_,0,0,_,_,_ ), 0 , 74 , 0 , 99 , 78 ), // #364 + INST(Korb , VexRvm , V(660F00,45,_,1,0,_,_,_ ), 0 , 67 , 0 , 94 , 76 ), // #365 + INST(Kord , VexRvm , V(660F00,45,_,1,1,_,_,_ ), 0 , 68 , 0 , 94 , 77 ), // #366 + INST(Korq , VexRvm , V(000F00,45,_,1,1,_,_,_ ), 0 , 69 , 0 , 94 , 77 ), // #367 + INST(Kortestb , VexRm , V(660F00,98,_,0,0,_,_,_ ), 0 , 71 , 0 , 99 , 82 ), // #368 + INST(Kortestd , VexRm , V(660F00,98,_,0,1,_,_,_ ), 0 , 72 , 0 , 99 , 83 ), // #369 + INST(Kortestq , VexRm , V(000F00,98,_,0,1,_,_,_ ), 0 , 73 , 0 , 99 , 83 ), // #370 + INST(Kortestw , VexRm , V(000F00,98,_,0,0,_,_,_ ), 0 , 74 , 0 , 99 , 84 ), // #371 + INST(Korw , VexRvm , V(000F00,45,_,1,0,_,_,_ ), 0 , 70 , 0 , 94 , 78 ), // #372 + INST(Kshiftlb , VexRmi , V(660F3A,32,_,0,0,_,_,_ ), 0 , 75 , 0 , 100, 76 ), // #373 + INST(Kshiftld , VexRmi , V(660F3A,33,_,0,0,_,_,_ ), 0 , 75 , 0 , 100, 77 ), // #374 + INST(Kshiftlq , VexRmi , V(660F3A,33,_,0,1,_,_,_ ), 0 , 76 , 0 , 100, 77 ), // #375 + INST(Kshiftlw , VexRmi , V(660F3A,32,_,0,1,_,_,_ ), 0 , 76 , 0 , 100, 78 ), // #376 + INST(Kshiftrb , VexRmi , V(660F3A,30,_,0,0,_,_,_ ), 0 , 75 , 0 , 100, 76 ), // #377 + INST(Kshiftrd , VexRmi , V(660F3A,31,_,0,0,_,_,_ ), 0 , 75 , 0 , 100, 77 ), // #378 + INST(Kshiftrq , VexRmi , V(660F3A,31,_,0,1,_,_,_ ), 0 , 76 , 0 , 100, 77 ), // #379 + INST(Kshiftrw , VexRmi , V(660F3A,30,_,0,1,_,_,_ ), 0 , 76 , 0 , 100, 78 ), // #380 + INST(Ktestb , VexRm , V(660F00,99,_,0,0,_,_,_ ), 0 , 71 , 0 , 99 , 82 ), // #381 + INST(Ktestd , VexRm , V(660F00,99,_,0,1,_,_,_ ), 0 , 72 , 0 , 99 , 83 ), // #382 + INST(Ktestq , VexRm , V(000F00,99,_,0,1,_,_,_ ), 0 , 73 , 0 , 99 , 83 ), // #383 + INST(Ktestw , VexRm , V(000F00,99,_,0,0,_,_,_ ), 0 , 74 , 0 , 99 , 82 ), // #384 + INST(Kunpckbw , VexRvm , V(660F00,4B,_,1,0,_,_,_ ), 0 , 67 , 0 , 94 , 78 ), // #385 + INST(Kunpckdq , VexRvm , V(000F00,4B,_,1,1,_,_,_ ), 0 , 69 , 0 , 94 , 77 ), // #386 + INST(Kunpckwd , VexRvm , V(000F00,4B,_,1,0,_,_,_ ), 0 , 70 , 0 , 94 , 77 ), // #387 + INST(Kxnorb , VexRvm , V(660F00,46,_,1,0,_,_,_ ), 0 , 67 , 0 , 101, 76 ), // #388 + INST(Kxnord , VexRvm , V(660F00,46,_,1,1,_,_,_ ), 0 , 68 , 0 , 101, 77 ), // #389 + INST(Kxnorq , VexRvm , V(000F00,46,_,1,1,_,_,_ ), 0 , 69 , 0 , 101, 77 ), // #390 + INST(Kxnorw , VexRvm , V(000F00,46,_,1,0,_,_,_ ), 0 , 70 , 0 , 101, 78 ), // #391 + INST(Kxorb , VexRvm , V(660F00,47,_,1,0,_,_,_ ), 0 , 67 , 0 , 101, 76 ), // #392 + INST(Kxord , VexRvm , V(660F00,47,_,1,1,_,_,_ ), 0 , 68 , 0 , 101, 77 ), // #393 + INST(Kxorq , VexRvm , V(000F00,47,_,1,1,_,_,_ ), 0 , 69 , 0 , 101, 77 ), // #394 + INST(Kxorw , VexRvm , V(000F00,47,_,1,0,_,_,_ ), 0 , 70 , 0 , 101, 78 ), // #395 + INST(Lahf , X86Op , O(000000,9F,_,_,_,_,_,_ ), 0 , 0 , 0 , 102, 85 ), // #396 + INST(Lar , X86Rm , O(000F00,02,_,_,_,_,_,_ ), 0 , 5 , 0 , 103, 11 ), // #397 + INST(Lcall , X86LcallLjmp , O(000000,FF,3,_,_,_,_,_ ), O(000000,9A,_,_,_,_,_,_ ), 77 , 40 , 104, 1 ), // #398 + INST(Lddqu , ExtRm , O(F20F00,F0,_,_,_,_,_,_ ), 0 , 6 , 0 , 105, 7 ), // #399 + INST(Ldmxcsr , X86M_Only , O(000F00,AE,2,_,_,_,_,_ ), 0 , 78 , 0 , 106, 6 ), // #400 + INST(Lds , X86Rm , O(000000,C5,_,_,_,_,_,_ ), 0 , 0 , 0 , 107, 0 ), // #401 + INST(Ldtilecfg , AmxCfg , V(000F38,49,_,0,0,_,_,_ ), 0 , 11 , 0 , 108, 86 ), // #402 + INST(Lea , X86Lea , O(000000,8D,_,_,x,_,_,_ ), 0 , 0 , 0 , 109, 0 ), // #403 + INST(Leave , X86Op , O(000000,C9,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 0 ), // #404 + INST(Les , X86Rm , O(000000,C4,_,_,_,_,_,_ ), 0 , 0 , 0 , 107, 0 ), // #405 + INST(Lfence , X86Fence , O(000F00,AE,5,_,_,_,_,_ ), 0 , 79 , 0 , 31 , 5 ), // #406 + INST(Lfs , X86Rm , O(000F00,B4,_,_,_,_,_,_ ), 0 , 5 , 0 , 110, 0 ), // #407 + INST(Lgdt , X86M_Only , O(000F00,01,2,_,_,_,_,_ ), 0 , 78 , 0 , 32 , 0 ), // #408 + INST(Lgs , X86Rm , O(000F00,B5,_,_,_,_,_,_ ), 0 , 5 , 0 , 110, 0 ), // #409 + INST(Lidt , X86M_Only , O(000F00,01,3,_,_,_,_,_ ), 0 , 80 , 0 , 32 , 0 ), // #410 + INST(Ljmp , X86LcallLjmp , O(000000,FF,5,_,_,_,_,_ ), O(000000,EA,_,_,_,_,_,_ ), 64 , 41 , 111, 0 ), // #411 + INST(Lldt , X86M_NoSize , O(000F00,00,2,_,_,_,_,_ ), 0 , 78 , 0 , 112, 0 ), // #412 + INST(Llwpcb , VexR_Wx , V(XOP_M9,12,0,0,x,_,_,_ ), 0 , 81 , 0 , 113, 87 ), // #413 + INST(Lmsw , X86M_NoSize , O(000F00,01,6,_,_,_,_,_ ), 0 , 82 , 0 , 112, 0 ), // #414 + INST(Lods , X86StrRm , O(000000,AC,_,_,_,_,_,_ ), 0 , 0 , 0 , 114, 88 ), // #415 + INST(Loop , X86JecxzLoop , 0 , O(000000,E2,_,_,_,_,_,_ ), 0 , 42 , 115, 0 ), // #416 + INST(Loope , X86JecxzLoop , 0 , O(000000,E1,_,_,_,_,_,_ ), 0 , 43 , 115, 71 ), // #417 + INST(Loopne , X86JecxzLoop , 0 , O(000000,E0,_,_,_,_,_,_ ), 0 , 44 , 115, 71 ), // #418 + INST(Lsl , X86Rm , O(000F00,03,_,_,_,_,_,_ ), 0 , 5 , 0 , 116, 11 ), // #419 + INST(Lss , X86Rm , O(000F00,B2,_,_,_,_,_,_ ), 0 , 5 , 0 , 110, 0 ), // #420 + INST(Ltr , X86M_NoSize , O(000F00,00,3,_,_,_,_,_ ), 0 , 80 , 0 , 112, 0 ), // #421 + INST(Lwpins , VexVmi4_Wx , V(XOP_MA,12,0,0,x,_,_,_ ), 0 , 83 , 0 , 117, 87 ), // #422 + INST(Lwpval , VexVmi4_Wx , V(XOP_MA,12,1,0,x,_,_,_ ), 0 , 84 , 0 , 117, 87 ), // #423 + INST(Lzcnt , X86Rm_Raw66H , O(F30F00,BD,_,_,x,_,_,_ ), 0 , 7 , 0 , 23 , 89 ), // #424 + INST(Maskmovdqu , ExtRm_ZDI , O(660F00,F7,_,_,_,_,_,_ ), 0 , 4 , 0 , 118, 5 ), // #425 + INST(Maskmovq , ExtRm_ZDI , O(000F00,F7,_,_,_,_,_,_ ), 0 , 5 , 0 , 119, 90 ), // #426 + INST(Maxpd , ExtRm , O(660F00,5F,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #427 + INST(Maxps , ExtRm , O(000F00,5F,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #428 + INST(Maxsd , ExtRm , O(F20F00,5F,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 5 ), // #429 + INST(Maxss , ExtRm , O(F30F00,5F,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #430 + INST(Mcommit , X86Op , O(F30F01,FA,_,_,_,_,_,_ ), 0 , 27 , 0 , 31 , 91 ), // #431 + INST(Mfence , X86Fence , O(000F00,AE,6,_,_,_,_,_ ), 0 , 82 , 0 , 31 , 5 ), // #432 + INST(Minpd , ExtRm , O(660F00,5D,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #433 + INST(Minps , ExtRm , O(000F00,5D,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #434 + INST(Minsd , ExtRm , O(F20F00,5D,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 5 ), // #435 + INST(Minss , ExtRm , O(F30F00,5D,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #436 + INST(Monitor , X86Op , O(000F01,C8,_,_,_,_,_,_ ), 0 , 23 , 0 , 120, 92 ), // #437 + INST(Monitorx , X86Op , O(000F01,FA,_,_,_,_,_,_ ), 0 , 23 , 0 , 120, 93 ), // #438 + INST(Mov , X86Mov , 0 , 0 , 0 , 0 , 121, 94 ), // #439 + INST(Movabs , X86Movabs , 0 , 0 , 0 , 0 , 122, 0 ), // #440 + INST(Movapd , ExtMov , O(660F00,28,_,_,_,_,_,_ ), O(660F00,29,_,_,_,_,_,_ ), 4 , 45 , 123, 95 ), // #441 + INST(Movaps , ExtMov , O(000F00,28,_,_,_,_,_,_ ), O(000F00,29,_,_,_,_,_,_ ), 5 , 46 , 123, 96 ), // #442 + INST(Movbe , ExtMovbe , O(000F38,F0,_,_,x,_,_,_ ), O(000F38,F1,_,_,x,_,_,_ ), 1 , 47 , 124, 97 ), // #443 + INST(Movd , ExtMovd , O(000F00,6E,_,_,_,_,_,_ ), O(000F00,7E,_,_,_,_,_,_ ), 5 , 48 , 125, 98 ), // #444 + INST(Movddup , ExtMov , O(F20F00,12,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 7 ), // #445 + INST(Movdir64b , X86EnqcmdMovdir64b , O(660F38,F8,_,_,_,_,_,_ ), 0 , 2 , 0 , 126, 99 ), // #446 + INST(Movdiri , X86MovntiMovdiri , O(000F38,F9,_,_,_,_,_,_ ), 0 , 1 , 0 , 3 , 100), // #447 + INST(Movdq2q , ExtMov , O(F20F00,D6,_,_,_,_,_,_ ), 0 , 6 , 0 , 127, 5 ), // #448 + INST(Movdqa , ExtMov , O(660F00,6F,_,_,_,_,_,_ ), O(660F00,7F,_,_,_,_,_,_ ), 4 , 49 , 123, 95 ), // #449 + INST(Movdqu , ExtMov , O(F30F00,6F,_,_,_,_,_,_ ), O(F30F00,7F,_,_,_,_,_,_ ), 7 , 50 , 123, 95 ), // #450 + INST(Movhlps , ExtMov , O(000F00,12,_,_,_,_,_,_ ), 0 , 5 , 0 , 128, 6 ), // #451 + INST(Movhpd , ExtMov , O(660F00,16,_,_,_,_,_,_ ), O(660F00,17,_,_,_,_,_,_ ), 4 , 51 , 129, 5 ), // #452 + INST(Movhps , ExtMov , O(000F00,16,_,_,_,_,_,_ ), O(000F00,17,_,_,_,_,_,_ ), 5 , 52 , 129, 6 ), // #453 + INST(Movlhps , ExtMov , O(000F00,16,_,_,_,_,_,_ ), 0 , 5 , 0 , 128, 6 ), // #454 + INST(Movlpd , ExtMov , O(660F00,12,_,_,_,_,_,_ ), O(660F00,13,_,_,_,_,_,_ ), 4 , 53 , 129, 5 ), // #455 + INST(Movlps , ExtMov , O(000F00,12,_,_,_,_,_,_ ), O(000F00,13,_,_,_,_,_,_ ), 5 , 54 , 129, 6 ), // #456 + INST(Movmskpd , ExtMov , O(660F00,50,_,_,_,_,_,_ ), 0 , 4 , 0 , 130, 5 ), // #457 + INST(Movmskps , ExtMov , O(000F00,50,_,_,_,_,_,_ ), 0 , 5 , 0 , 130, 6 ), // #458 + INST(Movntdq , ExtMov , 0 , O(660F00,E7,_,_,_,_,_,_ ), 0 , 55 , 131, 5 ), // #459 + INST(Movntdqa , ExtMov , O(660F38,2A,_,_,_,_,_,_ ), 0 , 2 , 0 , 105, 13 ), // #460 + INST(Movnti , X86MovntiMovdiri , O(000F00,C3,_,_,x,_,_,_ ), 0 , 5 , 0 , 3 , 5 ), // #461 + INST(Movntpd , ExtMov , 0 , O(660F00,2B,_,_,_,_,_,_ ), 0 , 56 , 131, 5 ), // #462 + INST(Movntps , ExtMov , 0 , O(000F00,2B,_,_,_,_,_,_ ), 0 , 57 , 131, 6 ), // #463 + INST(Movntq , ExtMov , 0 , O(000F00,E7,_,_,_,_,_,_ ), 0 , 58 , 132, 90 ), // #464 + INST(Movntsd , ExtMov , 0 , O(F20F00,2B,_,_,_,_,_,_ ), 0 , 59 , 133, 51 ), // #465 + INST(Movntss , ExtMov , 0 , O(F30F00,2B,_,_,_,_,_,_ ), 0 , 60 , 134, 51 ), // #466 + INST(Movq , ExtMovq , O(000F00,6E,_,_,x,_,_,_ ), O(000F00,7E,_,_,x,_,_,_ ), 5 , 48 , 135, 101), // #467 + INST(Movq2dq , ExtRm , O(F30F00,D6,_,_,_,_,_,_ ), 0 , 7 , 0 , 136, 5 ), // #468 + INST(Movs , X86StrMm , O(000000,A4,_,_,_,_,_,_ ), 0 , 0 , 0 , 137, 88 ), // #469 + INST(Movsd , ExtMov , O(F20F00,10,_,_,_,_,_,_ ), O(F20F00,11,_,_,_,_,_,_ ), 6 , 61 , 138, 95 ), // #470 + INST(Movshdup , ExtRm , O(F30F00,16,_,_,_,_,_,_ ), 0 , 7 , 0 , 6 , 7 ), // #471 + INST(Movsldup , ExtRm , O(F30F00,12,_,_,_,_,_,_ ), 0 , 7 , 0 , 6 , 7 ), // #472 + INST(Movss , ExtMov , O(F30F00,10,_,_,_,_,_,_ ), O(F30F00,11,_,_,_,_,_,_ ), 7 , 62 , 139, 96 ), // #473 + INST(Movsx , X86MovsxMovzx , O(000F00,BE,_,_,x,_,_,_ ), 0 , 5 , 0 , 140, 0 ), // #474 + INST(Movsxd , X86Rm , O(000000,63,_,_,x,_,_,_ ), 0 , 0 , 0 , 141, 0 ), // #475 + INST(Movupd , ExtMov , O(660F00,10,_,_,_,_,_,_ ), O(660F00,11,_,_,_,_,_,_ ), 4 , 63 , 123, 95 ), // #476 + INST(Movups , ExtMov , O(000F00,10,_,_,_,_,_,_ ), O(000F00,11,_,_,_,_,_,_ ), 5 , 64 , 123, 96 ), // #477 + INST(Movzx , X86MovsxMovzx , O(000F00,B6,_,_,x,_,_,_ ), 0 , 5 , 0 , 140, 0 ), // #478 + INST(Mpsadbw , ExtRmi , O(660F3A,42,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 13 ), // #479 + INST(Mul , X86M_GPB_MulDiv , O(000000,F6,4,_,x,_,_,_ ), 0 , 10 , 0 , 58 , 1 ), // #480 + INST(Mulpd , ExtRm , O(660F00,59,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #481 + INST(Mulps , ExtRm , O(000F00,59,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #482 + INST(Mulsd , ExtRm , O(F20F00,59,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 5 ), // #483 + INST(Mulss , ExtRm , O(F30F00,59,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #484 + INST(Mulx , VexRvm_ZDX_Wx , V(F20F38,F6,_,0,x,_,_,_ ), 0 , 85 , 0 , 142, 102), // #485 + INST(Mwait , X86Op , O(000F01,C9,_,_,_,_,_,_ ), 0 , 23 , 0 , 143, 92 ), // #486 + INST(Mwaitx , X86Op , O(000F01,FB,_,_,_,_,_,_ ), 0 , 23 , 0 , 144, 93 ), // #487 + INST(Neg , X86M_GPB , O(000000,F6,3,_,x,_,_,_ ), 0 , 77 , 0 , 145, 1 ), // #488 + INST(Nop , X86M_Nop , O(000000,90,_,_,_,_,_,_ ), 0 , 0 , 0 , 146, 0 ), // #489 + INST(Not , X86M_GPB , O(000000,F6,2,_,x,_,_,_ ), 0 , 3 , 0 , 145, 0 ), // #490 + INST(Or , X86Arith , O(000000,08,1,_,x,_,_,_ ), 0 , 33 , 0 , 147, 1 ), // #491 + INST(Orpd , ExtRm , O(660F00,56,_,_,_,_,_,_ ), 0 , 4 , 0 , 12 , 5 ), // #492 + INST(Orps , ExtRm , O(000F00,56,_,_,_,_,_,_ ), 0 , 5 , 0 , 12 , 6 ), // #493 + INST(Out , X86Out , O(000000,EE,_,_,_,_,_,_ ), O(000000,E6,_,_,_,_,_,_ ), 0 , 65 , 148, 0 ), // #494 + INST(Outs , X86Outs , O(000000,6E,_,_,_,_,_,_ ), 0 , 0 , 0 , 149, 0 ), // #495 + INST(Pabsb , ExtRm_P , O(000F38,1C,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #496 + INST(Pabsd , ExtRm_P , O(000F38,1E,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #497 + INST(Pabsw , ExtRm_P , O(000F38,1D,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #498 + INST(Packssdw , ExtRm_P , O(000F00,6B,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #499 + INST(Packsswb , ExtRm_P , O(000F00,63,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #500 + INST(Packusdw , ExtRm , O(660F38,2B,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 13 ), // #501 + INST(Packuswb , ExtRm_P , O(000F00,67,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #502 + INST(Paddb , ExtRm_P , O(000F00,FC,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #503 + INST(Paddd , ExtRm_P , O(000F00,FE,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #504 + INST(Paddq , ExtRm_P , O(000F00,D4,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 5 ), // #505 + INST(Paddsb , ExtRm_P , O(000F00,EC,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #506 + INST(Paddsw , ExtRm_P , O(000F00,ED,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #507 + INST(Paddusb , ExtRm_P , O(000F00,DC,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #508 + INST(Paddusw , ExtRm_P , O(000F00,DD,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #509 + INST(Paddw , ExtRm_P , O(000F00,FD,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #510 + INST(Palignr , ExtRmi_P , O(000F3A,0F,_,_,_,_,_,_ ), 0 , 86 , 0 , 151, 103), // #511 + INST(Pand , ExtRm_P , O(000F00,DB,_,_,_,_,_,_ ), 0 , 5 , 0 , 152, 98 ), // #512 + INST(Pandn , ExtRm_P , O(000F00,DF,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #513 + INST(Pause , X86Op , O(F30000,90,_,_,_,_,_,_ ), 0 , 87 , 0 , 31 , 0 ), // #514 + INST(Pavgb , ExtRm_P , O(000F00,E0,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 104), // #515 + INST(Pavgusb , Ext3dNow , O(000F0F,BF,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #516 + INST(Pavgw , ExtRm_P , O(000F00,E3,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 104), // #517 + INST(Pblendvb , ExtRm_XMM0 , O(660F38,10,_,_,_,_,_,_ ), 0 , 2 , 0 , 16 , 13 ), // #518 + INST(Pblendw , ExtRmi , O(660F3A,0E,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 13 ), // #519 + INST(Pclmulqdq , ExtRmi , O(660F3A,44,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 105), // #520 + INST(Pcmpeqb , ExtRm_P , O(000F00,74,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #521 + INST(Pcmpeqd , ExtRm_P , O(000F00,76,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #522 + INST(Pcmpeqq , ExtRm , O(660F38,29,_,_,_,_,_,_ ), 0 , 2 , 0 , 155, 13 ), // #523 + INST(Pcmpeqw , ExtRm_P , O(000F00,75,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #524 + INST(Pcmpestri , ExtRmi , O(660F3A,61,_,_,_,_,_,_ ), 0 , 9 , 0 , 156, 106), // #525 + INST(Pcmpestrm , ExtRmi , O(660F3A,60,_,_,_,_,_,_ ), 0 , 9 , 0 , 157, 106), // #526 + INST(Pcmpgtb , ExtRm_P , O(000F00,64,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #527 + INST(Pcmpgtd , ExtRm_P , O(000F00,66,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #528 + INST(Pcmpgtq , ExtRm , O(660F38,37,_,_,_,_,_,_ ), 0 , 2 , 0 , 155, 46 ), // #529 + INST(Pcmpgtw , ExtRm_P , O(000F00,65,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #530 + INST(Pcmpistri , ExtRmi , O(660F3A,63,_,_,_,_,_,_ ), 0 , 9 , 0 , 158, 106), // #531 + INST(Pcmpistrm , ExtRmi , O(660F3A,62,_,_,_,_,_,_ ), 0 , 9 , 0 , 159, 106), // #532 + INST(Pconfig , X86Op , O(000F01,C5,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 107), // #533 + INST(Pdep , VexRvm_Wx , V(F20F38,F5,_,0,x,_,_,_ ), 0 , 85 , 0 , 11 , 102), // #534 + INST(Pext , VexRvm_Wx , V(F30F38,F5,_,0,x,_,_,_ ), 0 , 89 , 0 , 11 , 102), // #535 + INST(Pextrb , ExtExtract , O(000F3A,14,_,_,_,_,_,_ ), 0 , 86 , 0 , 160, 13 ), // #536 + INST(Pextrd , ExtExtract , O(000F3A,16,_,_,_,_,_,_ ), 0 , 86 , 0 , 62 , 13 ), // #537 + INST(Pextrq , ExtExtract , O(000F3A,16,_,_,1,_,_,_ ), 0 , 90 , 0 , 161, 13 ), // #538 + INST(Pextrw , ExtPextrw , O(000F00,C5,_,_,_,_,_,_ ), O(000F3A,15,_,_,_,_,_,_ ), 5 , 66 , 162, 108), // #539 + INST(Pf2id , Ext3dNow , O(000F0F,1D,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #540 + INST(Pf2iw , Ext3dNow , O(000F0F,1C,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 109), // #541 + INST(Pfacc , Ext3dNow , O(000F0F,AE,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #542 + INST(Pfadd , Ext3dNow , O(000F0F,9E,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #543 + INST(Pfcmpeq , Ext3dNow , O(000F0F,B0,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #544 + INST(Pfcmpge , Ext3dNow , O(000F0F,90,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #545 + INST(Pfcmpgt , Ext3dNow , O(000F0F,A0,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #546 + INST(Pfmax , Ext3dNow , O(000F0F,A4,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #547 + INST(Pfmin , Ext3dNow , O(000F0F,94,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #548 + INST(Pfmul , Ext3dNow , O(000F0F,B4,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #549 + INST(Pfnacc , Ext3dNow , O(000F0F,8A,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 109), // #550 + INST(Pfpnacc , Ext3dNow , O(000F0F,8E,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 109), // #551 + INST(Pfrcp , Ext3dNow , O(000F0F,96,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #552 + INST(Pfrcpit1 , Ext3dNow , O(000F0F,A6,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #553 + INST(Pfrcpit2 , Ext3dNow , O(000F0F,B6,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #554 + INST(Pfrcpv , Ext3dNow , O(000F0F,86,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 110), // #555 + INST(Pfrsqit1 , Ext3dNow , O(000F0F,A7,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #556 + INST(Pfrsqrt , Ext3dNow , O(000F0F,97,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #557 + INST(Pfrsqrtv , Ext3dNow , O(000F0F,87,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 110), // #558 + INST(Pfsub , Ext3dNow , O(000F0F,9A,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #559 + INST(Pfsubr , Ext3dNow , O(000F0F,AA,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #560 + INST(Phaddd , ExtRm_P , O(000F38,02,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #561 + INST(Phaddsw , ExtRm_P , O(000F38,03,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #562 + INST(Phaddw , ExtRm_P , O(000F38,01,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #563 + INST(Phminposuw , ExtRm , O(660F38,41,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 13 ), // #564 + INST(Phsubd , ExtRm_P , O(000F38,06,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #565 + INST(Phsubsw , ExtRm_P , O(000F38,07,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #566 + INST(Phsubw , ExtRm_P , O(000F38,05,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #567 + INST(Pi2fd , Ext3dNow , O(000F0F,0D,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #568 + INST(Pi2fw , Ext3dNow , O(000F0F,0C,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 109), // #569 + INST(Pinsrb , ExtRmi , O(660F3A,20,_,_,_,_,_,_ ), 0 , 9 , 0 , 163, 13 ), // #570 + INST(Pinsrd , ExtRmi , O(660F3A,22,_,_,_,_,_,_ ), 0 , 9 , 0 , 164, 13 ), // #571 + INST(Pinsrq , ExtRmi , O(660F3A,22,_,_,1,_,_,_ ), 0 , 91 , 0 , 165, 13 ), // #572 + INST(Pinsrw , ExtRmi_P , O(000F00,C4,_,_,_,_,_,_ ), 0 , 5 , 0 , 166, 104), // #573 + INST(Pmaddubsw , ExtRm_P , O(000F38,04,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #574 + INST(Pmaddwd , ExtRm_P , O(000F00,F5,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #575 + INST(Pmaxsb , ExtRm , O(660F38,3C,_,_,_,_,_,_ ), 0 , 2 , 0 , 12 , 13 ), // #576 + INST(Pmaxsd , ExtRm , O(660F38,3D,_,_,_,_,_,_ ), 0 , 2 , 0 , 12 , 13 ), // #577 + INST(Pmaxsw , ExtRm_P , O(000F00,EE,_,_,_,_,_,_ ), 0 , 5 , 0 , 152, 104), // #578 + INST(Pmaxub , ExtRm_P , O(000F00,DE,_,_,_,_,_,_ ), 0 , 5 , 0 , 152, 104), // #579 + INST(Pmaxud , ExtRm , O(660F38,3F,_,_,_,_,_,_ ), 0 , 2 , 0 , 12 , 13 ), // #580 + INST(Pmaxuw , ExtRm , O(660F38,3E,_,_,_,_,_,_ ), 0 , 2 , 0 , 12 , 13 ), // #581 + INST(Pminsb , ExtRm , O(660F38,38,_,_,_,_,_,_ ), 0 , 2 , 0 , 12 , 13 ), // #582 + INST(Pminsd , ExtRm , O(660F38,39,_,_,_,_,_,_ ), 0 , 2 , 0 , 12 , 13 ), // #583 + INST(Pminsw , ExtRm_P , O(000F00,EA,_,_,_,_,_,_ ), 0 , 5 , 0 , 152, 104), // #584 + INST(Pminub , ExtRm_P , O(000F00,DA,_,_,_,_,_,_ ), 0 , 5 , 0 , 152, 104), // #585 + INST(Pminud , ExtRm , O(660F38,3B,_,_,_,_,_,_ ), 0 , 2 , 0 , 12 , 13 ), // #586 + INST(Pminuw , ExtRm , O(660F38,3A,_,_,_,_,_,_ ), 0 , 2 , 0 , 12 , 13 ), // #587 + INST(Pmovmskb , ExtRm_P , O(000F00,D7,_,_,_,_,_,_ ), 0 , 5 , 0 , 167, 104), // #588 + INST(Pmovsxbd , ExtRm , O(660F38,21,_,_,_,_,_,_ ), 0 , 2 , 0 , 8 , 13 ), // #589 + INST(Pmovsxbq , ExtRm , O(660F38,22,_,_,_,_,_,_ ), 0 , 2 , 0 , 168, 13 ), // #590 + INST(Pmovsxbw , ExtRm , O(660F38,20,_,_,_,_,_,_ ), 0 , 2 , 0 , 7 , 13 ), // #591 + INST(Pmovsxdq , ExtRm , O(660F38,25,_,_,_,_,_,_ ), 0 , 2 , 0 , 7 , 13 ), // #592 + INST(Pmovsxwd , ExtRm , O(660F38,23,_,_,_,_,_,_ ), 0 , 2 , 0 , 7 , 13 ), // #593 + INST(Pmovsxwq , ExtRm , O(660F38,24,_,_,_,_,_,_ ), 0 , 2 , 0 , 8 , 13 ), // #594 + INST(Pmovzxbd , ExtRm , O(660F38,31,_,_,_,_,_,_ ), 0 , 2 , 0 , 8 , 13 ), // #595 + INST(Pmovzxbq , ExtRm , O(660F38,32,_,_,_,_,_,_ ), 0 , 2 , 0 , 168, 13 ), // #596 + INST(Pmovzxbw , ExtRm , O(660F38,30,_,_,_,_,_,_ ), 0 , 2 , 0 , 7 , 13 ), // #597 + INST(Pmovzxdq , ExtRm , O(660F38,35,_,_,_,_,_,_ ), 0 , 2 , 0 , 7 , 13 ), // #598 + INST(Pmovzxwd , ExtRm , O(660F38,33,_,_,_,_,_,_ ), 0 , 2 , 0 , 7 , 13 ), // #599 + INST(Pmovzxwq , ExtRm , O(660F38,34,_,_,_,_,_,_ ), 0 , 2 , 0 , 8 , 13 ), // #600 + INST(Pmuldq , ExtRm , O(660F38,28,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 13 ), // #601 + INST(Pmulhrsw , ExtRm_P , O(000F38,0B,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #602 + INST(Pmulhrw , Ext3dNow , O(000F0F,B7,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 58 ), // #603 + INST(Pmulhuw , ExtRm_P , O(000F00,E4,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 104), // #604 + INST(Pmulhw , ExtRm_P , O(000F00,E5,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #605 + INST(Pmulld , ExtRm , O(660F38,40,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 13 ), // #606 + INST(Pmullw , ExtRm_P , O(000F00,D5,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #607 + INST(Pmuludq , ExtRm_P , O(000F00,F4,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 5 ), // #608 + INST(Pop , X86Pop , O(000000,8F,0,_,_,_,_,_ ), O(000000,58,_,_,_,_,_,_ ), 0 , 67 , 169, 0 ), // #609 + INST(Popa , X86Op , O(660000,61,_,_,_,_,_,_ ), 0 , 21 , 0 , 85 , 0 ), // #610 + INST(Popad , X86Op , O(000000,61,_,_,_,_,_,_ ), 0 , 0 , 0 , 85 , 0 ), // #611 + INST(Popcnt , X86Rm_Raw66H , O(F30F00,B8,_,_,x,_,_,_ ), 0 , 7 , 0 , 23 , 111), // #612 + INST(Popf , X86Op , O(660000,9D,_,_,_,_,_,_ ), 0 , 21 , 0 , 31 , 112), // #613 + INST(Popfd , X86Op , O(000000,9D,_,_,_,_,_,_ ), 0 , 0 , 0 , 85 , 112), // #614 + INST(Popfq , X86Op , O(000000,9D,_,_,_,_,_,_ ), 0 , 0 , 0 , 34 , 112), // #615 + INST(Por , ExtRm_P , O(000F00,EB,_,_,_,_,_,_ ), 0 , 5 , 0 , 152, 98 ), // #616 + INST(Prefetch , X86M_Only , O(000F00,0D,0,_,_,_,_,_ ), 0 , 5 , 0 , 32 , 58 ), // #617 + INST(Prefetchit0 , X86M_Only , O(000F00,18,7,_,_,_,_,_ ), 0 , 24 , 0 , 75 , 113), // #618 + INST(Prefetchit1 , X86M_Only , O(000F00,18,6,_,_,_,_,_ ), 0 , 82 , 0 , 75 , 113), // #619 + INST(Prefetchnta , X86M_Only , O(000F00,18,0,_,_,_,_,_ ), 0 , 5 , 0 , 32 , 6 ), // #620 + INST(Prefetcht0 , X86M_Only , O(000F00,18,1,_,_,_,_,_ ), 0 , 32 , 0 , 32 , 6 ), // #621 + INST(Prefetcht1 , X86M_Only , O(000F00,18,2,_,_,_,_,_ ), 0 , 78 , 0 , 32 , 6 ), // #622 + INST(Prefetcht2 , X86M_Only , O(000F00,18,3,_,_,_,_,_ ), 0 , 80 , 0 , 32 , 6 ), // #623 + INST(Prefetchw , X86M_Only , O(000F00,0D,1,_,_,_,_,_ ), 0 , 32 , 0 , 32 , 114), // #624 + INST(Prefetchwt1 , X86M_Only , O(000F00,0D,2,_,_,_,_,_ ), 0 , 78 , 0 , 32 , 115), // #625 + INST(Psadbw , ExtRm_P , O(000F00,F6,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 104), // #626 + INST(Pshufb , ExtRm_P , O(000F38,00,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #627 + INST(Pshufd , ExtRmi , O(660F00,70,_,_,_,_,_,_ ), 0 , 4 , 0 , 9 , 5 ), // #628 + INST(Pshufhw , ExtRmi , O(F30F00,70,_,_,_,_,_,_ ), 0 , 7 , 0 , 9 , 5 ), // #629 + INST(Pshuflw , ExtRmi , O(F20F00,70,_,_,_,_,_,_ ), 0 , 6 , 0 , 9 , 5 ), // #630 + INST(Pshufw , ExtRmi_P , O(000F00,70,_,_,_,_,_,_ ), 0 , 5 , 0 , 170, 90 ), // #631 + INST(Psignb , ExtRm_P , O(000F38,08,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #632 + INST(Psignd , ExtRm_P , O(000F38,0A,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #633 + INST(Psignw , ExtRm_P , O(000F38,09,_,_,_,_,_,_ ), 0 , 1 , 0 , 150, 103), // #634 + INST(Pslld , ExtRmRi_P , O(000F00,F2,_,_,_,_,_,_ ), O(000F00,72,6,_,_,_,_,_ ), 5 , 68 , 171, 98 ), // #635 + INST(Pslldq , ExtRmRi , 0 , O(660F00,73,7,_,_,_,_,_ ), 0 , 69 , 172, 5 ), // #636 + INST(Psllq , ExtRmRi_P , O(000F00,F3,_,_,_,_,_,_ ), O(000F00,73,6,_,_,_,_,_ ), 5 , 70 , 171, 98 ), // #637 + INST(Psllw , ExtRmRi_P , O(000F00,F1,_,_,_,_,_,_ ), O(000F00,71,6,_,_,_,_,_ ), 5 , 71 , 171, 98 ), // #638 + INST(Psmash , X86Op , O(F30F01,FF,_,_,_,_,_,_ ), 0 , 27 , 0 , 34 , 116), // #639 + INST(Psrad , ExtRmRi_P , O(000F00,E2,_,_,_,_,_,_ ), O(000F00,72,4,_,_,_,_,_ ), 5 , 72 , 171, 98 ), // #640 + INST(Psraw , ExtRmRi_P , O(000F00,E1,_,_,_,_,_,_ ), O(000F00,71,4,_,_,_,_,_ ), 5 , 73 , 171, 98 ), // #641 + INST(Psrld , ExtRmRi_P , O(000F00,D2,_,_,_,_,_,_ ), O(000F00,72,2,_,_,_,_,_ ), 5 , 74 , 171, 98 ), // #642 + INST(Psrldq , ExtRmRi , 0 , O(660F00,73,3,_,_,_,_,_ ), 0 , 75 , 172, 5 ), // #643 + INST(Psrlq , ExtRmRi_P , O(000F00,D3,_,_,_,_,_,_ ), O(000F00,73,2,_,_,_,_,_ ), 5 , 76 , 171, 98 ), // #644 + INST(Psrlw , ExtRmRi_P , O(000F00,D1,_,_,_,_,_,_ ), O(000F00,71,2,_,_,_,_,_ ), 5 , 77 , 171, 98 ), // #645 + INST(Psubb , ExtRm_P , O(000F00,F8,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #646 + INST(Psubd , ExtRm_P , O(000F00,FA,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #647 + INST(Psubq , ExtRm_P , O(000F00,FB,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 5 ), // #648 + INST(Psubsb , ExtRm_P , O(000F00,E8,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #649 + INST(Psubsw , ExtRm_P , O(000F00,E9,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #650 + INST(Psubusb , ExtRm_P , O(000F00,D8,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #651 + INST(Psubusw , ExtRm_P , O(000F00,D9,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #652 + INST(Psubw , ExtRm_P , O(000F00,F9,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #653 + INST(Pswapd , Ext3dNow , O(000F0F,BB,_,_,_,_,_,_ ), 0 , 88 , 0 , 154, 109), // #654 + INST(Ptest , ExtRm , O(660F38,17,_,_,_,_,_,_ ), 0 , 2 , 0 , 6 , 117), // #655 + INST(Ptwrite , X86M , O(F30F00,AE,4,_,_,_,_,_ ), 0 , 92 , 0 , 173, 118), // #656 + INST(Punpckhbw , ExtRm_P , O(000F00,68,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #657 + INST(Punpckhdq , ExtRm_P , O(000F00,6A,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #658 + INST(Punpckhqdq , ExtRm , O(660F00,6D,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #659 + INST(Punpckhwd , ExtRm_P , O(000F00,69,_,_,_,_,_,_ ), 0 , 5 , 0 , 150, 98 ), // #660 + INST(Punpcklbw , ExtRm_P , O(000F00,60,_,_,_,_,_,_ ), 0 , 5 , 0 , 174, 98 ), // #661 + INST(Punpckldq , ExtRm_P , O(000F00,62,_,_,_,_,_,_ ), 0 , 5 , 0 , 174, 98 ), // #662 + INST(Punpcklqdq , ExtRm , O(660F00,6C,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #663 + INST(Punpcklwd , ExtRm_P , O(000F00,61,_,_,_,_,_,_ ), 0 , 5 , 0 , 174, 98 ), // #664 + INST(Push , X86Push , O(000000,FF,6,_,_,_,_,_ ), O(000000,50,_,_,_,_,_,_ ), 34 , 78 , 175, 0 ), // #665 + INST(Pusha , X86Op , O(660000,60,_,_,_,_,_,_ ), 0 , 21 , 0 , 85 , 0 ), // #666 + INST(Pushad , X86Op , O(000000,60,_,_,_,_,_,_ ), 0 , 0 , 0 , 85 , 0 ), // #667 + INST(Pushf , X86Op , O(660000,9C,_,_,_,_,_,_ ), 0 , 21 , 0 , 31 , 119), // #668 + INST(Pushfd , X86Op , O(000000,9C,_,_,_,_,_,_ ), 0 , 0 , 0 , 85 , 119), // #669 + INST(Pushfq , X86Op , O(000000,9C,_,_,_,_,_,_ ), 0 , 0 , 0 , 34 , 119), // #670 + INST(Pvalidate , X86Op , O(F20F01,FF,_,_,_,_,_,_ ), 0 , 93 , 0 , 31 , 120), // #671 + INST(Pxor , ExtRm_P , O(000F00,EF,_,_,_,_,_,_ ), 0 , 5 , 0 , 153, 98 ), // #672 + INST(Rcl , X86Rot , O(000000,D0,2,_,x,_,_,_ ), 0 , 3 , 0 , 176, 121), // #673 + INST(Rcpps , ExtRm , O(000F00,53,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #674 + INST(Rcpss , ExtRm , O(F30F00,53,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #675 + INST(Rcr , X86Rot , O(000000,D0,3,_,x,_,_,_ ), 0 , 77 , 0 , 176, 121), // #676 + INST(Rdfsbase , X86M , O(F30F00,AE,0,_,x,_,_,_ ), 0 , 7 , 0 , 177, 122), // #677 + INST(Rdgsbase , X86M , O(F30F00,AE,1,_,x,_,_,_ ), 0 , 94 , 0 , 177, 122), // #678 + INST(Rdmsr , X86Op , O(000F00,32,_,_,_,_,_,_ ), 0 , 5 , 0 , 178, 123), // #679 + INST(Rdpid , X86R_Native , O(F30F00,C7,7,_,_,_,_,_ ), 0 , 95 , 0 , 179, 124), // #680 + INST(Rdpkru , X86Op , O(000F01,EE,_,_,_,_,_,_ ), 0 , 23 , 0 , 178, 125), // #681 + INST(Rdpmc , X86Op , O(000F00,33,_,_,_,_,_,_ ), 0 , 5 , 0 , 178, 0 ), // #682 + INST(Rdpru , X86Op , O(000F01,FD,_,_,_,_,_,_ ), 0 , 23 , 0 , 178, 126), // #683 + INST(Rdrand , X86M , O(000F00,C7,6,_,x,_,_,_ ), 0 , 82 , 0 , 24 , 127), // #684 + INST(Rdseed , X86M , O(000F00,C7,7,_,x,_,_,_ ), 0 , 24 , 0 , 24 , 128), // #685 + INST(Rdsspd , X86M , O(F30F00,1E,1,_,_,_,_,_ ), 0 , 94 , 0 , 80 , 65 ), // #686 + INST(Rdsspq , X86M , O(F30F00,1E,1,_,_,_,_,_ ), 0 , 94 , 0 , 81 , 65 ), // #687 + INST(Rdtsc , X86Op , O(000F00,31,_,_,_,_,_,_ ), 0 , 5 , 0 , 29 , 129), // #688 + INST(Rdtscp , X86Op , O(000F01,F9,_,_,_,_,_,_ ), 0 , 23 , 0 , 178, 130), // #689 + INST(Ret , X86Ret , O(000000,C2,_,_,_,_,_,_ ), 0 , 0 , 0 , 180, 0 ), // #690 + INST(Retf , X86Ret , O(000000,CA,_,_,x,_,_,_ ), 0 , 0 , 0 , 181, 0 ), // #691 + INST(Rmpadjust , X86Op , O(F30F01,FE,_,_,_,_,_,_ ), 0 , 27 , 0 , 34 , 116), // #692 + INST(Rmpupdate , X86Op , O(F20F01,FE,_,_,_,_,_,_ ), 0 , 93 , 0 , 34 , 116), // #693 + INST(Rol , X86Rot , O(000000,D0,0,_,x,_,_,_ ), 0 , 0 , 0 , 176, 131), // #694 + INST(Ror , X86Rot , O(000000,D0,1,_,x,_,_,_ ), 0 , 33 , 0 , 176, 131), // #695 + INST(Rorx , VexRmi_Wx , V(F20F3A,F0,_,0,x,_,_,_ ), 0 , 96 , 0 , 182, 102), // #696 + INST(Roundpd , ExtRmi , O(660F3A,09,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 13 ), // #697 + INST(Roundps , ExtRmi , O(660F3A,08,_,_,_,_,_,_ ), 0 , 9 , 0 , 9 , 13 ), // #698 + INST(Roundsd , ExtRmi , O(660F3A,0B,_,_,_,_,_,_ ), 0 , 9 , 0 , 39 , 13 ), // #699 + INST(Roundss , ExtRmi , O(660F3A,0A,_,_,_,_,_,_ ), 0 , 9 , 0 , 40 , 13 ), // #700 + INST(Rsm , X86Op , O(000F00,AA,_,_,_,_,_,_ ), 0 , 5 , 0 , 85 , 1 ), // #701 + INST(Rsqrtps , ExtRm , O(000F00,52,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #702 + INST(Rsqrtss , ExtRm , O(F30F00,52,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #703 + INST(Rstorssp , X86M_Only , O(F30F00,01,5,_,_,_,_,_ ), 0 , 65 , 0 , 33 , 25 ), // #704 + INST(Sahf , X86Op , O(000000,9E,_,_,_,_,_,_ ), 0 , 0 , 0 , 102, 132), // #705 + INST(Sal , X86Rot , O(000000,D0,4,_,x,_,_,_ ), 0 , 10 , 0 , 176, 1 ), // #706 + INST(Sar , X86Rot , O(000000,D0,7,_,x,_,_,_ ), 0 , 29 , 0 , 176, 1 ), // #707 + INST(Sarx , VexRmv_Wx , V(F30F38,F7,_,0,x,_,_,_ ), 0 , 89 , 0 , 14 , 102), // #708 + INST(Saveprevssp , X86Op , O(F30F01,EA,_,_,_,_,_,_ ), 0 , 27 , 0 , 31 , 25 ), // #709 + INST(Sbb , X86Arith , O(000000,18,3,_,x,_,_,_ ), 0 , 77 , 0 , 183, 3 ), // #710 + INST(Scas , X86StrRm , O(000000,AE,_,_,_,_,_,_ ), 0 , 0 , 0 , 184, 39 ), // #711 + INST(Seamcall , X86Op , O(660F01,CF,_,_,_,_,_,_ ), 0 , 97 , 0 , 31 , 133), // #712 + INST(Seamops , X86Op , O(660F01,CE,_,_,_,_,_,_ ), 0 , 97 , 0 , 31 , 133), // #713 + INST(Seamret , X86Op , O(660F01,CD,_,_,_,_,_,_ ), 0 , 97 , 0 , 31 , 133), // #714 + INST(Senduipi , X86M_NoSize , O(F30F00,C7,6,_,_,_,_,_ ), 0 , 26 , 0 , 81 , 26 ), // #715 + INST(Serialize , X86Op , O(000F01,E8,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 134), // #716 + INST(Seta , X86Set , O(000F00,97,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 69 ), // #717 + INST(Setae , X86Set , O(000F00,93,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 70 ), // #718 + INST(Setb , X86Set , O(000F00,92,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 70 ), // #719 + INST(Setbe , X86Set , O(000F00,96,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 69 ), // #720 + INST(Setc , X86Set , O(000F00,92,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 70 ), // #721 + INST(Sete , X86Set , O(000F00,94,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 71 ), // #722 + INST(Setg , X86Set , O(000F00,9F,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 72 ), // #723 + INST(Setge , X86Set , O(000F00,9D,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 73 ), // #724 + INST(Setl , X86Set , O(000F00,9C,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 73 ), // #725 + INST(Setle , X86Set , O(000F00,9E,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 72 ), // #726 + INST(Setna , X86Set , O(000F00,96,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 69 ), // #727 + INST(Setnae , X86Set , O(000F00,92,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 70 ), // #728 + INST(Setnb , X86Set , O(000F00,93,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 70 ), // #729 + INST(Setnbe , X86Set , O(000F00,97,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 69 ), // #730 + INST(Setnc , X86Set , O(000F00,93,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 70 ), // #731 + INST(Setne , X86Set , O(000F00,95,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 71 ), // #732 + INST(Setng , X86Set , O(000F00,9E,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 72 ), // #733 + INST(Setnge , X86Set , O(000F00,9C,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 73 ), // #734 + INST(Setnl , X86Set , O(000F00,9D,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 73 ), // #735 + INST(Setnle , X86Set , O(000F00,9F,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 72 ), // #736 + INST(Setno , X86Set , O(000F00,91,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 66 ), // #737 + INST(Setnp , X86Set , O(000F00,9B,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 74 ), // #738 + INST(Setns , X86Set , O(000F00,99,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 75 ), // #739 + INST(Setnz , X86Set , O(000F00,95,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 71 ), // #740 + INST(Seto , X86Set , O(000F00,90,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 66 ), // #741 + INST(Setp , X86Set , O(000F00,9A,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 74 ), // #742 + INST(Setpe , X86Set , O(000F00,9A,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 74 ), // #743 + INST(Setpo , X86Set , O(000F00,9B,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 74 ), // #744 + INST(Sets , X86Set , O(000F00,98,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 75 ), // #745 + INST(Setssbsy , X86Op , O(F30F01,E8,_,_,_,_,_,_ ), 0 , 27 , 0 , 31 , 65 ), // #746 + INST(Setz , X86Set , O(000F00,94,_,_,_,_,_,_ ), 0 , 5 , 0 , 185, 71 ), // #747 + INST(Sfence , X86Fence , O(000F00,AE,7,_,_,_,_,_ ), 0 , 24 , 0 , 31 , 6 ), // #748 + INST(Sgdt , X86M_Only , O(000F00,01,0,_,_,_,_,_ ), 0 , 5 , 0 , 32 , 0 ), // #749 + INST(Sha1msg1 , ExtRm , O(000F38,C9,_,_,_,_,_,_ ), 0 , 1 , 0 , 6 , 135), // #750 + INST(Sha1msg2 , ExtRm , O(000F38,CA,_,_,_,_,_,_ ), 0 , 1 , 0 , 6 , 135), // #751 + INST(Sha1nexte , ExtRm , O(000F38,C8,_,_,_,_,_,_ ), 0 , 1 , 0 , 6 , 135), // #752 + INST(Sha1rnds4 , ExtRmi , O(000F3A,CC,_,_,_,_,_,_ ), 0 , 86 , 0 , 9 , 135), // #753 + INST(Sha256msg1 , ExtRm , O(000F38,CC,_,_,_,_,_,_ ), 0 , 1 , 0 , 6 , 135), // #754 + INST(Sha256msg2 , ExtRm , O(000F38,CD,_,_,_,_,_,_ ), 0 , 1 , 0 , 6 , 135), // #755 + INST(Sha256rnds2 , ExtRm_XMM0 , O(000F38,CB,_,_,_,_,_,_ ), 0 , 1 , 0 , 16 , 135), // #756 + INST(Shl , X86Rot , O(000000,D0,4,_,x,_,_,_ ), 0 , 10 , 0 , 176, 1 ), // #757 + INST(Shld , X86ShldShrd , O(000F00,A4,_,_,x,_,_,_ ), 0 , 5 , 0 , 186, 1 ), // #758 + INST(Shlx , VexRmv_Wx , V(660F38,F7,_,0,x,_,_,_ ), 0 , 30 , 0 , 14 , 102), // #759 + INST(Shr , X86Rot , O(000000,D0,5,_,x,_,_,_ ), 0 , 64 , 0 , 176, 1 ), // #760 + INST(Shrd , X86ShldShrd , O(000F00,AC,_,_,x,_,_,_ ), 0 , 5 , 0 , 186, 1 ), // #761 + INST(Shrx , VexRmv_Wx , V(F20F38,F7,_,0,x,_,_,_ ), 0 , 85 , 0 , 14 , 102), // #762 + INST(Shufpd , ExtRmi , O(660F00,C6,_,_,_,_,_,_ ), 0 , 4 , 0 , 9 , 5 ), // #763 + INST(Shufps , ExtRmi , O(000F00,C6,_,_,_,_,_,_ ), 0 , 5 , 0 , 9 , 6 ), // #764 + INST(Sidt , X86M_Only , O(000F00,01,1,_,_,_,_,_ ), 0 , 32 , 0 , 32 , 0 ), // #765 + INST(Skinit , X86Op_xAX , O(000F01,DE,_,_,_,_,_,_ ), 0 , 23 , 0 , 56 , 136), // #766 + INST(Sldt , X86M_NoMemSize , O(000F00,00,0,_,_,_,_,_ ), 0 , 5 , 0 , 187, 0 ), // #767 + INST(Slwpcb , VexR_Wx , V(XOP_M9,12,1,0,x,_,_,_ ), 0 , 13 , 0 , 113, 87 ), // #768 + INST(Smsw , X86M_NoMemSize , O(000F00,01,4,_,_,_,_,_ ), 0 , 98 , 0 , 187, 0 ), // #769 + INST(Sqrtpd , ExtRm , O(660F00,51,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #770 + INST(Sqrtps , ExtRm , O(000F00,51,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #771 + INST(Sqrtsd , ExtRm , O(F20F00,51,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 5 ), // #772 + INST(Sqrtss , ExtRm , O(F30F00,51,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #773 + INST(Stac , X86Op , O(000F01,CB,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 17 ), // #774 + INST(Stc , X86Op , O(000000,F9,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 18 ), // #775 + INST(Std , X86Op , O(000000,FD,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 19 ), // #776 + INST(Stgi , X86Op , O(000F01,DC,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 136), // #777 + INST(Sti , X86Op , O(000000,FB,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 24 ), // #778 + INST(Stmxcsr , X86M_Only , O(000F00,AE,3,_,_,_,_,_ ), 0 , 80 , 0 , 106, 6 ), // #779 + INST(Stos , X86StrMr , O(000000,AA,_,_,_,_,_,_ ), 0 , 0 , 0 , 188, 88 ), // #780 + INST(Str , X86M_NoMemSize , O(000F00,00,1,_,_,_,_,_ ), 0 , 32 , 0 , 187, 0 ), // #781 + INST(Sttilecfg , AmxCfg , V(660F38,49,_,0,0,_,_,_ ), 0 , 30 , 0 , 108, 86 ), // #782 + INST(Stui , X86Op , O(F30F01,EF,_,_,_,_,_,_ ), 0 , 27 , 0 , 34 , 26 ), // #783 + INST(Sub , X86Arith , O(000000,28,5,_,x,_,_,_ ), 0 , 64 , 0 , 183, 1 ), // #784 + INST(Subpd , ExtRm , O(660F00,5C,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #785 + INST(Subps , ExtRm , O(000F00,5C,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #786 + INST(Subsd , ExtRm , O(F20F00,5C,_,_,_,_,_,_ ), 0 , 6 , 0 , 7 , 5 ), // #787 + INST(Subss , ExtRm , O(F30F00,5C,_,_,_,_,_,_ ), 0 , 7 , 0 , 8 , 6 ), // #788 + INST(Swapgs , X86Op , O(000F01,F8,_,_,_,_,_,_ ), 0 , 23 , 0 , 34 , 0 ), // #789 + INST(Syscall , X86Op , O(000F00,05,_,_,_,_,_,_ ), 0 , 5 , 0 , 34 , 0 ), // #790 + INST(Sysenter , X86Op , O(000F00,34,_,_,_,_,_,_ ), 0 , 5 , 0 , 31 , 0 ), // #791 + INST(Sysexit , X86Op , O(000F00,35,_,_,_,_,_,_ ), 0 , 5 , 0 , 31 , 0 ), // #792 + INST(Sysexitq , X86Op , O(000F00,35,_,_,1,_,_,_ ), 0 , 62 , 0 , 34 , 0 ), // #793 + INST(Sysret , X86Op , O(000F00,07,_,_,_,_,_,_ ), 0 , 5 , 0 , 34 , 0 ), // #794 + INST(Sysretq , X86Op , O(000F00,07,_,_,1,_,_,_ ), 0 , 62 , 0 , 34 , 0 ), // #795 + INST(T1mskc , VexVm_Wx , V(XOP_M9,01,7,0,x,_,_,_ ), 0 , 99 , 0 , 15 , 12 ), // #796 + INST(Tcmmimfp16ps , AmxRmv , V(660F38,6C,_,0,0,_,_,_ ), 0 , 30 , 0 , 189, 137), // #797 + INST(Tcmmrlfp16ps , AmxRmv , V(000F38,6C,_,0,0,_,_,_ ), 0 , 11 , 0 , 189, 137), // #798 + INST(Tdcall , X86Op , O(660F01,CC,_,_,_,_,_,_ ), 0 , 97 , 0 , 31 , 133), // #799 + INST(Tdpbf16ps , AmxRmv , V(F30F38,5C,_,0,0,_,_,_ ), 0 , 89 , 0 , 189, 138), // #800 + INST(Tdpbssd , AmxRmv , V(F20F38,5E,_,0,0,_,_,_ ), 0 , 85 , 0 , 189, 139), // #801 + INST(Tdpbsud , AmxRmv , V(F30F38,5E,_,0,0,_,_,_ ), 0 , 89 , 0 , 189, 139), // #802 + INST(Tdpbusd , AmxRmv , V(660F38,5E,_,0,0,_,_,_ ), 0 , 30 , 0 , 189, 139), // #803 + INST(Tdpbuud , AmxRmv , V(000F38,5E,_,0,0,_,_,_ ), 0 , 11 , 0 , 189, 139), // #804 + INST(Tdpfp16ps , AmxRmv , V(F20F38,5C,_,0,0,_,_,_ ), 0 , 85 , 0 , 189, 140), // #805 + INST(Test , X86Test , O(000000,84,_,_,x,_,_,_ ), O(000000,F6,_,_,x,_,_,_ ), 0 , 79 , 190, 1 ), // #806 + INST(Testui , X86Op , O(F30F01,ED,_,_,_,_,_,_ ), 0 , 27 , 0 , 34 , 141), // #807 + INST(Tileloadd , AmxRm , V(F20F38,4B,_,0,0,_,_,_ ), 0 , 85 , 0 , 191, 86 ), // #808 + INST(Tileloaddt1 , AmxRm , V(660F38,4B,_,0,0,_,_,_ ), 0 , 30 , 0 , 191, 86 ), // #809 + INST(Tilerelease , VexOpMod , V(000F38,49,0,0,0,_,_,_ ), 0 , 11 , 0 , 192, 86 ), // #810 + INST(Tilestored , AmxMr , V(F30F38,4B,_,0,0,_,_,_ ), 0 , 89 , 0 , 193, 86 ), // #811 + INST(Tilezero , AmxR , V(F20F38,49,_,0,0,_,_,_ ), 0 , 85 , 0 , 194, 86 ), // #812 + INST(Tlbsync , X86Op , O(000F01,FF,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 68 ), // #813 + INST(Tpause , X86R32_EDX_EAX , O(660F00,AE,6,_,_,_,_,_ ), 0 , 28 , 0 , 195, 142), // #814 + INST(Tzcnt , X86Rm_Raw66H , O(F30F00,BC,_,_,x,_,_,_ ), 0 , 7 , 0 , 23 , 10 ), // #815 + INST(Tzmsk , VexVm_Wx , V(XOP_M9,01,4,0,x,_,_,_ ), 0 , 100, 0 , 15 , 12 ), // #816 + INST(Ucomisd , ExtRm , O(660F00,2E,_,_,_,_,_,_ ), 0 , 4 , 0 , 7 , 43 ), // #817 + INST(Ucomiss , ExtRm , O(000F00,2E,_,_,_,_,_,_ ), 0 , 5 , 0 , 8 , 44 ), // #818 + INST(Ud0 , X86Rm , O(000F00,FF,_,_,_,_,_,_ ), 0 , 5 , 0 , 196, 0 ), // #819 + INST(Ud1 , X86Rm , O(000F00,B9,_,_,_,_,_,_ ), 0 , 5 , 0 , 196, 0 ), // #820 + INST(Ud2 , X86Op , O(000F00,0B,_,_,_,_,_,_ ), 0 , 5 , 0 , 31 , 0 ), // #821 + INST(Uiret , X86Op , O(F30F01,EC,_,_,_,_,_,_ ), 0 , 27 , 0 , 34 , 26 ), // #822 + INST(Umonitor , X86R_FromM , O(F30F00,AE,6,_,_,_,_,_ ), 0 , 26 , 0 , 197, 143), // #823 + INST(Umwait , X86R32_EDX_EAX , O(F20F00,AE,6,_,_,_,_,_ ), 0 , 101, 0 , 195, 142), // #824 + INST(Unpckhpd , ExtRm , O(660F00,15,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #825 + INST(Unpckhps , ExtRm , O(000F00,15,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #826 + INST(Unpcklpd , ExtRm , O(660F00,14,_,_,_,_,_,_ ), 0 , 4 , 0 , 6 , 5 ), // #827 + INST(Unpcklps , ExtRm , O(000F00,14,_,_,_,_,_,_ ), 0 , 5 , 0 , 6 , 6 ), // #828 + INST(V4fmaddps , VexRm_T1_4X , E(F20F38,9A,_,2,_,0,4,T4X), 0 , 102, 0 , 198, 144), // #829 + INST(V4fmaddss , VexRm_T1_4X , E(F20F38,9B,_,0,_,0,4,T4X), 0 , 103, 0 , 199, 144), // #830 + INST(V4fnmaddps , VexRm_T1_4X , E(F20F38,AA,_,2,_,0,4,T4X), 0 , 102, 0 , 198, 144), // #831 + INST(V4fnmaddss , VexRm_T1_4X , E(F20F38,AB,_,0,_,0,4,T4X), 0 , 103, 0 , 199, 144), // #832 + INST(Vaddpd , VexRvm_Lx , V(660F00,58,_,x,I,1,4,FV ), 0 , 104, 0 , 200, 145), // #833 + INST(Vaddph , VexRvm_Lx , E(00MAP5,58,_,_,_,0,4,FV ), 0 , 105, 0 , 201, 146), // #834 + INST(Vaddps , VexRvm_Lx , V(000F00,58,_,x,I,0,4,FV ), 0 , 106, 0 , 202, 145), // #835 + INST(Vaddsd , VexRvm , V(F20F00,58,_,I,I,1,3,T1S), 0 , 107, 0 , 203, 147), // #836 + INST(Vaddsh , VexRvm , E(F3MAP5,58,_,_,_,0,1,T1S), 0 , 108, 0 , 204, 148), // #837 + INST(Vaddss , VexRvm , V(F30F00,58,_,I,I,0,2,T1S), 0 , 109, 0 , 205, 147), // #838 + INST(Vaddsubpd , VexRvm_Lx , V(660F00,D0,_,x,I,_,_,_ ), 0 , 71 , 0 , 206, 149), // #839 + INST(Vaddsubps , VexRvm_Lx , V(F20F00,D0,_,x,I,_,_,_ ), 0 , 110, 0 , 206, 149), // #840 + INST(Vaesdec , VexRvm_Lx , V(660F38,DE,_,x,I,_,4,FVM), 0 , 111, 0 , 207, 150), // #841 + INST(Vaesdeclast , VexRvm_Lx , V(660F38,DF,_,x,I,_,4,FVM), 0 , 111, 0 , 207, 150), // #842 + INST(Vaesenc , VexRvm_Lx , V(660F38,DC,_,x,I,_,4,FVM), 0 , 111, 0 , 207, 150), // #843 + INST(Vaesenclast , VexRvm_Lx , V(660F38,DD,_,x,I,_,4,FVM), 0 , 111, 0 , 207, 150), // #844 + INST(Vaesimc , VexRm , V(660F38,DB,_,0,I,_,_,_ ), 0 , 30 , 0 , 208, 151), // #845 + INST(Vaeskeygenassist , VexRmi , V(660F3A,DF,_,0,I,_,_,_ ), 0 , 75 , 0 , 209, 151), // #846 + INST(Valignd , VexRvmi_Lx , E(660F3A,03,_,x,_,0,4,FV ), 0 , 112, 0 , 210, 152), // #847 + INST(Valignq , VexRvmi_Lx , E(660F3A,03,_,x,_,1,4,FV ), 0 , 113, 0 , 211, 152), // #848 + INST(Vandnpd , VexRvm_Lx , V(660F00,55,_,x,I,1,4,FV ), 0 , 104, 0 , 212, 153), // #849 + INST(Vandnps , VexRvm_Lx , V(000F00,55,_,x,I,0,4,FV ), 0 , 106, 0 , 213, 153), // #850 + INST(Vandpd , VexRvm_Lx , V(660F00,54,_,x,I,1,4,FV ), 0 , 104, 0 , 214, 153), // #851 + INST(Vandps , VexRvm_Lx , V(000F00,54,_,x,I,0,4,FV ), 0 , 106, 0 , 215, 153), // #852 + INST(Vbcstnebf162ps , VexRm_Lx , V(F30F38,B1,_,x,0,_,_,_ ), 0 , 89 , 0 , 216, 154), // #853 + INST(Vbcstnesh2ps , VexRm_Lx , V(660F38,B1,_,x,0,_,_,_ ), 0 , 30 , 0 , 216, 154), // #854 + INST(Vblendmpd , VexRvm_Lx , E(660F38,65,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #855 + INST(Vblendmps , VexRvm_Lx , E(660F38,65,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 152), // #856 + INST(Vblendpd , VexRvmi_Lx , V(660F3A,0D,_,x,I,_,_,_ ), 0 , 75 , 0 , 219, 149), // #857 + INST(Vblendps , VexRvmi_Lx , V(660F3A,0C,_,x,I,_,_,_ ), 0 , 75 , 0 , 219, 149), // #858 + INST(Vblendvpd , VexRvmr_Lx , V(660F3A,4B,_,x,0,_,_,_ ), 0 , 75 , 0 , 220, 149), // #859 + INST(Vblendvps , VexRvmr_Lx , V(660F3A,4A,_,x,0,_,_,_ ), 0 , 75 , 0 , 220, 149), // #860 + INST(Vbroadcastf128 , VexRm , V(660F38,1A,_,1,0,_,_,_ ), 0 , 116, 0 , 221, 149), // #861 + INST(Vbroadcastf32x2 , VexRm_Lx , E(660F38,19,_,x,_,0,3,T2 ), 0 , 117, 0 , 222, 155), // #862 + INST(Vbroadcastf32x4 , VexRm_Lx , E(660F38,1A,_,x,_,0,4,T4 ), 0 , 118, 0 , 223, 78 ), // #863 + INST(Vbroadcastf32x8 , VexRm , E(660F38,1B,_,2,_,0,5,T8 ), 0 , 119, 0 , 224, 76 ), // #864 + INST(Vbroadcastf64x2 , VexRm_Lx , E(660F38,1A,_,x,_,1,4,T2 ), 0 , 120, 0 , 223, 155), // #865 + INST(Vbroadcastf64x4 , VexRm , E(660F38,1B,_,2,_,1,5,T4 ), 0 , 121, 0 , 224, 78 ), // #866 + INST(Vbroadcasti128 , VexRm , V(660F38,5A,_,1,0,_,_,_ ), 0 , 116, 0 , 221, 156), // #867 + INST(Vbroadcasti32x2 , VexRm_Lx , E(660F38,59,_,x,_,0,3,T2 ), 0 , 117, 0 , 225, 155), // #868 + INST(Vbroadcasti32x4 , VexRm_Lx , E(660F38,5A,_,x,_,0,4,T4 ), 0 , 118, 0 , 223, 152), // #869 + INST(Vbroadcasti32x8 , VexRm , E(660F38,5B,_,2,_,0,5,T8 ), 0 , 119, 0 , 224, 76 ), // #870 + INST(Vbroadcasti64x2 , VexRm_Lx , E(660F38,5A,_,x,_,1,4,T2 ), 0 , 120, 0 , 223, 155), // #871 + INST(Vbroadcasti64x4 , VexRm , E(660F38,5B,_,2,_,1,5,T4 ), 0 , 121, 0 , 224, 78 ), // #872 + INST(Vbroadcastsd , VexRm_Lx , V(660F38,19,_,x,0,1,3,T1S), 0 , 122, 0 , 226, 157), // #873 + INST(Vbroadcastss , VexRm_Lx , V(660F38,18,_,x,0,0,2,T1S), 0 , 123, 0 , 227, 157), // #874 + INST(Vcmppd , VexRvmi_Lx_KEvex , V(660F00,C2,_,x,I,1,4,FV ), 0 , 104, 0 , 228, 145), // #875 + INST(Vcmpph , VexRvmi_Lx_KEvex , E(000F3A,C2,_,_,_,0,4,FV ), 0 , 124, 0 , 229, 146), // #876 + INST(Vcmpps , VexRvmi_Lx_KEvex , V(000F00,C2,_,x,I,0,4,FV ), 0 , 106, 0 , 230, 145), // #877 + INST(Vcmpsd , VexRvmi_KEvex , V(F20F00,C2,_,I,I,1,3,T1S), 0 , 107, 0 , 231, 147), // #878 + INST(Vcmpsh , VexRvmi_KEvex , E(F30F3A,C2,_,_,_,0,1,T1S), 0 , 125, 0 , 232, 148), // #879 + INST(Vcmpss , VexRvmi_KEvex , V(F30F00,C2,_,I,I,0,2,T1S), 0 , 109, 0 , 233, 147), // #880 + INST(Vcomisd , VexRm , V(660F00,2F,_,I,I,1,3,T1S), 0 , 126, 0 , 234, 158), // #881 + INST(Vcomish , VexRm , E(00MAP5,2F,_,_,_,0,1,T1S), 0 , 127, 0 , 235, 159), // #882 + INST(Vcomiss , VexRm , V(000F00,2F,_,I,I,0,2,T1S), 0 , 128, 0 , 236, 158), // #883 + INST(Vcompresspd , VexMr_Lx , E(660F38,8A,_,x,_,1,3,T1S), 0 , 129, 0 , 237, 152), // #884 + INST(Vcompressps , VexMr_Lx , E(660F38,8A,_,x,_,0,2,T1S), 0 , 130, 0 , 237, 152), // #885 + INST(Vcvtdq2pd , VexRm_Lx , V(F30F00,E6,_,x,I,0,3,HV ), 0 , 131, 0 , 238, 145), // #886 + INST(Vcvtdq2ph , VexRm_Lx_Narrow , E(00MAP5,5B,_,x,0,0,4,FV ), 0 , 105, 0 , 239, 146), // #887 + INST(Vcvtdq2ps , VexRm_Lx , V(000F00,5B,_,x,I,0,4,FV ), 0 , 106, 0 , 240, 145), // #888 + INST(Vcvtne2ps2bf16 , VexRvm_Lx , E(F20F38,72,_,_,_,0,4,FV ), 0 , 132, 0 , 218, 160), // #889 + INST(Vcvtneebf162ps , VexRm_Lx , V(F30F38,B0,_,x,0,_,_,_ ), 0 , 89 , 0 , 241, 154), // #890 + INST(Vcvtneeph2ps , VexRm_Lx , V(660F38,B0,_,x,0,_,_,_ ), 0 , 30 , 0 , 241, 154), // #891 + INST(Vcvtneobf162ps , VexRm_Lx , V(F20F38,B0,_,x,0,_,_,_ ), 0 , 85 , 0 , 241, 154), // #892 + INST(Vcvtneoph2ps , VexRm_Lx , V(000F38,B0,_,x,0,_,_,_ ), 0 , 11 , 0 , 241, 154), // #893 + INST(Vcvtneps2bf16 , VexRm_Lx_Narrow , V(F30F38,72,_,_,_,0,4,FV ), 0 , 133, 0 , 242, 161), // #894 + INST(Vcvtpd2dq , VexRm_Lx_Narrow , V(F20F00,E6,_,x,I,1,4,FV ), 0 , 134, 0 , 243, 145), // #895 + INST(Vcvtpd2ph , VexRm_Lx , E(66MAP5,5A,_,_,_,1,4,FV ), 0 , 135, 0 , 244, 146), // #896 + INST(Vcvtpd2ps , VexRm_Lx_Narrow , V(660F00,5A,_,x,I,1,4,FV ), 0 , 104, 0 , 243, 145), // #897 + INST(Vcvtpd2qq , VexRm_Lx , E(660F00,7B,_,x,_,1,4,FV ), 0 , 136, 0 , 245, 155), // #898 + INST(Vcvtpd2udq , VexRm_Lx_Narrow , E(000F00,79,_,x,_,1,4,FV ), 0 , 137, 0 , 246, 152), // #899 + INST(Vcvtpd2uqq , VexRm_Lx , E(660F00,79,_,x,_,1,4,FV ), 0 , 136, 0 , 245, 155), // #900 + INST(Vcvtph2dq , VexRm_Lx , E(66MAP5,5B,_,_,_,0,3,HV ), 0 , 138, 0 , 247, 146), // #901 + INST(Vcvtph2pd , VexRm_Lx , E(00MAP5,5A,_,_,_,0,2,QV ), 0 , 139, 0 , 248, 146), // #902 + INST(Vcvtph2ps , VexRm_Lx , V(660F38,13,_,x,0,0,3,HVM), 0 , 140, 0 , 249, 162), // #903 + INST(Vcvtph2psx , VexRm_Lx , E(66MAP6,13,_,_,_,0,3,HV ), 0 , 141, 0 , 250, 146), // #904 + INST(Vcvtph2qq , VexRm_Lx , E(66MAP5,7B,_,_,_,0,2,QV ), 0 , 142, 0 , 251, 146), // #905 + INST(Vcvtph2udq , VexRm_Lx , E(00MAP5,79,_,_,_,0,3,HV ), 0 , 143, 0 , 247, 146), // #906 + INST(Vcvtph2uqq , VexRm_Lx , E(66MAP5,79,_,_,_,0,2,QV ), 0 , 142, 0 , 251, 146), // #907 + INST(Vcvtph2uw , VexRm_Lx , E(00MAP5,7D,_,_,_,0,4,FV ), 0 , 105, 0 , 252, 146), // #908 + INST(Vcvtph2w , VexRm_Lx , E(66MAP5,7D,_,_,_,0,4,FV ), 0 , 144, 0 , 252, 146), // #909 + INST(Vcvtps2dq , VexRm_Lx , V(660F00,5B,_,x,I,0,4,FV ), 0 , 145, 0 , 240, 145), // #910 + INST(Vcvtps2pd , VexRm_Lx , V(000F00,5A,_,x,I,0,3,HV ), 0 , 146, 0 , 253, 145), // #911 + INST(Vcvtps2ph , VexMri_Lx , V(660F3A,1D,_,x,0,0,3,HVM), 0 , 147, 0 , 254, 162), // #912 + INST(Vcvtps2phx , VexRm_Lx_Narrow , E(66MAP5,1D,_,_,_,0,4,FV ), 0 , 144, 0 , 239, 146), // #913 + INST(Vcvtps2qq , VexRm_Lx , E(660F00,7B,_,x,_,0,3,HV ), 0 , 148, 0 , 255, 155), // #914 + INST(Vcvtps2udq , VexRm_Lx , E(000F00,79,_,x,_,0,4,FV ), 0 , 149, 0 , 256, 152), // #915 + INST(Vcvtps2uqq , VexRm_Lx , E(660F00,79,_,x,_,0,3,HV ), 0 , 148, 0 , 255, 155), // #916 + INST(Vcvtqq2pd , VexRm_Lx , E(F30F00,E6,_,x,_,1,4,FV ), 0 , 150, 0 , 245, 155), // #917 + INST(Vcvtqq2ph , VexRm_Lx , E(00MAP5,5B,_,_,_,1,4,FV ), 0 , 151, 0 , 244, 146), // #918 + INST(Vcvtqq2ps , VexRm_Lx_Narrow , E(000F00,5B,_,x,_,1,4,FV ), 0 , 137, 0 , 246, 155), // #919 + INST(Vcvtsd2sh , VexRvm , E(F2MAP5,5A,_,_,_,1,3,T1S), 0 , 152, 0 , 257, 148), // #920 + INST(Vcvtsd2si , VexRm_Wx , V(F20F00,2D,_,I,x,x,3,T1F), 0 , 153, 0 , 258, 147), // #921 + INST(Vcvtsd2ss , VexRvm , V(F20F00,5A,_,I,I,1,3,T1S), 0 , 107, 0 , 203, 147), // #922 + INST(Vcvtsd2usi , VexRm_Wx , E(F20F00,79,_,I,_,x,3,T1F), 0 , 154, 0 , 259, 78 ), // #923 + INST(Vcvtsh2sd , VexRvm , E(F3MAP5,5A,_,_,_,0,1,T1S), 0 , 108, 0 , 260, 148), // #924 + INST(Vcvtsh2si , VexRm_Wx , E(F3MAP5,2D,_,_,_,x,1,T1S), 0 , 108, 0 , 261, 148), // #925 + INST(Vcvtsh2ss , VexRvm , E(00MAP6,13,_,_,_,0,1,T1S), 0 , 155, 0 , 260, 148), // #926 + INST(Vcvtsh2usi , VexRm_Wx , E(F3MAP5,79,_,_,_,x,1,T1S), 0 , 108, 0 , 261, 148), // #927 + INST(Vcvtsi2sd , VexRvm_Wx , V(F20F00,2A,_,I,x,x,2,T1W), 0 , 156, 0 , 262, 147), // #928 + INST(Vcvtsi2sh , VexRvm_Wx , E(F3MAP5,2A,_,_,_,x,2,T1W), 0 , 157, 0 , 263, 148), // #929 + INST(Vcvtsi2ss , VexRvm_Wx , V(F30F00,2A,_,I,x,x,2,T1W), 0 , 158, 0 , 262, 147), // #930 + INST(Vcvtss2sd , VexRvm , V(F30F00,5A,_,I,I,0,2,T1S), 0 , 109, 0 , 264, 147), // #931 + INST(Vcvtss2sh , VexRvm , E(00MAP5,1D,_,_,_,0,2,T1S), 0 , 159, 0 , 265, 148), // #932 + INST(Vcvtss2si , VexRm_Wx , V(F30F00,2D,_,I,x,x,2,T1F), 0 , 109, 0 , 266, 147), // #933 + INST(Vcvtss2usi , VexRm_Wx , E(F30F00,79,_,I,_,x,2,T1F), 0 , 160, 0 , 267, 78 ), // #934 + INST(Vcvttpd2dq , VexRm_Lx_Narrow , V(660F00,E6,_,x,I,1,4,FV ), 0 , 104, 0 , 268, 145), // #935 + INST(Vcvttpd2qq , VexRm_Lx , E(660F00,7A,_,x,_,1,4,FV ), 0 , 136, 0 , 269, 152), // #936 + INST(Vcvttpd2udq , VexRm_Lx_Narrow , E(000F00,78,_,x,_,1,4,FV ), 0 , 137, 0 , 270, 152), // #937 + INST(Vcvttpd2uqq , VexRm_Lx , E(660F00,78,_,x,_,1,4,FV ), 0 , 136, 0 , 269, 155), // #938 + INST(Vcvttph2dq , VexRm_Lx , E(F3MAP5,5B,_,_,_,0,3,HV ), 0 , 161, 0 , 250, 146), // #939 + INST(Vcvttph2qq , VexRm_Lx , E(66MAP5,7A,_,_,_,0,2,QV ), 0 , 142, 0 , 248, 146), // #940 + INST(Vcvttph2udq , VexRm_Lx , E(00MAP5,78,_,_,_,0,3,HV ), 0 , 143, 0 , 250, 146), // #941 + INST(Vcvttph2uqq , VexRm_Lx , E(66MAP5,78,_,_,_,0,2,QV ), 0 , 142, 0 , 248, 146), // #942 + INST(Vcvttph2uw , VexRm_Lx , E(00MAP5,7C,_,_,_,0,4,FV ), 0 , 105, 0 , 271, 146), // #943 + INST(Vcvttph2w , VexRm_Lx , E(66MAP5,7C,_,_,_,0,4,FV ), 0 , 144, 0 , 271, 146), // #944 + INST(Vcvttps2dq , VexRm_Lx , V(F30F00,5B,_,x,I,0,4,FV ), 0 , 162, 0 , 272, 145), // #945 + INST(Vcvttps2qq , VexRm_Lx , E(660F00,7A,_,x,_,0,3,HV ), 0 , 148, 0 , 273, 155), // #946 + INST(Vcvttps2udq , VexRm_Lx , E(000F00,78,_,x,_,0,4,FV ), 0 , 149, 0 , 274, 152), // #947 + INST(Vcvttps2uqq , VexRm_Lx , E(660F00,78,_,x,_,0,3,HV ), 0 , 148, 0 , 273, 155), // #948 + INST(Vcvttsd2si , VexRm_Wx , V(F20F00,2C,_,I,x,x,3,T1F), 0 , 153, 0 , 275, 147), // #949 + INST(Vcvttsd2usi , VexRm_Wx , E(F20F00,78,_,I,_,x,3,T1F), 0 , 154, 0 , 276, 78 ), // #950 + INST(Vcvttsh2si , VexRm_Wx , E(F3MAP5,2C,_,_,_,x,1,T1S), 0 , 108, 0 , 277, 148), // #951 + INST(Vcvttsh2usi , VexRm_Wx , E(F3MAP5,78,_,_,_,x,1,T1S), 0 , 108, 0 , 277, 148), // #952 + INST(Vcvttss2si , VexRm_Wx , V(F30F00,2C,_,I,x,x,2,T1F), 0 , 109, 0 , 278, 147), // #953 + INST(Vcvttss2usi , VexRm_Wx , E(F30F00,78,_,I,_,x,2,T1F), 0 , 160, 0 , 279, 78 ), // #954 + INST(Vcvtudq2pd , VexRm_Lx , E(F30F00,7A,_,x,_,0,3,HV ), 0 , 163, 0 , 280, 152), // #955 + INST(Vcvtudq2ph , VexRm_Lx_Narrow , E(F2MAP5,7A,_,_,_,0,4,FV ), 0 , 164, 0 , 239, 146), // #956 + INST(Vcvtudq2ps , VexRm_Lx , E(F20F00,7A,_,x,_,0,4,FV ), 0 , 165, 0 , 256, 152), // #957 + INST(Vcvtuqq2pd , VexRm_Lx , E(F30F00,7A,_,x,_,1,4,FV ), 0 , 150, 0 , 245, 155), // #958 + INST(Vcvtuqq2ph , VexRm_Lx , E(F2MAP5,7A,_,_,_,1,4,FV ), 0 , 166, 0 , 244, 146), // #959 + INST(Vcvtuqq2ps , VexRm_Lx_Narrow , E(F20F00,7A,_,x,_,1,4,FV ), 0 , 167, 0 , 246, 155), // #960 + INST(Vcvtusi2sd , VexRvm_Wx , E(F20F00,7B,_,I,_,x,2,T1W), 0 , 168, 0 , 281, 78 ), // #961 + INST(Vcvtusi2sh , VexRvm_Wx , E(F3MAP5,7B,_,_,_,x,2,T1W), 0 , 157, 0 , 263, 148), // #962 + INST(Vcvtusi2ss , VexRvm_Wx , E(F30F00,7B,_,I,_,x,2,T1W), 0 , 169, 0 , 281, 78 ), // #963 + INST(Vcvtuw2ph , VexRm_Lx , E(F2MAP5,7D,_,_,_,0,4,FV ), 0 , 164, 0 , 252, 146), // #964 + INST(Vcvtw2ph , VexRm_Lx , E(F3MAP5,7D,_,_,_,0,4,FV ), 0 , 170, 0 , 252, 146), // #965 + INST(Vdbpsadbw , VexRvmi_Lx , E(660F3A,42,_,x,_,0,4,FVM), 0 , 112, 0 , 282, 163), // #966 + INST(Vdivpd , VexRvm_Lx , V(660F00,5E,_,x,I,1,4,FV ), 0 , 104, 0 , 200, 145), // #967 + INST(Vdivph , VexRvm_Lx , E(00MAP5,5E,_,_,_,0,4,FV ), 0 , 105, 0 , 201, 146), // #968 + INST(Vdivps , VexRvm_Lx , V(000F00,5E,_,x,I,0,4,FV ), 0 , 106, 0 , 202, 145), // #969 + INST(Vdivsd , VexRvm , V(F20F00,5E,_,I,I,1,3,T1S), 0 , 107, 0 , 203, 147), // #970 + INST(Vdivsh , VexRvm , E(F3MAP5,5E,_,_,_,0,1,T1S), 0 , 108, 0 , 204, 148), // #971 + INST(Vdivss , VexRvm , V(F30F00,5E,_,I,I,0,2,T1S), 0 , 109, 0 , 205, 147), // #972 + INST(Vdpbf16ps , VexRvm_Lx , E(F30F38,52,_,_,_,0,4,FV ), 0 , 171, 0 , 218, 160), // #973 + INST(Vdppd , VexRvmi_Lx , V(660F3A,41,_,x,I,_,_,_ ), 0 , 75 , 0 , 283, 149), // #974 + INST(Vdpps , VexRvmi_Lx , V(660F3A,40,_,x,I,_,_,_ ), 0 , 75 , 0 , 219, 149), // #975 + INST(Verr , X86M_NoSize , O(000F00,00,4,_,_,_,_,_ ), 0 , 98 , 0 , 112, 11 ), // #976 + INST(Verw , X86M_NoSize , O(000F00,00,5,_,_,_,_,_ ), 0 , 79 , 0 , 112, 11 ), // #977 + INST(Vexp2pd , VexRm , E(660F38,C8,_,2,_,1,4,FV ), 0 , 172, 0 , 284, 164), // #978 + INST(Vexp2ps , VexRm , E(660F38,C8,_,2,_,0,4,FV ), 0 , 173, 0 , 285, 164), // #979 + INST(Vexpandpd , VexRm_Lx , E(660F38,88,_,x,_,1,3,T1S), 0 , 129, 0 , 286, 152), // #980 + INST(Vexpandps , VexRm_Lx , E(660F38,88,_,x,_,0,2,T1S), 0 , 130, 0 , 286, 152), // #981 + INST(Vextractf128 , VexMri , V(660F3A,19,_,1,0,_,_,_ ), 0 , 174, 0 , 287, 149), // #982 + INST(Vextractf32x4 , VexMri_Lx , E(660F3A,19,_,x,_,0,4,T4 ), 0 , 175, 0 , 288, 152), // #983 + INST(Vextractf32x8 , VexMri , E(660F3A,1B,_,2,_,0,5,T8 ), 0 , 176, 0 , 289, 76 ), // #984 + INST(Vextractf64x2 , VexMri_Lx , E(660F3A,19,_,x,_,1,4,T2 ), 0 , 177, 0 , 288, 155), // #985 + INST(Vextractf64x4 , VexMri , E(660F3A,1B,_,2,_,1,5,T4 ), 0 , 178, 0 , 289, 78 ), // #986 + INST(Vextracti128 , VexMri , V(660F3A,39,_,1,0,_,_,_ ), 0 , 174, 0 , 287, 156), // #987 + INST(Vextracti32x4 , VexMri_Lx , E(660F3A,39,_,x,_,0,4,T4 ), 0 , 175, 0 , 288, 152), // #988 + INST(Vextracti32x8 , VexMri , E(660F3A,3B,_,2,_,0,5,T8 ), 0 , 176, 0 , 289, 76 ), // #989 + INST(Vextracti64x2 , VexMri_Lx , E(660F3A,39,_,x,_,1,4,T2 ), 0 , 177, 0 , 288, 155), // #990 + INST(Vextracti64x4 , VexMri , E(660F3A,3B,_,2,_,1,5,T4 ), 0 , 178, 0 , 289, 78 ), // #991 + INST(Vextractps , VexMri , V(660F3A,17,_,0,I,I,2,T1S), 0 , 179, 0 , 290, 147), // #992 + INST(Vfcmaddcph , VexRvm_Lx , E(F2MAP6,56,_,_,_,0,4,FV ), 0 , 180, 0 , 291, 146), // #993 + INST(Vfcmaddcsh , VexRvm , E(F2MAP6,57,_,_,_,0,2,T1S), 0 , 181, 0 , 265, 148), // #994 + INST(Vfcmulcph , VexRvm_Lx , E(F2MAP6,D6,_,_,_,0,4,FV ), 0 , 180, 0 , 291, 146), // #995 + INST(Vfcmulcsh , VexRvm , E(F2MAP6,D7,_,_,_,0,2,T1S), 0 , 181, 0 , 265, 148), // #996 + INST(Vfixupimmpd , VexRvmi_Lx , E(660F3A,54,_,x,_,1,4,FV ), 0 , 113, 0 , 292, 152), // #997 + INST(Vfixupimmps , VexRvmi_Lx , E(660F3A,54,_,x,_,0,4,FV ), 0 , 112, 0 , 293, 152), // #998 + INST(Vfixupimmsd , VexRvmi , E(660F3A,55,_,I,_,1,3,T1S), 0 , 182, 0 , 294, 78 ), // #999 + INST(Vfixupimmss , VexRvmi , E(660F3A,55,_,I,_,0,2,T1S), 0 , 183, 0 , 295, 78 ), // #1000 + INST(Vfmadd132pd , VexRvm_Lx , V(660F38,98,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1001 + INST(Vfmadd132ph , VexRvm_Lx , E(66MAP6,98,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1002 + INST(Vfmadd132ps , VexRvm_Lx , V(660F38,98,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1003 + INST(Vfmadd132sd , VexRvm , V(660F38,99,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1004 + INST(Vfmadd132sh , VexRvm , E(66MAP6,99,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1005 + INST(Vfmadd132ss , VexRvm , V(660F38,99,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1006 + INST(Vfmadd213pd , VexRvm_Lx , V(660F38,A8,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1007 + INST(Vfmadd213ph , VexRvm_Lx , E(66MAP6,A8,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1008 + INST(Vfmadd213ps , VexRvm_Lx , V(660F38,A8,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1009 + INST(Vfmadd213sd , VexRvm , V(660F38,A9,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1010 + INST(Vfmadd213sh , VexRvm , E(66MAP6,A9,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1011 + INST(Vfmadd213ss , VexRvm , V(660F38,A9,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1012 + INST(Vfmadd231pd , VexRvm_Lx , V(660F38,B8,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1013 + INST(Vfmadd231ph , VexRvm_Lx , E(66MAP6,B8,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1014 + INST(Vfmadd231ps , VexRvm_Lx , V(660F38,B8,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1015 + INST(Vfmadd231sd , VexRvm , V(660F38,B9,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1016 + INST(Vfmadd231sh , VexRvm , E(66MAP6,B9,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1017 + INST(Vfmadd231ss , VexRvm , V(660F38,B9,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1018 + INST(Vfmaddcph , VexRvm_Lx , E(F3MAP6,56,_,_,_,0,4,FV ), 0 , 188, 0 , 291, 146), // #1019 + INST(Vfmaddcsh , VexRvm , E(F3MAP6,57,_,_,_,0,2,T1S), 0 , 189, 0 , 265, 148), // #1020 + INST(Vfmaddpd , Fma4_Lx , V(660F3A,69,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1021 + INST(Vfmaddps , Fma4_Lx , V(660F3A,68,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1022 + INST(Vfmaddsd , Fma4 , V(660F3A,6B,_,0,x,_,_,_ ), 0 , 75 , 0 , 297, 167), // #1023 + INST(Vfmaddss , Fma4 , V(660F3A,6A,_,0,x,_,_,_ ), 0 , 75 , 0 , 298, 167), // #1024 + INST(Vfmaddsub132pd , VexRvm_Lx , V(660F38,96,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1025 + INST(Vfmaddsub132ph , VexRvm_Lx , E(66MAP6,96,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1026 + INST(Vfmaddsub132ps , VexRvm_Lx , V(660F38,96,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1027 + INST(Vfmaddsub213pd , VexRvm_Lx , V(660F38,A6,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1028 + INST(Vfmaddsub213ph , VexRvm_Lx , E(66MAP6,A6,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1029 + INST(Vfmaddsub213ps , VexRvm_Lx , V(660F38,A6,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1030 + INST(Vfmaddsub231pd , VexRvm_Lx , V(660F38,B6,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1031 + INST(Vfmaddsub231ph , VexRvm_Lx , E(66MAP6,B6,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1032 + INST(Vfmaddsub231ps , VexRvm_Lx , V(660F38,B6,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1033 + INST(Vfmaddsubpd , Fma4_Lx , V(660F3A,5D,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1034 + INST(Vfmaddsubps , Fma4_Lx , V(660F3A,5C,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1035 + INST(Vfmsub132pd , VexRvm_Lx , V(660F38,9A,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1036 + INST(Vfmsub132ph , VexRvm_Lx , E(66MAP6,9A,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1037 + INST(Vfmsub132ps , VexRvm_Lx , V(660F38,9A,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1038 + INST(Vfmsub132sd , VexRvm , V(660F38,9B,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1039 + INST(Vfmsub132sh , VexRvm , E(66MAP6,9B,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1040 + INST(Vfmsub132ss , VexRvm , V(660F38,9B,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1041 + INST(Vfmsub213pd , VexRvm_Lx , V(660F38,AA,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1042 + INST(Vfmsub213ph , VexRvm_Lx , E(66MAP6,AA,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1043 + INST(Vfmsub213ps , VexRvm_Lx , V(660F38,AA,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1044 + INST(Vfmsub213sd , VexRvm , V(660F38,AB,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1045 + INST(Vfmsub213sh , VexRvm , E(66MAP6,AB,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1046 + INST(Vfmsub213ss , VexRvm , V(660F38,AB,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1047 + INST(Vfmsub231pd , VexRvm_Lx , V(660F38,BA,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1048 + INST(Vfmsub231ph , VexRvm_Lx , E(66MAP6,BA,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1049 + INST(Vfmsub231ps , VexRvm_Lx , V(660F38,BA,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1050 + INST(Vfmsub231sd , VexRvm , V(660F38,BB,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1051 + INST(Vfmsub231sh , VexRvm , E(66MAP6,BB,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1052 + INST(Vfmsub231ss , VexRvm , V(660F38,BB,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1053 + INST(Vfmsubadd132pd , VexRvm_Lx , V(660F38,97,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1054 + INST(Vfmsubadd132ph , VexRvm_Lx , E(66MAP6,97,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1055 + INST(Vfmsubadd132ps , VexRvm_Lx , V(660F38,97,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1056 + INST(Vfmsubadd213pd , VexRvm_Lx , V(660F38,A7,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1057 + INST(Vfmsubadd213ph , VexRvm_Lx , E(66MAP6,A7,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1058 + INST(Vfmsubadd213ps , VexRvm_Lx , V(660F38,A7,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1059 + INST(Vfmsubadd231pd , VexRvm_Lx , V(660F38,B7,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1060 + INST(Vfmsubadd231ph , VexRvm_Lx , E(66MAP6,B7,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1061 + INST(Vfmsubadd231ps , VexRvm_Lx , V(660F38,B7,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1062 + INST(Vfmsubaddpd , Fma4_Lx , V(660F3A,5F,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1063 + INST(Vfmsubaddps , Fma4_Lx , V(660F3A,5E,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1064 + INST(Vfmsubpd , Fma4_Lx , V(660F3A,6D,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1065 + INST(Vfmsubps , Fma4_Lx , V(660F3A,6C,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1066 + INST(Vfmsubsd , Fma4 , V(660F3A,6F,_,0,x,_,_,_ ), 0 , 75 , 0 , 297, 167), // #1067 + INST(Vfmsubss , Fma4 , V(660F3A,6E,_,0,x,_,_,_ ), 0 , 75 , 0 , 298, 167), // #1068 + INST(Vfmulcph , VexRvm_Lx , E(F3MAP6,D6,_,_,_,0,4,FV ), 0 , 188, 0 , 291, 146), // #1069 + INST(Vfmulcsh , VexRvm , E(F3MAP6,D7,_,_,_,0,2,T1S), 0 , 189, 0 , 265, 146), // #1070 + INST(Vfnmadd132pd , VexRvm_Lx , V(660F38,9C,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1071 + INST(Vfnmadd132ph , VexRvm_Lx , E(66MAP6,9C,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1072 + INST(Vfnmadd132ps , VexRvm_Lx , V(660F38,9C,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1073 + INST(Vfnmadd132sd , VexRvm , V(660F38,9D,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1074 + INST(Vfnmadd132sh , VexRvm , E(66MAP6,9D,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1075 + INST(Vfnmadd132ss , VexRvm , V(660F38,9D,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1076 + INST(Vfnmadd213pd , VexRvm_Lx , V(660F38,AC,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1077 + INST(Vfnmadd213ph , VexRvm_Lx , E(66MAP6,AC,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1078 + INST(Vfnmadd213ps , VexRvm_Lx , V(660F38,AC,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1079 + INST(Vfnmadd213sd , VexRvm , V(660F38,AD,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1080 + INST(Vfnmadd213sh , VexRvm , E(66MAP6,AD,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1081 + INST(Vfnmadd213ss , VexRvm , V(660F38,AD,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1082 + INST(Vfnmadd231pd , VexRvm_Lx , V(660F38,BC,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1083 + INST(Vfnmadd231ph , VexRvm_Lx , E(66MAP6,BC,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1084 + INST(Vfnmadd231ps , VexRvm_Lx , V(660F38,BC,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1085 + INST(Vfnmadd231sd , VexRvm , V(660F38,BD,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1086 + INST(Vfnmadd231sh , VexRvm , E(66MAP6,BD,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1087 + INST(Vfnmadd231ss , VexRvm , V(660F38,BD,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1088 + INST(Vfnmaddpd , Fma4_Lx , V(660F3A,79,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1089 + INST(Vfnmaddps , Fma4_Lx , V(660F3A,78,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1090 + INST(Vfnmaddsd , Fma4 , V(660F3A,7B,_,0,x,_,_,_ ), 0 , 75 , 0 , 297, 167), // #1091 + INST(Vfnmaddss , Fma4 , V(660F3A,7A,_,0,x,_,_,_ ), 0 , 75 , 0 , 298, 167), // #1092 + INST(Vfnmsub132pd , VexRvm_Lx , V(660F38,9E,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1093 + INST(Vfnmsub132ph , VexRvm_Lx , E(66MAP6,9E,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1094 + INST(Vfnmsub132ps , VexRvm_Lx , V(660F38,9E,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1095 + INST(Vfnmsub132sd , VexRvm , V(660F38,9F,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1096 + INST(Vfnmsub132sh , VexRvm , E(66MAP6,9F,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1097 + INST(Vfnmsub132ss , VexRvm , V(660F38,9F,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1098 + INST(Vfnmsub213pd , VexRvm_Lx , V(660F38,AE,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1099 + INST(Vfnmsub213ph , VexRvm_Lx , E(66MAP6,AE,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1100 + INST(Vfnmsub213ps , VexRvm_Lx , V(660F38,AE,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1101 + INST(Vfnmsub213sd , VexRvm , V(660F38,AF,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1102 + INST(Vfnmsub213sh , VexRvm , E(66MAP6,AF,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1103 + INST(Vfnmsub213ss , VexRvm , V(660F38,AF,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1104 + INST(Vfnmsub231pd , VexRvm_Lx , V(660F38,BE,_,x,1,1,4,FV ), 0 , 184, 0 , 200, 165), // #1105 + INST(Vfnmsub231ph , VexRvm_Lx , E(66MAP6,BE,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1106 + INST(Vfnmsub231ps , VexRvm_Lx , V(660F38,BE,_,x,0,0,4,FV ), 0 , 111, 0 , 202, 165), // #1107 + INST(Vfnmsub231sd , VexRvm , V(660F38,BF,_,I,1,1,3,T1S), 0 , 186, 0 , 203, 166), // #1108 + INST(Vfnmsub231sh , VexRvm , E(66MAP6,BF,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1109 + INST(Vfnmsub231ss , VexRvm , V(660F38,BF,_,I,0,0,2,T1S), 0 , 123, 0 , 205, 166), // #1110 + INST(Vfnmsubpd , Fma4_Lx , V(660F3A,7D,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1111 + INST(Vfnmsubps , Fma4_Lx , V(660F3A,7C,_,x,x,_,_,_ ), 0 , 75 , 0 , 296, 167), // #1112 + INST(Vfnmsubsd , Fma4 , V(660F3A,7F,_,0,x,_,_,_ ), 0 , 75 , 0 , 297, 167), // #1113 + INST(Vfnmsubss , Fma4 , V(660F3A,7E,_,0,x,_,_,_ ), 0 , 75 , 0 , 298, 167), // #1114 + INST(Vfpclasspd , VexRmi_Lx , E(660F3A,66,_,x,_,1,4,FV ), 0 , 113, 0 , 299, 155), // #1115 + INST(Vfpclassph , VexRmi_Lx , E(000F3A,66,_,_,_,0,4,FV ), 0 , 124, 0 , 300, 146), // #1116 + INST(Vfpclassps , VexRmi_Lx , E(660F3A,66,_,x,_,0,4,FV ), 0 , 112, 0 , 301, 155), // #1117 + INST(Vfpclasssd , VexRmi , E(660F3A,67,_,I,_,1,3,T1S), 0 , 182, 0 , 302, 76 ), // #1118 + INST(Vfpclasssh , VexRmi , E(000F3A,67,_,_,_,0,1,T1S), 0 , 190, 0 , 303, 148), // #1119 + INST(Vfpclassss , VexRmi , E(660F3A,67,_,I,_,0,2,T1S), 0 , 183, 0 , 304, 76 ), // #1120 + INST(Vfrczpd , VexRm_Lx , V(XOP_M9,81,_,x,0,_,_,_ ), 0 , 81 , 0 , 305, 168), // #1121 + INST(Vfrczps , VexRm_Lx , V(XOP_M9,80,_,x,0,_,_,_ ), 0 , 81 , 0 , 305, 168), // #1122 + INST(Vfrczsd , VexRm , V(XOP_M9,83,_,0,0,_,_,_ ), 0 , 81 , 0 , 306, 168), // #1123 + INST(Vfrczss , VexRm , V(XOP_M9,82,_,0,0,_,_,_ ), 0 , 81 , 0 , 307, 168), // #1124 + INST(Vgatherdpd , VexRmvRm_VM , V(660F38,92,_,x,1,_,_,_ ), E(660F38,92,_,x,_,1,3,T1S), 191, 80 , 308, 169), // #1125 + INST(Vgatherdps , VexRmvRm_VM , V(660F38,92,_,x,0,_,_,_ ), E(660F38,92,_,x,_,0,2,T1S), 30 , 81 , 309, 169), // #1126 + INST(Vgatherpf0dpd , VexM_VM , E(660F38,C6,1,2,_,1,3,T1S), 0 , 192, 0 , 310, 170), // #1127 + INST(Vgatherpf0dps , VexM_VM , E(660F38,C6,1,2,_,0,2,T1S), 0 , 193, 0 , 311, 170), // #1128 + INST(Vgatherpf0qpd , VexM_VM , E(660F38,C7,1,2,_,1,3,T1S), 0 , 192, 0 , 312, 170), // #1129 + INST(Vgatherpf0qps , VexM_VM , E(660F38,C7,1,2,_,0,2,T1S), 0 , 193, 0 , 312, 170), // #1130 + INST(Vgatherpf1dpd , VexM_VM , E(660F38,C6,2,2,_,1,3,T1S), 0 , 194, 0 , 310, 170), // #1131 + INST(Vgatherpf1dps , VexM_VM , E(660F38,C6,2,2,_,0,2,T1S), 0 , 195, 0 , 311, 170), // #1132 + INST(Vgatherpf1qpd , VexM_VM , E(660F38,C7,2,2,_,1,3,T1S), 0 , 194, 0 , 312, 170), // #1133 + INST(Vgatherpf1qps , VexM_VM , E(660F38,C7,2,2,_,0,2,T1S), 0 , 195, 0 , 312, 170), // #1134 + INST(Vgatherqpd , VexRmvRm_VM , V(660F38,93,_,x,1,_,_,_ ), E(660F38,93,_,x,_,1,3,T1S), 191, 82 , 313, 169), // #1135 + INST(Vgatherqps , VexRmvRm_VM , V(660F38,93,_,x,0,_,_,_ ), E(660F38,93,_,x,_,0,2,T1S), 30 , 83 , 314, 169), // #1136 + INST(Vgetexppd , VexRm_Lx , E(660F38,42,_,x,_,1,4,FV ), 0 , 114, 0 , 269, 152), // #1137 + INST(Vgetexpph , VexRm_Lx , E(66MAP6,42,_,_,_,0,4,FV ), 0 , 185, 0 , 271, 146), // #1138 + INST(Vgetexpps , VexRm_Lx , E(660F38,42,_,x,_,0,4,FV ), 0 , 115, 0 , 274, 152), // #1139 + INST(Vgetexpsd , VexRvm , E(660F38,43,_,I,_,1,3,T1S), 0 , 129, 0 , 315, 78 ), // #1140 + INST(Vgetexpsh , VexRvm , E(66MAP6,43,_,_,_,0,1,T1S), 0 , 187, 0 , 260, 148), // #1141 + INST(Vgetexpss , VexRvm , E(660F38,43,_,I,_,0,2,T1S), 0 , 130, 0 , 316, 78 ), // #1142 + INST(Vgetmantpd , VexRmi_Lx , E(660F3A,26,_,x,_,1,4,FV ), 0 , 113, 0 , 317, 152), // #1143 + INST(Vgetmantph , VexRmi_Lx , E(000F3A,26,_,_,_,0,4,FV ), 0 , 124, 0 , 318, 146), // #1144 + INST(Vgetmantps , VexRmi_Lx , E(660F3A,26,_,x,_,0,4,FV ), 0 , 112, 0 , 319, 152), // #1145 + INST(Vgetmantsd , VexRvmi , E(660F3A,27,_,I,_,1,3,T1S), 0 , 182, 0 , 294, 78 ), // #1146 + INST(Vgetmantsh , VexRvmi , E(000F3A,27,_,_,_,0,1,T1S), 0 , 190, 0 , 320, 148), // #1147 + INST(Vgetmantss , VexRvmi , E(660F3A,27,_,I,_,0,2,T1S), 0 , 183, 0 , 295, 78 ), // #1148 + INST(Vgf2p8affineinvqb, VexRvmi_Lx , V(660F3A,CF,_,x,1,1,4,FV ), 0 , 196, 0 , 321, 171), // #1149 + INST(Vgf2p8affineqb , VexRvmi_Lx , V(660F3A,CE,_,x,1,1,4,FV ), 0 , 196, 0 , 321, 171), // #1150 + INST(Vgf2p8mulb , VexRvm_Lx , V(660F38,CF,_,x,0,0,4,FV ), 0 , 111, 0 , 322, 171), // #1151 + INST(Vhaddpd , VexRvm_Lx , V(660F00,7C,_,x,I,_,_,_ ), 0 , 71 , 0 , 206, 149), // #1152 + INST(Vhaddps , VexRvm_Lx , V(F20F00,7C,_,x,I,_,_,_ ), 0 , 110, 0 , 206, 149), // #1153 + INST(Vhsubpd , VexRvm_Lx , V(660F00,7D,_,x,I,_,_,_ ), 0 , 71 , 0 , 206, 149), // #1154 + INST(Vhsubps , VexRvm_Lx , V(F20F00,7D,_,x,I,_,_,_ ), 0 , 110, 0 , 206, 149), // #1155 + INST(Vinsertf128 , VexRvmi , V(660F3A,18,_,1,0,_,_,_ ), 0 , 174, 0 , 323, 149), // #1156 + INST(Vinsertf32x4 , VexRvmi_Lx , E(660F3A,18,_,x,_,0,4,T4 ), 0 , 175, 0 , 324, 152), // #1157 + INST(Vinsertf32x8 , VexRvmi , E(660F3A,1A,_,2,_,0,5,T8 ), 0 , 176, 0 , 325, 76 ), // #1158 + INST(Vinsertf64x2 , VexRvmi_Lx , E(660F3A,18,_,x,_,1,4,T2 ), 0 , 177, 0 , 324, 155), // #1159 + INST(Vinsertf64x4 , VexRvmi , E(660F3A,1A,_,2,_,1,5,T4 ), 0 , 178, 0 , 325, 78 ), // #1160 + INST(Vinserti128 , VexRvmi , V(660F3A,38,_,1,0,_,_,_ ), 0 , 174, 0 , 323, 156), // #1161 + INST(Vinserti32x4 , VexRvmi_Lx , E(660F3A,38,_,x,_,0,4,T4 ), 0 , 175, 0 , 324, 152), // #1162 + INST(Vinserti32x8 , VexRvmi , E(660F3A,3A,_,2,_,0,5,T8 ), 0 , 176, 0 , 325, 76 ), // #1163 + INST(Vinserti64x2 , VexRvmi_Lx , E(660F3A,38,_,x,_,1,4,T2 ), 0 , 177, 0 , 324, 155), // #1164 + INST(Vinserti64x4 , VexRvmi , E(660F3A,3A,_,2,_,1,5,T4 ), 0 , 178, 0 , 325, 78 ), // #1165 + INST(Vinsertps , VexRvmi , V(660F3A,21,_,0,I,0,2,T1S), 0 , 179, 0 , 326, 147), // #1166 + INST(Vlddqu , VexRm_Lx , V(F20F00,F0,_,x,I,_,_,_ ), 0 , 110, 0 , 241, 149), // #1167 + INST(Vldmxcsr , VexM , V(000F00,AE,2,0,I,_,_,_ ), 0 , 197, 0 , 327, 149), // #1168 + INST(Vmaskmovdqu , VexRm_ZDI , V(660F00,F7,_,0,I,_,_,_ ), 0 , 71 , 0 , 328, 149), // #1169 + INST(Vmaskmovpd , VexRvmMvr_Lx , V(660F38,2D,_,x,0,_,_,_ ), V(660F38,2F,_,x,0,_,_,_ ), 30 , 84 , 329, 149), // #1170 + INST(Vmaskmovps , VexRvmMvr_Lx , V(660F38,2C,_,x,0,_,_,_ ), V(660F38,2E,_,x,0,_,_,_ ), 30 , 85 , 329, 149), // #1171 + INST(Vmaxpd , VexRvm_Lx , V(660F00,5F,_,x,I,1,4,FV ), 0 , 104, 0 , 330, 145), // #1172 + INST(Vmaxph , VexRvm_Lx , E(00MAP5,5F,_,_,_,0,4,FV ), 0 , 105, 0 , 331, 146), // #1173 + INST(Vmaxps , VexRvm_Lx , V(000F00,5F,_,x,I,0,4,FV ), 0 , 106, 0 , 332, 145), // #1174 + INST(Vmaxsd , VexRvm , V(F20F00,5F,_,I,I,1,3,T1S), 0 , 107, 0 , 333, 147), // #1175 + INST(Vmaxsh , VexRvm , E(F3MAP5,5F,_,_,_,0,1,T1S), 0 , 108, 0 , 260, 148), // #1176 + INST(Vmaxss , VexRvm , V(F30F00,5F,_,I,I,0,2,T1S), 0 , 109, 0 , 264, 147), // #1177 + INST(Vmcall , X86Op , O(000F01,C1,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 67 ), // #1178 + INST(Vmclear , X86M_Only , O(660F00,C7,6,_,_,_,_,_ ), 0 , 28 , 0 , 33 , 67 ), // #1179 + INST(Vmfunc , X86Op , O(000F01,D4,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 67 ), // #1180 + INST(Vmgexit , X86Op , O(F20F01,D9,_,_,_,_,_,_ ), 0 , 93 , 0 , 31 , 172), // #1181 + INST(Vminpd , VexRvm_Lx , V(660F00,5D,_,x,I,1,4,FV ), 0 , 104, 0 , 330, 145), // #1182 + INST(Vminph , VexRvm_Lx , E(00MAP5,5D,_,_,_,0,4,FV ), 0 , 105, 0 , 331, 146), // #1183 + INST(Vminps , VexRvm_Lx , V(000F00,5D,_,x,I,0,4,FV ), 0 , 106, 0 , 332, 145), // #1184 + INST(Vminsd , VexRvm , V(F20F00,5D,_,I,I,1,3,T1S), 0 , 107, 0 , 333, 147), // #1185 + INST(Vminsh , VexRvm , E(F3MAP5,5D,_,_,_,0,1,T1S), 0 , 108, 0 , 260, 148), // #1186 + INST(Vminss , VexRvm , V(F30F00,5D,_,I,I,0,2,T1S), 0 , 109, 0 , 264, 147), // #1187 + INST(Vmlaunch , X86Op , O(000F01,C2,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 67 ), // #1188 + INST(Vmload , X86Op_xAX , O(000F01,DA,_,_,_,_,_,_ ), 0 , 23 , 0 , 334, 23 ), // #1189 + INST(Vmmcall , X86Op , O(000F01,D9,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 23 ), // #1190 + INST(Vmovapd , VexRmMr_Lx , V(660F00,28,_,x,I,1,4,FVM), V(660F00,29,_,x,I,1,4,FVM), 104, 86 , 335, 173), // #1191 + INST(Vmovaps , VexRmMr_Lx , V(000F00,28,_,x,I,0,4,FVM), V(000F00,29,_,x,I,0,4,FVM), 106, 87 , 335, 173), // #1192 + INST(Vmovd , VexMovdMovq , V(660F00,6E,_,0,0,0,2,T1S), V(660F00,7E,_,0,0,0,2,T1S), 198, 88 , 336, 147), // #1193 + INST(Vmovddup , VexRm_Lx , V(F20F00,12,_,x,I,1,3,DUP), 0 , 199, 0 , 337, 145), // #1194 + INST(Vmovdqa , VexRmMr_Lx , V(660F00,6F,_,x,I,_,_,_ ), V(660F00,7F,_,x,I,_,_,_ ), 71 , 89 , 338, 174), // #1195 + INST(Vmovdqa32 , VexRmMr_Lx , E(660F00,6F,_,x,_,0,4,FVM), E(660F00,7F,_,x,_,0,4,FVM), 200, 90 , 339, 175), // #1196 + INST(Vmovdqa64 , VexRmMr_Lx , E(660F00,6F,_,x,_,1,4,FVM), E(660F00,7F,_,x,_,1,4,FVM), 136, 91 , 339, 175), // #1197 + INST(Vmovdqu , VexRmMr_Lx , V(F30F00,6F,_,x,I,_,_,_ ), V(F30F00,7F,_,x,I,_,_,_ ), 201, 92 , 338, 174), // #1198 + INST(Vmovdqu16 , VexRmMr_Lx , E(F20F00,6F,_,x,_,1,4,FVM), E(F20F00,7F,_,x,_,1,4,FVM), 167, 93 , 339, 176), // #1199 + INST(Vmovdqu32 , VexRmMr_Lx , E(F30F00,6F,_,x,_,0,4,FVM), E(F30F00,7F,_,x,_,0,4,FVM), 202, 94 , 339, 175), // #1200 + INST(Vmovdqu64 , VexRmMr_Lx , E(F30F00,6F,_,x,_,1,4,FVM), E(F30F00,7F,_,x,_,1,4,FVM), 150, 95 , 339, 175), // #1201 + INST(Vmovdqu8 , VexRmMr_Lx , E(F20F00,6F,_,x,_,0,4,FVM), E(F20F00,7F,_,x,_,0,4,FVM), 165, 96 , 339, 176), // #1202 + INST(Vmovhlps , VexRvm , V(000F00,12,_,0,I,0,_,_ ), 0 , 74 , 0 , 340, 147), // #1203 + INST(Vmovhpd , VexRvmMr , V(660F00,16,_,0,I,1,3,T1S), V(660F00,17,_,0,I,1,3,T1S), 126, 97 , 341, 147), // #1204 + INST(Vmovhps , VexRvmMr , V(000F00,16,_,0,I,0,3,T2 ), V(000F00,17,_,0,I,0,3,T2 ), 203, 98 , 341, 147), // #1205 + INST(Vmovlhps , VexRvm , V(000F00,16,_,0,I,0,_,_ ), 0 , 74 , 0 , 340, 147), // #1206 + INST(Vmovlpd , VexRvmMr , V(660F00,12,_,0,I,1,3,T1S), V(660F00,13,_,0,I,1,3,T1S), 126, 99 , 341, 147), // #1207 + INST(Vmovlps , VexRvmMr , V(000F00,12,_,0,I,0,3,T2 ), V(000F00,13,_,0,I,0,3,T2 ), 203, 100, 341, 147), // #1208 + INST(Vmovmskpd , VexRm_Lx , V(660F00,50,_,x,I,_,_,_ ), 0 , 71 , 0 , 342, 149), // #1209 + INST(Vmovmskps , VexRm_Lx , V(000F00,50,_,x,I,_,_,_ ), 0 , 74 , 0 , 342, 149), // #1210 + INST(Vmovntdq , VexMr_Lx , V(660F00,E7,_,x,I,0,4,FVM), 0 , 145, 0 , 343, 145), // #1211 + INST(Vmovntdqa , VexRm_Lx , V(660F38,2A,_,x,I,0,4,FVM), 0 , 111, 0 , 344, 157), // #1212 + INST(Vmovntpd , VexMr_Lx , V(660F00,2B,_,x,I,1,4,FVM), 0 , 104, 0 , 343, 145), // #1213 + INST(Vmovntps , VexMr_Lx , V(000F00,2B,_,x,I,0,4,FVM), 0 , 106, 0 , 343, 145), // #1214 + INST(Vmovq , VexMovdMovq , V(660F00,6E,_,0,I,1,3,T1S), V(660F00,7E,_,0,I,1,3,T1S), 126, 101, 345, 177), // #1215 + INST(Vmovsd , VexMovssMovsd , V(F20F00,10,_,I,I,1,3,T1S), V(F20F00,11,_,I,I,1,3,T1S), 107, 102, 346, 177), // #1216 + INST(Vmovsh , VexMovssMovsd , E(F3MAP5,10,_,I,_,0,1,T1S), E(F3MAP5,11,_,I,_,0,1,T1S), 108, 103, 347, 148), // #1217 + INST(Vmovshdup , VexRm_Lx , V(F30F00,16,_,x,I,0,4,FVM), 0 , 162, 0 , 348, 145), // #1218 + INST(Vmovsldup , VexRm_Lx , V(F30F00,12,_,x,I,0,4,FVM), 0 , 162, 0 , 348, 145), // #1219 + INST(Vmovss , VexMovssMovsd , V(F30F00,10,_,I,I,0,2,T1S), V(F30F00,11,_,I,I,0,2,T1S), 109, 104, 349, 177), // #1220 + INST(Vmovupd , VexRmMr_Lx , V(660F00,10,_,x,I,1,4,FVM), V(660F00,11,_,x,I,1,4,FVM), 104, 105, 335, 173), // #1221 + INST(Vmovups , VexRmMr_Lx , V(000F00,10,_,x,I,0,4,FVM), V(000F00,11,_,x,I,0,4,FVM), 106, 106, 335, 173), // #1222 + INST(Vmovw , VexMovdMovq , E(66MAP5,6E,_,0,_,I,1,T1S), E(66MAP5,7E,_,0,_,I,1,T1S), 204, 107, 350, 148), // #1223 + INST(Vmpsadbw , VexRvmi_Lx , V(660F3A,42,_,x,I,_,_,_ ), 0 , 75 , 0 , 219, 178), // #1224 + INST(Vmptrld , X86M_Only , O(000F00,C7,6,_,_,_,_,_ ), 0 , 82 , 0 , 33 , 67 ), // #1225 + INST(Vmptrst , X86M_Only , O(000F00,C7,7,_,_,_,_,_ ), 0 , 24 , 0 , 33 , 67 ), // #1226 + INST(Vmread , X86Mr_NoSize , O(000F00,78,_,_,_,_,_,_ ), 0 , 5 , 0 , 351, 67 ), // #1227 + INST(Vmresume , X86Op , O(000F01,C3,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 67 ), // #1228 + INST(Vmrun , X86Op_xAX , O(000F01,D8,_,_,_,_,_,_ ), 0 , 23 , 0 , 334, 23 ), // #1229 + INST(Vmsave , X86Op_xAX , O(000F01,DB,_,_,_,_,_,_ ), 0 , 23 , 0 , 334, 23 ), // #1230 + INST(Vmulpd , VexRvm_Lx , V(660F00,59,_,x,I,1,4,FV ), 0 , 104, 0 , 200, 145), // #1231 + INST(Vmulph , VexRvm_Lx , E(00MAP5,59,_,_,_,0,4,FV ), 0 , 105, 0 , 201, 146), // #1232 + INST(Vmulps , VexRvm_Lx , V(000F00,59,_,x,I,0,4,FV ), 0 , 106, 0 , 202, 145), // #1233 + INST(Vmulsd , VexRvm , V(F20F00,59,_,I,I,1,3,T1S), 0 , 107, 0 , 203, 147), // #1234 + INST(Vmulsh , VexRvm , E(F3MAP5,59,_,_,_,0,1,T1S), 0 , 108, 0 , 204, 148), // #1235 + INST(Vmulss , VexRvm , V(F30F00,59,_,I,I,0,2,T1S), 0 , 109, 0 , 205, 147), // #1236 + INST(Vmwrite , X86Rm_NoSize , O(000F00,79,_,_,_,_,_,_ ), 0 , 5 , 0 , 352, 67 ), // #1237 + INST(Vmxoff , X86Op , O(000F01,C4,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 67 ), // #1238 + INST(Vmxon , X86M_Only , O(F30F00,C7,6,_,_,_,_,_ ), 0 , 26 , 0 , 33 , 67 ), // #1239 + INST(Vorpd , VexRvm_Lx , V(660F00,56,_,x,I,1,4,FV ), 0 , 104, 0 , 214, 153), // #1240 + INST(Vorps , VexRvm_Lx , V(000F00,56,_,x,I,0,4,FV ), 0 , 106, 0 , 215, 153), // #1241 + INST(Vp2intersectd , VexRvm_Lx_2xK , E(F20F38,68,_,_,_,0,4,FV ), 0 , 132, 0 , 353, 179), // #1242 + INST(Vp2intersectq , VexRvm_Lx_2xK , E(F20F38,68,_,_,_,1,4,FV ), 0 , 205, 0 , 354, 179), // #1243 + INST(Vp4dpwssd , VexRm_T1_4X , E(F20F38,52,_,2,_,0,4,T4X), 0 , 102, 0 , 198, 180), // #1244 + INST(Vp4dpwssds , VexRm_T1_4X , E(F20F38,53,_,2,_,0,4,T4X), 0 , 102, 0 , 198, 180), // #1245 + INST(Vpabsb , VexRm_Lx , V(660F38,1C,_,x,I,_,4,FVM), 0 , 111, 0 , 348, 181), // #1246 + INST(Vpabsd , VexRm_Lx , V(660F38,1E,_,x,I,0,4,FV ), 0 , 111, 0 , 355, 157), // #1247 + INST(Vpabsq , VexRm_Lx , E(660F38,1F,_,x,_,1,4,FV ), 0 , 114, 0 , 356, 152), // #1248 + INST(Vpabsw , VexRm_Lx , V(660F38,1D,_,x,I,_,4,FVM), 0 , 111, 0 , 348, 181), // #1249 + INST(Vpackssdw , VexRvm_Lx , V(660F00,6B,_,x,I,0,4,FV ), 0 , 145, 0 , 213, 181), // #1250 + INST(Vpacksswb , VexRvm_Lx , V(660F00,63,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1251 + INST(Vpackusdw , VexRvm_Lx , V(660F38,2B,_,x,I,0,4,FV ), 0 , 111, 0 , 213, 181), // #1252 + INST(Vpackuswb , VexRvm_Lx , V(660F00,67,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1253 + INST(Vpaddb , VexRvm_Lx , V(660F00,FC,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1254 + INST(Vpaddd , VexRvm_Lx , V(660F00,FE,_,x,I,0,4,FV ), 0 , 145, 0 , 213, 157), // #1255 + INST(Vpaddq , VexRvm_Lx , V(660F00,D4,_,x,I,1,4,FV ), 0 , 104, 0 , 212, 157), // #1256 + INST(Vpaddsb , VexRvm_Lx , V(660F00,EC,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1257 + INST(Vpaddsw , VexRvm_Lx , V(660F00,ED,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1258 + INST(Vpaddusb , VexRvm_Lx , V(660F00,DC,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1259 + INST(Vpaddusw , VexRvm_Lx , V(660F00,DD,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1260 + INST(Vpaddw , VexRvm_Lx , V(660F00,FD,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1261 + INST(Vpalignr , VexRvmi_Lx , V(660F3A,0F,_,x,I,I,4,FVM), 0 , 206, 0 , 321, 181), // #1262 + INST(Vpand , VexRvm_Lx , V(660F00,DB,_,x,I,_,_,_ ), 0 , 71 , 0 , 357, 178), // #1263 + INST(Vpandd , VexRvm_Lx , E(660F00,DB,_,x,_,0,4,FV ), 0 , 200, 0 , 358, 152), // #1264 + INST(Vpandn , VexRvm_Lx , V(660F00,DF,_,x,I,_,_,_ ), 0 , 71 , 0 , 359, 178), // #1265 + INST(Vpandnd , VexRvm_Lx , E(660F00,DF,_,x,_,0,4,FV ), 0 , 200, 0 , 360, 152), // #1266 + INST(Vpandnq , VexRvm_Lx , E(660F00,DF,_,x,_,1,4,FV ), 0 , 136, 0 , 361, 152), // #1267 + INST(Vpandq , VexRvm_Lx , E(660F00,DB,_,x,_,1,4,FV ), 0 , 136, 0 , 362, 152), // #1268 + INST(Vpavgb , VexRvm_Lx , V(660F00,E0,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1269 + INST(Vpavgw , VexRvm_Lx , V(660F00,E3,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1270 + INST(Vpblendd , VexRvmi_Lx , V(660F3A,02,_,x,0,_,_,_ ), 0 , 75 , 0 , 219, 156), // #1271 + INST(Vpblendmb , VexRvm_Lx , E(660F38,66,_,x,_,0,4,FVM), 0 , 115, 0 , 363, 163), // #1272 + INST(Vpblendmd , VexRvm_Lx , E(660F38,64,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 152), // #1273 + INST(Vpblendmq , VexRvm_Lx , E(660F38,64,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1274 + INST(Vpblendmw , VexRvm_Lx , E(660F38,66,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 163), // #1275 + INST(Vpblendvb , VexRvmr_Lx , V(660F3A,4C,_,x,0,_,_,_ ), 0 , 75 , 0 , 220, 178), // #1276 + INST(Vpblendw , VexRvmi_Lx , V(660F3A,0E,_,x,I,_,_,_ ), 0 , 75 , 0 , 219, 178), // #1277 + INST(Vpbroadcastb , VexRm_Lx_Bcst , V(660F38,78,_,x,0,0,0,T1S), E(660F38,7A,_,x,0,0,0,T1S), 30 , 108, 364, 182), // #1278 + INST(Vpbroadcastd , VexRm_Lx_Bcst , V(660F38,58,_,x,0,0,2,T1S), E(660F38,7C,_,x,0,0,0,T1S), 123, 109, 365, 169), // #1279 + INST(Vpbroadcastmb2q , VexRm_Lx , E(F30F38,2A,_,x,_,1,_,_ ), 0 , 207, 0 , 366, 183), // #1280 + INST(Vpbroadcastmw2d , VexRm_Lx , E(F30F38,3A,_,x,_,0,_,_ ), 0 , 208, 0 , 366, 183), // #1281 + INST(Vpbroadcastq , VexRm_Lx_Bcst , V(660F38,59,_,x,0,1,3,T1S), E(660F38,7C,_,x,0,1,0,T1S), 122, 110, 367, 169), // #1282 + INST(Vpbroadcastw , VexRm_Lx_Bcst , V(660F38,79,_,x,0,0,1,T1S), E(660F38,7B,_,x,0,0,0,T1S), 209, 111, 368, 182), // #1283 + INST(Vpclmulqdq , VexRvmi_Lx , V(660F3A,44,_,x,I,_,4,FVM), 0 , 206, 0 , 369, 184), // #1284 + INST(Vpcmov , VexRvrmRvmr_Lx , V(XOP_M8,A2,_,x,x,_,_,_ ), 0 , 210, 0 , 296, 168), // #1285 + INST(Vpcmpb , VexRvmi_Lx , E(660F3A,3F,_,x,_,0,4,FVM), 0 , 112, 0 , 370, 163), // #1286 + INST(Vpcmpd , VexRvmi_Lx , E(660F3A,1F,_,x,_,0,4,FV ), 0 , 112, 0 , 371, 152), // #1287 + INST(Vpcmpeqb , VexRvm_Lx_KEvex , V(660F00,74,_,x,I,I,4,FV ), 0 , 145, 0 , 372, 181), // #1288 + INST(Vpcmpeqd , VexRvm_Lx_KEvex , V(660F00,76,_,x,I,0,4,FVM), 0 , 145, 0 , 373, 157), // #1289 + INST(Vpcmpeqq , VexRvm_Lx_KEvex , V(660F38,29,_,x,I,1,4,FVM), 0 , 211, 0 , 374, 157), // #1290 + INST(Vpcmpeqw , VexRvm_Lx_KEvex , V(660F00,75,_,x,I,I,4,FV ), 0 , 145, 0 , 372, 181), // #1291 + INST(Vpcmpestri , VexRmi , V(660F3A,61,_,0,I,_,_,_ ), 0 , 75 , 0 , 375, 185), // #1292 + INST(Vpcmpestrm , VexRmi , V(660F3A,60,_,0,I,_,_,_ ), 0 , 75 , 0 , 376, 185), // #1293 + INST(Vpcmpgtb , VexRvm_Lx_KEvex , V(660F00,64,_,x,I,I,4,FV ), 0 , 145, 0 , 372, 181), // #1294 + INST(Vpcmpgtd , VexRvm_Lx_KEvex , V(660F00,66,_,x,I,0,4,FVM), 0 , 145, 0 , 373, 157), // #1295 + INST(Vpcmpgtq , VexRvm_Lx_KEvex , V(660F38,37,_,x,I,1,4,FVM), 0 , 211, 0 , 374, 157), // #1296 + INST(Vpcmpgtw , VexRvm_Lx_KEvex , V(660F00,65,_,x,I,I,4,FV ), 0 , 145, 0 , 372, 181), // #1297 + INST(Vpcmpistri , VexRmi , V(660F3A,63,_,0,I,_,_,_ ), 0 , 75 , 0 , 377, 185), // #1298 + INST(Vpcmpistrm , VexRmi , V(660F3A,62,_,0,I,_,_,_ ), 0 , 75 , 0 , 378, 185), // #1299 + INST(Vpcmpq , VexRvmi_Lx , E(660F3A,1F,_,x,_,1,4,FV ), 0 , 113, 0 , 379, 152), // #1300 + INST(Vpcmpub , VexRvmi_Lx , E(660F3A,3E,_,x,_,0,4,FVM), 0 , 112, 0 , 370, 163), // #1301 + INST(Vpcmpud , VexRvmi_Lx , E(660F3A,1E,_,x,_,0,4,FV ), 0 , 112, 0 , 371, 152), // #1302 + INST(Vpcmpuq , VexRvmi_Lx , E(660F3A,1E,_,x,_,1,4,FV ), 0 , 113, 0 , 379, 152), // #1303 + INST(Vpcmpuw , VexRvmi_Lx , E(660F3A,3E,_,x,_,1,4,FVM), 0 , 113, 0 , 379, 163), // #1304 + INST(Vpcmpw , VexRvmi_Lx , E(660F3A,3F,_,x,_,1,4,FVM), 0 , 113, 0 , 379, 163), // #1305 + INST(Vpcomb , VexRvmi , V(XOP_M8,CC,_,0,0,_,_,_ ), 0 , 210, 0 , 283, 168), // #1306 + INST(Vpcomd , VexRvmi , V(XOP_M8,CE,_,0,0,_,_,_ ), 0 , 210, 0 , 283, 168), // #1307 + INST(Vpcompressb , VexMr_Lx , E(660F38,63,_,x,_,0,0,T1S), 0 , 212, 0 , 237, 186), // #1308 + INST(Vpcompressd , VexMr_Lx , E(660F38,8B,_,x,_,0,2,T1S), 0 , 130, 0 , 237, 152), // #1309 + INST(Vpcompressq , VexMr_Lx , E(660F38,8B,_,x,_,1,3,T1S), 0 , 129, 0 , 237, 152), // #1310 + INST(Vpcompressw , VexMr_Lx , E(660F38,63,_,x,_,1,1,T1S), 0 , 213, 0 , 237, 186), // #1311 + INST(Vpcomq , VexRvmi , V(XOP_M8,CF,_,0,0,_,_,_ ), 0 , 210, 0 , 283, 168), // #1312 + INST(Vpcomub , VexRvmi , V(XOP_M8,EC,_,0,0,_,_,_ ), 0 , 210, 0 , 283, 168), // #1313 + INST(Vpcomud , VexRvmi , V(XOP_M8,EE,_,0,0,_,_,_ ), 0 , 210, 0 , 283, 168), // #1314 + INST(Vpcomuq , VexRvmi , V(XOP_M8,EF,_,0,0,_,_,_ ), 0 , 210, 0 , 283, 168), // #1315 + INST(Vpcomuw , VexRvmi , V(XOP_M8,ED,_,0,0,_,_,_ ), 0 , 210, 0 , 283, 168), // #1316 + INST(Vpcomw , VexRvmi , V(XOP_M8,CD,_,0,0,_,_,_ ), 0 , 210, 0 , 283, 168), // #1317 + INST(Vpconflictd , VexRm_Lx , E(660F38,C4,_,x,_,0,4,FV ), 0 , 115, 0 , 380, 183), // #1318 + INST(Vpconflictq , VexRm_Lx , E(660F38,C4,_,x,_,1,4,FV ), 0 , 114, 0 , 380, 183), // #1319 + INST(Vpdpbssd , VexRvm_Lx , V(F20F38,50,_,x,0,_,_,_ ), 0 , 85 , 0 , 206, 187), // #1320 + INST(Vpdpbssds , VexRvm_Lx , V(F20F38,51,_,x,0,_,_,_ ), 0 , 85 , 0 , 206, 187), // #1321 + INST(Vpdpbsud , VexRvm_Lx , V(F30F38,50,_,x,0,_,_,_ ), 0 , 89 , 0 , 206, 187), // #1322 + INST(Vpdpbsuds , VexRvm_Lx , V(F30F38,51,_,x,0,_,_,_ ), 0 , 89 , 0 , 206, 187), // #1323 + INST(Vpdpbusd , VexRvm_Lx , V(660F38,50,_,x,_,0,4,FV ), 0 , 111, 0 , 381, 188), // #1324 + INST(Vpdpbusds , VexRvm_Lx , V(660F38,51,_,x,_,0,4,FV ), 0 , 111, 0 , 381, 188), // #1325 + INST(Vpdpbuud , VexRvm_Lx , V(000F38,50,_,x,0,_,_,_ ), 0 , 11 , 0 , 206, 187), // #1326 + INST(Vpdpbuuds , VexRvm_Lx , V(000F38,51,_,x,0,_,_,_ ), 0 , 11 , 0 , 206, 187), // #1327 + INST(Vpdpwssd , VexRvm_Lx , V(660F38,52,_,x,_,0,4,FV ), 0 , 111, 0 , 381, 188), // #1328 + INST(Vpdpwssds , VexRvm_Lx , V(660F38,53,_,x,_,0,4,FV ), 0 , 111, 0 , 381, 188), // #1329 + INST(Vpdpwsud , VexRvm_Lx , V(F30F38,D2,_,x,0,_,_,_ ), 0 , 89 , 0 , 206, 189), // #1330 + INST(Vpdpwsuds , VexRvm_Lx , V(F30F38,D3,_,x,0,_,_,_ ), 0 , 89 , 0 , 206, 189), // #1331 + INST(Vpdpwusd , VexRvm_Lx , V(660F38,D2,_,x,0,_,_,_ ), 0 , 30 , 0 , 206, 189), // #1332 + INST(Vpdpwusds , VexRvm_Lx , V(660F38,D3,_,x,0,_,_,_ ), 0 , 30 , 0 , 206, 189), // #1333 + INST(Vpdpwuud , VexRvm_Lx , V(000F38,D2,_,x,0,_,_,_ ), 0 , 11 , 0 , 206, 189), // #1334 + INST(Vpdpwuuds , VexRvm_Lx , V(000F38,D3,_,x,0,_,_,_ ), 0 , 11 , 0 , 206, 189), // #1335 + INST(Vperm2f128 , VexRvmi , V(660F3A,06,_,1,0,_,_,_ ), 0 , 174, 0 , 382, 149), // #1336 + INST(Vperm2i128 , VexRvmi , V(660F3A,46,_,1,0,_,_,_ ), 0 , 174, 0 , 382, 156), // #1337 + INST(Vpermb , VexRvm_Lx , E(660F38,8D,_,x,_,0,4,FVM), 0 , 115, 0 , 363, 190), // #1338 + INST(Vpermd , VexRvm_Lx , V(660F38,36,_,x,0,0,4,FV ), 0 , 111, 0 , 383, 169), // #1339 + INST(Vpermi2b , VexRvm_Lx , E(660F38,75,_,x,_,0,4,FVM), 0 , 115, 0 , 363, 190), // #1340 + INST(Vpermi2d , VexRvm_Lx , E(660F38,76,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 152), // #1341 + INST(Vpermi2pd , VexRvm_Lx , E(660F38,77,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1342 + INST(Vpermi2ps , VexRvm_Lx , E(660F38,77,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 152), // #1343 + INST(Vpermi2q , VexRvm_Lx , E(660F38,76,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1344 + INST(Vpermi2w , VexRvm_Lx , E(660F38,75,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 163), // #1345 + INST(Vpermil2pd , VexRvrmiRvmri_Lx , V(660F3A,49,_,x,x,_,_,_ ), 0 , 75 , 0 , 384, 168), // #1346 + INST(Vpermil2ps , VexRvrmiRvmri_Lx , V(660F3A,48,_,x,x,_,_,_ ), 0 , 75 , 0 , 384, 168), // #1347 + INST(Vpermilpd , VexRvmRmi_Lx , V(660F38,0D,_,x,0,1,4,FV ), V(660F3A,05,_,x,0,1,4,FV ), 211, 112, 385, 145), // #1348 + INST(Vpermilps , VexRvmRmi_Lx , V(660F38,0C,_,x,0,0,4,FV ), V(660F3A,04,_,x,0,0,4,FV ), 111, 113, 386, 145), // #1349 + INST(Vpermpd , VexRvmRmi_Lx , E(660F38,16,_,x,1,1,4,FV ), V(660F3A,01,_,x,1,1,4,FV ), 214, 114, 387, 169), // #1350 + INST(Vpermps , VexRvm_Lx , V(660F38,16,_,x,0,0,4,FV ), 0 , 111, 0 , 383, 169), // #1351 + INST(Vpermq , VexRvmRmi_Lx , E(660F38,36,_,x,_,1,4,FV ), V(660F3A,00,_,x,1,1,4,FV ), 114, 115, 387, 169), // #1352 + INST(Vpermt2b , VexRvm_Lx , E(660F38,7D,_,x,_,0,4,FVM), 0 , 115, 0 , 363, 190), // #1353 + INST(Vpermt2d , VexRvm_Lx , E(660F38,7E,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 152), // #1354 + INST(Vpermt2pd , VexRvm_Lx , E(660F38,7F,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1355 + INST(Vpermt2ps , VexRvm_Lx , E(660F38,7F,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 152), // #1356 + INST(Vpermt2q , VexRvm_Lx , E(660F38,7E,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1357 + INST(Vpermt2w , VexRvm_Lx , E(660F38,7D,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 163), // #1358 + INST(Vpermw , VexRvm_Lx , E(660F38,8D,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 163), // #1359 + INST(Vpexpandb , VexRm_Lx , E(660F38,62,_,x,_,0,0,T1S), 0 , 212, 0 , 286, 186), // #1360 + INST(Vpexpandd , VexRm_Lx , E(660F38,89,_,x,_,0,2,T1S), 0 , 130, 0 , 286, 152), // #1361 + INST(Vpexpandq , VexRm_Lx , E(660F38,89,_,x,_,1,3,T1S), 0 , 129, 0 , 286, 152), // #1362 + INST(Vpexpandw , VexRm_Lx , E(660F38,62,_,x,_,1,1,T1S), 0 , 213, 0 , 286, 186), // #1363 + INST(Vpextrb , VexMri , V(660F3A,14,_,0,0,I,0,T1S), 0 , 75 , 0 , 388, 191), // #1364 + INST(Vpextrd , VexMri , V(660F3A,16,_,0,0,0,2,T1S), 0 , 179, 0 , 290, 192), // #1365 + INST(Vpextrq , VexMri , V(660F3A,16,_,0,1,1,3,T1S), 0 , 215, 0 , 389, 192), // #1366 + INST(Vpextrw , VexMri_Vpextrw , V(660F3A,15,_,0,0,I,1,T1S), 0 , 216, 0 , 390, 191), // #1367 + INST(Vpgatherdd , VexRmvRm_VM , V(660F38,90,_,x,0,_,_,_ ), E(660F38,90,_,x,_,0,2,T1S), 30 , 116, 309, 169), // #1368 + INST(Vpgatherdq , VexRmvRm_VM , V(660F38,90,_,x,1,_,_,_ ), E(660F38,90,_,x,_,1,3,T1S), 191, 117, 308, 169), // #1369 + INST(Vpgatherqd , VexRmvRm_VM , V(660F38,91,_,x,0,_,_,_ ), E(660F38,91,_,x,_,0,2,T1S), 30 , 118, 314, 169), // #1370 + INST(Vpgatherqq , VexRmvRm_VM , V(660F38,91,_,x,1,_,_,_ ), E(660F38,91,_,x,_,1,3,T1S), 191, 119, 313, 169), // #1371 + INST(Vphaddbd , VexRm , V(XOP_M9,C2,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1372 + INST(Vphaddbq , VexRm , V(XOP_M9,C3,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1373 + INST(Vphaddbw , VexRm , V(XOP_M9,C1,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1374 + INST(Vphaddd , VexRvm_Lx , V(660F38,02,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1375 + INST(Vphadddq , VexRm , V(XOP_M9,CB,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1376 + INST(Vphaddsw , VexRvm_Lx , V(660F38,03,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1377 + INST(Vphaddubd , VexRm , V(XOP_M9,D2,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1378 + INST(Vphaddubq , VexRm , V(XOP_M9,D3,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1379 + INST(Vphaddubw , VexRm , V(XOP_M9,D1,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1380 + INST(Vphaddudq , VexRm , V(XOP_M9,DB,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1381 + INST(Vphadduwd , VexRm , V(XOP_M9,D6,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1382 + INST(Vphadduwq , VexRm , V(XOP_M9,D7,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1383 + INST(Vphaddw , VexRvm_Lx , V(660F38,01,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1384 + INST(Vphaddwd , VexRm , V(XOP_M9,C6,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1385 + INST(Vphaddwq , VexRm , V(XOP_M9,C7,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1386 + INST(Vphminposuw , VexRm , V(660F38,41,_,0,I,_,_,_ ), 0 , 30 , 0 , 208, 149), // #1387 + INST(Vphsubbw , VexRm , V(XOP_M9,E1,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1388 + INST(Vphsubd , VexRvm_Lx , V(660F38,06,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1389 + INST(Vphsubdq , VexRm , V(XOP_M9,E3,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1390 + INST(Vphsubsw , VexRvm_Lx , V(660F38,07,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1391 + INST(Vphsubw , VexRvm_Lx , V(660F38,05,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1392 + INST(Vphsubwd , VexRm , V(XOP_M9,E2,_,0,0,_,_,_ ), 0 , 81 , 0 , 208, 168), // #1393 + INST(Vpinsrb , VexRvmi , V(660F3A,20,_,0,0,I,0,T1S), 0 , 75 , 0 , 391, 191), // #1394 + INST(Vpinsrd , VexRvmi , V(660F3A,22,_,0,0,0,2,T1S), 0 , 179, 0 , 392, 192), // #1395 + INST(Vpinsrq , VexRvmi , V(660F3A,22,_,0,1,1,3,T1S), 0 , 215, 0 , 393, 192), // #1396 + INST(Vpinsrw , VexRvmi , V(660F00,C4,_,0,0,I,1,T1S), 0 , 217, 0 , 394, 191), // #1397 + INST(Vplzcntd , VexRm_Lx , E(660F38,44,_,x,_,0,4,FV ), 0 , 115, 0 , 380, 183), // #1398 + INST(Vplzcntq , VexRm_Lx , E(660F38,44,_,x,_,1,4,FV ), 0 , 114, 0 , 356, 183), // #1399 + INST(Vpmacsdd , VexRvmr , V(XOP_M8,9E,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1400 + INST(Vpmacsdqh , VexRvmr , V(XOP_M8,9F,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1401 + INST(Vpmacsdql , VexRvmr , V(XOP_M8,97,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1402 + INST(Vpmacssdd , VexRvmr , V(XOP_M8,8E,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1403 + INST(Vpmacssdqh , VexRvmr , V(XOP_M8,8F,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1404 + INST(Vpmacssdql , VexRvmr , V(XOP_M8,87,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1405 + INST(Vpmacsswd , VexRvmr , V(XOP_M8,86,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1406 + INST(Vpmacssww , VexRvmr , V(XOP_M8,85,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1407 + INST(Vpmacswd , VexRvmr , V(XOP_M8,96,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1408 + INST(Vpmacsww , VexRvmr , V(XOP_M8,95,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1409 + INST(Vpmadcsswd , VexRvmr , V(XOP_M8,A6,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1410 + INST(Vpmadcswd , VexRvmr , V(XOP_M8,B6,_,0,0,_,_,_ ), 0 , 210, 0 , 395, 168), // #1411 + INST(Vpmadd52huq , VexRvm_Lx , V(660F38,B5,_,x,1,1,4,FV ), 0 , 184, 0 , 396, 193), // #1412 + INST(Vpmadd52luq , VexRvm_Lx , V(660F38,B4,_,x,1,1,4,FV ), 0 , 184, 0 , 396, 193), // #1413 + INST(Vpmaddubsw , VexRvm_Lx , V(660F38,04,_,x,I,I,4,FVM), 0 , 111, 0 , 322, 181), // #1414 + INST(Vpmaddwd , VexRvm_Lx , V(660F00,F5,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1415 + INST(Vpmaskmovd , VexRvmMvr_Lx , V(660F38,8C,_,x,0,_,_,_ ), V(660F38,8E,_,x,0,_,_,_ ), 30 , 120, 329, 156), // #1416 + INST(Vpmaskmovq , VexRvmMvr_Lx , V(660F38,8C,_,x,1,_,_,_ ), V(660F38,8E,_,x,1,_,_,_ ), 191, 121, 329, 156), // #1417 + INST(Vpmaxsb , VexRvm_Lx , V(660F38,3C,_,x,I,I,4,FVM), 0 , 111, 0 , 397, 181), // #1418 + INST(Vpmaxsd , VexRvm_Lx , V(660F38,3D,_,x,I,0,4,FV ), 0 , 111, 0 , 215, 157), // #1419 + INST(Vpmaxsq , VexRvm_Lx , E(660F38,3D,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1420 + INST(Vpmaxsw , VexRvm_Lx , V(660F00,EE,_,x,I,I,4,FVM), 0 , 145, 0 , 397, 181), // #1421 + INST(Vpmaxub , VexRvm_Lx , V(660F00,DE,_,x,I,I,4,FVM), 0 , 145, 0 , 397, 181), // #1422 + INST(Vpmaxud , VexRvm_Lx , V(660F38,3F,_,x,I,0,4,FV ), 0 , 111, 0 , 215, 157), // #1423 + INST(Vpmaxuq , VexRvm_Lx , E(660F38,3F,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1424 + INST(Vpmaxuw , VexRvm_Lx , V(660F38,3E,_,x,I,I,4,FVM), 0 , 111, 0 , 397, 181), // #1425 + INST(Vpminsb , VexRvm_Lx , V(660F38,38,_,x,I,I,4,FVM), 0 , 111, 0 , 397, 181), // #1426 + INST(Vpminsd , VexRvm_Lx , V(660F38,39,_,x,I,0,4,FV ), 0 , 111, 0 , 215, 157), // #1427 + INST(Vpminsq , VexRvm_Lx , E(660F38,39,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1428 + INST(Vpminsw , VexRvm_Lx , V(660F00,EA,_,x,I,I,4,FVM), 0 , 145, 0 , 397, 181), // #1429 + INST(Vpminub , VexRvm_Lx , V(660F00,DA,_,x,I,_,4,FVM), 0 , 145, 0 , 397, 181), // #1430 + INST(Vpminud , VexRvm_Lx , V(660F38,3B,_,x,I,0,4,FV ), 0 , 111, 0 , 215, 157), // #1431 + INST(Vpminuq , VexRvm_Lx , E(660F38,3B,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1432 + INST(Vpminuw , VexRvm_Lx , V(660F38,3A,_,x,I,_,4,FVM), 0 , 111, 0 , 397, 181), // #1433 + INST(Vpmovb2m , VexRm_Lx , E(F30F38,29,_,x,_,0,_,_ ), 0 , 208, 0 , 398, 163), // #1434 + INST(Vpmovd2m , VexRm_Lx , E(F30F38,39,_,x,_,0,_,_ ), 0 , 208, 0 , 398, 155), // #1435 + INST(Vpmovdb , VexMr_Lx , E(F30F38,31,_,x,_,0,2,QVM), 0 , 218, 0 , 399, 152), // #1436 + INST(Vpmovdw , VexMr_Lx , E(F30F38,33,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 152), // #1437 + INST(Vpmovm2b , VexRm_Lx , E(F30F38,28,_,x,_,0,_,_ ), 0 , 208, 0 , 366, 163), // #1438 + INST(Vpmovm2d , VexRm_Lx , E(F30F38,38,_,x,_,0,_,_ ), 0 , 208, 0 , 366, 155), // #1439 + INST(Vpmovm2q , VexRm_Lx , E(F30F38,38,_,x,_,1,_,_ ), 0 , 207, 0 , 366, 155), // #1440 + INST(Vpmovm2w , VexRm_Lx , E(F30F38,28,_,x,_,1,_,_ ), 0 , 207, 0 , 366, 163), // #1441 + INST(Vpmovmskb , VexRm_Lx , V(660F00,D7,_,x,I,_,_,_ ), 0 , 71 , 0 , 342, 178), // #1442 + INST(Vpmovq2m , VexRm_Lx , E(F30F38,39,_,x,_,1,_,_ ), 0 , 207, 0 , 398, 155), // #1443 + INST(Vpmovqb , VexMr_Lx , E(F30F38,32,_,x,_,0,1,OVM), 0 , 220, 0 , 401, 152), // #1444 + INST(Vpmovqd , VexMr_Lx , E(F30F38,35,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 152), // #1445 + INST(Vpmovqw , VexMr_Lx , E(F30F38,34,_,x,_,0,2,QVM), 0 , 218, 0 , 399, 152), // #1446 + INST(Vpmovsdb , VexMr_Lx , E(F30F38,21,_,x,_,0,2,QVM), 0 , 218, 0 , 399, 152), // #1447 + INST(Vpmovsdw , VexMr_Lx , E(F30F38,23,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 152), // #1448 + INST(Vpmovsqb , VexMr_Lx , E(F30F38,22,_,x,_,0,1,OVM), 0 , 220, 0 , 401, 152), // #1449 + INST(Vpmovsqd , VexMr_Lx , E(F30F38,25,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 152), // #1450 + INST(Vpmovsqw , VexMr_Lx , E(F30F38,24,_,x,_,0,2,QVM), 0 , 218, 0 , 399, 152), // #1451 + INST(Vpmovswb , VexMr_Lx , E(F30F38,20,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 163), // #1452 + INST(Vpmovsxbd , VexRm_Lx , V(660F38,21,_,x,I,I,2,QVM), 0 , 221, 0 , 402, 157), // #1453 + INST(Vpmovsxbq , VexRm_Lx , V(660F38,22,_,x,I,I,1,OVM), 0 , 222, 0 , 403, 157), // #1454 + INST(Vpmovsxbw , VexRm_Lx , V(660F38,20,_,x,I,I,3,HVM), 0 , 140, 0 , 404, 181), // #1455 + INST(Vpmovsxdq , VexRm_Lx , V(660F38,25,_,x,I,0,3,HVM), 0 , 140, 0 , 404, 157), // #1456 + INST(Vpmovsxwd , VexRm_Lx , V(660F38,23,_,x,I,I,3,HVM), 0 , 140, 0 , 404, 157), // #1457 + INST(Vpmovsxwq , VexRm_Lx , V(660F38,24,_,x,I,I,2,QVM), 0 , 221, 0 , 402, 157), // #1458 + INST(Vpmovusdb , VexMr_Lx , E(F30F38,11,_,x,_,0,2,QVM), 0 , 218, 0 , 399, 152), // #1459 + INST(Vpmovusdw , VexMr_Lx , E(F30F38,13,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 152), // #1460 + INST(Vpmovusqb , VexMr_Lx , E(F30F38,12,_,x,_,0,1,OVM), 0 , 220, 0 , 401, 152), // #1461 + INST(Vpmovusqd , VexMr_Lx , E(F30F38,15,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 152), // #1462 + INST(Vpmovusqw , VexMr_Lx , E(F30F38,14,_,x,_,0,2,QVM), 0 , 218, 0 , 399, 152), // #1463 + INST(Vpmovuswb , VexMr_Lx , E(F30F38,10,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 163), // #1464 + INST(Vpmovw2m , VexRm_Lx , E(F30F38,29,_,x,_,1,_,_ ), 0 , 207, 0 , 398, 163), // #1465 + INST(Vpmovwb , VexMr_Lx , E(F30F38,30,_,x,_,0,3,HVM), 0 , 219, 0 , 400, 163), // #1466 + INST(Vpmovzxbd , VexRm_Lx , V(660F38,31,_,x,I,I,2,QVM), 0 , 221, 0 , 402, 157), // #1467 + INST(Vpmovzxbq , VexRm_Lx , V(660F38,32,_,x,I,I,1,OVM), 0 , 222, 0 , 403, 157), // #1468 + INST(Vpmovzxbw , VexRm_Lx , V(660F38,30,_,x,I,I,3,HVM), 0 , 140, 0 , 404, 181), // #1469 + INST(Vpmovzxdq , VexRm_Lx , V(660F38,35,_,x,I,0,3,HVM), 0 , 140, 0 , 404, 157), // #1470 + INST(Vpmovzxwd , VexRm_Lx , V(660F38,33,_,x,I,I,3,HVM), 0 , 140, 0 , 404, 157), // #1471 + INST(Vpmovzxwq , VexRm_Lx , V(660F38,34,_,x,I,I,2,QVM), 0 , 221, 0 , 402, 157), // #1472 + INST(Vpmuldq , VexRvm_Lx , V(660F38,28,_,x,I,1,4,FV ), 0 , 211, 0 , 212, 157), // #1473 + INST(Vpmulhrsw , VexRvm_Lx , V(660F38,0B,_,x,I,I,4,FVM), 0 , 111, 0 , 322, 181), // #1474 + INST(Vpmulhuw , VexRvm_Lx , V(660F00,E4,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1475 + INST(Vpmulhw , VexRvm_Lx , V(660F00,E5,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1476 + INST(Vpmulld , VexRvm_Lx , V(660F38,40,_,x,I,0,4,FV ), 0 , 111, 0 , 213, 157), // #1477 + INST(Vpmullq , VexRvm_Lx , E(660F38,40,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 155), // #1478 + INST(Vpmullw , VexRvm_Lx , V(660F00,D5,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1479 + INST(Vpmultishiftqb , VexRvm_Lx , E(660F38,83,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 190), // #1480 + INST(Vpmuludq , VexRvm_Lx , V(660F00,F4,_,x,I,1,4,FV ), 0 , 104, 0 , 212, 157), // #1481 + INST(Vpopcntb , VexRm_Lx , E(660F38,54,_,x,_,0,4,FV ), 0 , 115, 0 , 286, 194), // #1482 + INST(Vpopcntd , VexRm_Lx , E(660F38,55,_,x,_,0,4,FVM), 0 , 115, 0 , 380, 195), // #1483 + INST(Vpopcntq , VexRm_Lx , E(660F38,55,_,x,_,1,4,FVM), 0 , 114, 0 , 356, 195), // #1484 + INST(Vpopcntw , VexRm_Lx , E(660F38,54,_,x,_,1,4,FV ), 0 , 114, 0 , 286, 194), // #1485 + INST(Vpor , VexRvm_Lx , V(660F00,EB,_,x,I,_,_,_ ), 0 , 71 , 0 , 357, 178), // #1486 + INST(Vpord , VexRvm_Lx , E(660F00,EB,_,x,_,0,4,FV ), 0 , 200, 0 , 358, 152), // #1487 + INST(Vporq , VexRvm_Lx , E(660F00,EB,_,x,_,1,4,FV ), 0 , 136, 0 , 362, 152), // #1488 + INST(Vpperm , VexRvrmRvmr , V(XOP_M8,A3,_,0,x,_,_,_ ), 0 , 210, 0 , 405, 168), // #1489 + INST(Vprold , VexVmi_Lx , E(660F00,72,1,x,_,0,4,FV ), 0 , 223, 0 , 406, 152), // #1490 + INST(Vprolq , VexVmi_Lx , E(660F00,72,1,x,_,1,4,FV ), 0 , 224, 0 , 407, 152), // #1491 + INST(Vprolvd , VexRvm_Lx , E(660F38,15,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 152), // #1492 + INST(Vprolvq , VexRvm_Lx , E(660F38,15,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1493 + INST(Vprord , VexVmi_Lx , E(660F00,72,0,x,_,0,4,FV ), 0 , 200, 0 , 406, 152), // #1494 + INST(Vprorq , VexVmi_Lx , E(660F00,72,0,x,_,1,4,FV ), 0 , 136, 0 , 407, 152), // #1495 + INST(Vprorvd , VexRvm_Lx , E(660F38,14,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 152), // #1496 + INST(Vprorvq , VexRvm_Lx , E(660F38,14,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1497 + INST(Vprotb , VexRvmRmvRmi , V(XOP_M9,90,_,0,x,_,_,_ ), V(XOP_M8,C0,_,0,x,_,_,_ ), 81 , 122, 408, 168), // #1498 + INST(Vprotd , VexRvmRmvRmi , V(XOP_M9,92,_,0,x,_,_,_ ), V(XOP_M8,C2,_,0,x,_,_,_ ), 81 , 123, 408, 168), // #1499 + INST(Vprotq , VexRvmRmvRmi , V(XOP_M9,93,_,0,x,_,_,_ ), V(XOP_M8,C3,_,0,x,_,_,_ ), 81 , 124, 408, 168), // #1500 + INST(Vprotw , VexRvmRmvRmi , V(XOP_M9,91,_,0,x,_,_,_ ), V(XOP_M8,C1,_,0,x,_,_,_ ), 81 , 125, 408, 168), // #1501 + INST(Vpsadbw , VexRvm_Lx , V(660F00,F6,_,x,I,I,4,FVM), 0 , 145, 0 , 207, 181), // #1502 + INST(Vpscatterdd , VexMr_VM , E(660F38,A0,_,x,_,0,2,T1S), 0 , 130, 0 , 409, 152), // #1503 + INST(Vpscatterdq , VexMr_VM , E(660F38,A0,_,x,_,1,3,T1S), 0 , 129, 0 , 410, 152), // #1504 + INST(Vpscatterqd , VexMr_VM , E(660F38,A1,_,x,_,0,2,T1S), 0 , 130, 0 , 411, 152), // #1505 + INST(Vpscatterqq , VexMr_VM , E(660F38,A1,_,x,_,1,3,T1S), 0 , 129, 0 , 412, 152), // #1506 + INST(Vpshab , VexRvmRmv , V(XOP_M9,98,_,0,x,_,_,_ ), 0 , 81 , 0 , 413, 168), // #1507 + INST(Vpshad , VexRvmRmv , V(XOP_M9,9A,_,0,x,_,_,_ ), 0 , 81 , 0 , 413, 168), // #1508 + INST(Vpshaq , VexRvmRmv , V(XOP_M9,9B,_,0,x,_,_,_ ), 0 , 81 , 0 , 413, 168), // #1509 + INST(Vpshaw , VexRvmRmv , V(XOP_M9,99,_,0,x,_,_,_ ), 0 , 81 , 0 , 413, 168), // #1510 + INST(Vpshlb , VexRvmRmv , V(XOP_M9,94,_,0,x,_,_,_ ), 0 , 81 , 0 , 413, 168), // #1511 + INST(Vpshld , VexRvmRmv , V(XOP_M9,96,_,0,x,_,_,_ ), 0 , 81 , 0 , 413, 168), // #1512 + INST(Vpshldd , VexRvmi_Lx , E(660F3A,71,_,x,_,0,4,FV ), 0 , 112, 0 , 210, 186), // #1513 + INST(Vpshldq , VexRvmi_Lx , E(660F3A,71,_,x,_,1,4,FV ), 0 , 113, 0 , 211, 186), // #1514 + INST(Vpshldvd , VexRvm_Lx , E(660F38,71,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 186), // #1515 + INST(Vpshldvq , VexRvm_Lx , E(660F38,71,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 186), // #1516 + INST(Vpshldvw , VexRvm_Lx , E(660F38,70,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 186), // #1517 + INST(Vpshldw , VexRvmi_Lx , E(660F3A,70,_,x,_,1,4,FVM), 0 , 113, 0 , 282, 186), // #1518 + INST(Vpshlq , VexRvmRmv , V(XOP_M9,97,_,0,x,_,_,_ ), 0 , 81 , 0 , 413, 168), // #1519 + INST(Vpshlw , VexRvmRmv , V(XOP_M9,95,_,0,x,_,_,_ ), 0 , 81 , 0 , 413, 168), // #1520 + INST(Vpshrdd , VexRvmi_Lx , E(660F3A,73,_,x,_,0,4,FV ), 0 , 112, 0 , 210, 186), // #1521 + INST(Vpshrdq , VexRvmi_Lx , E(660F3A,73,_,x,_,1,4,FV ), 0 , 113, 0 , 211, 186), // #1522 + INST(Vpshrdvd , VexRvm_Lx , E(660F38,73,_,x,_,0,4,FV ), 0 , 115, 0 , 218, 186), // #1523 + INST(Vpshrdvq , VexRvm_Lx , E(660F38,73,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 186), // #1524 + INST(Vpshrdvw , VexRvm_Lx , E(660F38,72,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 186), // #1525 + INST(Vpshrdw , VexRvmi_Lx , E(660F3A,72,_,x,_,1,4,FVM), 0 , 113, 0 , 282, 186), // #1526 + INST(Vpshufb , VexRvm_Lx , V(660F38,00,_,x,I,I,4,FVM), 0 , 111, 0 , 322, 181), // #1527 + INST(Vpshufbitqmb , VexRvm_Lx , E(660F38,8F,_,x,0,0,4,FVM), 0 , 115, 0 , 414, 194), // #1528 + INST(Vpshufd , VexRmi_Lx , V(660F00,70,_,x,I,0,4,FV ), 0 , 145, 0 , 415, 157), // #1529 + INST(Vpshufhw , VexRmi_Lx , V(F30F00,70,_,x,I,I,4,FVM), 0 , 162, 0 , 416, 181), // #1530 + INST(Vpshuflw , VexRmi_Lx , V(F20F00,70,_,x,I,I,4,FVM), 0 , 225, 0 , 416, 181), // #1531 + INST(Vpsignb , VexRvm_Lx , V(660F38,08,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1532 + INST(Vpsignd , VexRvm_Lx , V(660F38,0A,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1533 + INST(Vpsignw , VexRvm_Lx , V(660F38,09,_,x,I,_,_,_ ), 0 , 30 , 0 , 206, 178), // #1534 + INST(Vpslld , VexRvmVmi_Lx_MEvex , V(660F00,F2,_,x,I,0,4,128), V(660F00,72,6,x,I,0,4,FV ), 226, 126, 417, 157), // #1535 + INST(Vpslldq , VexVmi_Lx_MEvex , V(660F00,73,7,x,I,I,4,FVM), 0 , 227, 0 , 418, 181), // #1536 + INST(Vpsllq , VexRvmVmi_Lx_MEvex , V(660F00,F3,_,x,I,1,4,128), V(660F00,73,6,x,I,1,4,FV ), 228, 127, 419, 157), // #1537 + INST(Vpsllvd , VexRvm_Lx , V(660F38,47,_,x,0,0,4,FV ), 0 , 111, 0 , 213, 169), // #1538 + INST(Vpsllvq , VexRvm_Lx , V(660F38,47,_,x,1,1,4,FV ), 0 , 184, 0 , 212, 169), // #1539 + INST(Vpsllvw , VexRvm_Lx , E(660F38,12,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 163), // #1540 + INST(Vpsllw , VexRvmVmi_Lx_MEvex , V(660F00,F1,_,x,I,I,4,128), V(660F00,71,6,x,I,I,4,FVM), 226, 128, 420, 181), // #1541 + INST(Vpsrad , VexRvmVmi_Lx_MEvex , V(660F00,E2,_,x,I,0,4,128), V(660F00,72,4,x,I,0,4,FV ), 226, 129, 417, 157), // #1542 + INST(Vpsraq , VexRvmVmi_Lx_MEvex , E(660F00,E2,_,x,_,1,4,128), E(660F00,72,4,x,_,1,4,FV ), 229, 130, 421, 152), // #1543 + INST(Vpsravd , VexRvm_Lx , V(660F38,46,_,x,0,0,4,FV ), 0 , 111, 0 , 213, 169), // #1544 + INST(Vpsravq , VexRvm_Lx , E(660F38,46,_,x,_,1,4,FV ), 0 , 114, 0 , 217, 152), // #1545 + INST(Vpsravw , VexRvm_Lx , E(660F38,11,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 163), // #1546 + INST(Vpsraw , VexRvmVmi_Lx_MEvex , V(660F00,E1,_,x,I,I,4,128), V(660F00,71,4,x,I,I,4,FVM), 226, 131, 420, 181), // #1547 + INST(Vpsrld , VexRvmVmi_Lx_MEvex , V(660F00,D2,_,x,I,0,4,128), V(660F00,72,2,x,I,0,4,FV ), 226, 132, 417, 157), // #1548 + INST(Vpsrldq , VexVmi_Lx_MEvex , V(660F00,73,3,x,I,I,4,FVM), 0 , 230, 0 , 418, 181), // #1549 + INST(Vpsrlq , VexRvmVmi_Lx_MEvex , V(660F00,D3,_,x,I,1,4,128), V(660F00,73,2,x,I,1,4,FV ), 228, 133, 419, 157), // #1550 + INST(Vpsrlvd , VexRvm_Lx , V(660F38,45,_,x,0,0,4,FV ), 0 , 111, 0 , 213, 169), // #1551 + INST(Vpsrlvq , VexRvm_Lx , V(660F38,45,_,x,1,1,4,FV ), 0 , 184, 0 , 212, 169), // #1552 + INST(Vpsrlvw , VexRvm_Lx , E(660F38,10,_,x,_,1,4,FVM), 0 , 114, 0 , 363, 163), // #1553 + INST(Vpsrlw , VexRvmVmi_Lx_MEvex , V(660F00,D1,_,x,I,I,4,128), V(660F00,71,2,x,I,I,4,FVM), 226, 134, 420, 181), // #1554 + INST(Vpsubb , VexRvm_Lx , V(660F00,F8,_,x,I,I,4,FVM), 0 , 145, 0 , 422, 181), // #1555 + INST(Vpsubd , VexRvm_Lx , V(660F00,FA,_,x,I,0,4,FV ), 0 , 145, 0 , 423, 157), // #1556 + INST(Vpsubq , VexRvm_Lx , V(660F00,FB,_,x,I,1,4,FV ), 0 , 104, 0 , 424, 157), // #1557 + INST(Vpsubsb , VexRvm_Lx , V(660F00,E8,_,x,I,I,4,FVM), 0 , 145, 0 , 422, 181), // #1558 + INST(Vpsubsw , VexRvm_Lx , V(660F00,E9,_,x,I,I,4,FVM), 0 , 145, 0 , 422, 181), // #1559 + INST(Vpsubusb , VexRvm_Lx , V(660F00,D8,_,x,I,I,4,FVM), 0 , 145, 0 , 422, 181), // #1560 + INST(Vpsubusw , VexRvm_Lx , V(660F00,D9,_,x,I,I,4,FVM), 0 , 145, 0 , 422, 181), // #1561 + INST(Vpsubw , VexRvm_Lx , V(660F00,F9,_,x,I,I,4,FVM), 0 , 145, 0 , 422, 181), // #1562 + INST(Vpternlogd , VexRvmi_Lx , E(660F3A,25,_,x,_,0,4,FV ), 0 , 112, 0 , 210, 152), // #1563 + INST(Vpternlogq , VexRvmi_Lx , E(660F3A,25,_,x,_,1,4,FV ), 0 , 113, 0 , 211, 152), // #1564 + INST(Vptest , VexRm_Lx , V(660F38,17,_,x,I,_,_,_ ), 0 , 30 , 0 , 305, 185), // #1565 + INST(Vptestmb , VexRvm_Lx , E(660F38,26,_,x,_,0,4,FVM), 0 , 115, 0 , 414, 163), // #1566 + INST(Vptestmd , VexRvm_Lx , E(660F38,27,_,x,_,0,4,FV ), 0 , 115, 0 , 425, 152), // #1567 + INST(Vptestmq , VexRvm_Lx , E(660F38,27,_,x,_,1,4,FV ), 0 , 114, 0 , 426, 152), // #1568 + INST(Vptestmw , VexRvm_Lx , E(660F38,26,_,x,_,1,4,FVM), 0 , 114, 0 , 414, 163), // #1569 + INST(Vptestnmb , VexRvm_Lx , E(F30F38,26,_,x,_,0,4,FVM), 0 , 171, 0 , 414, 163), // #1570 + INST(Vptestnmd , VexRvm_Lx , E(F30F38,27,_,x,_,0,4,FV ), 0 , 171, 0 , 425, 152), // #1571 + INST(Vptestnmq , VexRvm_Lx , E(F30F38,27,_,x,_,1,4,FV ), 0 , 231, 0 , 426, 152), // #1572 + INST(Vptestnmw , VexRvm_Lx , E(F30F38,26,_,x,_,1,4,FVM), 0 , 231, 0 , 414, 163), // #1573 + INST(Vpunpckhbw , VexRvm_Lx , V(660F00,68,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1574 + INST(Vpunpckhdq , VexRvm_Lx , V(660F00,6A,_,x,I,0,4,FV ), 0 , 145, 0 , 213, 157), // #1575 + INST(Vpunpckhqdq , VexRvm_Lx , V(660F00,6D,_,x,I,1,4,FV ), 0 , 104, 0 , 212, 157), // #1576 + INST(Vpunpckhwd , VexRvm_Lx , V(660F00,69,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1577 + INST(Vpunpcklbw , VexRvm_Lx , V(660F00,60,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1578 + INST(Vpunpckldq , VexRvm_Lx , V(660F00,62,_,x,I,0,4,FV ), 0 , 145, 0 , 213, 157), // #1579 + INST(Vpunpcklqdq , VexRvm_Lx , V(660F00,6C,_,x,I,1,4,FV ), 0 , 104, 0 , 212, 157), // #1580 + INST(Vpunpcklwd , VexRvm_Lx , V(660F00,61,_,x,I,I,4,FVM), 0 , 145, 0 , 322, 181), // #1581 + INST(Vpxor , VexRvm_Lx , V(660F00,EF,_,x,I,_,_,_ ), 0 , 71 , 0 , 359, 178), // #1582 + INST(Vpxord , VexRvm_Lx , E(660F00,EF,_,x,_,0,4,FV ), 0 , 200, 0 , 360, 152), // #1583 + INST(Vpxorq , VexRvm_Lx , E(660F00,EF,_,x,_,1,4,FV ), 0 , 136, 0 , 361, 152), // #1584 + INST(Vrangepd , VexRvmi_Lx , E(660F3A,50,_,x,_,1,4,FV ), 0 , 113, 0 , 292, 155), // #1585 + INST(Vrangeps , VexRvmi_Lx , E(660F3A,50,_,x,_,0,4,FV ), 0 , 112, 0 , 293, 155), // #1586 + INST(Vrangesd , VexRvmi , E(660F3A,51,_,I,_,1,3,T1S), 0 , 182, 0 , 294, 76 ), // #1587 + INST(Vrangess , VexRvmi , E(660F3A,51,_,I,_,0,2,T1S), 0 , 183, 0 , 295, 76 ), // #1588 + INST(Vrcp14pd , VexRm_Lx , E(660F38,4C,_,x,_,1,4,FV ), 0 , 114, 0 , 356, 152), // #1589 + INST(Vrcp14ps , VexRm_Lx , E(660F38,4C,_,x,_,0,4,FV ), 0 , 115, 0 , 380, 152), // #1590 + INST(Vrcp14sd , VexRvm , E(660F38,4D,_,I,_,1,3,T1S), 0 , 129, 0 , 427, 78 ), // #1591 + INST(Vrcp14ss , VexRvm , E(660F38,4D,_,I,_,0,2,T1S), 0 , 130, 0 , 428, 78 ), // #1592 + INST(Vrcp28pd , VexRm , E(660F38,CA,_,2,_,1,4,FV ), 0 , 172, 0 , 284, 164), // #1593 + INST(Vrcp28ps , VexRm , E(660F38,CA,_,2,_,0,4,FV ), 0 , 173, 0 , 285, 164), // #1594 + INST(Vrcp28sd , VexRvm , E(660F38,CB,_,I,_,1,3,T1S), 0 , 129, 0 , 315, 164), // #1595 + INST(Vrcp28ss , VexRvm , E(660F38,CB,_,I,_,0,2,T1S), 0 , 130, 0 , 316, 164), // #1596 + INST(Vrcpph , VexRm_Lx , E(66MAP6,4C,_,_,_,0,4,FV ), 0 , 185, 0 , 429, 148), // #1597 + INST(Vrcpps , VexRm_Lx , V(000F00,53,_,x,I,_,_,_ ), 0 , 74 , 0 , 305, 149), // #1598 + INST(Vrcpsh , VexRvm , E(66MAP6,4D,_,_,_,0,1,T1S), 0 , 187, 0 , 430, 148), // #1599 + INST(Vrcpss , VexRvm , V(F30F00,53,_,I,I,_,_,_ ), 0 , 201, 0 , 431, 149), // #1600 + INST(Vreducepd , VexRmi_Lx , E(660F3A,56,_,x,_,1,4,FV ), 0 , 113, 0 , 407, 155), // #1601 + INST(Vreduceph , VexRmi_Lx , E(000F3A,56,_,_,_,0,4,FV ), 0 , 124, 0 , 318, 146), // #1602 + INST(Vreduceps , VexRmi_Lx , E(660F3A,56,_,x,_,0,4,FV ), 0 , 112, 0 , 406, 155), // #1603 + INST(Vreducesd , VexRvmi , E(660F3A,57,_,I,_,1,3,T1S), 0 , 182, 0 , 432, 76 ), // #1604 + INST(Vreducesh , VexRvmi , E(000F3A,57,_,_,_,0,1,T1S), 0 , 190, 0 , 320, 148), // #1605 + INST(Vreducess , VexRvmi , E(660F3A,57,_,I,_,0,2,T1S), 0 , 183, 0 , 433, 76 ), // #1606 + INST(Vrndscalepd , VexRmi_Lx , E(660F3A,09,_,x,_,1,4,FV ), 0 , 113, 0 , 317, 152), // #1607 + INST(Vrndscaleph , VexRmi_Lx , E(000F3A,08,_,_,_,0,4,FV ), 0 , 124, 0 , 318, 146), // #1608 + INST(Vrndscaleps , VexRmi_Lx , E(660F3A,08,_,x,_,0,4,FV ), 0 , 112, 0 , 319, 152), // #1609 + INST(Vrndscalesd , VexRvmi , E(660F3A,0B,_,I,_,1,3,T1S), 0 , 182, 0 , 294, 78 ), // #1610 + INST(Vrndscalesh , VexRvmi , E(000F3A,0A,_,_,_,0,1,T1S), 0 , 190, 0 , 320, 148), // #1611 + INST(Vrndscaless , VexRvmi , E(660F3A,0A,_,I,_,0,2,T1S), 0 , 183, 0 , 295, 78 ), // #1612 + INST(Vroundpd , VexRmi_Lx , V(660F3A,09,_,x,I,_,_,_ ), 0 , 75 , 0 , 434, 149), // #1613 + INST(Vroundps , VexRmi_Lx , V(660F3A,08,_,x,I,_,_,_ ), 0 , 75 , 0 , 434, 149), // #1614 + INST(Vroundsd , VexRvmi , V(660F3A,0B,_,I,I,_,_,_ ), 0 , 75 , 0 , 435, 149), // #1615 + INST(Vroundss , VexRvmi , V(660F3A,0A,_,I,I,_,_,_ ), 0 , 75 , 0 , 436, 149), // #1616 + INST(Vrsqrt14pd , VexRm_Lx , E(660F38,4E,_,x,_,1,4,FV ), 0 , 114, 0 , 356, 152), // #1617 + INST(Vrsqrt14ps , VexRm_Lx , E(660F38,4E,_,x,_,0,4,FV ), 0 , 115, 0 , 380, 152), // #1618 + INST(Vrsqrt14sd , VexRvm , E(660F38,4F,_,I,_,1,3,T1S), 0 , 129, 0 , 427, 78 ), // #1619 + INST(Vrsqrt14ss , VexRvm , E(660F38,4F,_,I,_,0,2,T1S), 0 , 130, 0 , 428, 78 ), // #1620 + INST(Vrsqrt28pd , VexRm , E(660F38,CC,_,2,_,1,4,FV ), 0 , 172, 0 , 284, 164), // #1621 + INST(Vrsqrt28ps , VexRm , E(660F38,CC,_,2,_,0,4,FV ), 0 , 173, 0 , 285, 164), // #1622 + INST(Vrsqrt28sd , VexRvm , E(660F38,CD,_,I,_,1,3,T1S), 0 , 129, 0 , 315, 164), // #1623 + INST(Vrsqrt28ss , VexRvm , E(660F38,CD,_,I,_,0,2,T1S), 0 , 130, 0 , 316, 164), // #1624 + INST(Vrsqrtph , VexRm_Lx , E(66MAP6,4E,_,_,_,0,4,FV ), 0 , 185, 0 , 429, 146), // #1625 + INST(Vrsqrtps , VexRm_Lx , V(000F00,52,_,x,I,_,_,_ ), 0 , 74 , 0 , 305, 149), // #1626 + INST(Vrsqrtsh , VexRvm , E(66MAP6,4F,_,_,_,0,1,T1S), 0 , 187, 0 , 430, 148), // #1627 + INST(Vrsqrtss , VexRvm , V(F30F00,52,_,I,I,_,_,_ ), 0 , 201, 0 , 431, 149), // #1628 + INST(Vscalefpd , VexRvm_Lx , E(660F38,2C,_,x,_,1,4,FV ), 0 , 114, 0 , 437, 152), // #1629 + INST(Vscalefph , VexRvm_Lx , E(66MAP6,2C,_,_,_,0,4,FV ), 0 , 185, 0 , 201, 146), // #1630 + INST(Vscalefps , VexRvm_Lx , E(660F38,2C,_,x,_,0,4,FV ), 0 , 115, 0 , 291, 152), // #1631 + INST(Vscalefsd , VexRvm , E(660F38,2D,_,I,_,1,3,T1S), 0 , 129, 0 , 257, 78 ), // #1632 + INST(Vscalefsh , VexRvm , E(66MAP6,2D,_,_,_,0,1,T1S), 0 , 187, 0 , 204, 148), // #1633 + INST(Vscalefss , VexRvm , E(660F38,2D,_,I,_,0,2,T1S), 0 , 130, 0 , 265, 78 ), // #1634 + INST(Vscatterdpd , VexMr_VM , E(660F38,A2,_,x,_,1,3,T1S), 0 , 129, 0 , 410, 152), // #1635 + INST(Vscatterdps , VexMr_VM , E(660F38,A2,_,x,_,0,2,T1S), 0 , 130, 0 , 409, 152), // #1636 + INST(Vscatterpf0dpd , VexM_VM , E(660F38,C6,5,2,_,1,3,T1S), 0 , 232, 0 , 310, 170), // #1637 + INST(Vscatterpf0dps , VexM_VM , E(660F38,C6,5,2,_,0,2,T1S), 0 , 233, 0 , 311, 170), // #1638 + INST(Vscatterpf0qpd , VexM_VM , E(660F38,C7,5,2,_,1,3,T1S), 0 , 232, 0 , 312, 170), // #1639 + INST(Vscatterpf0qps , VexM_VM , E(660F38,C7,5,2,_,0,2,T1S), 0 , 233, 0 , 312, 170), // #1640 + INST(Vscatterpf1dpd , VexM_VM , E(660F38,C6,6,2,_,1,3,T1S), 0 , 234, 0 , 310, 170), // #1641 + INST(Vscatterpf1dps , VexM_VM , E(660F38,C6,6,2,_,0,2,T1S), 0 , 235, 0 , 311, 170), // #1642 + INST(Vscatterpf1qpd , VexM_VM , E(660F38,C7,6,2,_,1,3,T1S), 0 , 234, 0 , 312, 170), // #1643 + INST(Vscatterpf1qps , VexM_VM , E(660F38,C7,6,2,_,0,2,T1S), 0 , 235, 0 , 312, 170), // #1644 + INST(Vscatterqpd , VexMr_VM , E(660F38,A3,_,x,_,1,3,T1S), 0 , 129, 0 , 412, 152), // #1645 + INST(Vscatterqps , VexMr_VM , E(660F38,A3,_,x,_,0,2,T1S), 0 , 130, 0 , 411, 152), // #1646 + INST(Vsha512msg1 , VexRm , V(F20F38,CC,_,1,0,_,_,_ ), 0 , 236, 0 , 438, 196), // #1647 + INST(Vsha512msg2 , VexRm , V(F20F38,CD,_,1,0,_,_,_ ), 0 , 236, 0 , 439, 196), // #1648 + INST(Vsha512rnds2 , VexRvm , V(F20F38,CB,_,1,0,_,_,_ ), 0 , 236, 0 , 440, 196), // #1649 + INST(Vshuff32x4 , VexRvmi_Lx , E(660F3A,23,_,x,_,0,4,FV ), 0 , 112, 0 , 441, 152), // #1650 + INST(Vshuff64x2 , VexRvmi_Lx , E(660F3A,23,_,x,_,1,4,FV ), 0 , 113, 0 , 442, 152), // #1651 + INST(Vshufi32x4 , VexRvmi_Lx , E(660F3A,43,_,x,_,0,4,FV ), 0 , 112, 0 , 441, 152), // #1652 + INST(Vshufi64x2 , VexRvmi_Lx , E(660F3A,43,_,x,_,1,4,FV ), 0 , 113, 0 , 442, 152), // #1653 + INST(Vshufpd , VexRvmi_Lx , V(660F00,C6,_,x,I,1,4,FV ), 0 , 104, 0 , 443, 145), // #1654 + INST(Vshufps , VexRvmi_Lx , V(000F00,C6,_,x,I,0,4,FV ), 0 , 106, 0 , 444, 145), // #1655 + INST(Vsm3msg1 , VexRvm , V(000F38,DA,_,0,0,_,_,_ ), 0 , 11 , 0 , 445, 197), // #1656 + INST(Vsm3msg2 , VexRvm , V(660F38,DA,_,0,0,_,_,_ ), 0 , 30 , 0 , 445, 197), // #1657 + INST(Vsm3rnds2 , VexRvmi , V(660F3A,DE,_,0,0,_,_,_ ), 0 , 75 , 0 , 283, 197), // #1658 + INST(Vsm4key4 , VexRvm_Lx , V(F30F38,DA,_,x,0,_,_,_ ), 0 , 89 , 0 , 206, 198), // #1659 + INST(Vsm4rnds4 , VexRvm_Lx , V(F20F38,DA,_,x,0,_,_,_ ), 0 , 85 , 0 , 206, 198), // #1660 + INST(Vsqrtpd , VexRm_Lx , V(660F00,51,_,x,I,1,4,FV ), 0 , 104, 0 , 446, 145), // #1661 + INST(Vsqrtph , VexRm_Lx , E(00MAP5,51,_,_,_,0,4,FV ), 0 , 105, 0 , 252, 146), // #1662 + INST(Vsqrtps , VexRm_Lx , V(000F00,51,_,x,I,0,4,FV ), 0 , 106, 0 , 240, 145), // #1663 + INST(Vsqrtsd , VexRvm , V(F20F00,51,_,I,I,1,3,T1S), 0 , 107, 0 , 203, 147), // #1664 + INST(Vsqrtsh , VexRvm , E(F3MAP5,51,_,_,_,0,1,T1S), 0 , 108, 0 , 204, 148), // #1665 + INST(Vsqrtss , VexRvm , V(F30F00,51,_,I,I,0,2,T1S), 0 , 109, 0 , 205, 147), // #1666 + INST(Vstmxcsr , VexM , V(000F00,AE,3,0,I,_,_,_ ), 0 , 237, 0 , 327, 149), // #1667 + INST(Vsubpd , VexRvm_Lx , V(660F00,5C,_,x,I,1,4,FV ), 0 , 104, 0 , 200, 145), // #1668 + INST(Vsubph , VexRvm_Lx , E(00MAP5,5C,_,_,_,0,4,FV ), 0 , 105, 0 , 201, 146), // #1669 + INST(Vsubps , VexRvm_Lx , V(000F00,5C,_,x,I,0,4,FV ), 0 , 106, 0 , 202, 145), // #1670 + INST(Vsubsd , VexRvm , V(F20F00,5C,_,I,I,1,3,T1S), 0 , 107, 0 , 203, 147), // #1671 + INST(Vsubsh , VexRvm , E(F3MAP5,5C,_,_,_,0,1,T1S), 0 , 108, 0 , 204, 148), // #1672 + INST(Vsubss , VexRvm , V(F30F00,5C,_,I,I,0,2,T1S), 0 , 109, 0 , 205, 147), // #1673 + INST(Vtestpd , VexRm_Lx , V(660F38,0F,_,x,0,_,_,_ ), 0 , 30 , 0 , 305, 185), // #1674 + INST(Vtestps , VexRm_Lx , V(660F38,0E,_,x,0,_,_,_ ), 0 , 30 , 0 , 305, 185), // #1675 + INST(Vucomisd , VexRm , V(660F00,2E,_,I,I,1,3,T1S), 0 , 126, 0 , 234, 158), // #1676 + INST(Vucomish , VexRm , E(00MAP5,2E,_,_,_,0,1,T1S), 0 , 127, 0 , 235, 159), // #1677 + INST(Vucomiss , VexRm , V(000F00,2E,_,I,I,0,2,T1S), 0 , 128, 0 , 236, 158), // #1678 + INST(Vunpckhpd , VexRvm_Lx , V(660F00,15,_,x,I,1,4,FV ), 0 , 104, 0 , 212, 145), // #1679 + INST(Vunpckhps , VexRvm_Lx , V(000F00,15,_,x,I,0,4,FV ), 0 , 106, 0 , 213, 145), // #1680 + INST(Vunpcklpd , VexRvm_Lx , V(660F00,14,_,x,I,1,4,FV ), 0 , 104, 0 , 212, 145), // #1681 + INST(Vunpcklps , VexRvm_Lx , V(000F00,14,_,x,I,0,4,FV ), 0 , 106, 0 , 213, 145), // #1682 + INST(Vxorpd , VexRvm_Lx , V(660F00,57,_,x,I,1,4,FV ), 0 , 104, 0 , 424, 153), // #1683 + INST(Vxorps , VexRvm_Lx , V(000F00,57,_,x,I,0,4,FV ), 0 , 106, 0 , 423, 153), // #1684 + INST(Vzeroall , VexOp , V(000F00,77,_,1,I,_,_,_ ), 0 , 70 , 0 , 447, 149), // #1685 + INST(Vzeroupper , VexOp , V(000F00,77,_,0,I,_,_,_ ), 0 , 74 , 0 , 447, 149), // #1686 + INST(Wbinvd , X86Op , O(000F00,09,_,_,_,_,_,_ ), 0 , 5 , 0 , 31 , 45 ), // #1687 + INST(Wbnoinvd , X86Op , O(F30F00,09,_,_,_,_,_,_ ), 0 , 7 , 0 , 31 , 199), // #1688 + INST(Wrfsbase , X86M , O(F30F00,AE,2,_,x,_,_,_ ), 0 , 238, 0 , 177, 122), // #1689 + INST(Wrgsbase , X86M , O(F30F00,AE,3,_,x,_,_,_ ), 0 , 239, 0 , 177, 122), // #1690 + INST(Wrmsr , X86Op , O(000F00,30,_,_,_,_,_,_ ), 0 , 5 , 0 , 178, 123), // #1691 + INST(Wrssd , X86Mr , O(000F38,F6,_,_,_,_,_,_ ), 0 , 1 , 0 , 448, 65 ), // #1692 + INST(Wrssq , X86Mr , O(000F38,F6,_,_,1,_,_,_ ), 0 , 240, 0 , 449, 65 ), // #1693 + INST(Wrussd , X86Mr , O(660F38,F5,_,_,_,_,_,_ ), 0 , 2 , 0 , 448, 65 ), // #1694 + INST(Wrussq , X86Mr , O(660F38,F5,_,_,1,_,_,_ ), 0 , 241, 0 , 449, 65 ), // #1695 + INST(Xabort , X86Op_Mod11RM_I8 , O(000000,C6,7,_,_,_,_,_ ), 0 , 29 , 0 , 84 , 200), // #1696 + INST(Xadd , X86Xadd , O(000F00,C0,_,_,x,_,_,_ ), 0 , 5 , 0 , 450, 40 ), // #1697 + INST(Xbegin , X86JmpRel , O(000000,C7,7,_,_,_,_,_ ), 0 , 29 , 0 , 451, 200), // #1698 + INST(Xchg , X86Xchg , O(000000,86,_,_,x,_,_,_ ), 0 , 0 , 0 , 452, 0 ), // #1699 + INST(Xend , X86Op , O(000F01,D5,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 200), // #1700 + INST(Xgetbv , X86Op , O(000F01,D0,_,_,_,_,_,_ ), 0 , 23 , 0 , 178, 201), // #1701 + INST(Xlatb , X86Op , O(000000,D7,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 0 ), // #1702 + INST(Xor , X86Arith , O(000000,30,6,_,x,_,_,_ ), 0 , 34 , 0 , 183, 1 ), // #1703 + INST(Xorpd , ExtRm , O(660F00,57,_,_,_,_,_,_ ), 0 , 4 , 0 , 155, 5 ), // #1704 + INST(Xorps , ExtRm , O(000F00,57,_,_,_,_,_,_ ), 0 , 5 , 0 , 155, 6 ), // #1705 + INST(Xresldtrk , X86Op , O(F20F01,E9,_,_,_,_,_,_ ), 0 , 93 , 0 , 31 , 202), // #1706 + INST(Xrstor , X86M_Only_EDX_EAX , O(000F00,AE,5,_,_,_,_,_ ), 0 , 79 , 0 , 453, 201), // #1707 + INST(Xrstor64 , X86M_Only_EDX_EAX , O(000F00,AE,5,_,1,_,_,_ ), 0 , 242, 0 , 454, 201), // #1708 + INST(Xrstors , X86M_Only_EDX_EAX , O(000F00,C7,3,_,_,_,_,_ ), 0 , 80 , 0 , 453, 203), // #1709 + INST(Xrstors64 , X86M_Only_EDX_EAX , O(000F00,C7,3,_,1,_,_,_ ), 0 , 243, 0 , 454, 203), // #1710 + INST(Xsave , X86M_Only_EDX_EAX , O(000F00,AE,4,_,_,_,_,_ ), 0 , 98 , 0 , 453, 201), // #1711 + INST(Xsave64 , X86M_Only_EDX_EAX , O(000F00,AE,4,_,1,_,_,_ ), 0 , 244, 0 , 454, 201), // #1712 + INST(Xsavec , X86M_Only_EDX_EAX , O(000F00,C7,4,_,_,_,_,_ ), 0 , 98 , 0 , 453, 204), // #1713 + INST(Xsavec64 , X86M_Only_EDX_EAX , O(000F00,C7,4,_,1,_,_,_ ), 0 , 244, 0 , 454, 204), // #1714 + INST(Xsaveopt , X86M_Only_EDX_EAX , O(000F00,AE,6,_,_,_,_,_ ), 0 , 82 , 0 , 453, 205), // #1715 + INST(Xsaveopt64 , X86M_Only_EDX_EAX , O(000F00,AE,6,_,1,_,_,_ ), 0 , 245, 0 , 454, 205), // #1716 + INST(Xsaves , X86M_Only_EDX_EAX , O(000F00,C7,5,_,_,_,_,_ ), 0 , 79 , 0 , 453, 203), // #1717 + INST(Xsaves64 , X86M_Only_EDX_EAX , O(000F00,C7,5,_,1,_,_,_ ), 0 , 242, 0 , 454, 203), // #1718 + INST(Xsetbv , X86Op , O(000F01,D1,_,_,_,_,_,_ ), 0 , 23 , 0 , 178, 201), // #1719 + INST(Xsusldtrk , X86Op , O(F20F01,E8,_,_,_,_,_,_ ), 0 , 93 , 0 , 31 , 202), // #1720 + INST(Xtest , X86Op , O(000F01,D6,_,_,_,_,_,_ ), 0 , 23 , 0 , 31 , 206) // #1721 // ${InstInfo:End} }; #undef NAME_DATA_INDEX @@ -1747,248 +1780,251 @@ const InstDB::InstInfo InstDB::_instInfoTable[] = { // ------------------- Automatically generated, do not edit ------------------- const uint32_t InstDB::_mainOpcodeTable[] = { O(000000,00,0,0,0,0,0,0 ), // #0 [ref=56x] - O(000000,00,2,0,0,0,0,0 ), // #1 [ref=4x] - O(660F38,00,0,0,0,0,0,0 ), // #2 [ref=43x] - O(660F00,00,0,0,0,0,0,0 ), // #3 [ref=38x] - O(000F00,00,0,0,0,0,0,0 ), // #4 [ref=231x] - O(F20F00,00,0,0,0,0,0,0 ), // #5 [ref=24x] - O(F30F00,00,0,0,0,0,0,0 ), // #6 [ref=29x] - O(F30F38,00,0,0,0,0,0,0 ), // #7 [ref=2x] - O(660F3A,00,0,0,0,0,0,0 ), // #8 [ref=22x] - O(000000,00,4,0,0,0,0,0 ), // #9 [ref=5x] - V(000F38,00,0,0,0,0,0,None), // #10 [ref=6x] - V(XOP_M9,00,1,0,0,0,0,None), // #11 [ref=3x] - V(XOP_M9,00,6,0,0,0,0,None), // #12 [ref=2x] - V(XOP_M9,00,5,0,0,0,0,None), // #13 [ref=1x] - V(XOP_M9,00,3,0,0,0,0,None), // #14 [ref=1x] - V(XOP_M9,00,2,0,0,0,0,None), // #15 [ref=1x] - V(000F38,00,3,0,0,0,0,None), // #16 [ref=1x] - V(000F38,00,2,0,0,0,0,None), // #17 [ref=1x] - V(000F38,00,1,0,0,0,0,None), // #18 [ref=1x] - O(660000,00,0,0,0,0,0,0 ), // #19 [ref=7x] - O(000000,00,0,0,1,0,0,0 ), // #20 [ref=3x] - O(000F01,00,0,0,0,0,0,0 ), // #21 [ref=29x] - O(000F00,00,7,0,0,0,0,0 ), // #22 [ref=5x] - O(660F00,00,7,0,0,0,0,0 ), // #23 [ref=1x] - O(F30F00,00,6,0,0,0,0,0 ), // #24 [ref=4x] - O(F30F01,00,0,0,0,0,0,0 ), // #25 [ref=9x] - O(660F00,00,6,0,0,0,0,0 ), // #26 [ref=3x] - O(000000,00,7,0,0,0,0,0 ), // #27 [ref=5x] - O(000F00,00,1,0,1,0,0,0 ), // #28 [ref=2x] - O(000F00,00,1,0,0,0,0,0 ), // #29 [ref=6x] - O(F20F38,00,0,0,0,0,0,0 ), // #30 [ref=2x] - O(000000,00,1,0,0,0,0,0 ), // #31 [ref=3x] - O(000000,00,6,0,0,0,0,0 ), // #32 [ref=3x] - O(F30F00,00,7,0,0,0,0,3 ), // #33 [ref=1x] - O(F30F00,00,7,0,0,0,0,2 ), // #34 [ref=1x] - O_FPU(00,D900,0) , // #35 [ref=29x] - O_FPU(00,C000,0) , // #36 [ref=1x] - O_FPU(00,DE00,0) , // #37 [ref=7x] - O_FPU(00,0000,4) , // #38 [ref=4x] - O_FPU(00,0000,6) , // #39 [ref=4x] - O_FPU(9B,DB00,0) , // #40 [ref=2x] - O_FPU(00,DA00,0) , // #41 [ref=5x] - O_FPU(00,DB00,0) , // #42 [ref=8x] - O_FPU(00,D000,2) , // #43 [ref=1x] - O_FPU(00,DF00,0) , // #44 [ref=2x] - O_FPU(00,D800,3) , // #45 [ref=1x] - O_FPU(00,F000,6) , // #46 [ref=1x] - O_FPU(00,F800,7) , // #47 [ref=1x] - O_FPU(00,DD00,0) , // #48 [ref=3x] - O_FPU(00,0000,0) , // #49 [ref=4x] - O_FPU(00,0000,2) , // #50 [ref=3x] - O_FPU(00,0000,3) , // #51 [ref=3x] - O_FPU(00,0000,7) , // #52 [ref=3x] - O_FPU(00,0000,1) , // #53 [ref=2x] - O_FPU(00,0000,5) , // #54 [ref=2x] - O_FPU(00,C800,1) , // #55 [ref=1x] - O_FPU(9B,0000,6) , // #56 [ref=2x] - O_FPU(9B,0000,7) , // #57 [ref=2x] - O_FPU(00,E000,4) , // #58 [ref=1x] - O_FPU(00,E800,5) , // #59 [ref=1x] - O(000F00,00,0,0,1,0,0,0 ), // #60 [ref=3x] - O(F30F3A,00,0,0,0,0,0,0 ), // #61 [ref=1x] - O(000000,00,5,0,0,0,0,0 ), // #62 [ref=4x] - O(F30F00,00,5,0,0,0,0,0 ), // #63 [ref=2x] - O(F30F00,00,5,0,1,0,0,0 ), // #64 [ref=1x] - V(660F00,00,0,1,0,0,0,None), // #65 [ref=7x] - V(660F00,00,0,1,1,0,0,None), // #66 [ref=6x] - V(000F00,00,0,1,1,0,0,None), // #67 [ref=7x] - V(000F00,00,0,1,0,0,0,None), // #68 [ref=8x] - V(660F00,00,0,0,0,0,0,None), // #69 [ref=15x] - V(660F00,00,0,0,1,0,0,None), // #70 [ref=4x] - V(000F00,00,0,0,1,0,0,None), // #71 [ref=4x] - V(000F00,00,0,0,0,0,0,None), // #72 [ref=10x] - V(660F3A,00,0,0,0,0,0,None), // #73 [ref=47x] - V(660F3A,00,0,0,1,0,0,None), // #74 [ref=4x] - O(000000,00,3,0,0,0,0,0 ), // #75 [ref=4x] - O(000F00,00,2,0,0,0,0,0 ), // #76 [ref=5x] - O(000F00,00,5,0,0,0,0,0 ), // #77 [ref=4x] - O(000F00,00,3,0,0,0,0,0 ), // #78 [ref=5x] - V(XOP_M9,00,0,0,0,0,0,None), // #79 [ref=32x] - O(000F00,00,6,0,0,0,0,0 ), // #80 [ref=5x] - V(XOP_MA,00,0,0,0,0,0,None), // #81 [ref=1x] - V(XOP_MA,00,1,0,0,0,0,None), // #82 [ref=1x] - O(000F38,00,0,0,0,0,0,0 ), // #83 [ref=24x] - V(F20F38,00,0,0,0,0,0,None), // #84 [ref=6x] - O(000F3A,00,0,0,0,0,0,0 ), // #85 [ref=4x] - O(F30000,00,0,0,0,0,0,0 ), // #86 [ref=1x] - O(000F0F,00,0,0,0,0,0,0 ), // #87 [ref=26x] - V(F30F38,00,0,0,0,0,0,None), // #88 [ref=5x] - O(000F3A,00,0,0,1,0,0,0 ), // #89 [ref=1x] - O(660F3A,00,0,0,1,0,0,0 ), // #90 [ref=1x] - O(F30F00,00,4,0,0,0,0,0 ), // #91 [ref=1x] - O(F20F01,00,0,0,0,0,0,0 ), // #92 [ref=4x] - O(F30F00,00,1,0,0,0,0,0 ), // #93 [ref=3x] - O(F30F00,00,7,0,0,0,0,0 ), // #94 [ref=1x] - V(F20F3A,00,0,0,0,0,0,None), // #95 [ref=1x] - V(660F38,00,0,0,0,0,0,None), // #96 [ref=26x] - O(000F00,00,4,0,0,0,0,0 ), // #97 [ref=4x] - V(XOP_M9,00,7,0,0,0,0,None), // #98 [ref=1x] - V(XOP_M9,00,4,0,0,0,0,None), // #99 [ref=1x] - O(F20F00,00,6,0,0,0,0,0 ), // #100 [ref=1x] - E(F20F38,00,0,2,0,0,4,None), // #101 [ref=4x] - E(F20F38,00,0,0,0,0,4,None), // #102 [ref=2x] - V(660F00,00,0,0,0,1,4,ByLL), // #103 [ref=25x] - E(00MAP5,00,0,0,0,0,4,ByLL), // #104 [ref=10x] - V(000F00,00,0,0,0,0,4,ByLL), // #105 [ref=19x] - V(F20F00,00,0,0,0,1,3,None), // #106 [ref=10x] - E(F3MAP5,00,0,0,0,0,1,None), // #107 [ref=13x] - V(F30F00,00,0,0,0,0,2,None), // #108 [ref=12x] - V(F20F00,00,0,0,0,0,0,None), // #109 [ref=4x] - V(660F38,00,0,0,0,0,4,ByLL), // #110 [ref=50x] - E(660F3A,00,0,0,0,0,4,ByLL), // #111 [ref=17x] - E(660F3A,00,0,0,0,1,4,ByLL), // #112 [ref=18x] - E(660F38,00,0,0,0,1,4,ByLL), // #113 [ref=40x] - E(660F38,00,0,0,0,0,4,ByLL), // #114 [ref=25x] - V(660F38,00,0,1,0,0,0,None), // #115 [ref=2x] - E(660F38,00,0,0,0,0,3,None), // #116 [ref=2x] - E(660F38,00,0,0,0,0,4,None), // #117 [ref=2x] - E(660F38,00,0,2,0,0,5,None), // #118 [ref=2x] - E(660F38,00,0,0,0,1,4,None), // #119 [ref=2x] - E(660F38,00,0,2,0,1,5,None), // #120 [ref=2x] - V(660F38,00,0,0,0,1,3,None), // #121 [ref=2x] - V(660F38,00,0,0,0,0,2,None), // #122 [ref=14x] - E(000F3A,00,0,0,0,0,4,ByLL), // #123 [ref=5x] - E(F30F3A,00,0,0,0,0,1,None), // #124 [ref=1x] - V(660F00,00,0,0,0,1,3,None), // #125 [ref=5x] - E(00MAP5,00,0,0,0,0,1,None), // #126 [ref=2x] - V(000F00,00,0,0,0,0,2,None), // #127 [ref=2x] - E(660F38,00,0,0,0,1,3,None), // #128 [ref=14x] - E(660F38,00,0,0,0,0,2,None), // #129 [ref=14x] - V(F30F00,00,0,0,0,0,3,ByLL), // #130 [ref=1x] - E(F20F38,00,0,0,0,0,4,ByLL), // #131 [ref=2x] - E(F30F38,00,0,0,0,0,4,ByLL), // #132 [ref=4x] - V(F20F00,00,0,0,0,1,4,ByLL), // #133 [ref=1x] - E(66MAP5,00,0,0,0,1,4,ByLL), // #134 [ref=1x] - E(660F00,00,0,0,0,1,4,ByLL), // #135 [ref=10x] - E(000F00,00,0,0,0,1,4,ByLL), // #136 [ref=3x] - E(66MAP5,00,0,0,0,0,3,ByLL), // #137 [ref=1x] - E(00MAP5,00,0,0,0,0,2,ByLL), // #138 [ref=1x] - V(660F38,00,0,0,0,0,3,ByLL), // #139 [ref=7x] - E(66MAP6,00,0,0,0,0,3,ByLL), // #140 [ref=1x] - E(66MAP5,00,0,0,0,0,2,ByLL), // #141 [ref=4x] - E(00MAP5,00,0,0,0,0,3,ByLL), // #142 [ref=2x] - E(66MAP5,00,0,0,0,0,4,ByLL), // #143 [ref=3x] - V(660F00,00,0,0,0,0,4,ByLL), // #144 [ref=43x] - V(000F00,00,0,0,0,0,3,ByLL), // #145 [ref=1x] - V(660F3A,00,0,0,0,0,3,ByLL), // #146 [ref=1x] - E(660F00,00,0,0,0,0,3,ByLL), // #147 [ref=4x] - E(000F00,00,0,0,0,0,4,ByLL), // #148 [ref=2x] - E(F30F00,00,0,0,0,1,4,ByLL), // #149 [ref=3x] - E(00MAP5,00,0,0,0,1,4,ByLL), // #150 [ref=1x] - E(F2MAP5,00,0,0,0,1,3,None), // #151 [ref=1x] - V(F20F00,00,0,0,0,0,3,None), // #152 [ref=2x] - E(F20F00,00,0,0,0,0,3,None), // #153 [ref=2x] - E(00MAP6,00,0,0,0,0,1,None), // #154 [ref=1x] - V(F20F00,00,0,0,0,0,2,T1W ), // #155 [ref=1x] - E(F3MAP5,00,0,0,0,0,2,T1W ), // #156 [ref=2x] - V(F30F00,00,0,0,0,0,2,T1W ), // #157 [ref=1x] - E(00MAP5,00,0,0,0,0,2,None), // #158 [ref=1x] - E(F30F00,00,0,0,0,0,2,None), // #159 [ref=2x] - E(F3MAP5,00,0,0,0,0,3,ByLL), // #160 [ref=1x] - V(F30F00,00,0,0,0,0,4,ByLL), // #161 [ref=4x] - E(F30F00,00,0,0,0,0,3,ByLL), // #162 [ref=1x] - E(F2MAP5,00,0,0,0,0,4,ByLL), // #163 [ref=2x] - E(F20F00,00,0,0,0,0,4,ByLL), // #164 [ref=2x] - E(F2MAP5,00,0,0,0,1,4,ByLL), // #165 [ref=1x] - E(F20F00,00,0,0,0,1,4,ByLL), // #166 [ref=2x] - E(F20F00,00,0,0,0,0,2,T1W ), // #167 [ref=1x] - E(F30F00,00,0,0,0,0,2,T1W ), // #168 [ref=1x] - E(F3MAP5,00,0,0,0,0,4,ByLL), // #169 [ref=1x] - E(660F38,00,0,2,0,1,4,ByLL), // #170 [ref=3x] - E(660F38,00,0,2,0,0,4,ByLL), // #171 [ref=3x] - V(660F3A,00,0,1,0,0,0,None), // #172 [ref=6x] - E(660F3A,00,0,0,0,0,4,None), // #173 [ref=4x] - E(660F3A,00,0,2,0,0,5,None), // #174 [ref=4x] - E(660F3A,00,0,0,0,1,4,None), // #175 [ref=4x] - E(660F3A,00,0,2,0,1,5,None), // #176 [ref=4x] - V(660F3A,00,0,0,0,0,2,None), // #177 [ref=4x] - E(F2MAP6,00,0,0,0,0,4,ByLL), // #178 [ref=2x] - E(F2MAP6,00,0,0,0,0,2,None), // #179 [ref=2x] - E(660F3A,00,0,0,0,1,3,None), // #180 [ref=6x] - E(660F3A,00,0,0,0,0,2,None), // #181 [ref=6x] - V(660F38,00,0,0,1,1,4,ByLL), // #182 [ref=20x] - E(66MAP6,00,0,0,0,0,4,ByLL), // #183 [ref=22x] - V(660F38,00,0,0,1,1,3,None), // #184 [ref=12x] - E(66MAP6,00,0,0,0,0,1,None), // #185 [ref=16x] - E(F3MAP6,00,0,0,0,0,4,ByLL), // #186 [ref=2x] - E(F3MAP6,00,0,0,0,0,2,None), // #187 [ref=2x] - E(000F3A,00,0,0,0,0,1,None), // #188 [ref=4x] - V(660F38,00,0,0,1,0,0,None), // #189 [ref=5x] - E(660F38,00,1,2,0,1,3,None), // #190 [ref=2x] - E(660F38,00,1,2,0,0,2,None), // #191 [ref=2x] - E(660F38,00,2,2,0,1,3,None), // #192 [ref=2x] - E(660F38,00,2,2,0,0,2,None), // #193 [ref=2x] - V(660F3A,00,0,0,1,1,4,ByLL), // #194 [ref=2x] - V(000F00,00,2,0,0,0,0,None), // #195 [ref=1x] - V(660F00,00,0,0,0,0,2,None), // #196 [ref=1x] - V(F20F00,00,0,0,0,1,3,DUP ), // #197 [ref=1x] - E(660F00,00,0,0,0,0,4,ByLL), // #198 [ref=6x] - V(F30F00,00,0,0,0,0,0,None), // #199 [ref=3x] - E(F30F00,00,0,0,0,0,4,ByLL), // #200 [ref=1x] - V(000F00,00,0,0,0,0,3,None), // #201 [ref=2x] - E(66MAP5,00,0,0,0,0,1,None), // #202 [ref=1x] - E(F20F38,00,0,0,0,1,4,ByLL), // #203 [ref=1x] - V(660F3A,00,0,0,0,0,4,ByLL), // #204 [ref=2x] - E(F30F38,00,0,0,0,1,0,None), // #205 [ref=5x] - E(F30F38,00,0,0,0,0,0,None), // #206 [ref=5x] - V(660F38,00,0,0,0,0,1,None), // #207 [ref=1x] - V(XOP_M8,00,0,0,0,0,0,None), // #208 [ref=22x] - V(660F38,00,0,0,0,1,4,ByLL), // #209 [ref=4x] - E(660F38,00,0,0,0,0,0,None), // #210 [ref=2x] - E(660F38,00,0,0,0,1,1,None), // #211 [ref=2x] - E(660F38,00,0,0,1,1,4,ByLL), // #212 [ref=1x] - V(660F3A,00,0,0,1,1,3,None), // #213 [ref=2x] - V(660F3A,00,0,0,0,0,1,None), // #214 [ref=1x] - V(660F00,00,0,0,0,0,1,None), // #215 [ref=1x] - E(F30F38,00,0,0,0,0,2,ByLL), // #216 [ref=6x] - E(F30F38,00,0,0,0,0,3,ByLL), // #217 [ref=9x] - E(F30F38,00,0,0,0,0,1,ByLL), // #218 [ref=3x] - V(660F38,00,0,0,0,0,2,ByLL), // #219 [ref=4x] - V(660F38,00,0,0,0,0,1,ByLL), // #220 [ref=2x] - E(660F00,00,1,0,0,0,4,ByLL), // #221 [ref=1x] - E(660F00,00,1,0,0,1,4,ByLL), // #222 [ref=1x] - V(F20F00,00,0,0,0,0,4,ByLL), // #223 [ref=1x] - V(660F00,00,0,0,0,0,4,None), // #224 [ref=6x] - V(660F00,00,7,0,0,0,4,ByLL), // #225 [ref=1x] - V(660F00,00,0,0,0,1,4,None), // #226 [ref=2x] - E(660F00,00,0,0,0,1,4,None), // #227 [ref=1x] - V(660F00,00,3,0,0,0,4,ByLL), // #228 [ref=1x] - E(F30F38,00,0,0,0,1,4,ByLL), // #229 [ref=2x] - E(660F38,00,5,2,0,1,3,None), // #230 [ref=2x] - E(660F38,00,5,2,0,0,2,None), // #231 [ref=2x] - E(660F38,00,6,2,0,1,3,None), // #232 [ref=2x] - E(660F38,00,6,2,0,0,2,None), // #233 [ref=2x] - V(000F00,00,3,0,0,0,0,None), // #234 [ref=1x] - O(F30F00,00,2,0,0,0,0,0 ), // #235 [ref=1x] - O(F30F00,00,3,0,0,0,0,0 ), // #236 [ref=1x] - O(000F38,00,0,0,1,0,0,0 ), // #237 [ref=1x] - O(660F38,00,0,0,1,0,0,0 ), // #238 [ref=1x] - O(000F00,00,5,0,1,0,0,0 ), // #239 [ref=2x] - O(000F00,00,3,0,1,0,0,0 ), // #240 [ref=1x] - O(000F00,00,4,0,1,0,0,0 ), // #241 [ref=2x] - O(000F00,00,6,0,1,0,0,0 ) // #242 [ref=1x] + O(000F38,00,0,0,0,0,0,0 ), // #1 [ref=25x] + O(660F38,00,0,0,0,0,0,0 ), // #2 [ref=44x] + O(000000,00,2,0,0,0,0,0 ), // #3 [ref=4x] + O(660F00,00,0,0,0,0,0,0 ), // #4 [ref=38x] + O(000F00,00,0,0,0,0,0,0 ), // #5 [ref=231x] + O(F20F00,00,0,0,0,0,0,0 ), // #6 [ref=24x] + O(F30F00,00,0,0,0,0,0,0 ), // #7 [ref=29x] + O(F30F38,00,0,0,0,0,0,0 ), // #8 [ref=3x] + O(660F3A,00,0,0,0,0,0,0 ), // #9 [ref=22x] + O(000000,00,4,0,0,0,0,0 ), // #10 [ref=5x] + V(000F38,00,0,0,0,0,0,None), // #11 [ref=13x] + O(F20F38,00,0,0,0,0,0,0 ), // #12 [ref=3x] + V(XOP_M9,00,1,0,0,0,0,None), // #13 [ref=3x] + V(XOP_M9,00,6,0,0,0,0,None), // #14 [ref=2x] + V(XOP_M9,00,5,0,0,0,0,None), // #15 [ref=1x] + V(XOP_M9,00,3,0,0,0,0,None), // #16 [ref=1x] + V(XOP_M9,00,2,0,0,0,0,None), // #17 [ref=1x] + V(000F38,00,3,0,0,0,0,None), // #18 [ref=1x] + V(000F38,00,2,0,0,0,0,None), // #19 [ref=1x] + V(000F38,00,1,0,0,0,0,None), // #20 [ref=1x] + O(660000,00,0,0,0,0,0,0 ), // #21 [ref=7x] + O(000000,00,0,0,1,0,0,0 ), // #22 [ref=3x] + O(000F01,00,0,0,0,0,0,0 ), // #23 [ref=32x] + O(000F00,00,7,0,0,0,0,0 ), // #24 [ref=6x] + O(660F00,00,7,0,0,0,0,0 ), // #25 [ref=1x] + O(F30F00,00,6,0,0,0,0,0 ), // #26 [ref=4x] + O(F30F01,00,0,0,0,0,0,0 ), // #27 [ref=9x] + O(660F00,00,6,0,0,0,0,0 ), // #28 [ref=3x] + O(000000,00,7,0,0,0,0,0 ), // #29 [ref=5x] + V(660F38,00,0,0,0,0,0,None), // #30 [ref=48x] + O(000F00,00,1,0,1,0,0,0 ), // #31 [ref=2x] + O(000F00,00,1,0,0,0,0,0 ), // #32 [ref=6x] + O(000000,00,1,0,0,0,0,0 ), // #33 [ref=3x] + O(000000,00,6,0,0,0,0,0 ), // #34 [ref=3x] + O(F30F00,00,7,0,0,0,0,3 ), // #35 [ref=1x] + O(F30F00,00,7,0,0,0,0,2 ), // #36 [ref=1x] + O_FPU(00,D900,0) , // #37 [ref=29x] + O_FPU(00,C000,0) , // #38 [ref=1x] + O_FPU(00,DE00,0) , // #39 [ref=7x] + O_FPU(00,0000,4) , // #40 [ref=4x] + O_FPU(00,0000,6) , // #41 [ref=4x] + O_FPU(9B,DB00,0) , // #42 [ref=2x] + O_FPU(00,DA00,0) , // #43 [ref=5x] + O_FPU(00,DB00,0) , // #44 [ref=8x] + O_FPU(00,D000,2) , // #45 [ref=1x] + O_FPU(00,DF00,0) , // #46 [ref=2x] + O_FPU(00,D800,3) , // #47 [ref=1x] + O_FPU(00,F000,6) , // #48 [ref=1x] + O_FPU(00,F800,7) , // #49 [ref=1x] + O_FPU(00,DD00,0) , // #50 [ref=3x] + O_FPU(00,0000,0) , // #51 [ref=4x] + O_FPU(00,0000,2) , // #52 [ref=3x] + O_FPU(00,0000,3) , // #53 [ref=3x] + O_FPU(00,0000,7) , // #54 [ref=3x] + O_FPU(00,0000,1) , // #55 [ref=2x] + O_FPU(00,0000,5) , // #56 [ref=2x] + O_FPU(00,C800,1) , // #57 [ref=1x] + O_FPU(9B,0000,6) , // #58 [ref=2x] + O_FPU(9B,0000,7) , // #59 [ref=2x] + O_FPU(00,E000,4) , // #60 [ref=1x] + O_FPU(00,E800,5) , // #61 [ref=1x] + O(000F00,00,0,0,1,0,0,0 ), // #62 [ref=3x] + O(F30F3A,00,0,0,0,0,0,0 ), // #63 [ref=1x] + O(000000,00,5,0,0,0,0,0 ), // #64 [ref=4x] + O(F30F00,00,5,0,0,0,0,0 ), // #65 [ref=2x] + O(F30F00,00,5,0,1,0,0,0 ), // #66 [ref=1x] + V(660F00,00,0,1,0,0,0,None), // #67 [ref=7x] + V(660F00,00,0,1,1,0,0,None), // #68 [ref=6x] + V(000F00,00,0,1,1,0,0,None), // #69 [ref=7x] + V(000F00,00,0,1,0,0,0,None), // #70 [ref=8x] + V(660F00,00,0,0,0,0,0,None), // #71 [ref=15x] + V(660F00,00,0,0,1,0,0,None), // #72 [ref=4x] + V(000F00,00,0,0,1,0,0,None), // #73 [ref=4x] + V(000F00,00,0,0,0,0,0,None), // #74 [ref=10x] + V(660F3A,00,0,0,0,0,0,None), // #75 [ref=48x] + V(660F3A,00,0,0,1,0,0,None), // #76 [ref=4x] + O(000000,00,3,0,0,0,0,0 ), // #77 [ref=4x] + O(000F00,00,2,0,0,0,0,0 ), // #78 [ref=5x] + O(000F00,00,5,0,0,0,0,0 ), // #79 [ref=4x] + O(000F00,00,3,0,0,0,0,0 ), // #80 [ref=5x] + V(XOP_M9,00,0,0,0,0,0,None), // #81 [ref=32x] + O(000F00,00,6,0,0,0,0,0 ), // #82 [ref=6x] + V(XOP_MA,00,0,0,0,0,0,None), // #83 [ref=1x] + V(XOP_MA,00,1,0,0,0,0,None), // #84 [ref=1x] + V(F20F38,00,0,0,0,0,0,None), // #85 [ref=11x] + O(000F3A,00,0,0,0,0,0,0 ), // #86 [ref=4x] + O(F30000,00,0,0,0,0,0,0 ), // #87 [ref=1x] + O(000F0F,00,0,0,0,0,0,0 ), // #88 [ref=26x] + V(F30F38,00,0,0,0,0,0,None), // #89 [ref=12x] + O(000F3A,00,0,0,1,0,0,0 ), // #90 [ref=1x] + O(660F3A,00,0,0,1,0,0,0 ), // #91 [ref=1x] + O(F30F00,00,4,0,0,0,0,0 ), // #92 [ref=1x] + O(F20F01,00,0,0,0,0,0,0 ), // #93 [ref=5x] + O(F30F00,00,1,0,0,0,0,0 ), // #94 [ref=3x] + O(F30F00,00,7,0,0,0,0,0 ), // #95 [ref=1x] + V(F20F3A,00,0,0,0,0,0,None), // #96 [ref=1x] + O(660F01,00,0,0,0,0,0,0 ), // #97 [ref=4x] + O(000F00,00,4,0,0,0,0,0 ), // #98 [ref=4x] + V(XOP_M9,00,7,0,0,0,0,None), // #99 [ref=1x] + V(XOP_M9,00,4,0,0,0,0,None), // #100 [ref=1x] + O(F20F00,00,6,0,0,0,0,0 ), // #101 [ref=1x] + E(F20F38,00,0,2,0,0,4,None), // #102 [ref=4x] + E(F20F38,00,0,0,0,0,4,None), // #103 [ref=2x] + V(660F00,00,0,0,0,1,4,ByLL), // #104 [ref=25x] + E(00MAP5,00,0,0,0,0,4,ByLL), // #105 [ref=10x] + V(000F00,00,0,0,0,0,4,ByLL), // #106 [ref=19x] + V(F20F00,00,0,0,0,1,3,None), // #107 [ref=10x] + E(F3MAP5,00,0,0,0,0,1,None), // #108 [ref=13x] + V(F30F00,00,0,0,0,0,2,None), // #109 [ref=12x] + V(F20F00,00,0,0,0,0,0,None), // #110 [ref=4x] + V(660F38,00,0,0,0,0,4,ByLL), // #111 [ref=50x] + E(660F3A,00,0,0,0,0,4,ByLL), // #112 [ref=17x] + E(660F3A,00,0,0,0,1,4,ByLL), // #113 [ref=18x] + E(660F38,00,0,0,0,1,4,ByLL), // #114 [ref=38x] + E(660F38,00,0,0,0,0,4,ByLL), // #115 [ref=25x] + V(660F38,00,0,1,0,0,0,None), // #116 [ref=2x] + E(660F38,00,0,0,0,0,3,None), // #117 [ref=2x] + E(660F38,00,0,0,0,0,4,None), // #118 [ref=2x] + E(660F38,00,0,2,0,0,5,None), // #119 [ref=2x] + E(660F38,00,0,0,0,1,4,None), // #120 [ref=2x] + E(660F38,00,0,2,0,1,5,None), // #121 [ref=2x] + V(660F38,00,0,0,0,1,3,None), // #122 [ref=2x] + V(660F38,00,0,0,0,0,2,None), // #123 [ref=14x] + E(000F3A,00,0,0,0,0,4,ByLL), // #124 [ref=5x] + E(F30F3A,00,0,0,0,0,1,None), // #125 [ref=1x] + V(660F00,00,0,0,0,1,3,None), // #126 [ref=5x] + E(00MAP5,00,0,0,0,0,1,None), // #127 [ref=2x] + V(000F00,00,0,0,0,0,2,None), // #128 [ref=2x] + E(660F38,00,0,0,0,1,3,None), // #129 [ref=14x] + E(660F38,00,0,0,0,0,2,None), // #130 [ref=14x] + V(F30F00,00,0,0,0,0,3,ByLL), // #131 [ref=1x] + E(F20F38,00,0,0,0,0,4,ByLL), // #132 [ref=2x] + V(F30F38,00,0,0,0,0,4,ByLL), // #133 [ref=1x] + V(F20F00,00,0,0,0,1,4,ByLL), // #134 [ref=1x] + E(66MAP5,00,0,0,0,1,4,ByLL), // #135 [ref=1x] + E(660F00,00,0,0,0,1,4,ByLL), // #136 [ref=10x] + E(000F00,00,0,0,0,1,4,ByLL), // #137 [ref=3x] + E(66MAP5,00,0,0,0,0,3,ByLL), // #138 [ref=1x] + E(00MAP5,00,0,0,0,0,2,ByLL), // #139 [ref=1x] + V(660F38,00,0,0,0,0,3,ByLL), // #140 [ref=7x] + E(66MAP6,00,0,0,0,0,3,ByLL), // #141 [ref=1x] + E(66MAP5,00,0,0,0,0,2,ByLL), // #142 [ref=4x] + E(00MAP5,00,0,0,0,0,3,ByLL), // #143 [ref=2x] + E(66MAP5,00,0,0,0,0,4,ByLL), // #144 [ref=3x] + V(660F00,00,0,0,0,0,4,ByLL), // #145 [ref=43x] + V(000F00,00,0,0,0,0,3,ByLL), // #146 [ref=1x] + V(660F3A,00,0,0,0,0,3,ByLL), // #147 [ref=1x] + E(660F00,00,0,0,0,0,3,ByLL), // #148 [ref=4x] + E(000F00,00,0,0,0,0,4,ByLL), // #149 [ref=2x] + E(F30F00,00,0,0,0,1,4,ByLL), // #150 [ref=3x] + E(00MAP5,00,0,0,0,1,4,ByLL), // #151 [ref=1x] + E(F2MAP5,00,0,0,0,1,3,None), // #152 [ref=1x] + V(F20F00,00,0,0,0,0,3,None), // #153 [ref=2x] + E(F20F00,00,0,0,0,0,3,None), // #154 [ref=2x] + E(00MAP6,00,0,0,0,0,1,None), // #155 [ref=1x] + V(F20F00,00,0,0,0,0,2,T1W ), // #156 [ref=1x] + E(F3MAP5,00,0,0,0,0,2,T1W ), // #157 [ref=2x] + V(F30F00,00,0,0,0,0,2,T1W ), // #158 [ref=1x] + E(00MAP5,00,0,0,0,0,2,None), // #159 [ref=1x] + E(F30F00,00,0,0,0,0,2,None), // #160 [ref=2x] + E(F3MAP5,00,0,0,0,0,3,ByLL), // #161 [ref=1x] + V(F30F00,00,0,0,0,0,4,ByLL), // #162 [ref=4x] + E(F30F00,00,0,0,0,0,3,ByLL), // #163 [ref=1x] + E(F2MAP5,00,0,0,0,0,4,ByLL), // #164 [ref=2x] + E(F20F00,00,0,0,0,0,4,ByLL), // #165 [ref=2x] + E(F2MAP5,00,0,0,0,1,4,ByLL), // #166 [ref=1x] + E(F20F00,00,0,0,0,1,4,ByLL), // #167 [ref=2x] + E(F20F00,00,0,0,0,0,2,T1W ), // #168 [ref=1x] + E(F30F00,00,0,0,0,0,2,T1W ), // #169 [ref=1x] + E(F3MAP5,00,0,0,0,0,4,ByLL), // #170 [ref=1x] + E(F30F38,00,0,0,0,0,4,ByLL), // #171 [ref=3x] + E(660F38,00,0,2,0,1,4,ByLL), // #172 [ref=3x] + E(660F38,00,0,2,0,0,4,ByLL), // #173 [ref=3x] + V(660F3A,00,0,1,0,0,0,None), // #174 [ref=6x] + E(660F3A,00,0,0,0,0,4,None), // #175 [ref=4x] + E(660F3A,00,0,2,0,0,5,None), // #176 [ref=4x] + E(660F3A,00,0,0,0,1,4,None), // #177 [ref=4x] + E(660F3A,00,0,2,0,1,5,None), // #178 [ref=4x] + V(660F3A,00,0,0,0,0,2,None), // #179 [ref=4x] + E(F2MAP6,00,0,0,0,0,4,ByLL), // #180 [ref=2x] + E(F2MAP6,00,0,0,0,0,2,None), // #181 [ref=2x] + E(660F3A,00,0,0,0,1,3,None), // #182 [ref=6x] + E(660F3A,00,0,0,0,0,2,None), // #183 [ref=6x] + V(660F38,00,0,0,1,1,4,ByLL), // #184 [ref=22x] + E(66MAP6,00,0,0,0,0,4,ByLL), // #185 [ref=22x] + V(660F38,00,0,0,1,1,3,None), // #186 [ref=12x] + E(66MAP6,00,0,0,0,0,1,None), // #187 [ref=16x] + E(F3MAP6,00,0,0,0,0,4,ByLL), // #188 [ref=2x] + E(F3MAP6,00,0,0,0,0,2,None), // #189 [ref=2x] + E(000F3A,00,0,0,0,0,1,None), // #190 [ref=4x] + V(660F38,00,0,0,1,0,0,None), // #191 [ref=5x] + E(660F38,00,1,2,0,1,3,None), // #192 [ref=2x] + E(660F38,00,1,2,0,0,2,None), // #193 [ref=2x] + E(660F38,00,2,2,0,1,3,None), // #194 [ref=2x] + E(660F38,00,2,2,0,0,2,None), // #195 [ref=2x] + V(660F3A,00,0,0,1,1,4,ByLL), // #196 [ref=2x] + V(000F00,00,2,0,0,0,0,None), // #197 [ref=1x] + V(660F00,00,0,0,0,0,2,None), // #198 [ref=1x] + V(F20F00,00,0,0,0,1,3,DUP ), // #199 [ref=1x] + E(660F00,00,0,0,0,0,4,ByLL), // #200 [ref=6x] + V(F30F00,00,0,0,0,0,0,None), // #201 [ref=3x] + E(F30F00,00,0,0,0,0,4,ByLL), // #202 [ref=1x] + V(000F00,00,0,0,0,0,3,None), // #203 [ref=2x] + E(66MAP5,00,0,0,0,0,1,None), // #204 [ref=1x] + E(F20F38,00,0,0,0,1,4,ByLL), // #205 [ref=1x] + V(660F3A,00,0,0,0,0,4,ByLL), // #206 [ref=2x] + E(F30F38,00,0,0,0,1,0,None), // #207 [ref=5x] + E(F30F38,00,0,0,0,0,0,None), // #208 [ref=5x] + V(660F38,00,0,0,0,0,1,None), // #209 [ref=1x] + V(XOP_M8,00,0,0,0,0,0,None), // #210 [ref=22x] + V(660F38,00,0,0,0,1,4,ByLL), // #211 [ref=4x] + E(660F38,00,0,0,0,0,0,None), // #212 [ref=2x] + E(660F38,00,0,0,0,1,1,None), // #213 [ref=2x] + E(660F38,00,0,0,1,1,4,ByLL), // #214 [ref=1x] + V(660F3A,00,0,0,1,1,3,None), // #215 [ref=2x] + V(660F3A,00,0,0,0,0,1,None), // #216 [ref=1x] + V(660F00,00,0,0,0,0,1,None), // #217 [ref=1x] + E(F30F38,00,0,0,0,0,2,ByLL), // #218 [ref=6x] + E(F30F38,00,0,0,0,0,3,ByLL), // #219 [ref=9x] + E(F30F38,00,0,0,0,0,1,ByLL), // #220 [ref=3x] + V(660F38,00,0,0,0,0,2,ByLL), // #221 [ref=4x] + V(660F38,00,0,0,0,0,1,ByLL), // #222 [ref=2x] + E(660F00,00,1,0,0,0,4,ByLL), // #223 [ref=1x] + E(660F00,00,1,0,0,1,4,ByLL), // #224 [ref=1x] + V(F20F00,00,0,0,0,0,4,ByLL), // #225 [ref=1x] + V(660F00,00,0,0,0,0,4,None), // #226 [ref=6x] + V(660F00,00,7,0,0,0,4,ByLL), // #227 [ref=1x] + V(660F00,00,0,0,0,1,4,None), // #228 [ref=2x] + E(660F00,00,0,0,0,1,4,None), // #229 [ref=1x] + V(660F00,00,3,0,0,0,4,ByLL), // #230 [ref=1x] + E(F30F38,00,0,0,0,1,4,ByLL), // #231 [ref=2x] + E(660F38,00,5,2,0,1,3,None), // #232 [ref=2x] + E(660F38,00,5,2,0,0,2,None), // #233 [ref=2x] + E(660F38,00,6,2,0,1,3,None), // #234 [ref=2x] + E(660F38,00,6,2,0,0,2,None), // #235 [ref=2x] + V(F20F38,00,0,1,0,0,0,None), // #236 [ref=3x] + V(000F00,00,3,0,0,0,0,None), // #237 [ref=1x] + O(F30F00,00,2,0,0,0,0,0 ), // #238 [ref=1x] + O(F30F00,00,3,0,0,0,0,0 ), // #239 [ref=1x] + O(000F38,00,0,0,1,0,0,0 ), // #240 [ref=1x] + O(660F38,00,0,0,1,0,0,0 ), // #241 [ref=1x] + O(000F00,00,5,0,1,0,0,0 ), // #242 [ref=2x] + O(000F00,00,3,0,1,0,0,0 ), // #243 [ref=1x] + O(000F00,00,4,0,1,0,0,0 ), // #244 [ref=2x] + O(000F00,00,6,0,1,0,0,0 ) // #245 [ref=1x] }; // ---------------------------------------------------------------------------- // ${MainOpcodeTable:End} @@ -1996,7 +2032,7 @@ const uint32_t InstDB::_mainOpcodeTable[] = { // ${AltOpcodeTable:Begin} // ------------------- Automatically generated, do not edit ------------------- const uint32_t InstDB::_altOpcodeTable[] = { - O(000000,00,0,0,0,0,0,0 ), // #0 [ref=1514x] + O(000000,00,0,0,0,0,0,0 ), // #0 [ref=1573x] O(660F00,1B,0,0,0,0,0,0 ), // #1 [ref=1x] O(000F00,BA,4,0,0,0,0,0 ), // #2 [ref=1x] O(000F00,BA,7,0,0,0,0,0 ), // #3 [ref=1x] @@ -2151,449 +2187,460 @@ const uint32_t InstDB::_altOpcodeTable[] = { #define SAME_REG_HINT(VAL) uint8_t(InstSameRegHint::k##VAL) const InstDB::CommonInfo InstDB::_commonInfoTable[] = { { 0 , 0 , 0 , 0 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #0 [ref=1x] - { 0 , 0 , 383, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #1 [ref=4x] - { 0 , 0 , 384, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #2 [ref=2x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #3 [ref=2x] - { 0 , 0 , 180, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #4 [ref=2x] - { F(Vec) , 0 , 79 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #5 [ref=54x] - { F(Vec) , 0 , 106, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #6 [ref=19x] - { F(Vec) , 0 , 212, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #7 [ref=16x] - { F(Vec) , 0 , 221, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #8 [ref=20x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 28 , 11, CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #9 [ref=1x] - { F(Vex) , 0 , 275, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #10 [ref=3x] - { F(Vec) , 0 , 79 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #11 [ref=12x] - { 0 , 0 , 385, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #12 [ref=1x] - { F(Vex) , 0 , 277, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #13 [ref=5x] - { F(Vex) , 0 , 180, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #14 [ref=12x] - { F(Vec) , 0 , 386, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #15 [ref=4x] - { 0 , 0 , 279, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #16 [ref=3x] - { F(Mib) , 0 , 387, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #17 [ref=1x] - { 0 , 0 , 388, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #18 [ref=1x] - { 0 , 0 , 281, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #19 [ref=1x] - { F(Mib) , 0 , 389, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #20 [ref=1x] - { 0 , 0 , 283, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #21 [ref=1x] - { 0 , 0 , 179, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #22 [ref=35x] - { 0 , 0 , 390, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #23 [ref=3x] - { 0 , 0 , 123, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #24 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 123, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #25 [ref=3x] - { F(Rep)|F(RepIgnored) , 0 , 285, 2 , CONTROL_FLOW(Call), SAME_REG_HINT(None)}, // #26 [ref=1x] - { 0 , 0 , 391, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #27 [ref=1x] - { 0 , 0 , 392, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #28 [ref=2x] - { 0 , 0 , 364, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #29 [ref=1x] - { 0 , 0 , 108, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #30 [ref=83x] - { 0 , 0 , 393, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #31 [ref=11x] - { 0 , 0 , 394, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #32 [ref=6x] - { 0 , 0 , 395, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #33 [ref=13x] - { 0 , 0 , 396, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #34 [ref=1x] - { 0 , 0 , 16 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #35 [ref=1x] - { F(Rep) , 0 , 127, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #36 [ref=1x] - { F(Vec) , 0 , 397, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #37 [ref=2x] - { F(Vec) , 0 , 398, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #38 [ref=3x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 131, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #39 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 399, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #40 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 400, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #41 [ref=1x] - { 0 , 0 , 401, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #42 [ref=1x] - { 0 , 0 , 402, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #43 [ref=1x] - { 0 , 0 , 287, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #44 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 403, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #45 [ref=2x] - { F(Mmx)|F(Vec) , 0 , 404, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #46 [ref=2x] - { F(Mmx)|F(Vec) , 0 , 405, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #47 [ref=2x] - { F(Vec) , 0 , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #48 [ref=2x] - { F(Vec) , 0 , 407, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #49 [ref=2x] - { F(Vec) , 0 , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #50 [ref=2x] - { 0 , 0 , 409, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #51 [ref=1x] - { 0 , 0 , 410, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #52 [ref=2x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 289, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #53 [ref=2x] - { 0 , 0 , 39 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #54 [ref=3x] - { F(Mmx) , 0 , 108, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #55 [ref=1x] - { 0 , 0 , 291, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #56 [ref=2x] - { 0 , 0 , 411, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #57 [ref=1x] - { F(Vec) , 0 , 412, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #58 [ref=2x] - { F(Vec) , 0 , 293, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #59 [ref=1x] - { F(FpuM32)|F(FpuM64) , 0 , 182, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #60 [ref=6x] - { 0 , 0 , 295, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #61 [ref=9x] - { F(FpuM80) , 0 , 413, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #62 [ref=2x] - { 0 , 0 , 296, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #63 [ref=13x] - { F(FpuM32)|F(FpuM64) , 0 , 297, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #64 [ref=2x] - { F(FpuM16)|F(FpuM32) , 0 , 414, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #65 [ref=9x] - { F(FpuM16)|F(FpuM32)|F(FpuM64) , 0 , 415, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #66 [ref=3x] - { F(FpuM32)|F(FpuM64)|F(FpuM80) , 0 , 416, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #67 [ref=2x] - { F(FpuM16) , 0 , 417, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #68 [ref=3x] - { 0 , 0 , 418, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #69 [ref=13x] - { F(FpuM16) , 0 , 419, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #70 [ref=2x] - { F(FpuM32)|F(FpuM64) , 0 , 298, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #71 [ref=1x] - { 0 , 0 , 420, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #72 [ref=2x] - { 0 , 0 , 421, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #73 [ref=1x] - { 0 , 0 , 39 , 10, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #74 [ref=1x] - { 0 , 0 , 422, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #75 [ref=1x] - { 0 , 0 , 423, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #76 [ref=2x] - { 0 , 0 , 348, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #77 [ref=3x] - { F(Rep) , 0 , 424, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #78 [ref=1x] - { F(Vec) , 0 , 299, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #79 [ref=1x] - { 0 , 0 , 425, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #80 [ref=2x] - { 0 , 0 , 426, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #81 [ref=8x] - { 0 , 0 , 301, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #82 [ref=3x] - { 0 , 0 , 303, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #83 [ref=1x] - { 0 , 0 , 108, 1 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #84 [ref=2x] - { 0 , 0 , 395, 1 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #85 [ref=1x] - { F(Rep)|F(RepIgnored) , 0 , 305, 2 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #86 [ref=30x] - { F(Rep)|F(RepIgnored) , 0 , 307, 2 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #87 [ref=1x] - { F(Rep)|F(RepIgnored) , 0 , 309, 2 , CONTROL_FLOW(Jump), SAME_REG_HINT(None)}, // #88 [ref=1x] - { F(Vex) , 0 , 427, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #89 [ref=19x] - { F(Vex) , 0 , 311, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #90 [ref=1x] - { F(Vex) , 0 , 313, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #91 [ref=1x] - { F(Vex) , 0 , 315, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #92 [ref=1x] - { F(Vex) , 0 , 317, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #93 [ref=1x] - { F(Vex) , 0 , 428, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #94 [ref=12x] - { F(Vex) , 0 , 429, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #95 [ref=8x] - { F(Vex) , 0 , 427, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #96 [ref=8x] - { 0 , 0 , 430, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #97 [ref=2x] - { 0 , 0 , 319, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #98 [ref=1x] - { 0 , 0 , 321, 2 , CONTROL_FLOW(Call), SAME_REG_HINT(None)}, // #99 [ref=1x] - { F(Vec) , 0 , 230, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #100 [ref=2x] - { 0 , 0 , 431, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #101 [ref=2x] - { 0 , 0 , 323, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #102 [ref=2x] - { F(Vex) , 0 , 432, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #103 [ref=2x] - { 0 , 0 , 433, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #104 [ref=1x] - { 0 , 0 , 185, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #105 [ref=3x] - { 0 , 0 , 321, 2 , CONTROL_FLOW(Jump), SAME_REG_HINT(None)}, // #106 [ref=1x] - { 0 , 0 , 434, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #107 [ref=5x] - { F(Vex) , 0 , 435, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #108 [ref=2x] - { F(Rep) , 0 , 135, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #109 [ref=1x] - { 0 , 0 , 307, 2 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #110 [ref=3x] - { 0 , 0 , 325, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #111 [ref=1x] - { F(Vex) , 0 , 436, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #112 [ref=2x] - { F(Vec) , 0 , 437, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #113 [ref=1x] - { F(Mmx) , 0 , 438, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #114 [ref=1x] - { 0 , 0 , 439, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #115 [ref=2x] - { F(XRelease) , 0 , 0 , 16, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #116 [ref=1x] - { 0 , 0 , 49 , 9 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #117 [ref=1x] - { F(Vec) , 0 , 79 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #118 [ref=6x] - { 0 , 0 , 73 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #119 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 327, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #120 [ref=1x] - { 0 , 0 , 440, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #121 [ref=1x] - { 0 , 0 , 77 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #122 [ref=2x] - { F(Mmx)|F(Vec) , 0 , 441, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #123 [ref=1x] - { F(Vec) , 0 , 294, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #124 [ref=2x] - { F(Vec) , 0 , 236, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #125 [ref=4x] - { F(Vec) , 0 , 442, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #126 [ref=2x] - { F(Vec) , 0 , 80 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #127 [ref=3x] - { F(Mmx) , 0 , 443, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #128 [ref=1x] - { F(Vec) , 0 , 107, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #129 [ref=1x] - { F(Vec) , 0 , 242, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #130 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 103, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #131 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 444, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #132 [ref=1x] - { F(Rep) , 0 , 139, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #133 [ref=1x] - { F(Vec) , 0 , 106, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #134 [ref=1x] - { F(Vec) , 0 , 329, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #135 [ref=1x] - { 0 , 0 , 331, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #136 [ref=2x] - { 0 , 0 , 333, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #137 [ref=1x] - { F(Vex) , 0 , 335, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #138 [ref=1x] - { 0 , 0 , 445, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #139 [ref=1x] - { 0 , 0 , 446, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #140 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 290, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #141 [ref=2x] - { 0 , 0 , 108, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #142 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #143 [ref=1x] - { 0 , 0 , 447, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #144 [ref=1x] - { F(Rep) , 0 , 448, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #145 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 337, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #146 [ref=37x] - { F(Mmx)|F(Vec) , 0 , 339, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #147 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 337, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #148 [ref=6x] - { F(Mmx)|F(Vec) , 0 , 337, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #149 [ref=16x] - { F(Mmx) , 0 , 337, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #150 [ref=26x] - { F(Vec) , 0 , 79 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #151 [ref=4x] - { F(Vec) , 0 , 449, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #152 [ref=1x] - { F(Vec) , 0 , 450, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #153 [ref=1x] - { F(Vec) , 0 , 451, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #154 [ref=1x] - { F(Vec) , 0 , 452, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #155 [ref=1x] - { F(Vec) , 0 , 453, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #156 [ref=1x] - { F(Vec) , 0 , 454, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #157 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 341, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #158 [ref=1x] - { F(Vec) , 0 , 455, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #159 [ref=1x] - { F(Vec) , 0 , 456, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #160 [ref=1x] - { F(Vec) , 0 , 457, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #161 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 458, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #162 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 459, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #163 [ref=1x] - { F(Vec) , 0 , 263, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #164 [ref=2x] - { 0 , 0 , 143, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #165 [ref=1x] - { F(Mmx) , 0 , 339, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #166 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 343, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #167 [ref=8x] - { F(Vec) , 0 , 460, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #168 [ref=2x] - { 0 , 0 , 461, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #169 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 345, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #170 [ref=3x] - { 0 , 0 , 147, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #171 [ref=1x] - { 0 , 0 , 462, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #172 [ref=8x] - { 0 , 0 , 463, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #173 [ref=4x] - { 0 , 0 , 464, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #174 [ref=8x] - { 0 , 0 , 347, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #175 [ref=1x] - { F(Rep)|F(RepIgnored) , 0 , 349, 2 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #176 [ref=1x] - { 0 , 0 , 349, 2 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #177 [ref=1x] - { F(Vex) , 0 , 351, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #178 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #179 [ref=3x] - { F(Rep) , 0 , 151, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #180 [ref=1x] - { 0 , 0 , 465, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #181 [ref=30x] - { 0 , 0 , 188, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #182 [ref=2x] - { 0 , 0 , 466, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #183 [ref=3x] - { F(Rep) , 0 , 155, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #184 [ref=1x] - { F(Vex) , 0 , 467, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #185 [ref=5x] - { 0 , 0 , 66 , 7 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #186 [ref=1x] - { F(Tsib)|F(Vex) , 0 , 468, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #187 [ref=2x] - { F(Vex) , 0 , 395, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #188 [ref=1x] - { F(Tsib)|F(Vex) , 0 , 469, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #189 [ref=1x] - { F(Vex) , 0 , 470, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #190 [ref=1x] - { 0 , 0 , 471, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #191 [ref=2x] - { 0 , 0 , 180, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #192 [ref=2x] - { 0 , 0 , 472, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #193 [ref=1x] - { F(Evex)|F(Vec) , X(K)|X(T4X)|X(Z) , 473, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #194 [ref=4x] - { F(Evex)|F(Vec) , X(K)|X(T4X)|X(Z) , 474, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #195 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #196 [ref=22x] - { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #197 [ref=23x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #198 [ref=22x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(K)|X(SAE)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #199 [ref=18x] - { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 476, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #200 [ref=18x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(K)|X(SAE)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #201 [ref=17x] - { F(Vec)|F(Vex) , 0 , 191, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #202 [ref=15x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #203 [ref=5x] - { F(Vec)|F(Vex) , 0 , 79 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #204 [ref=17x] - { F(Vec)|F(Vex) , 0 , 221, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #205 [ref=1x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #206 [ref=4x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #207 [ref=4x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #208 [ref=10x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #209 [ref=12x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #210 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #211 [ref=6x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #212 [ref=19x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #213 [ref=12x] - { F(Vec)|F(Vex) , 0 , 194, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #214 [ref=6x] - { F(Vec)|F(Vex) , 0 , 353, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #215 [ref=3x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 478, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #216 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 479, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #217 [ref=1x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 480, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #218 [ref=4x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 481, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #219 [ref=4x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 482, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #220 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 479, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #221 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 483, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #222 [ref=1x] - { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B64)|X(K)|X(SAE)|X(Z) , 197, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #223 [ref=1x] - { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE) , 200, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #224 [ref=1x] - { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B32)|X(K)|X(SAE)|X(Z) , 197, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #225 [ref=1x] - { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 484, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #226 [ref=1x] - { F(Evex)|F(Vec) , X(K)|X(SAE) , 485, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #227 [ref=1x] - { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 486, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #228 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 106, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #229 [ref=2x] - { F(Evex)|F(Vec) , X(SAE) , 263, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #230 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 212, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #231 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 203, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #232 [ref=6x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #233 [ref=1x] - { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #234 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #235 [ref=3x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #236 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #237 [ref=2x] - { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 487, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #238 [ref=3x] - { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #239 [ref=4x] - { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #240 [ref=3x] - { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #241 [ref=2x] - { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 212, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #242 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #243 [ref=1x] - { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #244 [ref=3x] - { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 212, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #245 [ref=2x] - { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #246 [ref=5x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #247 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 215, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #248 [ref=1x] - { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #249 [ref=2x] - { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #250 [ref=2x] - { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #251 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #252 [ref=1x] - { F(Evex)|F(Vec) , X(ER)|X(SAE) , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #253 [ref=1x] - { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 476, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #254 [ref=5x] - { F(Evex)|F(Vec) , X(ER)|X(SAE) , 488, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #255 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 489, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #256 [ref=2x] - { F(Evex)|F(Vec) , X(ER)|X(SAE) , 489, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #257 [ref=4x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #258 [ref=3x] - { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #259 [ref=6x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #260 [ref=1x] - { F(Evex)|F(Vec) , X(ER)|X(SAE) , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #261 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #262 [ref=1x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #263 [ref=3x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #264 [ref=1x] - { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #265 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #266 [ref=1x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #267 [ref=2x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #268 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #269 [ref=1x] - { F(Evex)|F(Vec) , X(SAE) , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #270 [ref=1x] - { F(Evex)|F(Vec) , X(SAE) , 488, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #271 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #272 [ref=1x] - { F(Evex)|F(Vec) , X(SAE) , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #273 [ref=1x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #274 [ref=1x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #275 [ref=3x] - { F(Vec)|F(Vex) , 0 , 194, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #276 [ref=9x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 83 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #277 [ref=3x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 83 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #278 [ref=3x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #279 [ref=8x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 216, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #280 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 490, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #281 [ref=4x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 217, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #282 [ref=4x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 412, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #283 [ref=2x] - { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #284 [ref=5x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #285 [ref=2x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #286 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 491, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #287 [ref=4x] - { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #288 [ref=4x] - { F(Vec)|F(Vex) , 0 , 159, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #289 [ref=13x] - { F(Vec)|F(Vex) , 0 , 357, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #290 [ref=4x] - { F(Vec)|F(Vex) , 0 , 359, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #291 [ref=4x] - { F(Evex)|F(Vec) , X(B64)|X(K) , 493, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #292 [ref=1x] - { F(Evex)|F(Vec) , X(B16)|X(K) , 493, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #293 [ref=1x] - { F(Evex)|F(Vec) , X(B32)|X(K) , 493, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #294 [ref=1x] - { F(Evex)|F(Vec) , X(K) , 494, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #295 [ref=1x] - { F(Evex)|F(Vec) , X(K) , 495, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #296 [ref=1x] - { F(Evex)|F(Vec) , X(K) , 496, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #297 [ref=1x] - { F(Vec)|F(Vex) , 0 , 209, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #298 [ref=7x] - { F(Vec)|F(Vex) , 0 , 106, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #299 [ref=1x] - { F(Vec)|F(Vex) , 0 , 212, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #300 [ref=1x] - { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 163, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #301 [ref=2x] - { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 113, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #302 [ref=2x] - { F(Evex)|F(Vsib) , X(K) , 497, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #303 [ref=4x] - { F(Evex)|F(Vsib) , X(K) , 498, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #304 [ref=4x] - { F(Evex)|F(Vsib) , X(K) , 499, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #305 [ref=8x] - { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 118, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #306 [ref=2x] - { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 218, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #307 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #308 [ref=3x] - { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #309 [ref=3x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #310 [ref=2x] - { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #311 [ref=3x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #312 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 500, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #313 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #314 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #315 [ref=22x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 361, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #316 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 361, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #317 [ref=4x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 501, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #318 [ref=4x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #319 [ref=1x] - { F(Vec)|F(Vex) , 0 , 230, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #320 [ref=1x] - { F(Vex) , 0 , 431, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #321 [ref=2x] - { F(Vec)|F(Vex) , 0 , 437, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #322 [ref=1x] - { F(Vec)|F(Vex) , 0 , 167, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #323 [ref=4x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #324 [ref=2x] - { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #325 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #326 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #327 [ref=2x] - { 0 , 0 , 363, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #328 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 79 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #329 [ref=4x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 365, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #330 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 224, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #331 [ref=1x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 79 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #332 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 79 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #333 [ref=6x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 238, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #334 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 367, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #335 [ref=4x] - { F(Vec)|F(Vex) , 0 , 502, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #336 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 227, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #337 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 230, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #338 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 233, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #339 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 236, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #340 [ref=1x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 239, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #341 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #342 [ref=4x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 242, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #343 [ref=1x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 369, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #344 [ref=1x] - { 0 , 0 , 371, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #345 [ref=1x] - { 0 , 0 , 373, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #346 [ref=1x] - { F(Evex)|F(Vec) , X(B32) , 245, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #347 [ref=1x] - { F(Evex)|F(Vec) , X(B64) , 245, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #348 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #349 [ref=1x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #350 [ref=5x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 191, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #351 [ref=2x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #352 [ref=2x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 191, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #353 [ref=2x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #354 [ref=2x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #355 [ref=2x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #356 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #357 [ref=13x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 503, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #358 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 504, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #359 [ref=1x] - { F(Evex)|F(Vec) , 0 , 505, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #360 [ref=6x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 248, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #361 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 506, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #362 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #363 [ref=1x] - { F(Evex)|F(Vec) , X(K) , 200, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #364 [ref=2x] - { F(Evex)|F(Vec) , X(B32)|X(K) , 200, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #365 [ref=2x] - { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(K) , 251, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #366 [ref=4x] - { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B32)|X(K) , 251, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #367 [ref=2x] - { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B64)|X(K) , 251, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #368 [ref=2x] - { F(Vec)|F(Vex) , 0 , 449, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #369 [ref=1x] - { F(Vec)|F(Vex) , 0 , 450, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #370 [ref=1x] - { F(Vec)|F(Vex) , 0 , 451, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #371 [ref=1x] - { F(Vec)|F(Vex) , 0 , 452, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #372 [ref=1x] - { F(Evex)|F(Vec) , X(B64)|X(K) , 200, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #373 [ref=4x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #374 [ref=6x] - { F(Evex)|F(EvexCompat)|F(PreferEvex)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #375 [ref=4x] - { F(Vec)|F(Vex) , 0 , 195, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #376 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 192, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #377 [ref=2x] - { F(Vec)|F(Vex) , 0 , 171, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #378 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 85 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #379 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 85 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #380 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 175, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #381 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 453, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #382 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 454, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #383 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 507, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #384 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 508, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #385 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 509, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #386 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 510, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #387 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 511, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #388 [ref=1x] - { F(Vec)|F(Vex) , 0 , 353, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #389 [ref=12x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #390 [ref=8x] - { F(Evex)|F(Vec) , 0 , 512, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #391 [ref=4x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 254, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #392 [ref=6x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 257, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #393 [ref=9x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 260, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #394 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 212, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #395 [ref=4x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 263, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #396 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #397 [ref=6x] - { F(Vec)|F(Vex) , 0 , 159, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #398 [ref=1x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #399 [ref=3x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #400 [ref=3x] - { F(Vec)|F(Vex) , 0 , 375, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #401 [ref=4x] - { F(Evex)|F(Vec)|F(Vsib) , X(K) , 266, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #402 [ref=2x] - { F(Evex)|F(Vec)|F(Vsib) , X(K) , 377, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #403 [ref=2x] - { F(Evex)|F(Vec)|F(Vsib) , X(K) , 379, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #404 [ref=2x] - { F(Evex)|F(Vec)|F(Vsib) , X(K) , 269, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #405 [ref=2x] - { F(Vec)|F(Vex) , 0 , 381, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #406 [ref=8x] - { F(Evex)|F(Vec) , X(K) , 272, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #407 [ref=5x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #408 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #409 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 91 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #410 [ref=3x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #411 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 91 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #412 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 91 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #413 [ref=3x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 97 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #414 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #415 [ref=6x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #416 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #417 [ref=2x] - { F(Evex)|F(Vec) , X(B32)|X(K) , 272, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #418 [ref=2x] - { F(Evex)|F(Vec) , X(B64)|X(K) , 272, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #419 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #420 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #421 [ref=2x] - { F(Evex)|F(Vec) , X(B16)|X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #422 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 476, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #423 [ref=2x] - { F(Vec)|F(Vex) , 0 , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #424 [ref=2x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 491, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #425 [ref=1x] - { F(Evex)|F(Vec) , X(K)|X(Z) , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #426 [ref=1x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 221, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #427 [ref=2x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 491, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #428 [ref=1x] - { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #429 [ref=1x] - { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #430 [ref=1x] - { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 195, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #431 [ref=2x] - { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 195, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #432 [ref=2x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #433 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #434 [ref=1x] - { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #435 [ref=1x] - { F(Vec)|F(Vex) , 0 , 108, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #436 [ref=2x] - { 0 , 0 , 23 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #437 [ref=2x] - { 0 , 0 , 61 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #438 [ref=2x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 58 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #439 [ref=1x] - { 0 , 0 , 513, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #440 [ref=1x] - { F(Lock)|F(XAcquire) , 0 , 58 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #441 [ref=1x] - { 0 , 0 , 514, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #442 [ref=6x] - { 0 , 0 , 515, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)} // #443 [ref=6x] + { 0 , 0 , 455, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #1 [ref=4x] + { 0 , 0 , 456, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #2 [ref=2x] + { 0 , 0 , 108, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #3 [ref=6x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 20 , 13, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #4 [ref=2x] + { 0 , 0 , 50 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #5 [ref=2x] + { F(Vec) , 0 , 72 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #6 [ref=54x] + { F(Vec) , 0 , 143, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #7 [ref=19x] + { F(Vec) , 0 , 283, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #8 [ref=16x] + { F(Vec) , 0 , 292, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #9 [ref=20x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 33 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #10 [ref=1x] + { F(Vex) , 0 , 325, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #11 [ref=3x] + { F(Vec) , 0 , 72 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #12 [ref=12x] + { 0 , 0 , 457, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #13 [ref=1x] + { F(Vex) , 0 , 327, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #14 [ref=5x] + { F(Vex) , 0 , 50 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #15 [ref=12x] + { F(Vec) , 0 , 458, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #16 [ref=4x] + { 0 , 0 , 329, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #17 [ref=3x] + { F(Mib) , 0 , 459, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #18 [ref=1x] + { 0 , 0 , 460, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #19 [ref=1x] + { 0 , 0 , 331, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #20 [ref=1x] + { F(Mib) , 0 , 461, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #21 [ref=1x] + { 0 , 0 , 333, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #22 [ref=1x] + { 0 , 0 , 49 , 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #23 [ref=35x] + { 0 , 0 , 335, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #24 [ref=3x] + { 0 , 0 , 134, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #25 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 134, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #26 [ref=3x] + { F(Rep)|F(RepIgnored) , 0 , 235, 3 , CONTROL_FLOW(Call), SAME_REG_HINT(None)}, // #27 [ref=1x] + { 0 , 0 , 462, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #28 [ref=1x] + { 0 , 0 , 463, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #29 [ref=2x] + { 0 , 0 , 436, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #30 [ref=1x] + { 0 , 0 , 110, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #31 [ref=88x] + { 0 , 0 , 464, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #32 [ref=24x] + { 0 , 0 , 465, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #33 [ref=6x] + { 0 , 0 , 466, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #34 [ref=14x] + { 0 , 0 , 467, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #35 [ref=1x] + { 0 , 0 , 20 , 13, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #36 [ref=1x] + { F(Vex) , 0 , 337, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #37 [ref=16x] + { F(Rep) , 0 , 179, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #38 [ref=1x] + { F(Vec) , 0 , 468, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #39 [ref=2x] + { F(Vec) , 0 , 469, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #40 [ref=3x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 183, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #41 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 470, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #42 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 471, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #43 [ref=1x] + { 0 , 0 , 472, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #44 [ref=1x] + { 0 , 0 , 473, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #45 [ref=1x] + { 0 , 0 , 339, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #46 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 474, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #47 [ref=2x] + { F(Mmx)|F(Vec) , 0 , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #48 [ref=2x] + { F(Mmx)|F(Vec) , 0 , 476, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #49 [ref=2x] + { F(Vec) , 0 , 341, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #50 [ref=2x] + { F(Vec) , 0 , 343, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #51 [ref=1x] + { F(Vec) , 0 , 345, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #52 [ref=1x] + { F(Vec) , 0 , 347, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #53 [ref=1x] + { F(Vec) , 0 , 349, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #54 [ref=1x] + { 0 , 0 , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #55 [ref=1x] + { 0 , 0 , 478, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #56 [ref=3x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 238, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #57 [ref=1x] + { 0 , 0 , 45 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #58 [ref=3x] + { F(Mmx) , 0 , 110, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #59 [ref=1x] + { 0 , 0 , 351, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #60 [ref=2x] + { 0 , 0 , 479, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #61 [ref=1x] + { F(Vec) , 0 , 480, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #62 [ref=2x] + { F(Vec) , 0 , 353, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #63 [ref=1x] + { F(FpuM32)|F(FpuM64) , 0 , 241, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #64 [ref=6x] + { 0 , 0 , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #65 [ref=9x] + { F(FpuM80) , 0 , 481, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #66 [ref=2x] + { 0 , 0 , 356, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #67 [ref=13x] + { F(FpuM32)|F(FpuM64) , 0 , 357, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #68 [ref=2x] + { F(FpuM16)|F(FpuM32) , 0 , 482, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #69 [ref=9x] + { F(FpuM16)|F(FpuM32)|F(FpuM64) , 0 , 483, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #70 [ref=3x] + { F(FpuM32)|F(FpuM64)|F(FpuM80) , 0 , 484, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #71 [ref=2x] + { F(FpuM16) , 0 , 485, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #72 [ref=3x] + { F(FpuM16) , 0 , 486, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #73 [ref=2x] + { F(FpuM32)|F(FpuM64) , 0 , 358, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #74 [ref=1x] + { 0 , 0 , 487, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #75 [ref=4x] + { 0 , 0 , 488, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #76 [ref=1x] + { 0 , 0 , 45 , 10, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #77 [ref=1x] + { 0 , 0 , 489, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #78 [ref=1x] + { F(Lock) , 0 , 238, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #79 [ref=1x] + { 0 , 0 , 379, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #80 [ref=2x] + { 0 , 0 , 336, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #81 [ref=3x] + { F(Rep) , 0 , 490, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #82 [ref=1x] + { F(Vec) , 0 , 359, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #83 [ref=1x] + { 0 , 0 , 491, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #84 [ref=2x] + { 0 , 0 , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #85 [ref=8x] + { 0 , 0 , 361, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #86 [ref=3x] + { 0 , 0 , 363, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #87 [ref=1x] + { 0 , 0 , 365, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #88 [ref=1x] + { 0 , 0 , 110, 1 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #89 [ref=2x] + { 0 , 0 , 466, 1 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #90 [ref=1x] + { F(Rep) , 0 , 244, 1 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #91 [ref=30x] + { F(Rep) , 0 , 367, 2 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #92 [ref=1x] + { F(Rep) , 0 , 244, 3 , CONTROL_FLOW(Jump), SAME_REG_HINT(None)}, // #93 [ref=1x] + { F(Vex) , 0 , 493, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #94 [ref=19x] + { F(Vex) , 0 , 369, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #95 [ref=1x] + { F(Vex) , 0 , 371, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #96 [ref=1x] + { F(Vex) , 0 , 187, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #97 [ref=1x] + { F(Vex) , 0 , 373, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #98 [ref=1x] + { F(Vex) , 0 , 494, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #99 [ref=12x] + { F(Vex) , 0 , 495, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #100 [ref=8x] + { F(Vex) , 0 , 493, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #101 [ref=8x] + { 0 , 0 , 496, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #102 [ref=2x] + { 0 , 0 , 253, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #103 [ref=1x] + { 0 , 0 , 247, 3 , CONTROL_FLOW(Call), SAME_REG_HINT(None)}, // #104 [ref=1x] + { F(Vec) , 0 , 169, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #105 [ref=2x] + { 0 , 0 , 497, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #106 [ref=2x] + { 0 , 0 , 375, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #107 [ref=2x] + { F(Vex) , 0 , 498, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #108 [ref=2x] + { 0 , 0 , 377, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #109 [ref=1x] + { 0 , 0 , 250, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #110 [ref=3x] + { 0 , 0 , 247, 3 , CONTROL_FLOW(Jump), SAME_REG_HINT(None)}, // #111 [ref=1x] + { 0 , 0 , 499, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #112 [ref=5x] + { F(Vex) , 0 , 379, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #113 [ref=2x] + { F(Rep) , 0 , 191, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #114 [ref=1x] + { 0 , 0 , 367, 2 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #115 [ref=3x] + { 0 , 0 , 253, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #116 [ref=1x] + { F(Vex) , 0 , 381, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #117 [ref=2x] + { F(Vec) , 0 , 500, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #118 [ref=1x] + { F(Mmx) , 0 , 501, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #119 [ref=1x] + { 0 , 0 , 502, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #120 [ref=2x] + { F(XRelease) , 0 , 0 , 20, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #121 [ref=1x] + { 0 , 0 , 55 , 9 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #122 [ref=1x] + { F(Vec) , 0 , 72 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #123 [ref=6x] + { 0 , 0 , 104, 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #124 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 383, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #125 [ref=1x] + { 0 , 0 , 385, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #126 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 503, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #127 [ref=1x] + { F(Vec) , 0 , 354, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #128 [ref=2x] + { F(Vec) , 0 , 80 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #129 [ref=4x] + { F(Vec) , 0 , 504, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #130 [ref=2x] + { F(Vec) , 0 , 73 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #131 [ref=3x] + { F(Mmx) , 0 , 505, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #132 [ref=1x] + { F(Vec) , 0 , 80 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #133 [ref=1x] + { F(Vec) , 0 , 88 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #134 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 139, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #135 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 506, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #136 [ref=1x] + { F(Rep) , 0 , 195, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #137 [ref=1x] + { F(Vec) , 0 , 387, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #138 [ref=1x] + { F(Vec) , 0 , 389, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #139 [ref=1x] + { 0 , 0 , 256, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #140 [ref=2x] + { 0 , 0 , 391, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #141 [ref=1x] + { F(Vex) , 0 , 393, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #142 [ref=1x] + { 0 , 0 , 507, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #143 [ref=1x] + { 0 , 0 , 508, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #144 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 239, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #145 [ref=2x] + { 0 , 0 , 110, 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #146 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 20 , 13, CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #147 [ref=1x] + { 0 , 0 , 509, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #148 [ref=1x] + { F(Rep) , 0 , 510, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #149 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 395, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #150 [ref=37x] + { F(Mmx)|F(Vec) , 0 , 397, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #151 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 395, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #152 [ref=6x] + { F(Mmx)|F(Vec) , 0 , 395, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #153 [ref=16x] + { F(Mmx) , 0 , 139, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #154 [ref=26x] + { F(Vec) , 0 , 72 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #155 [ref=4x] + { F(Vec) , 0 , 511, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #156 [ref=1x] + { F(Vec) , 0 , 512, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #157 [ref=1x] + { F(Vec) , 0 , 513, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #158 [ref=1x] + { F(Vec) , 0 , 514, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #159 [ref=1x] + { F(Vec) , 0 , 515, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #160 [ref=1x] + { F(Vec) , 0 , 516, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #161 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 399, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #162 [ref=1x] + { F(Vec) , 0 , 517, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #163 [ref=1x] + { F(Vec) , 0 , 518, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #164 [ref=1x] + { F(Vec) , 0 , 519, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #165 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 520, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #166 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 521, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #167 [ref=1x] + { F(Vec) , 0 , 313, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #168 [ref=2x] + { 0 , 0 , 144, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #169 [ref=1x] + { F(Mmx) , 0 , 397, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #170 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 401, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #171 [ref=8x] + { F(Vec) , 0 , 522, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #172 [ref=2x] + { 0 , 0 , 403, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #173 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 405, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #174 [ref=3x] + { 0 , 0 , 149, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #175 [ref=1x] + { 0 , 0 , 407, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #176 [ref=8x] + { 0 , 0 , 523, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #177 [ref=4x] + { 0 , 0 , 524, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #178 [ref=8x] + { 0 , 0 , 409, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #179 [ref=1x] + { F(Rep)|F(RepIgnored) , 0 , 411, 2 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #180 [ref=1x] + { 0 , 0 , 411, 2 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #181 [ref=1x] + { F(Vex) , 0 , 413, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #182 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 20 , 13, CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #183 [ref=3x] + { F(Rep) , 0 , 199, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #184 [ref=1x] + { 0 , 0 , 525, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #185 [ref=30x] + { 0 , 0 , 259, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #186 [ref=2x] + { 0 , 0 , 415, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #187 [ref=3x] + { F(Rep) , 0 , 203, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #188 [ref=1x] + { F(Vex) , 0 , 526, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #189 [ref=8x] + { 0 , 0 , 64 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #190 [ref=1x] + { F(Tsib)|F(Vex) , 0 , 527, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #191 [ref=2x] + { F(Vex) , 0 , 466, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #192 [ref=1x] + { F(Tsib)|F(Vex) , 0 , 528, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #193 [ref=1x] + { F(Vex) , 0 , 529, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #194 [ref=1x] + { 0 , 0 , 530, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #195 [ref=2x] + { 0 , 0 , 50 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #196 [ref=2x] + { 0 , 0 , 417, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #197 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(T4X)|X(Z) , 531, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #198 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(T4X)|X(Z) , 532, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #199 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #200 [ref=22x] + { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #201 [ref=23x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #202 [ref=22x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(K)|X(SAE)|X(Z) , 533, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #203 [ref=18x] + { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 534, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #204 [ref=18x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(K)|X(SAE)|X(Z) , 535, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #205 [ref=17x] + { F(Vec)|F(Vex) , 0 , 262, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #206 [ref=29x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #207 [ref=5x] + { F(Vec)|F(Vex) , 0 , 72 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #208 [ref=17x] + { F(Vec)|F(Vex) , 0 , 292, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #209 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #210 [ref=4x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #211 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #212 [ref=10x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #213 [ref=12x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #214 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #215 [ref=6x] + { F(Vec)|F(Vex) , 0 , 536, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #216 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #217 [ref=17x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #218 [ref=12x] + { F(Vec)|F(Vex) , 0 , 265, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #219 [ref=6x] + { F(Vec)|F(Vex) , 0 , 419, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #220 [ref=3x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 537, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #221 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 538, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #222 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 539, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #223 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 540, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #224 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 445, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #225 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 538, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #226 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 541, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #227 [ref=1x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B64)|X(ImplicitZ)|X(K)|X(SAE), 268, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #228 [ref=1x] + { F(Evex)|F(Vec) , X(B16)|X(ImplicitZ)|X(K)|X(SAE), 271, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #229 [ref=1x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B32)|X(ImplicitZ)|X(K)|X(SAE), 268, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #230 [ref=1x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(ImplicitZ)|X(K)|X(SAE) , 542, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #231 [ref=1x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K)|X(SAE) , 543, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #232 [ref=1x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(ImplicitZ)|X(K)|X(SAE) , 544, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #233 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 143, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #234 [ref=2x] + { F(Evex)|F(Vec) , X(SAE) , 313, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #235 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 283, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #236 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 274, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #237 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #238 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 421, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #239 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #240 [ref=3x] + { F(Vec)|F(Vex) , 0 , 169, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #241 [ref=5x] + { F(Evex)|F(EvexCompat)|F(PreferEvex)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 421, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #242 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 421, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #243 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 545, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #244 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #245 [ref=4x] + { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 421, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #246 [ref=3x] + { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #247 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 283, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #248 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #249 [ref=1x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #250 [ref=3x] + { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 283, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #251 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #252 [ref=5x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #253 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 286, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #254 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #255 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #256 [ref=2x] + { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 533, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #257 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 341, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #258 [ref=1x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 341, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #259 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 534, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #260 [ref=5x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 423, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #261 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 425, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #262 [ref=2x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 427, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #263 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 535, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #264 [ref=3x] + { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 535, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #265 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 347, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #266 [ref=1x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 347, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #267 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(SAE)|X(Z) , 421, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #268 [ref=1x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #269 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 421, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #270 [ref=1x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #271 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #272 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #273 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #274 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 341, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #275 [ref=1x] + { F(Evex)|F(Vec) , X(SAE) , 341, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #276 [ref=1x] + { F(Evex)|F(Vec) , X(SAE) , 423, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #277 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 347, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #278 [ref=1x] + { F(Evex)|F(Vec) , X(SAE) , 347, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #279 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #280 [ref=1x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 425, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #281 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #282 [ref=3x] + { F(Vec)|F(Vex) , 0 , 265, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #283 [ref=10x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 78 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #284 [ref=3x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 78 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #285 [ref=3x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #286 [ref=8x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 287, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #287 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 546, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #288 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 288, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #289 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 480, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #290 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #291 [ref=5x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #292 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #293 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 547, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #294 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 548, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #295 [ref=4x] + { F(Vec)|F(Vex) , 0 , 207, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #296 [ref=13x] + { F(Vec)|F(Vex) , 0 , 429, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #297 [ref=4x] + { F(Vec)|F(Vex) , 0 , 431, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #298 [ref=4x] + { F(Evex)|F(Vec) , X(B64)|X(ImplicitZ)|X(K) , 549, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #299 [ref=1x] + { F(Evex)|F(Vec) , X(B16)|X(K) , 549, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #300 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(ImplicitZ)|X(K) , 549, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #301 [ref=1x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K) , 550, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #302 [ref=1x] + { F(Evex)|F(Vec) , X(K) , 551, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #303 [ref=1x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K) , 552, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #304 [ref=1x] + { F(Vec)|F(Vex) , 0 , 280, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #305 [ref=7x] + { F(Vec)|F(Vex) , 0 , 143, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #306 [ref=1x] + { F(Vec)|F(Vex) , 0 , 283, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #307 [ref=1x] + { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 211, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #308 [ref=2x] + { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 154, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #309 [ref=2x] + { F(Evex)|F(Vsib) , X(K) , 553, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #310 [ref=4x] + { F(Evex)|F(Vsib) , X(K) , 554, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #311 [ref=4x] + { F(Evex)|F(Vsib) , X(K) , 555, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #312 [ref=8x] + { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 159, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #313 [ref=2x] + { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 289, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #314 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 533, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #315 [ref=3x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 535, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #316 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 292, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #317 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 292, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #318 [ref=3x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 292, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #319 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 556, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #320 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #321 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #322 [ref=22x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 433, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #323 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 433, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #324 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 557, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #325 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 548, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #326 [ref=1x] + { F(Vex) , 0 , 497, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #327 [ref=2x] + { F(Vec)|F(Vex) , 0 , 500, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #328 [ref=1x] + { F(Vec)|F(Vex) , 0 , 215, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #329 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(SAE)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #330 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #331 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(SAE)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #332 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 533, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #333 [ref=2x] + { 0 , 0 , 435, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #334 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 72 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #335 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 437, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #336 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 295, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #337 [ref=1x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 72 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #338 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 116, 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #339 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 82 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #340 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 219, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #341 [ref=4x] + { F(Vec)|F(Vex) , 0 , 558, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #342 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 164, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #343 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 169, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #344 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 174, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #345 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 80 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #346 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 223, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #347 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #348 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 88 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #349 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 439, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #350 [ref=1x] + { 0 , 0 , 441, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #351 [ref=1x] + { 0 , 0 , 443, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #352 [ref=1x] + { F(Evex)|F(Vec) , X(B32) , 298, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #353 [ref=1x] + { F(Evex)|F(Vec) , X(B64) , 298, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #354 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #355 [ref=1x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #356 [ref=5x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 262, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #357 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #358 [ref=2x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 262, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #359 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #360 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #361 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #362 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #363 [ref=13x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 559, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #364 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 560, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #365 [ref=1x] + { F(Evex)|F(Vec) , 0 , 561, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #366 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 445, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #367 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 562, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #368 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #369 [ref=1x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K) , 271, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #370 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(ImplicitZ)|X(K) , 271, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #371 [ref=2x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(ImplicitZ)|X(K) , 301, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #372 [ref=4x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B32)|X(ImplicitZ)|X(K) , 301, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #373 [ref=2x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B64)|X(ImplicitZ)|X(K) , 301, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #374 [ref=2x] + { F(Vec)|F(Vex) , 0 , 511, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #375 [ref=1x] + { F(Vec)|F(Vex) , 0 , 512, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #376 [ref=1x] + { F(Vec)|F(Vex) , 0 , 513, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #377 [ref=1x] + { F(Vec)|F(Vex) , 0 , 514, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #378 [ref=1x] + { F(Evex)|F(Vec) , X(B64)|X(ImplicitZ)|X(K) , 271, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #379 [ref=4x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #380 [ref=6x] + { F(Evex)|F(EvexCompat)|F(PreferEvex)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #381 [ref=4x] + { F(Vec)|F(Vex) , 0 , 266, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #382 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 263, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #383 [ref=2x] + { F(Vec)|F(Vex) , 0 , 227, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #384 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 96 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #385 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 96 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #386 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 231, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #387 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 515, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #388 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 516, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #389 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 563, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #390 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 564, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #391 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 565, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #392 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 566, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #393 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 567, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #394 [ref=1x] + { F(Vec)|F(Vex) , 0 , 419, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #395 [ref=12x] + { F(Evex)|F(EvexCompat)|F(PreferEvex)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #396 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #397 [ref=8x] + { F(Evex)|F(Vec) , 0 , 568, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #398 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 304, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #399 [ref=6x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 307, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #400 [ref=9x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 310, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #401 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 283, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #402 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 313, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #403 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 277, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #404 [ref=6x] + { F(Vec)|F(Vex) , 0 , 207, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #405 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 292, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #406 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 292, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #407 [ref=3x] + { F(Vec)|F(Vex) , 0 , 447, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #408 [ref=4x] + { F(Evex)|F(Vec)|F(Vsib) , X(K) , 316, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #409 [ref=2x] + { F(Evex)|F(Vec)|F(Vsib) , X(K) , 449, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #410 [ref=2x] + { F(Evex)|F(Vec)|F(Vsib) , X(K) , 451, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #411 [ref=2x] + { F(Evex)|F(Vec)|F(Vsib) , X(K) , 319, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #412 [ref=2x] + { F(Vec)|F(Vex) , 0 , 453, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #413 [ref=8x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K) , 322, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #414 [ref=5x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 292, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #415 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 292, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #416 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 122, 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #417 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 292, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #418 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 122, 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #419 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 122, 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #420 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 128, 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #421 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #422 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #423 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #424 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(ImplicitZ)|X(K) , 322, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #425 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(ImplicitZ)|X(K) , 322, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #426 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 533, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #427 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 535, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #428 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #429 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 534, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #430 [ref=2x] + { F(Vec)|F(Vex) , 0 , 535, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #431 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 547, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #432 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 548, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #433 [ref=1x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 292, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #434 [ref=2x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 547, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #435 [ref=1x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 548, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #436 [ref=1x] + { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 262, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #437 [ref=1x] + { F(Vec)|F(Vex) , 0 , 569, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #438 [ref=1x] + { F(Vec)|F(Vex) , 0 , 570, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #439 [ref=1x] + { F(Vec)|F(Vex) , 0 , 571, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #440 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 266, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #441 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 266, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #442 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #443 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 265, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #444 [ref=1x] + { F(Vec)|F(Vex) , 0 , 262, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #445 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 280, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #446 [ref=1x] + { F(Vec)|F(Vex) , 0 , 110, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #447 [ref=2x] + { 0 , 0 , 27 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #448 [ref=2x] + { 0 , 0 , 28 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #449 [ref=2x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 25 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #450 [ref=1x] + { 0 , 0 , 236, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #451 [ref=1x] + { F(XAcquire) , 0 , 25 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #452 [ref=1x] + { 0 , 0 , 572, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #453 [ref=6x] + { 0 , 0 , 573, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)} // #454 [ref=6x] }; #undef SAME_REG_HINT #undef CONTROL_FLOW @@ -2609,197 +2656,220 @@ const InstDB::CommonInfo InstDB::_commonInfoTable[] = { // ------------------- Automatically generated, do not edit ------------------- #define EXT(VAL) uint32_t(CpuFeatures::X86::k##VAL) const InstDB::AdditionalInfo InstDB::_additionalInfoTable[] = { - { 0, 0, { 0 } }, // #0 [ref=148x] + { 0, 0, { 0 } }, // #0 [ref=67x] { 0, 1, { 0 } }, // #1 [ref=32x] - { 0, 2, { 0 } }, // #2 [ref=2x] - { 0, 3, { EXT(ADX) } }, // #3 [ref=1x] - { 0, 0, { EXT(SSE2) } }, // #4 [ref=60x] - { 0, 0, { EXT(SSE) } }, // #5 [ref=41x] - { 0, 0, { EXT(SSE3) } }, // #6 [ref=12x] - { 0, 4, { EXT(ADX) } }, // #7 [ref=1x] - { 0, 0, { EXT(AESNI) } }, // #8 [ref=6x] - { 0, 1, { EXT(BMI) } }, // #9 [ref=6x] - { 0, 5, { 0 } }, // #10 [ref=5x] - { 0, 0, { EXT(TBM) } }, // #11 [ref=9x] - { 0, 0, { EXT(SSE4_1) } }, // #12 [ref=47x] - { 0, 0, { EXT(MPX) } }, // #13 [ref=7x] - { 0, 6, { 0 } }, // #14 [ref=4x] - { 0, 1, { EXT(BMI2) } }, // #15 [ref=1x] - { 0, 7, { EXT(SMAP) } }, // #16 [ref=2x] - { 0, 8, { 0 } }, // #17 [ref=2x] - { 0, 9, { 0 } }, // #18 [ref=2x] - { 0, 0, { EXT(CLDEMOTE) } }, // #19 [ref=1x] - { 0, 0, { EXT(CLFLUSH) } }, // #20 [ref=1x] - { 0, 0, { EXT(CLFLUSHOPT) } }, // #21 [ref=1x] - { 0, 0, { EXT(SVM) } }, // #22 [ref=6x] - { 0, 10, { 0 } }, // #23 [ref=2x] - { 0, 1, { EXT(CET_SS) } }, // #24 [ref=3x] - { 0, 0, { EXT(UINTR) } }, // #25 [ref=4x] - { 0, 0, { EXT(CLWB) } }, // #26 [ref=1x] - { 0, 0, { EXT(CLZERO) } }, // #27 [ref=1x] - { 0, 3, { 0 } }, // #28 [ref=1x] - { 0, 11, { EXT(CMOV) } }, // #29 [ref=6x] - { 0, 12, { EXT(CMOV) } }, // #30 [ref=8x] - { 0, 13, { EXT(CMOV) } }, // #31 [ref=6x] - { 0, 14, { EXT(CMOV) } }, // #32 [ref=4x] - { 0, 15, { EXT(CMOV) } }, // #33 [ref=4x] - { 0, 16, { EXT(CMOV) } }, // #34 [ref=2x] - { 0, 17, { EXT(CMOV) } }, // #35 [ref=6x] - { 0, 18, { EXT(CMOV) } }, // #36 [ref=2x] - { 0, 19, { 0 } }, // #37 [ref=2x] - { 0, 1, { EXT(I486) } }, // #38 [ref=2x] - { 0, 5, { EXT(CMPXCHG16B) } }, // #39 [ref=1x] - { 0, 5, { EXT(CMPXCHG8B) } }, // #40 [ref=1x] - { 0, 1, { EXT(SSE2) } }, // #41 [ref=2x] - { 0, 1, { EXT(SSE) } }, // #42 [ref=2x] - { 0, 0, { EXT(I486) } }, // #43 [ref=4x] - { 0, 0, { EXT(SSE4_2) } }, // #44 [ref=2x] - { 0, 20, { 0 } }, // #45 [ref=2x] - { 0, 0, { EXT(MMX) } }, // #46 [ref=1x] - { 0, 0, { EXT(CET_IBT) } }, // #47 [ref=2x] - { 0, 0, { EXT(ENQCMD) } }, // #48 [ref=2x] - { 0, 0, { EXT(SSE4A) } }, // #49 [ref=4x] - { 0, 21, { 0 } }, // #50 [ref=4x] - { 0, 0, { EXT(3DNOW) } }, // #51 [ref=21x] - { 0, 0, { EXT(FXSR) } }, // #52 [ref=4x] - { 0, 0, { EXT(SMX) } }, // #53 [ref=1x] - { 0, 0, { EXT(GFNI) } }, // #54 [ref=3x] - { 0, 0, { EXT(HRESET) } }, // #55 [ref=1x] - { 0, 0, { EXT(CET_SS) } }, // #56 [ref=9x] - { 0, 16, { 0 } }, // #57 [ref=5x] - { 0, 0, { EXT(VMX) } }, // #58 [ref=12x] - { 0, 11, { 0 } }, // #59 [ref=8x] - { 0, 12, { 0 } }, // #60 [ref=12x] - { 0, 13, { 0 } }, // #61 [ref=10x] - { 0, 14, { 0 } }, // #62 [ref=8x] - { 0, 15, { 0 } }, // #63 [ref=8x] - { 0, 17, { 0 } }, // #64 [ref=8x] - { 0, 18, { 0 } }, // #65 [ref=4x] - { 0, 0, { EXT(AVX512_DQ) } }, // #66 [ref=22x] - { 0, 0, { EXT(AVX512_BW) } }, // #67 [ref=20x] - { 0, 0, { EXT(AVX512_F) } }, // #68 [ref=36x] - { 1, 0, { EXT(AVX512_DQ) } }, // #69 [ref=1x] - { 1, 0, { EXT(AVX512_BW) } }, // #70 [ref=2x] - { 1, 0, { EXT(AVX512_F) } }, // #71 [ref=1x] - { 0, 1, { EXT(AVX512_DQ) } }, // #72 [ref=3x] - { 0, 1, { EXT(AVX512_BW) } }, // #73 [ref=4x] - { 0, 1, { EXT(AVX512_F) } }, // #74 [ref=1x] - { 0, 22, { EXT(LAHFSAHF) } }, // #75 [ref=1x] - { 0, 0, { EXT(AMX_TILE) } }, // #76 [ref=7x] - { 0, 0, { EXT(LWP) } }, // #77 [ref=4x] - { 0, 23, { 0 } }, // #78 [ref=3x] - { 0, 1, { EXT(LZCNT) } }, // #79 [ref=1x] - { 0, 0, { EXT(MMX2) } }, // #80 [ref=8x] - { 0, 1, { EXT(MCOMMIT) } }, // #81 [ref=1x] - { 0, 0, { EXT(MONITOR) } }, // #82 [ref=2x] - { 0, 0, { EXT(MONITORX) } }, // #83 [ref=2x] - { 1, 0, { 0 } }, // #84 [ref=1x] - { 1, 0, { EXT(SSE2) } }, // #85 [ref=5x] - { 1, 0, { EXT(SSE) } }, // #86 [ref=3x] - { 0, 0, { EXT(MOVBE) } }, // #87 [ref=1x] - { 0, 0, { EXT(MMX), EXT(SSE2) } }, // #88 [ref=45x] - { 0, 0, { EXT(MOVDIR64B) } }, // #89 [ref=1x] - { 0, 0, { EXT(MOVDIRI) } }, // #90 [ref=1x] - { 1, 0, { EXT(MMX), EXT(SSE2) } }, // #91 [ref=1x] - { 0, 0, { EXT(BMI2) } }, // #92 [ref=7x] - { 0, 0, { EXT(SSSE3) } }, // #93 [ref=15x] - { 0, 0, { EXT(MMX2), EXT(SSE2) } }, // #94 [ref=10x] - { 0, 0, { EXT(PCLMULQDQ) } }, // #95 [ref=1x] - { 0, 1, { EXT(SSE4_2) } }, // #96 [ref=4x] - { 0, 0, { EXT(PCONFIG) } }, // #97 [ref=1x] - { 0, 0, { EXT(MMX2), EXT(SSE2), EXT(SSE4_1) } }, // #98 [ref=1x] - { 0, 0, { EXT(3DNOW2) } }, // #99 [ref=5x] - { 0, 0, { EXT(GEODE) } }, // #100 [ref=2x] - { 0, 1, { EXT(POPCNT) } }, // #101 [ref=1x] - { 0, 24, { 0 } }, // #102 [ref=3x] - { 0, 1, { EXT(PREFETCHW) } }, // #103 [ref=1x] - { 0, 1, { EXT(PREFETCHWT1) } }, // #104 [ref=1x] - { 0, 20, { EXT(SNP) } }, // #105 [ref=3x] - { 0, 1, { EXT(SSE4_1) } }, // #106 [ref=1x] - { 0, 0, { EXT(PTWRITE) } }, // #107 [ref=1x] - { 0, 25, { 0 } }, // #108 [ref=3x] - { 0, 1, { EXT(SNP) } }, // #109 [ref=1x] - { 0, 26, { 0 } }, // #110 [ref=2x] - { 0, 0, { EXT(FSGSBASE) } }, // #111 [ref=4x] - { 0, 0, { EXT(MSR) } }, // #112 [ref=2x] - { 0, 0, { EXT(RDPID) } }, // #113 [ref=1x] - { 0, 0, { EXT(OSPKE) } }, // #114 [ref=1x] - { 0, 0, { EXT(RDPRU) } }, // #115 [ref=1x] - { 0, 1, { EXT(RDRAND) } }, // #116 [ref=1x] - { 0, 1, { EXT(RDSEED) } }, // #117 [ref=1x] - { 0, 0, { EXT(RDTSC) } }, // #118 [ref=1x] - { 0, 0, { EXT(RDTSCP) } }, // #119 [ref=1x] - { 0, 27, { 0 } }, // #120 [ref=2x] - { 0, 28, { EXT(LAHFSAHF) } }, // #121 [ref=1x] - { 0, 0, { EXT(SERIALIZE) } }, // #122 [ref=1x] - { 0, 0, { EXT(SHA) } }, // #123 [ref=7x] - { 0, 0, { EXT(SKINIT) } }, // #124 [ref=2x] - { 0, 0, { EXT(AMX_BF16) } }, // #125 [ref=1x] - { 0, 0, { EXT(AMX_INT8) } }, // #126 [ref=4x] - { 0, 1, { EXT(UINTR) } }, // #127 [ref=1x] - { 0, 1, { EXT(WAITPKG) } }, // #128 [ref=2x] - { 0, 0, { EXT(WAITPKG) } }, // #129 [ref=1x] - { 0, 0, { EXT(AVX512_4FMAPS) } }, // #130 [ref=4x] - { 0, 0, { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL) } }, // #131 [ref=42x] - { 0, 0, { EXT(AVX512_FP16), EXT(AVX512_VL) } }, // #132 [ref=63x] - { 0, 0, { EXT(AVX), EXT(AVX512_F) } }, // #133 [ref=29x] - { 0, 0, { EXT(AVX512_FP16) } }, // #134 [ref=43x] - { 0, 0, { EXT(AVX) } }, // #135 [ref=35x] - { 0, 0, { EXT(AESNI), EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(VAES) } }, // #136 [ref=4x] - { 0, 0, { EXT(AESNI), EXT(AVX) } }, // #137 [ref=2x] - { 0, 0, { EXT(AVX512_F), EXT(AVX512_VL) } }, // #138 [ref=108x] - { 0, 0, { EXT(AVX), EXT(AVX512_DQ), EXT(AVX512_VL) } }, // #139 [ref=8x] - { 0, 0, { EXT(AVX512_DQ), EXT(AVX512_VL) } }, // #140 [ref=30x] - { 0, 0, { EXT(AVX2) } }, // #141 [ref=7x] - { 0, 0, { EXT(AVX), EXT(AVX2), EXT(AVX512_F), EXT(AVX512_VL) } }, // #142 [ref=39x] - { 0, 1, { EXT(AVX), EXT(AVX512_F) } }, // #143 [ref=4x] - { 0, 0, { EXT(AVX512_BF16), EXT(AVX512_VL) } }, // #144 [ref=3x] - { 0, 0, { EXT(AVX512_F), EXT(AVX512_VL), EXT(F16C) } }, // #145 [ref=2x] - { 0, 0, { EXT(AVX512_BW), EXT(AVX512_VL) } }, // #146 [ref=24x] - { 0, 0, { EXT(AVX512_ERI) } }, // #147 [ref=10x] - { 0, 0, { EXT(AVX512_F), EXT(AVX512_VL), EXT(FMA) } }, // #148 [ref=36x] - { 0, 0, { EXT(AVX512_F), EXT(FMA) } }, // #149 [ref=24x] - { 0, 0, { EXT(FMA4) } }, // #150 [ref=20x] - { 0, 0, { EXT(XOP) } }, // #151 [ref=55x] - { 0, 0, { EXT(AVX2), EXT(AVX512_F), EXT(AVX512_VL) } }, // #152 [ref=19x] - { 0, 0, { EXT(AVX512_PFI) } }, // #153 [ref=16x] - { 0, 0, { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(GFNI) } }, // #154 [ref=3x] - { 1, 0, { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL) } }, // #155 [ref=4x] - { 1, 0, { EXT(AVX) } }, // #156 [ref=2x] - { 1, 0, { EXT(AVX512_F), EXT(AVX512_VL) } }, // #157 [ref=4x] - { 1, 0, { EXT(AVX512_BW), EXT(AVX512_VL) } }, // #158 [ref=2x] - { 1, 0, { EXT(AVX), EXT(AVX512_F) } }, // #159 [ref=3x] - { 0, 0, { EXT(AVX), EXT(AVX2) } }, // #160 [ref=17x] - { 0, 0, { EXT(AVX512_VP2INTERSECT) } }, // #161 [ref=2x] - { 0, 0, { EXT(AVX512_4VNNIW) } }, // #162 [ref=2x] - { 0, 0, { EXT(AVX), EXT(AVX2), EXT(AVX512_BW), EXT(AVX512_VL) } }, // #163 [ref=54x] - { 0, 0, { EXT(AVX2), EXT(AVX512_BW), EXT(AVX512_VL) } }, // #164 [ref=2x] - { 0, 0, { EXT(AVX512_CDI), EXT(AVX512_VL) } }, // #165 [ref=6x] - { 0, 0, { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(PCLMULQDQ), EXT(VPCLMULQDQ) } }, // #166 [ref=1x] - { 0, 1, { EXT(AVX) } }, // #167 [ref=7x] - { 0, 0, { EXT(AVX512_VBMI2), EXT(AVX512_VL) } }, // #168 [ref=16x] - { 0, 0, { EXT(AVX512_VL), EXT(AVX512_VNNI), EXT(AVX_VNNI) } }, // #169 [ref=4x] - { 0, 0, { EXT(AVX512_VBMI), EXT(AVX512_VL) } }, // #170 [ref=4x] - { 0, 0, { EXT(AVX), EXT(AVX512_BW) } }, // #171 [ref=4x] - { 0, 0, { EXT(AVX), EXT(AVX512_DQ) } }, // #172 [ref=4x] - { 0, 0, { EXT(AVX512_IFMA), EXT(AVX512_VL) } }, // #173 [ref=2x] - { 0, 0, { EXT(AVX512_BITALG), EXT(AVX512_VL) } }, // #174 [ref=3x] - { 0, 0, { EXT(AVX512_VL), EXT(AVX512_VPOPCNTDQ) } }, // #175 [ref=2x] - { 0, 0, { EXT(WBNOINVD) } }, // #176 [ref=1x] - { 0, 0, { EXT(RTM) } }, // #177 [ref=3x] - { 0, 0, { EXT(XSAVE) } }, // #178 [ref=6x] - { 0, 0, { EXT(TSXLDTRK) } }, // #179 [ref=2x] - { 0, 0, { EXT(XSAVES) } }, // #180 [ref=4x] - { 0, 0, { EXT(XSAVEC) } }, // #181 [ref=2x] - { 0, 0, { EXT(XSAVEOPT) } }, // #182 [ref=2x] - { 0, 1, { EXT(TSX) } } // #183 [ref=1x] + { 0, 0, { EXT(RAO_INT) } }, // #2 [ref=4x] + { 0, 2, { 0 } }, // #3 [ref=2x] + { 0, 3, { EXT(ADX) } }, // #4 [ref=1x] + { 0, 0, { EXT(SSE2) } }, // #5 [ref=60x] + { 0, 0, { EXT(SSE) } }, // #6 [ref=46x] + { 0, 0, { EXT(SSE3) } }, // #7 [ref=10x] + { 0, 4, { EXT(ADX) } }, // #8 [ref=1x] + { 0, 0, { EXT(AESNI) } }, // #9 [ref=6x] + { 0, 1, { EXT(BMI) } }, // #10 [ref=6x] + { 0, 5, { 0 } }, // #11 [ref=5x] + { 0, 0, { EXT(TBM) } }, // #12 [ref=9x] + { 0, 0, { EXT(SSE4_1) } }, // #13 [ref=47x] + { 0, 0, { EXT(MPX) } }, // #14 [ref=7x] + { 0, 6, { 0 } }, // #15 [ref=4x] + { 0, 1, { EXT(BMI2) } }, // #16 [ref=1x] + { 0, 7, { EXT(SMAP) } }, // #17 [ref=2x] + { 0, 8, { 0 } }, // #18 [ref=2x] + { 0, 9, { 0 } }, // #19 [ref=2x] + { 0, 0, { EXT(CLDEMOTE) } }, // #20 [ref=1x] + { 0, 0, { EXT(CLFLUSH) } }, // #21 [ref=1x] + { 0, 0, { EXT(CLFLUSHOPT) } }, // #22 [ref=1x] + { 0, 0, { EXT(SVM) } }, // #23 [ref=6x] + { 0, 10, { 0 } }, // #24 [ref=2x] + { 0, 1, { EXT(CET_SS) } }, // #25 [ref=3x] + { 0, 0, { EXT(UINTR) } }, // #26 [ref=4x] + { 0, 0, { EXT(CLWB) } }, // #27 [ref=1x] + { 0, 0, { EXT(CLZERO) } }, // #28 [ref=1x] + { 0, 3, { 0 } }, // #29 [ref=1x] + { 0, 11, { EXT(CMOV) } }, // #30 [ref=4x] + { 0, 12, { EXT(CMOV) } }, // #31 [ref=6x] + { 0, 13, { EXT(CMOV) } }, // #32 [ref=4x] + { 0, 14, { EXT(CMOV) } }, // #33 [ref=4x] + { 0, 15, { EXT(CMOV) } }, // #34 [ref=4x] + { 0, 16, { EXT(CMOV) } }, // #35 [ref=2x] + { 0, 17, { EXT(CMOV) } }, // #36 [ref=4x] + { 0, 18, { EXT(CMOV) } }, // #37 [ref=2x] + { 0, 1, { EXT(CMPCCXADD) } }, // #38 [ref=16x] + { 0, 19, { 0 } }, // #39 [ref=2x] + { 0, 1, { EXT(I486) } }, // #40 [ref=2x] + { 0, 5, { EXT(CMPXCHG16B) } }, // #41 [ref=1x] + { 0, 5, { EXT(CMPXCHG8B) } }, // #42 [ref=1x] + { 0, 1, { EXT(SSE2) } }, // #43 [ref=2x] + { 0, 1, { EXT(SSE) } }, // #44 [ref=2x] + { 0, 0, { EXT(I486) } }, // #45 [ref=5x] + { 0, 0, { EXT(SSE4_2) } }, // #46 [ref=2x] + { 0, 20, { 0 } }, // #47 [ref=2x] + { 0, 0, { EXT(MMX) } }, // #48 [ref=1x] + { 0, 0, { EXT(CET_IBT) } }, // #49 [ref=2x] + { 0, 1, { EXT(ENQCMD) } }, // #50 [ref=2x] + { 0, 0, { EXT(SSE4A) } }, // #51 [ref=4x] + { 0, 21, { EXT(FPU) } }, // #52 [ref=80x] + { 0, 22, { EXT(CMOV), EXT(FPU) } }, // #53 [ref=2x] + { 0, 23, { EXT(CMOV), EXT(FPU) } }, // #54 [ref=2x] + { 0, 24, { EXT(CMOV), EXT(FPU) } }, // #55 [ref=2x] + { 0, 25, { EXT(CMOV), EXT(FPU) } }, // #56 [ref=2x] + { 0, 26, { EXT(FPU) } }, // #57 [ref=4x] + { 0, 0, { EXT(3DNOW) } }, // #58 [ref=21x] + { 0, 21, { EXT(SSE3), EXT(FPU) } }, // #59 [ref=1x] + { 0, 21, { EXT(FXSR) } }, // #60 [ref=2x] + { 0, 27, { EXT(FXSR) } }, // #61 [ref=2x] + { 0, 0, { EXT(SMX) } }, // #62 [ref=1x] + { 0, 0, { EXT(GFNI) } }, // #63 [ref=3x] + { 0, 0, { EXT(HRESET) } }, // #64 [ref=1x] + { 0, 0, { EXT(CET_SS) } }, // #65 [ref=9x] + { 0, 16, { 0 } }, // #66 [ref=5x] + { 0, 0, { EXT(VMX) } }, // #67 [ref=13x] + { 0, 0, { EXT(INVLPGB) } }, // #68 [ref=2x] + { 0, 11, { 0 } }, // #69 [ref=8x] + { 0, 12, { 0 } }, // #70 [ref=12x] + { 0, 13, { 0 } }, // #71 [ref=10x] + { 0, 14, { 0 } }, // #72 [ref=8x] + { 0, 15, { 0 } }, // #73 [ref=8x] + { 0, 17, { 0 } }, // #74 [ref=8x] + { 0, 18, { 0 } }, // #75 [ref=4x] + { 0, 0, { EXT(AVX512_DQ) } }, // #76 [ref=22x] + { 0, 0, { EXT(AVX512_BW) } }, // #77 [ref=20x] + { 0, 0, { EXT(AVX512_F) } }, // #78 [ref=36x] + { 1, 0, { EXT(AVX512_DQ) } }, // #79 [ref=1x] + { 1, 0, { EXT(AVX512_BW) } }, // #80 [ref=2x] + { 1, 0, { EXT(AVX512_F) } }, // #81 [ref=1x] + { 0, 1, { EXT(AVX512_DQ) } }, // #82 [ref=3x] + { 0, 1, { EXT(AVX512_BW) } }, // #83 [ref=4x] + { 0, 1, { EXT(AVX512_F) } }, // #84 [ref=1x] + { 0, 28, { EXT(LAHFSAHF) } }, // #85 [ref=1x] + { 0, 0, { EXT(AMX_TILE) } }, // #86 [ref=7x] + { 0, 0, { EXT(LWP) } }, // #87 [ref=4x] + { 0, 29, { 0 } }, // #88 [ref=3x] + { 0, 1, { EXT(LZCNT) } }, // #89 [ref=1x] + { 0, 0, { EXT(MMX2) } }, // #90 [ref=3x] + { 0, 1, { EXT(MCOMMIT) } }, // #91 [ref=1x] + { 0, 0, { EXT(MONITOR) } }, // #92 [ref=2x] + { 0, 0, { EXT(MONITORX) } }, // #93 [ref=2x] + { 1, 0, { 0 } }, // #94 [ref=1x] + { 1, 0, { EXT(SSE2) } }, // #95 [ref=5x] + { 1, 0, { EXT(SSE) } }, // #96 [ref=3x] + { 0, 0, { EXT(MOVBE) } }, // #97 [ref=1x] + { 0, 0, { EXT(MMX), EXT(SSE2) } }, // #98 [ref=45x] + { 0, 0, { EXT(MOVDIR64B) } }, // #99 [ref=1x] + { 0, 0, { EXT(MOVDIRI) } }, // #100 [ref=1x] + { 1, 0, { EXT(MMX), EXT(SSE2) } }, // #101 [ref=1x] + { 0, 0, { EXT(BMI2) } }, // #102 [ref=7x] + { 0, 0, { EXT(SSSE3) } }, // #103 [ref=16x] + { 0, 0, { EXT(MMX2), EXT(SSE2) } }, // #104 [ref=10x] + { 0, 0, { EXT(PCLMULQDQ) } }, // #105 [ref=1x] + { 0, 1, { EXT(SSE4_2) } }, // #106 [ref=4x] + { 0, 0, { EXT(PCONFIG) } }, // #107 [ref=1x] + { 0, 0, { EXT(MMX2), EXT(SSE2), EXT(SSE4_1) } }, // #108 [ref=1x] + { 0, 0, { EXT(3DNOW2) } }, // #109 [ref=5x] + { 0, 0, { EXT(GEODE) } }, // #110 [ref=2x] + { 0, 1, { EXT(POPCNT) } }, // #111 [ref=1x] + { 0, 30, { 0 } }, // #112 [ref=3x] + { 0, 0, { EXT(PREFETCHI) } }, // #113 [ref=2x] + { 0, 1, { EXT(PREFETCHW) } }, // #114 [ref=1x] + { 0, 1, { EXT(PREFETCHWT1) } }, // #115 [ref=1x] + { 0, 20, { EXT(SEV_SNP) } }, // #116 [ref=3x] + { 0, 1, { EXT(SSE4_1) } }, // #117 [ref=1x] + { 0, 0, { EXT(PTWRITE) } }, // #118 [ref=1x] + { 0, 31, { 0 } }, // #119 [ref=3x] + { 0, 1, { EXT(SEV_SNP) } }, // #120 [ref=1x] + { 0, 32, { 0 } }, // #121 [ref=2x] + { 0, 0, { EXT(FSGSBASE) } }, // #122 [ref=4x] + { 0, 0, { EXT(MSR) } }, // #123 [ref=2x] + { 0, 0, { EXT(RDPID) } }, // #124 [ref=1x] + { 0, 0, { EXT(OSPKE) } }, // #125 [ref=1x] + { 0, 0, { EXT(RDPRU) } }, // #126 [ref=1x] + { 0, 1, { EXT(RDRAND) } }, // #127 [ref=1x] + { 0, 1, { EXT(RDSEED) } }, // #128 [ref=1x] + { 0, 0, { EXT(RDTSC) } }, // #129 [ref=1x] + { 0, 0, { EXT(RDTSCP) } }, // #130 [ref=1x] + { 0, 33, { 0 } }, // #131 [ref=2x] + { 0, 34, { EXT(LAHFSAHF) } }, // #132 [ref=1x] + { 0, 0, { EXT(SEAM) } }, // #133 [ref=4x] + { 0, 0, { EXT(SERIALIZE) } }, // #134 [ref=1x] + { 0, 0, { EXT(SHA) } }, // #135 [ref=7x] + { 0, 0, { EXT(SKINIT) } }, // #136 [ref=2x] + { 0, 0, { EXT(AMX_COMPLEX) } }, // #137 [ref=2x] + { 0, 0, { EXT(AMX_BF16) } }, // #138 [ref=1x] + { 0, 0, { EXT(AMX_INT8) } }, // #139 [ref=4x] + { 0, 0, { EXT(AMX_FP16) } }, // #140 [ref=1x] + { 0, 1, { EXT(UINTR) } }, // #141 [ref=1x] + { 0, 1, { EXT(WAITPKG) } }, // #142 [ref=2x] + { 0, 0, { EXT(WAITPKG) } }, // #143 [ref=1x] + { 0, 0, { EXT(AVX512_4FMAPS) } }, // #144 [ref=4x] + { 0, 0, { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL) } }, // #145 [ref=38x] + { 0, 0, { EXT(AVX512_FP16), EXT(AVX512_VL) } }, // #146 [ref=60x] + { 0, 0, { EXT(AVX), EXT(AVX512_F) } }, // #147 [ref=33x] + { 0, 0, { EXT(AVX512_FP16) } }, // #148 [ref=44x] + { 0, 0, { EXT(AVX) } }, // #149 [ref=35x] + { 0, 0, { EXT(AESNI), EXT(VAES), EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL) } }, // #150 [ref=4x] + { 0, 0, { EXT(AESNI), EXT(AVX) } }, // #151 [ref=2x] + { 0, 0, { EXT(AVX512_F), EXT(AVX512_VL) } }, // #152 [ref=108x] + { 0, 0, { EXT(AVX), EXT(AVX512_DQ), EXT(AVX512_VL) } }, // #153 [ref=8x] + { 0, 0, { EXT(AVX_NE_CONVERT) } }, // #154 [ref=6x] + { 0, 0, { EXT(AVX512_DQ), EXT(AVX512_VL) } }, // #155 [ref=30x] + { 0, 0, { EXT(AVX2) } }, // #156 [ref=7x] + { 0, 0, { EXT(AVX), EXT(AVX2), EXT(AVX512_F), EXT(AVX512_VL) } }, // #157 [ref=39x] + { 0, 1, { EXT(AVX), EXT(AVX512_F) } }, // #158 [ref=4x] + { 0, 1, { EXT(AVX512_FP16) } }, // #159 [ref=2x] + { 0, 0, { EXT(AVX512_BF16), EXT(AVX512_VL) } }, // #160 [ref=2x] + { 0, 0, { EXT(AVX_NE_CONVERT), EXT(AVX512_BF16), EXT(AVX512_VL) } }, // #161 [ref=1x] + { 0, 0, { EXT(F16C), EXT(AVX512_F), EXT(AVX512_VL) } }, // #162 [ref=2x] + { 0, 0, { EXT(AVX512_BW), EXT(AVX512_VL) } }, // #163 [ref=24x] + { 0, 0, { EXT(AVX512_ER) } }, // #164 [ref=10x] + { 0, 0, { EXT(FMA), EXT(AVX512_F), EXT(AVX512_VL) } }, // #165 [ref=36x] + { 0, 0, { EXT(FMA), EXT(AVX512_F) } }, // #166 [ref=24x] + { 0, 0, { EXT(FMA4) } }, // #167 [ref=20x] + { 0, 0, { EXT(XOP) } }, // #168 [ref=55x] + { 0, 0, { EXT(AVX2), EXT(AVX512_F), EXT(AVX512_VL) } }, // #169 [ref=19x] + { 0, 0, { EXT(AVX512_PF) } }, // #170 [ref=16x] + { 0, 0, { EXT(GFNI), EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL) } }, // #171 [ref=3x] + { 0, 0, { EXT(SEV_ES) } }, // #172 [ref=1x] + { 1, 0, { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL) } }, // #173 [ref=4x] + { 1, 0, { EXT(AVX) } }, // #174 [ref=2x] + { 1, 0, { EXT(AVX512_F), EXT(AVX512_VL) } }, // #175 [ref=4x] + { 1, 0, { EXT(AVX512_BW), EXT(AVX512_VL) } }, // #176 [ref=2x] + { 1, 0, { EXT(AVX), EXT(AVX512_F) } }, // #177 [ref=3x] + { 0, 0, { EXT(AVX), EXT(AVX2) } }, // #178 [ref=17x] + { 0, 0, { EXT(AVX512_VL), EXT(AVX512_VP2INTERSECT) } }, // #179 [ref=2x] + { 0, 0, { EXT(AVX512_4VNNIW) } }, // #180 [ref=2x] + { 0, 0, { EXT(AVX), EXT(AVX2), EXT(AVX512_BW), EXT(AVX512_VL) } }, // #181 [ref=54x] + { 0, 0, { EXT(AVX2), EXT(AVX512_BW), EXT(AVX512_VL) } }, // #182 [ref=2x] + { 0, 0, { EXT(AVX512_CD), EXT(AVX512_VL) } }, // #183 [ref=6x] + { 0, 0, { EXT(PCLMULQDQ), EXT(VPCLMULQDQ), EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL) } }, // #184 [ref=1x] + { 0, 1, { EXT(AVX) } }, // #185 [ref=7x] + { 0, 0, { EXT(AVX512_VBMI2), EXT(AVX512_VL) } }, // #186 [ref=16x] + { 0, 0, { EXT(AVX_VNNI_INT8) } }, // #187 [ref=6x] + { 0, 0, { EXT(AVX_VNNI), EXT(AVX512_VL), EXT(AVX512_VNNI) } }, // #188 [ref=4x] + { 0, 0, { EXT(AVX_VNNI_INT16) } }, // #189 [ref=6x] + { 0, 0, { EXT(AVX512_VBMI), EXT(AVX512_VL) } }, // #190 [ref=4x] + { 0, 0, { EXT(AVX), EXT(AVX512_BW) } }, // #191 [ref=4x] + { 0, 0, { EXT(AVX), EXT(AVX512_DQ) } }, // #192 [ref=4x] + { 0, 0, { EXT(AVX_IFMA), EXT(AVX512_IFMA), EXT(AVX512_VL) } }, // #193 [ref=2x] + { 0, 0, { EXT(AVX512_BITALG), EXT(AVX512_VL) } }, // #194 [ref=3x] + { 0, 0, { EXT(AVX512_VL), EXT(AVX512_VPOPCNTDQ) } }, // #195 [ref=2x] + { 0, 0, { EXT(SHA512), EXT(AVX) } }, // #196 [ref=3x] + { 0, 0, { EXT(SM3), EXT(AVX) } }, // #197 [ref=3x] + { 0, 0, { EXT(SM4), EXT(AVX) } }, // #198 [ref=2x] + { 0, 0, { EXT(WBNOINVD) } }, // #199 [ref=1x] + { 0, 0, { EXT(RTM) } }, // #200 [ref=3x] + { 0, 0, { EXT(XSAVE) } }, // #201 [ref=6x] + { 0, 0, { EXT(TSXLDTRK) } }, // #202 [ref=2x] + { 0, 0, { EXT(XSAVES) } }, // #203 [ref=4x] + { 0, 0, { EXT(XSAVEC) } }, // #204 [ref=2x] + { 0, 0, { EXT(XSAVEOPT) } }, // #205 [ref=2x] + { 0, 1, { EXT(TSX) } } // #206 [ref=1x] }; #undef EXT #define FLAG(VAL) uint32_t(CpuRWFlags::kX86_##VAL) const InstDB::RWFlagsInfoTable InstDB::_rwFlagsInfoTable[] = { - { 0, 0 }, // #0 [ref=1429x] - { 0, FLAG(AF) | FLAG(CF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #1 [ref=84x] + { 0, 0 }, // #0 [ref=1383x] + { 0, FLAG(AF) | FLAG(CF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #1 [ref=104x] { FLAG(CF), FLAG(AF) | FLAG(CF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #2 [ref=2x] { FLAG(CF), FLAG(CF) }, // #3 [ref=2x] { FLAG(OF), FLAG(OF) }, // #4 [ref=1x] @@ -2809,30 +2879,36 @@ const InstDB::RWFlagsInfoTable InstDB::_rwFlagsInfoTable[] = { { 0, FLAG(CF) }, // #8 [ref=2x] { 0, FLAG(DF) }, // #9 [ref=2x] { 0, FLAG(IF) }, // #10 [ref=2x] - { FLAG(CF) | FLAG(ZF), 0 }, // #11 [ref=14x] - { FLAG(CF), 0 }, // #12 [ref=20x] - { FLAG(ZF), 0 }, // #13 [ref=16x] + { FLAG(CF) | FLAG(ZF), 0 }, // #11 [ref=12x] + { FLAG(CF), 0 }, // #12 [ref=18x] + { FLAG(ZF), 0 }, // #13 [ref=14x] { FLAG(OF) | FLAG(SF) | FLAG(ZF), 0 }, // #14 [ref=12x] { FLAG(OF) | FLAG(SF), 0 }, // #15 [ref=12x] { FLAG(OF), 0 }, // #16 [ref=7x] - { FLAG(PF), 0 }, // #17 [ref=14x] + { FLAG(PF), 0 }, // #17 [ref=12x] { FLAG(SF), 0 }, // #18 [ref=6x] { FLAG(DF), FLAG(AF) | FLAG(CF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #19 [ref=2x] { 0, FLAG(AF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #20 [ref=5x] - { 0, FLAG(CF) | FLAG(PF) | FLAG(ZF) }, // #21 [ref=4x] - { FLAG(AF) | FLAG(CF) | FLAG(PF) | FLAG(SF) | FLAG(ZF), 0 }, // #22 [ref=1x] - { FLAG(DF), 0 }, // #23 [ref=3x] - { 0, FLAG(AF) | FLAG(CF) | FLAG(DF) | FLAG(IF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #24 [ref=3x] - { FLAG(AF) | FLAG(CF) | FLAG(DF) | FLAG(IF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF), 0 }, // #25 [ref=3x] - { FLAG(CF) | FLAG(OF), FLAG(CF) | FLAG(OF) }, // #26 [ref=2x] - { 0, FLAG(CF) | FLAG(OF) }, // #27 [ref=2x] - { 0, FLAG(AF) | FLAG(CF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) } // #28 [ref=1x] + { 0, FLAG(C0) | FLAG(C1) | FLAG(C2) | FLAG(C3) }, // #21 [ref=83x] + { FLAG(CF), FLAG(C0) | FLAG(C1) | FLAG(C2) | FLAG(C3) }, // #22 [ref=2x] + { FLAG(CF) | FLAG(ZF), FLAG(C0) | FLAG(C1) | FLAG(C2) | FLAG(C3) }, // #23 [ref=2x] + { FLAG(ZF), FLAG(C0) | FLAG(C1) | FLAG(C2) | FLAG(C3) }, // #24 [ref=2x] + { FLAG(PF), FLAG(C0) | FLAG(C1) | FLAG(C2) | FLAG(C3) }, // #25 [ref=2x] + { 0, FLAG(C1) | FLAG(CF) | FLAG(PF) | FLAG(ZF) }, // #26 [ref=4x] + { FLAG(C0) | FLAG(C1) | FLAG(C2) | FLAG(C3), 0 }, // #27 [ref=2x] + { FLAG(AF) | FLAG(CF) | FLAG(PF) | FLAG(SF) | FLAG(ZF), 0 }, // #28 [ref=1x] + { FLAG(DF), 0 }, // #29 [ref=3x] + { 0, FLAG(AF) | FLAG(CF) | FLAG(DF) | FLAG(IF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #30 [ref=3x] + { FLAG(AF) | FLAG(CF) | FLAG(DF) | FLAG(IF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF), 0 }, // #31 [ref=3x] + { FLAG(CF) | FLAG(OF), FLAG(CF) | FLAG(OF) }, // #32 [ref=2x] + { 0, FLAG(CF) | FLAG(OF) }, // #33 [ref=2x] + { 0, FLAG(AF) | FLAG(CF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) } // #34 [ref=1x] }; #undef FLAG #define FLAG(VAL) uint32_t(InstRWFlags::k##VAL) const InstRWFlags InstDB::_instFlagsTable[] = { - InstRWFlags(FLAG(None)), // #0 [ref=1634x] + InstRWFlags(FLAG(None)), // #0 [ref=1693x] InstRWFlags(FLAG(MovOp)) // #1 [ref=29x] }; #undef FLAG @@ -2845,164 +2921,8 @@ const InstRWFlags InstDB::_instFlagsTable[] = { #ifndef ASMJIT_NO_TEXT // ${NameData:Begin} // ------------------- Automatically generated, do not edit ------------------- -const char InstDB::_nameData[] = - "\0" "aaa\0" "aad\0" "aam\0" "aas\0" "adc\0" "adcx\0" "adox\0" "arpl\0" "bextr\0" "blcfill\0" "blci\0" "blcic\0" - "blcmsk\0" "blcs\0" "blsfill\0" "blsi\0" "blsic\0" "blsmsk\0" "blsr\0" "bndcl\0" "bndcn\0" "bndcu\0" "bndldx\0" - "bndmk\0" "bndmov\0" "bndstx\0" "bound\0" "bsf\0" "bsr\0" "bswap\0" "bt\0" "btc\0" "btr\0" "bts\0" "bzhi\0" "cbw\0" - "cdq\0" "cdqe\0" "clac\0" "clc\0" "cld\0" "cldemote\0" "clflush\0" "clflushopt\0" "clgi\0" "cli\0" "clrssbsy\0" - "clts\0" "clui\0" "clwb\0" "clzero\0" "cmc\0" "cmova\0" "cmovae\0" "cmovc\0" "cmovg\0" "cmovge\0" "cmovl\0" - "cmovle\0" "cmovna\0" "cmovnae\0" "cmovnc\0" "cmovng\0" "cmovnge\0" "cmovnl\0" "cmovnle\0" "cmovno\0" "cmovnp\0" - "cmovns\0" "cmovnz\0" "cmovo\0" "cmovp\0" "cmovpe\0" "cmovpo\0" "cmovs\0" "cmovz\0" "cmp\0" "cmps\0" "cmpxchg\0" - "cmpxchg16b\0" "cmpxchg8b\0" "cpuid\0" "cqo\0" "crc32\0" "cvtpd2pi\0" "cvtpi2pd\0" "cvtpi2ps\0" "cvtps2pi\0" - "cvttpd2pi\0" "cvttps2pi\0" "cwd\0" "cwde\0" "daa\0" "das\0" "endbr32\0" "endbr64\0" "enqcmd\0" "enqcmds\0" "f2xm1\0" - "fabs\0" "faddp\0" "fbld\0" "fbstp\0" "fchs\0" "fclex\0" "fcmovb\0" "fcmovbe\0" "fcmove\0" "fcmovnb\0" "fcmovnbe\0" - "fcmovne\0" "fcmovnu\0" "fcmovu\0" "fcom\0" "fcomi\0" "fcomip\0" "fcomp\0" "fcompp\0" "fcos\0" "fdecstp\0" "fdiv\0" - "fdivp\0" "fdivr\0" "fdivrp\0" "femms\0" "ffree\0" "fiadd\0" "ficom\0" "ficomp\0" "fidiv\0" "fidivr\0" "fild\0" - "fimul\0" "fincstp\0" "finit\0" "fist\0" "fistp\0" "fisttp\0" "fisub\0" "fisubr\0" "fld\0" "fld1\0" "fldcw\0" - "fldenv\0" "fldl2e\0" "fldl2t\0" "fldlg2\0" "fldln2\0" "fldpi\0" "fldz\0" "fmulp\0" "fnclex\0" "fninit\0" "fnop\0" - "fnsave\0" "fnstcw\0" "fnstenv\0" "fnstsw\0" "fpatan\0" "fprem\0" "fprem1\0" "fptan\0" "frndint\0" "frstor\0" - "fsave\0" "fscale\0" "fsin\0" "fsincos\0" "fsqrt\0" "fst\0" "fstcw\0" "fstenv\0" "fstp\0" "fstsw\0" "fsubp\0" - "fsubrp\0" "ftst\0" "fucom\0" "fucomi\0" "fucomip\0" "fucomp\0" "fucompp\0" "fwait\0" "fxam\0" "fxch\0" "fxrstor\0" - "fxrstor64\0" "fxsave\0" "fxsave64\0" "fxtract\0" "fyl2x\0" "fyl2xp1\0" "getsec\0" "hlt\0" "hreset\0" "inc\0" - "incsspd\0" "incsspq\0" "insertq\0" "int3\0" "into\0" "invept\0" "invlpg\0" "invlpga\0" "invpcid\0" "invvpid\0" - "iretd\0" "iretq\0" "ja\0" "jae\0" "jb\0" "jbe\0" "jc\0" "je\0" "jecxz\0" "jg\0" "jge\0" "jl\0" "jle\0" "jna\0" - "jnae\0" "jnb\0" "jnbe\0" "jnc\0" "jne\0" "jng\0" "jnge\0" "jnl\0" "jnle\0" "jno\0" "jnp\0" "jns\0" "jnz\0" "jo\0" - "jp\0" "jpe\0" "jpo\0" "js\0" "jz\0" "kaddb\0" "kaddd\0" "kaddq\0" "kaddw\0" "kandb\0" "kandd\0" "kandnb\0" - "kandnd\0" "kandnq\0" "kandnw\0" "kandq\0" "kandw\0" "kmovb\0" "kmovw\0" "knotb\0" "knotd\0" "knotq\0" "knotw\0" - "korb\0" "kord\0" "korq\0" "kortestb\0" "kortestd\0" "kortestq\0" "kortestw\0" "korw\0" "kshiftlb\0" "kshiftld\0" - "kshiftlq\0" "kshiftlw\0" "kshiftrb\0" "kshiftrd\0" "kshiftrq\0" "kshiftrw\0" "ktestb\0" "ktestd\0" "ktestq\0" - "ktestw\0" "kunpckbw\0" "kunpckdq\0" "kunpckwd\0" "kxnorb\0" "kxnord\0" "kxnorq\0" "kxnorw\0" "kxorb\0" "kxord\0" - "kxorq\0" "kxorw\0" "lahf\0" "lar\0" "lcall\0" "lds\0" "ldtilecfg\0" "lea\0" "leave\0" "les\0" "lfence\0" "lfs\0" - "lgdt\0" "lgs\0" "lidt\0" "ljmp\0" "lldt\0" "llwpcb\0" "lmsw\0" "lods\0" "loop\0" "loope\0" "loopne\0" "lsl\0" - "ltr\0" "lwpins\0" "lwpval\0" "lzcnt\0" "mcommit\0" "mfence\0" "monitorx\0" "movabs\0" "movdir64b\0" "movdiri\0" - "movdq2q\0" "movnti\0" "movntq\0" "movntsd\0" "movntss\0" "movq2dq\0" "movsx\0" "movsxd\0" "movzx\0" "mulx\0" - "mwaitx\0" "neg\0" "not\0" "out\0" "outs\0" "pavgusb\0" "pconfig\0" "pdep\0" "pext\0" "pf2id\0" "pf2iw\0" "pfacc\0" - "pfadd\0" "pfcmpeq\0" "pfcmpge\0" "pfcmpgt\0" "pfmax\0" "pfmin\0" "pfmul\0" "pfnacc\0" "pfpnacc\0" "pfrcp\0" - "pfrcpit1\0" "pfrcpit2\0" "pfrcpv\0" "pfrsqit1\0" "pfrsqrt\0" "pfrsqrtv\0" "pfsub\0" "pfsubr\0" "pi2fd\0" "pi2fw\0" - "pmulhrw\0" "pop\0" "popa\0" "popad\0" "popcnt\0" "popf\0" "popfd\0" "popfq\0" "prefetch\0" "prefetchnta\0" - "prefetcht0\0" "prefetcht1\0" "prefetcht2\0" "prefetchw\0" "prefetchwt1\0" "pshufw\0" "psmash\0" "pswapd\0" - "ptwrite\0" "push\0" "pusha\0" "pushad\0" "pushf\0" "pushfd\0" "pushfq\0" "pvalidate\0" "rcl\0" "rcr\0" "rdfsbase\0" - "rdgsbase\0" "rdmsr\0" "rdpid\0" "rdpkru\0" "rdpmc\0" "rdpru\0" "rdrand\0" "rdseed\0" "rdsspd\0" "rdsspq\0" "rdtsc\0" - "rdtscp\0" "retf\0" "rmpadjust\0" "rmpupdate\0" "rol\0" "ror\0" "rorx\0" "rsm\0" "rstorssp\0" "sahf\0" "sal\0" - "sar\0" "sarx\0" "saveprevssp\0" "sbb\0" "scas\0" "senduipi\0" "serialize\0" "seta\0" "setae\0" "setb\0" "setbe\0" - "setc\0" "sete\0" "setg\0" "setge\0" "setl\0" "setle\0" "setna\0" "setnae\0" "setnb\0" "setnbe\0" "setnc\0" "setne\0" - "setng\0" "setnge\0" "setnl\0" "setnle\0" "setno\0" "setnp\0" "setns\0" "setnz\0" "seto\0" "setp\0" "setpe\0" - "setpo\0" "sets\0" "setssbsy\0" "setz\0" "sfence\0" "sgdt\0" "sha1msg1\0" "sha1msg2\0" "sha1nexte\0" "sha1rnds4\0" - "sha256msg1\0" "sha256msg2\0" "sha256rnds2\0" "shl\0" "shlx\0" "shr\0" "shrd\0" "shrx\0" "sidt\0" "skinit\0" "sldt\0" - "slwpcb\0" "smsw\0" "stac\0" "stc\0" "stgi\0" "sti\0" "stos\0" "str\0" "sttilecfg\0" "swapgs\0" "syscall\0" - "sysenter\0" "sysexit\0" "sysexitq\0" "sysret\0" "sysretq\0" "t1mskc\0" "tdpbf16ps\0" "tdpbssd\0" "tdpbsud\0" - "tdpbusd\0" "tdpbuud\0" "testui\0" "tileloadd\0" "tileloaddt1\0" "tilerelease\0" "tilestored\0" "tilezero\0" - "tpause\0" "tzcnt\0" "tzmsk\0" "ud0\0" "ud1\0" "ud2\0" "uiret\0" "umonitor\0" "umwait\0" "v4fmaddps\0" "v4fmaddss\0" - "v4fnmaddps\0" "v4fnmaddss\0" "vaddpd\0" "vaddph\0" "vaddps\0" "vaddsd\0" "vaddsh\0" "vaddss\0" "vaddsubpd\0" - "vaddsubps\0" "vaesdec\0" "vaesdeclast\0" "vaesenc\0" "vaesenclast\0" "vaesimc\0" "vaeskeygenassist\0" "valignd\0" - "valignq\0" "vandnpd\0" "vandnps\0" "vandpd\0" "vandps\0" "vblendmpd\0" "vblendmps\0" "vblendpd\0" "vblendps\0" - "vblendvpd\0" "vblendvps\0" "vbroadcastf128\0" "vbroadcastf32x2\0" "vbroadcastf32x4\0" "vbroadcastf32x8\0" - "vbroadcastf64x2\0" "vbroadcastf64x4\0" "vbroadcasti128\0" "vbroadcasti32x2\0" "vbroadcasti32x4\0" - "vbroadcasti32x8\0" "vbroadcasti64x2\0" "vbroadcasti64x4\0" "vbroadcastsd\0" "vbroadcastss\0" "vcmppd\0" "vcmpph\0" - "vcmpps\0" "vcmpsd\0" "vcmpsh\0" "vcmpss\0" "vcomisd\0" "vcomish\0" "vcomiss\0" "vcompresspd\0" "vcompressps\0" - "vcvtdq2pd\0" "vcvtdq2ph\0" "vcvtdq2ps\0" "vcvtne2ps2bf16\0" "vcvtneps2bf16\0" "vcvtpd2dq\0" "vcvtpd2ph\0" - "vcvtpd2ps\0" "vcvtpd2qq\0" "vcvtpd2udq\0" "vcvtpd2uqq\0" "vcvtph2dq\0" "vcvtph2pd\0" "vcvtph2ps\0" "vcvtph2psx\0" - "vcvtph2qq\0" "vcvtph2udq\0" "vcvtph2uqq\0" "vcvtph2uw\0" "vcvtph2w\0" "vcvtps2dq\0" "vcvtps2pd\0" "vcvtps2ph\0" - "vcvtps2phx\0" "vcvtps2qq\0" "vcvtps2udq\0" "vcvtps2uqq\0" "vcvtqq2pd\0" "vcvtqq2ph\0" "vcvtqq2ps\0" "vcvtsd2sh\0" - "vcvtsd2si\0" "vcvtsd2ss\0" "vcvtsd2usi\0" "vcvtsh2sd\0" "vcvtsh2si\0" "vcvtsh2ss\0" "vcvtsh2usi\0" "vcvtsi2sd\0" - "vcvtsi2sh\0" "vcvtsi2ss\0" "vcvtss2sd\0" "vcvtss2sh\0" "vcvtss2si\0" "vcvtss2usi\0" "vcvttpd2dq\0" "vcvttpd2qq\0" - "vcvttpd2udq\0" "vcvttpd2uqq\0" "vcvttph2dq\0" "vcvttph2qq\0" "vcvttph2udq\0" "vcvttph2uqq\0" "vcvttph2uw\0" - "vcvttph2w\0" "vcvttps2dq\0" "vcvttps2qq\0" "vcvttps2udq\0" "vcvttps2uqq\0" "vcvttsd2si\0" "vcvttsd2usi\0" - "vcvttsh2si\0" "vcvttsh2usi\0" "vcvttss2si\0" "vcvttss2usi\0" "vcvtudq2pd\0" "vcvtudq2ph\0" "vcvtudq2ps\0" - "vcvtuqq2pd\0" "vcvtuqq2ph\0" "vcvtuqq2ps\0" "vcvtusi2sd\0" "vcvtusi2sh\0" "vcvtusi2ss\0" "vcvtuw2ph\0" "vcvtw2ph\0" - "vdbpsadbw\0" "vdivpd\0" "vdivph\0" "vdivps\0" "vdivsd\0" "vdivsh\0" "vdivss\0" "vdpbf16ps\0" "vdppd\0" "vdpps\0" - "verr\0" "verw\0" "vexp2pd\0" "vexp2ps\0" "vexpandpd\0" "vexpandps\0" "vextractf128\0" "vextractf32x4\0" - "vextractf32x8\0" "vextractf64x2\0" "vextractf64x4\0" "vextracti128\0" "vextracti32x4\0" "vextracti32x8\0" - "vextracti64x2\0" "vextracti64x4\0" "vextractps\0" "vfcmaddcph\0" "vfcmaddcsh\0" "vfcmulcph\0" "vfcmulcsh\0" - "vfixupimmpd\0" "vfixupimmps\0" "vfixupimmsd\0" "vfixupimmss\0" "vfmadd132pd\0" "vfmadd132ph\0" "vfmadd132ps\0" - "vfmadd132sd\0" "vfmadd132sh\0" "vfmadd132ss\0" "vfmadd213pd\0" "vfmadd213ph\0" "vfmadd213ps\0" "vfmadd213sd\0" - "vfmadd213sh\0" "vfmadd213ss\0" "vfmadd231pd\0" "vfmadd231ph\0" "vfmadd231ps\0" "vfmadd231sd\0" "vfmadd231sh\0" - "vfmadd231ss\0" "vfmaddcph\0" "vfmaddcsh\0" "vfmaddpd\0" "vfmaddps\0" "vfmaddsd\0" "vfmaddss\0" "vfmaddsub132pd\0" - "vfmaddsub132ph\0" "vfmaddsub132ps\0" "vfmaddsub213pd\0" "vfmaddsub213ph\0" "vfmaddsub213ps\0" "vfmaddsub231pd\0" - "vfmaddsub231ph\0" "vfmaddsub231ps\0" "vfmaddsubpd\0" "vfmaddsubps\0" "vfmsub132pd\0" "vfmsub132ph\0" "vfmsub132ps\0" - "vfmsub132sd\0" "vfmsub132sh\0" "vfmsub132ss\0" "vfmsub213pd\0" "vfmsub213ph\0" "vfmsub213ps\0" "vfmsub213sd\0" - "vfmsub213sh\0" "vfmsub213ss\0" "vfmsub231pd\0" "vfmsub231ph\0" "vfmsub231ps\0" "vfmsub231sd\0" "vfmsub231sh\0" - "vfmsub231ss\0" "vfmsubadd132pd\0" "vfmsubadd132ph\0" "vfmsubadd132ps\0" "vfmsubadd213pd\0" "vfmsubadd213ph\0" - "vfmsubadd213ps\0" "vfmsubadd231pd\0" "vfmsubadd231ph\0" "vfmsubadd231ps\0" "vfmsubaddpd\0" "vfmsubaddps\0" - "vfmsubpd\0" "vfmsubps\0" "vfmsubsd\0" "vfmsubss\0" "vfmulcph\0" "vfmulcsh\0" "vfnmadd132pd\0" "vfnmadd132ph\0" - "vfnmadd132ps\0" "vfnmadd132sd\0" "vfnmadd132sh\0" "vfnmadd132ss\0" "vfnmadd213pd\0" "vfnmadd213ph\0" - "vfnmadd213ps\0" "vfnmadd213sd\0" "vfnmadd213sh\0" "vfnmadd213ss\0" "vfnmadd231pd\0" "vfnmadd231ph\0" - "vfnmadd231ps\0" "vfnmadd231sd\0" "vfnmadd231sh\0" "vfnmadd231ss\0" "vfnmaddpd\0" "vfnmaddps\0" "vfnmaddsd\0" - "vfnmaddss\0" "vfnmsub132pd\0" "vfnmsub132ph\0" "vfnmsub132ps\0" "vfnmsub132sd\0" "vfnmsub132sh\0" "vfnmsub132ss\0" - "vfnmsub213pd\0" "vfnmsub213ph\0" "vfnmsub213ps\0" "vfnmsub213sd\0" "vfnmsub213sh\0" "vfnmsub213ss\0" - "vfnmsub231pd\0" "vfnmsub231ph\0" "vfnmsub231ps\0" "vfnmsub231sd\0" "vfnmsub231sh\0" "vfnmsub231ss\0" "vfnmsubpd\0" - "vfnmsubps\0" "vfnmsubsd\0" "vfnmsubss\0" "vfpclasspd\0" "vfpclassph\0" "vfpclassps\0" "vfpclasssd\0" "vfpclasssh\0" - "vfpclassss\0" "vfrczpd\0" "vfrczps\0" "vfrczsd\0" "vfrczss\0" "vgatherdpd\0" "vgatherdps\0" "vgatherpf0dpd\0" - "vgatherpf0dps\0" "vgatherpf0qpd\0" "vgatherpf0qps\0" "vgatherpf1dpd\0" "vgatherpf1dps\0" "vgatherpf1qpd\0" - "vgatherpf1qps\0" "vgatherqpd\0" "vgatherqps\0" "vgetexppd\0" "vgetexpph\0" "vgetexpps\0" "vgetexpsd\0" "vgetexpsh\0" - "vgetexpss\0" "vgetmantpd\0" "vgetmantph\0" "vgetmantps\0" "vgetmantsd\0" "vgetmantsh\0" "vgetmantss\0" - "vgf2p8affineinvqb\0" "vgf2p8affineqb\0" "vgf2p8mulb\0" "vhaddpd\0" "vhaddps\0" "vhsubpd\0" "vhsubps\0" - "vinsertf128\0" "vinsertf32x4\0" "vinsertf32x8\0" "vinsertf64x2\0" "vinsertf64x4\0" "vinserti128\0" "vinserti32x4\0" - "vinserti32x8\0" "vinserti64x2\0" "vinserti64x4\0" "vinsertps\0" "vlddqu\0" "vldmxcsr\0" "vmaskmovdqu\0" - "vmaskmovpd\0" "vmaskmovps\0" "vmaxpd\0" "vmaxph\0" "vmaxps\0" "vmaxsd\0" "vmaxsh\0" "vmaxss\0" "vmcall\0" - "vmclear\0" "vmfunc\0" "vminpd\0" "vminph\0" "vminps\0" "vminsd\0" "vminsh\0" "vminss\0" "vmlaunch\0" "vmload\0" - "vmmcall\0" "vmovapd\0" "vmovaps\0" "vmovd\0" "vmovddup\0" "vmovdqa\0" "vmovdqa32\0" "vmovdqa64\0" "vmovdqu\0" - "vmovdqu16\0" "vmovdqu32\0" "vmovdqu64\0" "vmovdqu8\0" "vmovhlps\0" "vmovhpd\0" "vmovhps\0" "vmovlhps\0" "vmovlpd\0" - "vmovlps\0" "vmovmskpd\0" "vmovmskps\0" "vmovntdq\0" "vmovntdqa\0" "vmovntpd\0" "vmovntps\0" "vmovq\0" "vmovsd\0" - "vmovsh\0" "vmovshdup\0" "vmovsldup\0" "vmovss\0" "vmovupd\0" "vmovups\0" "vmovw\0" "vmpsadbw\0" "vmptrld\0" - "vmptrst\0" "vmread\0" "vmresume\0" "vmrun\0" "vmsave\0" "vmulpd\0" "vmulph\0" "vmulps\0" "vmulsd\0" "vmulsh\0" - "vmulss\0" "vmwrite\0" "vmxon\0" "vorpd\0" "vorps\0" "vp2intersectd\0" "vp2intersectq\0" "vp4dpwssd\0" "vp4dpwssds\0" - "vpabsb\0" "vpabsd\0" "vpabsq\0" "vpabsw\0" "vpackssdw\0" "vpacksswb\0" "vpackusdw\0" "vpackuswb\0" "vpaddb\0" - "vpaddd\0" "vpaddq\0" "vpaddsb\0" "vpaddsw\0" "vpaddusb\0" "vpaddusw\0" "vpaddw\0" "vpalignr\0" "vpand\0" "vpandd\0" - "vpandn\0" "vpandnd\0" "vpandnq\0" "vpandq\0" "vpavgb\0" "vpavgw\0" "vpblendd\0" "vpblendmb\0" "vpblendmd\0" - "vpblendmq\0" "vpblendmw\0" "vpblendvb\0" "vpblendw\0" "vpbroadcastb\0" "vpbroadcastd\0" "vpbroadcastmb2q\0" - "vpbroadcastmw2d\0" "vpbroadcastq\0" "vpbroadcastw\0" "vpclmulqdq\0" "vpcmov\0" "vpcmpb\0" "vpcmpd\0" "vpcmpeqb\0" - "vpcmpeqd\0" "vpcmpeqq\0" "vpcmpeqw\0" "vpcmpestri\0" "vpcmpestrm\0" "vpcmpgtb\0" "vpcmpgtd\0" "vpcmpgtq\0" - "vpcmpgtw\0" "vpcmpistri\0" "vpcmpistrm\0" "vpcmpq\0" "vpcmpub\0" "vpcmpud\0" "vpcmpuq\0" "vpcmpuw\0" "vpcmpw\0" - "vpcomb\0" "vpcomd\0" "vpcompressb\0" "vpcompressd\0" "vpcompressq\0" "vpcompressw\0" "vpcomq\0" "vpcomub\0" - "vpcomud\0" "vpcomuq\0" "vpcomuw\0" "vpcomw\0" "vpconflictd\0" "vpconflictq\0" "vpdpbusd\0" "vpdpbusds\0" - "vpdpwssd\0" "vpdpwssds\0" "vperm2f128\0" "vperm2i128\0" "vpermb\0" "vpermd\0" "vpermi2b\0" "vpermi2d\0" - "vpermi2pd\0" "vpermi2ps\0" "vpermi2q\0" "vpermi2w\0" "vpermil2pd\0" "vpermil2ps\0" "vpermilpd\0" "vpermilps\0" - "vpermpd\0" "vpermps\0" "vpermq\0" "vpermt2b\0" "vpermt2d\0" "vpermt2pd\0" "vpermt2ps\0" "vpermt2q\0" "vpermt2w\0" - "vpermw\0" "vpexpandb\0" "vpexpandd\0" "vpexpandq\0" "vpexpandw\0" "vpextrb\0" "vpextrd\0" "vpextrq\0" "vpextrw\0" - "vpgatherdd\0" "vpgatherdq\0" "vpgatherqd\0" "vpgatherqq\0" "vphaddbd\0" "vphaddbq\0" "vphaddbw\0" "vphaddd\0" - "vphadddq\0" "vphaddsw\0" "vphaddubd\0" "vphaddubq\0" "vphaddubw\0" "vphaddudq\0" "vphadduwd\0" "vphadduwq\0" - "vphaddw\0" "vphaddwd\0" "vphaddwq\0" "vphminposuw\0" "vphsubbw\0" "vphsubd\0" "vphsubdq\0" "vphsubsw\0" "vphsubw\0" - "vphsubwd\0" "vpinsrb\0" "vpinsrd\0" "vpinsrq\0" "vpinsrw\0" "vplzcntd\0" "vplzcntq\0" "vpmacsdd\0" "vpmacsdqh\0" - "vpmacsdql\0" "vpmacssdd\0" "vpmacssdqh\0" "vpmacssdql\0" "vpmacsswd\0" "vpmacssww\0" "vpmacswd\0" "vpmacsww\0" - "vpmadcsswd\0" "vpmadcswd\0" "vpmadd52huq\0" "vpmadd52luq\0" "vpmaddubsw\0" "vpmaddwd\0" "vpmaskmovd\0" - "vpmaskmovq\0" "vpmaxsb\0" "vpmaxsd\0" "vpmaxsq\0" "vpmaxsw\0" "vpmaxub\0" "vpmaxud\0" "vpmaxuq\0" "vpmaxuw\0" - "vpminsb\0" "vpminsd\0" "vpminsq\0" "vpminsw\0" "vpminub\0" "vpminud\0" "vpminuq\0" "vpminuw\0" "vpmovb2m\0" - "vpmovd2m\0" "vpmovdb\0" "vpmovdw\0" "vpmovm2b\0" "vpmovm2d\0" "vpmovm2q\0" "vpmovm2w\0" "vpmovmskb\0" "vpmovq2m\0" - "vpmovqb\0" "vpmovqd\0" "vpmovqw\0" "vpmovsdb\0" "vpmovsdw\0" "vpmovsqb\0" "vpmovsqd\0" "vpmovsqw\0" "vpmovswb\0" - "vpmovsxbd\0" "vpmovsxbq\0" "vpmovsxbw\0" "vpmovsxdq\0" "vpmovsxwd\0" "vpmovsxwq\0" "vpmovusdb\0" "vpmovusdw\0" - "vpmovusqb\0" "vpmovusqd\0" "vpmovusqw\0" "vpmovuswb\0" "vpmovw2m\0" "vpmovwb\0" "vpmovzxbd\0" "vpmovzxbq\0" - "vpmovzxbw\0" "vpmovzxdq\0" "vpmovzxwd\0" "vpmovzxwq\0" "vpmuldq\0" "vpmulhrsw\0" "vpmulhuw\0" "vpmulhw\0" - "vpmulld\0" "vpmullq\0" "vpmullw\0" "vpmultishiftqb\0" "vpmuludq\0" "vpopcntb\0" "vpopcntd\0" "vpopcntq\0" - "vpopcntw\0" "vpor\0" "vpord\0" "vporq\0" "vpperm\0" "vprold\0" "vprolq\0" "vprolvd\0" "vprolvq\0" "vprord\0" - "vprorq\0" "vprorvd\0" "vprorvq\0" "vprotb\0" "vprotd\0" "vprotq\0" "vprotw\0" "vpsadbw\0" "vpscatterdd\0" - "vpscatterdq\0" "vpscatterqd\0" "vpscatterqq\0" "vpshab\0" "vpshad\0" "vpshaq\0" "vpshaw\0" "vpshlb\0" "vpshld\0" - "vpshldd\0" "vpshldq\0" "vpshldvd\0" "vpshldvq\0" "vpshldvw\0" "vpshldw\0" "vpshlq\0" "vpshlw\0" "vpshrdd\0" - "vpshrdq\0" "vpshrdvd\0" "vpshrdvq\0" "vpshrdvw\0" "vpshrdw\0" "vpshufb\0" "vpshufbitqmb\0" "vpshufd\0" "vpshufhw\0" - "vpshuflw\0" "vpsignb\0" "vpsignd\0" "vpsignw\0" "vpslld\0" "vpslldq\0" "vpsllq\0" "vpsllvd\0" "vpsllvq\0" - "vpsllvw\0" "vpsllw\0" "vpsrad\0" "vpsraq\0" "vpsravd\0" "vpsravq\0" "vpsravw\0" "vpsraw\0" "vpsrld\0" "vpsrldq\0" - "vpsrlq\0" "vpsrlvd\0" "vpsrlvq\0" "vpsrlvw\0" "vpsrlw\0" "vpsubb\0" "vpsubd\0" "vpsubq\0" "vpsubsb\0" "vpsubsw\0" - "vpsubusb\0" "vpsubusw\0" "vpsubw\0" "vpternlogd\0" "vpternlogq\0" "vptest\0" "vptestmb\0" "vptestmd\0" "vptestmq\0" - "vptestmw\0" "vptestnmb\0" "vptestnmd\0" "vptestnmq\0" "vptestnmw\0" "vpunpckhbw\0" "vpunpckhdq\0" "vpunpckhqdq\0" - "vpunpckhwd\0" "vpunpcklbw\0" "vpunpckldq\0" "vpunpcklqdq\0" "vpunpcklwd\0" "vpxor\0" "vpxord\0" "vpxorq\0" - "vrangepd\0" "vrangeps\0" "vrangesd\0" "vrangess\0" "vrcp14pd\0" "vrcp14ps\0" "vrcp14sd\0" "vrcp14ss\0" "vrcp28pd\0" - "vrcp28ps\0" "vrcp28sd\0" "vrcp28ss\0" "vrcpph\0" "vrcpps\0" "vrcpsh\0" "vrcpss\0" "vreducepd\0" "vreduceph\0" - "vreduceps\0" "vreducesd\0" "vreducesh\0" "vreducess\0" "vrndscalepd\0" "vrndscaleph\0" "vrndscaleps\0" - "vrndscalesd\0" "vrndscalesh\0" "vrndscaless\0" "vroundpd\0" "vroundps\0" "vroundsd\0" "vroundss\0" "vrsqrt14pd\0" - "vrsqrt14ps\0" "vrsqrt14sd\0" "vrsqrt14ss\0" "vrsqrt28pd\0" "vrsqrt28ps\0" "vrsqrt28sd\0" "vrsqrt28ss\0" "vrsqrtph\0" - "vrsqrtps\0" "vrsqrtsh\0" "vrsqrtss\0" "vscalefpd\0" "vscalefph\0" "vscalefps\0" "vscalefsd\0" "vscalefsh\0" - "vscalefss\0" "vscatterdpd\0" "vscatterdps\0" "vscatterpf0dpd\0" "vscatterpf0dps\0" "vscatterpf0qpd\0" - "vscatterpf0qps\0" "vscatterpf1dpd\0" "vscatterpf1dps\0" "vscatterpf1qpd\0" "vscatterpf1qps\0" "vscatterqpd\0" - "vscatterqps\0" "vshuff32x4\0" "vshuff64x2\0" "vshufi32x4\0" "vshufi64x2\0" "vshufpd\0" "vshufps\0" "vsqrtpd\0" - "vsqrtph\0" "vsqrtps\0" "vsqrtsd\0" "vsqrtsh\0" "vsqrtss\0" "vstmxcsr\0" "vsubpd\0" "vsubph\0" "vsubps\0" "vsubsd\0" - "vsubsh\0" "vsubss\0" "vtestpd\0" "vtestps\0" "vucomisd\0" "vucomish\0" "vucomiss\0" "vunpckhpd\0" "vunpckhps\0" - "vunpcklpd\0" "vunpcklps\0" "vxorpd\0" "vxorps\0" "vzeroall\0" "vzeroupper\0" "wbinvd\0" "wbnoinvd\0" "wrfsbase\0" - "wrgsbase\0" "wrmsr\0" "wrssd\0" "wrssq\0" "wrussd\0" "wrussq\0" "xabort\0" "xadd\0" "xbegin\0" "xend\0" "xgetbv\0" - "xlatb\0" "xresldtrk\0" "xrstors\0" "xrstors64\0" "xsavec\0" "xsavec64\0" "xsaveopt\0" "xsaveopt64\0" "xsaves\0" - "xsaves64\0" "xsetbv\0" "xsusldtrk\0" "xtest"; - -const InstDB::InstNameIndex InstDB::instNameIndex[26] = { - { Inst::kIdAaa , Inst::kIdArpl + 1 }, +const InstNameIndex InstDB::instNameIndex = {{ + { Inst::kIdAaa , Inst::kIdAxor + 1 }, { Inst::kIdBextr , Inst::kIdBzhi + 1 }, { Inst::kIdCall , Inst::kIdCwde + 1 }, { Inst::kIdDaa , Inst::kIdDpps + 1 }, @@ -3028,6 +2948,1761 @@ const InstDB::InstNameIndex InstDB::instNameIndex[26] = { { Inst::kIdXabort , Inst::kIdXtest + 1 }, { Inst::kIdNone , Inst::kIdNone + 1 }, { Inst::kIdNone , Inst::kIdNone + 1 } +}, uint16_t(17)}; + +const char InstDB::_instNameStringTable[] = + "vgf2p8affineinvqbvaeskeygenassistvbroadcastf32x464x264x4i32x2i32x4i32x8i64x2i64x" + "4vpbroadcastmb2w2dvbcstnebf162p128i128vcvtne2ps2vcvtneebf16vcvtneobf16vfmaddsub1" + "32ph213pd213ph213ps231pd231ph231psvfmsubadd132vpmultishiftvscatterpf0dqpdqps1dpd" + "1dps1qpd1qpsvcvtneps2vextracvextractfvgatherpf0vp2intersecttcmmimfp16tcmmrlfp16s" + "h2pssdph2psvfnmadd132213sd213sh213ss231sd231sh231ssvfnmsub132vinservinsertfvpshu" + "fbitqvsha512rndprefetchitntawt1saveprevsssha256rndtileloaddtilereleavaesdeclvaes" + "enclvcompressvcvttpd2uqqvcvttph2uvcvttps2uvcvttsd2uvcvttsh2uvcvttss2uvfixupimmvf" + "madd132vfmsub132vmaskmovdqvpcompressvpconflictvphminposuvpmadd52hluqvpscatterqdv" + "punpckhqlqdqvrndscalemsg1msg2clflushopcmpnbexcmpnlexcmpxchg16t0t2tilestorev4fnma" + "ddssvcvtpd2uvcvtph2psudqvcvtps2phvcvtsd2uvcvtsh2uvcvtss2uvcvtudq2vcvtuqq2vcvtusi" + "2vfcmaddcvfpclassvgetmanmulbvp4dpwssvpclmuvpcmpestrvpcmpistrvperm2fvpermil2vpgat" + "hervpmacssdqvpmadcsswubswvpmaskmovpternlogbwwdlbwldqlwdvrsqrt1428pd28ps28sd28ssv" + "shufvshuffvzeroupxsaveoptcmpbexcmplexcmpnbxcmpnlxcmpnoxcmpnpxcmpnsxcmpnzx8bfxrst" + "orldtilecfmovdir64pvalidarmpadjurmpupdaserialisha1nexsha1rndssttilecftdpbf16tdpf" + "p16v4fmadvaddsubvblendmvpdvcvtdq2uwvcvtqq2vcvtsi2vcvtuwvdbpsadvdpbf16vexpanvfcmu" + "lccphcshvgetexpvmovdqau16u32u64vmovmskvmovntvmovshdvmovsldvpackssdwbvpackuswbvpb" + "lendmdvpdpbssudsvpdpbusvpdpwssvpdpwus2pdvpermtvpexpanvphaddubwqdqhvpmovmskvpmovs" + "xbvpmovusqwvpmovzxbvpmulhrvptestnmqvreducevscalefvsm3rndvsm4rndsvunpckhlpdlpsxre" + "sldtrs64xsusldtrcldemoclrssbscmpbxcmplxcmpoxcmppxcmpsxcmpzxcvtpifcmovfxsavekorte" + "stkshiftrbkunpckmonitorpfrcpipfrsqirtvrdfsbrdgsbsspseamcalsenduisetssbssysesysex" + "vcvtwvfmulvldmxcsvmlaundupu8vmovhvmovlhvmpsadvmresumvpadduvpaligngtbgtdgtqgtw2b2" + "qbdbqvphsubvplzcnb2md2mq2mw2mvpopcnvpshldvqvpshrdvwhwvpsubuvrangevrcp14vroundsdv" + "sm4keyvstmxcsvucomiallwbnoinwrfsbwrgsbc64blcfiblsficmovnendbrenqcmnufdecsfincsfn" + "stefrndfsincfucomfyl2xincsspqinvlinvlpinvpcinvvpmcommmovq2pavgupfcmpepfpnaptwris" + "eamoseamrsyscsysretdpbutlbsyvaesivaligvandnvcomivfrczvhadvhsubvmclevmgexvmmcvmov" + "avmovuvmptvmwrivpandvpextrwvpinsvpmaxvpminvprolvprorvpsadvpsigvpslvpsllvpsravpsr" + "lvsqrvtes"; + + +const uint32_t InstDB::_instNameIndexTable[] = { + 0x80000000, // Small ''. + 0x80000421, // Small 'aaa'. + 0x80001021, // Small 'aad'. + 0x80021021, // Small 'aadd'. + 0x80003421, // Small 'aam'. + 0x80023821, // Small 'aand'. + 0x80004C21, // Small 'aas'. + 0x80000C81, // Small 'adc'. + 0x800C0C81, // Small 'adcx'. + 0x80001081, // Small 'add'. + 0x80481081, // Small 'addpd'. + 0x81381081, // Small 'addps'. + 0x80499081, // Small 'addsd'. + 0x81399081, // Small 'addss'. + 0x20A76099, // Large 'addsub|pd'. + 0x207D6099, // Large 'addsub|ps'. + 0x800C3C81, // Small 'adox'. + 0x86524CA1, // Small 'aesdec'. + 0x302871D5, // Large 'aesdecl|ast'. + 0x86E2CCA1, // Small 'aesenc'. + 0x302871DD, // Large 'aesencl|ast'. + 0x86D4CCA1, // Small 'aesimc'. + 0x0000F012, // Large 'aeskeygenassist'. + 0x800011C1, // Small 'and'. + 0x800711C1, // Small 'andn'. + 0x890711C1, // Small 'andnpd'. + 0xA70711C1, // Small 'andnps'. + 0x804811C1, // Small 'andpd'. + 0x813811C1, // Small 'andps'. + 0x800049E1, // Small 'aor'. + 0x80064241, // Small 'arpl'. + 0x80093F01, // Small 'axor'. + 0x812A60A2, // Small 'bextr'. + 0x26F45709, // Large 'blcfi|ll'. + 0x80048D82, // Small 'blci'. + 0x80348D82, // Small 'blcic'. + 0x97368D82, // Small 'blcmsk'. + 0x80098D82, // Small 'blcs'. + 0x20A75471, // Large 'blend|pd'. + 0x207D5471, // Large 'blend|ps'. + 0x34775471, // Large 'blend|vpd'. + 0x318B5471, // Large 'blend|vps'. + 0x26F4570E, // Large 'blsfi|ll'. + 0x8004CD82, // Small 'blsi'. + 0x8034CD82, // Small 'blsic'. + 0x9736CD82, // Small 'blsmsk'. + 0x80094D82, // Small 'blsr'. + 0x80C191C2, // Small 'bndcl'. + 0x80E191C2, // Small 'bndcn'. + 0x815191C2, // Small 'bndcu'. + 0xB04611C2, // Small 'bndldx'. + 0x80B691C2, // Small 'bndmk'. + 0xACF691C2, // Small 'bndmov'. + 0xB14991C2, // Small 'bndstx'. + 0x804755E2, // Small 'bound'. + 0x80001A62, // Small 'bsf'. + 0x80004A62, // Small 'bsr'. + 0x8100DE62, // Small 'bswap'. + 0x80000282, // Small 'bt'. + 0x80000E82, // Small 'btc'. + 0x80004A82, // Small 'btr'. + 0x80004E82, // Small 'bts'. + 0x8004A342, // Small 'bzhi'. + 0x80063023, // Small 'call'. + 0x80005C43, // Small 'cbw'. + 0x80004483, // Small 'cdq'. + 0x8002C483, // Small 'cdqe'. + 0x80018583, // Small 'clac'. + 0x80000D83, // Small 'clc'. + 0x80001183, // Small 'cld'. + 0x20DF65B0, // Large 'cldemo|te'. + 0x0000729D, // Large 'clflush'. + 0x1020929D, // Large 'clflushop|t'. + 0x80049D83, // Small 'clgi'. + 0x80002583, // Small 'cli'. + 0x101775B6, // Large 'clrssbs|y'. + 0x8009D183, // Small 'clts'. + 0x8004D583, // Small 'clui'. + 0x80015D83, // Small 'clwb'. + 0x9F22E983, // Small 'clzero'. + 0x80000DA3, // Small 'cmc'. + 0x801B3DA3, // Small 'cmova'. + 0x8A1B3DA3, // Small 'cmovae'. + 0x802B3DA3, // Small 'cmovb'. + 0x8A2B3DA3, // Small 'cmovbe'. + 0x803B3DA3, // Small 'cmovc'. + 0x805B3DA3, // Small 'cmove'. + 0x807B3DA3, // Small 'cmovg'. + 0x8A7B3DA3, // Small 'cmovge'. + 0x80CB3DA3, // Small 'cmovl'. + 0x8ACB3DA3, // Small 'cmovle'. + 0x82EB3DA3, // Small 'cmovna'. + 0x20125713, // Large 'cmovn|ae'. + 0x84EB3DA3, // Small 'cmovnb'. + 0x22AA5713, // Large 'cmovn|be'. + 0x86EB3DA3, // Small 'cmovnc'. + 0x8AEB3DA3, // Small 'cmovne'. + 0x8EEB3DA3, // Small 'cmovng'. + 0x20185713, // Large 'cmovn|ge'. + 0x98EB3DA3, // Small 'cmovnl'. + 0x21C45713, // Large 'cmovn|le'. + 0x9EEB3DA3, // Small 'cmovno'. + 0xA0EB3DA3, // Small 'cmovnp'. + 0xA6EB3DA3, // Small 'cmovns'. + 0xB4EB3DA3, // Small 'cmovnz'. + 0x80FB3DA3, // Small 'cmovo'. + 0x810B3DA3, // Small 'cmovp'. + 0x8B0B3DA3, // Small 'cmovpe'. + 0x9F0B3DA3, // Small 'cmovpo'. + 0x813B3DA3, // Small 'cmovs'. + 0x81AB3DA3, // Small 'cmovz'. + 0x800041A3, // Small 'cmp'. + 0x309963D9, // Large 'cmpbex|add'. + 0x309955BD, // Large 'cmpbx|add'. + 0x309963DF, // Large 'cmplex|add'. + 0x309955C2, // Large 'cmplx|add'. + 0x309972A6, // Large 'cmpnbex|add'. + 0x309963E5, // Large 'cmpnbx|add'. + 0x309972AD, // Large 'cmpnlex|add'. + 0x309963EB, // Large 'cmpnlx|add'. + 0x309963F1, // Large 'cmpnox|add'. + 0x309963F7, // Large 'cmpnpx|add'. + 0x309963FD, // Large 'cmpnsx|add'. + 0x30996403, // Large 'cmpnzx|add'. + 0x309955C7, // Large 'cmpox|add'. + 0x804841A3, // Small 'cmppd'. + 0x813841A3, // Small 'cmpps'. + 0x309955CC, // Large 'cmppx|add'. + 0x8009C1A3, // Small 'cmps'. + 0x8049C1A3, // Small 'cmpsd'. + 0x8139C1A3, // Small 'cmpss'. + 0x309955D1, // Large 'cmpsx|add'. + 0x000072B4, // Large 'cmpxchg'. + 0x101092B4, // Large 'cmpxchg16|b'. + 0x240972B4, // Large 'cmpxchg|8b'. + 0x309955D6, // Large 'cmpzx|add'. + 0x8934B5E3, // Small 'comisd'. + 0xA734B5E3, // Small 'comiss'. + 0x8044D603, // Small 'cpuid'. + 0x80003E23, // Small 'cqo'. + 0x81DF0E43, // Small 'crc32'. + 0x20A7647B, // Large 'cvtdq2|pd'. + 0x207D647B, // Large 'cvtdq2|ps'. + 0x20E562D5, // Large 'cvtpd2|dq'. + 0x222A62D5, // Large 'cvtpd2|pi'. + 0x207D62D5, // Large 'cvtpd2|ps'. + 0x352555DB, // Large 'cvtpi|2pd'. + 0x307C55DB, // Large 'cvtpi|2ps'. + 0x20E562E9, // Large 'cvtps2|dq'. + 0x102672E9, // Large 'cvtps2p|d'. + 0x100972E9, // Large 'cvtps2p|i'. + 0x201D62F2, // Large 'cvtsd2|si'. + 0x201C62F2, // Large 'cvtsd2|ss'. + 0x2144648B, // Large 'cvtsi2|sd'. + 0x201C648B, // Large 'cvtsi2|ss'. + 0x21446302, // Large 'cvtss2|sd'. + 0x201D6302, // Large 'cvtss2|si'. + 0x20E571EE, // Large 'cvttpd2|dq'. + 0x222A71EE, // Large 'cvttpd2|pi'. + 0x20E57202, // Large 'cvttps2|dq'. + 0x222A7202, // Large 'cvttps2|pi'. + 0x201D720B, // Large 'cvttsd2|si'. + 0x201D721D, // Large 'cvttss2|si'. + 0x800012E3, // Small 'cwd'. + 0x800292E3, // Small 'cwde'. + 0x80000424, // Small 'daa'. + 0x80004C24, // Small 'das'. + 0x80000CA4, // Small 'dec'. + 0x80005924, // Small 'div'. + 0x80485924, // Small 'divpd'. + 0x81385924, // Small 'divps'. + 0x8049D924, // Small 'divsd'. + 0x8139D924, // Small 'divss'. + 0x80024204, // Small 'dppd'. + 0x8009C204, // Small 'dpps'. + 0x8009B5A5, // Small 'emms'. + 0x202C5718, // Large 'endbr|32'. + 0x20305718, // Large 'endbr|64'. + 0x88D1C5C5, // Small 'enqcmd'. + 0x209B571D, // Large 'enqcm|ds'. + 0x8122D1C5, // Small 'enter'. + 0x207D710D, // Large 'extract|ps'. + 0x81195305, // Small 'extrq'. + 0x81C6E3A6, // Small 'f2xm1'. + 0x80098826, // Small 'fabs'. + 0x80021026, // Small 'fadd'. + 0x81021026, // Small 'faddp'. + 0x80023046, // Small 'fbld'. + 0x810A4C46, // Small 'fbstp'. + 0x8009A066, // Small 'fchs'. + 0x8182B066, // Small 'fclex'. + 0x8567B466, // Small 'fcmovb'. + 0x22AA55E0, // Large 'fcmov|be'. + 0x8B67B466, // Small 'fcmove'. + 0x22A955E0, // Large 'fcmov|nb'. + 0x32A955E0, // Large 'fcmov|nbe'. + 0x200A55E0, // Large 'fcmov|ne'. + 0x272255E0, // Large 'fcmov|nu'. + 0xAB67B466, // Small 'fcmovu'. + 0x8006BC66, // Small 'fcom'. + 0x8096BC66, // Small 'fcomi'. + 0xA096BC66, // Small 'fcomip'. + 0x8106BC66, // Small 'fcomp'. + 0xA106BC66, // Small 'fcompp'. + 0x8009BC66, // Small 'fcos'. + 0x21F15724, // Large 'fdecs|tp'. + 0x800B2486, // Small 'fdiv'. + 0x810B2486, // Small 'fdivp'. + 0x812B2486, // Small 'fdivr'. + 0xA12B2486, // Small 'fdivrp'. + 0x8136B4A6, // Small 'femms'. + 0x8052C8C6, // Small 'ffree'. + 0x80420526, // Small 'fiadd'. + 0x80D78D26, // Small 'ficom'. + 0xA0D78D26, // Small 'ficomp'. + 0x81649126, // Small 'fidiv'. + 0xA5649126, // Small 'fidivr'. + 0x80023126, // Small 'fild'. + 0x80CAB526, // Small 'fimul'. + 0x21F15729, // Large 'fincs|tp'. + 0x8144B926, // Small 'finit'. + 0x800A4D26, // Small 'fist'. + 0x810A4D26, // Small 'fistp'. + 0xA14A4D26, // Small 'fisttp'. + 0x802ACD26, // Small 'fisub'. + 0xA42ACD26, // Small 'fisubr'. + 0x80001186, // Small 'fld'. + 0x800E1186, // Small 'fld1'. + 0x81719186, // Small 'fldcw'. + 0xACE29186, // Small 'fldenv'. + 0x8BD61186, // Small 'fldl2e'. + 0xA9D61186, // Small 'fldl2t'. + 0xBA761186, // Small 'fldlg2'. + 0xBAE61186, // Small 'fldln2'. + 0x80981186, // Small 'fldpi'. + 0x800D1186, // Small 'fldz'. + 0x800655A6, // Small 'fmul'. + 0x810655A6, // Small 'fmulp'. + 0xB0560DC6, // Small 'fnclex'. + 0xA89725C6, // Small 'fninit'. + 0x80083DC6, // Small 'fnop'. + 0x8B60CDC6, // Small 'fnsave'. + 0xAE3A4DC6, // Small 'fnstcw'. + 0x200D572E, // Large 'fnste|nv'. + 0xAF3A4DC6, // Small 'fnstsw'. + 0x9C1A0606, // Small 'fpatan'. + 0x80D2CA06, // Small 'fprem'. + 0xB8D2CA06, // Small 'fprem1'. + 0x80E0D206, // Small 'fptan'. + 0x31224733, // Large 'frnd|int'. + 0xA4FA4E46, // Small 'frstor'. + 0x805B0666, // Small 'fsave'. + 0x8AC08E66, // Small 'fscale'. + 0x80072666, // Small 'fsin'. + 0x22655737, // Large 'fsinc|os'. + 0x81494666, // Small 'fsqrt'. + 0x80005266, // Small 'fst'. + 0x8171D266, // Small 'fstcw'. + 0xACE2D266, // Small 'fstenv'. + 0x80085266, // Small 'fstp'. + 0x8179D266, // Small 'fstsw'. + 0x80015666, // Small 'fsub'. + 0x81015666, // Small 'fsubp'. + 0x81215666, // Small 'fsubr'. + 0xA1215666, // Small 'fsubrp'. + 0x800A4E86, // Small 'ftst'. + 0x80D78EA6, // Small 'fucom'. + 0x92D78EA6, // Small 'fucomi'. + 0x260C573C, // Large 'fucom|ip'. + 0xA0D78EA6, // Small 'fucomp'. + 0x25CE573C, // Large 'fucom|pp'. + 0x814486E6, // Small 'fwait'. + 0x80068706, // Small 'fxam'. + 0x80040F06, // Small 'fxch'. + 0x0000740B, // Large 'fxrstor'. + 0x2030740B, // Large 'fxrstor|64'. + 0x8B60CF06, // Small 'fxsave'. + 0x203065E5, // Large 'fxsave|64'. + 0x510F240B, // Large 'fx|tract'. + 0x818EB326, // Small 'fyl2x'. + 0x206E5741, // Large 'fyl2x|p1'. + 0x8659D0A7, // Small 'getsec'. + 0x1010F001, // Large 'gf2p8affineinvq|b'. + 0x200FB001, // Large 'gf2p8affine|qb'. + 0x43385001, // Large 'gf2p8|mulb'. + 0x89021028, // Small 'haddpd'. + 0xA7021028, // Small 'haddps'. + 0x80005188, // Small 'hlt'. + 0xA8599648, // Small 'hreset'. + 0x89015668, // Small 'hsubpd'. + 0xA7015668, // Small 'hsubps'. + 0x800B2489, // Small 'idiv'. + 0x800655A9, // Small 'imul'. + 0x800001C9, // Small 'in'. + 0x80000DC9, // Small 'inc'. + 0x20A75746, // Large 'incss|pd'. + 0x274B5746, // Large 'incss|pq'. + 0x80004DC9, // Small 'ins'. + 0x207D6184, // Large 'insert|ps'. + 0x100F6184, // Large 'insert|q'. + 0x800051C9, // Small 'int'. + 0x800F51C9, // Small 'int3'. + 0x8007D1C9, // Small 'into'. + 0x800259C9, // Small 'invd'. + 0xA902D9C9, // Small 'invept'. + 0x8F0659C9, // Small 'invlpg'. + 0x336C474D, // Large 'invl|pga'. + 0x23995751, // Large 'invlp|gb'. + 0x24265756, // Large 'invpc|id'. + 0x2426575B, // Large 'invvp|id'. + 0x800A1649, // Small 'iret'. + 0x804A1649, // Small 'iretd'. + 0x811A1649, // Small 'iretq'. + 0x8000002A, // Small 'ja'. + 0x8000142A, // Small 'jae'. + 0x8000004A, // Small 'jb'. + 0x8000144A, // Small 'jbe'. + 0x8000006A, // Small 'jc'. + 0x800000AA, // Small 'je'. + 0x81AC0CAA, // Small 'jecxz'. + 0x800000EA, // Small 'jg'. + 0x800014EA, // Small 'jge'. + 0x8000018A, // Small 'jl'. + 0x8000158A, // Small 'jle'. + 0x800041AA, // Small 'jmp'. + 0x800005CA, // Small 'jna'. + 0x800285CA, // Small 'jnae'. + 0x800009CA, // Small 'jnb'. + 0x800289CA, // Small 'jnbe'. + 0x80000DCA, // Small 'jnc'. + 0x800015CA, // Small 'jne'. + 0x80001DCA, // Small 'jng'. + 0x80029DCA, // Small 'jnge'. + 0x800031CA, // Small 'jnl'. + 0x8002B1CA, // Small 'jnle'. + 0x80003DCA, // Small 'jno'. + 0x800041CA, // Small 'jnp'. + 0x80004DCA, // Small 'jns'. + 0x800069CA, // Small 'jnz'. + 0x800001EA, // Small 'jo'. + 0x8000020A, // Small 'jp'. + 0x8000160A, // Small 'jpe'. + 0x80003E0A, // Small 'jpo'. + 0x8000026A, // Small 'js'. + 0x8000034A, // Small 'jz'. + 0x8022102B, // Small 'kaddb'. + 0x8042102B, // Small 'kaddd'. + 0x8112102B, // Small 'kaddq'. + 0x8172102B, // Small 'kaddw'. + 0x8022382B, // Small 'kandb'. + 0x8042382B, // Small 'kandd'. + 0x84E2382B, // Small 'kandnb'. + 0x88E2382B, // Small 'kandnd'. + 0xA2E2382B, // Small 'kandnq'. + 0xAEE2382B, // Small 'kandnw'. + 0x8112382B, // Small 'kandq'. + 0x8172382B, // Small 'kandw'. + 0x802B3DAB, // Small 'kmovb'. + 0x804B3DAB, // Small 'kmovd'. + 0x811B3DAB, // Small 'kmovq'. + 0x817B3DAB, // Small 'kmovw'. + 0x802A3DCB, // Small 'knotb'. + 0x804A3DCB, // Small 'knotd'. + 0x811A3DCB, // Small 'knotq'. + 0x817A3DCB, // Small 'knotw'. + 0x800149EB, // Small 'korb'. + 0x800249EB, // Small 'kord'. + 0x8008C9EB, // Small 'korq'. + 0x101075EB, // Large 'kortest|b'. + 0x102675EB, // Large 'kortest|d'. + 0x100F75EB, // Large 'kortest|q'. + 0x105F75EB, // Large 'kortest|w'. + 0x800BC9EB, // Small 'korw'. + 0x233A65F2, // Large 'kshift|lb'. + 0x23A165F2, // Large 'kshift|ld'. + 0x228865F2, // Large 'kshift|lq'. + 0x23A465F2, // Large 'kshift|lw'. + 0x25F865F2, // Large 'kshift|rb'. + 0x102675F2, // Large 'kshiftr|d'. + 0x100F75F2, // Large 'kshiftr|q'. + 0x105F75F2, // Large 'kshiftr|w'. + 0x8549968B, // Small 'ktestb'. + 0x8949968B, // Small 'ktestd'. + 0xA349968B, // Small 'ktestq'. + 0xAF49968B, // Small 'ktestw'. + 0x239A65FA, // Large 'kunpck|bw'. + 0x20E565FA, // Large 'kunpck|dq'. + 0x239C65FA, // Large 'kunpck|wd'. + 0x8527BB0B, // Small 'kxnorb'. + 0x8927BB0B, // Small 'kxnord'. + 0xA327BB0B, // Small 'kxnorq'. + 0xAF27BB0B, // Small 'kxnorw'. + 0x80293F0B, // Small 'kxorb'. + 0x80493F0B, // Small 'kxord'. + 0x81193F0B, // Small 'kxorq'. + 0x81793F0B, // Small 'kxorw'. + 0x8003202C, // Small 'lahf'. + 0x8000482C, // Small 'lar'. + 0x80C6046C, // Small 'lcall'. + 0x8158908C, // Small 'lddqu'. + 0x1023664B, // Large 'ldmxcs|r'. + 0x80004C8C, // Small 'lds'. + 0x10018412, // Large 'ldtilecf|g'. + 0x800004AC, // Small 'lea'. + 0x805B04AC, // Small 'leave'. + 0x80004CAC, // Small 'les'. + 0x8A3714CC, // Small 'lfence'. + 0x80004CCC, // Small 'lfs'. + 0x800A10EC, // Small 'lgdt'. + 0x80004CEC, // Small 'lgs'. + 0x800A112C, // Small 'lidt'. + 0x8008354C, // Small 'ljmp'. + 0x800A118C, // Small 'lldt'. + 0x84385D8C, // Small 'llwpcb'. + 0x800BCDAC, // Small 'lmsw'. + 0x800991EC, // Small 'lods'. + 0x80083DEC, // Small 'loop'. + 0x80583DEC, // Small 'loope'. + 0x8AE83DEC, // Small 'loopne'. + 0x8000326C, // Small 'lsl'. + 0x80004E6C, // Small 'lss'. + 0x80004A8C, // Small 'ltr'. + 0xA6E4C2EC, // Small 'lwpins'. + 0x981B42EC, // Small 'lwpval'. + 0x81470F4C, // Small 'lzcnt'. + 0x109D9241, // Large 'maskmovdq|u'. + 0x100F7241, // Large 'maskmov|q'. + 0x8048602D, // Small 'maxpd'. + 0x8138602D, // Small 'maxps'. + 0x8049E02D, // Small 'maxsd'. + 0x8139E02D, // Small 'maxss'. + 0x21925760, // Large 'mcomm|it'. + 0x8A3714CD, // Small 'mfence'. + 0x8048392D, // Small 'minpd'. + 0x8138392D, // Small 'minps'. + 0x8049B92D, // Small 'minsd'. + 0x8139B92D, // Small 'minss'. + 0x00007600, // Large 'monitor'. + 0x102E7600, // Large 'monitor|x'. + 0x800059ED, // Small 'mov'. + 0xA620D9ED, // Small 'movabs'. + 0x8900D9ED, // Small 'movapd'. + 0xA700D9ED, // Small 'movaps'. + 0x805159ED, // Small 'movbe'. + 0x800259ED, // Small 'movd'. + 0x36574245, // Large 'movd|dup'. + 0x1010841A, // Large 'movdir64|b'. + 0x1009641A, // Large 'movdir|i'. + 0x268F5245, // Large 'movdq|2q'. + 0x831259ED, // Small 'movdqa'. + 0xAB1259ED, // Small 'movdqu'. + 0x359A465D, // Large 'movh|lps'. + 0x890459ED, // Small 'movhpd'. + 0xA70459ED, // Small 'movhps'. + 0x207D5662, // Large 'movlh|ps'. + 0x890659ED, // Small 'movlpd'. + 0xA70659ED, // Small 'movlps'. + 0x20A764D0, // Large 'movmsk|pd'. + 0x207D64D0, // Large 'movmsk|ps'. + 0x20E554D7, // Large 'movnt|dq'. + 0x34C354D7, // Large 'movnt|dqa'. + 0x934759ED, // Small 'movnti'. + 0x20A754D7, // Large 'movnt|pd'. + 0x207D54D7, // Large 'movnt|ps'. + 0xA34759ED, // Small 'movntq'. + 0x214454D7, // Large 'movnt|sd'. + 0x201C54D7, // Large 'movnt|ss'. + 0x8008D9ED, // Small 'movq'. + 0x20E55765, // Large 'movq2|dq'. + 0x8009D9ED, // Small 'movs'. + 0x8049D9ED, // Small 'movsd'. + 0x222964DD, // Large 'movshd|up'. + 0x222964E4, // Large 'movsld|up'. + 0x8139D9ED, // Small 'movss'. + 0x8189D9ED, // Small 'movsx'. + 0x8989D9ED, // Small 'movsxd'. + 0x890AD9ED, // Small 'movupd'. + 0xA70AD9ED, // Small 'movups'. + 0x818D59ED, // Small 'movzx'. + 0x239A5668, // Large 'mpsad|bw'. + 0x800032AD, // Small 'mul'. + 0x804832AD, // Small 'mulpd'. + 0x813832AD, // Small 'mulps'. + 0x8049B2AD, // Small 'mulsd'. + 0x8139B2AD, // Small 'mulss'. + 0x800C32AD, // Small 'mulx'. + 0x814486ED, // Small 'mwait'. + 0xB14486ED, // Small 'mwaitx'. + 0x80001CAE, // Small 'neg'. + 0x800041EE, // Small 'nop'. + 0x800051EE, // Small 'not'. + 0x8000024F, // Small 'or'. + 0x8002424F, // Small 'orpd'. + 0x8009C24F, // Small 'orps'. + 0x800052AF, // Small 'out'. + 0x8009D2AF, // Small 'outs'. + 0x80298830, // Small 'pabsb'. + 0x80498830, // Small 'pabsd'. + 0x81798830, // Small 'pabsw'. + 0x000084EB, // Large 'packssdw'. + 0x24F264EB, // Large 'packss|wb'. + 0x24F164F5, // Large 'packus|dw'. + 0x000084F5, // Large 'packuswb'. + 0x80221030, // Small 'paddb'. + 0x80421030, // Small 'paddd'. + 0x81121030, // Small 'paddq'. + 0x85321030, // Small 'paddsb'. + 0xAF321030, // Small 'paddsw'. + 0x25BA5675, // Large 'paddu|sb'. + 0x23835675, // Large 'paddu|sw'. + 0x81721030, // Small 'paddw'. + 0x1023667B, // Large 'palign|r'. + 0x80023830, // Small 'pand'. + 0x80E23830, // Small 'pandn'. + 0x8059D430, // Small 'pause'. + 0x8023D830, // Small 'pavgb'. + 0x25BA576A, // Large 'pavgu|sb'. + 0x8173D830, // Small 'pavgw'. + 0x202164FE, // Large 'pblend|vb'. + 0x105F64FE, // Large 'pblend|w'. + 0x42885345, // Large 'pclmu|lqdq'. + 0x200F534B, // Large 'pcmpe|qb'. + 0x227D534B, // Large 'pcmpe|qd'. + 0x21F6534B, // Large 'pcmpe|qq'. + 0x2559534B, // Large 'pcmpe|qw'. + 0x1009834B, // Large 'pcmpestr|i'. + 0x105C834B, // Large 'pcmpestr|m'. + 0x368142A5, // Large 'pcmp|gtb'. + 0x368442A5, // Large 'pcmp|gtd'. + 0x368742A5, // Large 'pcmp|gtq'. + 0x368A42A5, // Large 'pcmp|gtw'. + 0x10098354, // Large 'pcmpistr|i'. + 0x105C8354, // Large 'pcmpistr|m'. + 0x267E5255, // Large 'pconf|ig'. + 0x80081490, // Small 'pdep'. + 0x800A60B0, // Small 'pext'. + 0x852A60B0, // Small 'pextrb'. + 0x892A60B0, // Small 'pextrd'. + 0xA32A60B0, // Small 'pextrq'. + 0xAF2A60B0, // Small 'pextrw'. + 0x8044F4D0, // Small 'pf2id'. + 0x8174F4D0, // Small 'pf2iw'. + 0x803184D0, // Small 'pfacc'. + 0x804204D0, // Small 'pfadd'. + 0x100F676F, // Large 'pfcmpe|q'. + 0x2018576F, // Large 'pfcmp|ge'. + 0x2681576F, // Large 'pfcmp|gt'. + 0x8180B4D0, // Small 'pfmax'. + 0x80E4B4D0, // Small 'pfmin'. + 0x80CAB4D0, // Small 'pfmul'. + 0x8630B8D0, // Small 'pfnacc'. + 0x24B15775, // Large 'pfpna|cc'. + 0x8101C8D0, // Small 'pfrcp'. + 0x21AD6607, // Large 'pfrcpi|t1'. + 0x22BF6607, // Large 'pfrcpi|t2'. + 0xAD01C8D0, // Small 'pfrcpv'. + 0x21AD660D, // Large 'pfrsqi|t1'. + 0x2188560D, // Large 'pfrsq|rt'. + 0x3613560D, // Large 'pfrsq|rtv'. + 0x802ACCD0, // Small 'pfsub'. + 0xA42ACCD0, // Small 'pfsubr'. + 0x88420510, // Small 'phaddd'. + 0x23835536, // Large 'phadd|sw'. + 0xAE420510, // Small 'phaddw'. + 0x105F925F, // Large 'phminposu|w'. + 0x882ACD10, // Small 'phsubd'. + 0x23835696, // Large 'phsub|sw'. + 0xAE2ACD10, // Small 'phsubw'. + 0x80437530, // Small 'pi2fd'. + 0x81737530, // Small 'pi2fw'. + 0x8529B930, // Small 'pinsrb'. + 0x8929B930, // Small 'pinsrd'. + 0xA329B930, // Small 'pinsrq'. + 0xAF29B930, // Small 'pinsrw'. + 0x43855269, // Large 'pmadd|ubsw'. + 0x239C5269, // Large 'pmadd|wd'. + 0x853C05B0, // Small 'pmaxsb'. + 0x893C05B0, // Small 'pmaxsd'. + 0xAF3C05B0, // Small 'pmaxsw'. + 0x855C05B0, // Small 'pmaxub'. + 0x895C05B0, // Small 'pmaxud'. + 0xAF5C05B0, // Small 'pmaxuw'. + 0x853725B0, // Small 'pminsb'. + 0x893725B0, // Small 'pminsd'. + 0xAF3725B0, // Small 'pminsw'. + 0x855725B0, // Small 'pminub'. + 0x895725B0, // Small 'pminud'. + 0xAF5725B0, // Small 'pminuw'. + 0x10107543, // Large 'pmovmsk|b'. + 0x1026754B, // Large 'pmovsxb|d'. + 0x100F754B, // Large 'pmovsxb|q'. + 0x105F754B, // Large 'pmovsxb|w'. + 0x20E5654B, // Large 'pmovsx|dq'. + 0x239C654B, // Large 'pmovsx|wd'. + 0x253D654B, // Large 'pmovsx|wq'. + 0x1026755C, // Large 'pmovzxb|d'. + 0x100F755C, // Large 'pmovzxb|q'. + 0x105F755C, // Large 'pmovzxb|w'. + 0x20E5655C, // Large 'pmovzx|dq'. + 0x239C655C, // Large 'pmovzx|wd'. + 0x253D655C, // Large 'pmovzx|wq'. + 0xA24655B0, // Small 'pmuldq'. + 0x23836564, // Large 'pmulhr|sw'. + 0x105F6564, // Large 'pmulhr|w'. + 0x24815564, // Large 'pmulh|uw'. + 0xAE8655B0, // Small 'pmulhw'. + 0x88C655B0, // Small 'pmulld'. + 0xAEC655B0, // Small 'pmullw'. + 0x32E540CF, // Large 'pmul|udq'. + 0x800041F0, // Small 'pop'. + 0x8000C1F0, // Small 'popa'. + 0x8040C1F0, // Small 'popad'. + 0xA8E1C1F0, // Small 'popcnt'. + 0x800341F0, // Small 'popf'. + 0x804341F0, // Small 'popfd'. + 0x811341F0, // Small 'popfq'. + 0x800049F0, // Small 'por'. + 0x0000819F, // Large 'prefetch'. + 0x10E4A19F, // Large 'prefetchit|0'. + 0x106BA19F, // Large 'prefetchit|1'. + 0x31A9819F, // Large 'prefetch|nta'. + 0x22BD819F, // Large 'prefetch|t0'. + 0x21AD819F, // Large 'prefetch|t1'. + 0x22BF819F, // Large 'prefetch|t2'. + 0x105F819F, // Large 'prefetch|w'. + 0x31AC819F, // Large 'prefetch|wt1'. + 0xAE220670, // Small 'psadbw'. + 0x846AA270, // Small 'pshufb'. + 0x886AA270, // Small 'pshufd'. + 0x26C3518C, // Large 'pshuf|hw'. + 0x23A4518C, // Large 'pshuf|lw'. + 0xAE6AA270, // Small 'pshufw'. + 0x84E3A670, // Small 'psignb'. + 0x88E3A670, // Small 'psignd'. + 0xAEE3A670, // Small 'psignw'. + 0x80463270, // Small 'pslld'. + 0xA2463270, // Small 'pslldq'. + 0x81163270, // Small 'psllq'. + 0x81763270, // Small 'psllw'. + 0x9130B670, // Small 'psmash'. + 0x8040CA70, // Small 'psrad'. + 0x8170CA70, // Small 'psraw'. + 0x80464A70, // Small 'psrld'. + 0xA2464A70, // Small 'psrldq'. + 0x81164A70, // Small 'psrlq'. + 0x81764A70, // Small 'psrlw'. + 0x80215670, // Small 'psubb'. + 0x80415670, // Small 'psubd'. + 0x81115670, // Small 'psubq'. + 0x85315670, // Small 'psubsb'. + 0xAF315670, // Small 'psubsw'. + 0x25BA56C6, // Large 'psubu|sb'. + 0x238356C6, // Large 'psubu|sw'. + 0x81715670, // Small 'psubw'. + 0x8900DE70, // Small 'pswapd'. + 0x81499690, // Small 'ptest'. + 0x20DF577A, // Large 'ptwri|te'. + 0x239A7280, // Large 'punpckh|bw'. + 0x20E57280, // Large 'punpckh|dq'. + 0x20E58280, // Large 'punpckhq|dq'. + 0x239C7280, // Large 'punpckh|wd'. + 0x339E6280, // Large 'punpck|lbw'. + 0x33A16280, // Large 'punpck|ldq'. + 0x42886280, // Large 'punpck|lqdq'. + 0x33A46280, // Large 'punpck|lwd'. + 0x80044EB0, // Small 'push'. + 0x80144EB0, // Small 'pusha'. + 0x88144EB0, // Small 'pushad'. + 0x80644EB0, // Small 'pushf'. + 0x88644EB0, // Small 'pushfd'. + 0xA2644EB0, // Small 'pushfq'. + 0x20DF7422, // Large 'pvalida|te'. + 0x80093F10, // Small 'pxor'. + 0x80003072, // Small 'rcl'. + 0x81384072, // Small 'rcpps'. + 0x8139C072, // Small 'rcpss'. + 0x80004872, // Small 'rcr'. + 0x34365616, // Large 'rdfsb|ase'. + 0x3436561B, // Large 'rdgsb|ase'. + 0x8129B492, // Small 'rdmsr'. + 0x8044C092, // Small 'rdpid'. + 0xAB25C092, // Small 'rdpkru'. + 0x8036C092, // Small 'rdpmc'. + 0x81594092, // Small 'rdpru'. + 0x88E0C892, // Small 'rdrand'. + 0x8852CC92, // Small 'rdseed'. + 0x8909CC92, // Small 'rdsspd'. + 0xA309CC92, // Small 'rdsspq'. + 0x8039D092, // Small 'rdtsc'. + 0xA039D092, // Small 'rdtscp'. + 0x800050B2, // Small 'ret'. + 0x800350B2, // Small 'retf'. + 0x201F7429, // Large 'rmpadju|st'. + 0x20DF7430, // Large 'rmpupda|te'. + 0x800031F2, // Small 'rol'. + 0x800049F2, // Small 'ror'. + 0x800C49F2, // Small 'rorx'. + 0x20A756D8, // Large 'round|pd'. + 0x207D56D8, // Large 'round|ps'. + 0x000076D8, // Large 'roundsd'. + 0x101466D8, // Large 'rounds|s'. + 0x80003672, // Small 'rsm'. + 0x207D53A8, // Large 'rsqrt|ps'. + 0x201C53A8, // Large 'rsqrt|ss'. + 0x3620540D, // Large 'rstor|ssp'. + 0x80032033, // Small 'sahf'. + 0x80003033, // Small 'sal'. + 0x80004833, // Small 'sar'. + 0x800C4833, // Small 'sarx'. + 0x1004A1AF, // Large 'saveprevss|p'. + 0x80000853, // Small 'sbb'. + 0x80098473, // Small 'scas'. + 0x10D27623, // Large 'seamcal|l'. + 0x207D577F, // Large 'seamo|ps'. + 0x21A35784, // Large 'seamr|et'. + 0x222A662A, // Large 'sendui|pi'. + 0x23CB7437, // Large 'seriali|ze'. + 0x8000D0B3, // Small 'seta'. + 0x8050D0B3, // Small 'setae'. + 0x800150B3, // Small 'setb'. + 0x805150B3, // Small 'setbe'. + 0x8001D0B3, // Small 'setc'. + 0x8002D0B3, // Small 'sete'. + 0x8003D0B3, // Small 'setg'. + 0x8053D0B3, // Small 'setge'. + 0x800650B3, // Small 'setl'. + 0x805650B3, // Small 'setle'. + 0x801750B3, // Small 'setna'. + 0x8A1750B3, // Small 'setnae'. + 0x802750B3, // Small 'setnb'. + 0x8A2750B3, // Small 'setnbe'. + 0x803750B3, // Small 'setnc'. + 0x805750B3, // Small 'setne'. + 0x807750B3, // Small 'setng'. + 0x8A7750B3, // Small 'setnge'. + 0x80C750B3, // Small 'setnl'. + 0x8AC750B3, // Small 'setnle'. + 0x80F750B3, // Small 'setno'. + 0x810750B3, // Small 'setnp'. + 0x813750B3, // Small 'setns'. + 0x81A750B3, // Small 'setnz'. + 0x8007D0B3, // Small 'seto'. + 0x800850B3, // Small 'setp'. + 0x805850B3, // Small 'setpe'. + 0x80F850B3, // Small 'setpo'. + 0x8009D0B3, // Small 'sets'. + 0x10177630, // Large 'setssbs|y'. + 0x800D50B3, // Small 'setz'. + 0x8A3714D3, // Small 'sfence'. + 0x800A10F3, // Small 'sgdt'. + 0x4295443E, // Large 'sha1|msg1'. + 0x4299443E, // Large 'sha1|msg2'. + 0x20DF743E, // Large 'sha1nex|te'. + 0x102F8445, // Large 'sha1rnds|4'. + 0x429561B9, // Large 'sha256|msg1'. + 0x429961B9, // Large 'sha256|msg2'. + 0x207E91B9, // Large 'sha256rnd|s2'. + 0x80003113, // Small 'shl'. + 0x80023113, // Small 'shld'. + 0x800C3113, // Small 'shlx'. + 0x80004913, // Small 'shr'. + 0x80024913, // Small 'shrd'. + 0x800C4913, // Small 'shrx'. + 0x89035513, // Small 'shufpd'. + 0xA7035513, // Small 'shufps'. + 0x800A1133, // Small 'sidt'. + 0xA8972573, // Small 'skinit'. + 0x800A1193, // Small 'sldt'. + 0x84385D93, // Small 'slwpcb'. + 0x800BCDB3, // Small 'smsw'. + 0x890A4A33, // Small 'sqrtpd'. + 0xA70A4A33, // Small 'sqrtps'. + 0x893A4A33, // Small 'sqrtsd'. + 0xA73A4A33, // Small 'sqrtss'. + 0x80018693, // Small 'stac'. + 0x80000E93, // Small 'stc'. + 0x80001293, // Small 'std'. + 0x80049E93, // Small 'stgi'. + 0x80002693, // Small 'sti'. + 0x102366E7, // Large 'stmxcs|r'. + 0x8009BE93, // Small 'stos'. + 0x80004A93, // Small 'str'. + 0x1001844D, // Large 'sttilecf|g'. + 0x8004D693, // Small 'stui'. + 0x80000AB3, // Small 'sub'. + 0x80480AB3, // Small 'subpd'. + 0x81380AB3, // Small 'subps'. + 0x80498AB3, // Small 'subsd'. + 0x81398AB3, // Small 'subss'. + 0xA67806F3, // Small 'swapgs'. + 0x36F34789, // Large 'sysc|all'. + 0x41234637, // Large 'syse|nter'. + 0x2192563B, // Large 'sysex|it'. + 0x3192563B, // Large 'sysex|itq'. + 0xA8594F33, // Small 'sysret'. + 0x2193578D, // Large 'sysre|tq'. + 0x86B9B794, // Small 't1mskc'. + 0x207DA12B, // Large 'tcmmimfp16|ps'. + 0x207DA135, // Large 'tcmmrlfp16|ps'. + 0x98C08C94, // Small 'tdcall'. + 0x207D7455, // Large 'tdpbf16|ps'. + 0x31434455, // Large 'tdpb|ssd'. + 0x32E44455, // Large 'tdpb|sud'. + 0x21445792, // Large 'tdpbu|sd'. + 0x22E55792, // Large 'tdpbu|ud'. + 0x207D745C, // Large 'tdpfp16|ps'. + 0x800A4CB4, // Small 'test'. + 0x935A4CB4, // Small 'testui'. + 0x000091C2, // Large 'tileloadd'. + 0x21AD91C2, // Large 'tileloadd|t1'. + 0x212791CB, // Large 'tilerelea|se'. + 0x102692C1, // Large 'tilestore|d'. + 0x43CB41C2, // Large 'tile|zero'. + 0x21E15797, // Large 'tlbsy|nc'. + 0x8B3A8614, // Small 'tpause'. + 0x81470F54, // Small 'tzcnt'. + 0x80B9B754, // Small 'tzmsk'. + 0x214456EE, // Large 'ucomi|sd'. + 0x201C56EE, // Large 'ucomi|ss'. + 0x80006C95, // Small 'ud0'. + 0x80007095, // Small 'ud1'. + 0x80007495, // Small 'ud2'. + 0x8142C935, // Small 'uiret'. + 0x7600109D, // Large 'u|monitor'. + 0xA890DDB5, // Small 'umwait'. + 0x20A76281, // Large 'unpckh|pd'. + 0x207D6281, // Large 'unpckh|ps'. + 0x35975281, // Large 'unpck|lpd'. + 0x359A5281, // Large 'unpck|lps'. + 0x30F16463, // Large 'v4fmad|dps'. + 0x32D16463, // Large 'v4fmad|dss'. + 0x30F172CA, // Large 'v4fnmad|dps'. + 0x32D172CA, // Large 'v4fnmad|dss'. + 0x89021036, // Small 'vaddpd'. + 0x91021036, // Small 'vaddph'. + 0xA7021036, // Small 'vaddps'. + 0x89321036, // Small 'vaddsd'. + 0x91321036, // Small 'vaddsh'. + 0xA7321036, // Small 'vaddss'. + 0x20A77469, // Large 'vaddsub|pd'. + 0x207D7469, // Large 'vaddsub|ps'. + 0x000071D4, // Large 'vaesdec'. + 0x302881D4, // Large 'vaesdecl|ast'. + 0x000071DC, // Large 'vaesenc'. + 0x302881DC, // Large 'vaesencl|ast'. + 0x2626579C, // Large 'vaesi|mc'. + 0x1020F011, // Large 'vaeskeygenassis|t'. + 0x219D57A1, // Large 'valig|nd'. + 0x271E57A1, // Large 'valig|nq'. + 0x20A757A6, // Large 'vandn|pd'. + 0x207D57A6, // Large 'vandn|ps'. + 0x89023836, // Small 'vandpd'. + 0xA7023836, // Small 'vandps'. + 0x1014D062, // Large 'vbcstnebf162p|s'. + 0x513F7062, // Large 'vbcstne|sh2ps'. + 0x20A77470, // Large 'vblendm|pd'. + 0x207D7470, // Large 'vblendm|ps'. + 0x20A76470, // Large 'vblend|pd'. + 0x207D6470, // Large 'vblend|ps'. + 0x34776470, // Large 'vblend|vpd'. + 0x318B6470, // Large 'vblend|vps'. + 0x306FB021, // Large 'vbroadcastf|128'. + 0x1003E021, // Large 'vbroadcastf32x|2'. + 0x102FE021, // Large 'vbroadcastf32x|4'. + 0x1005E021, // Large 'vbroadcastf32x|8'. + 0x4030B021, // Large 'vbroadcastf|64x2'. + 0x4034B021, // Large 'vbroadcastf|64x4'. + 0x4072A021, // Large 'vbroadcast|i128'. + 0x5038A021, // Large 'vbroadcast|i32x2'. + 0x503DA021, // Large 'vbroadcast|i32x4'. + 0x5042A021, // Large 'vbroadcast|i32x8'. + 0x5047A021, // Large 'vbroadcast|i64x2'. + 0x504CA021, // Large 'vbroadcast|i64x4'. + 0x2144A021, // Large 'vbroadcast|sd'. + 0x201CA021, // Large 'vbroadcast|ss'. + 0x89083476, // Small 'vcmppd'. + 0x91083476, // Small 'vcmpph'. + 0xA7083476, // Small 'vcmpps'. + 0x89383476, // Small 'vcmpsd'. + 0x91383476, // Small 'vcmpsh'. + 0xA7383476, // Small 'vcmpss'. + 0x214457AB, // Large 'vcomi|sd'. + 0x20D557AB, // Large 'vcomi|sh'. + 0x201C57AB, // Large 'vcomi|ss'. + 0x20A791E4, // Large 'vcompress|pd'. + 0x207D91E4, // Large 'vcompress|ps'. + 0x20A7747A, // Large 'vcvtdq2|pd'. + 0x20A2747A, // Large 'vcvtdq2|ph'. + 0x207D747A, // Large 'vcvtdq2|ps'. + 0x4069A076, // Large 'vcvtne2ps2|bf16'. + 0x307CB080, // Large 'vcvtneebf16|2ps'. + 0x51467080, // Large 'vcvtnee|ph2ps'. + 0x307CB08B, // Large 'vcvtneobf16|2ps'. + 0x5146708B, // Large 'vcvtneo|ph2ps'. + 0x406990FC, // Large 'vcvtneps2|bf16'. + 0x20E572D4, // Large 'vcvtpd2|dq'. + 0x20A272D4, // Large 'vcvtpd2|ph'. + 0x207D72D4, // Large 'vcvtpd2|ps'. + 0x21F672D4, // Large 'vcvtpd2|qq'. + 0x20E582D4, // Large 'vcvtpd2u|dq'. + 0x21F682D4, // Large 'vcvtpd2u|qq'. + 0x20E572DC, // Large 'vcvtph2|dq'. + 0x102682DC, // Large 'vcvtph2p|d'. + 0x000092DC, // Large 'vcvtph2ps'. + 0x102E92DC, // Large 'vcvtph2ps|x'. + 0x21F672DC, // Large 'vcvtph2|qq'. + 0x32E572DC, // Large 'vcvtph2|udq'. + 0x31F572DC, // Large 'vcvtph2|uqq'. + 0x248172DC, // Large 'vcvtph2|uw'. + 0x105F72DC, // Large 'vcvtph2|w'. + 0x20E572E8, // Large 'vcvtps2|dq'. + 0x102682E8, // Large 'vcvtps2p|d'. + 0x000092E8, // Large 'vcvtps2ph'. + 0x102E92E8, // Large 'vcvtps2ph|x'. + 0x21F672E8, // Large 'vcvtps2|qq'. + 0x32E572E8, // Large 'vcvtps2|udq'. + 0x31F572E8, // Large 'vcvtps2|uqq'. + 0x20A77483, // Large 'vcvtqq2|pd'. + 0x20A27483, // Large 'vcvtqq2|ph'. + 0x207D7483, // Large 'vcvtqq2|ps'. + 0x20D572F1, // Large 'vcvtsd2|sh'. + 0x201D72F1, // Large 'vcvtsd2|si'. + 0x201C72F1, // Large 'vcvtsd2|ss'. + 0x201D82F1, // Large 'vcvtsd2u|si'. + 0x214472F9, // Large 'vcvtsh2|sd'. + 0x201D72F9, // Large 'vcvtsh2|si'. + 0x201C72F9, // Large 'vcvtsh2|ss'. + 0x201D82F9, // Large 'vcvtsh2u|si'. + 0x2144748A, // Large 'vcvtsi2|sd'. + 0x20D5748A, // Large 'vcvtsi2|sh'. + 0x201C748A, // Large 'vcvtsi2|ss'. + 0x21447301, // Large 'vcvtss2|sd'. + 0x20D57301, // Large 'vcvtss2|sh'. + 0x201D7301, // Large 'vcvtss2|si'. + 0x201D8301, // Large 'vcvtss2u|si'. + 0x20E581ED, // Large 'vcvttpd2|dq'. + 0x21F681ED, // Large 'vcvttpd2|qq'. + 0x20E591ED, // Large 'vcvttpd2u|dq'. + 0x21F691ED, // Large 'vcvttpd2u|qq'. + 0x20E581F8, // Large 'vcvttph2|dq'. + 0x21F681F8, // Large 'vcvttph2|qq'. + 0x20E591F8, // Large 'vcvttph2u|dq'. + 0x21F691F8, // Large 'vcvttph2u|qq'. + 0x105F91F8, // Large 'vcvttph2u|w'. + 0x105F81F8, // Large 'vcvttph2|w'. + 0x20E58201, // Large 'vcvttps2|dq'. + 0x21F68201, // Large 'vcvttps2|qq'. + 0x20E59201, // Large 'vcvttps2u|dq'. + 0x21F69201, // Large 'vcvttps2u|qq'. + 0x201D820A, // Large 'vcvttsd2|si'. + 0x201D920A, // Large 'vcvttsd2u|si'. + 0x201D8213, // Large 'vcvttsh2|si'. + 0x201D9213, // Large 'vcvttsh2u|si'. + 0x201D821C, // Large 'vcvttss2|si'. + 0x201D921C, // Large 'vcvttss2u|si'. + 0x20A78309, // Large 'vcvtudq2|pd'. + 0x20A28309, // Large 'vcvtudq2|ph'. + 0x207D8309, // Large 'vcvtudq2|ps'. + 0x20A78311, // Large 'vcvtuqq2|pd'. + 0x20A28311, // Large 'vcvtuqq2|ph'. + 0x207D8311, // Large 'vcvtuqq2|ps'. + 0x21448319, // Large 'vcvtusi2|sd'. + 0x20D58319, // Large 'vcvtusi2|sh'. + 0x201C8319, // Large 'vcvtusi2|ss'. + 0x30A16491, // Large 'vcvtuw|2ph'. + 0x30A15640, // Large 'vcvtw|2ph'. + 0x239A7497, // Large 'vdbpsad|bw'. + 0x890B2496, // Small 'vdivpd'. + 0x910B2496, // Small 'vdivph'. + 0xA70B2496, // Small 'vdivps'. + 0x893B2496, // Small 'vdivsd'. + 0x913B2496, // Small 'vdivsh'. + 0xA73B2496, // Small 'vdivss'. + 0x207D749E, // Large 'vdpbf16|ps'. + 0x80484096, // Small 'vdppd'. + 0x81384096, // Small 'vdpps'. + 0x800948B6, // Small 'verr'. + 0x800BC8B6, // Small 'verw'. + 0x352544A5, // Large 'vexp|2pd'. + 0x307C44A5, // Large 'vexp|2ps'. + 0x30ED64A5, // Large 'vexpan|dpd'. + 0x30F164A5, // Large 'vexpan|dps'. + 0x306F910C, // Large 'vextractf|128'. + 0x602A7105, // Large 'vextrac|tf32x4'. + 0x4043910C, // Large 'vextractf|32x8'. + 0x4030910C, // Large 'vextractf|64x2'. + 0x4034910C, // Large 'vextractf|64x4'. + 0x4072810C, // Large 'vextract|i128'. + 0x503D810C, // Large 'vextract|i32x4'. + 0x5042810C, // Large 'vextract|i32x8'. + 0x5047810C, // Large 'vextract|i64x2'. + 0x504C810C, // Large 'vextract|i64x4'. + 0x207D810C, // Large 'vextract|ps'. + 0x20A28321, // Large 'vfcmaddc|ph'. + 0x20D58321, // Large 'vfcmaddc|sh'. + 0x20A274AB, // Large 'vfcmulc|ph'. + 0x20D574AB, // Large 'vfcmulc|sh'. + 0x20A79225, // Large 'vfixupimm|pd'. + 0x207D9225, // Large 'vfixupimm|ps'. + 0x21449225, // Large 'vfixupimm|sd'. + 0x201C9225, // Large 'vfixupimm|ss'. + 0x20A7922E, // Large 'vfmadd132|pd'. + 0x20A2922E, // Large 'vfmadd132|ph'. + 0x207D922E, // Large 'vfmadd132|ps'. + 0x2144922E, // Large 'vfmadd132|sd'. + 0x20D5922E, // Large 'vfmadd132|sh'. + 0x201C922E, // Large 'vfmadd132|ss'. + 0x50A46096, // Large 'vfmadd|213pd'. + 0x50A96096, // Large 'vfmadd|213ph'. + 0x50AE6096, // Large 'vfmadd|213ps'. + 0x51556096, // Large 'vfmadd|213sd'. + 0x515A6096, // Large 'vfmadd|213sh'. + 0x515F6096, // Large 'vfmadd|213ss'. + 0x50B36096, // Large 'vfmadd|231pd'. + 0x50B86096, // Large 'vfmadd|231ph'. + 0x50BD6096, // Large 'vfmadd|231ps'. + 0x51646096, // Large 'vfmadd|231sd'. + 0x51696096, // Large 'vfmadd|231sh'. + 0x516E6096, // Large 'vfmadd|231ss'. + 0x34B26096, // Large 'vfmadd|cph'. + 0x34B56096, // Large 'vfmadd|csh'. + 0x20A76096, // Large 'vfmadd|pd'. + 0x207D6096, // Large 'vfmadd|ps'. + 0x10267096, // Large 'vfmadds|d'. + 0x10147096, // Large 'vfmadds|s'. + 0x1026D096, // Large 'vfmaddsub132p|d'. + 0x10A3D096, // Large 'vfmaddsub132p|h'. + 0x1014D096, // Large 'vfmaddsub132p|s'. + 0x50A49096, // Large 'vfmaddsub|213pd'. + 0x50A99096, // Large 'vfmaddsub|213ph'. + 0x50AE9096, // Large 'vfmaddsub|213ps'. + 0x50B39096, // Large 'vfmaddsub|231pd'. + 0x50B89096, // Large 'vfmaddsub|231ph'. + 0x50BD9096, // Large 'vfmaddsub|231ps'. + 0x20A79096, // Large 'vfmaddsub|pd'. + 0x207D9096, // Large 'vfmaddsub|ps'. + 0x20A79237, // Large 'vfmsub132|pd'. + 0x20A29237, // Large 'vfmsub132|ph'. + 0x207D9237, // Large 'vfmsub132|ps'. + 0x21449237, // Large 'vfmsub132|sd'. + 0x20D59237, // Large 'vfmsub132|sh'. + 0x201C9237, // Large 'vfmsub132|ss'. + 0x50A460C2, // Large 'vfmsub|213pd'. + 0x50A960C2, // Large 'vfmsub|213ph'. + 0x50AE60C2, // Large 'vfmsub|213ps'. + 0x515560C2, // Large 'vfmsub|213sd'. + 0x515A60C2, // Large 'vfmsub|213sh'. + 0x515F60C2, // Large 'vfmsub|213ss'. + 0x50B360C2, // Large 'vfmsub|231pd'. + 0x50B860C2, // Large 'vfmsub|231ph'. + 0x50BD60C2, // Large 'vfmsub|231ps'. + 0x516460C2, // Large 'vfmsub|231sd'. + 0x516960C2, // Large 'vfmsub|231sh'. + 0x516E60C2, // Large 'vfmsub|231ss'. + 0x20A7C0C2, // Large 'vfmsubadd132|pd'. + 0x20A2C0C2, // Large 'vfmsubadd132|ph'. + 0x207DC0C2, // Large 'vfmsubadd132|ps'. + 0x50A490C2, // Large 'vfmsubadd|213pd'. + 0x50A990C2, // Large 'vfmsubadd|213ph'. + 0x50AE90C2, // Large 'vfmsubadd|213ps'. + 0x50B390C2, // Large 'vfmsubadd|231pd'. + 0x50B890C2, // Large 'vfmsubadd|231ph'. + 0x50BD90C2, // Large 'vfmsubadd|231ps'. + 0x20A790C2, // Large 'vfmsubadd|pd'. + 0x207D90C2, // Large 'vfmsubadd|ps'. + 0x20A760C2, // Large 'vfmsub|pd'. + 0x207D60C2, // Large 'vfmsub|ps'. + 0x214460C2, // Large 'vfmsub|sd'. + 0x201C60C2, // Large 'vfmsub|ss'. + 0x34B25645, // Large 'vfmul|cph'. + 0x34B55645, // Large 'vfmul|csh'. + 0x20A7A14B, // Large 'vfnmadd132|pd'. + 0x20A2A14B, // Large 'vfnmadd132|ph'. + 0x207DA14B, // Large 'vfnmadd132|ps'. + 0x2144A14B, // Large 'vfnmadd132|sd'. + 0x20D5A14B, // Large 'vfnmadd132|sh'. + 0x201CA14B, // Large 'vfnmadd132|ss'. + 0x50A4714B, // Large 'vfnmadd|213pd'. + 0x50A9714B, // Large 'vfnmadd|213ph'. + 0x50AE714B, // Large 'vfnmadd|213ps'. + 0x5155714B, // Large 'vfnmadd|213sd'. + 0x515A714B, // Large 'vfnmadd|213sh'. + 0x515F714B, // Large 'vfnmadd|213ss'. + 0x50B3714B, // Large 'vfnmadd|231pd'. + 0x50B8714B, // Large 'vfnmadd|231ph'. + 0x50BD714B, // Large 'vfnmadd|231ps'. + 0x5164714B, // Large 'vfnmadd|231sd'. + 0x5169714B, // Large 'vfnmadd|231sh'. + 0x516E714B, // Large 'vfnmadd|231ss'. + 0x20A7714B, // Large 'vfnmadd|pd'. + 0x207D714B, // Large 'vfnmadd|ps'. + 0x2144714B, // Large 'vfnmadd|sd'. + 0x201C714B, // Large 'vfnmadd|ss'. + 0x20A7A173, // Large 'vfnmsub132|pd'. + 0x20A2A173, // Large 'vfnmsub132|ph'. + 0x207DA173, // Large 'vfnmsub132|ps'. + 0x2144A173, // Large 'vfnmsub132|sd'. + 0x20D5A173, // Large 'vfnmsub132|sh'. + 0x201CA173, // Large 'vfnmsub132|ss'. + 0x50A47173, // Large 'vfnmsub|213pd'. + 0x50A97173, // Large 'vfnmsub|213ph'. + 0x50AE7173, // Large 'vfnmsub|213ps'. + 0x51557173, // Large 'vfnmsub|213sd'. + 0x515A7173, // Large 'vfnmsub|213sh'. + 0x515F7173, // Large 'vfnmsub|213ss'. + 0x50B37173, // Large 'vfnmsub|231pd'. + 0x50B87173, // Large 'vfnmsub|231ph'. + 0x50BD7173, // Large 'vfnmsub|231ps'. + 0x51647173, // Large 'vfnmsub|231sd'. + 0x51697173, // Large 'vfnmsub|231sh'. + 0x516E7173, // Large 'vfnmsub|231ss'. + 0x20A77173, // Large 'vfnmsub|pd'. + 0x207D7173, // Large 'vfnmsub|ps'. + 0x21447173, // Large 'vfnmsub|sd'. + 0x201C7173, // Large 'vfnmsub|ss'. + 0x20A78329, // Large 'vfpclass|pd'. + 0x20A28329, // Large 'vfpclass|ph'. + 0x207D8329, // Large 'vfpclass|ps'. + 0x21448329, // Large 'vfpclass|sd'. + 0x20D58329, // Large 'vfpclass|sh'. + 0x201C8329, // Large 'vfpclass|ss'. + 0x20A757B0, // Large 'vfrcz|pd'. + 0x207D57B0, // Large 'vfrcz|ps'. + 0x214457B0, // Large 'vfrcz|sd'. + 0x201C57B0, // Large 'vfrcz|ss'. + 0x30ED7115, // Large 'vgather|dpd'. + 0x30F17115, // Large 'vgather|dps'. + 0x30EDA115, // Large 'vgatherpf0|dpd'. + 0x30F1A115, // Large 'vgatherpf0|dps'. + 0x30E6A115, // Large 'vgatherpf0|qpd'. + 0x30E9A115, // Large 'vgatherpf0|qps'. + 0x40EC9115, // Large 'vgatherpf|1dpd'. + 0x40F09115, // Large 'vgatherpf|1dps'. + 0x40F49115, // Large 'vgatherpf|1qpd'. + 0x40F89115, // Large 'vgatherpf|1qps'. + 0x30E67115, // Large 'vgather|qpd'. + 0x30E97115, // Large 'vgather|qps'. + 0x20A774B8, // Large 'vgetexp|pd'. + 0x20A274B8, // Large 'vgetexp|ph'. + 0x207D74B8, // Large 'vgetexp|ps'. + 0x214474B8, // Large 'vgetexp|sd'. + 0x20D574B8, // Large 'vgetexp|sh'. + 0x201C74B8, // Large 'vgetexp|ss'. + 0x31F17331, // Large 'vgetman|tpd'. + 0x31FC7331, // Large 'vgetman|tph'. + 0x32057331, // Large 'vgetman|tps'. + 0x320E7331, // Large 'vgetman|tsd'. + 0x32177331, // Large 'vgetman|tsh'. + 0x32207331, // Large 'vgetman|tss'. + 0x200FF000, // Large 'vgf2p8affineinv|qb'. + 0x200FC000, // Large 'vgf2p8affine|qb'. + 0x43386000, // Large 'vgf2p8|mulb'. + 0x30ED47B5, // Large 'vhad|dpd'. + 0x30F147B5, // Large 'vhad|dps'. + 0x20A757B9, // Large 'vhsub|pd'. + 0x207D57B9, // Large 'vhsub|ps'. + 0x306F8183, // Large 'vinsertf|128'. + 0x602A617D, // Large 'vinser|tf32x4'. + 0x40438183, // Large 'vinsertf|32x8'. + 0x40308183, // Large 'vinsertf|64x2'. + 0x40348183, // Large 'vinsertf|64x4'. + 0x40727183, // Large 'vinsert|i128'. + 0x503D7183, // Large 'vinsert|i32x4'. + 0x50427183, // Large 'vinsert|i32x8'. + 0x50477183, // Large 'vinsert|i64x2'. + 0x504C7183, // Large 'vinsert|i64x4'. + 0x207D7183, // Large 'vinsert|ps'. + 0xAB121196, // Small 'vlddqu'. + 0x1023764A, // Large 'vldmxcs|r'. + 0x109DA240, // Large 'vmaskmovdq|u'. + 0x20A78240, // Large 'vmaskmov|pd'. + 0x207D8240, // Large 'vmaskmov|ps'. + 0x890C05B6, // Small 'vmaxpd'. + 0x910C05B6, // Small 'vmaxph'. + 0xA70C05B6, // Small 'vmaxps'. + 0x893C05B6, // Small 'vmaxsd'. + 0x913C05B6, // Small 'vmaxsh'. + 0xA73C05B6, // Small 'vmaxss'. + 0x98C08DB6, // Small 'vmcall'. + 0x242857BE, // Large 'vmcle|ar'. + 0x86EA99B6, // Small 'vmfunc'. + 0x219257C3, // Large 'vmgex|it'. + 0x890725B6, // Small 'vminpd'. + 0x910725B6, // Small 'vminph'. + 0xA70725B6, // Small 'vminps'. + 0x893725B6, // Small 'vminsd'. + 0x913725B6, // Small 'vminsh'. + 0xA73725B6, // Small 'vminss'. + 0x21A56651, // Large 'vmlaun|ch'. + 0x8817B1B6, // Small 'vmload'. + 0x36F347C8, // Large 'vmmc|all'. + 0x20A757CC, // Large 'vmova|pd'. + 0x207D57CC, // Large 'vmova|ps'. + 0x804B3DB6, // Small 'vmovd'. + 0x365754BF, // Large 'vmovd|dup'. + 0x000074BF, // Large 'vmovdqa'. + 0x202C74BF, // Large 'vmovdqa|32'. + 0x203074BF, // Large 'vmovdqa|64'. + 0x109D64BF, // Large 'vmovdq|u'. + 0x34C664BF, // Large 'vmovdq|u16'. + 0x34C964BF, // Large 'vmovdq|u32'. + 0x34CC64BF, // Large 'vmovdq|u64'. + 0x265A64BF, // Large 'vmovdq|u8'. + 0x359A565C, // Large 'vmovh|lps'. + 0x20A7565C, // Large 'vmovh|pd'. + 0x207D565C, // Large 'vmovh|ps'. + 0x207D6661, // Large 'vmovlh|ps'. + 0x20A75661, // Large 'vmovl|pd'. + 0x207D5661, // Large 'vmovl|ps'. + 0x20A774CF, // Large 'vmovmsk|pd'. + 0x207D74CF, // Large 'vmovmsk|ps'. + 0x20E564D6, // Large 'vmovnt|dq'. + 0x34C364D6, // Large 'vmovnt|dqa'. + 0x20A764D6, // Large 'vmovnt|pd'. + 0x207D64D6, // Large 'vmovnt|ps'. + 0x811B3DB6, // Small 'vmovq'. + 0x893B3DB6, // Small 'vmovsd'. + 0x913B3DB6, // Small 'vmovsh'. + 0x222974DC, // Large 'vmovshd|up'. + 0x222974E3, // Large 'vmovsld|up'. + 0xA73B3DB6, // Small 'vmovss'. + 0x343344BF, // Large 'vmov|upd'. + 0x207D57D1, // Large 'vmovu|ps'. + 0x817B3DB6, // Small 'vmovw'. + 0x239A6667, // Large 'vmpsad|bw'. + 0x341147D6, // Large 'vmpt|rld'. + 0x340D47D6, // Large 'vmpt|rst'. + 0x8812C9B6, // Small 'vmread'. + 0x100B766D, // Large 'vmresum|e'. + 0x80EAC9B6, // Small 'vmrun'. + 0x8B60CDB6, // Small 'vmsave'. + 0x890655B6, // Small 'vmulpd'. + 0x910655B6, // Small 'vmulph'. + 0xA70655B6, // Small 'vmulps'. + 0x893655B6, // Small 'vmulsd'. + 0x913655B6, // Small 'vmulsh'. + 0xA73655B6, // Small 'vmulss'. + 0x20DF57DA, // Large 'vmwri|te'. + 0x8C67E1B6, // Small 'vmxoff'. + 0x80E7E1B6, // Small 'vmxon'. + 0x804849F6, // Small 'vorpd'. + 0x813849F6, // Small 'vorps'. + 0x1026C11F, // Large 'vp2intersect|d'. + 0x100FC11F, // Large 'vp2intersect|q'. + 0x1026833C, // Large 'vp4dpwss|d'. + 0x209B833C, // Large 'vp4dpwss|ds'. + 0x85310616, // Small 'vpabsb'. + 0x89310616, // Small 'vpabsd'. + 0xA3310616, // Small 'vpabsq'. + 0xAF310616, // Small 'vpabsw'. + 0x105F84EA, // Large 'vpackssd|w'. + 0x24F274EA, // Large 'vpackss|wb'. + 0x34F064F4, // Large 'vpacku|sdw'. + 0x34FA64F4, // Large 'vpacku|swb'. + 0x84420616, // Small 'vpaddb'. + 0x88420616, // Small 'vpaddd'. + 0xA2420616, // Small 'vpaddq'. + 0x25BA5674, // Large 'vpadd|sb'. + 0x23835674, // Large 'vpadd|sw'. + 0x25BA6674, // Large 'vpaddu|sb'. + 0x23836674, // Large 'vpaddu|sw'. + 0xAE420616, // Small 'vpaddw'. + 0x1023767A, // Large 'vpalign|r'. + 0x80470616, // Small 'vpand'. + 0x88470616, // Small 'vpandd'. + 0x9C470616, // Small 'vpandn'. + 0x219D57DF, // Large 'vpand|nd'. + 0x271E57DF, // Large 'vpand|nq'. + 0xA2470616, // Small 'vpandq'. + 0x847B0616, // Small 'vpavgb'. + 0xAE7B0616, // Small 'vpavgw'. + 0x102674FD, // Large 'vpblend|d'. + 0x205C74FD, // Large 'vpblend|mb'. + 0x250474FD, // Large 'vpblend|md'. + 0x100F84FD, // Large 'vpblendm|q'. + 0x105F84FD, // Large 'vpblendm|w'. + 0x202174FD, // Large 'vpblend|vb'. + 0x105F74FD, // Large 'vpblend|w'. + 0x1010B051, // Large 'vpbroadcast|b'. + 0x1026B051, // Large 'vpbroadcast|d'. + 0x100FE051, // Large 'vpbroadcastmb2|q'. + 0x305FC051, // Large 'vpbroadcastm|w2d'. + 0x100FB051, // Large 'vpbroadcast|q'. + 0x105FB051, // Large 'vpbroadcast|w'. + 0x42886344, // Large 'vpclmu|lqdq'. + 0xACF68E16, // Small 'vpcmov'. + 0x85068E16, // Small 'vpcmpb'. + 0x89068E16, // Small 'vpcmpd'. + 0x200F634A, // Large 'vpcmpe|qb'. + 0x227D634A, // Large 'vpcmpe|qd'. + 0x21F6634A, // Large 'vpcmpe|qq'. + 0x2559634A, // Large 'vpcmpe|qw'. + 0x1009934A, // Large 'vpcmpestr|i'. + 0x105C934A, // Large 'vpcmpestr|m'. + 0x3681534A, // Large 'vpcmp|gtb'. + 0x3684534A, // Large 'vpcmp|gtd'. + 0x3687534A, // Large 'vpcmp|gtq'. + 0x368A534A, // Large 'vpcmp|gtw'. + 0x10099353, // Large 'vpcmpistr|i'. + 0x105C9353, // Large 'vpcmpistr|m'. + 0xA3068E16, // Small 'vpcmpq'. + 0x209D534A, // Large 'vpcmp|ub'. + 0x22E5534A, // Large 'vpcmp|ud'. + 0x21F5534A, // Large 'vpcmp|uq'. + 0x2481534A, // Large 'vpcmp|uw'. + 0xAF068E16, // Small 'vpcmpw'. + 0x84D78E16, // Small 'vpcomb'. + 0x88D78E16, // Small 'vpcomd'. + 0x1010A24A, // Large 'vpcompress|b'. + 0x1026A24A, // Large 'vpcompress|d'. + 0x100FA24A, // Large 'vpcompress|q'. + 0x105FA24A, // Large 'vpcompress|w'. + 0xA2D78E16, // Small 'vpcomq'. + 0x209D524A, // Large 'vpcom|ub'. + 0x22E5524A, // Large 'vpcom|ud'. + 0x21F5524A, // Large 'vpcom|uq'. + 0x2481524A, // Large 'vpcom|uw'. + 0xAED78E16, // Small 'vpcomw'. + 0x1026A254, // Large 'vpconflict|d'. + 0x100FA254, // Large 'vpconflict|q'. + 0x10267506, // Large 'vpdpbss|d'. + 0x209B7506, // Large 'vpdpbss|ds'. + 0x22E56506, // Large 'vpdpbs|ud'. + 0x350D6506, // Large 'vpdpbs|uds'. + 0x10267510, // Large 'vpdpbus|d'. + 0x209B7510, // Large 'vpdpbus|ds'. + 0x22E56510, // Large 'vpdpbu|ud'. + 0x350D6510, // Large 'vpdpbu|uds'. + 0x10267517, // Large 'vpdpwss|d'. + 0x209B7517, // Large 'vpdpwss|ds'. + 0x22E56517, // Large 'vpdpws|ud'. + 0x350D6517, // Large 'vpdpws|uds'. + 0x1026751E, // Large 'vpdpwus|d'. + 0x209B751E, // Large 'vpdpwus|ds'. + 0x22E5651E, // Large 'vpdpwu|ud'. + 0x350D651E, // Large 'vpdpwu|uds'. + 0x306F735C, // Large 'vperm2f|128'. + 0x4072635C, // Large 'vperm2|i128'. + 0x84D91616, // Small 'vpermb'. + 0x88D91616, // Small 'vpermd'. + 0x268D6363, // Large 'vpermi|2b'. + 0x20606363, // Large 'vpermi|2d'. + 0x35256363, // Large 'vpermi|2pd'. + 0x307C6363, // Large 'vpermi|2ps'. + 0x268F6363, // Large 'vpermi|2q'. + 0x205E6363, // Large 'vpermi|2w'. + 0x20A78363, // Large 'vpermil2|pd'. + 0x207D8363, // Large 'vpermil2|ps'. + 0x20A77363, // Large 'vpermil|pd'. + 0x207D7363, // Large 'vpermil|ps'. + 0x20A7535C, // Large 'vperm|pd'. + 0x207D535C, // Large 'vperm|ps'. + 0xA2D91616, // Small 'vpermq'. + 0x268D6528, // Large 'vpermt|2b'. + 0x20606528, // Large 'vpermt|2d'. + 0x35256528, // Large 'vpermt|2pd'. + 0x307C6528, // Large 'vpermt|2ps'. + 0x268F6528, // Large 'vpermt|2q'. + 0x205E6528, // Large 'vpermt|2w'. + 0xAED91616, // Small 'vpermw'. + 0x2498752E, // Large 'vpexpan|db'. + 0x209A752E, // Large 'vpexpan|dd'. + 0x20E5752E, // Large 'vpexpan|dq'. + 0x24F1752E, // Large 'vpexpan|dw'. + 0x35F7452E, // Large 'vpex|trb'. + 0x261657E4, // Large 'vpext|rd'. + 0x227C57E4, // Large 'vpext|rq'. + 0x27E957E4, // Large 'vpext|rw'. + 0x209A836B, // Large 'vpgather|dd'. + 0x20E5836B, // Large 'vpgather|dq'. + 0x227D836B, // Large 'vpgather|qd'. + 0x21F6836B, // Large 'vpgather|qq'. + 0x26916535, // Large 'vphadd|bd'. + 0x26936535, // Large 'vphadd|bq'. + 0x239A6535, // Large 'vphadd|bw'. + 0x10266535, // Large 'vphadd|d'. + 0x20E56535, // Large 'vphadd|dq'. + 0x23836535, // Large 'vphadd|sw'. + 0x10268535, // Large 'vphaddub|d'. + 0x100F8535, // Large 'vphaddub|q'. + 0x105F8535, // Large 'vphaddub|w'. + 0x20E57535, // Large 'vphaddu|dq'. + 0x239C7535, // Large 'vphaddu|wd'. + 0x253D7535, // Large 'vphaddu|wq'. + 0x105F6535, // Large 'vphadd|w'. + 0x239C6535, // Large 'vphadd|wd'. + 0x253D6535, // Large 'vphadd|wq'. + 0x105FA25E, // Large 'vphminposu|w'. + 0x239A6695, // Large 'vphsub|bw'. + 0x10266695, // Large 'vphsub|d'. + 0x20E56695, // Large 'vphsub|dq'. + 0x23836695, // Large 'vphsub|sw'. + 0x105F6695, // Large 'vphsub|w'. + 0x239C6695, // Large 'vphsub|wd'. + 0x25F857EB, // Large 'vpins|rb'. + 0x261657EB, // Large 'vpins|rd'. + 0x227C57EB, // Large 'vpins|rq'. + 0x27E957EB, // Large 'vpins|rw'. + 0x2455669B, // Large 'vplzcn|td'. + 0x2193669B, // Large 'vplzcn|tq'. + 0x209A6373, // Large 'vpmacs|dd'. + 0x353F6373, // Large 'vpmacs|dqh'. + 0x33A26373, // Large 'vpmacs|dql'. + 0x10268373, // Large 'vpmacssd|d'. + 0x10A39373, // Large 'vpmacssdq|h'. + 0x10D29373, // Large 'vpmacssdq|l'. + 0x239C7373, // Large 'vpmacss|wd'. + 0x239B7373, // Large 'vpmacss|ww'. + 0x239C6373, // Large 'vpmacs|wd'. + 0x239B6373, // Large 'vpmacs|ww'. + 0x1026937C, // Large 'vpmadcssw|d'. + 0x239C737C, // Large 'vpmadcs|wd'. + 0x21F59268, // Large 'vpmadd52h|uq'. + 0x32718268, // Large 'vpmadd52|luq'. + 0x43856268, // Large 'vpmadd|ubsw'. + 0x239C6268, // Large 'vpmadd|wd'. + 0x62434268, // Large 'vpma|skmovd'. + 0x200E8389, // Large 'vpmaskmo|vq'. + 0x25BA57F0, // Large 'vpmax|sb'. + 0x214457F0, // Large 'vpmax|sd'. + 0x23A957F0, // Large 'vpmax|sq'. + 0x238357F0, // Large 'vpmax|sw'. + 0x209D57F0, // Large 'vpmax|ub'. + 0x22E557F0, // Large 'vpmax|ud'. + 0x21F557F0, // Large 'vpmax|uq'. + 0x248157F0, // Large 'vpmax|uw'. + 0x25BA57F5, // Large 'vpmin|sb'. + 0x214457F5, // Large 'vpmin|sd'. + 0x23A957F5, // Large 'vpmin|sq'. + 0x238357F5, // Large 'vpmin|sw'. + 0x209D57F5, // Large 'vpmin|ub'. + 0x22E557F5, // Large 'vpmin|ud'. + 0x21F557F5, // Large 'vpmin|uq'. + 0x248157F5, // Large 'vpmin|uw'. + 0x36A15542, // Large 'vpmov|b2m'. + 0x36A45542, // Large 'vpmov|d2m'. + 0x24985542, // Large 'vpmov|db'. + 0x24F15542, // Large 'vpmov|dw'. + 0x268D6542, // Large 'vpmovm|2b'. + 0x20606542, // Large 'vpmovm|2d'. + 0x268F6542, // Large 'vpmovm|2q'. + 0x205E6542, // Large 'vpmovm|2w'. + 0x10108542, // Large 'vpmovmsk|b'. + 0x36A75542, // Large 'vpmov|q2m'. + 0x200F5542, // Large 'vpmov|qb'. + 0x227D5542, // Large 'vpmov|qd'. + 0x25595542, // Large 'vpmov|qw'. + 0x2498654A, // Large 'vpmovs|db'. + 0x24F1654A, // Large 'vpmovs|dw'. + 0x200F654A, // Large 'vpmovs|qb'. + 0x227D654A, // Large 'vpmovs|qd'. + 0x2559654A, // Large 'vpmovs|qw'. + 0x24F2654A, // Large 'vpmovs|wb'. + 0x1026854A, // Large 'vpmovsxb|d'. + 0x100F854A, // Large 'vpmovsxb|q'. + 0x105F854A, // Large 'vpmovsxb|w'. + 0x20E5754A, // Large 'vpmovsx|dq'. + 0x239C754A, // Large 'vpmovsx|wd'. + 0x253D754A, // Large 'vpmovsx|wq'. + 0x24987552, // Large 'vpmovus|db'. + 0x24F17552, // Large 'vpmovus|dw'. + 0x200F7552, // Large 'vpmovus|qb'. + 0x227D7552, // Large 'vpmovus|qd'. + 0x25597552, // Large 'vpmovus|qw'. + 0x24F27552, // Large 'vpmovus|wb'. + 0x36AA5542, // Large 'vpmov|w2m'. + 0x24F25542, // Large 'vpmov|wb'. + 0x1026855B, // Large 'vpmovzxb|d'. + 0x100F855B, // Large 'vpmovzxb|q'. + 0x105F855B, // Large 'vpmovzxb|w'. + 0x20E5755B, // Large 'vpmovzx|dq'. + 0x239C755B, // Large 'vpmovzx|wd'. + 0x253D755B, // Large 'vpmovzx|wq'. + 0x20E550CE, // Large 'vpmul|dq'. + 0x23837563, // Large 'vpmulhr|sw'. + 0x24816563, // Large 'vpmulh|uw'. + 0x105F6563, // Large 'vpmulh|w'. + 0x23A150CE, // Large 'vpmul|ld'. + 0x228850CE, // Large 'vpmul|lq'. + 0x23A450CE, // Large 'vpmul|lw'. + 0x200FC0CE, // Large 'vpmultishift|qb'. + 0x32E550CE, // Large 'vpmul|udq'. + 0x268266AD, // Large 'vpopcn|tb'. + 0x245566AD, // Large 'vpopcn|td'. + 0x219366AD, // Large 'vpopcn|tq'. + 0x264366AD, // Large 'vpopcn|tw'. + 0x80093E16, // Small 'vpor'. + 0x80493E16, // Small 'vpord'. + 0x81193E16, // Small 'vporq'. + 0x9B22C216, // Small 'vpperm'. + 0x88C7CA16, // Small 'vprold'. + 0xA2C7CA16, // Small 'vprolq'. + 0x224757FA, // Large 'vprol|vd'. + 0x200E57FA, // Large 'vprol|vq'. + 0x8927CA16, // Small 'vprord'. + 0xA327CA16, // Small 'vprorq'. + 0x224757FF, // Large 'vpror|vd'. + 0x200E57FF, // Large 'vpror|vq'. + 0x8547CA16, // Small 'vprotb'. + 0x8947CA16, // Small 'vprotd'. + 0xA347CA16, // Small 'vprotq'. + 0xAF47CA16, // Small 'vprotw'. + 0x239A5804, // Large 'vpsad|bw'. + 0x209A9274, // Large 'vpscatter|dd'. + 0x20E59274, // Large 'vpscatter|dq'. + 0x227D9274, // Large 'vpscatter|qd'. + 0x100FA274, // Large 'vpscatterq|q'. + 0x84144E16, // Small 'vpshab'. + 0x88144E16, // Small 'vpshad'. + 0xA2144E16, // Small 'vpshaq'. + 0xAE144E16, // Small 'vpshaw'. + 0x84C44E16, // Small 'vpshlb'. + 0x88C44E16, // Small 'vpshld'. + 0x102666B3, // Large 'vpshld|d'. + 0x100F66B3, // Large 'vpshld|q'. + 0x349D56B3, // Large 'vpshl|dvd'. + 0x36B856B3, // Large 'vpshl|dvq'. + 0x105F76B3, // Large 'vpshldv|w'. + 0x105F66B3, // Large 'vpshld|w'. + 0xA2C44E16, // Small 'vpshlq'. + 0xAEC44E16, // Small 'vpshlw'. + 0x102666BB, // Large 'vpshrd|d'. + 0x100F66BB, // Large 'vpshrd|q'. + 0x349D56BB, // Large 'vpshr|dvd'. + 0x36B856BB, // Large 'vpshr|dvq'. + 0x36C056BB, // Large 'vpshr|dvw'. + 0x105F66BB, // Large 'vpshrd|w'. + 0x0000718B, // Large 'vpshufb'. + 0x205CA18B, // Large 'vpshufbitq|mb'. + 0x1026618B, // Large 'vpshuf|d'. + 0x26C3618B, // Large 'vpshuf|hw'. + 0x23A4618B, // Large 'vpshuf|lw'. + 0x22A95809, // Large 'vpsig|nb'. + 0x219D5809, // Large 'vpsig|nd'. + 0x26FB5809, // Large 'vpsig|nw'. + 0x88C64E16, // Small 'vpslld'. + 0x33A1480E, // Large 'vpsl|ldq'. + 0xA2C64E16, // Small 'vpsllq'. + 0x22475812, // Large 'vpsll|vd'. + 0x200E5812, // Large 'vpsll|vq'. + 0x26C15812, // Large 'vpsll|vw'. + 0xAEC64E16, // Small 'vpsllw'. + 0x88194E16, // Small 'vpsrad'. + 0xA2194E16, // Small 'vpsraq'. + 0x22475817, // Large 'vpsra|vd'. + 0x200E5817, // Large 'vpsra|vq'. + 0x26C15817, // Large 'vpsra|vw'. + 0xAE194E16, // Small 'vpsraw'. + 0x88C94E16, // Small 'vpsrld'. + 0x33A14817, // Large 'vpsr|ldq'. + 0xA2C94E16, // Small 'vpsrlq'. + 0x2247581C, // Large 'vpsrl|vd'. + 0x200E581C, // Large 'vpsrl|vq'. + 0x26C1581C, // Large 'vpsrl|vw'. + 0xAEC94E16, // Small 'vpsrlw'. + 0x842ACE16, // Small 'vpsubb'. + 0x882ACE16, // Small 'vpsubd'. + 0xA22ACE16, // Small 'vpsubq'. + 0x25BA56C5, // Large 'vpsub|sb'. + 0x238356C5, // Large 'vpsub|sw'. + 0x25BA66C5, // Large 'vpsubu|sb'. + 0x238366C5, // Large 'vpsubu|sw'. + 0xAE2ACE16, // Small 'vpsubw'. + 0x10269391, // Large 'vpternlog|d'. + 0x100F9391, // Large 'vpternlog|q'. + 0xA932D216, // Small 'vptest'. + 0x205C656A, // Large 'vptest|mb'. + 0x2504656A, // Large 'vptest|md'. + 0x2571656A, // Large 'vptest|mq'. + 0x26A9656A, // Large 'vptest|mw'. + 0x205C756A, // Large 'vptestn|mb'. + 0x2504756A, // Large 'vptestn|md'. + 0x2571756A, // Large 'vptestn|mq'. + 0x105F856A, // Large 'vptestnm|w'. + 0x239A827F, // Large 'vpunpckh|bw'. + 0x20E5827F, // Large 'vpunpckh|dq'. + 0x20E5927F, // Large 'vpunpckhq|dq'. + 0x239C827F, // Large 'vpunpckh|wd'. + 0x339E727F, // Large 'vpunpck|lbw'. + 0x33A1727F, // Large 'vpunpck|ldq'. + 0x4288727F, // Large 'vpunpck|lqdq'. + 0x33A4727F, // Large 'vpunpck|lwd'. + 0x8127E216, // Small 'vpxor'. + 0x8927E216, // Small 'vpxord'. + 0xA327E216, // Small 'vpxorq'. + 0x20A766CB, // Large 'vrange|pd'. + 0x207D66CB, // Large 'vrange|ps'. + 0x214466CB, // Large 'vrange|sd'. + 0x201C66CB, // Large 'vrange|ss'. + 0x20A766D1, // Large 'vrcp14|pd'. + 0x207D66D1, // Large 'vrcp14|ps'. + 0x214466D1, // Large 'vrcp14|sd'. + 0x201C66D1, // Large 'vrcp14|ss'. + 0x43AF46D1, // Large 'vrcp|28pd'. + 0x43B346D1, // Large 'vrcp|28ps'. + 0x43B746D1, // Large 'vrcp|28sd'. + 0x43BB46D1, // Large 'vrcp|28ss'. + 0x91080E56, // Small 'vrcpph'. + 0xA7080E56, // Small 'vrcpps'. + 0x91380E56, // Small 'vrcpsh'. + 0xA7380E56, // Small 'vrcpss'. + 0x20A77573, // Large 'vreduce|pd'. + 0x20A27573, // Large 'vreduce|ph'. + 0x207D7573, // Large 'vreduce|ps'. + 0x21447573, // Large 'vreduce|sd'. + 0x20D57573, // Large 'vreduce|sh'. + 0x201C7573, // Large 'vreduce|ss'. + 0x20A7928C, // Large 'vrndscale|pd'. + 0x20A2928C, // Large 'vrndscale|ph'. + 0x207D928C, // Large 'vrndscale|ps'. + 0x2144928C, // Large 'vrndscale|sd'. + 0x20D5928C, // Large 'vrndscale|sh'. + 0x201C928C, // Large 'vrndscale|ss'. + 0x30ED56D7, // Large 'vroun|dpd'. + 0x30F156D7, // Large 'vroun|dps'. + 0x36DC56D7, // Large 'vroun|dsd'. + 0x101476D7, // Large 'vrounds|s'. + 0x20A783A7, // Large 'vrsqrt14|pd'. + 0x207D83A7, // Large 'vrsqrt14|ps'. + 0x214483A7, // Large 'vrsqrt14|sd'. + 0x201C83A7, // Large 'vrsqrt14|ss'. + 0x43AF63A7, // Large 'vrsqrt|28pd'. + 0x43B363A7, // Large 'vrsqrt|28ps'. + 0x43B763A7, // Large 'vrsqrt|28sd'. + 0x43BB63A7, // Large 'vrsqrt|28ss'. + 0x20A263A7, // Large 'vrsqrt|ph'. + 0x207D63A7, // Large 'vrsqrt|ps'. + 0x20D563A7, // Large 'vrsqrt|sh'. + 0x201C63A7, // Large 'vrsqrt|ss'. + 0x20A7757A, // Large 'vscalef|pd'. + 0x20A2757A, // Large 'vscalef|ph'. + 0x207D757A, // Large 'vscalef|ps'. + 0x2144757A, // Large 'vscalef|sd'. + 0x20D5757A, // Large 'vscalef|sh'. + 0x201C757A, // Large 'vscalef|ss'. + 0x30ED80DA, // Large 'vscatter|dpd'. + 0x30F180DA, // Large 'vscatter|dps'. + 0x20A7C0DA, // Large 'vscatterpf0d|pd'. + 0x207DC0DA, // Large 'vscatterpf0d|ps'. + 0x30E6B0DA, // Large 'vscatterpf0|qpd'. + 0x30E9B0DA, // Large 'vscatterpf0|qps'. + 0x40ECA0DA, // Large 'vscatterpf|1dpd'. + 0x40F0A0DA, // Large 'vscatterpf|1dps'. + 0x40F4A0DA, // Large 'vscatterpf|1qpd'. + 0x40F8A0DA, // Large 'vscatterpf|1qps'. + 0x30E680DA, // Large 'vscatter|qpd'. + 0x30E980DA, // Large 'vscatter|qps'. + 0x42957195, // Large 'vsha512|msg1'. + 0x42997195, // Large 'vsha512|msg2'. + 0x207EA195, // Large 'vsha512rnd|s2'. + 0x502B53BF, // Large 'vshuf|f32x4'. + 0x403063C4, // Large 'vshuff|64x2'. + 0x503D53BF, // Large 'vshuf|i32x4'. + 0x504753BF, // Large 'vshuf|i64x2'. + 0x20A753BF, // Large 'vshuf|pd'. + 0x207D53BF, // Large 'vshuf|ps'. + 0x42954581, // Large 'vsm3|msg1'. + 0x42994581, // Large 'vsm3|msg2'. + 0x207E7581, // Large 'vsm3rnd|s2'. + 0x102F76DF, // Large 'vsm4key|4'. + 0x102F8588, // Large 'vsm4rnds|4'. + 0x31F14821, // Large 'vsqr|tpd'. + 0x31FC4821, // Large 'vsqr|tph'. + 0x32054821, // Large 'vsqr|tps'. + 0x320E4821, // Large 'vsqr|tsd'. + 0x32174821, // Large 'vsqr|tsh'. + 0x32204821, // Large 'vsqr|tss'. + 0x102376E6, // Large 'vstmxcs|r'. + 0x89015676, // Small 'vsubpd'. + 0x91015676, // Small 'vsubph'. + 0xA7015676, // Small 'vsubps'. + 0x89315676, // Small 'vsubsd'. + 0x91315676, // Small 'vsubsh'. + 0xA7315676, // Small 'vsubss'. + 0x31F14825, // Large 'vtes|tpd'. + 0x32054825, // Large 'vtes|tps'. + 0x214466ED, // Large 'vucomi|sd'. + 0x20D566ED, // Large 'vucomi|sh'. + 0x201C66ED, // Large 'vucomi|ss'. + 0x20A77590, // Large 'vunpckh|pd'. + 0x207D7590, // Large 'vunpckh|ps'. + 0x35976590, // Large 'vunpck|lpd'. + 0x359A6590, // Large 'vunpck|lps'. + 0x89093F16, // Small 'vxorpd'. + 0xA7093F16, // Small 'vxorps'. + 0x36F353CA, // Large 'vzero|all'. + 0x335D73CA, // Large 'vzeroup|per'. + 0x89672457, // Small 'wbinvd'. + 0x224766F6, // Large 'wbnoin|vd'. + 0x343656FC, // Large 'wrfsb|ase'. + 0x34365701, // Large 'wrgsb|ase'. + 0x8129B657, // Small 'wrmsr'. + 0x8049CE57, // Small 'wrssd'. + 0x8119CE57, // Small 'wrssq'. + 0x8939D657, // Small 'wrussd'. + 0xA339D657, // Small 'wrussq'. + 0xA9278838, // Small 'xabort'. + 0x80021038, // Small 'xadd'. + 0x9C939458, // Small 'xbegin'. + 0x8003A078, // Small 'xchg'. + 0x800238B8, // Small 'xend'. + 0xAC2A14F8, // Small 'xgetbv'. + 0x802A0598, // Small 'xlatb'. + 0x800049F8, // Small 'xor'. + 0x804849F8, // Small 'xorpd'. + 0x813849F8, // Small 'xorps'. + 0x1015859D, // Large 'xresldtr|k'. + 0xA4FA4E58, // Small 'xrstor'. + 0x2030640C, // Large 'xrstor|64'. + 0x1014640C, // Large 'xrstor|s'. + 0x35A5640C, // Large 'xrstor|s64'. + 0x805B0678, // Small 'xsave'. + 0x203053D1, // Large 'xsave|64'. + 0x865B0678, // Small 'xsavec'. + 0x370653D1, // Large 'xsave|c64'. + 0x000083D1, // Large 'xsaveopt'. + 0x203083D1, // Large 'xsaveopt|64'. + 0xA65B0678, // Small 'xsaves'. + 0x35A553D1, // Large 'xsave|s64'. + 0xAC2A1678, // Small 'xsetbv'. + 0x101585A8, // Large 'xsusldtr|k'. + 0x81499698 // Small 'xtest'. }; // ---------------------------------------------------------------------------- // ${NameData:End} @@ -3054,515 +4729,573 @@ const InstDB::InstSignature InstDB::_instSignatureTable[] = { ROW(2, 1, 1, 0, 9 , 10 , 0 , 0 , 0 , 0 ), // {r8lo|r8hi|m8, i8|u8} ROW(2, 1, 1, 0, 11 , 12 , 0 , 0 , 0 , 0 ), // {r16|m16, i16|u16} ROW(2, 1, 1, 0, 13 , 14 , 0 , 0 , 0 , 0 ), // {r32|m32, i32|u32} - ROW(2, 0, 1, 0, 15 , 16 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, i32} + ROW(2, 0, 1, 0, 15 , 16 , 0 , 0 , 0 , 0 ), // {r64|m64, i32} ROW(2, 0, 1, 0, 8 , 17 , 0 , 0 , 0 , 0 ), // {r64, i64|u64|m64|mem|sreg|creg|dreg} ROW(2, 1, 1, 0, 2 , 18 , 0 , 0 , 0 , 0 ), // {r8lo|r8hi, m8|mem} ROW(2, 1, 1, 0, 4 , 19 , 0 , 0 , 0 , 0 ), // {r16, m16|mem|sreg} ROW(2, 1, 1, 0, 6 , 20 , 0 , 0 , 0 , 0 ), // {r32, m32|mem|sreg} ROW(2, 1, 1, 0, 21 , 22 , 0 , 0 , 0 , 0 ), // {m16|mem, sreg} + ROW(2, 1, 1, 0, 21 , 22 , 0 , 0 , 0 , 0 ), // {m16|mem, sreg} + ROW(2, 0, 1, 0, 21 , 22 , 0 , 0 , 0 , 0 ), // {m16|mem, sreg} ROW(2, 1, 1, 0, 22 , 21 , 0 , 0 , 0 , 0 ), // {sreg, m16|mem} + ROW(2, 1, 1, 0, 22 , 21 , 0 , 0 , 0 , 0 ), // {sreg, m16|mem} + ROW(2, 0, 1, 0, 22 , 21 , 0 , 0 , 0 , 0 ), // {sreg, m16|mem} ROW(2, 1, 0, 0, 6 , 23 , 0 , 0 , 0 , 0 ), // {r32, creg|dreg} ROW(2, 1, 0, 0, 23 , 6 , 0 , 0 , 0 , 0 ), // {creg|dreg, r32} - ROW(2, 1, 1, 0, 9 , 10 , 0 , 0 , 0 , 0 ), // #16 {r8lo|r8hi|m8, i8|u8} + ROW(2, 1, 1, 0, 9 , 10 , 0 , 0 , 0 , 0 ), // #20 {r8lo|r8hi|m8, i8|u8} ROW(2, 1, 1, 0, 11 , 12 , 0 , 0 , 0 , 0 ), // {r16|m16, i16|u16} ROW(2, 1, 1, 0, 13 , 14 , 0 , 0 , 0 , 0 ), // {r32|m32, i32|u32} - ROW(2, 0, 1, 0, 15 , 24 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, i32|r64} - ROW(2, 1, 1, 0, 25 , 26 , 0 , 0 , 0 , 0 ), // {r16|m16|r32|m32|r64|m64|mem, i8} - ROW(2, 1, 1, 0, 1 , 2 , 0 , 0 , 0 , 0 ), // {r8lo|r8hi|m8|mem, r8lo|r8hi} + ROW(2, 0, 1, 0, 15 , 24 , 0 , 0 , 0 , 0 ), // {r64|m64, i32|i8} + ROW(2, 1, 1, 0, 25 , 26 , 0 , 0 , 0 , 0 ), // {r16|m16|r32|m32, i8} + ROW(2, 1, 1, 0, 1 , 2 , 0 , 0 , 0 , 0 ), // #25 {r8lo|r8hi|m8|mem, r8lo|r8hi} ROW(2, 1, 1, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // {r16|m16|mem, r16} - ROW(2, 1, 1, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // #23 {r32|m32|mem, r32} + ROW(2, 1, 1, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // #27 {r32|m32|mem, r32} + ROW(2, 0, 1, 0, 29 , 8 , 0 , 0 , 0 , 0 ), // #28 {r64|m64|mem, r64} ROW(2, 1, 1, 0, 2 , 18 , 0 , 0 , 0 , 0 ), // {r8lo|r8hi, m8|mem} ROW(2, 1, 1, 0, 4 , 21 , 0 , 0 , 0 , 0 ), // {r16, m16|mem} - ROW(2, 1, 1, 0, 6 , 29 , 0 , 0 , 0 , 0 ), // {r32, m32|mem} - ROW(2, 0, 1, 0, 8 , 30 , 0 , 0 , 0 , 0 ), // {r64, m64|mem} - ROW(2, 1, 1, 0, 31 , 10 , 0 , 0 , 0 , 0 ), // #28 {r8lo|r8hi|m8|r16|m16|r32|m32|r64|m64|mem, i8|u8} + ROW(2, 1, 1, 0, 6 , 30 , 0 , 0 , 0 , 0 ), // {r32, m32|mem} + ROW(2, 0, 1, 0, 8 , 31 , 0 , 0 , 0 , 0 ), // {r64, m64|mem} + ROW(2, 1, 1, 0, 32 , 10 , 0 , 0 , 0 , 0 ), // #33 {r8lo|r8hi|m8|r16|m16|r32|m32, i8|u8} ROW(2, 1, 1, 0, 11 , 12 , 0 , 0 , 0 , 0 ), // {r16|m16, i16|u16} ROW(2, 1, 1, 0, 13 , 14 , 0 , 0 , 0 , 0 ), // {r32|m32, i32|u32} - ROW(2, 0, 1, 0, 8 , 32 , 0 , 0 , 0 , 0 ), // {r64, u32|i32|r64|m64|mem} - ROW(2, 0, 1, 0, 30 , 24 , 0 , 0 , 0 , 0 ), // {m64|mem, i32|r64} + ROW(2, 0, 1, 0, 8 , 33 , 0 , 0 , 0 , 0 ), // {r64, u32|i32|i8|u8|r64|m64|mem} + ROW(2, 0, 1, 0, 34 , 35 , 0 , 0 , 0 , 0 ), // {m64, i32|i8|u8} ROW(2, 1, 1, 0, 1 , 2 , 0 , 0 , 0 , 0 ), // {r8lo|r8hi|m8|mem, r8lo|r8hi} ROW(2, 1, 1, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // {r16|m16|mem, r16} ROW(2, 1, 1, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // {r32|m32|mem, r32} + ROW(2, 0, 1, 0, 31 , 8 , 0 , 0 , 0 , 0 ), // {m64|mem, r64} ROW(2, 1, 1, 0, 2 , 18 , 0 , 0 , 0 , 0 ), // {r8lo|r8hi, m8|mem} ROW(2, 1, 1, 0, 4 , 21 , 0 , 0 , 0 , 0 ), // {r16, m16|mem} - ROW(2, 1, 1, 0, 6 , 29 , 0 , 0 , 0 , 0 ), // {r32, m32|mem} - ROW(2, 1, 1, 1, 33 , 1 , 0 , 0 , 0 , 0 ), // #39 {<ax>, r8lo|r8hi|m8|mem} - ROW(3, 1, 1, 2, 34 , 33 , 27 , 0 , 0 , 0 ), // {<dx>, <ax>, r16|m16|mem} - ROW(3, 1, 1, 2, 35 , 36 , 28 , 0 , 0 , 0 ), // {<edx>, <eax>, r32|m32|mem} - ROW(3, 0, 1, 2, 37 , 38 , 15 , 0 , 0 , 0 ), // {<rdx>, <rax>, r64|m64|mem} - ROW(2, 1, 1, 0, 4 , 39 , 0 , 0 , 0 , 0 ), // {r16, r16|m16|mem|i8|i16} - ROW(2, 1, 1, 0, 6 , 40 , 0 , 0 , 0 , 0 ), // {r32, r32|m32|mem|i8|i32} - ROW(2, 0, 1, 0, 8 , 41 , 0 , 0 , 0 , 0 ), // {r64, r64|m64|mem|i8|i32} + ROW(2, 1, 1, 0, 6 , 30 , 0 , 0 , 0 , 0 ), // {r32, m32|mem} + ROW(2, 1, 1, 1, 36 , 1 , 0 , 0 , 0 , 0 ), // #45 {<ax>, r8lo|r8hi|m8|mem} + ROW(3, 1, 1, 2, 37 , 36 , 27 , 0 , 0 , 0 ), // {<dx>, <ax>, r16|m16|mem} + ROW(3, 1, 1, 2, 38 , 39 , 28 , 0 , 0 , 0 ), // {<edx>, <eax>, r32|m32|mem} + ROW(3, 0, 1, 2, 40 , 41 , 29 , 0 , 0 , 0 ), // {<rdx>, <rax>, r64|m64|mem} + ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #49 {r16, r16|m16|mem} + ROW(2, 1, 1, 0, 6 , 28 , 0 , 0 , 0 , 0 ), // #50 {r32, r32|m32|mem} + ROW(2, 0, 1, 0, 8 , 29 , 0 , 0 , 0 , 0 ), // {r64, r64|m64|mem} ROW(3, 1, 1, 0, 4 , 27 , 42 , 0 , 0 , 0 ), // {r16, r16|m16|mem, i8|i16|u16} ROW(3, 1, 1, 0, 6 , 28 , 43 , 0 , 0 , 0 ), // {r32, r32|m32|mem, i8|i32|u32} - ROW(3, 0, 1, 0, 8 , 15 , 44 , 0 , 0 , 0 ), // {r64, r64|m64|mem, i8|i32} - ROW(2, 0, 1, 0, 8 , 45 , 0 , 0 , 0 , 0 ), // #49 {r64, i64|u64} - ROW(2, 0, 1, 0, 46 , 18 , 0 , 0 , 0 , 0 ), // {al, m8|mem} - ROW(2, 0, 1, 0, 47 , 21 , 0 , 0 , 0 , 0 ), // {ax, m16|mem} - ROW(2, 0, 1, 0, 48 , 29 , 0 , 0 , 0 , 0 ), // {eax, m32|mem} - ROW(2, 0, 1, 0, 49 , 30 , 0 , 0 , 0 , 0 ), // {rax, m64|mem} - ROW(2, 0, 1, 0, 18 , 46 , 0 , 0 , 0 , 0 ), // {m8|mem, al} - ROW(2, 0, 1, 0, 21 , 47 , 0 , 0 , 0 , 0 ), // {m16|mem, ax} - ROW(2, 0, 1, 0, 29 , 48 , 0 , 0 , 0 , 0 ), // {m32|mem, eax} - ROW(2, 0, 1, 0, 30 , 49 , 0 , 0 , 0 , 0 ), // {m64|mem, rax} - ROW(2, 1, 1, 0, 1 , 2 , 0 , 0 , 0 , 0 ), // #58 {r8lo|r8hi|m8|mem, r8lo|r8hi} - ROW(2, 1, 1, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // {r16|m16|mem, r16} - ROW(2, 1, 1, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // {r32|m32|mem, r32} - ROW(2, 0, 1, 0, 15 , 8 , 0 , 0 , 0 , 0 ), // #61 {r64|m64|mem, r64} - ROW(2, 1, 1, 0, 2 , 18 , 0 , 0 , 0 , 0 ), // {r8lo|r8hi, m8|mem} - ROW(2, 1, 1, 0, 4 , 21 , 0 , 0 , 0 , 0 ), // {r16, m16|mem} - ROW(2, 1, 1, 0, 6 , 29 , 0 , 0 , 0 , 0 ), // {r32, m32|mem} - ROW(2, 0, 1, 0, 8 , 30 , 0 , 0 , 0 , 0 ), // {r64, m64|mem} - ROW(2, 1, 1, 0, 9 , 10 , 0 , 0 , 0 , 0 ), // #66 {r8lo|r8hi|m8, i8|u8} + ROW(3, 0, 1, 0, 8 , 29 , 24 , 0 , 0 , 0 ), // {r64, r64|m64|mem, i8|i32} + ROW(2, 0, 1, 0, 8 , 44 , 0 , 0 , 0 , 0 ), // #55 {r64, i64|u64} + ROW(2, 1, 1, 0, 45 , 18 , 0 , 0 , 0 , 0 ), // {al, m8|mem} + ROW(2, 1, 1, 0, 46 , 21 , 0 , 0 , 0 , 0 ), // {ax, m16|mem} + ROW(2, 1, 1, 0, 47 , 30 , 0 , 0 , 0 , 0 ), // {eax, m32|mem} + ROW(2, 0, 1, 0, 48 , 31 , 0 , 0 , 0 , 0 ), // {rax, m64|mem} + ROW(2, 1, 1, 0, 18 , 45 , 0 , 0 , 0 , 0 ), // {m8|mem, al} + ROW(2, 1, 1, 0, 21 , 46 , 0 , 0 , 0 , 0 ), // {m16|mem, ax} + ROW(2, 1, 1, 0, 30 , 47 , 0 , 0 , 0 , 0 ), // {m32|mem, eax} + ROW(2, 0, 1, 0, 31 , 48 , 0 , 0 , 0 , 0 ), // {m64|mem, rax} + ROW(2, 1, 1, 0, 9 , 10 , 0 , 0 , 0 , 0 ), // #64 {r8lo|r8hi|m8, i8|u8} ROW(2, 1, 1, 0, 11 , 12 , 0 , 0 , 0 , 0 ), // {r16|m16, i16|u16} ROW(2, 1, 1, 0, 13 , 14 , 0 , 0 , 0 , 0 ), // {r32|m32, i32|u32} - ROW(2, 0, 1, 0, 15 , 24 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, i32|r64} + ROW(2, 0, 1, 0, 15 , 16 , 0 , 0 , 0 , 0 ), // {r64|m64, i32} ROW(2, 1, 1, 0, 1 , 2 , 0 , 0 , 0 , 0 ), // {r8lo|r8hi|m8|mem, r8lo|r8hi} ROW(2, 1, 1, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // {r16|m16|mem, r16} ROW(2, 1, 1, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // {r32|m32|mem, r32} - ROW(2, 1, 1, 0, 4 , 21 , 0 , 0 , 0 , 0 ), // #73 {r16, m16|mem} - ROW(2, 1, 1, 0, 6 , 29 , 0 , 0 , 0 , 0 ), // {r32, m32|mem} - ROW(2, 0, 1, 0, 8 , 30 , 0 , 0 , 0 , 0 ), // {r64, m64|mem} + ROW(2, 0, 1, 0, 29 , 8 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, r64} + ROW(2, 1, 1, 0, 49 , 50 , 0 , 0 , 0 , 0 ), // #72 {xmm, xmm|m128|mem} + ROW(2, 1, 1, 0, 51 , 49 , 0 , 0 , 0 , 0 ), // #73 {m128|mem, xmm} + ROW(2, 1, 1, 0, 52 , 53 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} + ROW(2, 1, 1, 0, 54 , 52 , 0 , 0 , 0 , 0 ), // {m256|mem, ymm} + ROW(2, 1, 1, 0, 51 , 49 , 0 , 0 , 0 , 0 ), // {m128|mem, xmm} + ROW(2, 1, 1, 0, 54 , 52 , 0 , 0 , 0 , 0 ), // {m256|mem, ymm} + ROW(2, 1, 1, 0, 55 , 56 , 0 , 0 , 0 , 0 ), // #78 {zmm, zmm|m512|mem} + ROW(2, 1, 1, 0, 57 , 55 , 0 , 0 , 0 , 0 ), // {m512|mem, zmm} + ROW(2, 1, 1, 0, 31 , 49 , 0 , 0 , 0 , 0 ), // #80 {m64|mem, xmm} + ROW(2, 1, 1, 0, 49 , 31 , 0 , 0 , 0 , 0 ), // {xmm, m64|mem} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // #82 {xmm, xmm, xmm} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(2, 1, 1, 0, 31 , 49 , 0 , 0 , 0 , 0 ), // {m64|mem, xmm} + ROW(2, 1, 1, 0, 49 , 31 , 0 , 0 , 0 , 0 ), // {xmm, m64|mem} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(2, 1, 1, 0, 30 , 49 , 0 , 0 , 0 , 0 ), // #88 {m32|mem, xmm} + ROW(2, 1, 1, 0, 49 , 30 , 0 , 0 , 0 , 0 ), // {xmm, m32|mem} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(2, 1, 1, 0, 30 , 49 , 0 , 0 , 0 , 0 ), // {m32|mem, xmm} + ROW(2, 1, 1, 0, 49 , 30 , 0 , 0 , 0 , 0 ), // {xmm, m32|mem} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(3, 1, 1, 0, 49 , 49 , 58 , 0 , 0 , 0 ), // #96 {xmm, xmm, xmm|m128|mem|i8|u8} + ROW(3, 1, 1, 0, 49 , 51 , 10 , 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8} + ROW(3, 1, 1, 0, 52 , 52 , 59 , 0 , 0 , 0 ), // {ymm, ymm, ymm|m256|mem|i8|u8} + ROW(3, 1, 1, 0, 52 , 54 , 10 , 0 , 0 , 0 ), // {ymm, m256|mem, i8|u8} + ROW(3, 1, 1, 0, 55 , 55 , 60 , 0 , 0 , 0 ), // {zmm, zmm, zmm|m512|mem|i8|u8} + ROW(3, 1, 1, 0, 49 , 51 , 10 , 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8} + ROW(3, 1, 1, 0, 52 , 54 , 10 , 0 , 0 , 0 ), // {ymm, m256|mem, i8|u8} + ROW(3, 1, 1, 0, 55 , 57 , 10 , 0 , 0 , 0 ), // {zmm, m512|mem, i8|u8} + ROW(2, 1, 1, 0, 4 , 21 , 0 , 0 , 0 , 0 ), // #104 {r16, m16|mem} + ROW(2, 1, 1, 0, 6 , 30 , 0 , 0 , 0 , 0 ), // {r32, m32|mem} + ROW(2, 0, 1, 0, 8 , 31 , 0 , 0 , 0 , 0 ), // {r64, m64|mem} ROW(2, 1, 1, 0, 21 , 4 , 0 , 0 , 0 , 0 ), // {m16|mem, r16} - ROW(2, 1, 1, 0, 29 , 6 , 0 , 0 , 0 , 0 ), // #77 {m32|mem, r32} - ROW(2, 0, 1, 0, 30 , 8 , 0 , 0 , 0 , 0 ), // {m64|mem, r64} - ROW(2, 1, 1, 0, 50 , 51 , 0 , 0 , 0 , 0 ), // #79 {xmm, xmm|m128|mem} - ROW(2, 1, 1, 0, 52 , 50 , 0 , 0 , 0 , 0 ), // #80 {m128|mem, xmm} - ROW(2, 1, 1, 0, 53 , 54 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} - ROW(2, 1, 1, 0, 55 , 53 , 0 , 0 , 0 , 0 ), // {m256|mem, ymm} - ROW(2, 1, 1, 0, 56 , 57 , 0 , 0 , 0 , 0 ), // #83 {zmm, zmm|m512|mem} - ROW(2, 1, 1, 0, 58 , 56 , 0 , 0 , 0 , 0 ), // {m512|mem, zmm} - ROW(3, 1, 1, 0, 50 , 50 , 59 , 0 , 0 , 0 ), // #85 {xmm, xmm, xmm|m128|mem|i8|u8} - ROW(3, 1, 1, 0, 50 , 52 , 10 , 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8} - ROW(3, 1, 1, 0, 53 , 53 , 60 , 0 , 0 , 0 ), // {ymm, ymm, ymm|m256|mem|i8|u8} - ROW(3, 1, 1, 0, 53 , 55 , 10 , 0 , 0 , 0 ), // {ymm, m256|mem, i8|u8} - ROW(3, 1, 1, 0, 56 , 56 , 61 , 0 , 0 , 0 ), // {zmm, zmm, zmm|m512|mem|i8|u8} - ROW(3, 1, 1, 0, 56 , 58 , 10 , 0 , 0 , 0 ), // {zmm, m512|mem, i8|u8} - ROW(3, 1, 1, 0, 50 , 50 , 59 , 0 , 0 , 0 ), // #91 {xmm, xmm, i8|u8|xmm|m128|mem} - ROW(3, 1, 1, 0, 53 , 53 , 59 , 0 , 0 , 0 ), // {ymm, ymm, i8|u8|xmm|m128|mem} - ROW(3, 1, 1, 0, 50 , 52 , 10 , 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8} - ROW(3, 1, 1, 0, 53 , 55 , 10 , 0 , 0 , 0 ), // {ymm, m256|mem, i8|u8} - ROW(3, 1, 1, 0, 56 , 56 , 59 , 0 , 0 , 0 ), // {zmm, zmm, xmm|m128|mem|i8|u8} - ROW(3, 1, 1, 0, 56 , 58 , 10 , 0 , 0 , 0 ), // {zmm, m512|mem, i8|u8} - ROW(3, 1, 1, 0, 50 , 50 , 59 , 0 , 0 , 0 ), // #97 {xmm, xmm, xmm|m128|mem|i8|u8} - ROW(3, 1, 1, 0, 50 , 52 , 10 , 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8} - ROW(3, 1, 1, 0, 53 , 53 , 59 , 0 , 0 , 0 ), // {ymm, ymm, xmm|m128|mem|i8|u8} - ROW(3, 1, 1, 0, 53 , 55 , 10 , 0 , 0 , 0 ), // {ymm, m256|mem, i8|u8} - ROW(3, 1, 1, 0, 56 , 56 , 59 , 0 , 0 , 0 ), // {zmm, zmm, xmm|m128|mem|i8|u8} - ROW(3, 1, 1, 0, 56 , 58 , 10 , 0 , 0 , 0 ), // {zmm, m512|mem, i8|u8} - ROW(2, 1, 1, 0, 62 , 63 , 0 , 0 , 0 , 0 ), // #103 {mm, mm|m64|mem|r64} - ROW(2, 1, 1, 0, 15 , 64 , 0 , 0 , 0 , 0 ), // {m64|mem|r64, mm|xmm} - ROW(2, 0, 1, 0, 50 , 15 , 0 , 0 , 0 , 0 ), // {xmm, r64|m64|mem} - ROW(2, 1, 1, 0, 50 , 65 , 0 , 0 , 0 , 0 ), // #106 {xmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // #107 {m64|mem, xmm} - ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #108 {} - ROW(1, 1, 1, 0, 66 , 0 , 0 , 0 , 0 , 0 ), // {r16|m16|r32|m32|r64|m64} + ROW(2, 1, 1, 0, 30 , 6 , 0 , 0 , 0 , 0 ), // #108 {m32|mem, r32} + ROW(2, 0, 1, 0, 31 , 8 , 0 , 0 , 0 , 0 ), // {m64|mem, r64} + ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #110 {} + ROW(1, 1, 1, 0, 25 , 0 , 0 , 0 , 0 , 0 ), // {r16|m16|r32|m32} + ROW(1, 0, 1, 0, 15 , 0 , 0 , 0 , 0 , 0 ), // {r64|m64} ROW(2, 1, 1, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // {r16|m16|mem, r16} ROW(2, 1, 1, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // {r32|m32|mem, r32} - ROW(2, 1, 1, 0, 15 , 8 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, r64} - ROW(3, 1, 1, 0, 50 , 67 , 50 , 0 , 0 , 0 ), // #113 {xmm, vm32x, xmm} - ROW(3, 1, 1, 0, 53 , 68 , 53 , 0 , 0 , 0 ), // {ymm, vm32y, ymm} - ROW(2, 1, 1, 0, 50 , 67 , 0 , 0 , 0 , 0 ), // {xmm, vm32x} - ROW(2, 1, 1, 0, 53 , 68 , 0 , 0 , 0 , 0 ), // {ymm, vm32y} - ROW(2, 1, 1, 0, 56 , 69 , 0 , 0 , 0 , 0 ), // {zmm, vm32z} - ROW(3, 1, 1, 0, 50 , 70 , 50 , 0 , 0 , 0 ), // #118 {xmm, vm64x, xmm} - ROW(3, 1, 1, 0, 53 , 71 , 53 , 0 , 0 , 0 ), // {ymm, vm64y, ymm} - ROW(2, 1, 1, 0, 50 , 70 , 0 , 0 , 0 , 0 ), // {xmm, vm64x} - ROW(2, 1, 1, 0, 53 , 71 , 0 , 0 , 0 , 0 ), // {ymm, vm64y} - ROW(2, 1, 1, 0, 56 , 72 , 0 , 0 , 0 , 0 ), // {zmm, vm64z} - ROW(2, 1, 1, 0, 25 , 10 , 0 , 0 , 0 , 0 ), // #123 {r16|m16|r32|m32|r64|m64|mem, i8|u8} + ROW(2, 0, 1, 0, 29 , 8 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, r64} + ROW(2, 1, 1, 0, 49 , 50 , 0 , 0 , 0 , 0 ), // #116 {xmm, xmm|m128|mem} + ROW(2, 1, 1, 0, 51 , 49 , 0 , 0 , 0 , 0 ), // {m128|mem, xmm} + ROW(2, 1, 1, 0, 52 , 53 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} + ROW(2, 1, 1, 0, 54 , 52 , 0 , 0 , 0 , 0 ), // {m256|mem, ymm} + ROW(2, 1, 1, 0, 55 , 56 , 0 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem} + ROW(2, 1, 1, 0, 57 , 55 , 0 , 0 , 0 , 0 ), // {m512|mem, zmm} + ROW(3, 1, 1, 0, 49 , 49 , 58 , 0 , 0 , 0 ), // #122 {xmm, xmm, i8|u8|xmm|m128|mem} + ROW(3, 1, 1, 0, 52 , 52 , 58 , 0 , 0 , 0 ), // {ymm, ymm, i8|u8|xmm|m128|mem} + ROW(3, 1, 1, 0, 49 , 51 , 10 , 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8} + ROW(3, 1, 1, 0, 52 , 54 , 10 , 0 , 0 , 0 ), // {ymm, m256|mem, i8|u8} + ROW(3, 1, 1, 0, 55 , 55 , 58 , 0 , 0 , 0 ), // {zmm, zmm, xmm|m128|mem|i8|u8} + ROW(3, 1, 1, 0, 55 , 57 , 10 , 0 , 0 , 0 ), // {zmm, m512|mem, i8|u8} + ROW(3, 1, 1, 0, 49 , 49 , 58 , 0 , 0 , 0 ), // #128 {xmm, xmm, xmm|m128|mem|i8|u8} + ROW(3, 1, 1, 0, 49 , 51 , 10 , 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8} + ROW(3, 1, 1, 0, 52 , 52 , 58 , 0 , 0 , 0 ), // {ymm, ymm, xmm|m128|mem|i8|u8} + ROW(3, 1, 1, 0, 52 , 54 , 10 , 0 , 0 , 0 ), // {ymm, m256|mem, i8|u8} + ROW(3, 1, 1, 0, 55 , 55 , 58 , 0 , 0 , 0 ), // {zmm, zmm, xmm|m128|mem|i8|u8} + ROW(3, 1, 1, 0, 55 , 57 , 10 , 0 , 0 , 0 ), // {zmm, m512|mem, i8|u8} + ROW(2, 1, 1, 0, 25 , 10 , 0 , 0 , 0 , 0 ), // #134 {r16|m16|r32|m32, i8|u8} + ROW(2, 0, 1, 0, 15 , 10 , 0 , 0 , 0 , 0 ), // {r64|m64, i8|u8} ROW(2, 1, 1, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // {r16|m16|mem, r16} ROW(2, 1, 1, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // {r32|m32|mem, r32} - ROW(2, 0, 1, 0, 15 , 8 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, r64} - ROW(2, 1, 1, 2, 73 , 74 , 0 , 0 , 0 , 0 ), // #127 {<ds:[m8|memBase|zsi]>, <es:[m8|memBase|zdi]>} - ROW(2, 1, 1, 2, 75 , 76 , 0 , 0 , 0 , 0 ), // {<ds:[m16|memBase|zsi]>, <es:[m16|memBase|zdi]>} - ROW(2, 1, 1, 2, 77 , 78 , 0 , 0 , 0 , 0 ), // {<ds:[m32|memBase|zsi]>, <es:[m32|memBase|zdi]>} - ROW(2, 0, 1, 2, 79 , 80 , 0 , 0 , 0 , 0 ), // {<ds:[m64|memBase|zsi]>, <es:[m64|memBase|zdi]>} - ROW(3, 1, 1, 1, 1 , 2 , 81 , 0 , 0 , 0 ), // #131 {r8lo|r8hi|m8|mem, r8lo|r8hi, <al>} - ROW(3, 1, 1, 1, 27 , 4 , 33 , 0 , 0 , 0 ), // {r16|m16|mem, r16, <ax>} - ROW(3, 1, 1, 1, 28 , 6 , 36 , 0 , 0 , 0 ), // {r32|m32|mem, r32, <eax>} - ROW(3, 0, 1, 1, 15 , 8 , 38 , 0 , 0 , 0 ), // {r64|m64|mem, r64, <rax>} - ROW(2, 1, 1, 2, 81 , 82 , 0 , 0 , 0 , 0 ), // #135 {<al>, <ds:[m8|memBase|zsi|mem]>} - ROW(2, 1, 1, 2, 33 , 83 , 0 , 0 , 0 , 0 ), // {<ax>, <ds:[m16|memBase|zsi|mem]>} - ROW(2, 1, 1, 2, 36 , 84 , 0 , 0 , 0 , 0 ), // {<eax>, <ds:[m32|memBase|zsi|mem]>} - ROW(2, 0, 1, 2, 38 , 85 , 0 , 0 , 0 , 0 ), // {<rax>, <ds:[m64|memBase|zsi|mem]>} - ROW(2, 1, 1, 2, 74 , 73 , 0 , 0 , 0 , 0 ), // #139 {<es:[m8|memBase|zdi]>, <ds:[m8|memBase|zsi]>} - ROW(2, 1, 1, 2, 76 , 75 , 0 , 0 , 0 , 0 ), // {<es:[m16|memBase|zdi]>, <ds:[m16|memBase|zsi]>} - ROW(2, 1, 1, 2, 78 , 77 , 0 , 0 , 0 , 0 ), // {<es:[m32|memBase|zdi]>, <ds:[m32|memBase|zsi]>} - ROW(2, 0, 1, 2, 80 , 79 , 0 , 0 , 0 , 0 ), // {<es:[m64|memBase|zdi]>, <ds:[m64|memBase|zsi]>} - ROW(1, 1, 1, 0, 86 , 0 , 0 , 0 , 0 , 0 ), // #143 {r16|m16|r64|m64} + ROW(2, 0, 1, 0, 29 , 8 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, r64} + ROW(2, 1, 1, 0, 61 , 62 , 0 , 0 , 0 , 0 ), // #139 {mm, mm|m64|mem} + ROW(2, 0, 1, 0, 63 , 29 , 0 , 0 , 0 , 0 ), // {mm|xmm, r64|m64|mem} + ROW(2, 1, 1, 0, 31 , 63 , 0 , 0 , 0 , 0 ), // {m64|mem, mm|xmm} + ROW(2, 0, 1, 0, 29 , 63 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, mm|xmm} + ROW(2, 1, 1, 0, 49 , 64 , 0 , 0 , 0 , 0 ), // #143 {xmm, xmm|m64|mem} + ROW(1, 1, 1, 0, 11 , 0 , 0 , 0 , 0 , 0 ), // #144 {r16|m16} ROW(1, 1, 0, 0, 13 , 0 , 0 , 0 , 0 , 0 ), // {r32|m32} - ROW(1, 1, 0, 0, 87 , 0 , 0 , 0 , 0 , 0 ), // {ds|es|ss} - ROW(1, 1, 1, 0, 88 , 0 , 0 , 0 , 0 , 0 ), // {fs|gs} - ROW(1, 1, 1, 0, 89 , 0 , 0 , 0 , 0 , 0 ), // #147 {r16|m16|r64|m64|i8|i16|i32} - ROW(1, 1, 0, 0, 90 , 0 , 0 , 0 , 0 , 0 ), // {r32|m32|i32|u32} - ROW(1, 1, 0, 0, 91 , 0 , 0 , 0 , 0 , 0 ), // {cs|ss|ds|es} - ROW(1, 1, 1, 0, 88 , 0 , 0 , 0 , 0 , 0 ), // {fs|gs} - ROW(2, 1, 1, 2, 81 , 92 , 0 , 0 , 0 , 0 ), // #151 {<al>, <es:[m8|memBase|zdi|mem]>} - ROW(2, 1, 1, 2, 33 , 93 , 0 , 0 , 0 , 0 ), // {<ax>, <es:[m16|memBase|zdi|mem]>} - ROW(2, 1, 1, 2, 36 , 94 , 0 , 0 , 0 , 0 ), // {<eax>, <es:[m32|memBase|zdi|mem]>} - ROW(2, 0, 1, 2, 38 , 95 , 0 , 0 , 0 , 0 ), // {<rax>, <es:[m64|memBase|zdi|mem]>} - ROW(2, 1, 1, 2, 92 , 81 , 0 , 0 , 0 , 0 ), // #155 {<es:[m8|memBase|zdi|mem]>, <al>} - ROW(2, 1, 1, 2, 93 , 33 , 0 , 0 , 0 , 0 ), // {<es:[m16|memBase|zdi|mem]>, <ax>} - ROW(2, 1, 1, 2, 94 , 36 , 0 , 0 , 0 , 0 ), // {<es:[m32|memBase|zdi|mem]>, <eax>} - ROW(2, 0, 1, 2, 95 , 38 , 0 , 0 , 0 , 0 ), // {<es:[m64|memBase|zdi|mem]>, <rax>} - ROW(4, 1, 1, 0, 50 , 50 , 50 , 51 , 0 , 0 ), // #159 {xmm, xmm, xmm, xmm|m128|mem} - ROW(4, 1, 1, 0, 50 , 50 , 52 , 50 , 0 , 0 ), // {xmm, xmm, m128|mem, xmm} - ROW(4, 1, 1, 0, 53 , 53 , 53 , 54 , 0 , 0 ), // {ymm, ymm, ymm, ymm|m256|mem} - ROW(4, 1, 1, 0, 53 , 53 , 55 , 53 , 0 , 0 ), // {ymm, ymm, m256|mem, ymm} - ROW(3, 1, 1, 0, 50 , 67 , 50 , 0 , 0 , 0 ), // #163 {xmm, vm32x, xmm} - ROW(3, 1, 1, 0, 53 , 67 , 53 , 0 , 0 , 0 ), // {ymm, vm32x, ymm} - ROW(2, 1, 1, 0, 96 , 67 , 0 , 0 , 0 , 0 ), // {xmm|ymm, vm32x} - ROW(2, 1, 1, 0, 56 , 68 , 0 , 0 , 0 , 0 ), // {zmm, vm32y} - ROW(3, 1, 1, 0, 52 , 50 , 50 , 0 , 0 , 0 ), // #167 {m128|mem, xmm, xmm} - ROW(3, 1, 1, 0, 55 , 53 , 53 , 0 , 0 , 0 ), // {m256|mem, ymm, ymm} - ROW(3, 1, 1, 0, 50 , 50 , 52 , 0 , 0 , 0 ), // {xmm, xmm, m128|mem} - ROW(3, 1, 1, 0, 53 , 53 , 55 , 0 , 0 , 0 ), // {ymm, ymm, m256|mem} - ROW(5, 1, 1, 0, 50 , 50 , 51 , 50 , 97 , 0 ), // #171 {xmm, xmm, xmm|m128|mem, xmm, i4|u4} - ROW(5, 1, 1, 0, 50 , 50 , 50 , 52 , 97 , 0 ), // {xmm, xmm, xmm, m128|mem, i4|u4} - ROW(5, 1, 1, 0, 53 , 53 , 54 , 53 , 97 , 0 ), // {ymm, ymm, ymm|m256|mem, ymm, i4|u4} - ROW(5, 1, 1, 0, 53 , 53 , 53 , 55 , 97 , 0 ), // {ymm, ymm, ymm, m256|mem, i4|u4} - ROW(3, 1, 1, 0, 53 , 54 , 10 , 0 , 0 , 0 ), // #175 {ymm, ymm|m256|mem, i8|u8} - ROW(3, 1, 1, 0, 53 , 53 , 54 , 0 , 0 , 0 ), // {ymm, ymm, ymm|m256|mem} - ROW(3, 1, 1, 0, 56 , 56 , 61 , 0 , 0 , 0 ), // {zmm, zmm, zmm|m512|mem|i8|u8} - ROW(3, 1, 1, 0, 56 , 58 , 10 , 0 , 0 , 0 ), // {zmm, m512|mem, i8|u8} - ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #179 {r16, r16|m16|mem} - ROW(2, 1, 1, 0, 6 , 28 , 0 , 0 , 0 , 0 ), // #180 {r32, r32|m32|mem} - ROW(2, 0, 1, 0, 8 , 15 , 0 , 0 , 0 , 0 ), // {r64, r64|m64|mem} - ROW(1, 1, 1, 0, 98 , 0 , 0 , 0 , 0 , 0 ), // #182 {m32|m64} - ROW(2, 1, 1, 0, 99 , 100, 0 , 0 , 0 , 0 ), // {st0, st} - ROW(2, 1, 1, 0, 100, 99 , 0 , 0 , 0 , 0 ), // {st, st0} - ROW(2, 1, 1, 0, 4 , 29 , 0 , 0 , 0 , 0 ), // #185 {r16, m32|mem} - ROW(2, 1, 1, 0, 6 , 101, 0 , 0 , 0 , 0 ), // {r32, m48|mem} - ROW(2, 0, 1, 0, 8 , 102, 0 , 0 , 0 , 0 ), // {r64, m80|mem} - ROW(3, 1, 1, 0, 27 , 4 , 103, 0 , 0 , 0 ), // #188 {r16|m16|mem, r16, cl|i8|u8} - ROW(3, 1, 1, 0, 28 , 6 , 103, 0 , 0 , 0 ), // {r32|m32|mem, r32, cl|i8|u8} - ROW(3, 0, 1, 0, 15 , 8 , 103, 0 , 0 , 0 ), // {r64|m64|mem, r64, cl|i8|u8} - ROW(3, 1, 1, 0, 50 , 50 , 51 , 0 , 0 , 0 ), // #191 {xmm, xmm, xmm|m128|mem} - ROW(3, 1, 1, 0, 53 , 53 , 54 , 0 , 0 , 0 ), // #192 {ymm, ymm, ymm|m256|mem} - ROW(3, 1, 1, 0, 56 , 56 , 57 , 0 , 0 , 0 ), // {zmm, zmm, zmm|m512|mem} - ROW(4, 1, 1, 0, 50 , 50 , 51 , 10 , 0 , 0 ), // #194 {xmm, xmm, xmm|m128|mem, i8|u8} - ROW(4, 1, 1, 0, 53 , 53 , 54 , 10 , 0 , 0 ), // #195 {ymm, ymm, ymm|m256|mem, i8|u8} - ROW(4, 1, 1, 0, 56 , 56 , 57 , 10 , 0 , 0 ), // {zmm, zmm, zmm|m512|mem, i8|u8} - ROW(4, 1, 1, 0, 104, 50 , 51 , 10 , 0 , 0 ), // #197 {xmm|k, xmm, xmm|m128|mem, i8|u8} - ROW(4, 1, 1, 0, 105, 53 , 54 , 10 , 0 , 0 ), // {ymm|k, ymm, ymm|m256|mem, i8|u8} - ROW(4, 1, 1, 0, 106, 56 , 57 , 10 , 0 , 0 ), // {k, zmm, zmm|m512|mem, i8|u8} - ROW(4, 1, 1, 0, 106, 50 , 51 , 10 , 0 , 0 ), // #200 {k, xmm, xmm|m128|mem, i8|u8} - ROW(4, 1, 1, 0, 106, 53 , 54 , 10 , 0 , 0 ), // {k, ymm, ymm|m256|mem, i8|u8} - ROW(4, 1, 1, 0, 106, 56 , 57 , 10 , 0 , 0 ), // {k, zmm, zmm|m512|mem, i8|u8} - ROW(2, 1, 1, 0, 51 , 50 , 0 , 0 , 0 , 0 ), // #203 {xmm|m128|mem, xmm} - ROW(2, 1, 1, 0, 54 , 53 , 0 , 0 , 0 , 0 ), // {ymm|m256|mem, ymm} - ROW(2, 1, 1, 0, 57 , 56 , 0 , 0 , 0 , 0 ), // {zmm|m512|mem, zmm} - ROW(2, 1, 1, 0, 50 , 65 , 0 , 0 , 0 , 0 ), // #206 {xmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 53 , 51 , 0 , 0 , 0 , 0 ), // {ymm, xmm|m128|mem} - ROW(2, 1, 1, 0, 56 , 54 , 0 , 0 , 0 , 0 ), // {zmm, ymm|m256|mem} - ROW(2, 1, 1, 0, 50 , 51 , 0 , 0 , 0 , 0 ), // #209 {xmm, xmm|m128|mem} - ROW(2, 1, 1, 0, 53 , 54 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} - ROW(2, 1, 1, 0, 56 , 57 , 0 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem} - ROW(2, 1, 1, 0, 50 , 107, 0 , 0 , 0 , 0 ), // #212 {xmm, xmm|m32|mem} - ROW(2, 1, 1, 0, 53 , 65 , 0 , 0 , 0 , 0 ), // {ymm, xmm|m64|mem} - ROW(2, 1, 1, 0, 56 , 51 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m128|mem} - ROW(3, 1, 1, 0, 65 , 50 , 10 , 0 , 0 , 0 ), // #215 {xmm|m64|mem, xmm, i8|u8} - ROW(3, 1, 1, 0, 51 , 53 , 10 , 0 , 0 , 0 ), // #216 {xmm|m128|mem, ymm, i8|u8} - ROW(3, 1, 1, 0, 54 , 56 , 10 , 0 , 0 , 0 ), // #217 {ymm|m256|mem, zmm, i8|u8} - ROW(3, 1, 1, 0, 50 , 108, 50 , 0 , 0 , 0 ), // #218 {xmm, vm64x|vm64y, xmm} - ROW(2, 1, 1, 0, 50 , 108, 0 , 0 , 0 , 0 ), // {xmm, vm64x|vm64y} - ROW(2, 1, 1, 0, 53 , 72 , 0 , 0 , 0 , 0 ), // {ymm, vm64z} - ROW(3, 1, 1, 0, 50 , 51 , 10 , 0 , 0 , 0 ), // #221 {xmm, xmm|m128|mem, i8|u8} - ROW(3, 1, 1, 0, 53 , 54 , 10 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem, i8|u8} - ROW(3, 1, 1, 0, 56 , 57 , 10 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem, i8|u8} - ROW(2, 1, 1, 0, 50 , 65 , 0 , 0 , 0 , 0 ), // #224 {xmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 53 , 54 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} - ROW(2, 1, 1, 0, 56 , 57 , 0 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem} - ROW(2, 1, 1, 0, 52 , 50 , 0 , 0 , 0 , 0 ), // #227 {m128|mem, xmm} - ROW(2, 1, 1, 0, 55 , 53 , 0 , 0 , 0 , 0 ), // {m256|mem, ymm} - ROW(2, 1, 1, 0, 58 , 56 , 0 , 0 , 0 , 0 ), // {m512|mem, zmm} - ROW(2, 1, 1, 0, 50 , 52 , 0 , 0 , 0 , 0 ), // #230 {xmm, m128|mem} - ROW(2, 1, 1, 0, 53 , 55 , 0 , 0 , 0 , 0 ), // {ymm, m256|mem} - ROW(2, 1, 1, 0, 56 , 58 , 0 , 0 , 0 , 0 ), // {zmm, m512|mem} - ROW(2, 0, 1, 0, 15 , 50 , 0 , 0 , 0 , 0 ), // #233 {r64|m64|mem, xmm} - ROW(2, 1, 1, 0, 50 , 109, 0 , 0 , 0 , 0 ), // {xmm, xmm|m64|mem|r64} - ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // {m64|mem, xmm} - ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // #236 {m64|mem, xmm} - ROW(2, 1, 1, 0, 50 , 30 , 0 , 0 , 0 , 0 ), // {xmm, m64|mem} - ROW(3, 1, 1, 0, 50 , 50 , 50 , 0 , 0 , 0 ), // #238 {xmm, xmm, xmm} - ROW(2, 1, 1, 0, 21 , 50 , 0 , 0 , 0 , 0 ), // #239 {m16|mem, xmm} - ROW(2, 1, 1, 0, 50 , 21 , 0 , 0 , 0 , 0 ), // {xmm, m16|mem} - ROW(3, 1, 1, 0, 50 , 50 , 50 , 0 , 0 , 0 ), // {xmm, xmm, xmm} - ROW(2, 1, 1, 0, 29 , 50 , 0 , 0 , 0 , 0 ), // #242 {m32|mem, xmm} - ROW(2, 1, 1, 0, 50 , 29 , 0 , 0 , 0 , 0 ), // {xmm, m32|mem} - ROW(3, 1, 1, 0, 50 , 50 , 50 , 0 , 0 , 0 ), // {xmm, xmm, xmm} - ROW(4, 1, 1, 0, 106, 106, 50 , 51 , 0 , 0 ), // #245 {k, k, xmm, xmm|m128|mem} - ROW(4, 1, 1, 0, 106, 106, 53 , 54 , 0 , 0 ), // {k, k, ymm, ymm|m256|mem} - ROW(4, 1, 1, 0, 106, 106, 56 , 57 , 0 , 0 ), // {k, k, zmm, zmm|m512|mem} - ROW(2, 1, 1, 0, 96 , 109, 0 , 0 , 0 , 0 ), // #248 {xmm|ymm, xmm|m64|mem|r64} - ROW(2, 0, 1, 0, 56 , 8 , 0 , 0 , 0 , 0 ), // {zmm, r64} - ROW(2, 1, 1, 0, 56 , 65 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m64|mem} - ROW(3, 1, 1, 0, 104, 50 , 51 , 0 , 0 , 0 ), // #251 {xmm|k, xmm, xmm|m128|mem} - ROW(3, 1, 1, 0, 105, 53 , 54 , 0 , 0 , 0 ), // {ymm|k, ymm, ymm|m256|mem} - ROW(3, 1, 1, 0, 106, 56 , 57 , 0 , 0 , 0 ), // {k, zmm, zmm|m512|mem} - ROW(2, 1, 1, 0, 107, 50 , 0 , 0 , 0 , 0 ), // #254 {xmm|m32|mem, xmm} - ROW(2, 1, 1, 0, 65 , 53 , 0 , 0 , 0 , 0 ), // {xmm|m64|mem, ymm} - ROW(2, 1, 1, 0, 51 , 56 , 0 , 0 , 0 , 0 ), // {xmm|m128|mem, zmm} - ROW(2, 1, 1, 0, 65 , 50 , 0 , 0 , 0 , 0 ), // #257 {xmm|m64|mem, xmm} - ROW(2, 1, 1, 0, 51 , 53 , 0 , 0 , 0 , 0 ), // {xmm|m128|mem, ymm} - ROW(2, 1, 1, 0, 54 , 56 , 0 , 0 , 0 , 0 ), // {ymm|m256|mem, zmm} - ROW(2, 1, 1, 0, 110, 50 , 0 , 0 , 0 , 0 ), // #260 {xmm|m16|mem, xmm} - ROW(2, 1, 1, 0, 107, 53 , 0 , 0 , 0 , 0 ), // {xmm|m32|mem, ymm} - ROW(2, 1, 1, 0, 65 , 56 , 0 , 0 , 0 , 0 ), // {xmm|m64|mem, zmm} - ROW(2, 1, 1, 0, 50 , 110, 0 , 0 , 0 , 0 ), // #263 {xmm, xmm|m16|mem} - ROW(2, 1, 1, 0, 53 , 107, 0 , 0 , 0 , 0 ), // {ymm, xmm|m32|mem} - ROW(2, 1, 1, 0, 56 , 65 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 67 , 50 , 0 , 0 , 0 , 0 ), // #266 {vm32x, xmm} - ROW(2, 1, 1, 0, 68 , 53 , 0 , 0 , 0 , 0 ), // {vm32y, ymm} - ROW(2, 1, 1, 0, 69 , 56 , 0 , 0 , 0 , 0 ), // {vm32z, zmm} - ROW(2, 1, 1, 0, 70 , 50 , 0 , 0 , 0 , 0 ), // #269 {vm64x, xmm} - ROW(2, 1, 1, 0, 71 , 53 , 0 , 0 , 0 , 0 ), // {vm64y, ymm} - ROW(2, 1, 1, 0, 72 , 56 , 0 , 0 , 0 , 0 ), // {vm64z, zmm} - ROW(3, 1, 1, 0, 106, 50 , 51 , 0 , 0 , 0 ), // #272 {k, xmm, xmm|m128|mem} - ROW(3, 1, 1, 0, 106, 53 , 54 , 0 , 0 , 0 ), // {k, ymm, ymm|m256|mem} - ROW(3, 1, 1, 0, 106, 56 , 57 , 0 , 0 , 0 ), // {k, zmm, zmm|m512|mem} - ROW(3, 1, 1, 0, 6 , 6 , 28 , 0 , 0 , 0 ), // #275 {r32, r32, r32|m32|mem} - ROW(3, 0, 1, 0, 8 , 8 , 15 , 0 , 0 , 0 ), // {r64, r64, r64|m64|mem} - ROW(3, 1, 1, 0, 6 , 28 , 6 , 0 , 0 , 0 ), // #277 {r32, r32|m32|mem, r32} - ROW(3, 0, 1, 0, 8 , 15 , 8 , 0 , 0 , 0 ), // {r64, r64|m64|mem, r64} - ROW(2, 1, 0, 0, 111, 28 , 0 , 0 , 0 , 0 ), // #279 {bnd, r32|m32|mem} - ROW(2, 0, 1, 0, 111, 15 , 0 , 0 , 0 , 0 ), // {bnd, r64|m64|mem} - ROW(2, 1, 1, 0, 111, 112, 0 , 0 , 0 , 0 ), // #281 {bnd, bnd|mem} - ROW(2, 1, 1, 0, 113, 111, 0 , 0 , 0 , 0 ), // {mem, bnd} - ROW(2, 1, 0, 0, 4 , 29 , 0 , 0 , 0 , 0 ), // #283 {r16, m32|mem} - ROW(2, 1, 0, 0, 6 , 30 , 0 , 0 , 0 , 0 ), // {r32, m64|mem} - ROW(1, 1, 0, 0, 114, 0 , 0 , 0 , 0 , 0 ), // #285 {rel16|r16|m16|r32|m32} - ROW(1, 1, 1, 0, 115, 0 , 0 , 0 , 0 , 0 ), // {rel32|r64|m64|mem} - ROW(2, 1, 1, 0, 6 , 116, 0 , 0 , 0 , 0 ), // #287 {r32, r8lo|r8hi|m8|r16|m16|r32|m32} - ROW(2, 0, 1, 0, 8 , 117, 0 , 0 , 0 , 0 ), // {r64, r8lo|r8hi|m8|r64|m64} - ROW(1, 1, 0, 0, 118, 0 , 0 , 0 , 0 , 0 ), // #289 {r16|r32} - ROW(1, 1, 1, 0, 31 , 0 , 0 , 0 , 0 , 0 ), // #290 {r8lo|r8hi|m8|r16|m16|r32|m32|r64|m64|mem} - ROW(2, 1, 0, 0, 119, 58 , 0 , 0 , 0 , 0 ), // #291 {es:[mem|m512|memBase], m512|mem} - ROW(2, 0, 1, 0, 119, 58 , 0 , 0 , 0 , 0 ), // {es:[mem|m512|memBase], m512|mem} - ROW(3, 1, 1, 0, 50 , 10 , 10 , 0 , 0 , 0 ), // #293 {xmm, i8|u8, i8|u8} - ROW(2, 1, 1, 0, 50 , 50 , 0 , 0 , 0 , 0 ), // #294 {xmm, xmm} - ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #295 {} - ROW(1, 1, 1, 0, 100, 0 , 0 , 0 , 0 , 0 ), // #296 {st} - ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #297 {} - ROW(1, 1, 1, 0, 120, 0 , 0 , 0 , 0 , 0 ), // #298 {m32|m64|st} - ROW(2, 1, 1, 0, 50 , 50 , 0 , 0 , 0 , 0 ), // #299 {xmm, xmm} - ROW(4, 1, 1, 0, 50 , 50 , 10 , 10 , 0 , 0 ), // {xmm, xmm, i8|u8, i8|u8} - ROW(2, 1, 0, 0, 6 , 52 , 0 , 0 , 0 , 0 ), // #301 {r32, m128|mem} - ROW(2, 0, 1, 0, 8 , 52 , 0 , 0 , 0 , 0 ), // {r64, m128|mem} - ROW(2, 1, 0, 2, 36 , 121, 0 , 0 , 0 , 0 ), // #303 {<eax>, <ecx>} - ROW(2, 0, 1, 2, 122, 121, 0 , 0 , 0 , 0 ), // {<eax|rax>, <ecx>} - ROW(1, 1, 1, 0, 123, 0 , 0 , 0 , 0 , 0 ), // #305 {rel8|rel32} - ROW(1, 1, 0, 0, 124, 0 , 0 , 0 , 0 , 0 ), // {rel16} - ROW(2, 1, 0, 1, 125, 126, 0 , 0 , 0 , 0 ), // #307 {<cx|ecx>, rel8} - ROW(2, 0, 1, 1, 127, 126, 0 , 0 , 0 , 0 ), // {<ecx|rcx>, rel8} - ROW(1, 1, 1, 0, 128, 0 , 0 , 0 , 0 , 0 ), // #309 {rel8|rel32|r64|m64|mem} - ROW(1, 1, 0, 0, 129, 0 , 0 , 0 , 0 , 0 ), // {rel16|r32|m32|mem} - ROW(2, 1, 1, 0, 106, 130, 0 , 0 , 0 , 0 ), // #311 {k, k|m8|mem|r32} - ROW(2, 1, 1, 0, 131, 106, 0 , 0 , 0 , 0 ), // {m8|mem|r32, k} - ROW(2, 1, 1, 0, 106, 132, 0 , 0 , 0 , 0 ), // #313 {k, k|m32|mem|r32} - ROW(2, 1, 1, 0, 28 , 106, 0 , 0 , 0 , 0 ), // {m32|mem|r32, k} - ROW(2, 1, 1, 0, 106, 133, 0 , 0 , 0 , 0 ), // #315 {k, k|m64|mem|r64} - ROW(2, 1, 1, 0, 15 , 106, 0 , 0 , 0 , 0 ), // {m64|mem|r64, k} - ROW(2, 1, 1, 0, 106, 134, 0 , 0 , 0 , 0 ), // #317 {k, k|m16|mem|r32} - ROW(2, 1, 1, 0, 135, 106, 0 , 0 , 0 , 0 ), // {m16|mem|r32, k} - ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #319 {r16, r16|m16|mem} - ROW(2, 1, 1, 0, 6 , 135, 0 , 0 , 0 , 0 ), // {r32, r32|m16|mem} - ROW(2, 1, 0, 0, 136, 137, 0 , 0 , 0 , 0 ), // #321 {i16, i16|i32} - ROW(1, 1, 1, 0, 138, 0 , 0 , 0 , 0 , 0 ), // {m32|m48|m80|mem} - ROW(2, 1, 0, 0, 4 , 29 , 0 , 0 , 0 , 0 ), // #323 {r16, m32|mem} - ROW(2, 1, 0, 0, 6 , 101, 0 , 0 , 0 , 0 ), // {r32, m48|mem} - ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #325 {r16, r16|m16|mem} - ROW(2, 1, 1, 0, 139, 135, 0 , 0 , 0 , 0 ), // {r32|r64, r32|m16|mem} - ROW(2, 1, 1, 0, 64 , 28 , 0 , 0 , 0 , 0 ), // #327 {mm|xmm, r32|m32|mem} - ROW(2, 1, 1, 0, 28 , 64 , 0 , 0 , 0 , 0 ), // {r32|m32|mem, mm|xmm} - ROW(2, 1, 1, 0, 50 , 107, 0 , 0 , 0 , 0 ), // #329 {xmm, xmm|m32|mem} - ROW(2, 1, 1, 0, 29 , 50 , 0 , 0 , 0 , 0 ), // {m32|mem, xmm} - ROW(2, 1, 1, 0, 4 , 9 , 0 , 0 , 0 , 0 ), // #331 {r16, r8lo|r8hi|m8} - ROW(2, 1, 1, 0, 139, 140, 0 , 0 , 0 , 0 ), // {r32|r64, r8lo|r8hi|m8|r16|m16} - ROW(2, 0, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #333 {r16, r16|m16|mem} - ROW(2, 0, 1, 0, 139, 28 , 0 , 0 , 0 , 0 ), // {r32|r64, r32|m32|mem} - ROW(4, 1, 1, 1, 6 , 6 , 28 , 35 , 0 , 0 ), // #335 {r32, r32, r32|m32|mem, <edx>} - ROW(4, 0, 1, 1, 8 , 8 , 15 , 37 , 0 , 0 ), // {r64, r64, r64|m64|mem, <rdx>} - ROW(2, 1, 1, 0, 62 , 141, 0 , 0 , 0 , 0 ), // #337 {mm, mm|m64|mem} - ROW(2, 1, 1, 0, 50 , 51 , 0 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem} - ROW(3, 1, 1, 0, 62 , 141, 10 , 0 , 0 , 0 ), // #339 {mm, mm|m64|mem, i8|u8} - ROW(3, 1, 1, 0, 50 , 51 , 10 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem, i8|u8} - ROW(3, 1, 1, 0, 6 , 64 , 10 , 0 , 0 , 0 ), // #341 {r32, mm|xmm, i8|u8} - ROW(3, 1, 1, 0, 21 , 50 , 10 , 0 , 0 , 0 ), // {m16|mem, xmm, i8|u8} - ROW(2, 1, 1, 0, 62 , 142, 0 , 0 , 0 , 0 ), // #343 {mm, i8|u8|mm|m64|mem} - ROW(2, 1, 1, 0, 50 , 59 , 0 , 0 , 0 , 0 ), // {xmm, i8|u8|xmm|m128|mem} - ROW(2, 1, 1, 0, 62 , 143, 0 , 0 , 0 , 0 ), // #345 {mm, mm|m32|mem} - ROW(2, 1, 1, 0, 50 , 51 , 0 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem} - ROW(1, 1, 0, 0, 6 , 0 , 0 , 0 , 0 , 0 ), // #347 {r32} - ROW(1, 0, 1, 0, 8 , 0 , 0 , 0 , 0 , 0 ), // #348 {r64} - ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #349 {} - ROW(1, 1, 1, 0, 144, 0 , 0 , 0 , 0 , 0 ), // {u16} - ROW(3, 1, 1, 0, 6 , 28 , 10 , 0 , 0 , 0 ), // #351 {r32, r32|m32|mem, i8|u8} - ROW(3, 0, 1, 0, 8 , 15 , 10 , 0 , 0 , 0 ), // {r64, r64|m64|mem, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 51 , 50 , 0 , 0 ), // #353 {xmm, xmm, xmm|m128|mem, xmm} - ROW(4, 1, 1, 0, 53 , 53 , 54 , 53 , 0 , 0 ), // {ymm, ymm, ymm|m256|mem, ymm} - ROW(2, 1, 1, 0, 50 , 145, 0 , 0 , 0 , 0 ), // #355 {xmm, xmm|m128|ymm|m256} - ROW(2, 1, 1, 0, 53 , 57 , 0 , 0 , 0 , 0 ), // {ymm, zmm|m512|mem} - ROW(4, 1, 1, 0, 50 , 50 , 50 , 65 , 0 , 0 ), // #357 {xmm, xmm, xmm, xmm|m64|mem} - ROW(4, 1, 1, 0, 50 , 50 , 30 , 50 , 0 , 0 ), // {xmm, xmm, m64|mem, xmm} - ROW(4, 1, 1, 0, 50 , 50 , 50 , 107, 0 , 0 ), // #359 {xmm, xmm, xmm, xmm|m32|mem} - ROW(4, 1, 1, 0, 50 , 50 , 29 , 50 , 0 , 0 ), // {xmm, xmm, m32|mem, xmm} - ROW(4, 1, 1, 0, 53 , 53 , 51 , 10 , 0 , 0 ), // #361 {ymm, ymm, xmm|m128|mem, i8|u8} - ROW(4, 1, 1, 0, 56 , 56 , 51 , 10 , 0 , 0 ), // {zmm, zmm, xmm|m128|mem, i8|u8} - ROW(1, 1, 0, 1, 36 , 0 , 0 , 0 , 0 , 0 ), // #363 {<eax>} - ROW(1, 0, 1, 1, 38 , 0 , 0 , 0 , 0 , 0 ), // #364 {<rax>} - ROW(2, 1, 1, 0, 28 , 50 , 0 , 0 , 0 , 0 ), // #365 {r32|m32|mem, xmm} - ROW(2, 1, 1, 0, 50 , 28 , 0 , 0 , 0 , 0 ), // {xmm, r32|m32|mem} - ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // #367 {m64|mem, xmm} - ROW(3, 1, 1, 0, 50 , 50 , 30 , 0 , 0 , 0 ), // {xmm, xmm, m64|mem} - ROW(2, 1, 1, 0, 135, 50 , 0 , 0 , 0 , 0 ), // #369 {r32|m16|mem, xmm} - ROW(2, 1, 1, 0, 50 , 135, 0 , 0 , 0 , 0 ), // {xmm, r32|m16|mem} - ROW(2, 1, 0, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // #371 {r32|m32|mem, r32} - ROW(2, 0, 1, 0, 15 , 8 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, r64} - ROW(2, 1, 0, 0, 6 , 28 , 0 , 0 , 0 , 0 ), // #373 {r32, r32|m32|mem} - ROW(2, 0, 1, 0, 8 , 15 , 0 , 0 , 0 , 0 ), // {r64, r64|m64|mem} - ROW(3, 1, 1, 0, 50 , 50 , 59 , 0 , 0 , 0 ), // #375 {xmm, xmm, xmm|m128|mem|i8|u8} - ROW(3, 1, 1, 0, 50 , 52 , 146, 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8|xmm} - ROW(2, 1, 1, 0, 67 , 96 , 0 , 0 , 0 , 0 ), // #377 {vm32x, xmm|ymm} - ROW(2, 1, 1, 0, 68 , 56 , 0 , 0 , 0 , 0 ), // {vm32y, zmm} - ROW(2, 1, 1, 0, 108, 50 , 0 , 0 , 0 , 0 ), // #379 {vm64x|vm64y, xmm} - ROW(2, 1, 1, 0, 72 , 53 , 0 , 0 , 0 , 0 ), // {vm64z, ymm} - ROW(3, 1, 1, 0, 50 , 50 , 51 , 0 , 0 , 0 ), // #381 {xmm, xmm, xmm|m128|mem} - ROW(3, 1, 1, 0, 50 , 52 , 50 , 0 , 0 , 0 ), // {xmm, m128|mem, xmm} - ROW(1, 1, 0, 1, 33 , 0 , 0 , 0 , 0 , 0 ), // #383 {<ax>} - ROW(2, 1, 0, 1, 33 , 10 , 0 , 0 , 0 , 0 ), // #384 {<ax>, i8|u8} - ROW(2, 1, 0, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // #385 {r16|m16|mem, r16} - ROW(3, 1, 1, 1, 50 , 51 , 147, 0 , 0 , 0 ), // #386 {xmm, xmm|m128|mem, <xmm0>} - ROW(2, 1, 1, 0, 111, 148, 0 , 0 , 0 , 0 ), // #387 {bnd, mib} - ROW(2, 1, 1, 0, 111, 113, 0 , 0 , 0 , 0 ), // #388 {bnd, mem} - ROW(2, 1, 1, 0, 148, 111, 0 , 0 , 0 , 0 ), // #389 {mib, bnd} - ROW(1, 1, 1, 0, 149, 0 , 0 , 0 , 0 , 0 ), // #390 {r16|r32|r64} - ROW(1, 1, 1, 1, 33 , 0 , 0 , 0 , 0 , 0 ), // #391 {<ax>} - ROW(2, 1, 1, 2, 35 , 36 , 0 , 0 , 0 , 0 ), // #392 {<edx>, <eax>} - ROW(1, 1, 1, 0, 150, 0 , 0 , 0 , 0 , 0 ), // #393 {mem|m8|m16|m32|m48|m64|m80|m128|m256|m512|m1024} - ROW(1, 1, 1, 0, 30 , 0 , 0 , 0 , 0 , 0 ), // #394 {m64|mem} - ROW(0, 0, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #395 {} - ROW(1, 1, 1, 1, 151, 0 , 0 , 0 , 0 , 0 ), // #396 {<ds:[mem|m512|memBase|zax]>} - ROW(3, 1, 1, 0, 50 , 65 , 10 , 0 , 0 , 0 ), // #397 {xmm, xmm|m64|mem, i8|u8} - ROW(3, 1, 1, 0, 50 , 107, 10 , 0 , 0 , 0 ), // #398 {xmm, xmm|m32|mem, i8|u8} - ROW(5, 0, 1, 4, 52 , 37 , 38 , 152, 153, 0 ), // #399 {m128|mem, <rdx>, <rax>, <rcx>, <rbx>} - ROW(5, 1, 1, 4, 30 , 35 , 36 , 121, 154, 0 ), // #400 {m64|mem, <edx>, <eax>, <ecx>, <ebx>} - ROW(4, 1, 1, 4, 36 , 154, 121, 35 , 0 , 0 ), // #401 {<eax>, <ebx>, <ecx>, <edx>} - ROW(2, 0, 1, 2, 37 , 38 , 0 , 0 , 0 , 0 ), // #402 {<rdx>, <rax>} - ROW(2, 1, 1, 0, 62 , 51 , 0 , 0 , 0 , 0 ), // #403 {mm, xmm|m128|mem} - ROW(2, 1, 1, 0, 50 , 141, 0 , 0 , 0 , 0 ), // #404 {xmm, mm|m64|mem} - ROW(2, 1, 1, 0, 62 , 65 , 0 , 0 , 0 , 0 ), // #405 {mm, xmm|m64|mem} - ROW(2, 1, 1, 0, 139, 65 , 0 , 0 , 0 , 0 ), // #406 {r32|r64, xmm|m64|mem} - ROW(2, 1, 1, 0, 50 , 155, 0 , 0 , 0 , 0 ), // #407 {xmm, r32|m32|mem|r64|m64} - ROW(2, 1, 1, 0, 139, 107, 0 , 0 , 0 , 0 ), // #408 {r32|r64, xmm|m32|mem} - ROW(2, 1, 1, 2, 34 , 33 , 0 , 0 , 0 , 0 ), // #409 {<dx>, <ax>} - ROW(1, 1, 1, 1, 36 , 0 , 0 , 0 , 0 , 0 ), // #410 {<eax>} - ROW(2, 1, 1, 0, 12 , 10 , 0 , 0 , 0 , 0 ), // #411 {i16|u16, i8|u8} - ROW(3, 1, 1, 0, 28 , 50 , 10 , 0 , 0 , 0 ), // #412 {r32|m32|mem, xmm, i8|u8} - ROW(1, 1, 1, 0, 102, 0 , 0 , 0 , 0 , 0 ), // #413 {m80|mem} - ROW(1, 1, 1, 0, 156, 0 , 0 , 0 , 0 , 0 ), // #414 {m16|m32} - ROW(1, 1, 1, 0, 157, 0 , 0 , 0 , 0 , 0 ), // #415 {m16|m32|m64} - ROW(1, 1, 1, 0, 158, 0 , 0 , 0 , 0 , 0 ), // #416 {m32|m64|m80|st} - ROW(1, 1, 1, 0, 21 , 0 , 0 , 0 , 0 , 0 ), // #417 {m16|mem} - ROW(1, 1, 1, 0, 113, 0 , 0 , 0 , 0 , 0 ), // #418 {mem} - ROW(1, 1, 1, 0, 159, 0 , 0 , 0 , 0 , 0 ), // #419 {ax|m16|mem} - ROW(1, 0, 1, 0, 113, 0 , 0 , 0 , 0 , 0 ), // #420 {mem} - ROW(2, 1, 1, 1, 10 , 36 , 0 , 0 , 0 , 0 ), // #421 {i8|u8, <eax>} - ROW(2, 1, 1, 0, 160, 161, 0 , 0 , 0 , 0 ), // #422 {al|ax|eax, i8|u8|dx} - ROW(1, 1, 1, 0, 6 , 0 , 0 , 0 , 0 , 0 ), // #423 {r32} - ROW(2, 1, 1, 0, 162, 163, 0 , 0 , 0 , 0 ), // #424 {es:[m8|memBase|zdi|m16|m32], dx} - ROW(1, 1, 1, 0, 10 , 0 , 0 , 0 , 0 , 0 ), // #425 {i8|u8} - ROW(0, 1, 0, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #426 {} - ROW(3, 1, 1, 0, 106, 106, 106, 0 , 0 , 0 ), // #427 {k, k, k} - ROW(2, 1, 1, 0, 106, 106, 0 , 0 , 0 , 0 ), // #428 {k, k} - ROW(3, 1, 1, 0, 106, 106, 10 , 0 , 0 , 0 ), // #429 {k, k, i8|u8} - ROW(1, 1, 1, 1, 164, 0 , 0 , 0 , 0 , 0 ), // #430 {<ah>} - ROW(1, 1, 1, 0, 29 , 0 , 0 , 0 , 0 , 0 ), // #431 {m32|mem} - ROW(1, 0, 1, 0, 58 , 0 , 0 , 0 , 0 , 0 ), // #432 {m512|mem} - ROW(2, 1, 1, 0, 149, 150, 0 , 0 , 0 , 0 ), // #433 {r16|r32|r64, mem|m8|m16|m32|m48|m64|m80|m128|m256|m512|m1024} - ROW(1, 1, 1, 0, 27 , 0 , 0 , 0 , 0 , 0 ), // #434 {r16|m16|mem} - ROW(1, 1, 1, 0, 139, 0 , 0 , 0 , 0 , 0 ), // #435 {r32|r64} - ROW(3, 1, 1, 0, 139, 28 , 14 , 0 , 0 , 0 ), // #436 {r32|r64, r32|m32|mem, i32|u32} - ROW(3, 1, 1, 1, 50 , 50 , 165, 0 , 0 , 0 ), // #437 {xmm, xmm, <ds:[mem|m128|memBase|zdi]>} - ROW(3, 1, 1, 1, 62 , 62 , 166, 0 , 0 , 0 ), // #438 {mm, mm, <ds:[mem|m64|memBase|zdi]>} - ROW(3, 1, 1, 3, 167, 121, 35 , 0 , 0 , 0 ), // #439 {<ds:[mem|memBase|zax]>, <ecx>, <edx>} - ROW(2, 1, 1, 0, 119, 58 , 0 , 0 , 0 , 0 ), // #440 {es:[mem|m512|memBase], m512|mem} - ROW(2, 1, 1, 0, 62 , 50 , 0 , 0 , 0 , 0 ), // #441 {mm, xmm} - ROW(2, 1, 1, 0, 6 , 50 , 0 , 0 , 0 , 0 ), // #442 {r32, xmm} - ROW(2, 1, 1, 0, 30 , 62 , 0 , 0 , 0 , 0 ), // #443 {m64|mem, mm} - ROW(2, 1, 1, 0, 50 , 62 , 0 , 0 , 0 , 0 ), // #444 {xmm, mm} - ROW(2, 1, 1, 2, 36 , 121, 0 , 0 , 0 , 0 ), // #445 {<eax>, <ecx>} - ROW(3, 1, 1, 3, 36 , 121, 154, 0 , 0 , 0 ), // #446 {<eax>, <ecx>, <ebx>} - ROW(2, 1, 1, 0, 168, 160, 0 , 0 , 0 , 0 ), // #447 {u8|dx, al|ax|eax} - ROW(2, 1, 1, 0, 163, 169, 0 , 0 , 0 , 0 ), // #448 {dx, ds:[m8|memBase|zsi|m16|m32]} - ROW(6, 1, 1, 3, 50 , 51 , 10 , 121, 36 , 35 ), // #449 {xmm, xmm|m128|mem, i8|u8, <ecx>, <eax>, <edx>} - ROW(6, 1, 1, 3, 50 , 51 , 10 , 147, 36 , 35 ), // #450 {xmm, xmm|m128|mem, i8|u8, <xmm0>, <eax>, <edx>} - ROW(4, 1, 1, 1, 50 , 51 , 10 , 121, 0 , 0 ), // #451 {xmm, xmm|m128|mem, i8|u8, <ecx>} - ROW(4, 1, 1, 1, 50 , 51 , 10 , 147, 0 , 0 ), // #452 {xmm, xmm|m128|mem, i8|u8, <xmm0>} - ROW(3, 1, 1, 0, 131, 50 , 10 , 0 , 0 , 0 ), // #453 {r32|m8|mem, xmm, i8|u8} - ROW(3, 0, 1, 0, 15 , 50 , 10 , 0 , 0 , 0 ), // #454 {r64|m64|mem, xmm, i8|u8} - ROW(3, 1, 1, 0, 50 , 131, 10 , 0 , 0 , 0 ), // #455 {xmm, r32|m8|mem, i8|u8} - ROW(3, 1, 1, 0, 50 , 28 , 10 , 0 , 0 , 0 ), // #456 {xmm, r32|m32|mem, i8|u8} - ROW(3, 0, 1, 0, 50 , 15 , 10 , 0 , 0 , 0 ), // #457 {xmm, r64|m64|mem, i8|u8} - ROW(3, 1, 1, 0, 64 , 135, 10 , 0 , 0 , 0 ), // #458 {mm|xmm, r32|m16|mem, i8|u8} - ROW(2, 1, 1, 0, 6 , 64 , 0 , 0 , 0 , 0 ), // #459 {r32, mm|xmm} - ROW(2, 1, 1, 0, 50 , 10 , 0 , 0 , 0 , 0 ), // #460 {xmm, i8|u8} - ROW(1, 1, 1, 0, 155, 0 , 0 , 0 , 0 , 0 ), // #461 {r32|m32|mem|r64|m64} - ROW(2, 1, 1, 0, 31 , 103, 0 , 0 , 0 , 0 ), // #462 {r8lo|r8hi|m8|r16|m16|r32|m32|r64|m64|mem, cl|i8|u8} - ROW(1, 0, 1, 0, 139, 0 , 0 , 0 , 0 , 0 ), // #463 {r32|r64} - ROW(3, 1, 1, 3, 35 , 36 , 121, 0 , 0 , 0 ), // #464 {<edx>, <eax>, <ecx>} - ROW(1, 1, 1, 0, 1 , 0 , 0 , 0 , 0 , 0 ), // #465 {r8lo|r8hi|m8|mem} - ROW(1, 1, 1, 0, 170, 0 , 0 , 0 , 0 , 0 ), // #466 {r16|m16|mem|r32|r64} - ROW(3, 0, 1, 0, 171, 171, 171, 0 , 0 , 0 ), // #467 {tmm, tmm, tmm} - ROW(2, 0, 1, 0, 171, 172, 0 , 0 , 0 , 0 ), // #468 {tmm, tmem} - ROW(2, 0, 1, 0, 172, 171, 0 , 0 , 0 , 0 ), // #469 {tmem, tmm} - ROW(1, 0, 1, 0, 171, 0 , 0 , 0 , 0 , 0 ), // #470 {tmm} - ROW(3, 1, 1, 2, 6 , 35 , 36 , 0 , 0 , 0 ), // #471 {r32, <edx>, <eax>} - ROW(1, 1, 1, 0, 173, 0 , 0 , 0 , 0 , 0 ), // #472 {ds:[mem|memBase]} - ROW(6, 1, 1, 0, 56 , 56 , 56 , 56 , 56 , 52 ), // #473 {zmm, zmm, zmm, zmm, zmm, m128|mem} - ROW(6, 1, 1, 0, 50 , 50 , 50 , 50 , 50 , 52 ), // #474 {xmm, xmm, xmm, xmm, xmm, m128|mem} - ROW(3, 1, 1, 0, 50 , 50 , 65 , 0 , 0 , 0 ), // #475 {xmm, xmm, xmm|m64|mem} - ROW(3, 1, 1, 0, 50 , 50 , 110, 0 , 0 , 0 ), // #476 {xmm, xmm, xmm|m16|mem} - ROW(3, 1, 1, 0, 50 , 50 , 107, 0 , 0 , 0 ), // #477 {xmm, xmm, xmm|m32|mem} - ROW(2, 1, 1, 0, 53 , 52 , 0 , 0 , 0 , 0 ), // #478 {ymm, m128|mem} - ROW(2, 1, 1, 0, 174, 65 , 0 , 0 , 0 , 0 ), // #479 {ymm|zmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 174, 52 , 0 , 0 , 0 , 0 ), // #480 {ymm|zmm, m128|mem} - ROW(2, 1, 1, 0, 56 , 55 , 0 , 0 , 0 , 0 ), // #481 {zmm, m256|mem} - ROW(2, 1, 1, 0, 175, 65 , 0 , 0 , 0 , 0 ), // #482 {xmm|ymm|zmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 175, 107, 0 , 0 , 0 , 0 ), // #483 {xmm|ymm|zmm, m32|mem|xmm} - ROW(4, 1, 1, 0, 104, 50 , 65 , 10 , 0 , 0 ), // #484 {xmm|k, xmm, xmm|m64|mem, i8|u8} - ROW(4, 1, 1, 0, 106, 50 , 110, 10 , 0 , 0 ), // #485 {k, xmm, xmm|m16|mem, i8|u8} - ROW(4, 1, 1, 0, 104, 50 , 107, 10 , 0 , 0 ), // #486 {xmm|k, xmm, xmm|m32|mem, i8|u8} - ROW(2, 1, 1, 0, 50 , 176, 0 , 0 , 0 , 0 ), // #487 {xmm, xmm|m128|ymm|m256|zmm|m512} - ROW(2, 1, 1, 0, 139, 110, 0 , 0 , 0 , 0 ), // #488 {r32|r64, xmm|m16|mem} - ROW(3, 1, 1, 0, 50 , 50 , 155, 0 , 0 , 0 ), // #489 {xmm, xmm, r32|m32|mem|r64|m64} - ROW(3, 1, 1, 0, 51 , 174, 10 , 0 , 0 , 0 ), // #490 {xmm|m128|mem, ymm|zmm, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 65 , 10 , 0 , 0 ), // #491 {xmm, xmm, xmm|m64|mem, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 107, 10 , 0 , 0 ), // #492 {xmm, xmm, xmm|m32|mem, i8|u8} - ROW(3, 1, 1, 0, 106, 176, 10 , 0 , 0 , 0 ), // #493 {k, xmm|m128|ymm|m256|zmm|m512, i8|u8} - ROW(3, 1, 1, 0, 106, 65 , 10 , 0 , 0 , 0 ), // #494 {k, xmm|m64|mem, i8|u8} - ROW(3, 1, 1, 0, 106, 110, 10 , 0 , 0 , 0 ), // #495 {k, xmm|m16|mem, i8|u8} - ROW(3, 1, 1, 0, 106, 107, 10 , 0 , 0 , 0 ), // #496 {k, xmm|m32|mem, i8|u8} - ROW(1, 1, 1, 0, 68 , 0 , 0 , 0 , 0 , 0 ), // #497 {vm32y} - ROW(1, 1, 1, 0, 69 , 0 , 0 , 0 , 0 , 0 ), // #498 {vm32z} - ROW(1, 1, 1, 0, 72 , 0 , 0 , 0 , 0 , 0 ), // #499 {vm64z} - ROW(4, 1, 1, 0, 50 , 50 , 110, 10 , 0 , 0 ), // #500 {xmm, xmm, xmm|m16|mem, i8|u8} - ROW(4, 1, 1, 0, 56 , 56 , 54 , 10 , 0 , 0 ), // #501 {zmm, zmm, ymm|m256|mem, i8|u8} - ROW(2, 1, 1, 0, 6 , 96 , 0 , 0 , 0 , 0 ), // #502 {r32, xmm|ymm} - ROW(2, 1, 1, 0, 175, 177, 0 , 0 , 0 , 0 ), // #503 {xmm|ymm|zmm, xmm|m8|mem|r32} - ROW(2, 1, 1, 0, 175, 178, 0 , 0 , 0 , 0 ), // #504 {xmm|ymm|zmm, xmm|m32|mem|r32} - ROW(2, 1, 1, 0, 175, 106, 0 , 0 , 0 , 0 ), // #505 {xmm|ymm|zmm, k} - ROW(2, 1, 1, 0, 175, 179, 0 , 0 , 0 , 0 ), // #506 {xmm|ymm|zmm, xmm|m16|mem|r32} - ROW(3, 1, 1, 0, 135, 50 , 10 , 0 , 0 , 0 ), // #507 {r32|m16|mem, xmm, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 131, 10 , 0 , 0 ), // #508 {xmm, xmm, r32|m8|mem, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 28 , 10 , 0 , 0 ), // #509 {xmm, xmm, r32|m32|mem, i8|u8} - ROW(4, 0, 1, 0, 50 , 50 , 15 , 10 , 0 , 0 ), // #510 {xmm, xmm, r64|m64|mem, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 135, 10 , 0 , 0 ), // #511 {xmm, xmm, r32|m16|mem, i8|u8} - ROW(2, 1, 1, 0, 106, 175, 0 , 0 , 0 , 0 ), // #512 {k, xmm|ymm|zmm} - ROW(1, 1, 1, 0, 124, 0 , 0 , 0 , 0 , 0 ), // #513 {rel16|rel32} - ROW(3, 1, 1, 2, 113, 35 , 36 , 0 , 0 , 0 ), // #514 {mem, <edx>, <eax>} - ROW(3, 0, 1, 2, 113, 35 , 36 , 0 , 0 , 0 ) // #515 {mem, <edx>, <eax>} + ROW(1, 0, 1, 0, 15 , 0 , 0 , 0 , 0 , 0 ), // {r64|m64} + ROW(1, 1, 0, 0, 65 , 0 , 0 , 0 , 0 , 0 ), // {ds|es|ss} + ROW(1, 1, 1, 0, 66 , 0 , 0 , 0 , 0 , 0 ), // {fs|gs} + ROW(1, 1, 1, 0, 67 , 0 , 0 , 0 , 0 , 0 ), // #149 {r16|m16|i8|i16} + ROW(1, 1, 0, 0, 68 , 0 , 0 , 0 , 0 , 0 ), // {r32|m32|i32|u32} + ROW(1, 0, 1, 0, 69 , 0 , 0 , 0 , 0 , 0 ), // {r64|m64|i32} + ROW(1, 1, 0, 0, 70 , 0 , 0 , 0 , 0 , 0 ), // {cs|ss|ds|es} + ROW(1, 1, 1, 0, 66 , 0 , 0 , 0 , 0 , 0 ), // {fs|gs} + ROW(3, 1, 1, 0, 49 , 71 , 49 , 0 , 0 , 0 ), // #154 {xmm, vm32x, xmm} + ROW(3, 1, 1, 0, 52 , 72 , 52 , 0 , 0 , 0 ), // {ymm, vm32y, ymm} + ROW(2, 1, 1, 0, 49 , 71 , 0 , 0 , 0 , 0 ), // {xmm, vm32x} + ROW(2, 1, 1, 0, 52 , 72 , 0 , 0 , 0 , 0 ), // {ymm, vm32y} + ROW(2, 1, 1, 0, 55 , 73 , 0 , 0 , 0 , 0 ), // {zmm, vm32z} + ROW(3, 1, 1, 0, 49 , 74 , 49 , 0 , 0 , 0 ), // #159 {xmm, vm64x, xmm} + ROW(3, 1, 1, 0, 52 , 75 , 52 , 0 , 0 , 0 ), // {ymm, vm64y, ymm} + ROW(2, 1, 1, 0, 49 , 74 , 0 , 0 , 0 , 0 ), // {xmm, vm64x} + ROW(2, 1, 1, 0, 52 , 75 , 0 , 0 , 0 , 0 ), // {ymm, vm64y} + ROW(2, 1, 1, 0, 55 , 76 , 0 , 0 , 0 , 0 ), // {zmm, vm64z} + ROW(2, 1, 1, 0, 51 , 49 , 0 , 0 , 0 , 0 ), // #164 {m128|mem, xmm} + ROW(2, 1, 1, 0, 54 , 52 , 0 , 0 , 0 , 0 ), // {m256|mem, ymm} + ROW(2, 1, 1, 0, 51 , 49 , 0 , 0 , 0 , 0 ), // {m128|mem, xmm} + ROW(2, 1, 1, 0, 54 , 52 , 0 , 0 , 0 , 0 ), // {m256|mem, ymm} + ROW(2, 1, 1, 0, 57 , 55 , 0 , 0 , 0 , 0 ), // {m512|mem, zmm} + ROW(2, 1, 1, 0, 49 , 51 , 0 , 0 , 0 , 0 ), // #169 {xmm, m128|mem} + ROW(2, 1, 1, 0, 52 , 54 , 0 , 0 , 0 , 0 ), // {ymm, m256|mem} + ROW(2, 1, 1, 0, 49 , 51 , 0 , 0 , 0 , 0 ), // {xmm, m128|mem} + ROW(2, 1, 1, 0, 52 , 54 , 0 , 0 , 0 , 0 ), // {ymm, m256|mem} + ROW(2, 1, 1, 0, 55 , 57 , 0 , 0 , 0 , 0 ), // {zmm, m512|mem} + ROW(2, 0, 1, 0, 29 , 49 , 0 , 0 , 0 , 0 ), // #174 {r64|m64|mem, xmm} + ROW(2, 1, 1, 0, 49 , 64 , 0 , 0 , 0 , 0 ), // {xmm, xmm|m64|mem} + ROW(2, 0, 1, 0, 49 , 29 , 0 , 0 , 0 , 0 ), // {xmm, r64|m64|mem} + ROW(2, 1, 1, 0, 31 , 49 , 0 , 0 , 0 , 0 ), // {m64|mem, xmm} + ROW(2, 1, 1, 0, 31 , 49 , 0 , 0 , 0 , 0 ), // {m64|mem, xmm} + ROW(2, 1, 1, 0, 77 , 78 , 0 , 0 , 0 , 0 ), // #179 {ds:[memBase|zsi|m8], es:[memBase|zdi|m8]} + ROW(2, 1, 1, 0, 79 , 80 , 0 , 0 , 0 , 0 ), // {ds:[memBase|zsi|m16], es:[memBase|zdi|m16]} + ROW(2, 1, 1, 0, 81 , 82 , 0 , 0 , 0 , 0 ), // {ds:[memBase|zsi|m32], es:[memBase|zdi|m32]} + ROW(2, 0, 1, 0, 83 , 84 , 0 , 0 , 0 , 0 ), // {ds:[memBase|zsi|m64], es:[memBase|zdi|m64]} + ROW(3, 1, 1, 1, 1 , 2 , 85 , 0 , 0 , 0 ), // #183 {r8lo|r8hi|m8|mem, r8lo|r8hi, <al>} + ROW(3, 1, 1, 1, 27 , 4 , 36 , 0 , 0 , 0 ), // {r16|m16|mem, r16, <ax>} + ROW(3, 1, 1, 1, 28 , 6 , 39 , 0 , 0 , 0 ), // {r32|m32|mem, r32, <eax>} + ROW(3, 0, 1, 1, 29 , 8 , 41 , 0 , 0 , 0 ), // {r64|m64|mem, r64, <rax>} + ROW(2, 1, 1, 0, 86 , 87 , 0 , 0 , 0 , 0 ), // #187 {k, k|m64|mem} + ROW(2, 0, 1, 0, 86 , 8 , 0 , 0 , 0 , 0 ), // {k, r64} + ROW(2, 1, 1, 0, 31 , 86 , 0 , 0 , 0 , 0 ), // {m64|mem, k} + ROW(2, 0, 1, 0, 8 , 86 , 0 , 0 , 0 , 0 ), // {r64, k} + ROW(2, 1, 1, 0, 45 , 88 , 0 , 0 , 0 , 0 ), // #191 {al, ds:[memBase|zsi|m8|mem]} + ROW(2, 1, 1, 0, 46 , 89 , 0 , 0 , 0 , 0 ), // {ax, ds:[memBase|zsi|m16|mem]} + ROW(2, 1, 1, 0, 47 , 90 , 0 , 0 , 0 , 0 ), // {eax, ds:[memBase|zsi|m32|mem]} + ROW(2, 0, 1, 0, 48 , 91 , 0 , 0 , 0 , 0 ), // {rax, ds:[memBase|zsi|m64|mem]} + ROW(2, 1, 1, 0, 78 , 77 , 0 , 0 , 0 , 0 ), // #195 {es:[memBase|zdi|m8], ds:[memBase|zsi|m8]} + ROW(2, 1, 1, 0, 80 , 79 , 0 , 0 , 0 , 0 ), // {es:[memBase|zdi|m16], ds:[memBase|zsi|m16]} + ROW(2, 1, 1, 0, 82 , 81 , 0 , 0 , 0 , 0 ), // {es:[memBase|zdi|m32], ds:[memBase|zsi|m32]} + ROW(2, 0, 1, 0, 84 , 83 , 0 , 0 , 0 , 0 ), // {es:[memBase|zdi|m64], ds:[memBase|zsi|m64]} + ROW(2, 1, 1, 0, 45 , 92 , 0 , 0 , 0 , 0 ), // #199 {al, es:[memBase|zdi|m8|mem]} + ROW(2, 1, 1, 0, 46 , 93 , 0 , 0 , 0 , 0 ), // {ax, es:[memBase|zdi|m16|mem]} + ROW(2, 1, 1, 0, 47 , 94 , 0 , 0 , 0 , 0 ), // {eax, es:[memBase|zdi|m32|mem]} + ROW(2, 0, 1, 0, 48 , 95 , 0 , 0 , 0 , 0 ), // {rax, es:[memBase|zdi|m64|mem]} + ROW(2, 1, 1, 0, 92 , 45 , 0 , 0 , 0 , 0 ), // #203 {es:[memBase|zdi|m8|mem], al} + ROW(2, 1, 1, 0, 93 , 46 , 0 , 0 , 0 , 0 ), // {es:[memBase|zdi|m16|mem], ax} + ROW(2, 1, 1, 0, 94 , 47 , 0 , 0 , 0 , 0 ), // {es:[memBase|zdi|m32|mem], eax} + ROW(2, 0, 1, 0, 95 , 48 , 0 , 0 , 0 , 0 ), // {es:[memBase|zdi|m64|mem], rax} + ROW(4, 1, 1, 0, 49 , 49 , 49 , 50 , 0 , 0 ), // #207 {xmm, xmm, xmm, xmm|m128|mem} + ROW(4, 1, 1, 0, 49 , 49 , 51 , 49 , 0 , 0 ), // {xmm, xmm, m128|mem, xmm} + ROW(4, 1, 1, 0, 52 , 52 , 52 , 53 , 0 , 0 ), // {ymm, ymm, ymm, ymm|m256|mem} + ROW(4, 1, 1, 0, 52 , 52 , 54 , 52 , 0 , 0 ), // {ymm, ymm, m256|mem, ymm} + ROW(3, 1, 1, 0, 49 , 71 , 49 , 0 , 0 , 0 ), // #211 {xmm, vm32x, xmm} + ROW(3, 1, 1, 0, 52 , 71 , 52 , 0 , 0 , 0 ), // {ymm, vm32x, ymm} + ROW(2, 1, 1, 0, 96 , 71 , 0 , 0 , 0 , 0 ), // {xmm|ymm, vm32x} + ROW(2, 1, 1, 0, 55 , 72 , 0 , 0 , 0 , 0 ), // {zmm, vm32y} + ROW(3, 1, 1, 0, 51 , 49 , 49 , 0 , 0 , 0 ), // #215 {m128|mem, xmm, xmm} + ROW(3, 1, 1, 0, 54 , 52 , 52 , 0 , 0 , 0 ), // {m256|mem, ymm, ymm} + ROW(3, 1, 1, 0, 49 , 49 , 51 , 0 , 0 , 0 ), // {xmm, xmm, m128|mem} + ROW(3, 1, 1, 0, 52 , 52 , 54 , 0 , 0 , 0 ), // {ymm, ymm, m256|mem} + ROW(2, 1, 1, 0, 31 , 49 , 0 , 0 , 0 , 0 ), // #219 {m64|mem, xmm} + ROW(3, 1, 1, 0, 49 , 49 , 31 , 0 , 0 , 0 ), // {xmm, xmm, m64|mem} + ROW(2, 1, 1, 0, 31 , 49 , 0 , 0 , 0 , 0 ), // {m64|mem, xmm} + ROW(3, 1, 1, 0, 49 , 49 , 31 , 0 , 0 , 0 ), // {xmm, xmm, m64|mem} + ROW(2, 1, 1, 0, 21 , 49 , 0 , 0 , 0 , 0 ), // #223 {m16|mem, xmm} + ROW(2, 1, 1, 0, 49 , 21 , 0 , 0 , 0 , 0 ), // {xmm, m16|mem} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(3, 1, 1, 0, 49 , 49 , 49 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(5, 1, 1, 0, 49 , 49 , 50 , 49 , 97 , 0 ), // #227 {xmm, xmm, xmm|m128|mem, xmm, i4|u4} + ROW(5, 1, 1, 0, 49 , 49 , 49 , 51 , 97 , 0 ), // {xmm, xmm, xmm, m128|mem, i4|u4} + ROW(5, 1, 1, 0, 52 , 52 , 53 , 52 , 97 , 0 ), // {ymm, ymm, ymm|m256|mem, ymm, i4|u4} + ROW(5, 1, 1, 0, 52 , 52 , 52 , 54 , 97 , 0 ), // {ymm, ymm, ymm, m256|mem, i4|u4} + ROW(3, 1, 1, 0, 52 , 53 , 10 , 0 , 0 , 0 ), // #231 {ymm, ymm|m256|mem, i8|u8} + ROW(3, 1, 1, 0, 52 , 52 , 53 , 0 , 0 , 0 ), // {ymm, ymm, ymm|m256|mem} + ROW(3, 1, 1, 0, 55 , 55 , 60 , 0 , 0 , 0 ), // {zmm, zmm, zmm|m512|mem|i8|u8} + ROW(3, 1, 1, 0, 55 , 57 , 10 , 0 , 0 , 0 ), // {zmm, m512|mem, i8|u8} + ROW(1, 1, 0, 0, 98 , 0 , 0 , 0 , 0 , 0 ), // #235 {rel16|r16|m16|mem|r32|m32} + ROW(1, 1, 1, 0, 99 , 0 , 0 , 0 , 0 , 0 ), // #236 {rel32} + ROW(1, 0, 1, 0, 29 , 0 , 0 , 0 , 0 , 0 ), // {r64|m64|mem} + ROW(1, 1, 0, 0, 100, 0 , 0 , 0 , 0 , 0 ), // #238 {r16|r32} + ROW(1, 1, 1, 0, 32 , 0 , 0 , 0 , 0 , 0 ), // #239 {r8lo|r8hi|m8|r16|m16|r32|m32} + ROW(1, 0, 1, 0, 15 , 0 , 0 , 0 , 0 , 0 ), // {r64|m64} + ROW(1, 1, 1, 0, 101, 0 , 0 , 0 , 0 , 0 ), // #241 {m32|m64} + ROW(2, 1, 1, 0, 102, 103, 0 , 0 , 0 , 0 ), // {st0, st} + ROW(2, 1, 1, 0, 103, 102, 0 , 0 , 0 , 0 ), // {st, st0} + ROW(1, 1, 1, 0, 104, 0 , 0 , 0 , 0 , 0 ), // #244 {rel8|rel32} + ROW(1, 1, 0, 0, 105, 0 , 0 , 0 , 0 , 0 ), // {rel16|r32|m32} + ROW(1, 0, 1, 0, 15 , 0 , 0 , 0 , 0 , 0 ), // {r64|m64} + ROW(2, 1, 0, 0, 106, 107, 0 , 0 , 0 , 0 ), // #247 {i16, i16|i32} + ROW(1, 1, 1, 0, 108, 0 , 0 , 0 , 0 , 0 ), // {m32|mem|m48} + ROW(1, 0, 1, 0, 109, 0 , 0 , 0 , 0 , 0 ), // {m80|mem} + ROW(2, 1, 1, 0, 4 , 30 , 0 , 0 , 0 , 0 ), // #250 {r16, m32|mem} + ROW(2, 1, 1, 0, 6 , 110, 0 , 0 , 0 , 0 ), // {r32, m48|mem} + ROW(2, 0, 1, 0, 8 , 109, 0 , 0 , 0 , 0 ), // {r64, m80|mem} + ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #253 {r16, r16|m16|mem} + ROW(2, 1, 1, 0, 6 , 111, 0 , 0 , 0 , 0 ), // {r32, r32|m16|mem} + ROW(2, 0, 1, 0, 8 , 111, 0 , 0 , 0 , 0 ), // {r64, r32|m16|mem} + ROW(2, 1, 1, 0, 4 , 9 , 0 , 0 , 0 , 0 ), // #256 {r16, r8lo|r8hi|m8} + ROW(2, 1, 1, 0, 6 , 112, 0 , 0 , 0 , 0 ), // {r32, r8lo|r8hi|m8|r16|m16} + ROW(2, 0, 1, 0, 8 , 113, 0 , 0 , 0 , 0 ), // {r64, r8lo|m8|r16|m16} + ROW(3, 1, 1, 0, 27 , 4 , 114, 0 , 0 , 0 ), // #259 {r16|m16|mem, r16, cl|i8|u8} + ROW(3, 1, 1, 0, 28 , 6 , 114, 0 , 0 , 0 ), // {r32|m32|mem, r32, cl|i8|u8} + ROW(3, 0, 1, 0, 29 , 8 , 114, 0 , 0 , 0 ), // {r64|m64|mem, r64, cl|i8|u8} + ROW(3, 1, 1, 0, 49 , 49 , 50 , 0 , 0 , 0 ), // #262 {xmm, xmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 52 , 52 , 53 , 0 , 0 , 0 ), // #263 {ymm, ymm, ymm|m256|mem} + ROW(3, 1, 1, 0, 55 , 55 , 56 , 0 , 0 , 0 ), // {zmm, zmm, zmm|m512|mem} + ROW(4, 1, 1, 0, 49 , 49 , 50 , 10 , 0 , 0 ), // #265 {xmm, xmm, xmm|m128|mem, i8|u8} + ROW(4, 1, 1, 0, 52 , 52 , 53 , 10 , 0 , 0 ), // #266 {ymm, ymm, ymm|m256|mem, i8|u8} + ROW(4, 1, 1, 0, 55 , 55 , 56 , 10 , 0 , 0 ), // {zmm, zmm, zmm|m512|mem, i8|u8} + ROW(4, 1, 1, 0, 115, 49 , 50 , 10 , 0 , 0 ), // #268 {xmm|k, xmm, xmm|m128|mem, i8|u8} + ROW(4, 1, 1, 0, 116, 52 , 53 , 10 , 0 , 0 ), // {ymm|k, ymm, ymm|m256|mem, i8|u8} + ROW(4, 1, 1, 0, 86 , 55 , 56 , 10 , 0 , 0 ), // {k, zmm, zmm|m512|mem, i8|u8} + ROW(4, 1, 1, 0, 86 , 49 , 50 , 10 , 0 , 0 ), // #271 {k, xmm, xmm|m128|mem, i8|u8} + ROW(4, 1, 1, 0, 86 , 52 , 53 , 10 , 0 , 0 ), // {k, ymm, ymm|m256|mem, i8|u8} + ROW(4, 1, 1, 0, 86 , 55 , 56 , 10 , 0 , 0 ), // {k, zmm, zmm|m512|mem, i8|u8} + ROW(2, 1, 1, 0, 50 , 49 , 0 , 0 , 0 , 0 ), // #274 {xmm|m128|mem, xmm} + ROW(2, 1, 1, 0, 53 , 52 , 0 , 0 , 0 , 0 ), // {ymm|m256|mem, ymm} + ROW(2, 1, 1, 0, 56 , 55 , 0 , 0 , 0 , 0 ), // {zmm|m512|mem, zmm} + ROW(2, 1, 1, 0, 49 , 64 , 0 , 0 , 0 , 0 ), // #277 {xmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 52 , 50 , 0 , 0 , 0 , 0 ), // {ymm, xmm|m128|mem} + ROW(2, 1, 1, 0, 55 , 53 , 0 , 0 , 0 , 0 ), // {zmm, ymm|m256|mem} + ROW(2, 1, 1, 0, 49 , 50 , 0 , 0 , 0 , 0 ), // #280 {xmm, xmm|m128|mem} + ROW(2, 1, 1, 0, 52 , 53 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} + ROW(2, 1, 1, 0, 55 , 56 , 0 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem} + ROW(2, 1, 1, 0, 49 , 117, 0 , 0 , 0 , 0 ), // #283 {xmm, xmm|m32|mem} + ROW(2, 1, 1, 0, 52 , 64 , 0 , 0 , 0 , 0 ), // {ymm, xmm|m64|mem} + ROW(2, 1, 1, 0, 55 , 50 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 64 , 49 , 10 , 0 , 0 , 0 ), // #286 {xmm|m64|mem, xmm, i8|u8} + ROW(3, 1, 1, 0, 50 , 52 , 10 , 0 , 0 , 0 ), // #287 {xmm|m128|mem, ymm, i8|u8} + ROW(3, 1, 1, 0, 53 , 55 , 10 , 0 , 0 , 0 ), // #288 {ymm|m256|mem, zmm, i8|u8} + ROW(3, 1, 1, 0, 49 , 118, 49 , 0 , 0 , 0 ), // #289 {xmm, vm64x|vm64y, xmm} + ROW(2, 1, 1, 0, 49 , 118, 0 , 0 , 0 , 0 ), // {xmm, vm64x|vm64y} + ROW(2, 1, 1, 0, 52 , 76 , 0 , 0 , 0 , 0 ), // {ymm, vm64z} + ROW(3, 1, 1, 0, 49 , 50 , 10 , 0 , 0 , 0 ), // #292 {xmm, xmm|m128|mem, i8|u8} + ROW(3, 1, 1, 0, 52 , 53 , 10 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem, i8|u8} + ROW(3, 1, 1, 0, 55 , 56 , 10 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem, i8|u8} + ROW(2, 1, 1, 0, 49 , 64 , 0 , 0 , 0 , 0 ), // #295 {xmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 52 , 53 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} + ROW(2, 1, 1, 0, 55 , 56 , 0 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem} + ROW(4, 1, 1, 0, 86 , 86 , 49 , 50 , 0 , 0 ), // #298 {k, k, xmm, xmm|m128|mem} + ROW(4, 1, 1, 0, 86 , 86 , 52 , 53 , 0 , 0 ), // {k, k, ymm, ymm|m256|mem} + ROW(4, 1, 1, 0, 86 , 86 , 55 , 56 , 0 , 0 ), // {k, k, zmm, zmm|m512|mem} + ROW(3, 1, 1, 0, 115, 49 , 50 , 0 , 0 , 0 ), // #301 {xmm|k, xmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 116, 52 , 53 , 0 , 0 , 0 ), // {ymm|k, ymm, ymm|m256|mem} + ROW(3, 1, 1, 0, 86 , 55 , 56 , 0 , 0 , 0 ), // {k, zmm, zmm|m512|mem} + ROW(2, 1, 1, 0, 117, 49 , 0 , 0 , 0 , 0 ), // #304 {xmm|m32|mem, xmm} + ROW(2, 1, 1, 0, 64 , 52 , 0 , 0 , 0 , 0 ), // {xmm|m64|mem, ymm} + ROW(2, 1, 1, 0, 50 , 55 , 0 , 0 , 0 , 0 ), // {xmm|m128|mem, zmm} + ROW(2, 1, 1, 0, 64 , 49 , 0 , 0 , 0 , 0 ), // #307 {xmm|m64|mem, xmm} + ROW(2, 1, 1, 0, 50 , 52 , 0 , 0 , 0 , 0 ), // {xmm|m128|mem, ymm} + ROW(2, 1, 1, 0, 53 , 55 , 0 , 0 , 0 , 0 ), // {ymm|m256|mem, zmm} + ROW(2, 1, 1, 0, 119, 49 , 0 , 0 , 0 , 0 ), // #310 {xmm|m16|mem, xmm} + ROW(2, 1, 1, 0, 117, 52 , 0 , 0 , 0 , 0 ), // {xmm|m32|mem, ymm} + ROW(2, 1, 1, 0, 64 , 55 , 0 , 0 , 0 , 0 ), // {xmm|m64|mem, zmm} + ROW(2, 1, 1, 0, 49 , 119, 0 , 0 , 0 , 0 ), // #313 {xmm, xmm|m16|mem} + ROW(2, 1, 1, 0, 52 , 117, 0 , 0 , 0 , 0 ), // {ymm, xmm|m32|mem} + ROW(2, 1, 1, 0, 55 , 64 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 71 , 49 , 0 , 0 , 0 , 0 ), // #316 {vm32x, xmm} + ROW(2, 1, 1, 0, 72 , 52 , 0 , 0 , 0 , 0 ), // {vm32y, ymm} + ROW(2, 1, 1, 0, 73 , 55 , 0 , 0 , 0 , 0 ), // {vm32z, zmm} + ROW(2, 1, 1, 0, 74 , 49 , 0 , 0 , 0 , 0 ), // #319 {vm64x, xmm} + ROW(2, 1, 1, 0, 75 , 52 , 0 , 0 , 0 , 0 ), // {vm64y, ymm} + ROW(2, 1, 1, 0, 76 , 55 , 0 , 0 , 0 , 0 ), // {vm64z, zmm} + ROW(3, 1, 1, 0, 86 , 49 , 50 , 0 , 0 , 0 ), // #322 {k, xmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 86 , 52 , 53 , 0 , 0 , 0 ), // {k, ymm, ymm|m256|mem} + ROW(3, 1, 1, 0, 86 , 55 , 56 , 0 , 0 , 0 ), // {k, zmm, zmm|m512|mem} + ROW(3, 1, 1, 0, 6 , 6 , 28 , 0 , 0 , 0 ), // #325 {r32, r32, r32|m32|mem} + ROW(3, 0, 1, 0, 8 , 8 , 29 , 0 , 0 , 0 ), // {r64, r64, r64|m64|mem} + ROW(3, 1, 1, 0, 6 , 28 , 6 , 0 , 0 , 0 ), // #327 {r32, r32|m32|mem, r32} + ROW(3, 0, 1, 0, 8 , 29 , 8 , 0 , 0 , 0 ), // {r64, r64|m64|mem, r64} + ROW(2, 1, 0, 0, 120, 28 , 0 , 0 , 0 , 0 ), // #329 {bnd, r32|m32|mem} + ROW(2, 0, 1, 0, 120, 29 , 0 , 0 , 0 , 0 ), // {bnd, r64|m64|mem} + ROW(2, 1, 1, 0, 120, 121, 0 , 0 , 0 , 0 ), // #331 {bnd, bnd|mem} + ROW(2, 1, 1, 0, 122, 120, 0 , 0 , 0 , 0 ), // {mem, bnd} + ROW(2, 1, 0, 0, 4 , 30 , 0 , 0 , 0 , 0 ), // #333 {r16, m32|mem} + ROW(2, 1, 0, 0, 6 , 31 , 0 , 0 , 0 , 0 ), // {r32, m64|mem} + ROW(1, 1, 1, 0, 100, 0 , 0 , 0 , 0 , 0 ), // #335 {r16|r32} + ROW(1, 0, 1, 0, 8 , 0 , 0 , 0 , 0 , 0 ), // #336 {r64} + ROW(3, 1, 1, 0, 30 , 6 , 6 , 0 , 0 , 0 ), // #337 {m32|mem, r32, r32} + ROW(3, 0, 1, 0, 31 , 8 , 8 , 0 , 0 , 0 ), // {m64|mem, r64, r64} + ROW(2, 1, 1, 0, 6 , 32 , 0 , 0 , 0 , 0 ), // #339 {r32, r8lo|r8hi|m8|r16|m16|r32|m32} + ROW(2, 0, 1, 0, 8 , 123, 0 , 0 , 0 , 0 ), // {r64, r8lo|m8|r64|m64} + ROW(2, 1, 1, 0, 6 , 64 , 0 , 0 , 0 , 0 ), // #341 {r32, xmm|m64|mem} + ROW(2, 0, 1, 0, 8 , 64 , 0 , 0 , 0 , 0 ), // {r64, xmm|m64|mem} + ROW(2, 1, 1, 0, 49 , 28 , 0 , 0 , 0 , 0 ), // #343 {xmm, r32|m32|mem} + ROW(2, 0, 1, 0, 49 , 29 , 0 , 0 , 0 , 0 ), // {xmm, r64|m64|mem} + ROW(2, 0, 1, 0, 49 , 29 , 0 , 0 , 0 , 0 ), // #345 {xmm, r64|m64|mem} + ROW(2, 1, 1, 0, 49 , 28 , 0 , 0 , 0 , 0 ), // {xmm, r32|m32|mem} + ROW(2, 1, 1, 0, 6 , 117, 0 , 0 , 0 , 0 ), // #347 {r32, xmm|m32|mem} + ROW(2, 0, 1, 0, 8 , 117, 0 , 0 , 0 , 0 ), // {r64, xmm|m32|mem} + ROW(2, 0, 1, 0, 8 , 117, 0 , 0 , 0 , 0 ), // #349 {r64, xmm|m32|mem} + ROW(2, 1, 1, 0, 6 , 117, 0 , 0 , 0 , 0 ), // {r32, xmm|m32|mem} + ROW(2, 1, 0, 0, 124, 57 , 0 , 0 , 0 , 0 ), // #351 {es:[mem|m512|memBase], m512|mem} + ROW(2, 0, 1, 0, 124, 57 , 0 , 0 , 0 , 0 ), // {es:[mem|m512|memBase], m512|mem} + ROW(3, 1, 1, 0, 49 , 10 , 10 , 0 , 0 , 0 ), // #353 {xmm, i8|u8, i8|u8} + ROW(2, 1, 1, 0, 49 , 49 , 0 , 0 , 0 , 0 ), // #354 {xmm, xmm} + ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #355 {} + ROW(1, 1, 1, 0, 103, 0 , 0 , 0 , 0 , 0 ), // #356 {st} + ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #357 {} + ROW(1, 1, 1, 0, 125, 0 , 0 , 0 , 0 , 0 ), // #358 {m32|m64|st} + ROW(2, 1, 1, 0, 49 , 49 , 0 , 0 , 0 , 0 ), // #359 {xmm, xmm} + ROW(4, 1, 1, 0, 49 , 49 , 10 , 10 , 0 , 0 ), // {xmm, xmm, i8|u8, i8|u8} + ROW(2, 1, 0, 0, 6 , 51 , 0 , 0 , 0 , 0 ), // #361 {r32, m128|mem} + ROW(2, 0, 1, 0, 8 , 51 , 0 , 0 , 0 , 0 ), // {r64, m128|mem} + ROW(2, 1, 0, 2, 39 , 126, 0 , 0 , 0 , 0 ), // #363 {<eax>, <ecx>} + ROW(2, 0, 1, 2, 127, 126, 0 , 0 , 0 , 0 ), // {<eax|rax>, <ecx>} + ROW(3, 1, 0, 3, 39 , 38 , 126, 0 , 0 , 0 ), // #365 {<eax>, <edx>, <ecx>} + ROW(3, 0, 1, 3, 127, 38 , 126, 0 , 0 , 0 ), // {<eax|rax>, <edx>, <ecx>} + ROW(2, 1, 0, 1, 128, 129, 0 , 0 , 0 , 0 ), // #367 {<cx|ecx>, rel8} + ROW(2, 0, 1, 1, 130, 129, 0 , 0 , 0 , 0 ), // {<ecx|rcx>, rel8} + ROW(2, 1, 1, 0, 86 , 131, 0 , 0 , 0 , 0 ), // #369 {k, k|m8|mem|r32} + ROW(2, 1, 1, 0, 132, 86 , 0 , 0 , 0 , 0 ), // {m8|mem|r32, k} + ROW(2, 1, 1, 0, 86 , 133, 0 , 0 , 0 , 0 ), // #371 {k, k|m32|mem|r32} + ROW(2, 1, 1, 0, 28 , 86 , 0 , 0 , 0 , 0 ), // {m32|mem|r32, k} + ROW(2, 1, 1, 0, 86 , 134, 0 , 0 , 0 , 0 ), // #373 {k, k|m16|mem|r32} + ROW(2, 1, 1, 0, 111, 86 , 0 , 0 , 0 , 0 ), // {m16|mem|r32, k} + ROW(2, 1, 0, 0, 4 , 30 , 0 , 0 , 0 , 0 ), // #375 {r16, m32|mem} + ROW(2, 1, 0, 0, 6 , 110, 0 , 0 , 0 , 0 ), // {r32, m48|mem} + ROW(2, 1, 1, 0, 100, 135, 0 , 0 , 0 , 0 ), // #377 {r16|r32, mem|m8|m16|m32|m48|m64|m80|m128|m256|m512|m1024} + ROW(2, 0, 1, 0, 8 , 135, 0 , 0 , 0 , 0 ), // {r64, mem|m8|m16|m32|m48|m64|m80|m128|m256|m512|m1024} + ROW(1, 1, 1, 0, 6 , 0 , 0 , 0 , 0 , 0 ), // #379 {r32} + ROW(1, 0, 1, 0, 8 , 0 , 0 , 0 , 0 , 0 ), // {r64} + ROW(3, 1, 1, 0, 6 , 28 , 14 , 0 , 0 , 0 ), // #381 {r32, r32|m32|mem, i32|u32} + ROW(3, 0, 1, 0, 8 , 28 , 14 , 0 , 0 , 0 ), // {r64, r32|m32|mem, i32|u32} + ROW(2, 1, 1, 0, 63 , 28 , 0 , 0 , 0 , 0 ), // #383 {mm|xmm, r32|m32|mem} + ROW(2, 1, 1, 0, 28 , 63 , 0 , 0 , 0 , 0 ), // {r32|m32|mem, mm|xmm} + ROW(2, 1, 1, 0, 124, 57 , 0 , 0 , 0 , 0 ), // #385 {es:[mem|m512|memBase], m512|mem} + ROW(2, 1, 1, 0, 124, 57 , 0 , 0 , 0 , 0 ), // {es:[mem|m512|memBase], m512|mem} + ROW(2, 1, 1, 0, 49 , 64 , 0 , 0 , 0 , 0 ), // #387 {xmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 31 , 49 , 0 , 0 , 0 , 0 ), // {m64|mem, xmm} + ROW(2, 1, 1, 0, 49 , 117, 0 , 0 , 0 , 0 ), // #389 {xmm, xmm|m32|mem} + ROW(2, 1, 1, 0, 30 , 49 , 0 , 0 , 0 , 0 ), // {m32|mem, xmm} + ROW(2, 0, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #391 {r16, r16|m16|mem} + ROW(2, 0, 1, 0, 136, 28 , 0 , 0 , 0 , 0 ), // {r32|r64, r32|m32|mem} + ROW(4, 1, 1, 1, 6 , 6 , 28 , 38 , 0 , 0 ), // #393 {r32, r32, r32|m32|mem, <edx>} + ROW(4, 0, 1, 1, 8 , 8 , 29 , 40 , 0 , 0 ), // {r64, r64, r64|m64|mem, <rdx>} + ROW(2, 1, 1, 0, 61 , 62 , 0 , 0 , 0 , 0 ), // #395 {mm, mm|m64|mem} + ROW(2, 1, 1, 0, 49 , 50 , 0 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 61 , 62 , 10 , 0 , 0 , 0 ), // #397 {mm, mm|m64|mem, i8|u8} + ROW(3, 1, 1, 0, 49 , 50 , 10 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem, i8|u8} + ROW(3, 1, 1, 0, 6 , 63 , 10 , 0 , 0 , 0 ), // #399 {r32, mm|xmm, i8|u8} + ROW(3, 1, 1, 0, 21 , 49 , 10 , 0 , 0 , 0 ), // {m16|mem, xmm, i8|u8} + ROW(2, 1, 1, 0, 61 , 137, 0 , 0 , 0 , 0 ), // #401 {mm, i8|u8|mm|m64|mem} + ROW(2, 1, 1, 0, 49 , 58 , 0 , 0 , 0 , 0 ), // {xmm, i8|u8|xmm|m128|mem} + ROW(1, 1, 1, 0, 28 , 0 , 0 , 0 , 0 , 0 ), // #403 {r32|m32|mem} + ROW(1, 0, 1, 0, 29 , 0 , 0 , 0 , 0 , 0 ), // {r64|m64|mem} + ROW(2, 1, 1, 0, 61 , 138, 0 , 0 , 0 , 0 ), // #405 {mm, mm|m32|mem} + ROW(2, 1, 1, 0, 49 , 50 , 0 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem} + ROW(2, 1, 1, 0, 32 , 114, 0 , 0 , 0 , 0 ), // #407 {r8lo|r8hi|m8|r16|m16|r32|m32, cl|i8|u8} + ROW(2, 0, 1, 0, 15 , 114, 0 , 0 , 0 , 0 ), // {r64|m64, cl|i8|u8} + ROW(1, 1, 0, 0, 6 , 0 , 0 , 0 , 0 , 0 ), // #409 {r32} + ROW(1, 0, 1, 0, 8 , 0 , 0 , 0 , 0 , 0 ), // {r64} + ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #411 {} + ROW(1, 1, 1, 0, 139, 0 , 0 , 0 , 0 , 0 ), // {u16} + ROW(3, 1, 1, 0, 6 , 28 , 10 , 0 , 0 , 0 ), // #413 {r32, r32|m32|mem, i8|u8} + ROW(3, 0, 1, 0, 8 , 29 , 10 , 0 , 0 , 0 ), // {r64, r64|m64|mem, i8|u8} + ROW(1, 1, 1, 0, 140, 0 , 0 , 0 , 0 , 0 ), // #415 {r16|m16|mem|r32} + ROW(1, 0, 1, 0, 141, 0 , 0 , 0 , 0 , 0 ), // {r64|m16|mem} + ROW(1, 1, 0, 0, 142, 0 , 0 , 0 , 0 , 0 ), // #417 {ds:[mem|memBase]} + ROW(1, 0, 1, 0, 142, 0 , 0 , 0 , 0 , 0 ), // {ds:[mem|memBase]} + ROW(4, 1, 1, 0, 49 , 49 , 50 , 49 , 0 , 0 ), // #419 {xmm, xmm, xmm|m128|mem, xmm} + ROW(4, 1, 1, 0, 52 , 52 , 53 , 52 , 0 , 0 ), // {ymm, ymm, ymm|m256|mem, ymm} + ROW(2, 1, 1, 0, 49 , 143, 0 , 0 , 0 , 0 ), // #421 {xmm, xmm|m128|ymm|m256} + ROW(2, 1, 1, 0, 52 , 56 , 0 , 0 , 0 , 0 ), // {ymm, zmm|m512|mem} + ROW(2, 1, 1, 0, 6 , 119, 0 , 0 , 0 , 0 ), // #423 {r32, xmm|m16|mem} + ROW(2, 0, 1, 0, 8 , 119, 0 , 0 , 0 , 0 ), // {r64, xmm|m16|mem} + ROW(3, 1, 1, 0, 49 , 49 , 28 , 0 , 0 , 0 ), // #425 {xmm, xmm, r32|m32|mem} + ROW(3, 0, 1, 0, 49 , 49 , 29 , 0 , 0 , 0 ), // {xmm, xmm, r64|m64|mem} + ROW(3, 1, 1, 0, 49 , 49 , 13 , 0 , 0 , 0 ), // #427 {xmm, xmm, r32|m32} + ROW(3, 0, 1, 0, 49 , 49 , 15 , 0 , 0 , 0 ), // {xmm, xmm, r64|m64} + ROW(4, 1, 1, 0, 49 , 49 , 49 , 64 , 0 , 0 ), // #429 {xmm, xmm, xmm, xmm|m64|mem} + ROW(4, 1, 1, 0, 49 , 49 , 31 , 49 , 0 , 0 ), // {xmm, xmm, m64|mem, xmm} + ROW(4, 1, 1, 0, 49 , 49 , 49 , 117, 0 , 0 ), // #431 {xmm, xmm, xmm, xmm|m32|mem} + ROW(4, 1, 1, 0, 49 , 49 , 30 , 49 , 0 , 0 ), // {xmm, xmm, m32|mem, xmm} + ROW(4, 1, 1, 0, 52 , 52 , 50 , 10 , 0 , 0 ), // #433 {ymm, ymm, xmm|m128|mem, i8|u8} + ROW(4, 1, 1, 0, 55 , 55 , 50 , 10 , 0 , 0 ), // {zmm, zmm, xmm|m128|mem, i8|u8} + ROW(1, 1, 0, 1, 39 , 0 , 0 , 0 , 0 , 0 ), // #435 {<eax>} + ROW(1, 0, 1, 1, 41 , 0 , 0 , 0 , 0 , 0 ), // #436 {<rax>} + ROW(2, 1, 1, 0, 28 , 49 , 0 , 0 , 0 , 0 ), // #437 {r32|m32|mem, xmm} + ROW(2, 1, 1, 0, 49 , 28 , 0 , 0 , 0 , 0 ), // {xmm, r32|m32|mem} + ROW(2, 1, 1, 0, 111, 49 , 0 , 0 , 0 , 0 ), // #439 {r32|m16|mem, xmm} + ROW(2, 1, 1, 0, 49 , 111, 0 , 0 , 0 , 0 ), // {xmm, r32|m16|mem} + ROW(2, 1, 0, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // #441 {r32|m32|mem, r32} + ROW(2, 0, 1, 0, 29 , 8 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, r64} + ROW(2, 1, 0, 0, 6 , 28 , 0 , 0 , 0 , 0 ), // #443 {r32, r32|m32|mem} + ROW(2, 0, 1, 0, 8 , 29 , 0 , 0 , 0 , 0 ), // {r64, r64|m64|mem} + ROW(2, 1, 1, 0, 144, 64 , 0 , 0 , 0 , 0 ), // #445 {xmm|ymm|zmm, xmm|m64|mem} + ROW(2, 0, 1, 0, 144, 8 , 0 , 0 , 0 , 0 ), // {xmm|ymm|zmm, r64} + ROW(3, 1, 1, 0, 49 , 49 , 58 , 0 , 0 , 0 ), // #447 {xmm, xmm, xmm|m128|mem|i8|u8} + ROW(3, 1, 1, 0, 49 , 51 , 145, 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8|xmm} + ROW(2, 1, 1, 0, 71 , 96 , 0 , 0 , 0 , 0 ), // #449 {vm32x, xmm|ymm} + ROW(2, 1, 1, 0, 72 , 55 , 0 , 0 , 0 , 0 ), // {vm32y, zmm} + ROW(2, 1, 1, 0, 118, 49 , 0 , 0 , 0 , 0 ), // #451 {vm64x|vm64y, xmm} + ROW(2, 1, 1, 0, 76 , 52 , 0 , 0 , 0 , 0 ), // {vm64z, ymm} + ROW(3, 1, 1, 0, 49 , 49 , 50 , 0 , 0 , 0 ), // #453 {xmm, xmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 49 , 51 , 49 , 0 , 0 , 0 ), // {xmm, m128|mem, xmm} + ROW(1, 1, 0, 1, 36 , 0 , 0 , 0 , 0 , 0 ), // #455 {<ax>} + ROW(2, 1, 0, 1, 36 , 10 , 0 , 0 , 0 , 0 ), // #456 {<ax>, i8|u8} + ROW(2, 1, 0, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // #457 {r16|m16|mem, r16} + ROW(3, 1, 1, 1, 49 , 50 , 146, 0 , 0 , 0 ), // #458 {xmm, xmm|m128|mem, <xmm0>} + ROW(2, 1, 1, 0, 120, 147, 0 , 0 , 0 , 0 ), // #459 {bnd, mib} + ROW(2, 1, 1, 0, 120, 122, 0 , 0 , 0 , 0 ), // #460 {bnd, mem} + ROW(2, 1, 1, 0, 147, 120, 0 , 0 , 0 , 0 ), // #461 {mib, bnd} + ROW(1, 1, 1, 1, 36 , 0 , 0 , 0 , 0 , 0 ), // #462 {<ax>} + ROW(2, 1, 1, 2, 38 , 39 , 0 , 0 , 0 , 0 ), // #463 {<edx>, <eax>} + ROW(1, 1, 1, 0, 122, 0 , 0 , 0 , 0 , 0 ), // #464 {mem} + ROW(1, 1, 1, 0, 31 , 0 , 0 , 0 , 0 , 0 ), // #465 {m64|mem} + ROW(0, 0, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #466 {} + ROW(1, 1, 1, 1, 148, 0 , 0 , 0 , 0 , 0 ), // #467 {<ds:[mem|m512|memBase|zax]>} + ROW(3, 1, 1, 0, 49 , 64 , 10 , 0 , 0 , 0 ), // #468 {xmm, xmm|m64|mem, i8|u8} + ROW(3, 1, 1, 0, 49 , 117, 10 , 0 , 0 , 0 ), // #469 {xmm, xmm|m32|mem, i8|u8} + ROW(5, 0, 1, 4, 51 , 40 , 41 , 149, 150, 0 ), // #470 {m128|mem, <rdx>, <rax>, <rcx>, <rbx>} + ROW(5, 1, 1, 4, 31 , 38 , 39 , 126, 151, 0 ), // #471 {m64|mem, <edx>, <eax>, <ecx>, <ebx>} + ROW(4, 1, 1, 4, 39 , 151, 126, 38 , 0 , 0 ), // #472 {<eax>, <ebx>, <ecx>, <edx>} + ROW(2, 0, 1, 2, 40 , 41 , 0 , 0 , 0 , 0 ), // #473 {<rdx>, <rax>} + ROW(2, 1, 1, 0, 61 , 50 , 0 , 0 , 0 , 0 ), // #474 {mm, xmm|m128|mem} + ROW(2, 1, 1, 0, 49 , 62 , 0 , 0 , 0 , 0 ), // #475 {xmm, mm|m64|mem} + ROW(2, 1, 1, 0, 61 , 64 , 0 , 0 , 0 , 0 ), // #476 {mm, xmm|m64|mem} + ROW(2, 1, 1, 2, 37 , 36 , 0 , 0 , 0 , 0 ), // #477 {<dx>, <ax>} + ROW(1, 1, 1, 1, 39 , 0 , 0 , 0 , 0 , 0 ), // #478 {<eax>} + ROW(2, 1, 1, 0, 12 , 10 , 0 , 0 , 0 , 0 ), // #479 {i16|u16, i8|u8} + ROW(3, 1, 1, 0, 28 , 49 , 10 , 0 , 0 , 0 ), // #480 {r32|m32|mem, xmm, i8|u8} + ROW(1, 1, 1, 0, 109, 0 , 0 , 0 , 0 , 0 ), // #481 {m80|mem} + ROW(1, 1, 1, 0, 152, 0 , 0 , 0 , 0 , 0 ), // #482 {m16|m32} + ROW(1, 1, 1, 0, 153, 0 , 0 , 0 , 0 , 0 ), // #483 {m16|m32|m64} + ROW(1, 1, 1, 0, 154, 0 , 0 , 0 , 0 , 0 ), // #484 {m32|m64|m80|st} + ROW(1, 1, 1, 0, 21 , 0 , 0 , 0 , 0 , 0 ), // #485 {m16|mem} + ROW(1, 1, 1, 0, 155, 0 , 0 , 0 , 0 , 0 ), // #486 {ax|m16|mem} + ROW(1, 0, 1, 0, 122, 0 , 0 , 0 , 0 , 0 ), // #487 {mem} + ROW(2, 1, 1, 1, 10 , 39 , 0 , 0 , 0 , 0 ), // #488 {i8|u8, <eax>} + ROW(2, 1, 1, 0, 156, 157, 0 , 0 , 0 , 0 ), // #489 {al|ax|eax, i8|u8|dx} + ROW(2, 1, 1, 0, 158, 159, 0 , 0 , 0 , 0 ), // #490 {es:[memBase|zdi|m8|m16|m32], dx} + ROW(1, 1, 1, 0, 10 , 0 , 0 , 0 , 0 , 0 ), // #491 {i8|u8} + ROW(0, 1, 0, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #492 {} + ROW(3, 1, 1, 0, 86 , 86 , 86 , 0 , 0 , 0 ), // #493 {k, k, k} + ROW(2, 1, 1, 0, 86 , 86 , 0 , 0 , 0 , 0 ), // #494 {k, k} + ROW(3, 1, 1, 0, 86 , 86 , 10 , 0 , 0 , 0 ), // #495 {k, k, i8|u8} + ROW(1, 1, 1, 1, 160, 0 , 0 , 0 , 0 , 0 ), // #496 {<ah>} + ROW(1, 1, 1, 0, 30 , 0 , 0 , 0 , 0 , 0 ), // #497 {m32|mem} + ROW(1, 0, 1, 0, 57 , 0 , 0 , 0 , 0 , 0 ), // #498 {m512|mem} + ROW(1, 1, 1, 0, 27 , 0 , 0 , 0 , 0 , 0 ), // #499 {r16|m16|mem} + ROW(3, 1, 1, 1, 49 , 49 , 161, 0 , 0 , 0 ), // #500 {xmm, xmm, <ds:[mem|m128|memBase|zdi]>} + ROW(3, 1, 1, 1, 61 , 61 , 162, 0 , 0 , 0 ), // #501 {mm, mm, <ds:[mem|m64|memBase|zdi]>} + ROW(3, 1, 1, 3, 163, 126, 38 , 0 , 0 , 0 ), // #502 {<ds:[mem|memBase|zax]>, <ecx>, <edx>} + ROW(2, 1, 1, 0, 61 , 49 , 0 , 0 , 0 , 0 ), // #503 {mm, xmm} + ROW(2, 1, 1, 0, 6 , 49 , 0 , 0 , 0 , 0 ), // #504 {r32, xmm} + ROW(2, 1, 1, 0, 31 , 61 , 0 , 0 , 0 , 0 ), // #505 {m64|mem, mm} + ROW(2, 1, 1, 0, 49 , 61 , 0 , 0 , 0 , 0 ), // #506 {xmm, mm} + ROW(2, 1, 1, 2, 39 , 126, 0 , 0 , 0 , 0 ), // #507 {<eax>, <ecx>} + ROW(3, 1, 1, 3, 39 , 126, 151, 0 , 0 , 0 ), // #508 {<eax>, <ecx>, <ebx>} + ROW(2, 1, 1, 0, 164, 156, 0 , 0 , 0 , 0 ), // #509 {u8|dx, al|ax|eax} + ROW(2, 1, 1, 0, 159, 165, 0 , 0 , 0 , 0 ), // #510 {dx, ds:[memBase|zsi|m8|m16|m32]} + ROW(6, 1, 1, 3, 49 , 50 , 10 , 126, 39 , 38 ), // #511 {xmm, xmm|m128|mem, i8|u8, <ecx>, <eax>, <edx>} + ROW(6, 1, 1, 3, 49 , 50 , 10 , 146, 39 , 38 ), // #512 {xmm, xmm|m128|mem, i8|u8, <xmm0>, <eax>, <edx>} + ROW(4, 1, 1, 1, 49 , 50 , 10 , 126, 0 , 0 ), // #513 {xmm, xmm|m128|mem, i8|u8, <ecx>} + ROW(4, 1, 1, 1, 49 , 50 , 10 , 146, 0 , 0 ), // #514 {xmm, xmm|m128|mem, i8|u8, <xmm0>} + ROW(3, 1, 1, 0, 132, 49 , 10 , 0 , 0 , 0 ), // #515 {r32|m8|mem, xmm, i8|u8} + ROW(3, 0, 1, 0, 29 , 49 , 10 , 0 , 0 , 0 ), // #516 {r64|m64|mem, xmm, i8|u8} + ROW(3, 1, 1, 0, 49 , 132, 10 , 0 , 0 , 0 ), // #517 {xmm, r32|m8|mem, i8|u8} + ROW(3, 1, 1, 0, 49 , 28 , 10 , 0 , 0 , 0 ), // #518 {xmm, r32|m32|mem, i8|u8} + ROW(3, 0, 1, 0, 49 , 29 , 10 , 0 , 0 , 0 ), // #519 {xmm, r64|m64|mem, i8|u8} + ROW(3, 1, 1, 0, 63 , 111, 10 , 0 , 0 , 0 ), // #520 {mm|xmm, r32|m16|mem, i8|u8} + ROW(2, 1, 1, 0, 6 , 63 , 0 , 0 , 0 , 0 ), // #521 {r32, mm|xmm} + ROW(2, 1, 1, 0, 49 , 10 , 0 , 0 , 0 , 0 ), // #522 {xmm, i8|u8} + ROW(1, 0, 1, 0, 136, 0 , 0 , 0 , 0 , 0 ), // #523 {r32|r64} + ROW(3, 1, 1, 3, 38 , 39 , 126, 0 , 0 , 0 ), // #524 {<edx>, <eax>, <ecx>} + ROW(1, 1, 1, 0, 1 , 0 , 0 , 0 , 0 , 0 ), // #525 {r8lo|r8hi|m8|mem} + ROW(3, 0, 1, 0, 166, 166, 166, 0 , 0 , 0 ), // #526 {tmm, tmm, tmm} + ROW(2, 0, 1, 0, 166, 167, 0 , 0 , 0 , 0 ), // #527 {tmm, tmem} + ROW(2, 0, 1, 0, 167, 166, 0 , 0 , 0 , 0 ), // #528 {tmem, tmm} + ROW(1, 0, 1, 0, 166, 0 , 0 , 0 , 0 , 0 ), // #529 {tmm} + ROW(3, 1, 1, 2, 6 , 38 , 39 , 0 , 0 , 0 ), // #530 {r32, <edx>, <eax>} + ROW(6, 1, 1, 0, 55 , 55 , 55 , 55 , 55 , 51 ), // #531 {zmm, zmm, zmm, zmm, zmm, m128|mem} + ROW(6, 1, 1, 0, 49 , 49 , 49 , 49 , 49 , 51 ), // #532 {xmm, xmm, xmm, xmm, xmm, m128|mem} + ROW(3, 1, 1, 0, 49 , 49 , 64 , 0 , 0 , 0 ), // #533 {xmm, xmm, xmm|m64|mem} + ROW(3, 1, 1, 0, 49 , 49 , 119, 0 , 0 , 0 ), // #534 {xmm, xmm, xmm|m16|mem} + ROW(3, 1, 1, 0, 49 , 49 , 117, 0 , 0 , 0 ), // #535 {xmm, xmm, xmm|m32|mem} + ROW(2, 1, 1, 0, 96 , 21 , 0 , 0 , 0 , 0 ), // #536 {xmm|ymm, m16|mem} + ROW(2, 1, 1, 0, 52 , 51 , 0 , 0 , 0 , 0 ), // #537 {ymm, m128|mem} + ROW(2, 1, 1, 0, 168, 64 , 0 , 0 , 0 , 0 ), // #538 {ymm|zmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 168, 51 , 0 , 0 , 0 , 0 ), // #539 {ymm|zmm, m128|mem} + ROW(2, 1, 1, 0, 55 , 54 , 0 , 0 , 0 , 0 ), // #540 {zmm, m256|mem} + ROW(2, 1, 1, 0, 144, 117, 0 , 0 , 0 , 0 ), // #541 {xmm|ymm|zmm, m32|mem|xmm} + ROW(4, 1, 1, 0, 115, 49 , 64 , 10 , 0 , 0 ), // #542 {xmm|k, xmm, xmm|m64|mem, i8|u8} + ROW(4, 1, 1, 0, 86 , 49 , 119, 10 , 0 , 0 ), // #543 {k, xmm, xmm|m16|mem, i8|u8} + ROW(4, 1, 1, 0, 115, 49 , 117, 10 , 0 , 0 ), // #544 {xmm|k, xmm, xmm|m32|mem, i8|u8} + ROW(2, 1, 1, 0, 49 , 169, 0 , 0 , 0 , 0 ), // #545 {xmm, xmm|m128|ymm|m256|zmm|m512} + ROW(3, 1, 1, 0, 50 , 168, 10 , 0 , 0 , 0 ), // #546 {xmm|m128|mem, ymm|zmm, i8|u8} + ROW(4, 1, 1, 0, 49 , 49 , 64 , 10 , 0 , 0 ), // #547 {xmm, xmm, xmm|m64|mem, i8|u8} + ROW(4, 1, 1, 0, 49 , 49 , 117, 10 , 0 , 0 ), // #548 {xmm, xmm, xmm|m32|mem, i8|u8} + ROW(3, 1, 1, 0, 86 , 169, 10 , 0 , 0 , 0 ), // #549 {k, xmm|m128|ymm|m256|zmm|m512, i8|u8} + ROW(3, 1, 1, 0, 86 , 64 , 10 , 0 , 0 , 0 ), // #550 {k, xmm|m64|mem, i8|u8} + ROW(3, 1, 1, 0, 86 , 119, 10 , 0 , 0 , 0 ), // #551 {k, xmm|m16|mem, i8|u8} + ROW(3, 1, 1, 0, 86 , 117, 10 , 0 , 0 , 0 ), // #552 {k, xmm|m32|mem, i8|u8} + ROW(1, 1, 1, 0, 72 , 0 , 0 , 0 , 0 , 0 ), // #553 {vm32y} + ROW(1, 1, 1, 0, 73 , 0 , 0 , 0 , 0 , 0 ), // #554 {vm32z} + ROW(1, 1, 1, 0, 76 , 0 , 0 , 0 , 0 , 0 ), // #555 {vm64z} + ROW(4, 1, 1, 0, 49 , 49 , 119, 10 , 0 , 0 ), // #556 {xmm, xmm, xmm|m16|mem, i8|u8} + ROW(4, 1, 1, 0, 55 , 55 , 53 , 10 , 0 , 0 ), // #557 {zmm, zmm, ymm|m256|mem, i8|u8} + ROW(2, 1, 1, 0, 6 , 96 , 0 , 0 , 0 , 0 ), // #558 {r32, xmm|ymm} + ROW(2, 1, 1, 0, 144, 170, 0 , 0 , 0 , 0 ), // #559 {xmm|ymm|zmm, xmm|m8|mem|r32} + ROW(2, 1, 1, 0, 144, 171, 0 , 0 , 0 , 0 ), // #560 {xmm|ymm|zmm, xmm|m32|mem|r32} + ROW(2, 1, 1, 0, 144, 86 , 0 , 0 , 0 , 0 ), // #561 {xmm|ymm|zmm, k} + ROW(2, 1, 1, 0, 144, 172, 0 , 0 , 0 , 0 ), // #562 {xmm|ymm|zmm, xmm|m16|mem|r32} + ROW(3, 1, 1, 0, 111, 49 , 10 , 0 , 0 , 0 ), // #563 {r32|m16|mem, xmm, i8|u8} + ROW(4, 1, 1, 0, 49 , 49 , 132, 10 , 0 , 0 ), // #564 {xmm, xmm, r32|m8|mem, i8|u8} + ROW(4, 1, 1, 0, 49 , 49 , 28 , 10 , 0 , 0 ), // #565 {xmm, xmm, r32|m32|mem, i8|u8} + ROW(4, 0, 1, 0, 49 , 49 , 29 , 10 , 0 , 0 ), // #566 {xmm, xmm, r64|m64|mem, i8|u8} + ROW(4, 1, 1, 0, 49 , 49 , 111, 10 , 0 , 0 ), // #567 {xmm, xmm, r32|m16|mem, i8|u8} + ROW(2, 1, 1, 0, 86 , 144, 0 , 0 , 0 , 0 ), // #568 {k, xmm|ymm|zmm} + ROW(2, 1, 1, 0, 52 , 49 , 0 , 0 , 0 , 0 ), // #569 {ymm, xmm} + ROW(2, 1, 1, 0, 52 , 52 , 0 , 0 , 0 , 0 ), // #570 {ymm, ymm} + ROW(3, 1, 1, 0, 52 , 52 , 49 , 0 , 0 , 0 ), // #571 {ymm, ymm, xmm} + ROW(3, 1, 1, 2, 122, 38 , 39 , 0 , 0 , 0 ), // #572 {mem, <edx>, <eax>} + ROW(3, 0, 1, 2, 122, 38 , 39 , 0 , 0 , 0 ) // #573 {mem, <edx>, <eax>} }; #undef ROW @@ -3584,7 +5317,7 @@ const InstDB::OpSignature InstDB::_opSignatureTable[] = { ROW(F(ImmI16) | F(ImmU16), 0x00), ROW(F(RegGpd) | F(Mem32), 0x00), ROW(F(ImmI32) | F(ImmU32), 0x00), - ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegGpq) | F(Mem64), 0x00), ROW(F(ImmI32), 0x00), ROW(F(RegSReg) | F(RegCReg) | F(RegDReg) | F(MemUnspecified) | F(Mem64) | F(ImmI64) | F(ImmU64), 0x00), ROW(F(MemUnspecified) | F(Mem8), 0x00), @@ -3593,27 +5326,26 @@ const InstDB::OpSignature InstDB::_opSignatureTable[] = { ROW(F(MemUnspecified) | F(Mem16), 0x00), ROW(F(RegSReg), 0x00), ROW(F(RegCReg) | F(RegDReg), 0x00), - ROW(F(RegGpq) | F(ImmI32), 0x00), - ROW(F(RegGpw) | F(RegGpd) | F(RegGpq) | F(MemUnspecified) | F(Mem16) | F(Mem32) | F(Mem64), 0x00), + ROW(F(ImmI8) | F(ImmI32), 0x00), + ROW(F(RegGpw) | F(RegGpd) | F(Mem16) | F(Mem32), 0x00), ROW(F(ImmI8), 0x00), ROW(F(RegGpw) | F(MemUnspecified) | F(Mem16), 0x00), ROW(F(RegGpd) | F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64), 0x00), ROW(F(MemUnspecified) | F(Mem32), 0x00), ROW(F(MemUnspecified) | F(Mem64), 0x00), - ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpw) | F(RegGpd) | F(RegGpq) | F(MemUnspecified) | F(Mem8) | F(Mem16) | F(Mem32) | F(Mem64), 0x00), - ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI32) | F(ImmU32), 0x00), + ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpw) | F(RegGpd) | F(Mem8) | F(Mem16) | F(Mem32), 0x00), + ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI8) | F(ImmU8) | F(ImmI32) | F(ImmU32), 0x00), + ROW(F(Mem64), 0x00), + ROW(F(ImmI8) | F(ImmU8) | F(ImmI32), 0x00), ROW(F(RegGpw) | F(FlagImplicit), 0x01), ROW(F(RegGpw) | F(FlagImplicit), 0x04), ROW(F(RegGpd) | F(FlagImplicit), 0x04), ROW(F(RegGpd) | F(FlagImplicit), 0x01), ROW(F(RegGpq) | F(FlagImplicit), 0x04), ROW(F(RegGpq) | F(FlagImplicit), 0x01), - ROW(F(RegGpw) | F(MemUnspecified) | F(Mem16) | F(ImmI8) | F(ImmI16), 0x00), - ROW(F(RegGpd) | F(MemUnspecified) | F(Mem32) | F(ImmI8) | F(ImmI32), 0x00), - ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI8) | F(ImmI32), 0x00), ROW(F(ImmI8) | F(ImmI16) | F(ImmU16), 0x00), ROW(F(ImmI8) | F(ImmI32) | F(ImmU32), 0x00), - ROW(F(ImmI8) | F(ImmI32), 0x00), ROW(F(ImmI64) | F(ImmU64), 0x00), ROW(F(RegGpbLo), 0x01), ROW(F(RegGpw), 0x01), @@ -3632,99 +5364,96 @@ const InstDB::OpSignature InstDB::_opSignatureTable[] = { ROW(F(RegYmm) | F(MemUnspecified) | F(Mem256) | F(ImmI8) | F(ImmU8), 0x00), ROW(F(RegZmm) | F(MemUnspecified) | F(Mem512) | F(ImmI8) | F(ImmU8), 0x00), ROW(F(RegMm), 0x00), - ROW(F(RegGpq) | F(RegMm) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegMm) | F(MemUnspecified) | F(Mem64), 0x00), ROW(F(RegXmm) | F(RegMm), 0x00), ROW(F(RegXmm) | F(MemUnspecified) | F(Mem64), 0x00), - ROW(F(RegGpw) | F(RegGpd) | F(RegGpq) | F(Mem16) | F(Mem32) | F(Mem64), 0x00), + ROW(F(RegSReg), 0x1A), + ROW(F(RegSReg), 0x60), + ROW(F(RegGpw) | F(Mem16) | F(ImmI8) | F(ImmI16), 0x00), + ROW(F(RegGpd) | F(Mem32) | F(ImmI32) | F(ImmU32), 0x00), + ROW(F(RegGpq) | F(Mem64) | F(ImmI32), 0x00), + ROW(F(RegSReg), 0x1E), ROW(F(Vm32x), 0x00), ROW(F(Vm32y), 0x00), ROW(F(Vm32z), 0x00), ROW(F(Vm64x), 0x00), ROW(F(Vm64y), 0x00), ROW(F(Vm64z), 0x00), - ROW(F(Mem8) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), - ROW(F(Mem8) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), - ROW(F(Mem16) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), - ROW(F(Mem16) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), - ROW(F(Mem32) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), - ROW(F(Mem32) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), - ROW(F(Mem64) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), - ROW(F(Mem64) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(Mem8) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(Mem8) | F(FlagMemBase) | F(FlagMemEs), 0x80), + ROW(F(Mem16) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(Mem16) | F(FlagMemBase) | F(FlagMemEs), 0x80), + ROW(F(Mem32) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(Mem32) | F(FlagMemBase) | F(FlagMemEs), 0x80), + ROW(F(Mem64) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(Mem64) | F(FlagMemBase) | F(FlagMemEs), 0x80), ROW(F(RegGpbLo) | F(FlagImplicit), 0x01), - ROW(F(MemUnspecified) | F(Mem8) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), - ROW(F(MemUnspecified) | F(Mem16) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), - ROW(F(MemUnspecified) | F(Mem32) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), - ROW(F(MemUnspecified) | F(Mem64) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), - ROW(F(RegGpw) | F(RegGpq) | F(Mem16) | F(Mem64), 0x00), - ROW(F(RegSReg), 0x1A), - ROW(F(RegSReg), 0x60), - ROW(F(RegGpw) | F(RegGpq) | F(Mem16) | F(Mem64) | F(ImmI8) | F(ImmI16) | F(ImmI32), 0x00), - ROW(F(RegGpd) | F(Mem32) | F(ImmI32) | F(ImmU32), 0x00), - ROW(F(RegSReg), 0x1E), - ROW(F(MemUnspecified) | F(Mem8) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), - ROW(F(MemUnspecified) | F(Mem16) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), - ROW(F(MemUnspecified) | F(Mem32) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), - ROW(F(MemUnspecified) | F(Mem64) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(RegKReg), 0x00), + ROW(F(RegKReg) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(MemUnspecified) | F(Mem8) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(MemUnspecified) | F(Mem16) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(MemUnspecified) | F(Mem32) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(MemUnspecified) | F(Mem64) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(MemUnspecified) | F(Mem8) | F(FlagMemBase) | F(FlagMemEs), 0x80), + ROW(F(MemUnspecified) | F(Mem16) | F(FlagMemBase) | F(FlagMemEs), 0x80), + ROW(F(MemUnspecified) | F(Mem32) | F(FlagMemBase) | F(FlagMemEs), 0x80), + ROW(F(MemUnspecified) | F(Mem64) | F(FlagMemBase) | F(FlagMemEs), 0x80), ROW(F(RegXmm) | F(RegYmm), 0x00), ROW(F(ImmI4) | F(ImmU4), 0x00), + ROW(F(RegGpw) | F(RegGpd) | F(MemUnspecified) | F(Mem16) | F(Mem32) | F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), + ROW(F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), + ROW(F(RegGpw) | F(RegGpd), 0x00), ROW(F(Mem32) | F(Mem64), 0x00), ROW(F(RegSt), 0x01), ROW(F(RegSt), 0x00), - ROW(F(MemUnspecified) | F(Mem48), 0x00), + ROW(F(ImmI32) | F(ImmI64) | F(Rel8) | F(Rel32), 0x00), + ROW(F(RegGpd) | F(Mem32) | F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), + ROW(F(ImmI16), 0x00), + ROW(F(ImmI16) | F(ImmI32), 0x00), + ROW(F(MemUnspecified) | F(Mem32) | F(Mem48), 0x00), ROW(F(MemUnspecified) | F(Mem80), 0x00), + ROW(F(MemUnspecified) | F(Mem48), 0x00), + ROW(F(RegGpd) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpw) | F(Mem8) | F(Mem16), 0x00), + ROW(F(RegGpbLo) | F(RegGpw) | F(Mem8) | F(Mem16), 0x00), ROW(F(RegGpbLo) | F(ImmI8) | F(ImmU8), 0x02), ROW(F(RegXmm) | F(RegKReg), 0x00), ROW(F(RegYmm) | F(RegKReg), 0x00), - ROW(F(RegKReg), 0x00), ROW(F(RegXmm) | F(MemUnspecified) | F(Mem32), 0x00), ROW(F(Vm64x) | F(Vm64y), 0x00), - ROW(F(RegGpq) | F(RegXmm) | F(MemUnspecified) | F(Mem64), 0x00), ROW(F(RegXmm) | F(MemUnspecified) | F(Mem16), 0x00), ROW(F(RegBnd), 0x00), ROW(F(RegBnd) | F(MemUnspecified), 0x00), ROW(F(MemUnspecified), 0x00), - ROW(F(RegGpw) | F(RegGpd) | F(Mem16) | F(Mem32) | F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), - ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), - ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpw) | F(RegGpd) | F(Mem8) | F(Mem16) | F(Mem32), 0x00), - ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpq) | F(Mem8) | F(Mem64), 0x00), - ROW(F(RegGpw) | F(RegGpd), 0x00), + ROW(F(RegGpbLo) | F(RegGpq) | F(Mem8) | F(Mem64), 0x00), ROW(F(MemUnspecified) | F(Mem512) | F(FlagMemBase) | F(FlagMemEs), 0x00), ROW(F(RegSt) | F(Mem32) | F(Mem64), 0x00), ROW(F(RegGpd) | F(FlagImplicit), 0x02), ROW(F(RegGpd) | F(RegGpq) | F(FlagImplicit), 0x01), - ROW(F(ImmI32) | F(ImmI64) | F(Rel8) | F(Rel32), 0x00), - ROW(F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), ROW(F(RegGpw) | F(RegGpd) | F(FlagImplicit), 0x02), ROW(F(ImmI32) | F(ImmI64) | F(Rel8), 0x00), ROW(F(RegGpd) | F(RegGpq) | F(FlagImplicit), 0x02), - ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI32) | F(ImmI64) | F(Rel8) | F(Rel32), 0x00), - ROW(F(RegGpd) | F(MemUnspecified) | F(Mem32) | F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), ROW(F(RegGpd) | F(RegKReg) | F(MemUnspecified) | F(Mem8), 0x00), ROW(F(RegGpd) | F(MemUnspecified) | F(Mem8), 0x00), ROW(F(RegGpd) | F(RegKReg) | F(MemUnspecified) | F(Mem32), 0x00), - ROW(F(RegGpq) | F(RegKReg) | F(MemUnspecified) | F(Mem64), 0x00), ROW(F(RegGpd) | F(RegKReg) | F(MemUnspecified) | F(Mem16), 0x00), - ROW(F(RegGpd) | F(MemUnspecified) | F(Mem16), 0x00), - ROW(F(ImmI16), 0x00), - ROW(F(ImmI16) | F(ImmI32), 0x00), - ROW(F(MemUnspecified) | F(Mem32) | F(Mem48) | F(Mem80), 0x00), + ROW(F(MemUnspecified) | F(Mem8) | F(Mem16) | F(Mem32) | F(Mem48) | F(Mem64) | F(Mem80) | F(Mem128) | F(Mem256) | F(Mem512) | F(Mem1024), 0x00), ROW(F(RegGpd) | F(RegGpq), 0x00), - ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpw) | F(Mem8) | F(Mem16), 0x00), - ROW(F(RegMm) | F(MemUnspecified) | F(Mem64), 0x00), ROW(F(RegMm) | F(MemUnspecified) | F(Mem64) | F(ImmI8) | F(ImmU8), 0x00), ROW(F(RegMm) | F(MemUnspecified) | F(Mem32), 0x00), ROW(F(ImmU16), 0x00), + ROW(F(RegGpw) | F(RegGpd) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegGpq) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(MemUnspecified) | F(FlagMemBase) | F(FlagMemDs), 0x00), ROW(F(RegXmm) | F(RegYmm) | F(Mem128) | F(Mem256), 0x00), + ROW(F(RegXmm) | F(RegYmm) | F(RegZmm), 0x00), ROW(F(RegXmm) | F(ImmI8) | F(ImmU8), 0x00), ROW(F(RegXmm) | F(FlagImplicit), 0x01), ROW(F(MemUnspecified) | F(FlagMib), 0x00), - ROW(F(RegGpw) | F(RegGpd) | F(RegGpq), 0x00), - ROW(F(MemUnspecified) | F(Mem8) | F(Mem16) | F(Mem32) | F(Mem48) | F(Mem64) | F(Mem80) | F(Mem128) | F(Mem256) | F(Mem512) | F(Mem1024), 0x00), ROW(F(MemUnspecified) | F(Mem512) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x01), ROW(F(RegGpq) | F(FlagImplicit), 0x02), ROW(F(RegGpq) | F(FlagImplicit), 0x08), ROW(F(RegGpd) | F(FlagImplicit), 0x08), - ROW(F(RegGpd) | F(RegGpq) | F(MemUnspecified) | F(Mem32) | F(Mem64), 0x00), ROW(F(Mem16) | F(Mem32), 0x00), ROW(F(Mem16) | F(Mem32) | F(Mem64), 0x00), ROW(F(RegSt) | F(Mem32) | F(Mem64) | F(Mem80), 0x00), @@ -3739,12 +5468,9 @@ const InstDB::OpSignature InstDB::_opSignatureTable[] = { ROW(F(MemUnspecified) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x01), ROW(F(RegGpw) | F(ImmU8), 0x04), ROW(F(Mem8) | F(Mem16) | F(Mem32) | F(FlagMemBase) | F(FlagMemDs), 0x40), - ROW(F(RegGpw) | F(RegGpd) | F(RegGpq) | F(MemUnspecified) | F(Mem16), 0x00), ROW(F(RegTmm), 0x00), ROW(F(MemUnspecified) | F(FlagTMem), 0x00), - ROW(F(MemUnspecified) | F(FlagMemBase) | F(FlagMemDs), 0x00), ROW(F(RegYmm) | F(RegZmm), 0x00), - ROW(F(RegXmm) | F(RegYmm) | F(RegZmm), 0x00), ROW(F(RegXmm) | F(RegYmm) | F(RegZmm) | F(Mem128) | F(Mem256) | F(Mem512), 0x00), ROW(F(RegGpd) | F(RegXmm) | F(MemUnspecified) | F(Mem8), 0x00), ROW(F(RegGpd) | F(RegXmm) | F(MemUnspecified) | F(Mem32), 0x00), @@ -3762,302 +5488,311 @@ const InstDB::OpSignature InstDB::_opSignatureTable[] = { // ${InstRWInfoTable:Begin} // ------------------- Automatically generated, do not edit ------------------- const uint8_t InstDB::rwInfoIndexA[Inst::_kIdCount] = { - 0, 0, 1, 1, 0, 2, 3, 2, 4, 4, 5, 6, 4, 4, 3, 4, 4, 4, 4, 7, 0, 2, 0, 4, 4, 4, - 4, 8, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, 13, - 14, 9, 9, 0, 15, 16, 16, 16, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 18, 0, 0, 19, 0, 0, 0, 0, 0, 20, 21, 0, 22, 23, 24, 7, 25, - 25, 25, 24, 26, 7, 24, 27, 28, 29, 30, 31, 32, 33, 25, 25, 7, 27, 28, 33, 34, - 0, 0, 0, 0, 35, 4, 4, 5, 6, 0, 0, 0, 0, 0, 36, 36, 0, 0, 37, 0, 0, 38, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 38, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 38, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 39, 4, - 4, 35, 40, 41, 0, 0, 0, 42, 0, 37, 0, 0, 0, 0, 43, 0, 44, 43, 43, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 47, 48, 49, 50, 51, - 52, 53, 0, 0, 0, 54, 55, 56, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 55, 56, 57, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 0, 59, 0, 60, 0, 61, 0, 60, 0, 60, 0, 60, - 0, 0, 0, 0, 0, 62, 63, 63, 63, 58, 60, 0, 0, 0, 9, 0, 0, 4, 4, 5, 6, 0, 0, 4, - 4, 5, 6, 0, 0, 64, 65, 66, 66, 67, 47, 24, 36, 67, 52, 66, 66, 68, 69, 69, 70, - 71, 71, 72, 72, 59, 59, 67, 59, 59, 71, 71, 73, 48, 52, 74, 75, 7, 7, 76, 77, - 9, 66, 66, 77, 0, 35, 4, 4, 5, 6, 0, 78, 0, 0, 79, 0, 2, 4, 4, 80, 81, 9, 9, - 9, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 82, 3, 0, 0, 0, 3, 3, - 4, 3, 0, 0, 3, 3, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 83, 27, 27, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 27, 82, 82, 82, 27, 27, 82, 82, 82, 3, 3, 3, 84, 3, 3, 3, - 27, 27, 0, 0, 0, 0, 3, 3, 4, 4, 3, 3, 4, 4, 4, 4, 3, 3, 4, 4, 85, 86, 87, 24, - 24, 24, 86, 86, 87, 24, 24, 24, 86, 4, 3, 82, 3, 3, 4, 3, 3, 0, 0, 0, 9, 0, - 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 3, 3, 3, 3, 88, 3, 3, 0, 3, 3, - 3, 88, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 89, 0, 3, 3, 4, 3, 90, 90, 4, 90, 0, - 0, 0, 0, 0, 0, 0, 3, 91, 7, 92, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, - 0, 0, 0, 91, 91, 0, 0, 0, 0, 0, 0, 7, 92, 0, 0, 91, 91, 0, 0, 2, 94, 0, 0, 0, + 0, 0, 1, 2, 1, 2, 0, 3, 4, 3, 5, 5, 6, 7, 5, 5, 4, 5, 5, 5, 5, 8, 0, 3, 0, 5, + 5, 5, 5, 2, 9, 2, 0, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, 10, 10, 10, 11, 11, + 11, 12, 12, 13, 14, 15, 10, 10, 0, 16, 17, 17, 17, 0, 0, 0, 18, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 21, 22, 0, 23, 24, 25, 8, 26, 26, + 26, 25, 27, 8, 25, 28, 29, 30, 31, 32, 33, 34, 26, 26, 8, 28, 29, 34, 35, 0, + 0, 0, 0, 36, 5, 5, 6, 7, 0, 0, 0, 0, 0, 37, 37, 0, 0, 38, 0, 0, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 39, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 39, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 40, 5, 5, 36, + 41, 42, 0, 0, 0, 43, 0, 38, 0, 0, 0, 0, 44, 0, 45, 0, 44, 44, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 48, 49, 50, 51, 52, 53, + 54, 0, 0, 0, 55, 56, 57, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 56, 57, 58, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 60, 0, 2, 0, 61, 0, 2, 0, 2, 0, 2, 0, 0, + 0, 0, 0, 62, 63, 63, 63, 59, 2, 0, 0, 0, 10, 0, 0, 5, 5, 6, 7, 0, 0, 5, 5, 6, + 7, 0, 0, 64, 65, 66, 66, 67, 48, 25, 37, 67, 53, 66, 66, 68, 69, 69, 70, 71, + 71, 72, 72, 60, 60, 67, 60, 60, 71, 71, 73, 49, 53, 74, 75, 8, 8, 76, 77, 10, + 66, 66, 77, 0, 36, 5, 5, 6, 7, 0, 78, 0, 0, 79, 0, 3, 5, 5, 80, 81, 10, 10, 10, + 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 0, 4, 82, 4, 0, 0, 0, 4, 4, 5, + 4, 0, 0, 4, 4, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 83, 28, 28, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 28, 82, 82, 82, 28, 28, 82, 82, 82, 4, 4, 4, 84, 4, 4, 4, 28, + 28, 0, 0, 0, 0, 4, 4, 5, 5, 4, 4, 5, 5, 5, 5, 4, 4, 5, 5, 85, 86, 87, 25, 25, + 25, 86, 86, 87, 25, 25, 25, 86, 5, 4, 82, 4, 4, 5, 4, 4, 0, 0, 0, 10, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 88, 4, 4, 0, 4, + 4, 4, 88, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 28, 89, 0, 4, 4, 5, 4, 90, 90, 5, 90, + 0, 0, 0, 0, 0, 0, 0, 4, 91, 8, 92, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, + 0, 0, 0, 0, 0, 91, 91, 0, 0, 0, 0, 0, 0, 8, 92, 0, 0, 91, 91, 0, 0, 3, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 4, 4, 0, 91, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 7, 7, 26, 92, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 2, 4, 4, 5, 6, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 96, 96, 0, 97, 0, 0, 9, 9, 20, 21, 98, 98, 0, - 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 28, 100, 101, 100, 101, 99, 28, 100, 101, - 100, 101, 102, 103, 0, 0, 0, 0, 0, 0, 20, 104, 21, 105, 105, 106, 77, 9, 0, 77, - 107, 108, 107, 9, 107, 9, 109, 110, 106, 109, 110, 109, 110, 9, 9, 9, 106, - 0, 77, 106, 9, 106, 9, 108, 107, 0, 28, 0, 28, 0, 111, 0, 111, 0, 0, 0, 0, 0, - 33, 33, 107, 9, 107, 9, 109, 110, 109, 110, 9, 9, 9, 106, 9, 106, 28, 28, 111, - 111, 33, 33, 106, 77, 9, 9, 108, 107, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 112, 112, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 5, 5, 0, 91, 0, 0, 91, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 8, 27, 92, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 3, 5, 5, 6, 7, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 96, 96, 0, 97, 0, 0, + 0, 10, 10, 21, 22, 98, 98, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 99, 99, 0, 0, 0, 0, 0, 0, 100, 29, + 101, 102, 101, 102, 100, 29, 101, 102, 101, 102, 103, 104, 0, 0, 0, 0, 0, 0, + 21, 105, 22, 106, 106, 107, 77, 10, 0, 67, 67, 67, 67, 77, 108, 109, 108, 10, + 108, 10, 110, 111, 107, 110, 111, 110, 111, 10, 10, 10, 107, 0, 77, 107, 10, + 107, 10, 109, 108, 0, 29, 0, 29, 0, 112, 0, 112, 0, 0, 0, 0, 0, 34, 34, 108, + 10, 108, 10, 110, 111, 110, 111, 10, 10, 10, 107, 10, 107, 29, 29, 112, 112, 34, + 34, 107, 77, 10, 10, 109, 108, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 113, 113, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 27, 113, 60, 60, - 0, 0, 0, 0, 0, 0, 0, 0, 60, 114, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 28, 114, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 115, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 115, 47, 116, 115, 115, 115, 115, 115, - 115, 115, 115, 0, 117, 117, 0, 71, 71, 118, 119, 67, 67, 67, 67, 120, 71, 121, - 9, 9, 73, 115, 115, 49, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 33, 124, 124, 28, 125, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 105, 105, 105, 0, - 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 60, 60, 114, 60, 7, 7, 7, - 0, 7, 0, 7, 7, 7, 7, 7, 7, 0, 7, 7, 84, 7, 0, 7, 0, 0, 7, 0, 0, 0, 0, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 116, 48, 117, 116, 116, 116, 116, + 116, 116, 116, 116, 0, 118, 118, 0, 71, 71, 119, 120, 67, 67, 67, 67, 121, 71, + 122, 10, 10, 73, 116, 116, 50, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, + 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 34, 125, 125, 29, 126, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 106, + 106, 106, 0, 0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 126, 126, 127, 128, 124, 124, 124, 124, 85, 126, 129, 128, - 127, 127, 128, 129, 128, 127, 128, 130, 131, 106, 106, 106, 130, 127, 128, - 129, 128, 127, 128, 126, 128, 130, 131, 106, 106, 106, 130, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, - 132, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 0, 0, 0, 0, 2, 2, 115, 2, 8, 8, 8, 0, 8, 0, 8, 8, 8, 8, 8, 8, + 0, 8, 8, 84, 8, 0, 8, 0, 0, 8, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, + 127, 128, 129, 125, 125, 125, 125, 85, 127, 130, 129, 128, 128, 129, 130, + 129, 128, 129, 131, 132, 107, 107, 107, 131, 128, 129, 130, 129, 128, 129, 127, + 129, 131, 132, 107, 107, 107, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 133, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 112, 112, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 112, 112, 0, 0, 9, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 67, 67, 0, 0, 0, 0, 0, 0, 0, 0, 67, 132, 0, 0, 0, 0, 0, 0, 9, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 20, 104, 21, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 133, 134, 133, 134, 0, 135, 0, 136, 0, 0, 0, 2, 4, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 10, 0, 0, 113, 113, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 10, 0, 0, 113, 113, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 67, 67, 0, 0, 0, 0, 0, 0, 0, 0, 67, 133, 134, 135, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 123, 21, 105, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 137, 136, 137, 0, 138, 0, 139, 0, + 0, 0, 3, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const uint8_t InstDB::rwInfoIndexB[Inst::_kIdCount] = { - 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 0, - 0, 0, 4, 0, 0, 0, 0, 0, 5, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 7, 0, 0, 0, 0, 4, 8, 1, 0, 9, 0, 0, 0, 10, 10, 10, 0, 0, 11, 0, 0, 10, 12, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 5, 0, 13, 14, 15, 16, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 1, 1, 20, 21, 0, 0, - 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 22, 23, 0, 0, 24, 25, 26, 27, 0, 0, 25, 25, 25, - 25, 25, 25, 25, 25, 28, 29, 29, 28, 0, 0, 0, 24, 25, 24, 25, 0, 25, 24, 24, 24, - 24, 24, 24, 24, 0, 0, 30, 30, 30, 24, 24, 28, 0, 31, 10, 0, 0, 0, 0, 0, 0, 24, - 25, 0, 0, 0, 32, 33, 32, 34, 0, 0, 0, 0, 0, 10, 32, 0, 0, 0, 0, 35, 33, 32, - 35, 34, 24, 25, 24, 25, 0, 29, 29, 29, 29, 0, 0, 0, 25, 10, 10, 32, 32, 0, 0, - 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 21, 36, 0, 20, 37, 38, 0, 39, 40, 0, 0, 0, 0, - 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 43, 44, 41, 42, 41, 42, 43, - 44, 43, 44, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 43, 0, 0, 0, 0, 44, 45, 46, 47, - 48, 45, 46, 47, 48, 0, 0, 0, 0, 49, 50, 51, 41, 42, 43, 44, 41, 42, 43, 44, 52, - 0, 24, 0, 53, 0, 54, 0, 0, 0, 0, 0, 10, 0, 10, 24, 55, 56, 55, 0, 0, 0, 0, - 0, 0, 55, 57, 57, 0, 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 5, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 4, 8, 1, 0, 9, 0, 0, 0, 10, 10, 10, 0, 0, 11, 0, + 0, 10, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 5, 5, 13, 0, 14, 15, 13, 16, 17, 18, 13, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 1, 1, 21, 22, 0, 0, 0, + 0, 5, 5, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 25, 26, 27, 28, 0, 0, 26, 26, 26, 26, + 26, 26, 26, 26, 29, 30, 30, 29, 0, 0, 0, 25, 26, 25, 26, 0, 26, 25, 25, 25, + 25, 25, 25, 25, 0, 0, 31, 31, 31, 25, 25, 29, 0, 32, 10, 0, 0, 0, 0, 0, 0, 25, + 26, 0, 0, 0, 33, 34, 33, 35, 0, 0, 0, 0, 0, 10, 33, 0, 0, 0, 0, 36, 34, 33, 36, + 35, 25, 26, 25, 26, 0, 30, 30, 30, 30, 0, 0, 0, 26, 10, 10, 33, 33, 0, 0, 0, + 20, 5, 5, 0, 0, 0, 0, 0, 0, 0, 22, 37, 0, 21, 38, 39, 0, 40, 41, 0, 0, 0, 0, + 0, 10, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 46, 43, 44, 43, 44, + 45, 46, 45, 46, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 0, 0, 0, 0, 46, 47, 48, + 49, 50, 47, 48, 49, 50, 0, 0, 0, 0, 51, 52, 53, 43, 44, 45, 46, 43, 44, 45, 46, + 54, 0, 25, 0, 55, 0, 56, 0, 0, 0, 0, 0, 10, 0, 10, 25, 57, 58, 57, 0, 0, 0, + 0, 0, 0, 57, 59, 59, 0, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 61, 0, 0, 61, 0, 0, 0, 0, 0, 5, 62, 0, 0, 0, 0, 63, 0, 64, 20, 65, 20, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, - 6, 5, 5, 0, 0, 0, 0, 67, 68, 0, 0, 0, 0, 69, 70, 0, 3, 3, 71, 22, 72, 73, 0, + 0, 0, 63, 0, 0, 63, 0, 0, 0, 0, 0, 5, 64, 0, 0, 0, 0, 65, 0, 66, 21, 67, 21, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, + 0, 6, 5, 5, 0, 0, 0, 0, 69, 70, 0, 0, 0, 0, 71, 72, 0, 3, 3, 73, 23, 74, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 74, 39, 75, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 10, - 10, 10, 10, 10, 10, 10, 0, 0, 2, 2, 2, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 81, 80, 81, 81, 81, 80, 80, 82, 83, 0, 84, - 0, 0, 0, 0, 0, 0, 85, 2, 2, 86, 87, 0, 0, 0, 11, 88, 0, 0, 4, 0, 0, 0, 89, 0, - 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 90, 90, 0, 90, 0, 32, 0, 0, 0, 5, 0, 0, 6, 0, 91, - 4, 0, 91, 4, 5, 5, 32, 19, 92, 80, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 92, - 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 95, 95, 95, 95, 0, 0, 0, 0, - 0, 0, 96, 97, 0, 0, 0, 0, 0, 0, 0, 0, 56, 97, 0, 0, 0, 0, 98, 99, 98, 99, 3, - 3, 3, 100, 101, 102, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 103, - 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 104, 3, 105, 106, 107, 0, - 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 108, 0, 0, 0, 0, 0, 0, 0, 109, 0, 110, 0, 111, 0, 111, 0, 112, 113, 114, 115, - 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 112, 113, 114, 0, 0, 3, 3, 3, 3, 100, 111, 102, 3, 117, 3, 55, 55, - 0, 0, 0, 0, 118, 119, 120, 119, 120, 118, 119, 120, 119, 120, 22, 121, 122, 121, - 122, 121, 121, 123, 124, 121, 121, 121, 125, 126, 127, 121, 121, 121, 125, - 126, 127, 121, 121, 121, 125, 126, 127, 121, 122, 128, 128, 129, 130, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 128, 128, 121, 121, 121, 125, 131, 127, 121, - 121, 121, 125, 131, 127, 121, 121, 121, 125, 131, 127, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 128, 128, 128, 128, 129, 130, 121, 122, 121, 121, 121, - 125, 126, 127, 121, 121, 121, 125, 126, 127, 121, 121, 121, 125, 126, 127, - 128, 128, 129, 130, 121, 121, 121, 125, 131, 127, 121, 121, 121, 125, 131, 127, - 121, 121, 121, 132, 131, 133, 128, 128, 129, 130, 134, 134, 134, 78, 135, 136, - 0, 0, 0, 0, 137, 138, 10, 10, 10, 10, 10, 10, 10, 10, 138, 139, 0, 0, 0, 140, - 141, 142, 85, 85, 85, 140, 141, 142, 3, 3, 3, 3, 3, 3, 3, 143, 144, 145, 144, - 145, 143, 144, 145, 144, 145, 102, 0, 53, 58, 146, 146, 3, 3, 3, 100, 101, - 102, 0, 147, 0, 3, 3, 3, 100, 101, 102, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 149, 150, 150, 151, 152, 152, 0, 0, 0, 0, 0, 0, 0, 153, 154, 0, 0, 155, - 0, 0, 0, 3, 11, 147, 0, 0, 156, 148, 3, 3, 3, 100, 101, 102, 0, 11, 3, 3, 157, - 157, 158, 158, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 103, 3, 0, 0, 0, 0, 0, 0, 3, 128, 104, 104, 3, - 3, 3, 3, 67, 68, 3, 3, 3, 3, 69, 70, 104, 104, 104, 104, 104, 104, 117, 117, 0, - 0, 0, 0, 117, 117, 117, 117, 117, 117, 0, 0, 121, 121, 121, 121, 159, 159, 3, - 3, 3, 121, 3, 3, 121, 121, 128, 128, 160, 160, 160, 3, 160, 3, 121, 121, 121, - 121, 121, 3, 0, 0, 0, 0, 71, 22, 72, 161, 138, 137, 139, 138, 0, 0, 0, 3, 0, - 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 3, 3, 0, 162, 102, 100, 101, 0, 0, - 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 121, 121, 3, 3, 146, - 146, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, 3, 3, 164, 85, 85, - 3, 3, 85, 85, 3, 3, 165, 165, 165, 165, 3, 0, 0, 0, 0, 165, 165, 165, 165, 165, - 165, 3, 3, 121, 121, 121, 3, 165, 165, 3, 3, 121, 121, 121, 3, 3, 104, 85, 85, - 85, 3, 3, 3, 166, 167, 166, 3, 3, 3, 168, 166, 169, 3, 3, 3, 168, 166, 167, - 166, 3, 3, 3, 168, 3, 3, 3, 3, 3, 3, 3, 3, 121, 121, 0, 104, 104, 104, 104, 104, - 104, 104, 104, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 140, 142, 0, 0, 140, - 142, 0, 0, 140, 142, 0, 0, 141, 142, 85, 85, 85, 140, 141, 142, 85, 85, 85, 140, - 141, 142, 85, 85, 140, 142, 0, 0, 140, 142, 0, 0, 140, 142, 0, 0, 141, 142, - 3, 3, 3, 100, 101, 102, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 3, 3, 3, - 3, 3, 3, 0, 0, 0, 140, 141, 142, 93, 3, 3, 3, 100, 101, 102, 0, 0, 0, 0, 0, 3, - 3, 3, 3, 3, 3, 0, 0, 0, 0, 56, 56, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, - 0, 0, 0, 171, 171, 171, 171, 172, 172, 172, 172, 172, 172, 172, 172, 170, 0, - 0 + 0, 0, 0, 0, 76, 40, 77, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 2, 2, 2, 80, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, + 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 81, 82, 81, 82, 82, 82, 81, 81, 83, + 84, 0, 85, 0, 0, 0, 0, 0, 0, 86, 2, 2, 87, 88, 0, 0, 0, 11, 89, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 90, 0, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 91, 0, 33, 0, 0, + 0, 5, 0, 0, 6, 0, 92, 4, 0, 92, 4, 5, 5, 33, 20, 93, 81, 93, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 0, 93, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, 0, + 96, 96, 96, 96, 96, 96, 0, 0, 0, 0, 0, 0, 97, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 98, 0, 0, 0, 0, 99, 100, 99, 100, 3, 3, 3, 101, 102, 103, 3, 3, 3, 3, 3, 3, + 0, 2, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 3, 3, 104, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 105, 3, 106, 107, 108, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, 0, 0, 0, 0, + 0, 0, 110, 0, 111, 0, 112, 0, 112, 0, 113, 114, 115, 116, 117, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 114, + 115, 0, 0, 3, 3, 3, 3, 101, 112, 103, 3, 118, 3, 57, 57, 0, 0, 0, 0, 119, 120, + 121, 120, 121, 119, 120, 121, 120, 121, 23, 122, 123, 122, 123, 124, 124, 125, + 126, 124, 124, 124, 127, 128, 129, 124, 124, 124, 127, 128, 129, 124, 124, + 124, 127, 128, 129, 122, 123, 130, 130, 131, 132, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 130, 130, 124, 124, 124, 127, 133, 129, 124, 124, 124, 127, 133, + 129, 124, 124, 124, 127, 133, 129, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 130, 130, 130, 130, 131, 132, 122, 123, 124, 124, 124, 127, 128, 129, 124, + 124, 124, 127, 128, 129, 124, 124, 124, 127, 128, 129, 130, 130, 131, 132, + 124, 124, 124, 127, 133, 129, 124, 124, 124, 127, 133, 129, 124, 124, 124, 134, + 133, 135, 130, 130, 131, 132, 136, 136, 136, 80, 137, 138, 0, 0, 0, 0, 139, + 140, 10, 10, 10, 10, 10, 10, 10, 10, 140, 141, 0, 0, 0, 142, 143, 144, 86, 86, + 86, 142, 143, 144, 3, 3, 3, 3, 3, 3, 3, 145, 146, 147, 146, 147, 145, 146, 147, + 146, 147, 103, 0, 55, 60, 148, 148, 3, 3, 3, 101, 102, 103, 0, 149, 0, 0, 3, + 3, 3, 101, 102, 103, 0, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 152, + 152, 153, 154, 154, 0, 0, 0, 0, 0, 0, 0, 155, 156, 0, 0, 157, 0, 0, 0, 3, 11, + 149, 0, 0, 158, 150, 3, 3, 3, 101, 102, 103, 0, 0, 11, 3, 3, 159, 159, 160, + 160, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 104, 3, 0, 0, 0, 0, 0, 0, 3, 130, 105, 105, 3, 3, 3, 3, 69, 70, + 3, 3, 3, 3, 71, 72, 105, 105, 105, 105, 105, 105, 118, 118, 0, 0, 0, 0, 118, + 118, 118, 118, 118, 118, 0, 0, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 161, 161, 3, 3, 124, 124, 3, 3, 124, 124, 130, + 130, 162, 162, 162, 3, 162, 124, 124, 124, 124, 124, 124, 3, 0, 0, 0, 0, 73, + 23, 74, 163, 140, 139, 141, 140, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 3, 3, 0, 164, 103, 101, 102, 0, 0, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 124, 124, 3, 3, 148, 148, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, 3, 3, 166, 86, 86, 3, 3, 86, 86, 3, 3, 167, 167, + 167, 167, 3, 0, 0, 0, 0, 167, 167, 167, 167, 167, 167, 3, 3, 124, 124, 124, + 3, 167, 167, 3, 3, 124, 124, 124, 3, 3, 105, 86, 86, 86, 3, 3, 3, 168, 169, 168, + 3, 3, 3, 170, 168, 171, 3, 3, 3, 170, 168, 169, 168, 3, 3, 3, 170, 3, 3, 3, + 3, 3, 3, 3, 3, 172, 172, 0, 105, 105, 105, 105, 105, 105, 105, 105, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 142, 144, 0, 0, 142, 144, 0, 0, 142, 144, 0, 0, + 143, 144, 86, 86, 86, 142, 143, 144, 86, 86, 86, 142, 143, 144, 86, 86, 142, 144, + 0, 0, 142, 144, 0, 0, 142, 144, 0, 0, 143, 144, 3, 3, 3, 101, 102, 103, 0, + 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 173, 3, 3, 3, 3, 3, 3, 174, 174, + 174, 3, 3, 0, 0, 0, 142, 143, 144, 94, 3, 3, 3, 101, 102, 103, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 58, 58, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, + 0, 0, 0, 0, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 177, 177, 175, + 0, 0 }; const InstDB::RWInfo InstDB::rwInfoA[] = { - { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #0 [ref=1007x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #0 [ref=1054x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 1 , 0 , 0 , 0 , 0 , 0 } }, // #1 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 1 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #2 [ref=7x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #3 [ref=96x] - { InstDB::RWInfo::kCategoryGeneric , 3 , { 4 , 5 , 0 , 0 , 0 , 0 } }, // #4 [ref=55x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 6 , 7 , 0 , 0 , 0 , 0 } }, // #5 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 8 , 9 , 0 , 0 , 0 , 0 } }, // #6 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 3 , { 10, 5 , 0 , 0 , 0 , 0 } }, // #7 [ref=26x] - { InstDB::RWInfo::kCategoryGeneric , 7 , { 12, 13, 0 , 0 , 0 , 0 } }, // #8 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #9 [ref=75x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 5 , 3 , 0 , 0 , 0 , 0 } }, // #10 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 10, 3 , 0 , 0 , 0 , 0 } }, // #11 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 9 , { 10, 5 , 0 , 0 , 0 , 0 } }, // #12 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 15, 5 , 0 , 0 , 0 , 0 } }, // #13 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 3 , 3 , 0 , 0 , 0 , 0 } }, // #14 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 10, { 3 , 3 , 0 , 0 , 0 , 0 } }, // #15 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 10, { 2 , 3 , 0 , 0 , 0 , 0 } }, // #16 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 17, 0 , 0 , 0 , 0 } }, // #17 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 1 , { 3 , 3 , 0 , 0 , 0 , 0 } }, // #18 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 20, 21, 0 , 0 , 0 , 0 } }, // #19 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 7 , 7 , 0 , 0 , 0 , 0 } }, // #20 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 9 , 9 , 0 , 0 , 0 , 0 } }, // #21 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 33, 34, 0 , 0 , 0 , 0 } }, // #22 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 14, { 2 , 3 , 0 , 0 , 0 , 0 } }, // #23 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 10, 7 , 0 , 0 , 0 , 0 } }, // #24 [ref=10x] - { InstDB::RWInfo::kCategoryGeneric , 3 , { 35, 5 , 0 , 0 , 0 , 0 } }, // #25 [ref=5x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 36, 7 , 0 , 0 , 0 , 0 } }, // #26 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #27 [ref=11x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 11, 7 , 0 , 0 , 0 , 0 } }, // #28 [ref=9x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 37, 7 , 0 , 0 , 0 , 0 } }, // #29 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 14, { 36, 3 , 0 , 0 , 0 , 0 } }, // #30 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 14, { 37, 3 , 0 , 0 , 0 , 0 } }, // #31 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 36, 9 , 0 , 0 , 0 , 0 } }, // #32 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 11, 9 , 0 , 0 , 0 , 0 } }, // #33 [ref=7x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 38, 39, 0 , 0 , 0 , 0 } }, // #34 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 15, { 1 , 40, 0 , 0 , 0 , 0 } }, // #35 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 16, { 11, 43, 0 , 0 , 0 , 0 } }, // #36 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 4 , 5 , 0 , 0 , 0 , 0 } }, // #37 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 45, 46, 0 , 0 , 0 , 0 } }, // #38 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 50, 0 , 0 , 0 , 0 } }, // #39 [ref=1x] - { InstDB::RWInfo::kCategoryImul , 2 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #40 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 51, 52, 0 , 0 , 0 , 0 } }, // #41 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 54, 52, 0 , 0 , 0 , 0 } }, // #42 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 3 , 5 , 0 , 0 , 0 , 0 } }, // #43 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 22, 29, 0 , 0 , 0 , 0 } }, // #44 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 55, 0 , 0 , 0 , 0 , 0 } }, // #45 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 23, { 56, 40, 0 , 0 , 0 , 0 } }, // #46 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 24, { 44, 9 , 0 , 0 , 0 , 0 } }, // #47 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 25, { 35, 7 , 0 , 0 , 0 , 0 } }, // #48 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 26, { 48, 13, 0 , 0 , 0 , 0 } }, // #49 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 56, 40, 0 , 0 , 0 , 0 } }, // #50 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 44, 9 , 0 , 0 , 0 , 0 } }, // #51 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #52 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 48, 13, 0 , 0 , 0 , 0 } }, // #53 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 40, 40, 0 , 0 , 0 , 0 } }, // #54 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 9 , 9 , 0 , 0 , 0 , 0 } }, // #55 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 7 , 7 , 0 , 0 , 0 , 0 } }, // #56 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 13, 13, 0 , 0 , 0 , 0 } }, // #57 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 3 , 0 , 0 , 0 , 0 } }, // #58 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 10, 5 , 0 , 0 , 0 , 0 } }, // #59 [ref=5x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #60 [ref=11x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #2 [ref=15x] + { InstDB::RWInfo::kCategoryGeneric , 1 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #3 [ref=7x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #4 [ref=96x] + { InstDB::RWInfo::kCategoryGeneric , 3 , { 4 , 5 , 0 , 0 , 0 , 0 } }, // #5 [ref=55x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 6 , 7 , 0 , 0 , 0 , 0 } }, // #6 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 8 , 9 , 0 , 0 , 0 , 0 } }, // #7 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 3 , { 10, 5 , 0 , 0 , 0 , 0 } }, // #8 [ref=26x] + { InstDB::RWInfo::kCategoryGeneric , 7 , { 12, 13, 0 , 0 , 0 , 0 } }, // #9 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #10 [ref=75x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 5 , 3 , 0 , 0 , 0 , 0 } }, // #11 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 10, 3 , 0 , 0 , 0 , 0 } }, // #12 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 9 , { 10, 5 , 0 , 0 , 0 , 0 } }, // #13 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 15, 5 , 0 , 0 , 0 , 0 } }, // #14 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 3 , 3 , 0 , 0 , 0 , 0 } }, // #15 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 10, { 3 , 3 , 0 , 0 , 0 , 0 } }, // #16 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 10, { 2 , 3 , 0 , 0 , 0 , 0 } }, // #17 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 17, 0 , 0 , 0 , 0 } }, // #18 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 1 , { 3 , 3 , 0 , 0 , 0 , 0 } }, // #19 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 20, 21, 0 , 0 , 0 , 0 } }, // #20 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 7 , 7 , 0 , 0 , 0 , 0 } }, // #21 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 9 , 9 , 0 , 0 , 0 , 0 } }, // #22 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 33, 34, 0 , 0 , 0 , 0 } }, // #23 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 16, { 2 , 3 , 0 , 0 , 0 , 0 } }, // #24 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 10, 7 , 0 , 0 , 0 , 0 } }, // #25 [ref=10x] + { InstDB::RWInfo::kCategoryGeneric , 3 , { 35, 5 , 0 , 0 , 0 , 0 } }, // #26 [ref=5x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 36, 7 , 0 , 0 , 0 , 0 } }, // #27 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #28 [ref=11x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 11, 7 , 0 , 0 , 0 , 0 } }, // #29 [ref=9x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 37, 7 , 0 , 0 , 0 , 0 } }, // #30 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 16, { 36, 3 , 0 , 0 , 0 , 0 } }, // #31 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 16, { 37, 3 , 0 , 0 , 0 , 0 } }, // #32 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 36, 9 , 0 , 0 , 0 , 0 } }, // #33 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 11, 9 , 0 , 0 , 0 , 0 } }, // #34 [ref=7x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 38, 39, 0 , 0 , 0 , 0 } }, // #35 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 17, { 1 , 40, 0 , 0 , 0 , 0 } }, // #36 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 13, { 43, 44, 0 , 0 , 0 , 0 } }, // #37 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 4 , 5 , 0 , 0 , 0 , 0 } }, // #38 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 46, 47, 0 , 0 , 0 , 0 } }, // #39 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 51, 0 , 0 , 0 , 0 } }, // #40 [ref=1x] + { InstDB::RWInfo::kCategoryImul , 2 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #41 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 52, 53, 0 , 0 , 0 , 0 } }, // #42 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 55, 53, 0 , 0 , 0 , 0 } }, // #43 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 3 , 5 , 0 , 0 , 0 , 0 } }, // #44 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 22, 29, 0 , 0 , 0 , 0 } }, // #45 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 57, 0 , 0 , 0 , 0 , 0 } }, // #46 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 23, { 58, 40, 0 , 0 , 0 , 0 } }, // #47 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 24, { 45, 9 , 0 , 0 , 0 , 0 } }, // #48 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 25, { 35, 7 , 0 , 0 , 0 , 0 } }, // #49 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 26, { 49, 13, 0 , 0 , 0 , 0 } }, // #50 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 58, 40, 0 , 0 , 0 , 0 } }, // #51 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 45, 9 , 0 , 0 , 0 , 0 } }, // #52 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #53 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 49, 13, 0 , 0 , 0 , 0 } }, // #54 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 40, 40, 0 , 0 , 0 , 0 } }, // #55 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 9 , 9 , 0 , 0 , 0 , 0 } }, // #56 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 7 , 7 , 0 , 0 , 0 , 0 } }, // #57 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 13, 13, 0 , 0 , 0 , 0 } }, // #58 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 3 , 0 , 0 , 0 , 0 } }, // #59 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 10, 5 , 0 , 0 , 0 , 0 } }, // #60 [ref=5x] { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #61 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 51, 20, 0 , 0 , 0 , 0 } }, // #62 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 58, 0 , 0 , 0 , 0 , 0 } }, // #63 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 52, 20, 0 , 0 , 0 , 0 } }, // #62 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 60, 0 , 0 , 0 , 0 , 0 } }, // #63 [ref=3x] { InstDB::RWInfo::kCategoryMov , 29, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #64 [ref=1x] { InstDB::RWInfo::kCategoryMovabs , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #65 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 30, { 10, 5 , 0 , 0 , 0 , 0 } }, // #66 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #67 [ref=14x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 36, 61, 0 , 0 , 0 , 0 } }, // #68 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #67 [ref=18x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 36, 64, 0 , 0 , 0 , 0 } }, // #68 [ref=1x] { InstDB::RWInfo::kCategoryMovh64 , 12, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #69 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 62, 7 , 0 , 0 , 0 , 0 } }, // #70 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 65, 7 , 0 , 0 , 0 , 0 } }, // #70 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 7 , 0 , 0 , 0 , 0 } }, // #71 [ref=7x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 56, 5 , 0 , 0 , 0 , 0 } }, // #72 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 28, { 44, 9 , 0 , 0 , 0 , 0 } }, // #73 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 63, 20, 0 , 0 , 0 , 0 } }, // #74 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 58, 5 , 0 , 0 , 0 , 0 } }, // #72 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 28, { 45, 9 , 0 , 0 , 0 , 0 } }, // #73 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 66, 20, 0 , 0 , 0 , 0 } }, // #74 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 31, { 35, 7 , 0 , 0 , 0 , 0 } }, // #75 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 33, { 44, 9 , 0 , 0 , 0 , 0 } }, // #76 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 14, { 11, 3 , 0 , 0 , 0 , 0 } }, // #77 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 33, { 45, 9 , 0 , 0 , 0 , 0 } }, // #76 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 16, { 11, 3 , 0 , 0 , 0 , 0 } }, // #77 [ref=6x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 17, 29, 0 , 0 , 0 , 0 } }, // #78 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 11, { 3 , 3 , 0 , 0 , 0 , 0 } }, // #79 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 52, 22, 0 , 0 , 0 , 0 } }, // #80 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 52, 66, 0 , 0 , 0 , 0 } }, // #81 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 53, 22, 0 , 0 , 0 , 0 } }, // #80 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 53, 69, 0 , 0 , 0 , 0 } }, // #81 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 4 , { 26, 7 , 0 , 0 , 0 , 0 } }, // #82 [ref=18x] { InstDB::RWInfo::kCategoryGeneric , 36, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #83 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 3 , { 69, 5 , 0 , 0 , 0 , 0 } }, // #84 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 3 , { 72, 5 , 0 , 0 , 0 , 0 } }, // #84 [ref=2x] { InstDB::RWInfo::kCategoryVmov1_8 , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #85 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 5 , { 10, 9 , 0 , 0 , 0 , 0 } }, // #86 [ref=4x] { InstDB::RWInfo::kCategoryGeneric , 27, { 10, 13, 0 , 0 , 0 , 0 } }, // #87 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 4 , 0 , 0 , 0 , 0 , 0 } }, // #88 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 0 , 0 , 0 } }, // #89 [ref=1x] { InstDB::RWInfo::kCategoryPunpcklxx , 38, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #90 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 10, { 2 , 71, 0 , 0 , 0 , 0 } }, // #91 [ref=8x] + { InstDB::RWInfo::kCategoryGeneric , 10, { 2 , 73, 0 , 0 , 0 , 0 } }, // #91 [ref=8x] { InstDB::RWInfo::kCategoryGeneric , 5 , { 37, 9 , 0 , 0 , 0 , 0 } }, // #92 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 50, 0 , 0 , 0 , 0 } }, // #93 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 51, 0 , 0 , 0 , 0 } }, // #93 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 22, 21, 0 , 0 , 0 , 0 } }, // #94 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 63, 22, 0 , 0 , 0 , 0 } }, // #95 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 74, 3 , 0 , 0 , 0 , 0 } }, // #96 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 43, 0 , 0 , 0 , 0 } }, // #97 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 53, 9 , 0 , 0 , 0 , 0 } }, // #98 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 80, 5 , 0 , 0 , 0 , 0 } }, // #99 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 11, 5 , 0 , 0 , 0 , 0 } }, // #100 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 43, { 74, 81, 0 , 0 , 0 , 0 } }, // #101 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 44, { 11, 7 , 0 , 0 , 0 , 0 } }, // #102 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 45, { 11, 9 , 0 , 0 , 0 , 0 } }, // #103 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 27, { 13, 13, 0 , 0 , 0 , 0 } }, // #104 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 11, { 11, 3 , 0 , 0 , 0 , 0 } }, // #105 [ref=7x] - { InstDB::RWInfo::kCategoryVmov2_1 , 46, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #106 [ref=14x] - { InstDB::RWInfo::kCategoryVmov1_2 , 14, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #107 [ref=7x] - { InstDB::RWInfo::kCategoryGeneric , 14, { 10, 3 , 0 , 0 , 0 , 0 } }, // #108 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 46, { 11, 3 , 0 , 0 , 0 , 0 } }, // #109 [ref=5x] - { InstDB::RWInfo::kCategoryGeneric , 47, { 11, 5 , 0 , 0 , 0 , 0 } }, // #110 [ref=5x] - { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 5 , 0 , 0 , 0 , 0 } }, // #111 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 51, { 74, 43, 0 , 0 , 0 , 0 } }, // #112 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 44, 9 , 0 , 0 , 0 , 0 } }, // #113 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 18, { 2 , 3 , 0 , 0 , 0 , 0 } }, // #114 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 58, { 11, 3 , 0 , 0 , 0 , 0 } }, // #115 [ref=12x] - { InstDB::RWInfo::kCategoryVmovddup , 38, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #116 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 61, 0 , 0 , 0 , 0 } }, // #117 [ref=2x] - { InstDB::RWInfo::kCategoryVmovmskpd , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #118 [ref=1x] - { InstDB::RWInfo::kCategoryVmovmskps , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #119 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 59, { 35, 7 , 0 , 0 , 0 , 0 } }, // #120 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 21, { 48, 13, 0 , 0 , 0 , 0 } }, // #121 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 3 , 3 , 0 , 0 , 0 , 0 } }, // #122 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 15, { 11, 40, 0 , 0 , 0 , 0 } }, // #123 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 11, 7 , 0 , 0 , 0 , 0 } }, // #124 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 13, 0 , 0 , 0 , 0 } }, // #125 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 3 , 0 , 0 , 0 , 0 } }, // #126 [ref=4x] - { InstDB::RWInfo::kCategoryVmov1_4 , 62, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #127 [ref=6x] - { InstDB::RWInfo::kCategoryVmov1_2 , 48, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #128 [ref=9x] - { InstDB::RWInfo::kCategoryVmov1_8 , 63, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #129 [ref=3x] - { InstDB::RWInfo::kCategoryVmov4_1 , 47, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #130 [ref=4x] - { InstDB::RWInfo::kCategoryVmov8_1 , 64, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #131 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 18, { 11, 3 , 0 , 0 , 0 , 0 } }, // #132 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 17, { 44, 9 , 0 , 0 , 0 , 0 } }, // #133 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 35, { 35, 7 , 0 , 0 , 0 , 0 } }, // #134 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 11, { 2 , 2 , 0 , 0 , 0 , 0 } }, // #135 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 58, { 2 , 2 , 0 , 0 , 0 , 0 } } // #136 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 66, 22, 0 , 0 , 0 , 0 } }, // #95 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 43, 3 , 0 , 0 , 0 , 0 } }, // #96 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 44, 0 , 0 , 0 , 0 } }, // #97 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 54, 9 , 0 , 0 , 0 , 0 } }, // #98 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 21, { 11, 13, 0 , 0 , 0 , 0 } }, // #99 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 81, 5 , 0 , 0 , 0 , 0 } }, // #100 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 11, 5 , 0 , 0 , 0 , 0 } }, // #101 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 43, { 43, 82, 0 , 0 , 0 , 0 } }, // #102 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 44, { 11, 7 , 0 , 0 , 0 , 0 } }, // #103 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 45, { 11, 9 , 0 , 0 , 0 , 0 } }, // #104 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 13, 13, 0 , 0 , 0 , 0 } }, // #105 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 11, { 11, 3 , 0 , 0 , 0 , 0 } }, // #106 [ref=7x] + { InstDB::RWInfo::kCategoryVmov2_1 , 46, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #107 [ref=14x] + { InstDB::RWInfo::kCategoryVmov1_2 , 16, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #108 [ref=7x] + { InstDB::RWInfo::kCategoryGeneric , 16, { 10, 3 , 0 , 0 , 0 , 0 } }, // #109 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 46, { 11, 3 , 0 , 0 , 0 , 0 } }, // #110 [ref=5x] + { InstDB::RWInfo::kCategoryGeneric , 47, { 11, 5 , 0 , 0 , 0 , 0 } }, // #111 [ref=5x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 5 , 0 , 0 , 0 , 0 } }, // #112 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 51, { 43, 44, 0 , 0 , 0 , 0 } }, // #113 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 45, 9 , 0 , 0 , 0 , 0 } }, // #114 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 2 , 3 , 0 , 0 , 0 , 0 } }, // #115 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 58, { 11, 3 , 0 , 0 , 0 , 0 } }, // #116 [ref=12x] + { InstDB::RWInfo::kCategoryVmovddup , 38, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #117 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 64, 0 , 0 , 0 , 0 } }, // #118 [ref=2x] + { InstDB::RWInfo::kCategoryVmovmskpd , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #119 [ref=1x] + { InstDB::RWInfo::kCategoryVmovmskps , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #120 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 59, { 35, 7 , 0 , 0 , 0 , 0 } }, // #121 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 21, { 49, 13, 0 , 0 , 0 , 0 } }, // #122 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 3 , 3 , 0 , 0 , 0 , 0 } }, // #123 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 17, { 11, 40, 0 , 0 , 0 , 0 } }, // #124 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 11, 7 , 0 , 0 , 0 , 0 } }, // #125 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 13, 0 , 0 , 0 , 0 } }, // #126 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 3 , 0 , 0 , 0 , 0 } }, // #127 [ref=4x] + { InstDB::RWInfo::kCategoryVmov1_4 , 62, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #128 [ref=6x] + { InstDB::RWInfo::kCategoryVmov1_2 , 48, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #129 [ref=9x] + { InstDB::RWInfo::kCategoryVmov1_8 , 63, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #130 [ref=3x] + { InstDB::RWInfo::kCategoryVmov4_1 , 47, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #131 [ref=4x] + { InstDB::RWInfo::kCategoryVmov8_1 , 64, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #132 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 11, 3 , 0 , 0 , 0 , 0 } }, // #133 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 90, 5 , 0 , 0 , 0 , 0 } }, // #134 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 90, 82, 0 , 0 , 0 , 0 } }, // #135 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 18, { 45, 9 , 0 , 0 , 0 , 0 } }, // #136 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 35, { 35, 7 , 0 , 0 , 0 , 0 } }, // #137 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 11, { 2 , 2 , 0 , 0 , 0 , 0 } }, // #138 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 58, { 2 , 2 , 0 , 0 , 0 , 0 } } // #139 [ref=1x] }; const InstDB::RWInfo InstDB::rwInfoB[] = { - { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #0 [ref=773x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #0 [ref=791x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 1 , 0 , 0 , 0 , 0 , 0 } }, // #1 [ref=5x] { InstDB::RWInfo::kCategoryGeneric , 3 , { 10, 5 , 0 , 0 , 0 , 0 } }, // #2 [ref=7x] { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 3 , 3 , 0 , 0 , 0 } }, // #3 [ref=193x] @@ -4067,201 +5802,206 @@ const InstDB::RWInfo InstDB::rwInfoB[] = { { InstDB::RWInfo::kCategoryGeneric , 0 , { 2 , 0 , 0 , 0 , 0 , 0 } }, // #7 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 11, { 3 , 0 , 0 , 0 , 0 , 0 } }, // #8 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 18, 0 , 0 , 0 , 0 , 0 } }, // #9 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 3 , 0 , 0 , 0 , 0 , 0 } }, // #10 [ref=34x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 3 , 0 , 0 , 0 , 0 , 0 } }, // #10 [ref=37x] { InstDB::RWInfo::kCategoryGeneric , 12, { 7 , 0 , 0 , 0 , 0 , 0 } }, // #11 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 19, 0 , 0 , 0 , 0 , 0 } }, // #12 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 6 , 7 , 0 , 0 , 0 , 0 } }, // #13 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 8 , 9 , 0 , 0 , 0 , 0 } }, // #14 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 11, { 2 , 3 , 22, 0 , 0 , 0 } }, // #15 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 4 , 23, 18, 24, 25, 0 } }, // #16 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 26, 27, 28, 29, 30, 0 } }, // #17 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 28, 31, 32, 16, 0 , 0 } }, // #18 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 28, 0 , 0 , 0 , 0 , 0 } }, // #19 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 10, { 2 , 0 , 0 , 0 , 0 , 0 } }, // #20 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 41, 42, 3 , 0 , 0 , 0 } }, // #21 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 17, { 44, 5 , 0 , 0 , 0 , 0 } }, // #22 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 4 , 0 , 0 , 0 , 0 , 0 } }, // #23 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 18, { 3 , 0 , 0 , 0 , 0 , 0 } }, // #24 [ref=17x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 45, 0 , 0 , 0 , 0 , 0 } }, // #25 [ref=16x] - { InstDB::RWInfo::kCategoryGeneric , 19, { 46, 0 , 0 , 0 , 0 , 0 } }, // #26 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 13, { 19, 0 , 0 , 0 , 0 , 0 } }, // #12 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 2 , 2 , 3 , 0 , 0 , 0 } }, // #13 [ref=16x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 6 , 7 , 0 , 0 , 0 , 0 } }, // #14 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 8 , 9 , 0 , 0 , 0 , 0 } }, // #15 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 11, { 2 , 3 , 22, 0 , 0 , 0 } }, // #16 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 4 , 23, 18, 24, 25, 0 } }, // #17 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 26, 27, 28, 29, 30, 0 } }, // #18 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 28, 31, 32, 16, 0 , 0 } }, // #19 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 28, 0 , 0 , 0 , 0 , 0 } }, // #20 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 10, { 2 , 0 , 0 , 0 , 0 , 0 } }, // #21 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 41, 42, 3 , 0 , 0 , 0 } }, // #22 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 18, { 45, 5 , 0 , 0 , 0 , 0 } }, // #23 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 4 , 0 , 0 , 0 , 0 , 0 } }, // #24 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 3 , 0 , 0 , 0 , 0 , 0 } }, // #25 [ref=17x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 46, 0 , 0 , 0 , 0 , 0 } }, // #26 [ref=16x] { InstDB::RWInfo::kCategoryGeneric , 19, { 47, 0 , 0 , 0 , 0 , 0 } }, // #27 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 20, { 3 , 0 , 0 , 0 , 0 , 0 } }, // #28 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 46, 0 , 0 , 0 , 0 , 0 } }, // #29 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 18, { 11, 0 , 0 , 0 , 0 , 0 } }, // #30 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 21, { 13, 0 , 0 , 0 , 0 , 0 } }, // #31 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 0 , 0 , 0 , 0 , 0 } }, // #32 [ref=8x] - { InstDB::RWInfo::kCategoryGeneric , 21, { 48, 0 , 0 , 0 , 0 , 0 } }, // #33 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 7 , { 49, 0 , 0 , 0 , 0 , 0 } }, // #34 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 20, { 11, 0 , 0 , 0 , 0 , 0 } }, // #35 [ref=2x] - { InstDB::RWInfo::kCategoryImul , 22, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #36 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 53, 0 , 0 , 0 , 0 , 0 } }, // #37 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 26, 0 , 0 , 0 , 0 , 0 } }, // #38 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 4 , 9 , 0 , 0 , 0 , 0 } }, // #39 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 4 , 5 , 0 , 0 , 0 , 0 } }, // #40 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 56, 40, 40, 0 , 0 , 0 } }, // #41 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 44, 9 , 9 , 0 , 0 , 0 } }, // #42 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 7 , 7 , 0 , 0 , 0 } }, // #43 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 48, 13, 13, 0 , 0 , 0 } }, // #44 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 56, 40, 0 , 0 , 0 , 0 } }, // #45 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 44, 9 , 0 , 0 , 0 , 0 } }, // #46 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #47 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 48, 13, 0 , 0 , 0 , 0 } }, // #48 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 48, 40, 40, 0 , 0 , 0 } }, // #49 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 9 , 9 , 0 , 0 , 0 } }, // #50 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 44, 13, 13, 0 , 0 , 0 } }, // #51 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 57, 0 , 0 , 0 , 0 , 0 } }, // #52 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 28, { 9 , 0 , 0 , 0 , 0 , 0 } }, // #53 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 16, { 43, 0 , 0 , 0 , 0 , 0 } }, // #54 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 7 , { 13, 0 , 0 , 0 , 0 , 0 } }, // #55 [ref=5x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 3 , 0 , 0 , 0 , 0 , 0 } }, // #56 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 3 , 9 , 0 , 0 , 0 , 0 } }, // #57 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 5 , 5 , 59, 0 , 0 , 0 } }, // #58 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 7 , 7 , 59, 0 , 0 , 0 } }, // #59 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 19, 29, 60, 0 , 0 , 0 } }, // #60 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 32, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #61 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 64, 42, 3 , 0 , 0 , 0 } }, // #62 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 11, 3 , 65, 0 , 0 } }, // #63 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 17, 29, 30, 0 , 0 , 0 } }, // #64 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 10, { 3 , 0 , 0 , 0 , 0 , 0 } }, // #65 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #66 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 67, 17, 60 } }, // #67 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 68, 17, 60 } }, // #68 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 67, 0 , 0 } }, // #69 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 68, 0 , 0 } }, // #70 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 34, { 56, 5 , 0 , 0 , 0 , 0 } }, // #71 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 35, { 35, 5 , 0 , 0 , 0 , 0 } }, // #72 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 37, { 48, 3 , 0 , 0 , 0 , 0 } }, // #73 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 15, { 4 , 40, 0 , 0 , 0 , 0 } }, // #74 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 4 , 7 , 0 , 0 , 0 , 0 } }, // #75 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 27, { 2 , 13, 0 , 0 , 0 , 0 } }, // #76 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 10, { 70, 0 , 0 , 0 , 0 , 0 } }, // #77 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #78 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 10, { 65, 0 , 0 , 0 , 0 , 0 } }, // #79 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 11, 0 , 0 , 0 , 0 , 0 } }, // #80 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 50, 29, 0 , 0 , 0 } }, // #81 [ref=5x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 44, 0 , 0 , 0 , 0 , 0 } }, // #82 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 0 , 0 , 0 , 0 , 0 } }, // #83 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 50, 67, 0 , 0 , 0 } }, // #84 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #85 [ref=19x] - { InstDB::RWInfo::kCategoryGeneric , 4 , { 36, 7 , 0 , 0 , 0 , 0 } }, // #86 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 37, 9 , 0 , 0 , 0 , 0 } }, // #87 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 72, 0 , 0 , 0 , 0 , 0 } }, // #88 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 7 , 0 , 0 , 0 , 0 , 0 } }, // #89 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 34, { 73, 0 , 0 , 0 , 0 , 0 } }, // #90 [ref=30x] - { InstDB::RWInfo::kCategoryGeneric , 11, { 2 , 3 , 71, 0 , 0 , 0 } }, // #91 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 39, { 11, 0 , 0 , 0 , 0 , 0 } }, // #92 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 28, { 44, 0 , 0 , 0 , 0 , 0 } }, // #93 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 16, { 74, 0 , 0 , 0 , 0 , 0 } }, // #94 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 75, 43, 43, 0 , 0 , 0 } }, // #95 [ref=5x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 74, 0 , 0 , 0 , 0 , 0 } }, // #96 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 9 , 60, 17, 0 , 0 , 0 } }, // #97 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 75, 76, 77, 77, 77, 5 } }, // #98 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 4 , 78, 79, 79, 79, 5 } }, // #99 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 10, 5 , 7 , 0 , 0 , 0 } }, // #100 [ref=8x] - { InstDB::RWInfo::kCategoryGeneric , 41, { 10, 5 , 13, 0 , 0 , 0 } }, // #101 [ref=7x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 10, 5 , 9 , 0 , 0 , 0 } }, // #102 [ref=9x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 3 , 3 , 3 , 0 , 0 } }, // #103 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 35, 3 , 3 , 0 , 0 , 0 } }, // #104 [ref=18x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 11, 5 , 7 , 0 , 0 , 0 } }, // #105 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 41, { 35, 13, 13, 0 , 0 , 0 } }, // #106 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 11, 5 , 9 , 0 , 0 , 0 } }, // #107 [ref=1x] - { InstDB::RWInfo::kCategoryVmov1_2 , 48, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #108 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 10, 5 , 5 , 0 , 0 , 0 } }, // #109 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 10, 82, 7 , 0 , 0 , 0 } }, // #110 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 41, { 10, 5 , 5 , 0 , 0 , 0 } }, // #111 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 49, { 10, 61, 3 , 0 , 0 , 0 } }, // #112 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 49, { 10, 3 , 3 , 0 , 0 , 0 } }, // #113 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 49, { 10, 82, 3 , 0 , 0 , 0 } }, // #114 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 10, 61, 9 , 0 , 0 , 0 } }, // #115 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 10, 5 , 5 , 0 , 0 , 0 } }, // #116 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 50, { 10, 5 , 5 , 0 , 0 , 0 } }, // #117 [ref=9x] - { InstDB::RWInfo::kCategoryGeneric , 52, { 10, 81, 0 , 0 , 0 , 0 } }, // #118 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 52, { 10, 3 , 0 , 0 , 0 , 0 } }, // #119 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 53, { 80, 43, 0 , 0 , 0 , 0 } }, // #120 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 2 , 3 , 3 , 0 , 0 , 0 } }, // #121 [ref=82x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 4 , 5 , 5 , 0 , 0 , 0 } }, // #122 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 4 , 61, 7 , 0 , 0 , 0 } }, // #123 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 4 , 82, 9 , 0 , 0 , 0 } }, // #124 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 6 , 7 , 7 , 0 , 0 , 0 } }, // #125 [ref=11x] - { InstDB::RWInfo::kCategoryGeneric , 41, { 4 , 5 , 5 , 0 , 0 , 0 } }, // #126 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 8 , 9 , 9 , 0 , 0 , 0 } }, // #127 [ref=11x] - { InstDB::RWInfo::kCategoryGeneric , 54, { 11, 3 , 3 , 3 , 0 , 0 } }, // #128 [ref=15x] - { InstDB::RWInfo::kCategoryGeneric , 55, { 35, 7 , 7 , 7 , 0 , 0 } }, // #129 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 56, { 44, 9 , 9 , 9 , 0 , 0 } }, // #130 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 41, { 4 , 5 , 13, 0 , 0 , 0 } }, // #131 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 26, 7 , 7 , 0 , 0 , 0 } }, // #132 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 53, 9 , 9 , 0 , 0 , 0 } }, // #133 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 14, { 35, 3 , 0 , 0 , 0 , 0 } }, // #134 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 27, { 35, 13, 0 , 0 , 0 , 0 } }, // #135 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 35, 9 , 0 , 0 , 0 , 0 } }, // #136 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 2 , 3 , 2 , 0 , 0 , 0 } }, // #137 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 2 , 3 , 2 , 0 , 0 , 0 } }, // #138 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 18, { 4 , 3 , 4 , 0 , 0 , 0 } }, // #139 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 10, 61, 7 , 0 , 0 , 0 } }, // #140 [ref=11x] - { InstDB::RWInfo::kCategoryGeneric , 41, { 10, 83, 13, 0 , 0 , 0 } }, // #141 [ref=7x] - { InstDB::RWInfo::kCategoryGeneric , 42, { 10, 82, 9 , 0 , 0 , 0 } }, // #142 [ref=13x] - { InstDB::RWInfo::kCategoryGeneric , 50, { 80, 81, 5 , 0 , 0 , 0 } }, // #143 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 50, { 11, 3 , 5 , 0 , 0 , 0 } }, // #144 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 57, { 74, 43, 81, 0 , 0 , 0 } }, // #145 [ref=4x] - { InstDB::RWInfo::kCategoryVmaskmov , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #146 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 0 , 0 , 0 , 0 , 0 } }, // #147 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 22, 0 , 0 , 0 , 0 , 0 } }, // #148 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 61, 61, 0 , 0 , 0 } }, // #149 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 10, 7 , 7 , 0 , 0 , 0 } }, // #150 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 7 , 7 , 0 , 0 , 0 } }, // #151 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 10, 61, 7 , 0 , 0 , 0 } }, // #152 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 61, 7 , 0 , 0 , 0 } }, // #153 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 83, 13, 0 , 0 , 0 } }, // #154 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 82, 9 , 0 , 0 , 0 } }, // #155 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 84, 0 , 0 , 0 , 0 , 0 } }, // #156 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 60, { 85, 86, 3 , 3 , 0 , 0 } }, // #157 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 74, 76, 77, 77, 77, 5 } }, // #158 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 57, { 80, 81, 81, 0 , 0 , 0 } }, // #159 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 22, { 11, 3 , 3 , 0 , 0 , 0 } }, // #160 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 7 , { 48, 5 , 0 , 0 , 0 , 0 } }, // #161 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 61, { 10, 5 , 40, 0 , 0 , 0 } }, // #162 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 50, { 10, 5 , 5 , 5 , 0 , 0 } }, // #163 [ref=12x] - { InstDB::RWInfo::kCategoryGeneric , 65, { 10, 5 , 5 , 5 , 0 , 0 } }, // #164 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 66, { 10, 5 , 5 , 0 , 0 , 0 } }, // #165 [ref=12x] - { InstDB::RWInfo::kCategoryGeneric , 67, { 11, 3 , 5 , 0 , 0 , 0 } }, // #166 [ref=5x] - { InstDB::RWInfo::kCategoryGeneric , 68, { 11, 3 , 0 , 0 , 0 , 0 } }, // #167 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 69, { 11, 3 , 5 , 0 , 0 , 0 } }, // #168 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 22, { 11, 3 , 5 , 0 , 0 , 0 } }, // #169 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 60, 17, 29, 0 , 0 , 0 } }, // #170 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 3 , 60, 17, 0 , 0 , 0 } }, // #171 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 60, 17, 0 , 0 , 0 } } // #172 [ref=8x] + { InstDB::RWInfo::kCategoryGeneric , 19, { 48, 0 , 0 , 0 , 0 , 0 } }, // #28 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 20, { 3 , 0 , 0 , 0 , 0 , 0 } }, // #29 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 47, 0 , 0 , 0 , 0 , 0 } }, // #30 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 11, 0 , 0 , 0 , 0 , 0 } }, // #31 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 21, { 13, 0 , 0 , 0 , 0 , 0 } }, // #32 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 0 , 0 , 0 , 0 , 0 } }, // #33 [ref=8x] + { InstDB::RWInfo::kCategoryGeneric , 21, { 49, 0 , 0 , 0 , 0 , 0 } }, // #34 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 7 , { 50, 0 , 0 , 0 , 0 , 0 } }, // #35 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 20, { 11, 0 , 0 , 0 , 0 , 0 } }, // #36 [ref=2x] + { InstDB::RWInfo::kCategoryImul , 22, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #37 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 54, 0 , 0 , 0 , 0 , 0 } }, // #38 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 26, 0 , 0 , 0 , 0 , 0 } }, // #39 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 4 , 9 , 0 , 0 , 0 , 0 } }, // #40 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 4 , 5 , 0 , 0 , 0 , 0 } }, // #41 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 22, 56, 57, 0 , 0 , 0 } }, // #42 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 58, 40, 40, 0 , 0 , 0 } }, // #43 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 45, 9 , 9 , 0 , 0 , 0 } }, // #44 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 7 , 7 , 0 , 0 , 0 } }, // #45 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 49, 13, 13, 0 , 0 , 0 } }, // #46 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 58, 40, 0 , 0 , 0 , 0 } }, // #47 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 45, 9 , 0 , 0 , 0 , 0 } }, // #48 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #49 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 49, 13, 0 , 0 , 0 , 0 } }, // #50 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 49, 40, 40, 0 , 0 , 0 } }, // #51 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 9 , 9 , 0 , 0 , 0 } }, // #52 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 45, 13, 13, 0 , 0 , 0 } }, // #53 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 59, 0 , 0 , 0 , 0 , 0 } }, // #54 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 28, { 9 , 0 , 0 , 0 , 0 , 0 } }, // #55 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 13, { 44, 0 , 0 , 0 , 0 , 0 } }, // #56 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 7 , { 13, 0 , 0 , 0 , 0 , 0 } }, // #57 [ref=5x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 3 , 0 , 0 , 0 , 0 , 0 } }, // #58 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 3 , 9 , 0 , 0 , 0 , 0 } }, // #59 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 5 , 5 , 61, 0 , 0 , 0 } }, // #60 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 7 , 7 , 62, 0 , 0 , 0 } }, // #61 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 63, 29, 56, 0 , 0 , 0 } }, // #62 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 32, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #63 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 67, 42, 3 , 0 , 0 , 0 } }, // #64 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 11, 3 , 68, 0 , 0 } }, // #65 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 17, 29, 30, 0 , 0 , 0 } }, // #66 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 10, { 3 , 0 , 0 , 0 , 0 , 0 } }, // #67 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #68 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 70, 17, 56 } }, // #69 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 71, 17, 56 } }, // #70 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 70, 0 , 0 } }, // #71 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 3 , { 5 , 5 , 0 , 71, 0 , 0 } }, // #72 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 34, { 58, 5 , 0 , 0 , 0 , 0 } }, // #73 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 35, { 35, 5 , 0 , 0 , 0 , 0 } }, // #74 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 37, { 49, 3 , 0 , 0 , 0 , 0 } }, // #75 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 17, { 4 , 40, 0 , 0 , 0 , 0 } }, // #76 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 4 , 7 , 0 , 0 , 0 , 0 } }, // #77 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 2 , 13, 0 , 0 , 0 , 0 } }, // #78 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 10, { 11, 0 , 0 , 0 , 0 , 0 } }, // #79 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #80 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 11, 0 , 0 , 0 , 0 , 0 } }, // #81 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 51, 29, 0 , 0 , 0 } }, // #82 [ref=5x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 45, 0 , 0 , 0 , 0 , 0 } }, // #83 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 0 , 0 , 0 , 0 , 0 } }, // #84 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 51, 70, 0 , 0 , 0 } }, // #85 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #86 [ref=19x] + { InstDB::RWInfo::kCategoryGeneric , 4 , { 36, 7 , 0 , 0 , 0 , 0 } }, // #87 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 37, 9 , 0 , 0 , 0 , 0 } }, // #88 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 74, 0 , 0 , 0 , 0 , 0 } }, // #89 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 7 , 0 , 0 , 0 , 0 , 0 } }, // #90 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 34, { 75, 0 , 0 , 0 , 0 , 0 } }, // #91 [ref=30x] + { InstDB::RWInfo::kCategoryGeneric , 11, { 2 , 3 , 73, 0 , 0 , 0 } }, // #92 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 39, { 11, 0 , 0 , 0 , 0 , 0 } }, // #93 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 28, { 45, 0 , 0 , 0 , 0 , 0 } }, // #94 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 13, { 43, 0 , 0 , 0 , 0 , 0 } }, // #95 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 76, 44, 44, 0 , 0 , 0 } }, // #96 [ref=8x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 43, 0 , 0 , 0 , 0 , 0 } }, // #97 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 9 , 56, 17, 0 , 0 , 0 } }, // #98 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 76, 77, 78, 78, 78, 5 } }, // #99 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 4 , 79, 80, 80, 80, 5 } }, // #100 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 10, 5 , 7 , 0 , 0 , 0 } }, // #101 [ref=8x] + { InstDB::RWInfo::kCategoryGeneric , 41, { 10, 5 , 13, 0 , 0 , 0 } }, // #102 [ref=7x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 10, 5 , 9 , 0 , 0 , 0 } }, // #103 [ref=9x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 3 , 3 , 3 , 0 , 0 } }, // #104 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 35, 3 , 3 , 0 , 0 , 0 } }, // #105 [ref=18x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 11, 5 , 7 , 0 , 0 , 0 } }, // #106 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 41, { 35, 13, 13, 0 , 0 , 0 } }, // #107 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 11, 5 , 9 , 0 , 0 , 0 } }, // #108 [ref=1x] + { InstDB::RWInfo::kCategoryVmov1_2 , 48, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #109 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 10, 5 , 5 , 0 , 0 , 0 } }, // #110 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 10, 83, 7 , 0 , 0 , 0 } }, // #111 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 41, { 10, 5 , 5 , 0 , 0 , 0 } }, // #112 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 49, { 10, 64, 3 , 0 , 0 , 0 } }, // #113 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 49, { 10, 3 , 3 , 0 , 0 , 0 } }, // #114 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 49, { 10, 83, 3 , 0 , 0 , 0 } }, // #115 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 10, 64, 9 , 0 , 0 , 0 } }, // #116 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 10, 5 , 5 , 0 , 0 , 0 } }, // #117 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 50, { 10, 5 , 5 , 0 , 0 , 0 } }, // #118 [ref=9x] + { InstDB::RWInfo::kCategoryGeneric , 52, { 10, 82, 0 , 0 , 0 , 0 } }, // #119 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 52, { 10, 3 , 0 , 0 , 0 , 0 } }, // #120 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 53, { 81, 44, 0 , 0 , 0 , 0 } }, // #121 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 84, 3 , 3 , 0 , 0 , 0 } }, // #122 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 85, 5 , 5 , 0 , 0 , 0 } }, // #123 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 2 , 3 , 3 , 0 , 0 , 0 } }, // #124 [ref=90x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 4 , 64, 7 , 0 , 0 , 0 } }, // #125 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 4 , 83, 9 , 0 , 0 , 0 } }, // #126 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 6 , 7 , 7 , 0 , 0 , 0 } }, // #127 [ref=11x] + { InstDB::RWInfo::kCategoryGeneric , 41, { 4 , 5 , 5 , 0 , 0 , 0 } }, // #128 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 8 , 9 , 9 , 0 , 0 , 0 } }, // #129 [ref=11x] + { InstDB::RWInfo::kCategoryGeneric , 54, { 11, 3 , 3 , 3 , 0 , 0 } }, // #130 [ref=15x] + { InstDB::RWInfo::kCategoryGeneric , 55, { 35, 7 , 7 , 7 , 0 , 0 } }, // #131 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 56, { 45, 9 , 9 , 9 , 0 , 0 } }, // #132 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 41, { 4 , 5 , 13, 0 , 0 , 0 } }, // #133 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 26, 7 , 7 , 0 , 0 , 0 } }, // #134 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 54, 9 , 9 , 0 , 0 , 0 } }, // #135 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 16, { 35, 3 , 0 , 0 , 0 , 0 } }, // #136 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 35, 13, 0 , 0 , 0 , 0 } }, // #137 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 35, 9 , 0 , 0 , 0 , 0 } }, // #138 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 2 , 3 , 2 , 0 , 0 , 0 } }, // #139 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 2 , 3 , 2 , 0 , 0 , 0 } }, // #140 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 4 , 3 , 4 , 0 , 0 , 0 } }, // #141 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 10, 64, 7 , 0 , 0 , 0 } }, // #142 [ref=11x] + { InstDB::RWInfo::kCategoryGeneric , 41, { 10, 86, 13, 0 , 0 , 0 } }, // #143 [ref=7x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 10, 83, 9 , 0 , 0 , 0 } }, // #144 [ref=13x] + { InstDB::RWInfo::kCategoryGeneric , 50, { 81, 82, 5 , 0 , 0 , 0 } }, // #145 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 50, { 11, 3 , 5 , 0 , 0 , 0 } }, // #146 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 57, { 43, 44, 82, 0 , 0 , 0 } }, // #147 [ref=4x] + { InstDB::RWInfo::kCategoryVmaskmov , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #148 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 0 , 0 , 0 , 0 , 0 } }, // #149 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 22, 0 , 0 , 0 , 0 , 0 } }, // #150 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 64, 64, 0 , 0 , 0 } }, // #151 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 10, 7 , 7 , 0 , 0 , 0 } }, // #152 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 7 , 7 , 0 , 0 , 0 } }, // #153 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 10, 64, 7 , 0 , 0 , 0 } }, // #154 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 64, 7 , 0 , 0 , 0 } }, // #155 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 86, 13, 0 , 0 , 0 } }, // #156 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 83, 9 , 0 , 0 , 0 } }, // #157 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 87, 0 , 0 , 0 , 0 , 0 } }, // #158 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 60, { 88, 89, 3 , 3 , 0 , 0 } }, // #159 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 43, 77, 78, 78, 78, 5 } }, // #160 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 57, { 81, 82, 82, 0 , 0 , 0 } }, // #161 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 22, { 11, 3 , 3 , 0 , 0 , 0 } }, // #162 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 7 , { 49, 5 , 0 , 0 , 0 , 0 } }, // #163 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 61, { 10, 5 , 40, 0 , 0 , 0 } }, // #164 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 50, { 10, 5 , 5 , 5 , 0 , 0 } }, // #165 [ref=12x] + { InstDB::RWInfo::kCategoryGeneric , 65, { 10, 5 , 5 , 5 , 0 , 0 } }, // #166 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 66, { 10, 5 , 5 , 0 , 0 , 0 } }, // #167 [ref=12x] + { InstDB::RWInfo::kCategoryGeneric , 67, { 11, 3 , 5 , 0 , 0 , 0 } }, // #168 [ref=5x] + { InstDB::RWInfo::kCategoryGeneric , 68, { 11, 3 , 0 , 0 , 0 , 0 } }, // #169 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 69, { 11, 3 , 5 , 0 , 0 , 0 } }, // #170 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 22, { 11, 3 , 5 , 0 , 0 , 0 } }, // #171 [ref=1x] + { InstDB::RWInfo::kCategoryGenericEx , 6 , { 2 , 3 , 3 , 0 , 0 , 0 } }, // #172 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 90, 82, 5 , 0 , 0 , 0 } }, // #173 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 50, { 4 , 5 , 5 , 0 , 0 , 0 } }, // #174 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 56, 17, 29, 0 , 0 , 0 } }, // #175 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 3 , 56, 17, 0 , 0 , 0 } }, // #176 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 56, 17, 0 , 0 , 0 } } // #177 [ref=8x] }; const InstDB::RWInfoOp InstDB::rwInfoOp[] = { - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kNone }, // #0 [ref=16519x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kNone }, // #0 [ref=17086x] { 0x0000000000000003u, 0x0000000000000003u, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId }, // #1 [ref=10x] - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #2 [ref=236x] - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #3 [ref=1077x] - { 0x000000000000FFFFu, 0x000000000000FFFFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #4 [ref=108x] - { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #5 [ref=348x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #2 [ref=282x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #3 [ref=1132x] + { 0x000000000000FFFFu, 0x000000000000FFFFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #4 [ref=107x] + { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #5 [ref=356x] { 0x00000000000000FFu, 0x00000000000000FFu, 0xFF, 0, { 0 }, OpRWFlags::kRW }, // #6 [ref=18x] { 0x00000000000000FFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #7 [ref=186x] { 0x000000000000000Fu, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kRW }, // #8 [ref=18x] { 0x000000000000000Fu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #9 [ref=135x] { 0x0000000000000000u, 0x000000000000FFFFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #10 [ref=184x] - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #11 [ref=455x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #11 [ref=459x] { 0x0000000000000003u, 0x0000000000000003u, 0xFF, 0, { 0 }, OpRWFlags::kRW }, // #12 [ref=1x] - { 0x0000000000000003u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #13 [ref=63x] + { 0x0000000000000003u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #13 [ref=65x] { 0x000000000000FFFFu, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #14 [ref=4x] { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kMemBaseWrite | OpRWFlags::kMemIndexWrite }, // #15 [ref=1x] { 0x0000000000000000u, 0x000000000000000Fu, 0x02, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #16 [ref=9x] { 0x000000000000000Fu, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #17 [ref=23x] { 0x00000000000000FFu, 0x00000000000000FFu, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #18 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemPhysId }, // #19 [ref=3x] + { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemPhysId }, // #19 [ref=1x] { 0x0000000000000000u, 0x0000000000000000u, 0x06, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemBaseRW | OpRWFlags::kMemBasePostModify | OpRWFlags::kMemPhysId }, // #20 [ref=3x] { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemBaseRW | OpRWFlags::kMemBasePostModify | OpRWFlags::kMemPhysId }, // #21 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #22 [ref=7x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #22 [ref=8x] { 0x00000000000000FFu, 0x00000000000000FFu, 0x02, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #23 [ref=1x] { 0x00000000000000FFu, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #24 [ref=1x] { 0x00000000000000FFu, 0x0000000000000000u, 0x03, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #25 [ref=1x] { 0x00000000000000FFu, 0x00000000000000FFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #26 [ref=21x] { 0x000000000000000Fu, 0x000000000000000Fu, 0x02, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #27 [ref=1x] - { 0x000000000000000Fu, 0x000000000000000Fu, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #28 [ref=4x] + { 0x000000000000000Fu, 0x000000000000000Fu, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #28 [ref=5x] { 0x000000000000000Fu, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #29 [ref=13x] { 0x000000000000000Fu, 0x0000000000000000u, 0x03, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #30 [ref=2x] { 0x0000000000000000u, 0x000000000000000Fu, 0x03, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #31 [ref=1x] @@ -4276,75 +6016,79 @@ const InstDB::RWInfoOp InstDB::rwInfoOp[] = { { 0x0000000000000001u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #40 [ref=28x] { 0x0000000000000000u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #41 [ref=2x] { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #42 [ref=3x] - { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #43 [ref=29x] - { 0x0000000000000000u, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #44 [ref=30x] - { 0x00000000000003FFu, 0x00000000000003FFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #45 [ref=22x] - { 0x00000000000003FFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #46 [ref=13x] - { 0x0000000000000000u, 0x00000000000003FFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #47 [ref=1x] - { 0x0000000000000000u, 0x0000000000000003u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #48 [ref=17x] - { 0x0000000000000000u, 0x0000000000000003u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #49 [ref=2x] - { 0x0000000000000000u, 0x000000000000000Fu, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #50 [ref=8x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #51 [ref=2x] - { 0x0000000000000003u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #52 [ref=4x] - { 0x000000000000000Fu, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #53 [ref=4x] - { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kMemPhysId }, // #54 [ref=1x] - { 0x0000000000000000u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #55 [ref=1x] - { 0x0000000000000000u, 0x0000000000000001u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #56 [ref=14x] - { 0x0000000000000000u, 0x0000000000000001u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId }, // #57 [ref=1x] - { 0x0000000000000000u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #58 [ref=3x] - { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kMemPhysId }, // #59 [ref=3x] - { 0x000000000000000Fu, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #60 [ref=22x] - { 0x000000000000FF00u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #61 [ref=23x] - { 0x0000000000000000u, 0x000000000000FF00u, 0xFF, 0, { 0 }, OpRWFlags::kWrite }, // #62 [ref=1x] - { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kMemBaseRW | OpRWFlags::kMemBasePostModify | OpRWFlags::kMemPhysId }, // #63 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #64 [ref=1x] - { 0x0000000000000000u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #65 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x06, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemPhysId }, // #66 [ref=1x] - { 0x0000000000000000u, 0x000000000000000Fu, 0x01, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #67 [ref=5x] - { 0x0000000000000000u, 0x000000000000FFFFu, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #68 [ref=4x] - { 0x0000000000000000u, 0x0000000000000007u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #69 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x04, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #70 [ref=1x] - { 0x0000000000000001u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #71 [ref=10x] - { 0x0000000000000001u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #72 [ref=1x] - { 0x0000000000000000u, 0x0000000000000001u, 0xFF, 0, { 0 }, OpRWFlags::kWrite }, // #73 [ref=30x] - { 0x0000000000000000u, 0xFFFFFFFFFFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #74 [ref=20x] - { 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #75 [ref=7x] - { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 4, { 0 }, OpRWFlags::kRead }, // #76 [ref=4x] - { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kConsecutive }, // #77 [ref=12x] - { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 4, { 0 }, OpRWFlags::kRead }, // #78 [ref=2x] - { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kConsecutive }, // #79 [ref=6x] - { 0x0000000000000000u, 0x00000000FFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #80 [ref=10x] - { 0x00000000FFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #81 [ref=16x] - { 0x000000000000FFF0u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #82 [ref=18x] - { 0x000000000000FFFCu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #83 [ref=8x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #84 [ref=1x] - { 0x0000000000000000u, 0x00000000000000FFu, 0xFF, 2, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #85 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kConsecutive } // #86 [ref=2x] + { 0x0000000000000000u, 0xFFFFFFFFFFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #43 [ref=23x] + { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #44 [ref=35x] + { 0x0000000000000000u, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #45 [ref=30x] + { 0x00000000000003FFu, 0x00000000000003FFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #46 [ref=22x] + { 0x00000000000003FFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #47 [ref=13x] + { 0x0000000000000000u, 0x00000000000003FFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #48 [ref=1x] + { 0x0000000000000000u, 0x0000000000000003u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #49 [ref=17x] + { 0x0000000000000000u, 0x0000000000000003u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #50 [ref=2x] + { 0x0000000000000000u, 0x000000000000000Fu, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #51 [ref=8x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #52 [ref=2x] + { 0x0000000000000003u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #53 [ref=4x] + { 0x000000000000000Fu, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #54 [ref=4x] + { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kMemPhysId }, // #55 [ref=1x] + { 0x000000000000000Fu, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #56 [ref=23x] + { 0x0000000000000000u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #57 [ref=2x] + { 0x0000000000000000u, 0x0000000000000001u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #58 [ref=14x] + { 0x0000000000000000u, 0x0000000000000001u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId }, // #59 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #60 [ref=3x] + { 0x000000000000FFFFu, 0x000000000000FFFFu, 0x07, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kMemPhysId }, // #61 [ref=2x] + { 0x00000000000000FFu, 0x00000000000000FFu, 0x07, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kMemPhysId }, // #62 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemPhysId }, // #63 [ref=2x] + { 0x000000000000FF00u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #64 [ref=23x] + { 0x0000000000000000u, 0x000000000000FF00u, 0xFF, 0, { 0 }, OpRWFlags::kWrite }, // #65 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kMemBaseRW | OpRWFlags::kMemBasePostModify | OpRWFlags::kMemPhysId }, // #66 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #67 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #68 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x06, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemPhysId }, // #69 [ref=1x] + { 0x0000000000000000u, 0x000000000000000Fu, 0x01, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #70 [ref=5x] + { 0x0000000000000000u, 0x000000000000FFFFu, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #71 [ref=4x] + { 0x0000000000000000u, 0x0000000000000007u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #72 [ref=2x] + { 0x0000000000000001u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #73 [ref=10x] + { 0x0000000000000001u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #74 [ref=1x] + { 0x0000000000000000u, 0x0000000000000001u, 0xFF, 0, { 0 }, OpRWFlags::kWrite }, // #75 [ref=30x] + { 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #76 [ref=10x] + { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 4, { 0 }, OpRWFlags::kRead }, // #77 [ref=4x] + { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kConsecutive }, // #78 [ref=12x] + { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 4, { 0 }, OpRWFlags::kRead }, // #79 [ref=2x] + { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kConsecutive }, // #80 [ref=6x] + { 0x0000000000000000u, 0x00000000FFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #81 [ref=10x] + { 0x00000000FFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #82 [ref=18x] + { 0x000000000000FFF0u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #83 [ref=18x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kUnique | OpRWFlags::kZExt }, // #84 [ref=4x] + { 0x000000000000FFFFu, 0x000000000000FFFFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kUnique | OpRWFlags::kZExt }, // #85 [ref=4x] + { 0x000000000000FFFCu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #86 [ref=8x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #87 [ref=1x] + { 0x0000000000000000u, 0x00000000000000FFu, 0xFF, 2, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #88 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kConsecutive }, // #89 [ref=2x] + { 0x00000000FFFFFFFFu, 0x00000000FFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt } // #90 [ref=3x] }; const InstDB::RWInfoRm InstDB::rwInfoRm[] = { - { InstDB::RWInfoRm::kCategoryNone , 0x00, 0 , 0, 0 }, // #0 [ref=1997x] + { InstDB::RWInfoRm::kCategoryNone , 0x00, 0 , 0, 0 }, // #0 [ref=2083x] { InstDB::RWInfoRm::kCategoryConsistent, 0x03, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #1 [ref=8x] { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , 0, 0 }, // #2 [ref=204x] { InstDB::RWInfoRm::kCategoryFixed , 0x02, 16, 0, 0 }, // #3 [ref=122x] { InstDB::RWInfoRm::kCategoryFixed , 0x02, 8 , 0, 0 }, // #4 [ref=66x] { InstDB::RWInfoRm::kCategoryFixed , 0x02, 4 , 0, 0 }, // #5 [ref=35x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x04, 0 , 0, 0 }, // #6 [ref=300x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x04, 0 , 0, 0 }, // #6 [ref=314x] { InstDB::RWInfoRm::kCategoryFixed , 0x01, 2 , 0, 0 }, // #7 [ref=9x] - { InstDB::RWInfoRm::kCategoryFixed , 0x00, 0 , 0, 0 }, // #8 [ref=63x] + { InstDB::RWInfoRm::kCategoryFixed , 0x00, 0 , 0, 0 }, // #8 [ref=68x] { InstDB::RWInfoRm::kCategoryFixed , 0x03, 0 , 0, 0 }, // #9 [ref=1x] { InstDB::RWInfoRm::kCategoryConsistent, 0x01, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #10 [ref=21x] { InstDB::RWInfoRm::kCategoryConsistent, 0x01, 0 , 0, 0 }, // #11 [ref=14x] - { InstDB::RWInfoRm::kCategoryFixed , 0x00, 8 , 0, 0 }, // #12 [ref=22x] - { InstDB::RWInfoRm::kCategoryFixed , 0x00, 16, 0, 0 }, // #13 [ref=21x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #14 [ref=22x] - { InstDB::RWInfoRm::kCategoryFixed , 0x02, 1 , 0, 0 }, // #15 [ref=5x] - { InstDB::RWInfoRm::kCategoryFixed , 0x00, 64, 0, 0 }, // #16 [ref=5x] - { InstDB::RWInfoRm::kCategoryFixed , 0x01, 4 , 0, 0 }, // #17 [ref=6x] - { InstDB::RWInfoRm::kCategoryNone , 0x00, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #18 [ref=26x] + { InstDB::RWInfoRm::kCategoryFixed , 0x00, 8 , 0, 0 }, // #12 [ref=23x] + { InstDB::RWInfoRm::kCategoryFixed , 0x00, 64, 0, 0 }, // #13 [ref=6x] + { InstDB::RWInfoRm::kCategoryNone , 0x00, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #14 [ref=30x] + { InstDB::RWInfoRm::kCategoryFixed , 0x00, 16, 0, 0 }, // #15 [ref=23x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #16 [ref=22x] + { InstDB::RWInfoRm::kCategoryFixed , 0x02, 1 , 0, 0 }, // #17 [ref=5x] + { InstDB::RWInfoRm::kCategoryFixed , 0x01, 4 , 0, 0 }, // #18 [ref=6x] { InstDB::RWInfoRm::kCategoryFixed , 0x00, 10, 0, 0 }, // #19 [ref=2x] { InstDB::RWInfoRm::kCategoryNone , 0x01, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #20 [ref=5x] - { InstDB::RWInfoRm::kCategoryFixed , 0x00, 2 , 0, 0 }, // #21 [ref=4x] + { InstDB::RWInfoRm::kCategoryFixed , 0x00, 2 , 0, 0 }, // #21 [ref=6x] { InstDB::RWInfoRm::kCategoryConsistent, 0x06, 0 , 0, 0 }, // #22 [ref=6x] { InstDB::RWInfoRm::kCategoryFixed , 0x03, 1 , 0, 0 }, // #23 [ref=1x] { InstDB::RWInfoRm::kCategoryFixed , 0x03, 4 , 0, 0 }, // #24 [ref=3x] @@ -4373,7 +6117,7 @@ const InstDB::RWInfoRm InstDB::rwInfoRm[] = { { InstDB::RWInfoRm::kCategoryQuarter , 0x02, 0 , 0, 0 }, // #47 [ref=9x] { InstDB::RWInfoRm::kCategoryHalf , 0x01, 0 , 0, 0 }, // #48 [ref=10x] { InstDB::RWInfoRm::kCategoryConsistent, 0x04, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #49 [ref=6x] - { InstDB::RWInfoRm::kCategoryFixed , 0x04, 16, 0, 0 }, // #50 [ref=27x] + { InstDB::RWInfoRm::kCategoryFixed , 0x04, 16, 0, 0 }, // #50 [ref=30x] { InstDB::RWInfoRm::kCategoryFixed , 0x02, 64, 0, 0 }, // #51 [ref=6x] { InstDB::RWInfoRm::kCategoryFixed , 0x01, 16, 0, 0 }, // #52 [ref=6x] { InstDB::RWInfoRm::kCategoryFixed , 0x01, 32, 0, 0 }, // #53 [ref=4x] @@ -4405,20 +6149,33 @@ UNIT(x86_inst_db) { INFO("Checking validity of Inst enums"); // Cross-validate prefixes. - EXPECT(uint32_t(InstOptions::kX86_Rex ) == 0x40000000u, "REX prefix must be at 0x40000000"); - EXPECT(uint32_t(InstOptions::kX86_Evex) == 0x00001000u, "EVEX prefix must be at 0x00001000"); + EXPECT_EQ(uint32_t(InstOptions::kX86_Rex ), 0x40000000u) + .message("REX prefix must be at 0x40000000"); + + EXPECT_EQ(uint32_t(InstOptions::kX86_Evex), 0x00001000u) + .message("EVEX prefix must be at 0x00001000"); // These could be combined together to form a valid REX prefix, they must match. - EXPECT(uint32_t(InstOptions::kX86_OpCodeB) == uint32_t(Opcode::kB), "Opcode::kB must match InstOptions::kX86_OpCodeB"); - EXPECT(uint32_t(InstOptions::kX86_OpCodeX) == uint32_t(Opcode::kX), "Opcode::kX must match InstOptions::kX86_OpCodeX"); - EXPECT(uint32_t(InstOptions::kX86_OpCodeR) == uint32_t(Opcode::kR), "Opcode::kR must match InstOptions::kX86_OpCodeR"); - EXPECT(uint32_t(InstOptions::kX86_OpCodeW) == uint32_t(Opcode::kW), "Opcode::kW must match InstOptions::kX86_OpCodeW"); + EXPECT_EQ(uint32_t(InstOptions::kX86_OpCodeB), uint32_t(Opcode::kB)) + .message("Opcode::kB must match InstOptions::kX86_OpCodeB"); + + EXPECT_EQ(uint32_t(InstOptions::kX86_OpCodeX), uint32_t(Opcode::kX)) + .message("Opcode::kX must match InstOptions::kX86_OpCodeX"); + + EXPECT_EQ(uint32_t(InstOptions::kX86_OpCodeR), uint32_t(Opcode::kR)) + .message("Opcode::kR must match InstOptions::kX86_OpCodeR"); + + EXPECT_EQ(uint32_t(InstOptions::kX86_OpCodeW), uint32_t(Opcode::kW)) + .message("Opcode::kW must match InstOptions::kX86_OpCodeW"); uint32_t rex_rb = (Opcode::kR >> Opcode::kREX_Shift) | (Opcode::kB >> Opcode::kREX_Shift) | 0x40; uint32_t rex_rw = (Opcode::kR >> Opcode::kREX_Shift) | (Opcode::kW >> Opcode::kREX_Shift) | 0x40; - EXPECT(rex_rb == 0x45, "Opcode::kR|B must form a valid REX prefix (0x45) if combined with 0x40"); - EXPECT(rex_rw == 0x4C, "Opcode::kR|W must form a valid REX prefix (0x4C) if combined with 0x40"); + EXPECT_EQ(rex_rb, 0x45u) + .message("Opcode::kR|B must form a valid REX prefix (0x45) if combined with 0x40"); + + EXPECT_EQ(rex_rw, 0x4Cu) + .message("Opcode::kR|W must form a valid REX prefix (0x4C) if combined with 0x40"); } #endif diff --git a/3rdparty/asmjit/src/asmjit/x86/x86instdb.h b/3rdparty/asmjit/src/asmjit/x86/x86instdb.h index 87a286c2829..2bf7d148957 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86instdb.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86instdb.h @@ -30,7 +30,7 @@ enum class Mode : uint8_t { ASMJIT_DEFINE_ENUM_FLAGS(Mode) //! Converts architecture to operation mode, see \ref Mode. -static constexpr Mode modeFromArch(Arch arch) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mode modeFromArch(Arch arch) noexcept { return arch == Arch::kX86 ? Mode::kX86 : arch == Arch::kX64 ? Mode::kX64 : Mode::kNone; } @@ -348,92 +348,92 @@ struct CommonInfo { //! \{ //! Returns instruction flags. - inline InstFlags flags() const noexcept { return (InstFlags)_flags; } + ASMJIT_INLINE_NODEBUG InstFlags flags() const noexcept { return (InstFlags)_flags; } //! Tests whether the instruction has a `flag`. - inline bool hasFlag(InstFlags flag) const noexcept { return Support::test(_flags, flag); } + ASMJIT_INLINE_NODEBUG bool hasFlag(InstFlags flag) const noexcept { return Support::test(_flags, flag); } //! Returns instruction AVX-512 flags. - inline Avx512Flags avx512Flags() const noexcept { return (Avx512Flags)_avx512Flags; } + ASMJIT_INLINE_NODEBUG Avx512Flags avx512Flags() const noexcept { return (Avx512Flags)_avx512Flags; } //! Tests whether the instruction has an AVX-512 `flag`. - inline bool hasAvx512Flag(Avx512Flags flag) const noexcept { return Support::test(_avx512Flags, flag); } + ASMJIT_INLINE_NODEBUG bool hasAvx512Flag(Avx512Flags flag) const noexcept { return Support::test(_avx512Flags, flag); } //! Tests whether the instruction is FPU instruction. - inline bool isFpu() const noexcept { return hasFlag(InstFlags::kFpu); } + ASMJIT_INLINE_NODEBUG bool isFpu() const noexcept { return hasFlag(InstFlags::kFpu); } //! Tests whether the instruction is MMX/3DNOW instruction that accesses MMX registers (includes EMMS and FEMMS). - inline bool isMmx() const noexcept { return hasFlag(InstFlags::kMmx); } + ASMJIT_INLINE_NODEBUG bool isMmx() const noexcept { return hasFlag(InstFlags::kMmx); } //! Tests whether the instruction is SSE|AVX|AVX512 instruction that accesses XMM|YMM|ZMM registers. - inline bool isVec() const noexcept { return hasFlag(InstFlags::kVec); } + ASMJIT_INLINE_NODEBUG bool isVec() const noexcept { return hasFlag(InstFlags::kVec); } //! Tests whether the instruction is SSE+ (SSE4.2, AES, SHA included) instruction that accesses XMM registers. - inline bool isSse() const noexcept { return (flags() & (InstFlags::kVec | InstFlags::kVex | InstFlags::kEvex)) == InstFlags::kVec; } + ASMJIT_INLINE_NODEBUG bool isSse() const noexcept { return (flags() & (InstFlags::kVec | InstFlags::kVex | InstFlags::kEvex)) == InstFlags::kVec; } //! Tests whether the instruction is AVX+ (FMA included) instruction that accesses XMM|YMM|ZMM registers. - inline bool isAvx() const noexcept { return isVec() && isVexOrEvex(); } + ASMJIT_INLINE_NODEBUG bool isAvx() const noexcept { return isVec() && isVexOrEvex(); } //! Tests whether the instruction can be prefixed with LOCK prefix. - inline bool hasLockPrefix() const noexcept { return hasFlag(InstFlags::kLock); } + ASMJIT_INLINE_NODEBUG bool hasLockPrefix() const noexcept { return hasFlag(InstFlags::kLock); } //! Tests whether the instruction can be prefixed with REP (REPE|REPZ) prefix. - inline bool hasRepPrefix() const noexcept { return hasFlag(InstFlags::kRep); } + ASMJIT_INLINE_NODEBUG bool hasRepPrefix() const noexcept { return hasFlag(InstFlags::kRep); } //! Tests whether the instruction can be prefixed with XACQUIRE prefix. - inline bool hasXAcquirePrefix() const noexcept { return hasFlag(InstFlags::kXAcquire); } + ASMJIT_INLINE_NODEBUG bool hasXAcquirePrefix() const noexcept { return hasFlag(InstFlags::kXAcquire); } //! Tests whether the instruction can be prefixed with XRELEASE prefix. - inline bool hasXReleasePrefix() const noexcept { return hasFlag(InstFlags::kXRelease); } + ASMJIT_INLINE_NODEBUG bool hasXReleasePrefix() const noexcept { return hasFlag(InstFlags::kXRelease); } //! Tests whether the rep prefix is supported by the instruction, but ignored (has no effect). - inline bool isRepIgnored() const noexcept { return hasFlag(InstFlags::kRepIgnored); } + ASMJIT_INLINE_NODEBUG bool isRepIgnored() const noexcept { return hasFlag(InstFlags::kRepIgnored); } //! Tests whether the instruction uses MIB. - inline bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); } + ASMJIT_INLINE_NODEBUG bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); } //! Tests whether the instruction uses VSIB. - inline bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); } + ASMJIT_INLINE_NODEBUG bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); } //! Tests whether the instruction uses TSIB (AMX, instruction requires MOD+SIB). - inline bool isTsibOp() const noexcept { return hasFlag(InstFlags::kTsib); } + ASMJIT_INLINE_NODEBUG bool isTsibOp() const noexcept { return hasFlag(InstFlags::kTsib); } //! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable). - inline bool isVex() const noexcept { return hasFlag(InstFlags::kVex); } + ASMJIT_INLINE_NODEBUG bool isVex() const noexcept { return hasFlag(InstFlags::kVex); } //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable). - inline bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); } + ASMJIT_INLINE_NODEBUG bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); } //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable). - inline bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); } + ASMJIT_INLINE_NODEBUG bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); } //! Tests whether the instruction should prefer EVEX prefix instead of VEX prefix. - inline bool preferEvex() const noexcept { return hasFlag(InstFlags::kPreferEvex); } + ASMJIT_INLINE_NODEBUG bool preferEvex() const noexcept { return hasFlag(InstFlags::kPreferEvex); } - inline bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); } - inline bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); } - inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); } - inline bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); } + ASMJIT_INLINE_NODEBUG bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); } + ASMJIT_INLINE_NODEBUG bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); } + ASMJIT_INLINE_NODEBUG bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); } + ASMJIT_INLINE_NODEBUG bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); } //! Tests whether the instruction supports AVX512 masking {k}. - inline bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); } + ASMJIT_INLINE_NODEBUG bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); } //! Tests whether the instruction supports AVX512 zeroing {k}{z}. - inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); } + ASMJIT_INLINE_NODEBUG bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); } //! Tests whether the instruction supports AVX512 embedded-rounding {er}. - inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); } + ASMJIT_INLINE_NODEBUG bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); } //! Tests whether the instruction supports AVX512 suppress-all-exceptions {sae}. - inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); } + ASMJIT_INLINE_NODEBUG bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); } //! Tests whether the instruction supports AVX512 broadcast (either 32-bit or 64-bit). - inline bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); } + ASMJIT_INLINE_NODEBUG bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); } //! Tests whether the instruction supports AVX512 broadcast (16-bit). - inline bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); } + ASMJIT_INLINE_NODEBUG bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); } //! Tests whether the instruction supports AVX512 broadcast (32-bit). - inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); } + ASMJIT_INLINE_NODEBUG bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); } //! Tests whether the instruction supports AVX512 broadcast (64-bit). - inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); } + ASMJIT_INLINE_NODEBUG bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); } // Returns the size of the broadcast - either 2, 4, or 8, or 0 if broadcast is not supported. - inline uint32_t broadcastSize() const noexcept { + ASMJIT_INLINE_NODEBUG uint32_t broadcastSize() const noexcept { constexpr uint32_t kShift = Support::ConstCTZ<uint32_t(Avx512Flags::kB16)>::value; return (uint32_t(_avx512Flags) & uint32_t(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64)) >> (kShift - 1); } - inline uint32_t signatureIndex() const noexcept { return _iSignatureIndex; } - inline uint32_t signatureCount() const noexcept { return _iSignatureCount; } + ASMJIT_INLINE_NODEBUG uint32_t signatureIndex() const noexcept { return _iSignatureIndex; } + ASMJIT_INLINE_NODEBUG uint32_t signatureCount() const noexcept { return _iSignatureCount; } - inline const InstSignature* signatureData() const noexcept { return _instSignatureTable + _iSignatureIndex; } - inline const InstSignature* signatureEnd() const noexcept { return _instSignatureTable + _iSignatureIndex + _iSignatureCount; } + ASMJIT_INLINE_NODEBUG const InstSignature* signatureData() const noexcept { return _instSignatureTable + _iSignatureIndex; } + ASMJIT_INLINE_NODEBUG const InstSignature* signatureEnd() const noexcept { return _instSignatureTable + _iSignatureIndex + _iSignatureCount; } //! Returns a control flow category of the instruction. - inline InstControlFlow controlFlow() const noexcept { return (InstControlFlow)_controlFlow; } + ASMJIT_INLINE_NODEBUG InstControlFlow controlFlow() const noexcept { return (InstControlFlow)_controlFlow; } //! Returns a hint that can be used when both inputs are the same register. - inline InstSameRegHint sameRegHint() const noexcept { return (InstSameRegHint)_sameRegHint; } + ASMJIT_INLINE_NODEBUG InstSameRegHint sameRegHint() const noexcept { return (InstSameRegHint)_sameRegHint; } //! \} }; @@ -442,8 +442,8 @@ ASMJIT_VARAPI const CommonInfo _commonInfoTable[]; //! Instruction information. struct InstInfo { - //! Index to \ref _nameData. - uint32_t _nameDataIndex : 14; + //! Reserved for future use. + uint32_t _reserved : 14; //! Index to \ref _commonInfoTable. uint32_t _commonInfoIndex : 10; //! Index to \ref _additionalInfoTable. @@ -462,83 +462,83 @@ struct InstInfo { //! \{ //! Returns common information, see \ref CommonInfo. - inline const CommonInfo& commonInfo() const noexcept { return _commonInfoTable[_commonInfoIndex]; } + ASMJIT_INLINE_NODEBUG const CommonInfo& commonInfo() const noexcept { return _commonInfoTable[_commonInfoIndex]; } - //! Returns instruction flags, see \ref Flags. - inline InstFlags flags() const noexcept { return commonInfo().flags(); } - //! Tests whether the instruction has flag `flag`, see \ref Flags. - inline bool hasFlag(InstFlags flag) const noexcept { return commonInfo().hasFlag(flag); } + //! Returns instruction flags, see \ref InstFlags. + ASMJIT_INLINE_NODEBUG InstFlags flags() const noexcept { return commonInfo().flags(); } + //! Tests whether the instruction has flag `flag`, see \ref InstFlags. + ASMJIT_INLINE_NODEBUG bool hasFlag(InstFlags flag) const noexcept { return commonInfo().hasFlag(flag); } //! Returns instruction AVX-512 flags, see \ref Avx512Flags. - inline Avx512Flags avx512Flags() const noexcept { return commonInfo().avx512Flags(); } + ASMJIT_INLINE_NODEBUG Avx512Flags avx512Flags() const noexcept { return commonInfo().avx512Flags(); } //! Tests whether the instruction has an AVX-512 `flag`, see \ref Avx512Flags. - inline bool hasAvx512Flag(Avx512Flags flag) const noexcept { return commonInfo().hasAvx512Flag(flag); } + ASMJIT_INLINE_NODEBUG bool hasAvx512Flag(Avx512Flags flag) const noexcept { return commonInfo().hasAvx512Flag(flag); } //! Tests whether the instruction is FPU instruction. - inline bool isFpu() const noexcept { return commonInfo().isFpu(); } + ASMJIT_INLINE_NODEBUG bool isFpu() const noexcept { return commonInfo().isFpu(); } //! Tests whether the instruction is MMX/3DNOW instruction that accesses MMX registers (includes EMMS and FEMMS). - inline bool isMmx() const noexcept { return commonInfo().isMmx(); } + ASMJIT_INLINE_NODEBUG bool isMmx() const noexcept { return commonInfo().isMmx(); } //! Tests whether the instruction is SSE|AVX|AVX512 instruction that accesses XMM|YMM|ZMM registers. - inline bool isVec() const noexcept { return commonInfo().isVec(); } + ASMJIT_INLINE_NODEBUG bool isVec() const noexcept { return commonInfo().isVec(); } //! Tests whether the instruction is SSE+ (SSE4.2, AES, SHA included) instruction that accesses XMM registers. - inline bool isSse() const noexcept { return commonInfo().isSse(); } + ASMJIT_INLINE_NODEBUG bool isSse() const noexcept { return commonInfo().isSse(); } //! Tests whether the instruction is AVX+ (FMA included) instruction that accesses XMM|YMM|ZMM registers. - inline bool isAvx() const noexcept { return commonInfo().isAvx(); } + ASMJIT_INLINE_NODEBUG bool isAvx() const noexcept { return commonInfo().isAvx(); } //! Tests whether the instruction can be prefixed with LOCK prefix. - inline bool hasLockPrefix() const noexcept { return commonInfo().hasLockPrefix(); } + ASMJIT_INLINE_NODEBUG bool hasLockPrefix() const noexcept { return commonInfo().hasLockPrefix(); } //! Tests whether the instruction can be prefixed with REP (REPE|REPZ) prefix. - inline bool hasRepPrefix() const noexcept { return commonInfo().hasRepPrefix(); } + ASMJIT_INLINE_NODEBUG bool hasRepPrefix() const noexcept { return commonInfo().hasRepPrefix(); } //! Tests whether the instruction can be prefixed with XACQUIRE prefix. - inline bool hasXAcquirePrefix() const noexcept { return commonInfo().hasXAcquirePrefix(); } + ASMJIT_INLINE_NODEBUG bool hasXAcquirePrefix() const noexcept { return commonInfo().hasXAcquirePrefix(); } //! Tests whether the instruction can be prefixed with XRELEASE prefix. - inline bool hasXReleasePrefix() const noexcept { return commonInfo().hasXReleasePrefix(); } + ASMJIT_INLINE_NODEBUG bool hasXReleasePrefix() const noexcept { return commonInfo().hasXReleasePrefix(); } //! Tests whether the rep prefix is supported by the instruction, but ignored (has no effect). - inline bool isRepIgnored() const noexcept { return commonInfo().isRepIgnored(); } + ASMJIT_INLINE_NODEBUG bool isRepIgnored() const noexcept { return commonInfo().isRepIgnored(); } //! Tests whether the instruction uses MIB. - inline bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); } + ASMJIT_INLINE_NODEBUG bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); } //! Tests whether the instruction uses VSIB. - inline bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); } + ASMJIT_INLINE_NODEBUG bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); } //! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable). - inline bool isVex() const noexcept { return hasFlag(InstFlags::kVex); } + ASMJIT_INLINE_NODEBUG bool isVex() const noexcept { return hasFlag(InstFlags::kVex); } //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable). - inline bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); } + ASMJIT_INLINE_NODEBUG bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); } //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable). - inline bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); } + ASMJIT_INLINE_NODEBUG bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); } - inline bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); } - inline bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); } - inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); } - inline bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); } + ASMJIT_INLINE_NODEBUG bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); } + ASMJIT_INLINE_NODEBUG bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); } + ASMJIT_INLINE_NODEBUG bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); } + ASMJIT_INLINE_NODEBUG bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); } //! Tests whether the instruction supports AVX512 masking {k}. - inline bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); } + ASMJIT_INLINE_NODEBUG bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); } //! Tests whether the instruction supports AVX512 zeroing {k}{z}. - inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); } + ASMJIT_INLINE_NODEBUG bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); } //! Tests whether the instruction supports AVX512 embedded-rounding {er}. - inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); } + ASMJIT_INLINE_NODEBUG bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); } //! Tests whether the instruction supports AVX512 suppress-all-exceptions {sae}. - inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); } + ASMJIT_INLINE_NODEBUG bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); } //! Tests whether the instruction supports AVX512 broadcast (either 32-bit or 64-bit). - inline bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); } + ASMJIT_INLINE_NODEBUG bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); } //! Tests whether the instruction supports AVX512 broadcast (16-bit). - inline bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); } + ASMJIT_INLINE_NODEBUG bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); } //! Tests whether the instruction supports AVX512 broadcast (32-bit). - inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); } + ASMJIT_INLINE_NODEBUG bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); } //! Tests whether the instruction supports AVX512 broadcast (64-bit). - inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); } + ASMJIT_INLINE_NODEBUG bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); } //! Returns a control flow category of the instruction. - inline InstControlFlow controlFlow() const noexcept { return commonInfo().controlFlow(); } + ASMJIT_INLINE_NODEBUG InstControlFlow controlFlow() const noexcept { return commonInfo().controlFlow(); } //! Returns a hint that can be used when both inputs are the same register. - inline InstSameRegHint sameRegHint() const noexcept { return commonInfo().sameRegHint(); } + ASMJIT_INLINE_NODEBUG InstSameRegHint sameRegHint() const noexcept { return commonInfo().sameRegHint(); } - inline uint32_t signatureIndex() const noexcept { return commonInfo().signatureIndex(); } - inline uint32_t signatureCount() const noexcept { return commonInfo().signatureCount(); } + ASMJIT_INLINE_NODEBUG uint32_t signatureIndex() const noexcept { return commonInfo().signatureIndex(); } + ASMJIT_INLINE_NODEBUG uint32_t signatureCount() const noexcept { return commonInfo().signatureCount(); } - inline const InstSignature* signatureData() const noexcept { return commonInfo().signatureData(); } - inline const InstSignature* signatureEnd() const noexcept { return commonInfo().signatureEnd(); } + ASMJIT_INLINE_NODEBUG const InstSignature* signatureData() const noexcept { return commonInfo().signatureData(); } + ASMJIT_INLINE_NODEBUG const InstSignature* signatureEnd() const noexcept { return commonInfo().signatureEnd(); } //! \} }; diff --git a/3rdparty/asmjit/src/asmjit/x86/x86instdb_p.h b/3rdparty/asmjit/src/asmjit/x86/x86instdb_p.h index b8e12e16b45..cb006060832 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86instdb_p.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86instdb_p.h @@ -6,6 +6,7 @@ #ifndef ASMJIT_X86_X86INSTDB_P_H_INCLUDED #define ASMJIT_X86_X86INSTDB_P_H_INCLUDED +#include "../core/instdb_p.h" #include "../x86/x86instdb.h" ASMJIT_BEGIN_SUB_NAMESPACE(x86) @@ -38,11 +39,11 @@ enum EncodingId : uint32_t { kEncodingX86M_GPB, //!< X86 [M] (handles single-byte size). kEncodingX86M_GPB_MulDiv, //!< X86 [M] (like GPB, handles implicit|explicit MUL|DIV|IDIV). kEncodingX86M_Only, //!< X86 [M] (restricted to memory operand of any size). - kEncodingX86M_Only_EDX_EAX, //!< X86 [M] (memory operand only, followed by implicit <edx> and <eax>). + kEncodingX86M_Only_EDX_EAX, //!< X86 [M] (memory operand only, followed by implicit `EDX` and `EAX`). kEncodingX86M_Nop, //!< X86 [M] (special case of NOP instruction). kEncodingX86R_Native, //!< X86 [R] (register must be either 32-bit or 64-bit depending on arch). kEncodingX86R_FromM, //!< X86 [R] - which specifies memory address. - kEncodingX86R32_EDX_EAX, //!< X86 [R32] followed by implicit EDX and EAX. + kEncodingX86R32_EDX_EAX, //!< X86 [R32] followed by implicit `EDX` and `EAX`. kEncodingX86Rm, //!< X86 [RM] (doesn't handle single-byte size). kEncodingX86Rm_Raw66H, //!< X86 [RM] (used by LZCNT, POPCNT, and TZCNT). kEncodingX86Rm_NoSize, //!< X86 [RM] (doesn't add REX.W prefix if 64-bit reg is used). @@ -126,6 +127,7 @@ enum EncodingId : uint32_t { kEncodingVexMri, //!< VEX|EVEX [MRI]. kEncodingVexMri_Lx, //!< VEX|EVEX [MRI] (propagates VEX|EVEX.L if YMM used). kEncodingVexMri_Vpextrw, //!< VEX|EVEX [MRI] (special case required by VPEXTRW instruction). + kEncodingVexMvr_Wx, //!< VEX|EVEX [MVR] (propagates VEX|EVEX.W if GPQ used). kEncodingVexRm, //!< VEX|EVEX [RM]. kEncodingVexRm_ZDI, //!< VEX|EVEX [RM<ZDI>]. kEncodingVexRm_Wx, //!< VEX|EVEX [RM] (propagates VEX|EVEX.W if GPQ used). @@ -200,20 +202,10 @@ struct AdditionalInfo { inline const uint8_t* featuresEnd() const noexcept { return _features + ASMJIT_ARRAY_SIZE(_features); } }; -// ${NameLimits:Begin} -// ------------------- Automatically generated, do not edit ------------------- -enum : uint32_t { kMaxNameSize = 17 }; -// ---------------------------------------------------------------------------- -// ${NameLimits:End} - -struct InstNameIndex { - uint16_t start; - uint16_t end; -}; - struct RWInfo { enum Category : uint8_t { - kCategoryGeneric, + kCategoryGeneric = 0, + kCategoryGenericEx, kCategoryMov, kCategoryMovabs, kCategoryImul, @@ -295,8 +287,9 @@ extern const uint32_t _mainOpcodeTable[]; extern const uint32_t _altOpcodeTable[]; #ifndef ASMJIT_NO_TEXT -extern const char _nameData[]; -extern const InstNameIndex instNameIndex[26]; +extern const InstNameIndex instNameIndex; +extern const char _instNameStringTable[]; +extern const uint32_t _instNameIndexTable[]; #endif // !ASMJIT_NO_TEXT extern const AdditionalInfo _additionalInfoTable[]; diff --git a/3rdparty/asmjit/src/asmjit/x86/x86opcode_p.h b/3rdparty/asmjit/src/asmjit/x86/x86opcode_p.h index 94a76f04818..ab0b13e1a50 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86opcode_p.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86opcode_p.h @@ -45,7 +45,7 @@ struct Opcode { //! `pp` in instruction manuals. //! //! - `LL` field is used exclusively by AVX+ and AVX512+ instruction sets. It describes vector size, which is `L.128` - //! for XMM register, `L.256` for for YMM register, and `L.512` for ZMM register. The `LL` field is omitted in case + //! for XMM register, `L.256` for YMM register, and `L.512` for ZMM register. The `LL` field is omitted in case //! that instruction supports multiple vector lengths, however, if the instruction requires specific `L` value it //! must be specified as a part of the opcode. //! @@ -244,7 +244,7 @@ struct Opcode { // REX|VEX|EVEX B|X|R|W Bits // ------------------------- // - // NOTE: REX.[B|X|R] are never stored within the opcode itself, they are reserved by AsmJit are are added + // NOTE: REX.[B|X|R] are never stored within the opcode itself, they are reserved by AsmJit and are added // dynamically to the opcode to represent [REX|VEX|EVEX].[B|X|R] bits. REX.W can be stored in DB as it's sometimes // part of the opcode itself. @@ -280,7 +280,7 @@ struct Opcode { // `L` or `LL` field in AVX/XOP/AVX-512 // ------------------------------------ // - // VEX/XOP prefix can only use the first bit `L.128` or `L.256`. EVEX prefix prefix makes it possible to use also + // VEX/XOP prefix can only use the first bit `L.128` or `L.256`. EVEX prefix makes it possible to use also // `L.512`. If the instruction set manual describes an instruction by `LIG` it means that the `L` field is ignored // and AsmJit defaults to `0` in such case. kLL_Shift = 29, @@ -336,27 +336,27 @@ struct Opcode { // Opcode Builder // -------------- - inline uint32_t get() const noexcept { return v; } + ASMJIT_INLINE_NODEBUG uint32_t get() const noexcept { return v; } - inline bool hasW() const noexcept { return (v & kW) != 0; } - inline bool has66h() const noexcept { return (v & kPP_66) != 0; } + ASMJIT_INLINE_NODEBUG bool hasW() const noexcept { return (v & kW) != 0; } + ASMJIT_INLINE_NODEBUG bool has66h() const noexcept { return (v & kPP_66) != 0; } - inline Opcode& add(uint32_t x) noexcept { return operator+=(x); } + ASMJIT_INLINE_NODEBUG Opcode& add(uint32_t x) noexcept { return operator+=(x); } - inline Opcode& add66h() noexcept { return operator|=(kPP_66); } + ASMJIT_INLINE_NODEBUG Opcode& add66h() noexcept { return operator|=(kPP_66); } template<typename T> - inline Opcode& add66hIf(T exp) noexcept { return operator|=(uint32_t(exp) << kPP_Shift); } + ASMJIT_INLINE_NODEBUG Opcode& add66hIf(T exp) noexcept { return operator|=(uint32_t(exp) << kPP_Shift); } template<typename T> - inline Opcode& add66hBySize(T size) noexcept { return add66hIf(size == 2); } + ASMJIT_INLINE_NODEBUG Opcode& add66hBySize(T size) noexcept { return add66hIf(size == 2); } - inline Opcode& addW() noexcept { return operator|=(kW); } + ASMJIT_INLINE_NODEBUG Opcode& addW() noexcept { return operator|=(kW); } template<typename T> - inline Opcode& addWIf(T exp) noexcept { return operator|=(uint32_t(exp) << kW_Shift); } + ASMJIT_INLINE_NODEBUG Opcode& addWIf(T exp) noexcept { return operator|=(uint32_t(exp) << kW_Shift); } template<typename T> - inline Opcode& addWBySize(T size) noexcept { return addWIf(size == 8); } + ASMJIT_INLINE_NODEBUG Opcode& addWBySize(T size) noexcept { return addWIf(size == 8); } template<typename T> - inline Opcode& addPrefixBySize(T size) noexcept { + ASMJIT_INLINE_NODEBUG Opcode& addPrefixBySize(T size) noexcept { static const uint32_t mask[16] = { 0, // #0 0, // #1 -> nothing (already handled or not possible) @@ -372,7 +372,7 @@ struct Opcode { } template<typename T> - inline Opcode& addArithBySize(T size) noexcept { + ASMJIT_INLINE_NODEBUG Opcode& addArithBySize(T size) noexcept { static const uint32_t mask[16] = { 0, // #0 0, // #1 -> nothing @@ -387,45 +387,45 @@ struct Opcode { return operator|=(mask[size & 0xF]); } - inline Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); } + ASMJIT_INLINE_NODEBUG Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); } template<typename T> - inline Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::ConstCTZ<uint32_t(kMM_ForceEvex)>::value); } + ASMJIT_INLINE_NODEBUG Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::ConstCTZ<uint32_t(kMM_ForceEvex)>::value); } //! Extract `O` field (R) from the opcode (specified as /0..7 in instruction manuals). - inline uint32_t extractModO() const noexcept { + ASMJIT_INLINE_NODEBUG uint32_t extractModO() const noexcept { return (v >> kModO_Shift) & 0x07; } //! Extract `RM` field (RM) from the opcode (usually specified as another opcode value). - inline uint32_t extractModRM() const noexcept { + ASMJIT_INLINE_NODEBUG uint32_t extractModRM() const noexcept { return (v >> kModRM_Shift) & 0x07; } //! Extract `REX` prefix from opcode combined with `options`. - inline uint32_t extractRex(InstOptions options) const noexcept { + ASMJIT_INLINE_NODEBUG uint32_t extractRex(InstOptions options) const noexcept { // kREX was designed in a way that when shifted there will be no bytes set except REX.[B|X|R|W]. // The returned value forms a real REX prefix byte. This case should be unit-tested as well. return (v | uint32_t(options)) >> kREX_Shift; } - inline uint32_t extractLLMMMMM(InstOptions options) const noexcept { + ASMJIT_INLINE_NODEBUG uint32_t extractLLMMMMM(InstOptions options) const noexcept { uint32_t llMmmmm = uint32_t(v & (kLL_Mask | kMM_Mask)); uint32_t vexEvex = uint32_t(options & InstOptions::kX86_Evex); return (llMmmmm | vexEvex) >> kMM_Shift; } - inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; } - inline Opcode& operator+=(uint32_t x) noexcept { v += x; return *this; } - inline Opcode& operator-=(uint32_t x) noexcept { v -= x; return *this; } - inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; } - inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; } - inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; } - - inline uint32_t operator&(uint32_t x) const noexcept { return v & x; } - inline uint32_t operator|(uint32_t x) const noexcept { return v | x; } - inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; } - inline uint32_t operator<<(uint32_t x) const noexcept { return v << x; } - inline uint32_t operator>>(uint32_t x) const noexcept { return v >> x; } + ASMJIT_INLINE_NODEBUG Opcode& operator=(uint32_t x) noexcept { v = x; return *this; } + ASMJIT_INLINE_NODEBUG Opcode& operator+=(uint32_t x) noexcept { v += x; return *this; } + ASMJIT_INLINE_NODEBUG Opcode& operator-=(uint32_t x) noexcept { v -= x; return *this; } + ASMJIT_INLINE_NODEBUG Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; } + ASMJIT_INLINE_NODEBUG Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; } + ASMJIT_INLINE_NODEBUG Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; } + + ASMJIT_INLINE_NODEBUG uint32_t operator&(uint32_t x) const noexcept { return v & x; } + ASMJIT_INLINE_NODEBUG uint32_t operator|(uint32_t x) const noexcept { return v | x; } + ASMJIT_INLINE_NODEBUG uint32_t operator^(uint32_t x) const noexcept { return v ^ x; } + ASMJIT_INLINE_NODEBUG uint32_t operator<<(uint32_t x) const noexcept { return v << x; } + ASMJIT_INLINE_NODEBUG uint32_t operator>>(uint32_t x) const noexcept { return v >> x; } }; //! \} diff --git a/3rdparty/asmjit/src/asmjit/x86/x86operand.cpp b/3rdparty/asmjit/src/asmjit/x86/x86operand.cpp index a47fec2b5b2..5ab50de570e 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86operand.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86operand.cpp @@ -19,210 +19,210 @@ UNIT(x86_operand) { Label L(1000); // Label with some ID. INFO("Checking basic properties of built-in X86 registers"); - EXPECT(gpb(Gp::kIdAx) == al); - EXPECT(gpb(Gp::kIdBx) == bl); - EXPECT(gpb(Gp::kIdCx) == cl); - EXPECT(gpb(Gp::kIdDx) == dl); - - EXPECT(gpb_lo(Gp::kIdAx) == al); - EXPECT(gpb_lo(Gp::kIdBx) == bl); - EXPECT(gpb_lo(Gp::kIdCx) == cl); - EXPECT(gpb_lo(Gp::kIdDx) == dl); - - EXPECT(gpb_hi(Gp::kIdAx) == ah); - EXPECT(gpb_hi(Gp::kIdBx) == bh); - EXPECT(gpb_hi(Gp::kIdCx) == ch); - EXPECT(gpb_hi(Gp::kIdDx) == dh); - - EXPECT(gpw(Gp::kIdAx) == ax); - EXPECT(gpw(Gp::kIdBx) == bx); - EXPECT(gpw(Gp::kIdCx) == cx); - EXPECT(gpw(Gp::kIdDx) == dx); - - EXPECT(gpd(Gp::kIdAx) == eax); - EXPECT(gpd(Gp::kIdBx) == ebx); - EXPECT(gpd(Gp::kIdCx) == ecx); - EXPECT(gpd(Gp::kIdDx) == edx); - - EXPECT(gpq(Gp::kIdAx) == rax); - EXPECT(gpq(Gp::kIdBx) == rbx); - EXPECT(gpq(Gp::kIdCx) == rcx); - EXPECT(gpq(Gp::kIdDx) == rdx); - - EXPECT(gpb(Gp::kIdAx) != dl); - EXPECT(gpw(Gp::kIdBx) != cx); - EXPECT(gpd(Gp::kIdCx) != ebx); - EXPECT(gpq(Gp::kIdDx) != rax); + EXPECT_EQ(gpb(Gp::kIdAx), al); + EXPECT_EQ(gpb(Gp::kIdBx), bl); + EXPECT_EQ(gpb(Gp::kIdCx), cl); + EXPECT_EQ(gpb(Gp::kIdDx), dl); + + EXPECT_EQ(gpb_lo(Gp::kIdAx), al); + EXPECT_EQ(gpb_lo(Gp::kIdBx), bl); + EXPECT_EQ(gpb_lo(Gp::kIdCx), cl); + EXPECT_EQ(gpb_lo(Gp::kIdDx), dl); + + EXPECT_EQ(gpb_hi(Gp::kIdAx), ah); + EXPECT_EQ(gpb_hi(Gp::kIdBx), bh); + EXPECT_EQ(gpb_hi(Gp::kIdCx), ch); + EXPECT_EQ(gpb_hi(Gp::kIdDx), dh); + + EXPECT_EQ(gpw(Gp::kIdAx), ax); + EXPECT_EQ(gpw(Gp::kIdBx), bx); + EXPECT_EQ(gpw(Gp::kIdCx), cx); + EXPECT_EQ(gpw(Gp::kIdDx), dx); + + EXPECT_EQ(gpd(Gp::kIdAx), eax); + EXPECT_EQ(gpd(Gp::kIdBx), ebx); + EXPECT_EQ(gpd(Gp::kIdCx), ecx); + EXPECT_EQ(gpd(Gp::kIdDx), edx); + + EXPECT_EQ(gpq(Gp::kIdAx), rax); + EXPECT_EQ(gpq(Gp::kIdBx), rbx); + EXPECT_EQ(gpq(Gp::kIdCx), rcx); + EXPECT_EQ(gpq(Gp::kIdDx), rdx); + + EXPECT_NE(gpb(Gp::kIdAx), dl); + EXPECT_NE(gpw(Gp::kIdBx), cx); + EXPECT_NE(gpd(Gp::kIdCx), ebx); + EXPECT_NE(gpq(Gp::kIdDx), rax); INFO("Checking if x86::reg(...) matches built-in IDs"); - EXPECT(gpb(5) == bpl); - EXPECT(gpw(5) == bp); - EXPECT(gpd(5) == ebp); - EXPECT(gpq(5) == rbp); - EXPECT(st(5) == st5); - EXPECT(mm(5) == mm5); - EXPECT(k(5) == k5); - EXPECT(cr(5) == cr5); - EXPECT(dr(5) == dr5); - EXPECT(xmm(5) == xmm5); - EXPECT(ymm(5) == ymm5); - EXPECT(zmm(5) == zmm5); + EXPECT_EQ(gpb(5), bpl); + EXPECT_EQ(gpw(5), bp); + EXPECT_EQ(gpd(5), ebp); + EXPECT_EQ(gpq(5), rbp); + EXPECT_EQ(st(5) , st5); + EXPECT_EQ(mm(5) , mm5); + EXPECT_EQ(k(5) , k5); + EXPECT_EQ(cr(5) , cr5); + EXPECT_EQ(dr(5) , dr5); + EXPECT_EQ(xmm(5), xmm5); + EXPECT_EQ(ymm(5), ymm5); + EXPECT_EQ(zmm(5), zmm5); INFO("Checking x86::Gp register properties"); - EXPECT(Gp().isReg() == true); - EXPECT(eax.isReg() == true); - EXPECT(eax.id() == 0); - EXPECT(eax.size() == 4); - EXPECT(eax.type() == RegType::kX86_Gpd); - EXPECT(eax.group() == RegGroup::kGp); + EXPECT_TRUE(Gp().isReg()); + EXPECT_TRUE(eax.isReg()); + EXPECT_EQ(eax.id(), 0u); + EXPECT_EQ(eax.size(), 4u); + EXPECT_EQ(eax.type(), RegType::kX86_Gpd); + EXPECT_EQ(eax.group(), RegGroup::kGp); INFO("Checking x86::Xmm register properties"); - EXPECT(Xmm().isReg() == true); - EXPECT(xmm4.isReg() == true); - EXPECT(xmm4.id() == 4); - EXPECT(xmm4.size() == 16); - EXPECT(xmm4.type() == RegType::kX86_Xmm); - EXPECT(xmm4.group() == RegGroup::kVec); - EXPECT(xmm4.isVec()); + EXPECT_TRUE(Xmm().isReg()); + EXPECT_TRUE(xmm4.isReg()); + EXPECT_EQ(xmm4.id(), 4u); + EXPECT_EQ(xmm4.size(), 16u); + EXPECT_EQ(xmm4.type(), RegType::kX86_Xmm); + EXPECT_EQ(xmm4.group(), RegGroup::kVec); + EXPECT_TRUE(xmm4.isVec()); INFO("Checking x86::Ymm register properties"); - EXPECT(Ymm().isReg() == true); - EXPECT(ymm5.isReg() == true); - EXPECT(ymm5.id() == 5); - EXPECT(ymm5.size() == 32); - EXPECT(ymm5.type() == RegType::kX86_Ymm); - EXPECT(ymm5.group() == RegGroup::kVec); - EXPECT(ymm5.isVec()); + EXPECT_TRUE(Ymm().isReg()); + EXPECT_TRUE(ymm5.isReg()); + EXPECT_EQ(ymm5.id(), 5u); + EXPECT_EQ(ymm5.size(), 32u); + EXPECT_EQ(ymm5.type(), RegType::kX86_Ymm); + EXPECT_EQ(ymm5.group(), RegGroup::kVec); + EXPECT_TRUE(ymm5.isVec()); INFO("Checking x86::Zmm register properties"); - EXPECT(Zmm().isReg() == true); - EXPECT(zmm6.isReg() == true); - EXPECT(zmm6.id() == 6); - EXPECT(zmm6.size() == 64); - EXPECT(zmm6.type() == RegType::kX86_Zmm); - EXPECT(zmm6.group() == RegGroup::kVec); - EXPECT(zmm6.isVec()); + EXPECT_TRUE(Zmm().isReg()); + EXPECT_TRUE(zmm6.isReg()); + EXPECT_EQ(zmm6.id(), 6u); + EXPECT_EQ(zmm6.size(), 64u); + EXPECT_EQ(zmm6.type(), RegType::kX86_Zmm); + EXPECT_EQ(zmm6.group(), RegGroup::kVec); + EXPECT_TRUE(zmm6.isVec()); INFO("Checking x86::Vec register properties"); - EXPECT(Vec().isReg() == true); + EXPECT_TRUE(Vec().isReg()); // Converts a VEC register to a type of the passed register, but keeps the ID. - EXPECT(xmm4.cloneAs(ymm10) == ymm4); - EXPECT(xmm4.cloneAs(zmm11) == zmm4); - EXPECT(ymm5.cloneAs(xmm12) == xmm5); - EXPECT(ymm5.cloneAs(zmm13) == zmm5); - EXPECT(zmm6.cloneAs(xmm14) == xmm6); - EXPECT(zmm6.cloneAs(ymm15) == ymm6); + EXPECT_EQ(xmm4.cloneAs(ymm10), ymm4); + EXPECT_EQ(xmm4.cloneAs(zmm11), zmm4); + EXPECT_EQ(ymm5.cloneAs(xmm12), xmm5); + EXPECT_EQ(ymm5.cloneAs(zmm13), zmm5); + EXPECT_EQ(zmm6.cloneAs(xmm14), xmm6); + EXPECT_EQ(zmm6.cloneAs(ymm15), ymm6); - EXPECT(xmm7.xmm() == xmm7); - EXPECT(xmm7.ymm() == ymm7); - EXPECT(xmm7.zmm() == zmm7); + EXPECT_EQ(xmm7.xmm(), xmm7); + EXPECT_EQ(xmm7.ymm(), ymm7); + EXPECT_EQ(xmm7.zmm(), zmm7); - EXPECT(ymm7.xmm() == xmm7); - EXPECT(ymm7.ymm() == ymm7); - EXPECT(ymm7.zmm() == zmm7); + EXPECT_EQ(ymm7.xmm(), xmm7); + EXPECT_EQ(ymm7.ymm(), ymm7); + EXPECT_EQ(ymm7.zmm(), zmm7); - EXPECT(zmm7.xmm() == xmm7); - EXPECT(zmm7.ymm() == ymm7); - EXPECT(zmm7.zmm() == zmm7); + EXPECT_EQ(zmm7.xmm(), xmm7); + EXPECT_EQ(zmm7.ymm(), ymm7); + EXPECT_EQ(zmm7.zmm(), zmm7); INFO("Checking x86::Mm register properties"); - EXPECT(Mm().isReg() == true); - EXPECT(mm2.isReg() == true); - EXPECT(mm2.id() == 2); - EXPECT(mm2.size() == 8); - EXPECT(mm2.type() == RegType::kX86_Mm); - EXPECT(mm2.group() == RegGroup::kX86_MM); + EXPECT_TRUE(Mm().isReg()); + EXPECT_TRUE(mm2.isReg()); + EXPECT_EQ(mm2.id(), 2u); + EXPECT_EQ(mm2.size(), 8u); + EXPECT_EQ(mm2.type(), RegType::kX86_Mm); + EXPECT_EQ(mm2.group(), RegGroup::kX86_MM); INFO("Checking x86::KReg register properties"); - EXPECT(KReg().isReg() == true); - EXPECT(k3.isReg() == true); - EXPECT(k3.id() == 3); - EXPECT(k3.size() == 0); - EXPECT(k3.type() == RegType::kX86_KReg); - EXPECT(k3.group() == RegGroup::kX86_K); + EXPECT_TRUE(KReg().isReg()); + EXPECT_TRUE(k3.isReg()); + EXPECT_EQ(k3.id(), 3u); + EXPECT_EQ(k3.size(), 0u); + EXPECT_EQ(k3.type(), RegType::kX86_KReg); + EXPECT_EQ(k3.group(), RegGroup::kX86_K); INFO("Checking x86::St register properties"); - EXPECT(St().isReg() == true); - EXPECT(st1.isReg() == true); - EXPECT(st1.id() == 1); - EXPECT(st1.size() == 10); - EXPECT(st1.type() == RegType::kX86_St); - EXPECT(st1.group() == RegGroup::kX86_St); + EXPECT_TRUE(St().isReg()); + EXPECT_TRUE(st1.isReg()); + EXPECT_EQ(st1.id(), 1u); + EXPECT_EQ(st1.size(), 10u); + EXPECT_EQ(st1.type(), RegType::kX86_St); + EXPECT_EQ(st1.group(), RegGroup::kX86_St); INFO("Checking if default constructed regs behave as expected"); - EXPECT(Reg().isValid() == false); - EXPECT(Gp().isValid() == false); - EXPECT(Xmm().isValid() == false); - EXPECT(Ymm().isValid() == false); - EXPECT(Zmm().isValid() == false); - EXPECT(Mm().isValid() == false); - EXPECT(KReg().isValid() == false); - EXPECT(SReg().isValid() == false); - EXPECT(CReg().isValid() == false); - EXPECT(DReg().isValid() == false); - EXPECT(St().isValid() == false); - EXPECT(Bnd().isValid() == false); + EXPECT_FALSE(Reg().isValid()); + EXPECT_FALSE(Gp().isValid()); + EXPECT_FALSE(Xmm().isValid()); + EXPECT_FALSE(Ymm().isValid()); + EXPECT_FALSE(Zmm().isValid()); + EXPECT_FALSE(Mm().isValid()); + EXPECT_FALSE(KReg().isValid()); + EXPECT_FALSE(SReg().isValid()); + EXPECT_FALSE(CReg().isValid()); + EXPECT_FALSE(DReg().isValid()); + EXPECT_FALSE(St().isValid()); + EXPECT_FALSE(Bnd().isValid()); INFO("Checking x86::Mem operand"); Mem m; - EXPECT(m == Mem(), "Two default constructed x86::Mem operands must be equal"); + EXPECT_EQ(m, Mem()); m = ptr(L); - EXPECT(m.hasBase() == true); - EXPECT(m.hasBaseReg() == false); - EXPECT(m.hasBaseLabel() == true); - EXPECT(m.hasOffset() == false); - EXPECT(m.isOffset64Bit() == false); - EXPECT(m.offset() == 0); - EXPECT(m.offsetLo32() == 0); + EXPECT_TRUE(m.hasBase()); + EXPECT_FALSE(m.hasBaseReg()); + EXPECT_TRUE(m.hasBaseLabel()); + EXPECT_FALSE(m.hasOffset()); + EXPECT_FALSE(m.isOffset64Bit()); + EXPECT_EQ(m.offset(), 0); + EXPECT_EQ(m.offsetLo32(), 0); m = ptr(0x0123456789ABCDEFu); - EXPECT(m.hasBase() == false); - EXPECT(m.hasBaseReg() == false); - EXPECT(m.hasIndex() == false); - EXPECT(m.hasIndexReg() == false); - EXPECT(m.hasOffset() == true); - EXPECT(m.isOffset64Bit() == true); - EXPECT(m.offset() == int64_t(0x0123456789ABCDEFu)); - EXPECT(m.offsetLo32() == int32_t(0x89ABCDEFu)); + EXPECT_FALSE(m.hasBase()); + EXPECT_FALSE(m.hasBaseReg()); + EXPECT_FALSE(m.hasIndex()); + EXPECT_FALSE(m.hasIndexReg()); + EXPECT_TRUE(m.hasOffset()); + EXPECT_TRUE(m.isOffset64Bit()); + EXPECT_EQ(m.offset(), int64_t(0x0123456789ABCDEFu)); + EXPECT_EQ(m.offsetLo32(), int32_t(0x89ABCDEFu)); m.addOffset(1); - EXPECT(m.offset() == int64_t(0x0123456789ABCDF0u)); + EXPECT_EQ(m.offset(), int64_t(0x0123456789ABCDF0u)); m = ptr(0x0123456789ABCDEFu, rdi, 3); - EXPECT(m.hasSegment() == false); - EXPECT(m.hasBase() == false); - EXPECT(m.hasBaseReg() == false); - EXPECT(m.hasIndex() == true); - EXPECT(m.hasIndexReg() == true); - EXPECT(m.indexType() == rdi.type()); - EXPECT(m.indexId() == rdi.id()); - EXPECT(m.shift() == 3); - EXPECT(m.hasOffset() == true); - EXPECT(m.isOffset64Bit() == true); - EXPECT(m.offset() == int64_t(0x0123456789ABCDEFu)); - EXPECT(m.offsetLo32() == int32_t(0x89ABCDEFu)); + EXPECT_FALSE(m.hasSegment()); + EXPECT_FALSE(m.hasBase()); + EXPECT_FALSE(m.hasBaseReg()); + EXPECT_TRUE(m.hasIndex()); + EXPECT_TRUE(m.hasIndexReg()); + EXPECT_EQ(m.indexType(), rdi.type()); + EXPECT_EQ(m.indexId(), rdi.id()); + EXPECT_EQ(m.shift(), 3u); + EXPECT_TRUE(m.hasOffset()); + EXPECT_TRUE(m.isOffset64Bit()); + EXPECT_EQ(m.offset(), int64_t(0x0123456789ABCDEFu)); + EXPECT_EQ(m.offsetLo32(), int32_t(0x89ABCDEFu)); m.resetIndex(); - EXPECT(m.hasIndex() == false); - EXPECT(m.hasIndexReg() == false); + EXPECT_FALSE(m.hasIndex()); + EXPECT_FALSE(m.hasIndexReg()); m = ptr(rax); - EXPECT(m.hasBase() == true); - EXPECT(m.hasBaseReg() == true); - EXPECT(m.baseType() == rax.type()); - EXPECT(m.baseId() == rax.id()); - EXPECT(m.hasIndex() == false); - EXPECT(m.hasIndexReg() == false); - EXPECT(m.indexType() == RegType::kNone); - EXPECT(m.indexId() == 0); - EXPECT(m.hasOffset() == false); - EXPECT(m.isOffset64Bit() == false); - EXPECT(m.offset() == 0); - EXPECT(m.offsetLo32() == 0); + EXPECT_TRUE(m.hasBase()); + EXPECT_TRUE(m.hasBaseReg()); + EXPECT_EQ(m.baseType(), rax.type()); + EXPECT_EQ(m.baseId(), rax.id()); + EXPECT_FALSE(m.hasIndex()); + EXPECT_FALSE(m.hasIndexReg()); + EXPECT_EQ(m.indexType(), RegType::kNone); + EXPECT_EQ(m.indexId(), 0u); + EXPECT_FALSE(m.hasOffset()); + EXPECT_FALSE(m.isOffset64Bit()); + EXPECT_EQ(m.offset(), 0); + EXPECT_EQ(m.offsetLo32(), 0); m.setIndex(rsi); - EXPECT(m.hasIndex() == true); - EXPECT(m.hasIndexReg() == true); - EXPECT(m.indexType() == rsi.type()); - EXPECT(m.indexId() == rsi.id()); + EXPECT_TRUE(m.hasIndex()); + EXPECT_TRUE(m.hasIndexReg()); + EXPECT_EQ(m.indexType(), rsi.type()); + EXPECT_EQ(m.indexId(), rsi.id()); } #endif diff --git a/3rdparty/asmjit/src/asmjit/x86/x86operand.h b/3rdparty/asmjit/src/asmjit/x86/x86operand.h index 037d4af4ddf..8510a9310b5 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86operand.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86operand.h @@ -49,26 +49,26 @@ template<RegType kRegType> struct RegTraits : public BaseRegTraits {}; //! \cond -// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ -// | Reg | Reg-Type | Reg-Group |Sz |Cnt| TypeId | -// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ -ASMJIT_DEFINE_REG_TRAITS(Rip , RegType::kX86_Rip , RegGroup::kX86_Rip , 0 , 1 , TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(GpbLo, RegType::kX86_GpbLo , RegGroup::kGp , 1 , 16, TypeId::kInt8 ); -ASMJIT_DEFINE_REG_TRAITS(GpbHi, RegType::kX86_GpbHi , RegGroup::kGp , 1 , 4 , TypeId::kInt8 ); -ASMJIT_DEFINE_REG_TRAITS(Gpw , RegType::kX86_Gpw , RegGroup::kGp , 2 , 16, TypeId::kInt16 ); -ASMJIT_DEFINE_REG_TRAITS(Gpd , RegType::kX86_Gpd , RegGroup::kGp , 4 , 16, TypeId::kInt32 ); -ASMJIT_DEFINE_REG_TRAITS(Gpq , RegType::kX86_Gpq , RegGroup::kGp , 8 , 16, TypeId::kInt64 ); -ASMJIT_DEFINE_REG_TRAITS(Xmm , RegType::kX86_Xmm , RegGroup::kVec , 16, 32, TypeId::kInt32x4 ); -ASMJIT_DEFINE_REG_TRAITS(Ymm , RegType::kX86_Ymm , RegGroup::kVec , 32, 32, TypeId::kInt32x8 ); -ASMJIT_DEFINE_REG_TRAITS(Zmm , RegType::kX86_Zmm , RegGroup::kVec , 64, 32, TypeId::kInt32x16); -ASMJIT_DEFINE_REG_TRAITS(KReg , RegType::kX86_KReg , RegGroup::kX86_K , 0 , 8 , TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(Mm , RegType::kX86_Mm , RegGroup::kX86_MM , 8 , 8 , TypeId::kMmx64 ); -ASMJIT_DEFINE_REG_TRAITS(SReg , RegType::kX86_SReg , RegGroup::kX86_SReg , 2 , 7 , TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(CReg , RegType::kX86_CReg , RegGroup::kX86_CReg , 0 , 16, TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(DReg , RegType::kX86_DReg , RegGroup::kX86_DReg , 0 , 16, TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(St , RegType::kX86_St , RegGroup::kX86_St , 10, 8 , TypeId::kFloat80 ); -ASMJIT_DEFINE_REG_TRAITS(Bnd , RegType::kX86_Bnd , RegGroup::kX86_Bnd , 16, 4 , TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(Tmm , RegType::kX86_Tmm , RegGroup::kX86_Tmm , 0 , 8 , TypeId::kVoid ); +// <--------------------+------------------------+------------------------+---+------------------+ +// | Reg-Type | Reg-Group |Sz | TypeId | +// <--------------------+------------------------+------------------------+---+------------------+ +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Rip , RegGroup::kX86_Rip , 0 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_GpbLo , RegGroup::kGp , 1 , TypeId::kInt8 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_GpbHi , RegGroup::kGp , 1 , TypeId::kInt8 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Gpw , RegGroup::kGp , 2 , TypeId::kInt16 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Gpd , RegGroup::kGp , 4 , TypeId::kInt32 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Gpq , RegGroup::kGp , 8 , TypeId::kInt64 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Xmm , RegGroup::kVec , 16, TypeId::kInt32x4 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Ymm , RegGroup::kVec , 32, TypeId::kInt32x8 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Zmm , RegGroup::kVec , 64, TypeId::kInt32x16); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_KReg , RegGroup::kX86_K , 0 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Mm , RegGroup::kX86_MM , 8 , TypeId::kMmx64 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_SReg , RegGroup::kX86_SReg , 2 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_CReg , RegGroup::kX86_CReg , 0 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_DReg , RegGroup::kX86_DReg , 0 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_St , RegGroup::kX86_St , 10, TypeId::kFloat80 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Bnd , RegGroup::kX86_Bnd , 16, TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Tmm , RegGroup::kX86_Tmm , 0 , TypeId::kVoid ); //! \endcond //! Register (X86). @@ -77,121 +77,135 @@ public: ASMJIT_DEFINE_ABSTRACT_REG(Reg, BaseReg) //! Tests whether the register is a GPB register (8-bit). - inline constexpr bool isGpb() const noexcept { return size() == 1; } + ASMJIT_INLINE_NODEBUG constexpr bool isGpb() const noexcept { return size() == 1; } //! Tests whether the register is a low GPB register (8-bit). - inline constexpr bool isGpbLo() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbLo>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isGpbLo() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbLo>::kSignature); } //! Tests whether the register is a high GPB register (8-bit). - inline constexpr bool isGpbHi() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbHi>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isGpbHi() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbHi>::kSignature); } //! Tests whether the register is a GPW register (16-bit). - inline constexpr bool isGpw() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpw>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isGpw() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpw>::kSignature); } //! Tests whether the register is a GPD register (32-bit). - inline constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); } //! Tests whether the register is a GPQ register (64-bit). - inline constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); } + + //! Tests whether the register is a 32-bit general purpose register, alias of \ref isGpd(). + ASMJIT_INLINE_NODEBUG constexpr bool isGp32() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); } + //! Tests whether the register is a 64-bit general purpose register, alias of \ref isGpq() + ASMJIT_INLINE_NODEBUG constexpr bool isGp64() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); } + //! Tests whether the register is an XMM register (128-bit). - inline constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); } //! Tests whether the register is a YMM register (256-bit). - inline constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); } //! Tests whether the register is a ZMM register (512-bit). - inline constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); } + + //! Tests whether the register is a 128-bit vector register, alias of \ref isXmm(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); } + //! Tests whether the register is a 256-bit vector register, alias of \ref isYmm(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec256() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); } + //! Tests whether the register is a 512-bit vector register, alias of \ref isZmm(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec512() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); } + //! Tests whether the register is an MMX register (64-bit). - inline constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Mm>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Mm>::kSignature); } //! Tests whether the register is a K register (64-bit). - inline constexpr bool isKReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_KReg>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isKReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_KReg>::kSignature); } //! Tests whether the register is a segment register. - inline constexpr bool isSReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_SReg>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isSReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_SReg>::kSignature); } //! Tests whether the register is a control register. - inline constexpr bool isCReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_CReg>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isCReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_CReg>::kSignature); } //! Tests whether the register is a debug register. - inline constexpr bool isDReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_DReg>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isDReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_DReg>::kSignature); } //! Tests whether the register is an FPU register (80-bit). - inline constexpr bool isSt() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_St>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isSt() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_St>::kSignature); } //! Tests whether the register is a bound register. - inline constexpr bool isBnd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Bnd>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isBnd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Bnd>::kSignature); } //! Tests whether the register is a TMM register. - inline constexpr bool isTmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Tmm>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isTmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Tmm>::kSignature); } //! Tests whether the register is RIP. - inline constexpr bool isRip() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Rip>::kSignature); } + ASMJIT_INLINE_NODEBUG constexpr bool isRip() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Rip>::kSignature); } template<RegType REG_TYPE> - inline void setRegT(uint32_t rId) noexcept { + ASMJIT_INLINE_NODEBUG void setRegT(uint32_t rId) noexcept { setSignature(OperandSignature{RegTraits<REG_TYPE>::kSignature}); setId(rId); } - inline void setTypeAndId(RegType type, uint32_t id) noexcept { + ASMJIT_INLINE_NODEBUG void setTypeAndId(RegType type, uint32_t id) noexcept { setSignature(signatureOf(type)); setId(id); } - static inline RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToGroup(type); } - static inline TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToTypeId(type); } - static inline OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToSignature(type); } + static ASMJIT_INLINE_NODEBUG RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToGroup(type); } + static ASMJIT_INLINE_NODEBUG TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToTypeId(type); } + static ASMJIT_INLINE_NODEBUG OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToSignature(type); } template<RegType REG_TYPE> - static inline RegGroup groupOfT() noexcept { return RegGroup(RegTraits<REG_TYPE>::kGroup); } + static ASMJIT_INLINE_NODEBUG RegGroup groupOfT() noexcept { return RegGroup(RegTraits<REG_TYPE>::kGroup); } template<RegType REG_TYPE> - static inline TypeId typeIdOfT() noexcept { return TypeId(RegTraits<REG_TYPE>::kTypeId); } + static ASMJIT_INLINE_NODEBUG TypeId typeIdOfT() noexcept { return TypeId(RegTraits<REG_TYPE>::kTypeId); } template<RegType REG_TYPE> - static inline OperandSignature signatureOfT() noexcept { return OperandSignature{RegTraits<REG_TYPE>::kSignature}; } + static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfT() noexcept { return OperandSignature{RegTraits<REG_TYPE>::kSignature}; } - static inline OperandSignature signatureOfVecByType(TypeId typeId) noexcept { + static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfVecByType(TypeId typeId) noexcept { return OperandSignature{typeId <= TypeId::_kVec128End ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) : typeId <= TypeId::_kVec256End ? uint32_t(RegTraits<RegType::kX86_Ymm>::kSignature) : uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature)}; } - static inline OperandSignature signatureOfVecBySize(uint32_t size) noexcept { + static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfVecBySize(uint32_t size) noexcept { return OperandSignature{size <= 16 ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) : size <= 32 ? uint32_t(RegTraits<RegType::kX86_Ymm>::kSignature) : uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature)}; } //! Tests whether the `op` operand is either a low or high 8-bit GPB register. - static inline bool isGpb(const Operand_& op) noexcept { + static ASMJIT_INLINE_NODEBUG bool isGpb(const Operand_& op) noexcept { // Check operand type, register group, and size. Not interested in register type. return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask | Signature::kSizeMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kGp) | Signature::fromSize(1)); } - static inline bool isGpbLo(const Operand_& op) noexcept { return op.as<Reg>().isGpbLo(); } - static inline bool isGpbHi(const Operand_& op) noexcept { return op.as<Reg>().isGpbHi(); } - static inline bool isGpw(const Operand_& op) noexcept { return op.as<Reg>().isGpw(); } - static inline bool isGpd(const Operand_& op) noexcept { return op.as<Reg>().isGpd(); } - static inline bool isGpq(const Operand_& op) noexcept { return op.as<Reg>().isGpq(); } - static inline bool isXmm(const Operand_& op) noexcept { return op.as<Reg>().isXmm(); } - static inline bool isYmm(const Operand_& op) noexcept { return op.as<Reg>().isYmm(); } - static inline bool isZmm(const Operand_& op) noexcept { return op.as<Reg>().isZmm(); } - static inline bool isMm(const Operand_& op) noexcept { return op.as<Reg>().isMm(); } - static inline bool isKReg(const Operand_& op) noexcept { return op.as<Reg>().isKReg(); } - static inline bool isSReg(const Operand_& op) noexcept { return op.as<Reg>().isSReg(); } - static inline bool isCReg(const Operand_& op) noexcept { return op.as<Reg>().isCReg(); } - static inline bool isDReg(const Operand_& op) noexcept { return op.as<Reg>().isDReg(); } - static inline bool isSt(const Operand_& op) noexcept { return op.as<Reg>().isSt(); } - static inline bool isBnd(const Operand_& op) noexcept { return op.as<Reg>().isBnd(); } - static inline bool isTmm(const Operand_& op) noexcept { return op.as<Reg>().isTmm(); } - static inline bool isRip(const Operand_& op) noexcept { return op.as<Reg>().isRip(); } - - static inline bool isGpb(const Operand_& op, uint32_t rId) noexcept { return isGpb(op) & (op.id() == rId); } - static inline bool isGpbLo(const Operand_& op, uint32_t rId) noexcept { return isGpbLo(op) & (op.id() == rId); } - static inline bool isGpbHi(const Operand_& op, uint32_t rId) noexcept { return isGpbHi(op) & (op.id() == rId); } - static inline bool isGpw(const Operand_& op, uint32_t rId) noexcept { return isGpw(op) & (op.id() == rId); } - static inline bool isGpd(const Operand_& op, uint32_t rId) noexcept { return isGpd(op) & (op.id() == rId); } - static inline bool isGpq(const Operand_& op, uint32_t rId) noexcept { return isGpq(op) & (op.id() == rId); } - static inline bool isXmm(const Operand_& op, uint32_t rId) noexcept { return isXmm(op) & (op.id() == rId); } - static inline bool isYmm(const Operand_& op, uint32_t rId) noexcept { return isYmm(op) & (op.id() == rId); } - static inline bool isZmm(const Operand_& op, uint32_t rId) noexcept { return isZmm(op) & (op.id() == rId); } - static inline bool isMm(const Operand_& op, uint32_t rId) noexcept { return isMm(op) & (op.id() == rId); } - static inline bool isKReg(const Operand_& op, uint32_t rId) noexcept { return isKReg(op) & (op.id() == rId); } - static inline bool isSReg(const Operand_& op, uint32_t rId) noexcept { return isSReg(op) & (op.id() == rId); } - static inline bool isCReg(const Operand_& op, uint32_t rId) noexcept { return isCReg(op) & (op.id() == rId); } - static inline bool isDReg(const Operand_& op, uint32_t rId) noexcept { return isDReg(op) & (op.id() == rId); } - static inline bool isSt(const Operand_& op, uint32_t rId) noexcept { return isSt(op) & (op.id() == rId); } - static inline bool isBnd(const Operand_& op, uint32_t rId) noexcept { return isBnd(op) & (op.id() == rId); } - static inline bool isTmm(const Operand_& op, uint32_t rId) noexcept { return isTmm(op) & (op.id() == rId); } - static inline bool isRip(const Operand_& op, uint32_t rId) noexcept { return isRip(op) & (op.id() == rId); } + static ASMJIT_INLINE_NODEBUG bool isGpbLo(const Operand_& op) noexcept { return op.as<Reg>().isGpbLo(); } + static ASMJIT_INLINE_NODEBUG bool isGpbHi(const Operand_& op) noexcept { return op.as<Reg>().isGpbHi(); } + static ASMJIT_INLINE_NODEBUG bool isGpw(const Operand_& op) noexcept { return op.as<Reg>().isGpw(); } + static ASMJIT_INLINE_NODEBUG bool isGpd(const Operand_& op) noexcept { return op.as<Reg>().isGpd(); } + static ASMJIT_INLINE_NODEBUG bool isGpq(const Operand_& op) noexcept { return op.as<Reg>().isGpq(); } + static ASMJIT_INLINE_NODEBUG bool isXmm(const Operand_& op) noexcept { return op.as<Reg>().isXmm(); } + static ASMJIT_INLINE_NODEBUG bool isYmm(const Operand_& op) noexcept { return op.as<Reg>().isYmm(); } + static ASMJIT_INLINE_NODEBUG bool isZmm(const Operand_& op) noexcept { return op.as<Reg>().isZmm(); } + static ASMJIT_INLINE_NODEBUG bool isMm(const Operand_& op) noexcept { return op.as<Reg>().isMm(); } + static ASMJIT_INLINE_NODEBUG bool isKReg(const Operand_& op) noexcept { return op.as<Reg>().isKReg(); } + static ASMJIT_INLINE_NODEBUG bool isSReg(const Operand_& op) noexcept { return op.as<Reg>().isSReg(); } + static ASMJIT_INLINE_NODEBUG bool isCReg(const Operand_& op) noexcept { return op.as<Reg>().isCReg(); } + static ASMJIT_INLINE_NODEBUG bool isDReg(const Operand_& op) noexcept { return op.as<Reg>().isDReg(); } + static ASMJIT_INLINE_NODEBUG bool isSt(const Operand_& op) noexcept { return op.as<Reg>().isSt(); } + static ASMJIT_INLINE_NODEBUG bool isBnd(const Operand_& op) noexcept { return op.as<Reg>().isBnd(); } + static ASMJIT_INLINE_NODEBUG bool isTmm(const Operand_& op) noexcept { return op.as<Reg>().isTmm(); } + static ASMJIT_INLINE_NODEBUG bool isRip(const Operand_& op) noexcept { return op.as<Reg>().isRip(); } + + static ASMJIT_INLINE_NODEBUG bool isGpb(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpb(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isGpbLo(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpbLo(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isGpbHi(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpbHi(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isGpw(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpw(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isGpd(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpd(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isGpq(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpq(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isXmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isXmm(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isYmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isYmm(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isZmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isZmm(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isMm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isMm(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isKReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isKReg(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isSReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isSReg(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isCReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isCReg(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isDReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isDReg(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isSt(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isSt(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isBnd(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isBnd(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isTmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isTmm(op)) & unsigned(op.id() == rId)); } + static ASMJIT_INLINE_NODEBUG bool isRip(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isRip(op)) & unsigned(op.id() == rId)); } }; //! General purpose register (X86). @@ -223,17 +237,17 @@ public: }; //! Casts this register to 8-bit (LO) part. - inline GpbLo r8() const noexcept; + ASMJIT_INLINE_NODEBUG GpbLo r8() const noexcept; //! Casts this register to 8-bit (LO) part. - inline GpbLo r8Lo() const noexcept; + ASMJIT_INLINE_NODEBUG GpbLo r8Lo() const noexcept; //! Casts this register to 8-bit (HI) part. - inline GpbHi r8Hi() const noexcept; + ASMJIT_INLINE_NODEBUG GpbHi r8Hi() const noexcept; //! Casts this register to 16-bit. - inline Gpw r16() const noexcept; + ASMJIT_INLINE_NODEBUG Gpw r16() const noexcept; //! Casts this register to 32-bit. - inline Gpd r32() const noexcept; + ASMJIT_INLINE_NODEBUG Gpd r32() const noexcept; //! Casts this register to 64-bit. - inline Gpq r64() const noexcept; + ASMJIT_INLINE_NODEBUG Gpq r64() const noexcept; }; //! Vector register (XMM|YMM|ZMM) (X86). @@ -241,14 +255,21 @@ class Vec : public Reg { ASMJIT_DEFINE_ABSTRACT_REG(Vec, Reg) //! Casts this register to XMM (clone). - inline Xmm xmm() const noexcept; - //! Casts this register to YMM. - inline Ymm ymm() const noexcept; - //! Casts this register to ZMM. - inline Zmm zmm() const noexcept; + ASMJIT_INLINE_NODEBUG Xmm xmm() const noexcept; + //! Casts this register to YMM (clone). + ASMJIT_INLINE_NODEBUG Ymm ymm() const noexcept; + //! Casts this register to ZMM (clone). + ASMJIT_INLINE_NODEBUG Zmm zmm() const noexcept; + + //! Casts this register to XMM (clone). + ASMJIT_INLINE_NODEBUG Vec v128() const noexcept; + //! Casts this register to YMM (clone). + ASMJIT_INLINE_NODEBUG Vec v256() const noexcept; + //! Casts this register to ZMM (clone). + ASMJIT_INLINE_NODEBUG Vec v512() const noexcept; //! Casts this register to a register that has half the size (or XMM if it's already XMM). - inline Vec half() const noexcept { + ASMJIT_INLINE_NODEBUG Vec half() const noexcept { return Vec(type() == RegType::kX86_Zmm ? signatureOfT<RegType::kX86_Ymm>() : signatureOfT<RegType::kX86_Xmm>(), id()); } }; @@ -300,21 +321,21 @@ class Gpq : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpq, Gp, RegTraits<RegType::kX86 class Xmm : public Vec { ASMJIT_DEFINE_FINAL_REG(Xmm, Vec, RegTraits<RegType::kX86_Xmm>) //! Casts this register to a register that has half the size (XMM). - inline Xmm half() const noexcept { return Xmm(id()); } + ASMJIT_INLINE_NODEBUG Xmm half() const noexcept { return Xmm(id()); } }; //! 256-bit YMM register (AVX+). class Ymm : public Vec { ASMJIT_DEFINE_FINAL_REG(Ymm, Vec, RegTraits<RegType::kX86_Ymm>) //! Casts this register to a register that has half the size (XMM). - inline Xmm half() const noexcept { return Xmm(id()); } + ASMJIT_INLINE_NODEBUG Xmm half() const noexcept { return Xmm(id()); } }; //! 512-bit ZMM register (AVX512+). class Zmm : public Vec { ASMJIT_DEFINE_FINAL_REG(Zmm, Vec, RegTraits<RegType::kX86_Zmm>) //! Casts this register to a register that has half the size (YMM). - inline Ymm half() const noexcept { return Ymm(id()); } + ASMJIT_INLINE_NODEBUG Ymm half() const noexcept { return Ymm(id()); } }; //! 64-bit MMX register (MMX+). @@ -335,60 +356,61 @@ class Tmm : public Reg { ASMJIT_DEFINE_FINAL_REG(Tmm, Reg, RegTraits<RegType::kX class Rip : public Reg { ASMJIT_DEFINE_FINAL_REG(Rip, Reg, RegTraits<RegType::kX86_Rip>) }; //! \cond -inline GpbLo Gp::r8() const noexcept { return GpbLo(id()); } -inline GpbLo Gp::r8Lo() const noexcept { return GpbLo(id()); } -inline GpbHi Gp::r8Hi() const noexcept { return GpbHi(id()); } -inline Gpw Gp::r16() const noexcept { return Gpw(id()); } -inline Gpd Gp::r32() const noexcept { return Gpd(id()); } -inline Gpq Gp::r64() const noexcept { return Gpq(id()); } -inline Xmm Vec::xmm() const noexcept { return Xmm(id()); } -inline Ymm Vec::ymm() const noexcept { return Ymm(id()); } -inline Zmm Vec::zmm() const noexcept { return Zmm(id()); } +ASMJIT_INLINE_NODEBUG GpbLo Gp::r8() const noexcept { return GpbLo(id()); } +ASMJIT_INLINE_NODEBUG GpbLo Gp::r8Lo() const noexcept { return GpbLo(id()); } +ASMJIT_INLINE_NODEBUG GpbHi Gp::r8Hi() const noexcept { return GpbHi(id()); } +ASMJIT_INLINE_NODEBUG Gpw Gp::r16() const noexcept { return Gpw(id()); } +ASMJIT_INLINE_NODEBUG Gpd Gp::r32() const noexcept { return Gpd(id()); } +ASMJIT_INLINE_NODEBUG Gpq Gp::r64() const noexcept { return Gpq(id()); } +ASMJIT_INLINE_NODEBUG Xmm Vec::xmm() const noexcept { return Xmm(id()); } +ASMJIT_INLINE_NODEBUG Ymm Vec::ymm() const noexcept { return Ymm(id()); } +ASMJIT_INLINE_NODEBUG Zmm Vec::zmm() const noexcept { return Zmm(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v128() const noexcept { return Xmm(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v256() const noexcept { return Ymm(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v512() const noexcept { return Zmm(id()); } //! \endcond //! \namespace asmjit::x86::regs //! -//! Registers provided by X86 and X64 ISAs are in both `asmjit::x86` and -//! `asmjit::x86::regs` namespaces so they can be included with using directive. -//! For example `using namespace asmjit::x86::regs` would include all registers, -//! but not other X86-specific API, whereas `using namespace asmjit::x86` would -//! include everything X86-specific. +//! Registers provided by X86 and X64 ISAs are in both `asmjit::x86` and `asmjit::x86::regs` namespaces so they can +//! be included with using directive. For example `using namespace asmjit::x86::regs` would include all registers, +//! but not other X86-specific API, whereas `using namespace asmjit::x86` would include everything X86-specific. #ifndef _DOXYGEN namespace regs { #endif //! Creates an 8-bit low GPB register operand. -static constexpr GpbLo gpb(uint32_t rId) noexcept { return GpbLo(rId); } +static ASMJIT_INLINE_NODEBUG constexpr GpbLo gpb(uint32_t rId) noexcept { return GpbLo(rId); } //! Creates an 8-bit low GPB register operand. -static constexpr GpbLo gpb_lo(uint32_t rId) noexcept { return GpbLo(rId); } +static ASMJIT_INLINE_NODEBUG constexpr GpbLo gpb_lo(uint32_t rId) noexcept { return GpbLo(rId); } //! Creates an 8-bit high GPB register operand. -static constexpr GpbHi gpb_hi(uint32_t rId) noexcept { return GpbHi(rId); } +static ASMJIT_INLINE_NODEBUG constexpr GpbHi gpb_hi(uint32_t rId) noexcept { return GpbHi(rId); } //! Creates a 16-bit GPW register operand. -static constexpr Gpw gpw(uint32_t rId) noexcept { return Gpw(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Gpw gpw(uint32_t rId) noexcept { return Gpw(rId); } //! Creates a 32-bit GPD register operand. -static constexpr Gpd gpd(uint32_t rId) noexcept { return Gpd(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Gpd gpd(uint32_t rId) noexcept { return Gpd(rId); } //! Creates a 64-bit GPQ register operand (64-bit). -static constexpr Gpq gpq(uint32_t rId) noexcept { return Gpq(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Gpq gpq(uint32_t rId) noexcept { return Gpq(rId); } //! Creates a 128-bit XMM register operand. -static constexpr Xmm xmm(uint32_t rId) noexcept { return Xmm(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Xmm xmm(uint32_t rId) noexcept { return Xmm(rId); } //! Creates a 256-bit YMM register operand. -static constexpr Ymm ymm(uint32_t rId) noexcept { return Ymm(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Ymm ymm(uint32_t rId) noexcept { return Ymm(rId); } //! Creates a 512-bit ZMM register operand. -static constexpr Zmm zmm(uint32_t rId) noexcept { return Zmm(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Zmm zmm(uint32_t rId) noexcept { return Zmm(rId); } //! Creates a 64-bit Mm register operand. -static constexpr Mm mm(uint32_t rId) noexcept { return Mm(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Mm mm(uint32_t rId) noexcept { return Mm(rId); } //! Creates a 64-bit K register operand. -static constexpr KReg k(uint32_t rId) noexcept { return KReg(rId); } +static ASMJIT_INLINE_NODEBUG constexpr KReg k(uint32_t rId) noexcept { return KReg(rId); } //! Creates a 32-bit or 64-bit control register operand. -static constexpr CReg cr(uint32_t rId) noexcept { return CReg(rId); } +static ASMJIT_INLINE_NODEBUG constexpr CReg cr(uint32_t rId) noexcept { return CReg(rId); } //! Creates a 32-bit or 64-bit debug register operand. -static constexpr DReg dr(uint32_t rId) noexcept { return DReg(rId); } +static ASMJIT_INLINE_NODEBUG constexpr DReg dr(uint32_t rId) noexcept { return DReg(rId); } //! Creates an 80-bit st register operand. -static constexpr St st(uint32_t rId) noexcept { return St(rId); } +static ASMJIT_INLINE_NODEBUG constexpr St st(uint32_t rId) noexcept { return St(rId); } //! Creates a 128-bit bound register operand. -static constexpr Bnd bnd(uint32_t rId) noexcept { return Bnd(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Bnd bnd(uint32_t rId) noexcept { return Bnd(rId); } //! Creates a TMM register operand. -static constexpr Tmm tmm(uint32_t rId) noexcept { return Tmm(rId); } +static ASMJIT_INLINE_NODEBUG constexpr Tmm tmm(uint32_t rId) noexcept { return Tmm(rId); } static constexpr GpbLo al = GpbLo(Gp::kIdAx); static constexpr GpbLo bl = GpbLo(Gp::kIdBx); @@ -723,25 +745,25 @@ public: //! \{ //! Creates a default `Mem` operand that points to [0]. - inline constexpr Mem() noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem() noexcept : BaseMem() {} - inline constexpr Mem(const Mem& other) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const Mem& other) noexcept : BaseMem(other) {} - inline explicit Mem(Globals::NoInit_) noexcept + ASMJIT_INLINE_NODEBUG explicit Mem(Globals::NoInit_) noexcept : BaseMem(Globals::NoInit) {} - inline constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept : BaseMem(signature, baseId, indexId, offset) {} - inline constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(RegType::kLabelTag) | Signature::fromSize(size) | signature, base.id(), 0, off) {} - inline constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(RegType::kLabelTag) | Signature::fromMemIndexType(index.type()) | @@ -749,13 +771,13 @@ public: Signature::fromSize(size) | signature, base.id(), index.id(), off) {} - inline constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(base.type()) | Signature::fromSize(size) | signature, base.id(), 0, off) {} - inline constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(base.type()) | Signature::fromMemIndexType(index.type()) | @@ -763,12 +785,12 @@ public: Signature::fromSize(size) | signature, base.id(), index.id(), off) {} - inline constexpr explicit Mem(uint64_t base, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr explicit Mem(uint64_t base, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromSize(size) | signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {} - inline constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemIndexType(index.type()) | Signature::fromValue<kSignatureMemShiftValueMask>(shift) | @@ -780,7 +802,7 @@ public: //! \name Overloaded Operators //! \{ - inline Mem& operator=(const Mem& other) noexcept = default; + ASMJIT_INLINE_NODEBUG Mem& operator=(const Mem& other) noexcept = default; //! \} @@ -788,17 +810,25 @@ public: //! \{ //! Clones the memory operand. - inline constexpr Mem clone() const noexcept { return Mem(*this); } + ASMJIT_INLINE_NODEBUG constexpr Mem clone() const noexcept { return Mem(*this); } - //! Creates a new copy of this memory operand adjusted by `off`. + //! Creates a copy of this memory operand adjusted by `off`. inline Mem cloneAdjusted(int64_t off) const noexcept { Mem result(*this); result.addOffset(off); return result; } - inline constexpr Mem cloneBroadcasted(Broadcast b) const noexcept { - return Mem((_signature & ~Signature{kSignatureMemBroadcastMask}) | Signature::fromValue<kSignatureMemBroadcastMask>(b), _baseId, _data[0], int32_t(_data[1])); + //! Creates a copy of this memory operand resized to `size`. + inline Mem cloneResized(uint32_t size) const noexcept { + Mem result(*this); + result.setSize(size); + return result; + } + + //! Creates a copy of this memory operand with a broadcast `bcst`. + ASMJIT_INLINE_NODEBUG constexpr Mem cloneBroadcasted(Broadcast bcst) const noexcept { + return Mem((_signature & ~Signature{kSignatureMemBroadcastMask}) | Signature::fromValue<kSignatureMemBroadcastMask>(bcst), _baseId, _data[0], int32_t(_data[1])); } //! \} @@ -809,43 +839,64 @@ public: //! Converts memory `baseType` and `baseId` to `x86::Reg` instance. //! //! The memory must have a valid base register otherwise the result will be wrong. - inline Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); } + ASMJIT_INLINE_NODEBUG Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); } //! Converts memory `indexType` and `indexId` to `x86::Reg` instance. //! //! The memory must have a valid index register otherwise the result will be wrong. - inline Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); } + ASMJIT_INLINE_NODEBUG Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); } using BaseMem::setIndex; - inline void setIndex(const BaseReg& index, uint32_t shift) noexcept { + ASMJIT_INLINE_NODEBUG void setIndex(const BaseReg& index, uint32_t shift) noexcept { setIndex(index); setShift(shift); } //! \} + //! \name Memory Size + //! \{ + + //! Tests whether the memory operand specifies a size (i.e. the size is not zero). + ASMJIT_INLINE_NODEBUG constexpr bool hasSize() const noexcept { return _signature.hasField<Signature::kSizeMask>(); } + //! Tests whether the memory operand size matches size `s`. + ASMJIT_INLINE_NODEBUG constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; } + + //! Returns the size of the memory operand in bytes. + //! + //! \note Most instructions would deduce the size of the memory operand, so in most cases it's expected that the + //! returned value would be zero. However, some instruction require the size to select between multiple variations, + //! so in some cases size is required would be non-zero (for example `inc [mem], immediate` requires size to + //! distinguish between 8-bit, 16-bit, 32-bit, and 64-bit increments. + ASMJIT_INLINE_NODEBUG constexpr uint32_t size() const noexcept { return _signature.getField<Signature::kSizeMask>(); } + + //! Sets the memory operand size (in bytes). + ASMJIT_INLINE_NODEBUG void setSize(uint32_t size) noexcept { _signature.setField<Signature::kSizeMask>(size); } + + //! \} + //! \name Address Type //! \{ //! Returns the address type of the memory operand. //! //! By default, address type of newly created memory operands is always \ref AddrType::kDefault. - inline constexpr AddrType addrType() const noexcept { return (AddrType)_signature.getField<kSignatureMemAddrTypeMask>(); } + ASMJIT_INLINE_NODEBUG constexpr AddrType addrType() const noexcept { return (AddrType)_signature.getField<kSignatureMemAddrTypeMask>(); } //! Sets the address type to `addrType`. - inline void setAddrType(AddrType addrType) noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(addrType)); } + ASMJIT_INLINE_NODEBUG void setAddrType(AddrType addrType) noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(addrType)); } //! Resets the address type to \ref AddrType::kDefault. - inline void resetAddrType() noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(AddrType::kDefault)); } + ASMJIT_INLINE_NODEBUG void resetAddrType() noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(AddrType::kDefault)); } //! Tests whether the address type is \ref AddrType::kAbs. - inline constexpr bool isAbs() const noexcept { return addrType() == AddrType::kAbs; } + ASMJIT_INLINE_NODEBUG constexpr bool isAbs() const noexcept { return addrType() == AddrType::kAbs; } //! Sets the address type to \ref AddrType::kAbs. - inline void setAbs() noexcept { setAddrType(AddrType::kAbs); } + ASMJIT_INLINE_NODEBUG void setAbs() noexcept { setAddrType(AddrType::kAbs); } //! Tests whether the address type is \ref AddrType::kRel. - inline constexpr bool isRel() const noexcept { return addrType() == AddrType::kRel; } + ASMJIT_INLINE_NODEBUG constexpr bool isRel() const noexcept { return addrType() == AddrType::kRel; } //! Sets the address type to \ref AddrType::kRel. - inline void setRel() noexcept { setAddrType(AddrType::kRel); } + ASMJIT_INLINE_NODEBUG void setRel() noexcept { setAddrType(AddrType::kRel); } //! \} @@ -853,18 +904,18 @@ public: //! \{ //! Tests whether the memory operand has a segment override. - inline constexpr bool hasSegment() const noexcept { return _signature.hasField<kSignatureMemSegmentMask>(); } + ASMJIT_INLINE_NODEBUG constexpr bool hasSegment() const noexcept { return _signature.hasField<kSignatureMemSegmentMask>(); } //! Returns the associated segment override as `SReg` operand. - inline constexpr SReg segment() const noexcept { return SReg(segmentId()); } + ASMJIT_INLINE_NODEBUG constexpr SReg segment() const noexcept { return SReg(segmentId()); } //! Returns segment override register id, see `SReg::Id`. - inline constexpr uint32_t segmentId() const noexcept { return _signature.getField<kSignatureMemSegmentMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t segmentId() const noexcept { return _signature.getField<kSignatureMemSegmentMask>(); } //! Sets the segment override to `seg`. - inline void setSegment(const SReg& seg) noexcept { setSegment(seg.id()); } + ASMJIT_INLINE_NODEBUG void setSegment(const SReg& seg) noexcept { setSegment(seg.id()); } //! Sets the segment override to `id`. - inline void setSegment(uint32_t rId) noexcept { _signature.setField<kSignatureMemSegmentMask>(rId); } + ASMJIT_INLINE_NODEBUG void setSegment(uint32_t rId) noexcept { _signature.setField<kSignatureMemSegmentMask>(rId); } //! Resets the segment override. - inline void resetSegment() noexcept { _signature.setField<kSignatureMemSegmentMask>(0); } + ASMJIT_INLINE_NODEBUG void resetSegment() noexcept { _signature.setField<kSignatureMemSegmentMask>(0); } //! \} @@ -872,13 +923,13 @@ public: //! \{ //! Tests whether the memory operand has shift (aka scale) value. - inline constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); } + ASMJIT_INLINE_NODEBUG constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); } //! Returns the memory operand's shift (aka scale) value. - inline constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); } + ASMJIT_INLINE_NODEBUG constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); } //! Sets the memory operand's shift (aka scale) value. - inline void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); } + ASMJIT_INLINE_NODEBUG void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); } //! Resets the memory operand's shift (aka scale) value to zero. - inline void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); } + ASMJIT_INLINE_NODEBUG void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); } //! \} @@ -886,156 +937,168 @@ public: //! \{ //! Tests whether the memory operand has broadcast {1tox}. - inline constexpr bool hasBroadcast() const noexcept { return _signature.hasField<kSignatureMemBroadcastMask>(); } + ASMJIT_INLINE_NODEBUG constexpr bool hasBroadcast() const noexcept { return _signature.hasField<kSignatureMemBroadcastMask>(); } //! Returns the memory operand's broadcast. - inline constexpr Broadcast getBroadcast() const noexcept { return (Broadcast)_signature.getField<kSignatureMemBroadcastMask>(); } + ASMJIT_INLINE_NODEBUG constexpr Broadcast getBroadcast() const noexcept { return (Broadcast)_signature.getField<kSignatureMemBroadcastMask>(); } //! Sets the memory operand's broadcast. - inline void setBroadcast(Broadcast b) noexcept { _signature.setField<kSignatureMemBroadcastMask>(uint32_t(b)); } + ASMJIT_INLINE_NODEBUG void setBroadcast(Broadcast b) noexcept { _signature.setField<kSignatureMemBroadcastMask>(uint32_t(b)); } //! Resets the memory operand's broadcast to none. - inline void resetBroadcast() noexcept { _signature.setField<kSignatureMemBroadcastMask>(0); } + ASMJIT_INLINE_NODEBUG void resetBroadcast() noexcept { _signature.setField<kSignatureMemBroadcastMask>(0); } //! Returns a new `Mem` without a broadcast (the possible broadcast is cleared). - inline constexpr Mem _1to1() const noexcept { return cloneBroadcasted(Broadcast::kNone); } + ASMJIT_INLINE_NODEBUG constexpr Mem _1to1() const noexcept { return cloneBroadcasted(Broadcast::kNone); } //! Returns a new `Mem` with {1to2} broadcast (AVX-512). - inline constexpr Mem _1to2() const noexcept { return cloneBroadcasted(Broadcast::k1To2); } + ASMJIT_INLINE_NODEBUG constexpr Mem _1to2() const noexcept { return cloneBroadcasted(Broadcast::k1To2); } //! Returns a new `Mem` with {1to4} broadcast (AVX-512). - inline constexpr Mem _1to4() const noexcept { return cloneBroadcasted(Broadcast::k1To4); } + ASMJIT_INLINE_NODEBUG constexpr Mem _1to4() const noexcept { return cloneBroadcasted(Broadcast::k1To4); } //! Returns a new `Mem` with {1to8} broadcast (AVX-512). - inline constexpr Mem _1to8() const noexcept { return cloneBroadcasted(Broadcast::k1To8); } + ASMJIT_INLINE_NODEBUG constexpr Mem _1to8() const noexcept { return cloneBroadcasted(Broadcast::k1To8); } //! Returns a new `Mem` with {1to16} broadcast (AVX-512). - inline constexpr Mem _1to16() const noexcept { return cloneBroadcasted(Broadcast::k1To16); } + ASMJIT_INLINE_NODEBUG constexpr Mem _1to16() const noexcept { return cloneBroadcasted(Broadcast::k1To16); } //! Returns a new `Mem` with {1to32} broadcast (AVX-512). - inline constexpr Mem _1to32() const noexcept { return cloneBroadcasted(Broadcast::k1To32); } + ASMJIT_INLINE_NODEBUG constexpr Mem _1to32() const noexcept { return cloneBroadcasted(Broadcast::k1To32); } //! Returns a new `Mem` with {1to64} broadcast (AVX-512). - inline constexpr Mem _1to64() const noexcept { return cloneBroadcasted(Broadcast::k1To64); } + ASMJIT_INLINE_NODEBUG constexpr Mem _1to64() const noexcept { return cloneBroadcasted(Broadcast::k1To64); } //! \} }; //! Creates `[base.reg + offset]` memory operand. -static inline constexpr Mem ptr(const Gp& base, int32_t offset = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, offset, size); } //! Creates `[base.reg + (index << shift) + offset]` memory operand (scalar index). -static inline constexpr Mem ptr(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, offset, size); } //! Creates `[base.reg + (index << shift) + offset]` memory operand (vector index). -static inline constexpr Mem ptr(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, offset, size); } //! Creates `[base + offset]` memory operand. -static inline constexpr Mem ptr(const Label& base, int32_t offset = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, offset, size); } //! Creates `[base + (index << shift) + offset]` memory operand. -static inline constexpr Mem ptr(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, offset, size); } //! Creates `[base + (index << shift) + offset]` memory operand. -static inline constexpr Mem ptr(const Label& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, offset, size); } //! Creates `[rip + offset]` memory operand. -static inline constexpr Mem ptr(const Rip& rip_, int32_t offset = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Rip& rip_, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(rip_, offset, size); } //! Creates `[base]` absolute memory operand. -static inline constexpr Mem ptr(uint64_t base, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base, uint32_t size = 0) noexcept { return Mem(base, size); } //! Creates `[base + (index.reg << shift)]` absolute memory operand. -static inline constexpr Mem ptr(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, size); } //! Creates `[base + (index.reg << shift)]` absolute memory operand. -static inline constexpr Mem ptr(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, size); } //! Creates `[base]` absolute memory operand (absolute). -static inline constexpr Mem ptr_abs(uint64_t base, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_abs(uint64_t base, uint32_t size = 0) noexcept { return Mem(base, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } //! Creates `[base + (index.reg << shift)]` absolute memory operand (absolute). -static inline constexpr Mem ptr_abs(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_abs(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } //! Creates `[base + (index.reg << shift)]` absolute memory operand (absolute). -static inline constexpr Mem ptr_abs(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_abs(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } //! Creates `[base]` relative memory operand (relative). -static inline constexpr Mem ptr_rel(uint64_t base, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_rel(uint64_t base, uint32_t size = 0) noexcept { return Mem(base, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } //! Creates `[base + (index.reg << shift)]` relative memory operand (relative). -static inline constexpr Mem ptr_rel(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_rel(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } //! Creates `[base + (index.reg << shift)]` relative memory operand (relative). -static inline constexpr Mem ptr_rel(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_rel(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } -#define ASMJIT_MEM_PTR(FUNC, SIZE) \ - static constexpr Mem FUNC(const Gp& base, int32_t offset = 0) noexcept { \ - return Mem(base, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ - return Mem(base, index, shift, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ - return Mem(base, index, shift, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Label& base, int32_t offset = 0) noexcept { \ - return Mem(base, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ - return Mem(base, index, shift, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Rip& rip_, int32_t offset = 0) noexcept { \ - return Mem(rip_, offset, SIZE); \ - } \ - static constexpr Mem FUNC(uint64_t base) noexcept { \ - return Mem(base, SIZE); \ - } \ - static constexpr Mem FUNC(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE); \ - } \ - static constexpr Mem FUNC(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE); \ - } \ - \ - static constexpr Mem FUNC##_abs(uint64_t base) noexcept { \ - return Mem(base, SIZE, \ - OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \ - } \ - static constexpr Mem FUNC##_abs(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE, \ - OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \ - } \ - static constexpr Mem FUNC##_abs(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE, \ - OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \ - } \ - \ - static constexpr Mem FUNC##_rel(uint64_t base) noexcept { \ - return Mem(base, SIZE, \ - OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \ - } \ - static constexpr Mem FUNC##_rel(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE, \ - OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \ - } \ - static constexpr Mem FUNC##_rel(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE, \ - OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \ - } +#define ASMJIT_MEM_PTR(FUNC, SIZE) \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + const Gp& base, int32_t offset = 0) noexcept \ + { return Mem(base, offset, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept \ + { return Mem(base, index, shift, offset, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0) noexcept \ + { return Mem(base, index, shift, offset, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + const Label& base, int32_t offset = 0) noexcept \ + { return Mem(base, offset, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept \ + { return Mem(base, index, shift, offset, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + const Rip& rip_, int32_t offset = 0) noexcept \ + { return Mem(rip_, offset, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + uint64_t base) noexcept \ + { return Mem(base, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + uint64_t base, const Gp& index, uint32_t shift = 0) noexcept \ + { return Mem(base, index, shift, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \ + uint64_t base, const Vec& index, uint32_t shift = 0) noexcept \ + { return Mem(base, index, shift, SIZE); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_abs( \ + uint64_t base) noexcept \ + { return Mem(base, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_abs( \ + uint64_t base, const Gp& index, uint32_t shift = 0) noexcept \ + { return Mem(base, index, shift, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_abs( \ + uint64_t base, const Vec& index, uint32_t shift = 0) noexcept \ + { return Mem(base, index, shift, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_rel( \ + uint64_t base) noexcept \ + { return Mem(base, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_rel( \ + uint64_t base, const Gp& index, uint32_t shift = 0) noexcept \ + { return Mem(base, index, shift, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } \ + \ + static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_rel( \ + uint64_t base, const Vec& index, uint32_t shift = 0) noexcept \ + { return Mem(base, index, shift, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } // Definition of memory operand constructors that use platform independent naming. ASMJIT_MEM_PTR(ptr_8, 1) diff --git a/3rdparty/asmjit/src/asmjit/x86/x86rapass.cpp b/3rdparty/asmjit/src/asmjit/x86/x86rapass.cpp index 02870d95ffe..c106c6c7e1d 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86rapass.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86rapass.cpp @@ -183,6 +183,9 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& cf, RAInstBuilder& i RATiedFlags flags = raRegRwFlags(opRwInfo.opFlags()); RegMask allowedRegs = instructionAllowedRegs; + if (opRwInfo.isUnique()) + flags |= RATiedFlags::kUnique; + // X86-specific constraints related to LO|HI general purpose registers. This is only required when the // register is part of the encoding. If the register is fixed we won't restrict anything as it doesn't // restrict encoding of other registers. @@ -220,9 +223,11 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& cf, RAInstBuilder& i } } - // Do not use RegMem flag if changing Reg to Mem requires additional CPU feature that may not be enabled. + // Do not use RegMem flag if changing Reg to Mem requires a CPU feature that is not available. if (rwInfo.rmFeature() && Support::test(flags, RATiedFlags::kUseRM | RATiedFlags::kOutRM)) { - flags &= ~(RATiedFlags::kUseRM | RATiedFlags::kOutRM); + if (!cc()->code()->cpuFeatures().has(rwInfo.rmFeature())) { + flags &= ~(RATiedFlags::kUseRM | RATiedFlags::kOutRM); + } } RegGroup group = workReg->group(); @@ -472,6 +477,20 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& cf, RAInstBuilder& i } } } + else if (opCount == 4 && inst->op(3).isImm()) { + const Imm& imm = inst->op(3).as<Imm>(); + + switch (inst->id()) { + case Inst::kIdVpternlogd: + case Inst::kIdVpternlogq: { + uint32_t predicate = uint32_t(imm.value() & 0xFFu); + if (predicate == 0x00u || predicate == 0xFFu) { + ib[0]->makeWriteOnly(); + } + break; + } + } + } switch (sameRegHint) { case InstSameRegHint::kNone: @@ -818,7 +837,7 @@ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& a stackPtr.setSize(4); imm[0] = imm_; - uint32_t nMovs = 0; + uint32_t movCount = 0; // One stack entry has the same size as the native register size. That means that if we want to move a 32-bit // integer on the stack in 64-bit mode, we need to extend it to a 64-bit integer first. In 32-bit mode, pushing @@ -834,7 +853,7 @@ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& a case TypeId::kFloat32: MovU32: imm[0].zeroExtend32Bits(); - nMovs = 1; + movCount = 1; break; case TypeId::kInt64: @@ -844,20 +863,20 @@ MovU32: case TypeId::kMmx64: if (_is64Bit && imm[0].isInt32()) { stackPtr.setSize(8); - nMovs = 1; + movCount = 1; break; } imm[1].setValue(imm[0].uint32Hi()); imm[0].zeroExtend32Bits(); - nMovs = 2; + movCount = 2; break; default: return DebugUtils::errored(kErrorInvalidAssignment); } - for (uint32_t i = 0; i < nMovs; i++) { + for (uint32_t i = 0; i < movCount; i++) { ASMJIT_PROPAGATE(cc()->mov(stackPtr, imm[i])); stackPtr.addOffsetLo32(int32_t(stackPtr.size())); } @@ -1304,6 +1323,54 @@ ASMJIT_FAVOR_SPEED Error X86RAPass::_rewrite(BaseNode* first, BaseNode* stop) no } } + // If one operand was rewritten from Reg to Mem, we have to ensure that we are using the correct instruction. + if (raInst->isRegToMemPatched()) { + switch (inst->id()) { + case Inst::kIdKmovb: { + if (operands[0].isGp() && operands[1].isMem()) { + // Transform from [V]MOVD to MOV. + operands[1].as<Mem>().setSize(1); + inst->setId(Inst::kIdMovzx); + } + break; + } + + case Inst::kIdVmovw: { + if (operands[0].isGp() && operands[1].isMem()) { + // Transform from [V]MOVD to MOV. + operands[1].as<Mem>().setSize(2); + inst->setId(Inst::kIdMovzx); + } + break; + } + + case Inst::kIdMovd: + case Inst::kIdVmovd: + case Inst::kIdKmovd: { + if (operands[0].isGp() && operands[1].isMem()) { + // Transform from [V]MOVD to MOV. + operands[1].as<Mem>().setSize(4); + inst->setId(Inst::kIdMov); + } + break; + } + + case Inst::kIdMovq: + case Inst::kIdVmovq: + case Inst::kIdKmovq: { + if (operands[0].isGp() && operands[1].isMem()) { + // Transform from [V]MOVQ to MOV. + operands[1].as<Mem>().setSize(8); + inst->setId(Inst::kIdMov); + } + break; + } + + default: + break; + } + } + // Transform VEX instruction to EVEX when necessary. if (raInst->isTransformable()) { if (maxRegId > 15) { diff --git a/3rdparty/asmjit/src/asmjit/x86/x86rapass_p.h b/3rdparty/asmjit/src/asmjit/x86/x86rapass_p.h index b9603c21afc..67227a1a619 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86rapass_p.h +++ b/3rdparty/asmjit/src/asmjit/x86/x86rapass_p.h @@ -36,7 +36,7 @@ public: //! \{ X86RAPass() noexcept; - virtual ~X86RAPass() noexcept; + ~X86RAPass() noexcept override; //! \} @@ -44,20 +44,20 @@ public: //! \{ //! Returns the compiler casted to `x86::Compiler`. - inline Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); } + ASMJIT_INLINE_NODEBUG Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); } //! Returns emit helper. - inline EmitHelper* emitHelper() noexcept { return &_emitHelper; } + ASMJIT_INLINE_NODEBUG EmitHelper* emitHelper() noexcept { return &_emitHelper; } - inline bool avxEnabled() const noexcept { return _emitHelper._avxEnabled; } - inline bool avx512Enabled() const noexcept { return _emitHelper._avx512Enabled; } + ASMJIT_INLINE_NODEBUG bool avxEnabled() const noexcept { return _emitHelper._avxEnabled; } + ASMJIT_INLINE_NODEBUG bool avx512Enabled() const noexcept { return _emitHelper._avx512Enabled; } //! \} //! \name Utilities //! \{ - inline uint32_t choose(uint32_t sseInstId, uint32_t avxInstId) noexcept { + ASMJIT_INLINE_NODEBUG InstId choose(InstId sseInstId, InstId avxInstId) noexcept { return avxEnabled() ? avxInstId : sseInstId; } |