LCOV - code coverage report
Current view: top level - asmjit - operand.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 53 111 47.7 %
Date: 2026-11-05 10:19:06 Functions: 4 23 17.4 %

          Line data    Source code
       1             : #ifdef __PLUMED_HAS_ASMJIT
       2             : // This file is part of AsmJit project <https://asmjit.com>
       3             : //
       4             : // See asmjit.h or LICENSE.md for license and copyright information
       5             : // SPDX-License-Identifier: Zlib
       6             : 
       7             : #ifndef ASMJIT_CORE_OPERAND_H_INCLUDED
       8             : #define ASMJIT_CORE_OPERAND_H_INCLUDED
       9             : 
      10             : #include "archcommons.h"
      11             : #include "support.h"
      12             : #include "type.h"
      13             : 
      14             : ASMJIT_BEGIN_NAMESPACE
      15             : 
      16             : //! \addtogroup asmjit_assembler
      17             : //! \{
      18             : 
      19             : //! Operand type used by \ref Operand_.
      20             : enum class OperandType : uint32_t {
      21             :   //! Not an operand or not initialized.
      22             :   kNone = 0,
      23             :   //! Operand is a register.
      24             :   kReg = 1,
      25             :   //! Operand is a memory.
      26             :   kMem = 2,
      27             :   //! Operand is an immediate value.
      28             :   kImm = 3,
      29             :   //! Operand is a label.
      30             :   kLabel = 4,
      31             : 
      32             :   //! Maximum value of `OperandType`.
      33             :   kMaxValue = kLabel
      34             : };
      35             : 
      36             : static_assert(uint32_t(OperandType::kMem) == uint32_t(OperandType::kReg) + 1,
      37             :               "AsmJit requires that `OperandType::kMem` equals to `OperandType::kReg + 1`");
      38             : 
      39             : //! Register mask is a convenience typedef that describes a mask where each bit describes a physical register id
      40             : //! in the same \ref RegGroup. At the moment 32 bits are enough as AsmJit doesn't support any architecture that
      41             : //! would provide more than 32 registers for a register group.
      42             : typedef uint32_t RegMask;
      43             : 
      44             : //! Register type.
      45             : //!
      46             : //! Provides a unique type that can be used to identify a register or its view.
      47             : enum class RegType : uint8_t {
      48             :   //! No register - unused, invalid, multiple meanings.
      49             :   kNone = 0,
      50             : 
      51             :   //! This is not a register type. This value is reserved for a \ref Label that used in \ref BaseMem as a base.
      52             :   //!
      53             :   //! Label tag is used as a sub-type, forming a unique signature across all operand types as 0x1 is never associated
      54             :   //! with any register type. This means that a memory operand's BASE register can be constructed from virtually any
      55             :   //! operand (register vs. label) by just assigning its type (register type or label-tag) and operand id.
      56             :   kLabelTag = 1,
      57             : 
      58             :   //! Universal type describing program counter (PC) or instruction pointer (IP) register, if the target architecture
      59             :   //! actually exposes it as a separate register type, which most modern targets do.
      60             :   kPC = 2,
      61             : 
      62             :   //! 8-bit low general purpose register (X86).
      63             :   kGp8Lo = 3,
      64             :   //! 8-bit high general purpose register (X86).
      65             :   kGp8Hi = 4,
      66             :   //! 16-bit general purpose register (X86).
      67             :   kGp16 = 5,
      68             :   //! 32-bit general purpose register (X86|ARM).
      69             :   kGp32 = 6,
      70             :   //! 64-bit general purpose register (X86|ARM).
      71             :   kGp64 = 7,
      72             :   //! 8-bit view of a vector register (ARM).
      73             :   kVec8 = 8,
      74             :   //! 16-bit view of a vector register (ARM).
      75             :   kVec16 = 9,
      76             :   //! 32-bit view of a vector register (ARM).
      77             :   kVec32 = 10,
      78             :   //! 64-bit view of a vector register (ARM).
      79             :   //!
      80             :   //! \note This is never used for MMX registers on X86, MMX registers have its own category.
      81             :   kVec64 = 11,
      82             :   //! 128-bit view of a vector register (X86|ARM).
      83             :   kVec128 = 12,
      84             :   //! 256-bit view of a vector register (X86).
      85             :   kVec256 = 13,
      86             :   //! 512-bit view of a vector register (X86).
      87             :   kVec512 = 14,
      88             :   //! 1024-bit view of a vector register (future).
      89             :   kVec1024 = 15,
      90             :   //! View of a vector register, which width is implementation specific (AArch64).
      91             :   kVecNLen = 16,
      92             : 
      93             :   //! Mask register (X86).
      94             :   kMask = 17,
      95             : 
      96             :   //! Start of architecture dependent register types.
      97             :   kExtra = 18,
      98             : 
      99             :   // X86 Specific Register Types
     100             :   // ---------------------------
     101             : 
     102             :   // X86 Specific Register Types
     103             :   // ===========================
     104             : 
     105             :   //! Instruction pointer (RIP), only addressable in \ref x86::Mem in 64-bit targets.
     106             :   kX86_Rip = kPC,
     107             :   //! Low GPB register (AL, BL, CL, DL, ...).
     108             :   kX86_GpbLo = kGp8Lo,
     109             :   //! High GPB register (AH, BH, CH, DH only).
     110             :   kX86_GpbHi = kGp8Hi,
     111             :   //! GPW register.
     112             :   kX86_Gpw = kGp16,
     113             :   //! GPD register.
     114             :   kX86_Gpd = kGp32,
     115             :   //! GPQ register (64-bit).
     116             :   kX86_Gpq = kGp64,
     117             :   //! XMM register (SSE+).
     118             :   kX86_Xmm = kVec128,
     119             :   //! YMM register (AVX+).
     120             :   kX86_Ymm = kVec256,
     121             :   //! ZMM register (AVX512+).
     122             :   kX86_Zmm = kVec512,
     123             :   //! K register (AVX512+).
     124             :   kX86_KReg = kMask,
     125             :   //! MMX register.
     126             :   kX86_Mm = kExtra + 0,
     127             :   //! Segment register (None, ES, CS, SS, DS, FS, GS).
     128             :   kX86_SReg = kExtra + 1,
     129             :   //! Control register (CR).
     130             :   kX86_CReg = kExtra + 2,
     131             :   //! Debug register (DR).
     132             :   kX86_DReg = kExtra + 3,
     133             :   //! FPU (x87) register.
     134             :   kX86_St = kExtra + 4,
     135             :   //! Bound register (BND).
     136             :   kX86_Bnd = kExtra + 5,
     137             :   //! TMM register (AMX_TILE)
     138             :   kX86_Tmm = kExtra + 6,
     139             : 
     140             :   // ARM Specific Register Types
     141             :   // ===========================
     142             : 
     143             :   //! Program pointer (PC) register (AArch64).
     144             :   kARM_PC = kPC,
     145             :   //! 32-bit general purpose register (R or W).
     146             :   kARM_GpW = kGp32,
     147             :   //! 64-bit general purpose register (X).
     148             :   kARM_GpX = kGp64,
     149             :   //! 8-bit view of VFP/ASIMD register (B).
     150             :   kARM_VecB = kVec8,
     151             :   //! 16-bit view of VFP/ASIMD register (H).
     152             :   kARM_VecH = kVec16,
     153             :   //! 32-bit view of VFP/ASIMD register (S).
     154             :   kARM_VecS = kVec32,
     155             :   //! 64-bit view of VFP/ASIMD register (D).
     156             :   kARM_VecD = kVec64,
     157             :   //! 128-bit view of VFP/ASIMD register (Q|V).
     158             :   kARM_VecV = kVec128,
     159             : 
     160             :   //! Maximum value of `RegType`.
     161             :   kMaxValue = 31
     162             : };
     163             : ASMJIT_DEFINE_ENUM_COMPARE(RegType)
     164             : 
     165             : //! Register group.
     166             : //!
     167             : //! Provides a unique value that identifies groups of registers and their views.
     168             : enum class RegGroup : uint8_t {
     169             :   //! General purpose register group compatible with all backends.
     170             :   kGp = 0,
     171             :   //! Vector register group compatible with all backends.
     172             :   //!
     173             :   //! Describes X86 XMM|YMM|ZMM registers ARM/AArch64 V registers.
     174             :   kVec = 1,
     175             : 
     176             :   //! Extra virtual group #2 that can be used by Compiler for register allocation.
     177             :   kExtraVirt2 = 2,
     178             :   //! Extra virtual group #3 that can be used by Compiler for register allocation.
     179             :   kExtraVirt3 = 3,
     180             : 
     181             :   //! Program counter group.
     182             :   kPC = 4,
     183             : 
     184             :   //! Extra non-virtual group that can be used by registers not managed by Compiler.
     185             :   kExtraNonVirt = 5,
     186             : 
     187             :   // X86 Specific Register Groups
     188             :   // ----------------------------
     189             : 
     190             :   //! K register group (KReg) - maps to \ref RegGroup::kExtraVirt2 (X86, X86_64).
     191             :   kX86_K = kExtraVirt2,
     192             :   //! MMX register group (MM) - maps to \ref RegGroup::kExtraVirt3 (X86, X86_64).
     193             :   kX86_MM = kExtraVirt3,
     194             : 
     195             :   //! Instruction pointer (X86, X86_64).
     196             :   kX86_Rip = kPC,
     197             :   //! Segment register group (X86, X86_64).
     198             :   kX86_SReg = kExtraNonVirt + 0,
     199             :   //! CR register group (X86, X86_64).
     200             :   kX86_CReg = kExtraNonVirt + 1,
     201             :   //! DR register group (X86, X86_64).
     202             :   kX86_DReg = kExtraNonVirt + 2,
     203             :   //! FPU register group (X86, X86_64).
     204             :   kX86_St = kExtraNonVirt + 3,
     205             :   //! BND register group (X86, X86_64).
     206             :   kX86_Bnd = kExtraNonVirt + 4,
     207             :   //! TMM register group (X86, X86_64).
     208             :   kX86_Tmm = kExtraNonVirt + 5,
     209             : 
     210             :   //! First group - only used in loops.
     211             :   k0 = 0,
     212             :   //! Last value of a virtual register that is managed by \ref BaseCompiler.
     213             :   kMaxVirt = Globals::kNumVirtGroups - 1,
     214             :   //! Maximum value of `RegGroup`.
     215             :   kMaxValue = 15
     216             : };
     217           0 : ASMJIT_DEFINE_ENUM_COMPARE(RegGroup)
     218             : 
     219             : typedef Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kMaxVirt> RegGroupVirtValues;
     220             : 
     221             : //! Operand signature is a 32-bit number describing \ref Operand and some of its payload.
     222             : //!
     223             : //! In AsmJit operand signature is used to store additional payload of register, memory, and immediate operands.
     224             : //! In practice the biggest pressure on OperandSignature is from \ref BaseMem and architecture specific memory
     225             : //! operands that need to store additional payload that cannot be stored elsewhere as values of all other members
     226             : //! are fully specified by \ref BaseMem.
     227             : struct OperandSignature {
     228             :   //! \name Constants
     229             :   //! \{
     230             : 
     231             :   enum : uint32_t {
     232             :     // Operand type (3 least significant bits).
     233             :     // |........|........|........|.....XXX|
     234             :     kOpTypeShift = 0,
     235             :     kOpTypeMask = 0x07u << kOpTypeShift,
     236             : 
     237             :     // Register type (5 bits).
     238             :     // |........|........|........|XXXXX...|
     239             :     kRegTypeShift = 3,
     240             :     kRegTypeMask = 0x1Fu << kRegTypeShift,
     241             : 
     242             :     // Register group (4 bits).
     243             :     // |........|........|....XXXX|........|
     244             :     kRegGroupShift = 8,
     245             :     kRegGroupMask = 0x0Fu << kRegGroupShift,
     246             : 
     247             :     // Memory base type (5 bits).
     248             :     // |........|........|........|XXXXX...|
     249             :     kMemBaseTypeShift = 3,
     250             :     kMemBaseTypeMask = 0x1Fu << kMemBaseTypeShift,
     251             : 
     252             :     // Memory index type (5 bits).
     253             :     // |........|........|...XXXXX|........|
     254             :     kMemIndexTypeShift = 8,
     255             :     kMemIndexTypeMask = 0x1Fu << kMemIndexTypeShift,
     256             : 
     257             :     // Memory base+index combined (10 bits).
     258             :     // |........|........|...XXXXX|XXXXX...|
     259             :     kMemBaseIndexShift = 3,
     260             :     kMemBaseIndexMask = 0x3FFu << kMemBaseIndexShift,
     261             : 
     262             :     // This memory operand represents a home-slot or stack (Compiler) (1 bit).
     263             :     // |........|........|..X.....|........|
     264             :     kMemRegHomeShift = 13,
     265             :     kMemRegHomeFlag = 0x01u << kMemRegHomeShift,
     266             : 
     267             :     // Immediate type (1 bit).
     268             :     // |........|........|........|....X...|
     269             :     kImmTypeShift = 3,
     270             :     kImmTypeMask = 0x01u << kImmTypeShift,
     271             : 
     272             :     // Predicate used by either registers or immediate values (4 bits).
     273             :     // |........|XXXX....|........|........|
     274             :     kPredicateShift = 20,
     275             :     kPredicateMask = 0x0Fu << kPredicateShift,
     276             : 
     277             :     // Operand size (8 most significant bits).
     278             :     // |XXXXXXXX|........|........|........|
     279             :     kSizeShift = 24,
     280             :     kSizeMask = 0xFFu << kSizeShift
     281             :   };
     282             : 
     283             :   //! \}
     284             : 
     285             :   //! \name Members
     286             :   //! \{
     287             : 
     288             :   uint32_t _bits;
     289             : 
     290             :   //! \}
     291             : 
     292             :   //! \name Overloaded Operators
     293             :   //!
     294             :   //! Overloaded operators make `OperandSignature` behave like regular integer.
     295             :   //!
     296             :   //! \{
     297             : 
     298             :   inline constexpr bool operator!() const noexcept { return _bits != 0; }
     299             :   inline constexpr explicit operator bool() const noexcept { return _bits != 0; }
     300             : 
     301             :   inline OperandSignature& operator|=(uint32_t x) noexcept { _bits |= x; return *this; }
     302       71131 :   inline OperandSignature& operator&=(uint32_t x) noexcept { _bits &= x; return *this; }
     303             :   inline OperandSignature& operator^=(uint32_t x) noexcept { _bits ^= x; return *this; }
     304             : 
     305             :   inline OperandSignature& operator|=(const OperandSignature& other) noexcept { return operator|=(other._bits); }
     306             :   inline OperandSignature& operator&=(const OperandSignature& other) noexcept { return operator&=(other._bits); }
     307             :   inline OperandSignature& operator^=(const OperandSignature& other) noexcept { return operator^=(other._bits); }
     308             : 
     309             :   inline constexpr OperandSignature operator~() const noexcept { return OperandSignature{~_bits}; }
     310             : 
     311             :   inline constexpr OperandSignature operator|(uint32_t x) const noexcept { return OperandSignature{_bits | x}; }
     312        1970 :   inline constexpr OperandSignature operator&(uint32_t x) const noexcept { return OperandSignature{_bits & x}; }
     313             :   inline constexpr OperandSignature operator^(uint32_t x) const noexcept { return OperandSignature{_bits ^ x}; }
     314             : 
     315      197089 :   inline constexpr OperandSignature operator|(const OperandSignature& other) const noexcept { return OperandSignature{_bits | other._bits}; }
     316             :   inline constexpr OperandSignature operator&(const OperandSignature& other) const noexcept { return OperandSignature{_bits & other._bits}; }
     317             :   inline constexpr OperandSignature operator^(const OperandSignature& other) const noexcept { return OperandSignature{_bits ^ other._bits}; }
     318             : 
     319        1970 :   inline constexpr bool operator==(uint32_t x) const noexcept { return _bits == x; }
     320      551203 :   inline constexpr bool operator!=(uint32_t x) const noexcept { return _bits != x; }
     321             : 
     322     1162590 :   inline constexpr bool operator==(const OperandSignature& other) const noexcept { return _bits == other._bits; }
     323             :   inline constexpr bool operator!=(const OperandSignature& other) const noexcept { return _bits != other._bits; }
     324             : 
     325             :   //! \}
     326             : 
     327             :   //! \name Accessors
     328             :   //! \{
     329             : 
     330     1176164 :   inline void reset() noexcept { _bits = 0; }
     331             : 
     332             :   inline constexpr uint32_t bits() const noexcept { return _bits; }
     333             :   inline void setBits(uint32_t bits) noexcept { _bits = bits; }
     334             : 
     335             :   template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
     336             :   inline constexpr bool hasField() const noexcept {
     337      355164 :     return (_bits & kFieldMask) != 0;
     338             :   }
     339             : 
     340             :   template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
     341             :   inline constexpr bool hasField(uint32_t value) const noexcept {
     342             :     return (_bits & kFieldMask) != value << kFieldShift;
     343             :   }
     344             : 
     345             :   template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
     346             :   inline constexpr uint32_t getField() const noexcept {
     347     7014257 :     return (_bits >> kFieldShift) & (kFieldMask >> kFieldShift);
     348             :   }
     349             : 
     350             :   template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
     351             :   inline void setField(uint32_t value) noexcept {
     352             :     ASMJIT_ASSERT((value & ~(kFieldMask >> kFieldShift)) == 0);
     353      119547 :     _bits = (_bits & ~kFieldMask) | (value << kFieldShift);
     354             :   }
     355             : 
     356      862649 :   inline constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature{_bits & mask}; }
     357             : 
     358             :   template<uint32_t kFieldMask>
     359             :   inline constexpr bool matchesSignature(const OperandSignature& signature) const noexcept {
     360             :     return (_bits & kFieldMask) == signature._bits;
     361             :   }
     362             : 
     363             :   template<uint32_t kFieldMask>
     364             :   inline constexpr bool matchesFields(uint32_t bits) const noexcept {
     365             :     return (_bits & kFieldMask) == bits;
     366             :   }
     367             : 
     368             :   template<uint32_t kFieldMask>
     369             :   inline constexpr bool matchesFields(const OperandSignature& fields) const noexcept {
     370             :     return (_bits & kFieldMask) == fields._bits;
     371             :   }
     372             : 
     373      389876 :   inline constexpr bool isValid() const noexcept { return _bits != 0; }
     374             : 
     375             :   inline constexpr OperandType opType() const noexcept { return (OperandType)getField<kOpTypeMask>(); }
     376             : 
     377      102060 :   inline constexpr RegType regType() const noexcept { return (RegType)getField<kRegTypeMask>(); }
     378      662273 :   inline constexpr RegGroup regGroup() const noexcept { return (RegGroup)getField<kRegGroupMask>(); }
     379             : 
     380           0 :   inline constexpr RegType memBaseType() const noexcept { return (RegType)getField<kMemBaseTypeMask>(); }
     381           0 :   inline constexpr RegType memIndexType() const noexcept { return (RegType)getField<kMemIndexTypeMask>(); }
     382             : 
     383             :   inline constexpr uint32_t predicate() const noexcept { return getField<kPredicateMask>(); }
     384             :   inline constexpr uint32_t size() const noexcept { return getField<kSizeMask>(); }
     385             : 
     386             :   inline void setOpType(OperandType opType) noexcept { setField<kOpTypeMask>(uint32_t(opType)); }
     387             :   inline void setRegType(RegType regType) noexcept { setField<kRegTypeMask>(uint32_t(regType)); }
     388             :   inline void setRegGroup(RegGroup regGroup) noexcept { setField<kRegGroupMask>(uint32_t(regGroup)); }
     389             : 
     390             :   inline void setMemBaseType(RegGroup baseType) noexcept { setField<kMemBaseTypeMask>(uint32_t(baseType)); }
     391             :   inline void setMemIndexType(RegGroup indexType) noexcept { setField<kMemIndexTypeMask>(uint32_t(indexType)); }
     392             : 
     393             :   inline void setPredicate(uint32_t predicate) noexcept { setField<kPredicateMask>(predicate); }
     394             :   inline void setSize(uint32_t size) noexcept { setField<kSizeMask>(size); }
     395             : 
     396             :   //! \}
     397             : 
     398             :   //! \name Static Constructors
     399             :   //! \{
     400             : 
     401             :   static inline constexpr OperandSignature fromBits(uint32_t bits) noexcept {
     402             :     return OperandSignature{bits};
     403             :   }
     404             : 
     405             :   template<uint32_t kFieldMask, typename T>
     406             :   static inline constexpr OperandSignature fromValue(const T& value) noexcept {
     407             :     return OperandSignature{uint32_t(value) << Support::ConstCTZ<kFieldMask>::value};
     408             :   }
     409             : 
     410             :   static inline constexpr OperandSignature fromOpType(OperandType opType) noexcept {
     411             :     return OperandSignature{uint32_t(opType) << kOpTypeShift};
     412             :   }
     413             : 
     414             :   static inline constexpr OperandSignature fromRegType(RegType regType) noexcept {
     415             :     return OperandSignature{uint32_t(regType) << kRegTypeShift};
     416             :   }
     417             : 
     418             :   static inline constexpr OperandSignature fromRegGroup(RegGroup regGroup) noexcept {
     419             :     return OperandSignature{uint32_t(regGroup) << kRegGroupShift};
     420             :   }
     421             : 
     422             :   static inline constexpr OperandSignature fromRegTypeAndGroup(RegType regType, RegGroup regGroup) noexcept {
     423             :     return fromRegType(regType) | fromRegGroup(regGroup);
     424             :   }
     425             : 
     426             :   static inline constexpr OperandSignature fromMemBaseType(RegType baseType) noexcept {
     427      197089 :     return OperandSignature{uint32_t(baseType) << kMemBaseTypeShift};
     428             :   }
     429             : 
     430             :   static inline constexpr OperandSignature fromMemIndexType(RegType indexType) noexcept {
     431             :     return OperandSignature{uint32_t(indexType) << kMemIndexTypeShift};
     432             :   }
     433             : 
     434             :   static inline constexpr OperandSignature fromPredicate(uint32_t predicate) noexcept {
     435             :     return OperandSignature{predicate << kPredicateShift};
     436             :   }
     437             : 
     438             :   static inline constexpr OperandSignature fromSize(uint32_t size) noexcept {
     439       54984 :     return OperandSignature{size << kSizeShift};
     440             :   }
     441             : 
     442             :   //! \}
     443             : };
     444             : 
     445             : //! Base class representing an operand in AsmJit (non-default constructed version).
     446             : //!
     447             : //! Contains no initialization code and can be used safely to define an array of operands that won't be initialized.
     448             : //! This is a \ref Operand base structure designed to be statically initialized, static const, or to be used by user
     449             : //! code to define an array of operands without having them default initialized at construction time.
     450             : //!
     451             : //! The key difference between \ref Operand and \ref Operand_ is:
     452             : //!
     453             : //! ```
     454             : //! Operand_ xArray[10];    // Not initialized, contains garbage.
     455             : //! Operand_ yArray[10] {}; // All operands initialized to none explicitly (zero initialized).
     456             : //! Operand  yArray[10];    // All operands initialized to none implicitly (zero initialized).
     457             : //! ```
     458             : struct Operand_ {
     459             :   //! \name Types
     460             :   //! \{
     461             : 
     462             :   typedef OperandSignature Signature;
     463             : 
     464             :   //! \}
     465             : 
     466             :   //! \name Constants
     467             :   //! \{
     468             : 
     469             :   // Indexes to `_data` array.
     470             :   enum DataIndex : uint32_t {
     471             :     kDataMemIndexId = 0,
     472             :     kDataMemOffsetLo = 1,
     473             : 
     474             :     kDataImmValueLo = ASMJIT_ARCH_LE ? 0 : 1,
     475             :     kDataImmValueHi = ASMJIT_ARCH_LE ? 1 : 0
     476             :   };
     477             : 
     478             :   //! Constants useful for VirtId <-> Index translation.
     479             :   enum VirtIdConstants : uint32_t {
     480             :     //! Minimum valid packed-id.
     481             :     kVirtIdMin = 256,
     482             :     //! Maximum valid packed-id, excludes Globals::kInvalidId.
     483             :     kVirtIdMax = Globals::kInvalidId - 1,
     484             :     //! Count of valid packed-ids.
     485             :     kVirtIdCount = uint32_t(kVirtIdMax - kVirtIdMin + 1)
     486             :   };
     487             : 
     488             :   //! \}
     489             : 
     490             :   //! \name Members
     491             :   //! \{
     492             : 
     493             :   //! Provides operand type and additional payload.
     494             :   Signature _signature;
     495             :   //! Either base id as used by memory operand or any id as used by others.
     496             :   uint32_t _baseId;
     497             : 
     498             :   //! Data specific to the operand type.
     499             :   //!
     500             :   //! The reason we don't use union is that we have `constexpr` constructors that construct operands and other
     501             :   //!`constexpr` functions that return whether another Operand or something else. These cannot generally work with
     502             :   //! unions so we also cannot use `union` if we want to be standard compliant.
     503             :   uint32_t _data[2];
     504             : 
     505             :   //! \}
     506             : 
     507             :   //! Tests whether the given `id` is a valid virtual register id. Since AsmJit supports both physical and virtual
     508             :   //! registers it must be able to distinguish between these two. The idea is that physical registers are always
     509             :   //! limited in size, so virtual identifiers start from `kVirtIdMin` and end at `kVirtIdMax`.
     510           0 :   static inline bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); }
     511             :   //! Converts a real-id into a packed-id that can be stored in Operand.
     512      273777 :   static inline uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; }
     513             :   //! Converts a packed-id back to real-id.
     514      273777 :   static inline uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; }
     515             : 
     516             :   //! \name Construction & Destruction
     517             :   //! \{
     518             : 
     519             :   //! \cond INTERNAL
     520             :   //! Initializes a `BaseReg` operand from `signature` and register `id`.
     521             :   inline void _initReg(const Signature& signature, uint32_t id) noexcept {
     522      273777 :     _signature = signature;
     523      273777 :     _baseId = id;
     524      273777 :     _data[0] = 0;
     525      273777 :     _data[1] = 0;
     526             :   }
     527             :   //! \endcond
     528             : 
     529             :   //! Initializes the operand from `other` operand (used by operator overloads).
     530     1213866 :   inline void copyFrom(const Operand_& other) noexcept { memcpy(this, &other, sizeof(Operand_)); }
     531             : 
     532             :   //! Resets the `Operand` to none.
     533             :   //!
     534             :   //! None operand is defined the following way:
     535             :   //!   - Its signature is zero (OperandType::kNone, and the rest zero as well).
     536             :   //!   - Its id is `0`.
     537             :   //!   - The reserved8_4 field is set to `0`.
     538             :   //!   - The reserved12_4 field is set to zero.
     539             :   //!
     540             :   //! In other words, reset operands have all members set to zero. Reset operand must match the Operand state
     541             :   //! right after its construction. Alternatively, if you have an array of operands, you can simply use `memset()`.
     542             :   //!
     543             :   //! ```
     544             :   //! using namespace asmjit;
     545             :   //!
     546             :   //! Operand a;
     547             :   //! Operand b;
     548             :   //! assert(a == b);
     549             :   //!
     550             :   //! b = x86::eax;
     551             :   //! assert(a != b);
     552             :   //!
     553             :   //! b.reset();
     554             :   //! assert(a == b);
     555             :   //!
     556             :   //! memset(&b, 0, sizeof(Operand));
     557             :   //! assert(a == b);
     558             :   //! ```
     559             :   inline void reset() noexcept {
     560             :     _signature.reset();
     561     1176164 :     _baseId = 0;
     562     1176164 :     _data[0] = 0;
     563     1176164 :     _data[1] = 0;
     564             :   }
     565             : 
     566             :   //! \}
     567             : 
     568             :   //! \name Overloaded Operators
     569             :   //! \{
     570             : 
     571             :   //! Tests whether this operand is the same as `other`.
     572       30807 :   inline constexpr bool operator==(const Operand_& other) const noexcept { return  equals(other); }
     573             :   //! Tests whether this operand is not the same as `other`.
     574             :   inline constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); }
     575             : 
     576             :   //! \}
     577             : 
     578             :   //! \name Cast
     579             :   //! \{
     580             : 
     581             :   //! Casts this operand to `T` type.
     582             :   template<typename T>
     583             :   inline T& as() noexcept { return static_cast<T&>(*this); }
     584             : 
     585             :   //! Casts this operand to `T` type (const).
     586             :   template<typename T>
     587             :   inline const T& as() const noexcept { return static_cast<const T&>(*this); }
     588             : 
     589             :   //! \}
     590             : 
     591             :   //! \name Accessors
     592             :   //! \{
     593             : 
     594             :   //! Tests whether the operand's signature matches the signature of the `other` operand.
     595             :   inline constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other._signature; }
     596             :   //! Tests whether the operand's signature matches the given signature `sign`.
     597             :   inline constexpr bool hasSignature(const Signature& other) const noexcept { return _signature == other; }
     598             : 
     599             :   //! Returns operand signature as unsigned 32-bit integer.
     600             :   //!
     601             :   //! Signature is first 4 bytes of the operand data. It's used mostly for operand checking as it's
     602             :   //! much faster to check packed 4 bytes at once than having to check these bytes individually.
     603           0 :   inline constexpr Signature signature() const noexcept { return _signature; }
     604             : 
     605             :   //! Sets the operand signature, see `signature()`.
     606             :   //!
     607             :   //! \note Improper use of `setSignature()` can lead to hard-to-debug errors.
     608           0 :   inline void setSignature(const Signature& signature) noexcept { _signature = signature; }
     609             : 
     610             :   //! Returns the type of the operand, see `OpType`.
     611             :   inline constexpr OperandType opType() const noexcept { return _signature.opType(); }
     612             :   //! Tests whether the operand is none (`OperandType::kNone`).
     613             :   inline constexpr bool isNone() const noexcept { return _signature == Signature::fromBits(0); }
     614             :   //! Tests whether the operand is a register (`OperandType::kReg`).
     615             :   inline constexpr bool isReg() const noexcept { return opType() == OperandType::kReg; }
     616             :   //! Tests whether the operand is a memory location (`OperandType::kMem`).
     617           0 :   inline constexpr bool isMem() const noexcept { return opType() == OperandType::kMem; }
     618             :   //! Tests whether the operand is an immediate (`OperandType::kImm`).
     619             :   inline constexpr bool isImm() const noexcept { return opType() == OperandType::kImm; }
     620             :   //! Tests whether the operand is a label (`OperandType::kLabel`).
     621             :   inline constexpr bool isLabel() const noexcept { return opType() == OperandType::kLabel; }
     622             : 
     623             :   //! Tests whether the operand is a physical register.
     624             :   inline constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; }
     625             :   //! Tests whether the operand is a virtual register.
     626             :   inline constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; }
     627             : 
     628             :   //! Tests whether the operand specifies a size (i.e. the size is not zero).
     629             :   inline constexpr bool hasSize() const noexcept { return _signature.hasField<Signature::kSizeMask>(); }
     630             :   //! Tests whether the size of the operand matches `size`.
     631             :   inline constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; }
     632             : 
     633             :   //! Returns the size of the operand in bytes.
     634             :   //!
     635             :   //! The value returned depends on the operand type:
     636             :   //!   * None  - Should always return zero size.
     637             :   //!   * Reg   - Should always return the size of the register. If the register size depends on architecture
     638             :   //!             (like `x86::CReg` and `x86::DReg`) the size returned should be the greatest possible (so it
     639             :   //!             should return 64-bit size in such case).
     640             :   //!   * Mem   - Size is optional and will be in most cases zero.
     641             :   //!   * Imm   - Should always return zero size.
     642             :   //!   * Label - Should always return zero size.
     643             :   inline constexpr uint32_t size() const noexcept { return _signature.getField<Signature::kSizeMask>(); }
     644             : 
     645             :   //! Returns the operand id.
     646             :   //!
     647             :   //! The value returned should be interpreted accordingly to the operand type:
     648             :   //!   * None  - Should be `0`.
     649             :   //!   * Reg   - Physical or virtual register id.
     650             :   //!   * Mem   - Multiple meanings - BASE address (register or label id), or high value of a 64-bit absolute address.
     651             :   //!   * Imm   - Should be `0`.
     652             :   //!   * Label - Label id if it was created by using `newLabel()` or `Globals::kInvalidId` if the label is invalid or
     653             :   //!             not initialized.
     654     1208200 :   inline constexpr uint32_t id() const noexcept { return _baseId; }
     655             : 
     656             :   //! Tests whether the operand is 100% equal to `other` operand.
     657             :   //!
     658             :   //! \note This basically performs a binary comparison, if aby bit is
     659             :   //! different the operands are not equal.
     660       30807 :   inline constexpr bool equals(const Operand_& other) const noexcept {
     661             :     return (_signature == other._signature) &
     662       30807 :            (_baseId    == other._baseId   ) &
     663       30807 :            (_data[0]   == other._data[0]  ) &
     664       30807 :            (_data[1]   == other._data[1]  ) ;
     665             :   }
     666             : 
     667             :   //! Tests whether the operand is a register matching the given register `type`.
     668             :   inline constexpr bool isReg(RegType type) const noexcept {
     669             :     return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegType(type));
     670             :   }
     671             : 
     672             :   //! Tests whether the operand is register and of register `type` and `id`.
     673             :   inline constexpr bool isReg(RegType type, uint32_t id) const noexcept {
     674             :     return isReg(type) && this->id() == id;
     675             :   }
     676             : 
     677             :   //! Tests whether the operand is a register or memory.
     678             :   inline constexpr bool isRegOrMem() const noexcept {
     679             :     return Support::isBetween<uint32_t>(uint32_t(opType()), uint32_t(OperandType::kReg), uint32_t(OperandType::kMem));
     680             :   }
     681             : 
     682             :   //! \}
     683             : };
     684             : 
     685             : //! Base class representing an operand in AsmJit (default constructed version).
     686             : class Operand : public Operand_ {
     687             : public:
     688             :   //! \name Construction & Destruction
     689             :   //! \{
     690             : 
     691             :   //! Creates `kOpNone` operand having all members initialized to zero.
     692             :   inline constexpr Operand() noexcept
     693       54984 :     : Operand_{ Signature::fromOpType(OperandType::kNone), 0u, { 0u, 0u }} {}
     694             : 
     695             :   //! Creates a cloned `other` operand.
     696             :   inline constexpr Operand(const Operand& other) noexcept = default;
     697             : 
     698             :   //! Creates a cloned `other` operand.
     699             :   inline constexpr explicit Operand(const Operand_& other)
     700       50221 :     : Operand_(other) {}
     701             : 
     702             :   //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values.
     703             :   inline constexpr Operand(Globals::Init_, const Signature& u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept
     704      464297 :     : Operand_{ u0, u1, { u2, u3 }} {}
     705             : 
     706             :   //! Creates an uninitialized operand (dangerous).
     707             :   inline explicit Operand(Globals::NoInit_) noexcept {}
     708             : 
     709             :   //! \}
     710             : 
     711             :   //! \name Overloaded Operators
     712             :   //! \{
     713             : 
     714             :   inline Operand& operator=(const Operand& other) noexcept = default;
     715          94 :   inline Operand& operator=(const Operand_& other) noexcept { return operator=(static_cast<const Operand&>(other)); }
     716             : 
     717             :   //! \}
     718             : 
     719             :   //! \name Clone
     720             :   //! \{
     721             : 
     722             :   //! Clones this operand and returns its copy.
     723             :   inline constexpr Operand clone() const noexcept { return Operand(*this); }
     724             : 
     725             :   //! \}
     726             : };
     727             : 
     728             : static_assert(sizeof(Operand) == 16, "asmjit::Operand must be exactly 16 bytes long");
     729             : 
     730             : //! Label (jump target or data location).
     731             : //!
     732             : //! Label represents a location in code typically used as a jump target, but may be also a reference to some data or
     733             : //! a static variable. Label has to be explicitly created by BaseEmitter.
     734             : //!
     735             : //! Example of using labels:
     736             : //!
     737             : //! ```
     738             : //! // Create some emitter (for example x86::Assembler).
     739             : //! x86::Assembler a;
     740             : //!
     741             : //! // Create Label instance.
     742             : //! Label L1 = a.newLabel();
     743             : //!
     744             : //! // ... your code ...
     745             : //!
     746             : //! // Using label.
     747             : //! a.jump(L1);
     748             : //!
     749             : //! // ... your code ...
     750             : //!
     751             : //! // Bind label to the current position, see `BaseEmitter::bind()`.
     752             : //! a.bind(L1);
     753             : //! ```
     754             : class Label : public Operand {
     755             : public:
     756             :   //! \name Construction & Destruction
     757             :   //! \{
     758             : 
     759             :   //! Creates a label operand without ID (you must set the ID to make it valid).
     760             :   inline constexpr Label() noexcept
     761             :     : Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), Globals::kInvalidId, 0, 0) {}
     762             : 
     763             :   //! Creates a cloned label operand of `other`.
     764             :   inline constexpr Label(const Label& other) noexcept
     765           0 :     : Operand(other) {}
     766             : 
     767             :   //! Creates a label operand of the given `id`.
     768             :   inline constexpr explicit Label(uint32_t id) noexcept
     769             :     : Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), id, 0, 0) {}
     770             : 
     771             :   inline explicit Label(Globals::NoInit_) noexcept
     772             :     : Operand(Globals::NoInit) {}
     773             : 
     774             :   //! Resets the label, will reset all properties and set its ID to `Globals::kInvalidId`.
     775             :   inline void reset() noexcept {
     776             :     _signature = Signature::fromOpType(OperandType::kLabel);
     777             :     _baseId = Globals::kInvalidId;
     778             :     _data[0] = 0;
     779             :     _data[1] = 0;
     780             :   }
     781             : 
     782             :   //! \}
     783             : 
     784             :   //! \name Overloaded Operators
     785             :   //! \{
     786             : 
     787             :   inline Label& operator=(const Label& other) noexcept = default;
     788             : 
     789             :   //! \}
     790             : 
     791             :   //! \name Accessors
     792             :   //! \{
     793             : 
     794             :   //! Tests whether the label was created by CodeHolder and/or an attached emitter.
     795             :   inline constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; }
     796             :   //! Sets the label `id`.
     797             :   inline void setId(uint32_t id) noexcept { _baseId = id; }
     798             : 
     799             :   //! \}
     800             : };
     801             : 
     802             : //! \cond INTERNAL
     803             : //! Default register traits.
     804             : struct BaseRegTraits {
     805             :   enum : uint32_t {
     806             :     //! \ref TypeId representing this register type, could be \ref TypeId::kVoid if such type doesn't exist.
     807             :     kTypeId = uint32_t(TypeId::kVoid),
     808             :     //! RegType is not valid by default.
     809             :     kValid = 0,
     810             :     //! Count of registers (0 if none).
     811             :     kCount = 0,
     812             : 
     813             :     //! Zero type by default (defeaults to None).
     814             :     kType = uint32_t(RegType::kNone),
     815             :     //! Zero group by default (defaults to GP).
     816             :     kGroup = uint32_t(RegGroup::kGp),
     817             :     //! No size by default.
     818             :     kSize = 0,
     819             : 
     820             :     //! Empty signature by default (not even having operand type set to register).
     821             :     kSignature = 0
     822             :   };
     823             : };
     824             : //! \endcond
     825             : 
     826             : //! Physical or virtual register operand.
     827             : class BaseReg : public Operand {
     828             : public:
     829             :   //! \name Constants
     830             :   //! \{
     831             : 
     832             :   enum : uint32_t {
     833             :     //! None or any register (mostly internal).
     834             :     kIdBad = 0xFFu,
     835             : 
     836             :     kBaseSignatureMask =
     837             :       Signature::kOpTypeMask   |
     838             :       Signature::kRegTypeMask  |
     839             :       Signature::kRegGroupMask |
     840             :       Signature::kSizeMask,
     841             : 
     842             :     kTypeNone = uint32_t(RegType::kNone),
     843             :     kSignature = Signature::fromOpType(OperandType::kReg).bits()
     844             :   };
     845             : 
     846             :   //! \}
     847             : 
     848             :   //! \name Construction & Destruction
     849             :   //! \{
     850             : 
     851             :   //! Creates a dummy register operand.
     852             :   inline constexpr BaseReg() noexcept
     853             :     : Operand(Globals::Init, Signature::fromOpType(OperandType::kReg), kIdBad, 0, 0) {}
     854             : 
     855             :   //! Creates a new register operand which is the same as `other` .
     856             :   inline constexpr BaseReg(const BaseReg& other) noexcept
     857       54984 :     : Operand(other) {}
     858             : 
     859             :   //! Creates a new register operand compatible with `other`, but with a different `id`.
     860             :   inline constexpr BaseReg(const BaseReg& other, uint32_t id) noexcept
     861             :     : Operand(Globals::Init, other._signature, id, 0, 0) {}
     862             : 
     863             :   //! Creates a register initialized to the given `signature` and `id`.
     864             :   inline constexpr BaseReg(const Signature& signature, uint32_t id) noexcept
     865             :     : Operand(Globals::Init, signature, id, 0, 0) {}
     866             : 
     867             :   inline explicit BaseReg(Globals::NoInit_) noexcept
     868             :     : Operand(Globals::NoInit) {}
     869             : 
     870             :   //! \}
     871             : 
     872             :   //! \name Overloaded Operators
     873             :   //! \{
     874             : 
     875             :   inline BaseReg& operator=(const BaseReg& other) noexcept = default;
     876             : 
     877             :   //! \}
     878             : 
     879             :   //! \name Accessors
     880             :   //! \{
     881             : 
     882             :   //! Returns base signature of the register associated with each register type.
     883             :   //!
     884             :   //! Base signature only contains the operand type, register type, register group, and register size. It doesn't
     885             :   //! contain element type, predicate, or other architecture-specific data. Base signature is a signature that is
     886             :   //! provided by architecture-specific `RegTraits`, like \ref x86::RegTraits.
     887             :   inline constexpr OperandSignature baseSignature() const noexcept { return _signature & kBaseSignatureMask; }
     888             : 
     889             :   //! Tests whether the operand's base signature matches the given signature `sign`.
     890             :   inline constexpr bool hasBaseSignature(uint32_t signature) const noexcept { return baseSignature() == signature; }
     891             :   //! Tests whether the operand's base signature matches the given signature `sign`.
     892             :   inline constexpr bool hasBaseSignature(const OperandSignature& signature) const noexcept { return baseSignature() == signature; }
     893             :   //! Tests whether the operand's base signature matches the base signature of the `other` operand.
     894             :   inline constexpr bool hasBaseSignature(const BaseReg& other) const noexcept { return baseSignature() == other.baseSignature(); }
     895             : 
     896             :   //! Tests whether this register is the same as `other`.
     897             :   //!
     898             :   //! This is just an optimization. Registers by default only use the first 8 bytes of Operand data, so this method
     899             :   //! takes advantage of this knowledge and only compares these 8 bytes. If both operands were created correctly
     900             :   //! both \ref equals() and \ref isSame() should give the same answer, however, if any of these two contains garbage
     901             :   //! or other metadata in the upper 8 bytes then \ref isSame() may return `true` in cases in which \ref equals()
     902             :   //! returns false.
     903             :   inline constexpr bool isSame(const BaseReg& other) const noexcept {
     904             :     return (_signature == other._signature) & (_baseId == other._baseId);
     905             :   }
     906             : 
     907             :   //! Tests whether the register is valid (either virtual or physical).
     908             :   inline constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); }
     909             : 
     910             :   //! Tests whether this is a physical register.
     911             :   inline constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; }
     912             :   //! Tests whether this is a virtual register.
     913           0 :   inline constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; }
     914             : 
     915             :   //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience.
     916             :   inline constexpr bool isType(RegType type) const noexcept { return _signature.subset(Signature::kRegTypeMask) == Signature::fromRegType(type); }
     917             :   //! Tests whether the register group matches `group`.
     918             :   inline constexpr bool isGroup(RegGroup group) const noexcept { return _signature.subset(Signature::kRegGroupMask) == Signature::fromRegGroup(group); }
     919             : 
     920             :   //! Tests whether the register is a general purpose register (any size).
     921             :   inline constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); }
     922             :   //! Tests whether the register is a vector register.
     923             :   inline constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); }
     924             : 
     925             :   using Operand_::isReg;
     926             : 
     927             :   //! Same as `isType()`, provided for convenience.
     928             :   inline constexpr bool isReg(RegType rType) const noexcept { return isType(rType); }
     929             :   //! Tests whether the register type matches `type` and register id matches `id`.
     930             :   inline constexpr bool isReg(RegType rType, uint32_t id) const noexcept { return isType(rType) && this->id() == id; }
     931             : 
     932             :   //! Returns the register type.
     933             :   inline constexpr RegType type() const noexcept { return _signature.regType(); }
     934             :   //! Returns the register group.
     935             :   inline constexpr RegGroup group() const noexcept { return _signature.regGroup(); }
     936             : 
     937             :   //! Returns operation predicate of the register (ARM/AArch64).
     938             :   //!
     939             :   //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp
     940             :   //! of the register.
     941             :   inline constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); }
     942             : 
     943             :   //! Sets operation predicate of the register to `predicate` (ARM/AArch64).
     944             :   //!
     945             :   //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp
     946             :   //! of the register.
     947             :   inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); }
     948             : 
     949             :   //! Resets shift operation type of the register to the default value (ARM/AArch64).
     950             :   inline void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); }
     951             : 
     952             :   //! Clones the register operand.
     953             :   inline constexpr BaseReg clone() const noexcept { return BaseReg(*this); }
     954             : 
     955             :   //! Casts this register to `RegT` by also changing its signature.
     956             :   //!
     957             :   //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors.
     958             :   template<typename RegT>
     959             :   inline constexpr RegT cloneAs() const noexcept { return RegT(Signature(RegT::kSignature), id()); }
     960             : 
     961             :   //! Casts this register to `other` by also changing its signature.
     962             :   //!
     963             :   //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors.
     964             :   template<typename RegT>
     965             :   inline constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(other.signature(), id()); }
     966             : 
     967             :   //! Sets the register id to `id`.
     968           0 :   inline void setId(uint32_t id) noexcept { _baseId = id; }
     969             : 
     970             :   //! Sets a 32-bit operand signature based on traits of `RegT`.
     971             :   template<typename RegT>
     972             :   inline void setSignatureT() noexcept { _signature = RegT::kSignature; }
     973             : 
     974             :   //! Sets the register `signature` and `id`.
     975             :   inline void setSignatureAndId(const OperandSignature& signature, uint32_t id) noexcept {
     976           0 :     _signature = signature;
     977           0 :     _baseId = id;
     978             :   }
     979             : 
     980             :   //! \}
     981             : 
     982             :   //! \name Static Functions
     983             :   //! \{
     984             : 
     985             :   //! Tests whether the `op` operand is a general purpose register.
     986             :   static inline bool isGp(const Operand_& op) noexcept {
     987             :     // Check operand type and register group. Not interested in register type and size.
     988             :     return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kGp));
     989             :   }
     990             : 
     991             :   //! Tests whether the `op` operand is a vector register.
     992             :   static inline bool isVec(const Operand_& op) noexcept {
     993             :     // Check operand type and register group. Not interested in register type and size.
     994             :     return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kVec));
     995             :   }
     996             : 
     997             :   //! Tests whether the `op` is a general purpose register of the given `id`.
     998           0 :   static inline bool isGp(const Operand_& op, uint32_t id) noexcept { return isGp(op) & (op.id() == id); }
     999             :   //! Tests whether the `op` is a vector register of the given `id`.
    1000             :   static inline bool isVec(const Operand_& op, uint32_t id) noexcept { return isVec(op) & (op.id() == id); }
    1001             : 
    1002             :   //! \}
    1003             : };
    1004             : 
    1005             : //! RegOnly is 8-byte version of `BaseReg` that allows to store either register or nothing.
    1006             : //!
    1007             : //! It's designed to decrease the space consumed by an extra "operand" in \ref BaseEmitter and \ref InstNode.
    1008             : struct RegOnly {
    1009             :   //! \name Types
    1010             :   //! \{
    1011             : 
    1012             :   typedef OperandSignature Signature;
    1013             : 
    1014             :   //! \}
    1015             : 
    1016             :   //! Operand signature - only \ref OperandType::kNone and \ref OperandType::kReg are supported.
    1017             :   Signature _signature;
    1018             :   //! Physical or virtual register id.
    1019             :   uint32_t _id;
    1020             : 
    1021             :   //! \name Construction & Destruction
    1022             :   //! \{
    1023             : 
    1024             :   //! Initializes the `RegOnly` instance to hold register `signature` and `id`.
    1025             :   inline void init(const OperandSignature& signature, uint32_t id) noexcept {
    1026     1558397 :     _signature = signature;
    1027      784018 :     _id = id;
    1028             :   }
    1029             : 
    1030             :   inline void init(const BaseReg& reg) noexcept { init(reg.signature(), reg.id()); }
    1031             :   inline void init(const RegOnly& reg) noexcept { init(reg.signature(), reg.id()); }
    1032             : 
    1033             :   //! Resets the `RegOnly` members to zeros (none).
    1034             :   inline void reset() noexcept { init(Signature::fromBits(0), 0); }
    1035             : 
    1036             :   //! \}
    1037             : 
    1038             :   //! \name Accessors
    1039             :   //! \{
    1040             : 
    1041             :   //! Tests whether this ExtraReg is none (same as calling `Operand_::isNone()`).
    1042             :   inline constexpr bool isNone() const noexcept { return _signature == 0; }
    1043             :   //! Tests whether the register is valid (either virtual or physical).
    1044             :   inline constexpr bool isReg() const noexcept { return _signature != 0; }
    1045             : 
    1046             :   //! Tests whether this is a physical register.
    1047           0 :   inline constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; }
    1048             :   //! Tests whether this is a virtual register (used by `BaseCompiler`).
    1049             :   inline constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; }
    1050             : 
    1051             :   //! Returns the register signature or 0 if no register is assigned.
    1052      774379 :   inline constexpr OperandSignature signature() const noexcept { return _signature; }
    1053             :   //! Returns the register id.
    1054             :   //!
    1055             :   //! \note Always check whether the register is assigned before using the returned identifier as
    1056             :   //! non-assigned `RegOnly` instance would return zero id, which is still a valid register id.
    1057     1031021 :   inline constexpr uint32_t id() const noexcept { return _id; }
    1058             : 
    1059             :   //! Sets the register id.
    1060             :   inline void setId(uint32_t id) noexcept { _id = id; }
    1061             : 
    1062             :   //! Returns the register type.
    1063             :   inline constexpr RegType type() const noexcept { return _signature.regType(); }
    1064             :   //! Returns the register group.
    1065             :   inline constexpr RegGroup group() const noexcept { return _signature.regGroup(); }
    1066             : 
    1067             :   //! \}
    1068             : 
    1069             :   //! \name Utilities
    1070             :   //! \{
    1071             : 
    1072             :   //! Converts this ExtraReg to a real `RegT` operand.
    1073             :   template<typename RegT>
    1074           0 :   inline constexpr RegT toReg() const noexcept { return RegT(_signature, _id); }
    1075             : 
    1076             :   //! \}
    1077             : };
    1078             : 
    1079             : //! \cond INTERNAL
    1080             : //! Adds a template specialization for `REG_TYPE` into the local `RegTraits`.
    1081             : #define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID) \
    1082             : template<>                                                                   \
    1083             : struct RegTraits<REG_TYPE> {                                                 \
    1084             :   typedef REG RegT;                                                          \
    1085             :                                                                              \
    1086             :   enum : uint32_t {                                                          \
    1087             :     kValid = uint32_t(true),                                                 \
    1088             :     kCount = uint32_t(COUNT),                                                \
    1089             :     kType = uint32_t(REG_TYPE),                                              \
    1090             :     kGroup = uint32_t(GROUP),                                                \
    1091             :     kSize = uint32_t(SIZE),                                                  \
    1092             :     kTypeId = uint32_t(TYPE_ID),                                             \
    1093             :                                                                              \
    1094             :     kSignature = (OperandSignature::fromOpType(OperandType::kReg) |          \
    1095             :                   OperandSignature::fromRegType(REG_TYPE)         |          \
    1096             :                   OperandSignature::fromRegGroup(GROUP)           |          \
    1097             :                   OperandSignature::fromSize(kSize)).bits(),                 \
    1098             :   };                                                                         \
    1099             : }
    1100             : 
    1101             : //! Adds constructors and member functions to a class that implements abstract register. Abstract register is register
    1102             : //! that doesn't have type or signature yet, it's a base class like `x86::Reg` or `arm::Reg`.
    1103             : #define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE)                                \
    1104             : public:                                                                      \
    1105             :   /*! Default constructor that only setups basics. */                        \
    1106             :   inline constexpr REG() noexcept                                            \
    1107             :     : BASE(Signature{kSignature}, kIdBad) {}                                 \
    1108             :                                                                              \
    1109             :   /*! Makes a copy of the `other` register operand. */                       \
    1110             :   inline constexpr REG(const REG& other) noexcept                            \
    1111             :     : BASE(other) {}                                                         \
    1112             :                                                                              \
    1113             :   /*! Makes a copy of the `other` register having id set to `id` */          \
    1114             :   inline constexpr REG(const BaseReg& other, uint32_t id) noexcept           \
    1115             :     : BASE(other, id) {}                                                     \
    1116             :                                                                              \
    1117             :   /*! Creates a register based on `signature` and `id`. */                   \
    1118             :   inline constexpr REG(const OperandSignature& sgn, uint32_t id) noexcept    \
    1119             :     : BASE(sgn, id) {}                                                       \
    1120             :                                                                              \
    1121             :   /*! Creates a completely uninitialized REG register operand (garbage). */  \
    1122             :   inline explicit REG(Globals::NoInit_) noexcept                             \
    1123             :     : BASE(Globals::NoInit) {}                                               \
    1124             :                                                                              \
    1125             :   /*! Creates a new register from register type and id. */                   \
    1126             :   static inline REG fromTypeAndId(RegType type, uint32_t id) noexcept {      \
    1127             :     return REG(signatureOf(type), id);                                       \
    1128             :   }                                                                          \
    1129             :                                                                              \
    1130             :   /*! Clones the register operand. */                                        \
    1131             :   inline constexpr REG clone() const noexcept { return REG(*this); }         \
    1132             :                                                                              \
    1133             :   inline REG& operator=(const REG& other) noexcept = default;
    1134             : 
    1135             : //! Adds constructors and member functions to a class that implements final register. Final registers MUST HAVE a valid
    1136             : //! signature.
    1137             : #define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS)                           \
    1138             : public:                                                                      \
    1139             :   enum : uint32_t {                                                          \
    1140             :     kThisType  = TRAITS::kType,                                              \
    1141             :     kThisGroup = TRAITS::kGroup,                                             \
    1142             :     kThisSize  = TRAITS::kSize,                                              \
    1143             :     kSignature = TRAITS::kSignature                                          \
    1144             :   };                                                                         \
    1145             :                                                                              \
    1146             :   ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE)                                      \
    1147             :                                                                              \
    1148             :   /*! Creates a register operand having its id set to `id`. */               \
    1149             :   inline constexpr explicit REG(uint32_t id) noexcept                        \
    1150             :     : BASE(Signature{kSignature}, id) {}
    1151             : //! \endcond
    1152             : 
    1153             : //! Base class for all memory operands.
    1154             : //!
    1155             : //! The data is split into the following parts:
    1156             : //!
    1157             : //!   - BASE - Base register or label - requires 36 bits total. 4 bits are used to encode the type of the BASE operand
    1158             : //!     (label vs. register type) and the remaining 32 bits define the BASE id, which can be a physical or virtual
    1159             : //!     register index. If BASE type is zero, which is never used as a register type and label doesn't use it as well
    1160             : //!     then BASE field contains a high DWORD of a possible 64-bit absolute address, which is possible on X64.
    1161             : //!
    1162             : //!   - INDEX - Index register (or theoretically Label, which doesn't make sense). Encoding is similar to BASE - it
    1163             : //!     also requires 36 bits and splits the encoding to INDEX type (4 bits defining the register type) and 32-bit id.
    1164             : //!
    1165             : //!   - OFFSET - A relative offset of the address. Basically if BASE is specified the relative displacement adjusts
    1166             : //!     BASE and an optional INDEX. if BASE is not specified then the OFFSET should be considered as ABSOLUTE address
    1167             : //!     (at least on X86). In that case its low 32 bits are stored in DISPLACEMENT field and the remaining high 32
    1168             : //!     bits are stored in BASE.
    1169             : //!
    1170             : //!   - OTHER - There is rest 8 bits that can be used for whatever purpose. For example \ref x86::Mem operand uses
    1171             : //!     these bits to store segment override prefix and index shift (or scale).
    1172             : class BaseMem : public Operand {
    1173             : public:
    1174             :   //! \name Construction & Destruction
    1175             :   //! \{
    1176             : 
    1177             :   //! Creates a default `BaseMem` operand, that points to [0].
    1178             :   inline constexpr BaseMem() noexcept
    1179             :       : Operand(Globals::Init, Signature::fromOpType(OperandType::kMem), 0, 0, 0) {}
    1180             : 
    1181             :   //! Creates a `BaseMem` operand that is a clone of `other`.
    1182             :   inline constexpr BaseMem(const BaseMem& other) noexcept
    1183           0 :     : Operand(other) {}
    1184             : 
    1185             :   //! Creates a `BaseMem` operand from `baseReg` and `offset`.
    1186             :   //!
    1187             :   //! \note This is an architecture independent constructor that can be used to create an architecture
    1188             :   //! independent memory operand to be used in portable code that can handle multiple architectures.
    1189           0 :   inline constexpr explicit BaseMem(const BaseReg& baseReg, int32_t offset = 0) noexcept
    1190             :     : Operand(Globals::Init,
    1191             :               Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(baseReg.type()),
    1192             :               baseReg.id(),
    1193             :               0,
    1194           0 :               uint32_t(offset)) {}
    1195             : 
    1196             :   //! \cond INTERNAL
    1197             :   //! Creates a `BaseMem` operand from 4 integers as used by `Operand_` struct.
    1198             :   inline constexpr BaseMem(const OperandSignature& u0, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept
    1199       89069 :     : Operand(Globals::Init, u0, baseId, indexId, uint32_t(offset)) {}
    1200             :   //! \endcond
    1201             : 
    1202             :   //! Creates a completely uninitialized `BaseMem` operand.
    1203             :   inline explicit BaseMem(Globals::NoInit_) noexcept
    1204             :     : Operand(Globals::NoInit) {}
    1205             : 
    1206             :   //! Resets the memory operand - after the reset the memory points to [0].
    1207             :   inline void reset() noexcept {
    1208           0 :     _signature = Signature::fromOpType(OperandType::kMem);
    1209           0 :     _baseId = 0;
    1210           0 :     _data[0] = 0;
    1211           0 :     _data[1] = 0;
    1212             :   }
    1213             : 
    1214             :   //! \}
    1215             : 
    1216             :   //! \name Overloaded Operators
    1217             :   //! \{
    1218             : 
    1219           0 :   inline BaseMem& operator=(const BaseMem& other) noexcept { copyFrom(other); return *this; }
    1220             : 
    1221             :   //! \}
    1222             : 
    1223             :   //! \name Accessors
    1224             :   //! \{
    1225             : 
    1226             :   //! Clones the memory operand.
    1227             :   inline constexpr BaseMem clone() const noexcept { return BaseMem(*this); }
    1228             : 
    1229             :   //! Creates a new copy of this memory operand adjusted by `off`.
    1230             :   inline BaseMem cloneAdjusted(int64_t off) const noexcept {
    1231             :     BaseMem result(*this);
    1232           0 :     result.addOffset(off);
    1233             :     return result;
    1234             :   }
    1235             : 
    1236             :   //! Tests whether this memory operand is a register home (only used by \ref asmjit_compiler)
    1237             :   inline constexpr bool isRegHome() const noexcept { return _signature.hasField<Signature::kMemRegHomeFlag>(); }
    1238             :   //! Mark this memory operand as register home (only used by \ref asmjit_compiler).
    1239             :   inline void setRegHome() noexcept { _signature |= Signature::kMemRegHomeFlag; }
    1240             :   //! Marks this operand to not be a register home (only used by \ref asmjit_compiler).
    1241             :   inline void clearRegHome() noexcept { _signature &= ~Signature::kMemRegHomeFlag; }
    1242             : 
    1243             :   //! Tests whether the memory operand has a BASE register or label specified.
    1244             :   inline constexpr bool hasBase() const noexcept {
    1245             :     return (_signature & Signature::kMemBaseTypeMask) != 0;
    1246             :   }
    1247             : 
    1248             :   //! Tests whether the memory operand has an INDEX register specified.
    1249             :   inline constexpr bool hasIndex() const noexcept {
    1250             :     return (_signature & Signature::kMemIndexTypeMask) != 0;
    1251             :   }
    1252             : 
    1253             :   //! Tests whether the memory operand has BASE or INDEX register.
    1254             :   inline constexpr bool hasBaseOrIndex() const noexcept {
    1255             :     return (_signature & Signature::kMemBaseIndexMask) != 0;
    1256             :   }
    1257             : 
    1258             :   //! Tests whether the memory operand has BASE and INDEX register.
    1259             :   inline constexpr bool hasBaseAndIndex() const noexcept {
    1260             :     return (_signature & Signature::kMemBaseTypeMask) != 0 && (_signature & Signature::kMemIndexTypeMask) != 0;
    1261             :   }
    1262             : 
    1263             :   //! Tests whether the BASE operand is a label.
    1264             :   inline constexpr bool hasBaseLabel() const noexcept {
    1265             :     return _signature.subset(Signature::kMemBaseTypeMask) == Signature::fromMemBaseType(RegType::kLabelTag);
    1266             :   }
    1267             : 
    1268             :   //! Tests whether the BASE operand is a register (registers start after `RegType::kLabelTag`).
    1269             :   inline constexpr bool hasBaseReg() const noexcept {
    1270             :     return _signature.subset(Signature::kMemBaseTypeMask).bits() > Signature::fromMemBaseType(RegType::kLabelTag).bits();
    1271             :   }
    1272             : 
    1273             :   //! Tests whether the INDEX operand is a register (registers start after `RegType::kLabelTag`).
    1274             :   inline constexpr bool hasIndexReg() const noexcept {
    1275             :     return _signature.subset(Signature::kMemIndexTypeMask).bits() > Signature::fromMemIndexType(RegType::kLabelTag).bits();
    1276             :   }
    1277             : 
    1278             :   //! Returns the type of the BASE register (0 if this memory operand doesn't use the BASE register).
    1279             :   //!
    1280             :   //! \note If the returned type is one (a value never associated to a register type) the BASE is not register, but it
    1281             :   //! is a label. One equals to `kLabelTag`. You should always check `hasBaseLabel()` before using `baseId()` result.
    1282             :   inline constexpr RegType baseType() const noexcept { return _signature.memBaseType(); }
    1283             : 
    1284             :   //! Returns the type of an INDEX register (0 if this memory operand doesn't
    1285             :   //! use the INDEX register).
    1286             :   inline constexpr RegType indexType() const noexcept { return _signature.memIndexType(); }
    1287             : 
    1288             :   //! This is used internally for BASE+INDEX validation.
    1289             :   inline constexpr uint32_t baseAndIndexTypes() const noexcept { return _signature.getField<Signature::kMemBaseIndexMask>(); }
    1290             : 
    1291             :   //! Returns both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a single value.
    1292             :   //!
    1293             :   //! \remarks Returns id of the BASE register or label (if the BASE was specified as label).
    1294      284190 :   inline constexpr uint32_t baseId() const noexcept { return _baseId; }
    1295             : 
    1296             :   //! Returns the id of the INDEX register.
    1297          20 :   inline constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; }
    1298             : 
    1299             :   //! Sets the id of the BASE register (without modifying its type).
    1300           0 :   inline void setBaseId(uint32_t id) noexcept { _baseId = id; }
    1301             :   //! Sets the id of the INDEX register (without modifying its type).
    1302             :   inline void setIndexId(uint32_t id) noexcept { _data[kDataMemIndexId] = id; }
    1303             : 
    1304             :   //! Sets the base register to type and id of the given `base` operand.
    1305             :   inline void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); }
    1306             :   //! Sets the index register to type and id of the given `index` operand.
    1307             :   inline void setIndex(const BaseReg& index) noexcept { return _setIndex(index.type(), index.id()); }
    1308             : 
    1309             :   //! \cond INTERNAL
    1310             :   inline void _setBase(RegType type, uint32_t id) noexcept {
    1311             :     _signature.setField<Signature::kMemBaseTypeMask>(uint32_t(type));
    1312       71131 :     _baseId = id;
    1313             :   }
    1314             : 
    1315             :   inline void _setIndex(RegType type, uint32_t id) noexcept {
    1316             :     _signature.setField<Signature::kMemIndexTypeMask>(uint32_t(type));
    1317             :     _data[kDataMemIndexId] = id;
    1318             :   }
    1319             :   //! \endcond
    1320             : 
    1321             :   //! Resets the memory operand's BASE register or label.
    1322             :   inline void resetBase() noexcept { _setBase(RegType::kNone, 0); }
    1323             :   //! Resets the memory operand's INDEX register.
    1324             :   inline void resetIndex() noexcept { _setIndex(RegType::kNone, 0); }
    1325             : 
    1326             :   //! Sets the memory operand size (in bytes).
    1327       96852 :   inline void setSize(uint32_t size) noexcept { _signature.setField<Signature::kSizeMask>(size); }
    1328             : 
    1329             :   //! Tests whether the memory operand has a 64-bit offset or absolute address.
    1330             :   //!
    1331             :   //! If this is true then `hasBase()` must always report false.
    1332           0 :   inline constexpr bool isOffset64Bit() const noexcept { return baseType() == RegType::kNone; }
    1333             : 
    1334             :   //! Tests whether the memory operand has a non-zero offset or absolute address.
    1335           0 :   inline constexpr bool hasOffset() const noexcept {
    1336           0 :     return (_data[kDataMemOffsetLo] | uint32_t(_baseId & Support::bitMaskFromBool<uint32_t>(isOffset64Bit()))) != 0;
    1337             :   }
    1338             : 
    1339             :   //! Returns either relative offset or absolute address as 64-bit integer.
    1340           0 :   inline constexpr int64_t offset() const noexcept {
    1341           0 :     return isOffset64Bit() ? int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32))
    1342           0 :                            : int64_t(int32_t(_data[kDataMemOffsetLo])); // Sign extend 32-bit offset.
    1343             :   }
    1344             : 
    1345             :   //! Returns a 32-bit low part of a 64-bit offset or absolute address.
    1346      142105 :   inline constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); }
    1347             :   //! Returns a 32-but high part of a 64-bit offset or absolute address.
    1348             :   //!
    1349             :   //! \note This function is UNSAFE and returns garbage if `isOffset64Bit()`
    1350             :   //! returns false. Never use it blindly without checking it first.
    1351           0 :   inline constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); }
    1352             : 
    1353             :   //! Sets a 64-bit offset or an absolute address to `offset`.
    1354             :   //!
    1355             :   //! \note This functions attempts to set both high and low parts of a 64-bit offset, however, if the operand has
    1356             :   //! a BASE register it will store only the low 32 bits of the offset / address as there is no way to store both
    1357             :   //! BASE and 64-bit offset, and there is currently no architecture that has such capability targeted by AsmJit.
    1358           0 :   inline void setOffset(int64_t offset) noexcept {
    1359           0 :     uint32_t lo = uint32_t(uint64_t(offset) & 0xFFFFFFFFu);
    1360           0 :     uint32_t hi = uint32_t(uint64_t(offset) >> 32);
    1361             :     uint32_t hiMsk = Support::bitMaskFromBool<uint32_t>(isOffset64Bit());
    1362             : 
    1363           0 :     _data[kDataMemOffsetLo] = lo;
    1364           0 :     _baseId = (hi & hiMsk) | (_baseId & ~hiMsk);
    1365           0 :   }
    1366             :   //! Sets a low 32-bit offset to `offset` (don't use without knowing how BaseMem works).
    1367           0 :   inline void setOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] = uint32_t(offset); }
    1368             : 
    1369             :   //! Adjusts the offset by `offset`.
    1370             :   //!
    1371             :   //! \note This is a fast function that doesn't use the HI 32-bits of a 64-bit offset. Use it only if you know that
    1372             :   //! there is a BASE register and the offset is only 32 bits anyway.
    1373             : 
    1374             :   //! Adjusts the memory operand offset by a `offset`.
    1375           0 :   inline void addOffset(int64_t offset) noexcept {
    1376           0 :     if (isOffset64Bit()) {
    1377           0 :       int64_t result = offset + int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32));
    1378           0 :       _data[kDataMemOffsetLo] = uint32_t(uint64_t(result) & 0xFFFFFFFFu);
    1379           0 :       _baseId                 = uint32_t(uint64_t(result) >> 32);
    1380             :     }
    1381             :     else {
    1382           0 :       _data[kDataMemOffsetLo] += uint32_t(uint64_t(offset) & 0xFFFFFFFFu);
    1383             :     }
    1384           0 :   }
    1385             : 
    1386             :   //! Adds `offset` to a low 32-bit offset part (don't use without knowing how BaseMem works).
    1387       71131 :   inline void addOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] += uint32_t(offset); }
    1388             : 
    1389             :   //! Resets the memory offset to zero.
    1390             :   inline void resetOffset() noexcept { setOffset(0); }
    1391             : 
    1392             :   //! Resets the lo part of the memory offset to zero (don't use without knowing how BaseMem works).
    1393             :   inline void resetOffsetLo32() noexcept { setOffsetLo32(0); }
    1394             : 
    1395             :   //! \}
    1396             : };
    1397             : 
    1398             : //! Type of the an immediate value.
    1399             : enum class ImmType : uint32_t {
    1400             :   //! Immediate is integer.
    1401             :   kInt = 0,
    1402             :   //! Immediate is a floating point stored as double-precision.
    1403             :   kDouble = 1
    1404             : };
    1405             : 
    1406             : //! Immediate operands are encoded with instruction data.
    1407             : class Imm : public Operand {
    1408             : public:
    1409             :   //! \cond INTERNAL
    1410             :   template<typename T>
    1411             :   struct IsConstexprConstructibleAsImmType
    1412             :     : public std::integral_constant<bool, std::is_enum<T>::value ||
    1413             :                                           std::is_pointer<T>::value ||
    1414             :                                           std::is_integral<T>::value ||
    1415             :                                           std::is_function<T>::value> {};
    1416             : 
    1417             :   template<typename T>
    1418             :   struct IsConvertibleToImmType
    1419             :     : public std::integral_constant<bool, IsConstexprConstructibleAsImmType<T>::value ||
    1420             :                                           std::is_floating_point<T>::value> {};
    1421             :   //! \endcond
    1422             : 
    1423             :   //! \name Construction & Destruction
    1424             :   //! \{
    1425             : 
    1426             :   //! Creates a new immediate value (initial value is 0).
    1427             :   inline constexpr Imm() noexcept
    1428             :     : Operand(Globals::Init, Signature::fromOpType(OperandType::kImm), 0, 0, 0) {}
    1429             : 
    1430             :   //! Creates a new immediate value from `other`.
    1431             :   inline constexpr Imm(const Imm& other) noexcept
    1432         188 :     : Operand(other) {}
    1433             : 
    1434             :   //! Creates a new immediate value from ARM/AArch64 specific `shift`.
    1435             :   inline constexpr Imm(const arm::Shift& shift) noexcept
    1436             :     : Operand(Globals::Init,
    1437             :               Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(uint32_t(shift.op())),
    1438             :               0,
    1439             :               Support::unpackU32At0(shift.value()),
    1440             :               Support::unpackU32At1(shift.value())) {}
    1441             : 
    1442             :   //! Creates a new signed immediate value, assigning the value to `val` and an architecture-specific predicate
    1443             :   //! to `predicate`.
    1444             :   //!
    1445             :   //! \note Predicate is currently only used by ARM architectures.
    1446             :   template<typename T, typename = typename std::enable_if<IsConstexprConstructibleAsImmType<typename std::decay<T>::type>::value>::type>
    1447             :   inline constexpr Imm(const T& val, const uint32_t predicate = 0) noexcept
    1448             :     : Operand(Globals::Init,
    1449             :               Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate),
    1450             :               0,
    1451             :               Support::unpackU32At0(int64_t(val)),
    1452       88142 :               Support::unpackU32At1(int64_t(val))) {}
    1453             : 
    1454             :   inline Imm(const float& val, const uint32_t predicate = 0) noexcept
    1455             :     : Operand(Globals::Init,
    1456             :               Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate),
    1457             :               0,
    1458             :               0,
    1459             :               0) { setValue(val); }
    1460             : 
    1461             :   inline Imm(const double& val, const uint32_t predicate = 0) noexcept
    1462             :     : Operand(Globals::Init,
    1463             :               Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate),
    1464             :               0,
    1465             :               0,
    1466             :               0) { setValue(val); }
    1467             : 
    1468             :   inline explicit Imm(Globals::NoInit_) noexcept
    1469             :     : Operand(Globals::NoInit) {}
    1470             : 
    1471             :   //! \}
    1472             : 
    1473             :   //! \name Overloaded Operators
    1474             :   //! \{
    1475             : 
    1476             :   //! Assigns the value of the `other` operand to this immediate.
    1477           0 :   inline Imm& operator=(const Imm& other) noexcept { copyFrom(other); return *this; }
    1478             : 
    1479             :   //! \}
    1480             : 
    1481             :   //! \name Accessors
    1482             :   //! \{
    1483             : 
    1484             :   //! Returns immediate type.
    1485             :   inline constexpr ImmType type() const noexcept { return (ImmType)_signature.getField<Signature::kImmTypeMask>(); }
    1486             :   //! Sets the immediate type to `type`.
    1487             :   inline void setType(ImmType type) noexcept { _signature.setField<Signature::kImmTypeMask>(uint32_t(type)); }
    1488             :   //! Resets immediate type to \ref ImmType::kInt.
    1489             :   inline void resetType() noexcept { setType(ImmType::kInt); }
    1490             : 
    1491             :   //! Returns operation predicate of the immediate.
    1492             :   //!
    1493             :   //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp
    1494             :   //! of the immediate.
    1495             :   inline constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); }
    1496             : 
    1497             :   //! Sets operation predicate of the immediate to `predicate`.
    1498             :   //!
    1499             :   //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp
    1500             :   //! of the immediate.
    1501             :   inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); }
    1502             : 
    1503             :   //! Resets the shift operation type of the immediate to the default value (no operation).
    1504             :   inline void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); }
    1505             : 
    1506             :   //! Returns the immediate value as `int64_t`, which is the internal format Imm uses.
    1507             :   inline constexpr int64_t value() const noexcept {
    1508      100192 :     return int64_t((uint64_t(_data[kDataImmValueHi]) << 32) | _data[kDataImmValueLo]);
    1509             :   }
    1510             : 
    1511             :   //! Tests whether this immediate value is integer of any size.
    1512             :   inline constexpr uint32_t isInt() const noexcept { return type() == ImmType::kInt; }
    1513             :   //! Tests whether this immediate value is a double precision floating point value.
    1514             :   inline constexpr uint32_t isDouble() const noexcept { return type() == ImmType::kDouble; }
    1515             : 
    1516             :   //! Tests whether the immediate can be casted to 8-bit signed integer.
    1517             :   inline constexpr bool isInt8() const noexcept { return type() == ImmType::kInt && Support::isInt8(value()); }
    1518             :   //! Tests whether the immediate can be casted to 8-bit unsigned integer.
    1519             :   inline constexpr bool isUInt8() const noexcept { return type() == ImmType::kInt && Support::isUInt8(value()); }
    1520             :   //! Tests whether the immediate can be casted to 16-bit signed integer.
    1521             :   inline constexpr bool isInt16() const noexcept { return type() == ImmType::kInt && Support::isInt16(value()); }
    1522             :   //! Tests whether the immediate can be casted to 16-bit unsigned integer.
    1523             :   inline constexpr bool isUInt16() const noexcept { return type() == ImmType::kInt && Support::isUInt16(value()); }
    1524             :   //! Tests whether the immediate can be casted to 32-bit signed integer.
    1525           0 :   inline constexpr bool isInt32() const noexcept { return type() == ImmType::kInt && Support::isInt32(value()); }
    1526             :   //! Tests whether the immediate can be casted to 32-bit unsigned integer.
    1527         188 :   inline constexpr bool isUInt32() const noexcept { return type() == ImmType::kInt && _data[kDataImmValueHi] == 0; }
    1528             : 
    1529             :   //! Returns the immediate value casted to `T`.
    1530             :   //!
    1531             :   //! The value is masked before it's casted to `T` so the returned value is simply the representation of `T`
    1532             :   //! considering the original value's lowest bits.
    1533             :   template<typename T>
    1534             :   inline T valueAs() const noexcept { return Support::immediateToT<T>(value()); }
    1535             : 
    1536             :   //! Returns low 32-bit signed integer.
    1537             :   inline constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); }
    1538             :   //! Returns high 32-bit signed integer.
    1539             :   inline constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); }
    1540             :   //! Returns low 32-bit signed integer.
    1541             :   inline constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; }
    1542             :   //! Returns high 32-bit signed integer.
    1543           0 :   inline constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; }
    1544             : 
    1545             :   //! Sets immediate value to `val`, the value is casted to a signed 64-bit integer.
    1546             :   template<typename T>
    1547             :   inline void setValue(const T& val) noexcept {
    1548             :     _setValueInternal(Support::immediateFromT(val), std::is_floating_point<T>::value ? ImmType::kDouble : ImmType::kInt);
    1549             :   }
    1550             : 
    1551             :   inline void _setValueInternal(int64_t val, ImmType type) noexcept {
    1552             :     setType(type);
    1553           0 :     _data[kDataImmValueHi] = uint32_t(uint64_t(val) >> 32);
    1554           0 :     _data[kDataImmValueLo] = uint32_t(uint64_t(val) & 0xFFFFFFFFu);
    1555             :   }
    1556             : 
    1557             :   //! \}
    1558             : 
    1559             :   //! \name Utilities
    1560             :   //! \{
    1561             : 
    1562             :   //! Clones the immediate operand.
    1563             :   inline constexpr Imm clone() const noexcept { return Imm(*this); }
    1564             : 
    1565           0 :   inline void signExtend8Bits() noexcept { setValue(int64_t(valueAs<int8_t>())); }
    1566           0 :   inline void signExtend16Bits() noexcept { setValue(int64_t(valueAs<int16_t>())); }
    1567           0 :   inline void signExtend32Bits() noexcept { setValue(int64_t(valueAs<int32_t>())); }
    1568             : 
    1569           0 :   inline void zeroExtend8Bits() noexcept { setValue(valueAs<uint8_t>()); }
    1570           0 :   inline void zeroExtend16Bits() noexcept { setValue(valueAs<uint16_t>()); }
    1571           0 :   inline void zeroExtend32Bits() noexcept { _data[kDataImmValueHi] = 0u; }
    1572             : 
    1573             :   //! \}
    1574             : };
    1575             : 
    1576             : //! Creates a new immediate operand.
    1577             : template<typename T>
    1578             : static inline constexpr Imm imm(const T& val) noexcept { return Imm(val); }
    1579             : 
    1580             : //! \}
    1581             : 
    1582             : namespace Globals {
    1583             :   //! \ingroup asmjit_assembler
    1584             :   //!
    1585             :   //! A default-constructed operand of `Operand_::kOpNone` type.
    1586             :   static constexpr const Operand none;
    1587             : }
    1588             : 
    1589             : //! \cond INTERNAL
    1590             : namespace Support {
    1591             : 
    1592             : template<typename T, bool kIsImm>
    1593             : struct ForwardOpImpl {
    1594      100442 :   static inline const T& forward(const T& value) noexcept { return value; }
    1595             : };
    1596             : 
    1597             : template<typename T>
    1598             : struct ForwardOpImpl<T, true> {
    1599           0 :   static inline Imm forward(const T& value) noexcept { return Imm(value); }
    1600             : };
    1601             : 
    1602             : //! Either forwards operand T or returns a new operand that wraps it if T is a type convertible to operand.
    1603             : //! At the moment this is only used to convert integers, floats, and enumarations to \ref Imm operands.
    1604             : template<typename T>
    1605             : struct ForwardOp : public ForwardOpImpl<T, Imm::IsConvertibleToImmType<typename std::decay<T>::type>::value> {};
    1606             : 
    1607             : } // {Support}
    1608             : //! \endcond
    1609             : 
    1610             : ASMJIT_END_NAMESPACE
    1611             : 
    1612             : #endif // ASMJIT_CORE_OPERAND_H_INCLUDED
    1613             : 
    1614             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16