text: // [AsmJit]
  // Complete x86/x64 JIT and Remote Assembler for C++.
  //
  // [License]
  // Zlib - See LICENSE.md file in the package.
  
  // [Guard]
  #ifndef _ASMJIT_X86_X86OPERAND_H
  #define _ASMJIT_X86_X86OPERAND_H
  
  // [Dependencies - AsmJit]
  #include "../base/assembler.h"
  #include "../base/compiler.h"
  #include "../base/globals.h"
  #include "../base/intutil.h"
  #include "../base/operand.h"
  #include "../base/vectypes.h"
  
  // [Api-Begin]
  #include "../apibegin.h"
  
  //! \internal
  //!
  //! Internal macro to get an operand ID casting it to `Operand`. Basically
  //! allows to get an id of operand that has been just 'typedef'ed.
  #define ASMJIT_OP_ID(_Op_) reinterpret_cast<const Operand&>(_Op_).getId()
  
  namespace asmjit {
  
  // ============================================================================
  // [Forward Declarations]
  // ============================================================================
  
  struct X86Reg;
  struct X86RipReg;
  struct X86SegReg;
  struct X86GpReg;
  struct X86FpReg;
  struct X86MmReg;
  struct X86KReg;
  struct X86XmmReg;
  struct X86YmmReg;
  struct X86ZmmReg;
  
  #if !defined(ASMJIT_DISABLE_COMPILER)
  struct X86Var;
  struct X86GpVar;
  struct X86MmVar;
  struct X86KVar;
  struct X86XmmVar;
  struct X86YmmVar;
  struct X86ZmmVar;
  #endif // !ASMJIT_DISABLE_COMPILER
  
  //! \addtogroup asmjit_x86_general
  //! \{
  
  // ============================================================================
  // [asmjit::X86RegClass]
  // ============================================================================
  
  //! X86/X64 variable class.
  ASMJIT_ENUM(X86RegClass) {
    // --------------------------------------------------------------------------
    // [Regs & Vars]
    // --------------------------------------------------------------------------
  
    //! X86/X64 Gp register class (compatible with universal \ref kRegClassGp).
    kX86RegClassGp = kRegClassGp,
    //! X86/X64 Mm register class.
    kX86RegClassMm = 1,
    //! X86/X64 K register class.
    kX86RegClassK = 2,
    //! X86/X64 Xmm/Ymm/Zmm register class.
    kX86RegClassXyz = 3,
  
    //! \internal
    //!
    //! Last register class that is managed by `X86Compiler`, used by asserts.
    _kX86RegClassManagedCount = 4,
  
    // --------------------------------------------------------------------------
    // [Regs Only]
    // --------------------------------------------------------------------------
  
    //! X86/X64 Fp register class.
    kX86RegClassFp = 4,
  
    //! Count of X86/X64 register classes.
    kX86RegClassCount = 5
  };
  
  // ============================================================================
  // [asmjit::X86RegType]
  // ============================================================================
  
  //! X86/X64 register type.
  ASMJIT_ENUM(X86RegType) {
    //! Gpb-lo register (AL, BL, CL, DL, ...).
    kX86RegTypeGpbLo = 0x01,
    //! Gpb-hi register (AH, BH, CH, DH only).
    kX86RegTypeGpbHi = 0x02,
  
    //! \internal
    //!
    //! Gpb-hi register patched to native index (4-7).
    _kX86RegTypePatchedGpbHi = kX86RegTypeGpbLo | kX86RegTypeGpbHi,
  
    //! Gpw register.
    kX86RegTypeGpw = 0x10,
    //! Gpd register.
    kX86RegTypeGpd = 0x20,
    //! Gpq register (X64).
    kX86RegTypeGpq = 0x30,
  
    //! Fp register.
    kX86RegTypeFp = 0x40,
    //! Mm register (MMX+).
    kX86RegTypeMm = 0x50,
  
    //! K register (AVX512+).
    kX86RegTypeK = 0x60,
  
    //! Xmm register (SSE+).
    kX86RegTypeXmm = 0x70,
    //! Ymm register (AVX+).
    kX86RegTypeYmm = 0x80,
    //! Zmm register (AVX512+).
    kX86RegTypeZmm = 0x90,
  
    //! Instruction pointer (RIP).
    kX86RegTypeRip = 0xE0,
    //! Segment register.
    kX86RegTypeSeg = 0xF0
  };
  
  // ============================================================================
  // [asmjit::X86RegIndex]
  // ============================================================================
  
  //! X86/X64 register indexes.
  //!
  //! \note Register indexes have been reduced to only support general purpose
  //! registers. There is no need to have enumerations with number suffix that
  //! expands to the exactly same value as the suffix value itself.
  ASMJIT_ENUM(X86RegIndex) {
    //! Index of Al/Ah/Ax/Eax/Rax registers.
    kX86RegIndexAx = 0,
    //! Index of Cl/Ch/Cx/Ecx/Rcx registers.
    kX86RegIndexCx = 1,
    //! Index of Dl/Dh/Dx/Edx/Rdx registers.
    kX86RegIndexDx = 2,
    //! Index of Bl/Bh/Bx/Ebx/Rbx registers.
    kX86RegIndexBx = 3,
    //! Index of Spl/Sp/Esp/Rsp registers.
    kX86RegIndexSp = 4,
    //! Index of Bpl/Bp/Ebp/Rbp registers.
    kX86RegIndexBp = 5,
    //! Index of Sil/Si/Esi/Rsi registers.
    kX86RegIndexSi = 6,
    //! Index of Dil/Di/Edi/Rdi registers.
    kX86RegIndexDi = 7,
    //! Index of R8b/R8w/R8d/R8 registers (64-bit only).
    kX86RegIndexR8 = 8,
    //! Index of R9B/R9w/R9d/R9 registers (64-bit only).
    kX86RegIndexR9 = 9,
    //! Index of R10B/R10w/R10D/R10 registers (64-bit only).
    kX86RegIndexR10 = 10,
    //! Index of R11B/R11w/R11d/R11 registers (64-bit only).
    kX86RegIndexR11 = 11,
    //! Index of R12B/R12w/R12d/R12 registers (64-bit only).
    kX86RegIndexR12 = 12,
    //! Index of R13B/R13w/R13d/R13 registers (64-bit only).
    kX86RegIndexR13 = 13,
    //! Index of R14B/R14w/R14d/R14 registers (64-bit only).
    kX86RegIndexR14 = 14,
    //! Index of R15B/R15w/R15d/R15 registers (64-bit only).
    kX86RegIndexR15 = 15
  };
  
  // ============================================================================
  // [asmjit::X86Seg]
  // ============================================================================
  
  //! X86/X64 segment codes.
  ASMJIT_ENUM(X86Seg) {
    //! No/Default segment.
    kX86SegDefault = 0,
    //! Es segment.
    kX86SegEs = 1,
    //! Cs segment.
    kX86SegCs = 2,
    //! Ss segment.
    kX86SegSs = 3,
    //! Ds segment.
    kX86SegDs = 4,
    //! Fs segment.
    kX86SegFs = 5,
    //! Gs segment.
    kX86SegGs = 6,
  
    //! Count of X86 segment registers supported by AsmJit.
    //!
    //! \note X86 architecture has 6 segment registers - ES, CS, SS, DS, FS, GS.
    //! X64 architecture lowers them down to just FS and GS. AsmJit supports 7
    //! segment registers - all addressable in both X86 and X64 modes and one
    //! extra called `kX86SegDefault`, which is AsmJit specific and means that there
    //! is no segment register specified so the segment prefix will not be emitted.
    kX86SegCount = 7
  };
  
  // ============================================================================
  // [asmjit::X86MemVSib]
  // ============================================================================
  
  //! X86/X64 index register legacy and AVX2 (VSIB) support.
  ASMJIT_ENUM(X86MemVSib) {
    //! Memory operand uses Gpd/Gpq index (or no index register).
    kX86MemVSibGpz = 0,
    //! Memory operand uses Xmm index (or no index register).
    kX86MemVSibXmm = 1,
    //! Memory operand uses Ymm index (or no index register).
    kX86MemVSibYmm = 2,
    //! Memory operand uses Zmm index (or no index register).
    kX86MemVSibZmm = 3
  };
  
  // ============================================================================
  // [asmjit::X86MemFlags]
  // ============================================================================
  
  //! \internal
  //!
  //! X86/X64 specific memory flags.
  ASMJIT_ENUM(X86MemFlags) {
    kX86MemSegBits    = 0x7,
    kX86MemSegIndex   = 0,
    kX86MemSegMask    = kX86MemSegBits << kX86MemSegIndex,
  
    kX86MemGpdBits    = 0x1,
    kX86MemGpdIndex   = 3,
    kX86MemGpdMask    = kX86MemGpdBits << kX86MemGpdIndex,
  
    kX86MemVSibBits   = 0x3,
    kX86MemVSibIndex  = 4,
    kX86MemVSibMask   = kX86MemVSibBits << kX86MemVSibIndex,
  
    kX86MemShiftBits  = 0x3,
    kX86MemShiftIndex = 6,
    kX86MemShiftMask  = kX86MemShiftBits << kX86MemShiftIndex
  };
  
  // This is only defined by `x86operand_regs.cpp` when exporting registers.
  #if defined(ASMJIT_EXPORTS_X86OPERAND_REGS)
  
  // Remap all classes to POD structs so they can be statically initialized
  // without calling a constructor. Compiler will store these in .DATA section.
  struct X86RipReg { Operand::VRegOp data; };
  struct X86SegReg { Operand::VRegOp data; };
  struct X86GpReg  { Operand::VRegOp data; };
  struct X86FpReg  { Operand::VRegOp data; };
  struct X86KReg   { Operand::VRegOp data; };
  struct X86MmReg  { Operand::VRegOp data; };
  struct X86XmmReg { Operand::VRegOp data; };
  struct X86YmmReg { Operand::VRegOp data; };
  struct X86ZmmReg { Operand::VRegOp data; };
  
  #else
  
  // ============================================================================
  // [asmjit::X86RegCount]
  // ============================================================================
  
  //! \internal
  //!
  //! X86/X64 registers count (Gp, Mm, K, Xmm/Ymm/Zmm).
  //!
  //! Since the number of registers changed across CPU generations `X86RegCount`
  //! class is used by `X86Assembler` and `X86Compiler` to provide a way to get
  //! number of available registers dynamically. 32-bit mode offers always only
  //! 8 registers of all classes, however, 64-bit mode offers 16 Gp registers and
  //! 16 Xmm/Ymm/Zmm registers. AVX512 instruction set doubles the number of SIMD
  //! registers (Xmm/Ymm/Zmm) to 32, this mode has to be explicitly enabled to
  //! take effect as it changes some assumptions.
  //!
  //! `X86RegCount` is also used extensively by `X86Compiler`'s register allocator
  //! and data structures. Fp registers were omitted as they are never mapped to
  //! variables, thus, not needed to be managed.
  //!
  //! \note At the moment `X86RegCount` can fit into 32-bits, having 8-bits for
  //! all register classes (except Fp). This can change in the future after a
  //! new instruction set is announced.
  struct X86RegCount {
    // --------------------------------------------------------------------------
    // [Zero]
    // --------------------------------------------------------------------------
  
    //! Reset all counters to zero.
    ASMJIT_INLINE void reset() {
      _packed = 0;
    }
  
    // --------------------------------------------------------------------------
    // [Get]
    // --------------------------------------------------------------------------
  
    //! Get register count by `classId`.
    ASMJIT_INLINE uint32_t get(uint32_t classId) const {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
      return _regs[classId];
    }
  
    //! Get Gp register count.
    ASMJIT_INLINE uint32_t getGp() const { return _regs[kX86RegClassGp]; }
    //! Get Mm register count.
    ASMJIT_INLINE uint32_t getMm() const { return _regs[kX86RegClassMm]; }
    //! Get K register count.
    ASMJIT_INLINE uint32_t getK() const { return _regs[kX86RegClassK]; }
    //! Get Xmm/Ymm/Zmm register count.
    ASMJIT_INLINE uint32_t getXyz() const { return _regs[kX86RegClassXyz]; }
  
    // --------------------------------------------------------------------------
    // [Set]
    // --------------------------------------------------------------------------
  
    //! Set register count by `classId`.
    ASMJIT_INLINE void set(uint32_t classId, uint32_t n) {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
      ASMJIT_ASSERT(n <= 0xFF);
  
      _regs[classId] = static_cast<uint8_t>(n);
    }
  
    //! Set Gp register count.
    ASMJIT_INLINE void setGp(uint32_t n) { set(kX86RegClassGp, n); }
    //! Set Mm register count.
    ASMJIT_INLINE void setMm(uint32_t n) { set(kX86RegClassMm, n); }
    //! Set K register count.
    ASMJIT_INLINE void setK(uint32_t n) { set(kX86RegClassK, n); }
    //! Set Xmm/Ymm/Zmm register count.
    ASMJIT_INLINE void setXyz(uint32_t n) { set(kX86RegClassXyz, n); }
  
    // --------------------------------------------------------------------------
    // [Add]
    // --------------------------------------------------------------------------
  
    //! Add register count by `classId`.
    ASMJIT_INLINE void add(uint32_t classId, uint32_t n = 1) {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
      ASMJIT_ASSERT(0xFF - static_cast<uint32_t>(_regs[classId]) >= n);
  
      _regs[classId] += static_cast<uint8_t>(n);
    }
  
    //! Add Gp register count.
    ASMJIT_INLINE void addGp(uint32_t n) { add(kX86RegClassGp, n); }
    //! Add Mm register count.
    ASMJIT_INLINE void addMm(uint32_t n) { add(kX86RegClassMm, n); }
    //! Add K register count.
    ASMJIT_INLINE void addK(uint32_t n) { add(kX86RegClassK, n); }
    //! Add Xmm/Ymm/Zmm register count.
    ASMJIT_INLINE void addXyz(uint32_t n) { add(kX86RegClassXyz, n); }
  
    // --------------------------------------------------------------------------
    // [Misc]
    // --------------------------------------------------------------------------
  
    //! Build a register indexes, based on register's `count`.
    //!
    //! Register index is used by \ref `X86Compiler` in per-instruction register
    //! data. Indexes are sorted by register class in Gp, Mm, K, and Xmm/Ymm/Zmm
    //! order.
    ASMJIT_INLINE void indexFromRegCount(const X86RegCount& count) {
      uint32_t x = count._regs[0];
      uint32_t y;
  
      _regs[0] = static_cast<uint8_t>(0);
      _regs[1] = static_cast<uint8_t>(x);
  
      x = x + count._regs[1];
      y = x + count._regs[2];
  
      ASMJIT_ASSERT(x <= 0xFF);
      ASMJIT_ASSERT(y <= 0xFF);
  
      _regs[2] = static_cast<uint8_t>(x);
      _regs[3] = static_cast<uint8_t>(y);
    }
  
    // --------------------------------------------------------------------------
    // [Members]
    // --------------------------------------------------------------------------
  
    union {
      struct {
        //! Count of Gp registers.
        uint8_t _gp;
        //! Count of Mm registers.
        uint8_t _mm;
        //! Count of K registers.
        uint8_t _k;
        //! Count of Xmm/Ymm/Zmm registers.
        uint8_t _xyz;
        //! \internal
        uint8_t _reserved[3];
      };
  
      uint8_t _regs[4];
      uint32_t _packed;
    };
  };
  
  // ============================================================================
  // [asmjit::X86RegMask]
  // ============================================================================
  
  //! \internal
  //!
  //! X86/X64 registers mask (Gp, Mm, K, Xmm/Ymm/Zmm).
  struct X86RegMask {
    // --------------------------------------------------------------------------
    // [Reset]
    // --------------------------------------------------------------------------
  
    //! Reset all register masks to zero.
    ASMJIT_INLINE void reset() {
      _packed.reset();
    }
  
    // --------------------------------------------------------------------------
    // [IsEmpty / Has]
    // --------------------------------------------------------------------------
  
    //! Get whether all register masks are zero (empty).
    ASMJIT_INLINE bool isEmpty() const {
      return _packed.isZero();
    }
  
    ASMJIT_INLINE bool has(uint32_t classId, uint32_t mask = 0xFFFFFFFF) const {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
  
      switch (classId) {
        case kX86RegClassGp : return (static_cast<uint32_t>(_gp ) & mask) != 0;
        case kX86RegClassMm : return (static_cast<uint32_t>(_mm ) & mask) != 0;
        case kX86RegClassK  : return (static_cast<uint32_t>(_k  ) & mask) != 0;
        case kX86RegClassXyz: return (static_cast<uint32_t>(_xyz) & mask) != 0;
      }
  
      return false;
    }
  
    ASMJIT_INLINE bool hasGp(uint32_t mask = 0xFFFFFFFF) const { return has(kX86RegClassGp, mask); }
    ASMJIT_INLINE bool hasMm(uint32_t mask = 0xFFFFFFFF) const { return has(kX86RegClassMm, mask); }
    ASMJIT_INLINE bool hasK(uint32_t mask = 0xFFFFFFFF) const { return has(kX86RegClassK, mask); }
    ASMJIT_INLINE bool hasXyz(uint32_t mask = 0xFFFFFFFF) const { return has(kX86RegClassXyz, mask); }
  
    // --------------------------------------------------------------------------
    // [Get]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE uint32_t get(uint32_t classId) const {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
  
      switch (classId) {
        case kX86RegClassGp : return _gp;
        case kX86RegClassMm : return _mm;
        case kX86RegClassK  : return _k;
        case kX86RegClassXyz: return _xyz;
      }
  
      return 0;
    }
  
    ASMJIT_INLINE uint32_t getGp() const { return get(kX86RegClassGp); }
    ASMJIT_INLINE uint32_t getMm() const { return get(kX86RegClassMm); }
    ASMJIT_INLINE uint32_t getK() const { return get(kX86RegClassK); }
    ASMJIT_INLINE uint32_t getXyz() const { return get(kX86RegClassXyz); }
  
    // --------------------------------------------------------------------------
    // [Zero]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE void zero(uint32_t classId) {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
  
      switch (classId) {
        case kX86RegClassGp : _gp  = 0; break;
        case kX86RegClassMm : _mm  = 0; break;
        case kX86RegClassK  : _k   = 0; break;
        case kX86RegClassXyz: _xyz = 0; break;
      }
    }
  
    ASMJIT_INLINE void zeroGp() { zero(kX86RegClassGp); }
    ASMJIT_INLINE void zeroMm() { zero(kX86RegClassMm); }
    ASMJIT_INLINE void zeroK() { zero(kX86RegClassK); }
    ASMJIT_INLINE void zeroXyz() { zero(kX86RegClassXyz); }
  
    // --------------------------------------------------------------------------
    // [Set]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE void set(const X86RegMask& other) {
      _packed = other._packed;
    }
  
    ASMJIT_INLINE void set(uint32_t classId, uint32_t mask) {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
  
      switch (classId) {
        case kX86RegClassGp : _gp  = static_cast<uint16_t>(mask); break;
        case kX86RegClassMm : _mm  = static_cast<uint8_t >(mask); break;
        case kX86RegClassK  : _k   = static_cast<uint8_t >(mask); break;
        case kX86RegClassXyz: _xyz = static_cast<uint32_t>(mask); break;
      }
    }
  
    ASMJIT_INLINE void setGp(uint32_t mask) { return set(kX86RegClassGp, mask); }
    ASMJIT_INLINE void setMm(uint32_t mask) { return set(kX86RegClassMm, mask); }
    ASMJIT_INLINE void setK(uint32_t mask) { return set(kX86RegClassK, mask); }
    ASMJIT_INLINE void setXyz(uint32_t mask) { return set(kX86RegClassXyz, mask); }
  
    // --------------------------------------------------------------------------
    // [And]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE void and_(const X86RegMask& other) {
      _packed.and_(other._packed);
    }
  
    ASMJIT_INLINE void and_(uint32_t classId, uint32_t mask) {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
  
      switch (classId) {
        case kX86RegClassGp : _gp  &= static_cast<uint16_t>(mask); break;
        case kX86RegClassMm : _mm  &= static_cast<uint8_t >(mask); break;
        case kX86RegClassK  : _k   &= static_cast<uint8_t >(mask); break;
        case kX86RegClassXyz: _xyz &= static_cast<uint32_t>(mask); break;
      }
    }
  
    ASMJIT_INLINE void andGp(uint32_t mask) { and_(kX86RegClassGp, mask); }
    ASMJIT_INLINE void andMm(uint32_t mask) { and_(kX86RegClassMm, mask); }
    ASMJIT_INLINE void andK(uint32_t mask) { and_(kX86RegClassK, mask); }
    ASMJIT_INLINE void andXyz(uint32_t mask) { and_(kX86RegClassXyz, mask); }
  
    // --------------------------------------------------------------------------
    // [AndNot]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE void andNot(const X86RegMask& other) {
      _packed.andNot(other._packed);
    }
  
    ASMJIT_INLINE void andNot(uint32_t classId, uint32_t mask) {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
  
      switch (classId) {
        case kX86RegClassGp : _gp  &= ~static_cast<uint16_t>(mask); break;
        case kX86RegClassMm : _mm  &= ~static_cast<uint8_t >(mask); break;
        case kX86RegClassK  : _k   &= ~static_cast<uint8_t >(mask); break;
        case kX86RegClassXyz: _xyz &= ~static_cast<uint32_t>(mask); break;
      }
    }
  
    ASMJIT_INLINE void andNotGp(uint32_t mask) { andNot(kX86RegClassGp, mask); }
    ASMJIT_INLINE void andNotMm(uint32_t mask) { andNot(kX86RegClassMm, mask); }
    ASMJIT_INLINE void andNotK(uint32_t mask) { andNot(kX86RegClassK, mask); }
    ASMJIT_INLINE void andNotXyz(uint32_t mask) { andNot(kX86RegClassXyz, mask); }
  
    // --------------------------------------------------------------------------
    // [Or]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE void or_(const X86RegMask& other) {
      _packed.or_(other._packed);
    }
  
    ASMJIT_INLINE void or_(uint32_t classId, uint32_t mask) {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
      switch (classId) {
        case kX86RegClassGp : _gp  |= static_cast<uint16_t>(mask); break;
        case kX86RegClassMm : _mm  |= static_cast<uint8_t >(mask); break;
        case kX86RegClassK  : _k   |= static_cast<uint8_t >(mask); break;
        case kX86RegClassXyz: _xyz |= static_cast<uint32_t>(mask); break;
      }
    }
  
    ASMJIT_INLINE void orGp(uint32_t mask) { return or_(kX86RegClassGp, mask); }
    ASMJIT_INLINE void orMm(uint32_t mask) { return or_(kX86RegClassMm, mask); }
    ASMJIT_INLINE void orK(uint32_t mask) { return or_(kX86RegClassK, mask); }
    ASMJIT_INLINE void orXyz(uint32_t mask) { return or_(kX86RegClassXyz, mask); }
  
    // --------------------------------------------------------------------------
    // [Xor]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE void xor_(const X86RegMask& other) {
      _packed.xor_(other._packed);
    }
  
    ASMJIT_INLINE void xor_(uint32_t classId, uint32_t mask) {
      ASMJIT_ASSERT(classId < _kX86RegClassManagedCount);
  
      switch (classId) {
        case kX86RegClassGp : _gp  ^= static_cast<uint16_t>(mask); break;
        case kX86RegClassMm : _mm  ^= static_cast<uint8_t >(mask); break;
        case kX86RegClassK  : _k   ^= static_cast<uint8_t >(mask); break;
        case kX86RegClassXyz: _xyz ^= static_cast<uint32_t>(mask); break;
      }
    }
  
    ASMJIT_INLINE void xorGp(uint32_t mask) { xor_(kX86RegClassGp, mask); }
    ASMJIT_INLINE void xorMm(uint32_t mask) { xor_(kX86RegClassMm, mask); }
    ASMJIT_INLINE void xorK(uint32_t mask) { xor_(kX86RegClassK, mask); }
    ASMJIT_INLINE void xorXyz(uint32_t mask) { xor_(kX86RegClassXyz, mask); }
  
    // --------------------------------------------------------------------------
    // [Members]
    // --------------------------------------------------------------------------
  
    union {
      struct {
        //! Gp registers mask (16 bits).
        uint16_t _gp;
        //! Mm registers mask (8 bits).
        uint8_t _mm;
        //! K registers mask (8 bits).
        uint8_t _k;
        //! Xmm/Ymm/Zmm registers mask (32 bits).
        uint32_t _xyz;
      };
  
      //! Packed masks.
      UInt64 _packed;
    };
  };
  
  // ============================================================================
  // [asmjit::X86Reg]
  // ============================================================================
  
  //! X86/X86 register base class.
  struct X86Reg : public Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy X86 register.
    ASMJIT_INLINE X86Reg() : Reg() {}
    //! Create a reference to `other` X86 register.
    ASMJIT_INLINE X86Reg(const X86Reg& other) : Reg(other) {}
    //! Create a reference to `other` X86 register and change the index to `index`.
    ASMJIT_INLINE X86Reg(const X86Reg& other, uint32_t index) : Reg(other, index) {}
    //! Create a custom X86 register.
    ASMJIT_INLINE X86Reg(uint32_t type, uint32_t index, uint32_t size) : Reg(type, index, size) {}
    //! Create non-initialized X86 register.
    explicit ASMJIT_INLINE X86Reg(const _NoInit&) : Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86Reg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86Reg)
  
    //! Get whether the register is Gp register.
    ASMJIT_INLINE bool isGp() const { return _vreg.type <= kX86RegTypeGpq; }
    //! Get whether the register is Gp byte (8-bit) register.
    ASMJIT_INLINE bool isGpb() const { return _vreg.type <= _kX86RegTypePatchedGpbHi; }
    //! Get whether the register is Gp lo-byte (8-bit) register.
    ASMJIT_INLINE bool isGpbLo() const { return _vreg.type == kX86RegTypeGpbLo; }
    //! Get whether the register is Gp hi-byte (8-bit) register.
    ASMJIT_INLINE bool isGpbHi() const { return _vreg.type == kX86RegTypeGpbHi; }
    //! Get whether the register is Gp word (16-bit) register.
    ASMJIT_INLINE bool isGpw() const { return _vreg.type == kX86RegTypeGpw; }
    //! Get whether the register is Gp dword (32-bit) register.
    ASMJIT_INLINE bool isGpd() const { return _vreg.type == kX86RegTypeGpd; }
    //! Get whether the register is Gp qword (64-bit) register.
    ASMJIT_INLINE bool isGpq() const { return _vreg.type == kX86RegTypeGpq; }
  
    //! Get whether the register is Fp register.
    ASMJIT_INLINE bool isFp() const { return _vreg.type == kX86RegTypeFp; }
    //! Get whether the register is Mm (64-bit) register.
    ASMJIT_INLINE bool isMm() const { return _vreg.type == kX86RegTypeMm; }
  
    //! Get whether the register is K (64-bit) register.
    ASMJIT_INLINE bool isK() const { return _vreg.type == kX86RegTypeK; }
  
    //! Get whether the register is Xmm (128-bit) register.
    ASMJIT_INLINE bool isXmm() const { return _vreg.type == kX86RegTypeXmm; }
    //! Get whether the register is Ymm (256-bit) register.
    ASMJIT_INLINE bool isYmm() const { return _vreg.type == kX86RegTypeYmm; }
    //! Get whether the register is Zmm (512-bit) register.
    ASMJIT_INLINE bool isZmm() const { return _vreg.type == kX86RegTypeZmm; }
  
    //! Get whether the register is RIP.
    ASMJIT_INLINE bool isRip() const { return _vreg.type == kX86RegTypeRip; }
    //! Get whether the register is Segment.
    ASMJIT_INLINE bool isSeg() const { return _vreg.type == kX86RegTypeSeg; }
  
    // --------------------------------------------------------------------------
    // [Statics]
    // --------------------------------------------------------------------------
  
    //! Get whether the `op` operand is Gpb-Lo or Gpb-Hi register.
    static ASMJIT_INLINE bool isGpbReg(const Operand& op) {
      const uint32_t mask = IntUtil::pack32_2x8_1x16(
        0xFF, 0xFF, ~(_kX86RegTypePatchedGpbHi << 8) & 0xFF00);
  
      return (op._packed[0].u32[0] & mask) == IntUtil::pack32_2x8_1x16(kOperandTypeReg, 1, 0x0000);
    }
  };
  
  // ============================================================================
  // [asmjit::X86RipReg]
  // ============================================================================
  
  //! X86/X64 RIP register.
  struct X86RipReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a RIP register.
    ASMJIT_INLINE X86RipReg() : X86Reg(kX86RegTypeRip, 0, 0) {}
    //! Create a reference to `other` RIP register.
    ASMJIT_INLINE X86RipReg(const X86RipReg& other) : X86Reg(other) {}
    //! Create non-initialized RIP register.
    explicit ASMJIT_INLINE X86RipReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86RipReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86RipReg)
  };
  
  // ============================================================================
  // [asmjit::X86SegReg]
  // ============================================================================
  
  //! X86/X64 segment register.
  struct X86SegReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy segment register.
    ASMJIT_INLINE X86SegReg() : X86Reg() {}
    //! Create a reference to `other` segment register.
    ASMJIT_INLINE X86SegReg(const X86SegReg& other) : X86Reg(other) {}
    //! Create a reference to `other` segment register and change the index to `index`.
    ASMJIT_INLINE X86SegReg(const X86SegReg& other, uint32_t index) : X86Reg(other, index) {}
    //! Create a custom segment register.
    ASMJIT_INLINE X86SegReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {}
    //! Create non-initialized segment register.
    explicit ASMJIT_INLINE X86SegReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86SegReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86SegReg)
  };
  
  // ============================================================================
  // [asmjit::X86GpReg]
  // ============================================================================
  
  //! X86/X64 Gpb/Gpw/Gpd/Gpq register.
  struct X86GpReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy Gp register.
    ASMJIT_INLINE X86GpReg() : X86Reg() {}
    //! Create a reference to `other` Gp register.
    ASMJIT_INLINE X86GpReg(const X86GpReg& other) : X86Reg(other) {}
    //! Create a reference to `other` Gp register and change the index to `index`.
    ASMJIT_INLINE X86GpReg(const X86GpReg& other, uint32_t index) : X86Reg(other, index) {}
    //! Create a custom Gp register.
    ASMJIT_INLINE X86GpReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {}
    //! Create non-initialized Gp register.
    explicit ASMJIT_INLINE X86GpReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86GpReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86GpReg)
  
    // --------------------------------------------------------------------------
    // [X86GpReg Cast]
    // --------------------------------------------------------------------------
  
    //! Cast this register to 8-bit (LO) part.
    ASMJIT_INLINE X86GpReg r8() const { return X86GpReg(kX86RegTypeGpbLo, getRegIndex(), 1); }
    //! Cast this register to 8-bit (LO) part.
    ASMJIT_INLINE X86GpReg r8Lo() const { return X86GpReg(kX86RegTypeGpbLo, getRegIndex(), 1); }
    //! Cast this register to 8-bit (HI) part.
    ASMJIT_INLINE X86GpReg r8Hi() const { return X86GpReg(kX86RegTypeGpbHi, getRegIndex(), 1); }
  
    //! Cast this register to 16-bit.
    ASMJIT_INLINE X86GpReg r16() const { return X86GpReg(kX86RegTypeGpw, getRegIndex(), 2); }
    //! Cast this register to 32-bit.
    ASMJIT_INLINE X86GpReg r32() const { return X86GpReg(kX86RegTypeGpd, getRegIndex(), 4); }
    //! Cast this register to 64-bit.
    ASMJIT_INLINE X86GpReg r64() const { return X86GpReg(kX86RegTypeGpq, getRegIndex(), 8); }
  };
  
  // ============================================================================
  // [asmjit::X86FpReg]
  // ============================================================================
  
  //! X86/X64 80-bit Fp register.
  struct X86FpReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy Fp register.
    ASMJIT_INLINE X86FpReg() : X86Reg() {}
    //! Create a reference to `other` Fp register.
    ASMJIT_INLINE X86FpReg(const X86FpReg& other) : X86Reg(other) {}
    //! Create a reference to `other` Fp register and change the index to `index`.
    ASMJIT_INLINE X86FpReg(const X86FpReg& other, uint32_t index) : X86Reg(other, index) {}
    //! Create a custom Fp register.
    ASMJIT_INLINE X86FpReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {}
    //! Create non-initialized Fp register.
    explicit ASMJIT_INLINE X86FpReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86FpReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86FpReg)
  };
  
  // ============================================================================
  // [asmjit::X86MmReg]
  // ============================================================================
  
  //! X86/X64 64-bit Mm register (MMX+).
  //!
  //! Structure of MMX register and it's memory mapping:
  //!
  //! ~~~
  //!       Memory Bytes
  //! +--+--+--+--+--+--+--+--+
  //! |00|01|02|03|04|05|06|07|
  //! +--+--+--+--+--+--+--+--+
  //!
  //!       MMX Register
  //! +-----------------------+
  //! |         QWord         |
  //! +-----------+-----------+
  //! |  HI-DWord |  LO-DWord |
  //! +-----------+-----------+
  //! |  W3 |  W2 |  W1 |  W0 |
  //! +--+--+--+--+--+--+--+--+
  //! |07|06|05|04|03|02|01|00|
  //! +--+--+--+--+--+--+--+--+
  //! ~~~
  //!
  //! Move instruction semantics:
  //!
  //!   - `movd` - writes 4-bytes in `LO-DWord` and zeroes `HI-DWord`.
  //!   - `movq` - writes 8-bytes in `QWord`.
  struct X86MmReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy Mm register.
    ASMJIT_INLINE X86MmReg() : X86Reg() {}
    //! Create a reference to `other` Mm register.
    ASMJIT_INLINE X86MmReg(const X86MmReg& other) : X86Reg(other) {}
    //! Create a reference to `other` Mm register and change the index to `index`.
    ASMJIT_INLINE X86MmReg(const X86MmReg& other, uint32_t index) : X86Reg(other, index) {}
    //! Create a custom Mm register.
    ASMJIT_INLINE X86MmReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {}
    //! Create non-initialized Mm register.
    explicit ASMJIT_INLINE X86MmReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86MmReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86MmReg)
  };
  
  // ============================================================================
  // [asmjit::X86KReg]
  // ============================================================================
  
  //! X86/X64 64-bit K register (AVX512+).
  struct X86KReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy K register.
    ASMJIT_INLINE X86KReg() : X86Reg() {}
    //! Create a reference to `other` K register.
    ASMJIT_INLINE X86KReg(const X86KReg& other) : X86Reg(other) {}
    //! Create a reference to `other` K register and change the index to `index`.
    ASMJIT_INLINE X86KReg(const X86KReg& other, uint32_t index) : X86Reg(other, index) {}
    //! Create a custom K register.
    ASMJIT_INLINE X86KReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {}
    //! Create non-initialized K register.
    explicit ASMJIT_INLINE X86KReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86KReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86KReg)
  };
  
  // ============================================================================
  // [asmjit::X86XmmReg]
  // ============================================================================
  
  //! X86/X64 128-bit Xmm register (SSE+).
  //!
  //! Structure of XMM register and it's memory mapping:
  //!
  //! ~~~
  //!                   Memory Bytes
  //! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  //! |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
  //! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  //!
  //!                   XMM Register
  //! +-----------------------------------------------+
  //! |                     OWord                     |
  //! +-----------------------+-----------------------+
  //! |      HI-QWord/PD      |      LO-QWord/SD      |
  //! +-----------+-----------+-----------+-----------+
  //! |   D3/PS   |   D2/PS   |   D1/PS   |   D0/SS   |
  //! +-----------+-----------+-----------+-----------+
  //! |  W7 |  W6 |  W5 |  W4 |  W3 |  W2 |  W1 |  W0 |
  //! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  //! |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
  //! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  //! ~~~
  //!
  //! Move instruction semantics:
  //!
  //!   - `movd` - writes 4-bytes in `D0` and zeroes the rest.
  //!   - `movq` - writes 8-bytes in `Lo-QWord` and zeroes the rest.
  //!   - `movq2dq` - writes 8 bytes in `Lo-QWord` and zeroes the rest.
  //!
  //!   - `movss` - writes 4-bytes in `D0`
  //!       (the rest is zeroed only if the source operand is a memory location).
  //!   - `movsd` - writes 8-bytes in `Lo-QWord`
  //!       (the rest is zeroed only if the source operand is a memory location).
  //!
  //!   - `movaps`,
  //!     `movups`,
  //!     `movapd`,
  //!     `movupd`,
  //!     `movdqu`,
  //!     `movdqa`,
  //!     `lddqu` - writes 16-bytes in `OWord`.
  //!
  //!   - `movlps`,
  //!     `movlpd`,
  //!     `movhlps` - writes 8-bytes in `Lo-QWord` and keeps the rest untouched.
  //!
  //!   - `movhps`,
  //!     `movhpd`,
  //!     `movlhps` - writes 8-bytes in `Hi-QWord` and keeps the rest untouched.
  //!
  //!   - `movddup`,
  //!   - `movsldup`,
  //!   - `movshdup` - writes 16 bytes in `OWord`.
  struct X86XmmReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy Xmm register.
    ASMJIT_INLINE X86XmmReg() : X86Reg() {}
    //! Create a reference to `other` Xmm register.
    ASMJIT_INLINE X86XmmReg(const X86XmmReg& other) : X86Reg(other) {}
    //! Create a reference to `other` Xmm register and change the index to `index`.
    ASMJIT_INLINE X86XmmReg(const X86XmmReg& other, uint32_t index) : X86Reg(other, index) {}
    //! Create a custom Xmm register.
    ASMJIT_INLINE X86XmmReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {}
    //! Create non-initialized Xmm register.
    explicit ASMJIT_INLINE X86XmmReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86XmmReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86XmmReg)
  
    // --------------------------------------------------------------------------
    // [X86XmmReg Cast]
    // --------------------------------------------------------------------------
  
    //! Cast this register to Xmm (clone).
    ASMJIT_INLINE X86XmmReg xmm() const { return X86XmmReg(kX86RegTypeXmm, getRegIndex(), 16); }
    //! Cast this register to Ymm.
    ASMJIT_INLINE X86YmmReg ymm() const;
    //! Cast this register to Zmm.
    ASMJIT_INLINE X86ZmmReg zmm() const;
  };
  
  // ============================================================================
  // [asmjit::X86YmmReg]
  // ============================================================================
  
  //! X86/X64 256-bit Ymm register (AVX+).
  //!
  //! Structure of YMM register and it's memory mapping:
  //!
  //! ~~~
  //!                                           Memory Bytes
  //! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  //! |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
  //! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  //!
  //!                                           YMM Register
  //! +-----------------------------------------------+-----------------------------------------------+
  //! |                  HI-DQWord                    |                  LO-DQWord                    |
  //! +-----------------------+-----------------------+-----------------------+-----------------------+
  //! |         Q3/PD         |         Q2/PD         |         Q1/PD         |         Q0/SD         |
  //! +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
  //! |   D7/PS   |   D6/PS   |   D5/PS   |   D4/PS   |   D3/PS   |   D2/PS   |   D1/PS   |   D0/SS   |
  //! +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
  //! | W15 | W14 | W13 | W12 | W11 | W10 |  W9 |  W8 |  W7 |  W6 |  W5 |  W4 |  W3 |  W2 |  W1 |  W0 |
  //! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  //! |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
  //! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  //! ~~~
  struct X86YmmReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy Ymm register.
    ASMJIT_INLINE X86YmmReg() : X86Reg() {}
    //! Create a reference to `other` Ymm register.
    ASMJIT_INLINE X86YmmReg(const X86YmmReg& other) : X86Reg(other) {}
    //! Create a reference to `other` Ymm register and change the index to `index`.
    ASMJIT_INLINE X86YmmReg(const X86YmmReg& other, uint32_t index) : X86Reg(other, index) {}
    //! Create a custom Ymm register.
    ASMJIT_INLINE X86YmmReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {}
    //! Create non-initialized Ymm register.
    explicit ASMJIT_INLINE X86YmmReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86YmmReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86YmmReg)
  
    // --------------------------------------------------------------------------
    // [X86YmmReg Cast]
    // --------------------------------------------------------------------------
  
    //! Cast this register to Xmm.
    ASMJIT_INLINE X86XmmReg xmm() const { return X86XmmReg(kX86RegTypeXmm, getRegIndex(), 16); }
    //! Cast this register to Ymm (clone).
    ASMJIT_INLINE X86YmmReg ymm() const { return X86YmmReg(kX86RegTypeYmm, getRegIndex(), 32); }
    //! Cast this register to Zmm.
    ASMJIT_INLINE X86ZmmReg zmm() const;
  };
  
  ASMJIT_INLINE X86YmmReg X86XmmReg::ymm() const { return X86YmmReg(kX86RegTypeYmm, getRegIndex(), 32); }
  
  // ============================================================================
  // [asmjit::X86ZmmReg]
  // ============================================================================
  
  //! X86/X64 512-bit Zmm register (AVX512+).
  struct X86ZmmReg : public X86Reg {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    //! Create a dummy Zmm register.
    ASMJIT_INLINE X86ZmmReg() : X86Reg() {}
    //! Create a reference to `other` Zmm register.
    ASMJIT_INLINE X86ZmmReg(const X86ZmmReg& other) : X86Reg(other) {}
    //! Create a reference to `other` Zmm register and change the index to `index`.
    ASMJIT_INLINE X86ZmmReg(const X86ZmmReg& other, uint32_t index) : X86Reg(other, index) {}
    //! Create a custom Zmm register.
    ASMJIT_INLINE X86ZmmReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {}
    //! Create non-initialized Zmm register.
    explicit ASMJIT_INLINE X86ZmmReg(const _NoInit&) : X86Reg(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86ZmmReg Specific]
    // --------------------------------------------------------------------------
  
    ASMJIT_REG_OP(X86ZmmReg)
  
    // --------------------------------------------------------------------------
    // [X86ZmmReg Cast]
    // --------------------------------------------------------------------------
  
    //! Cast this register to Xmm.
    ASMJIT_INLINE X86XmmReg xmm() const { return X86XmmReg(kX86RegTypeXmm, getRegIndex(), 16); }
    //! Cast this register to Ymm.
    ASMJIT_INLINE X86YmmReg ymm() const { return X86YmmReg(kX86RegTypeYmm, getRegIndex(), 32); }
    //! Cast this register to Zmm (clone).
    ASMJIT_INLINE X86ZmmReg zmm() const { return X86ZmmReg(kX86RegTypeZmm, getRegIndex(), 64); }
  };
  
  ASMJIT_INLINE X86ZmmReg X86XmmReg::zmm() const { return X86ZmmReg(kX86RegTypeZmm, getRegIndex(), 64); }
  ASMJIT_INLINE X86ZmmReg X86YmmReg::zmm() const { return X86ZmmReg(kX86RegTypeZmm, getRegIndex(), 64); }
  
  // ============================================================================
  // [asmjit::X86Mem]
  // ============================================================================
  
  //! X86 memory operand.
  struct X86Mem : public BaseMem {
    // --------------------------------------------------------------------------
    // [Construction / Destruction]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE X86Mem() : BaseMem(NoInit) {
      reset();
    }
  
    ASMJIT_INLINE X86Mem(const Label& label, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeLabel, 0, label._base.id);
      _init_packed_d2_d3(kInvalidValue, disp);
    }
  
    ASMJIT_INLINE X86Mem(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeLabel,
        (kX86MemVSibGpz << kX86MemVSibIndex)
          + (shift << kX86MemShiftIndex),
        label.getId());
      _vmem.index = index.getRegIndex();
      _vmem.displacement = disp;
    }
  
    ASMJIT_INLINE X86Mem(const X86RipReg& rip, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeRip, 0, kInvalidValue);
      _init_packed_d2_d3(kInvalidValue, disp);
    }
  
    ASMJIT_INLINE X86Mem(const X86GpReg& base, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
        _getGpdFlags(base)
          + (kX86MemVSibGpz << kX86MemVSibIndex),
        base.getRegIndex());
      _init_packed_d2_d3(kInvalidValue, disp);
    }
  
    ASMJIT_INLINE X86Mem(const X86GpReg& base, const X86GpReg& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
        _getGpdFlags(base) + (shift << kX86MemShiftIndex),
        base.getRegIndex());
      _vmem.index = index.getRegIndex();
      _vmem.displacement = disp;
    }
  
    ASMJIT_INLINE X86Mem(const X86GpReg& base, const X86XmmReg& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
        _getGpdFlags(base)
          + (kX86MemVSibXmm << kX86MemVSibIndex)
          + (shift << kX86MemShiftIndex),
        base.getRegIndex());
      _vmem.index = index.getRegIndex();
      _vmem.displacement = disp;
    }
  
    ASMJIT_INLINE X86Mem(const X86GpReg& base, const X86YmmReg& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
        _getGpdFlags(base)
          + (kX86MemVSibYmm << kX86MemVSibIndex)
          + (shift << kX86MemShiftIndex),
        base.getRegIndex());
      _vmem.index = index.getRegIndex();
      _vmem.displacement = disp;
    }
  
  #if !defined(ASMJIT_DISABLE_COMPILER)
    ASMJIT_INLINE X86Mem(const Label& label, const X86GpVar& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeLabel,
        (kX86MemVSibGpz << kX86MemVSibIndex)
          + (shift << kX86MemShiftIndex),
        label.getId());
      _vmem.index = ASMJIT_OP_ID(index);
      _vmem.displacement = disp;
    }
  
    ASMJIT_INLINE X86Mem(const X86GpVar& base, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
        _getGpdFlags(reinterpret_cast<const Var&>(base))
          + (kX86MemVSibGpz << kX86MemVSibIndex),
        ASMJIT_OP_ID(base));
      _init_packed_d2_d3(kInvalidValue, disp);
    }
  
    ASMJIT_INLINE X86Mem(const X86GpVar& base, const X86GpVar& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
        _getGpdFlags(reinterpret_cast<const Var&>(base))
          + (shift << kX86MemShiftIndex),
        ASMJIT_OP_ID(base));
      _vmem.index = ASMJIT_OP_ID(index);
      _vmem.displacement = disp;
    }
  
    ASMJIT_INLINE X86Mem(const X86GpVar& base, const X86XmmVar& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
        _getGpdFlags(reinterpret_cast<const Var&>(base))
          + (kX86MemVSibXmm << kX86MemVSibIndex)
          + (shift << kX86MemShiftIndex),
        ASMJIT_OP_ID(base));
      _vmem.index = ASMJIT_OP_ID(index);
      _vmem.displacement = disp;
    }
  
    ASMJIT_INLINE X86Mem(const X86GpVar& base, const X86YmmVar& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
        _getGpdFlags(reinterpret_cast<const Var&>(base))
          + (kX86MemVSibYmm << kX86MemVSibIndex)
          + (shift << kX86MemShiftIndex),
        ASMJIT_OP_ID(base));
      _vmem.index = ASMJIT_OP_ID(index);
      _vmem.displacement = disp;
    }
  
    ASMJIT_INLINE X86Mem(const _Init&, uint32_t memType, const X86Var& base, int32_t disp, uint32_t size) : BaseMem(NoInit) {
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, memType, 0, ASMJIT_OP_ID(base));
      _vmem.index = kInvalidValue;
      _vmem.displacement = disp;
    }
  
    ASMJIT_INLINE X86Mem(const _Init&, uint32_t memType, const X86Var& base, const X86GpVar& index, uint32_t shift, int32_t disp, uint32_t size) : BaseMem(NoInit) {
      ASMJIT_ASSERT(shift <= 3);
  
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, memType, shift << kX86MemShiftIndex, ASMJIT_OP_ID(base));
      _vmem.index = ASMJIT_OP_ID(index);
      _vmem.displacement = disp;
    }
  #endif // !ASMJIT_DISABLE_COMPILER
  
    ASMJIT_INLINE X86Mem(const X86Mem& other) : BaseMem(other) {}
    explicit ASMJIT_INLINE X86Mem(const _NoInit&) : BaseMem(NoInit) {}
  
    // --------------------------------------------------------------------------
    // [X86Mem Specific]
    // --------------------------------------------------------------------------
  
    //! Clone X86Mem operand.
    ASMJIT_INLINE X86Mem clone() const {
      return X86Mem(*this);
    }
  
    //! Reset X86Mem operand.
    ASMJIT_INLINE void reset() {
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, 0, kMemTypeBaseIndex, 0, kInvalidValue);
      _init_packed_d2_d3(kInvalidValue, 0);
    }
  
    //! \internal
    ASMJIT_INLINE void _init(uint32_t memType, uint32_t base, int32_t disp, uint32_t size) {
      _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, memType, 0, base);
      _vmem.index = kInvalidValue;
      _vmem.displacement = disp;
    }
  
    // --------------------------------------------------------------------------
    // [Segment]
    // --------------------------------------------------------------------------
  
    //! Get whether the memory operand has segment override prefix.
    ASMJIT_INLINE bool hasSegment() const {
      return (_vmem.flags & kX86MemSegMask) != (kX86SegDefault << kX86MemSegIndex);
    }
  
    //! Get memory operand segment, see `X86Seg`.
    ASMJIT_INLINE uint32_t getSegment() const {
      return (static_cast<uint32_t>(_vmem.flags) >> kX86MemSegIndex) & kX86MemSegBits;
    }
  
    //! Set memory operand segment, see `X86Seg`.
    ASMJIT_INLINE X86Mem& setSegment(uint32_t segIndex) {
      _vmem.flags = static_cast<uint8_t>(
        (static_cast<uint32_t>(_vmem.flags) & kX86MemSegMask) + (segIndex << kX86MemSegIndex));
      return *this;
    }
  
    //! Set memory operand segment, see `X86Seg`.
    ASMJIT_INLINE X86Mem& setSegment(const X86SegReg& seg) {
      return setSegment(seg.getRegIndex());
    }
  
    // --------------------------------------------------------------------------
    // [Gpd]
    // --------------------------------------------------------------------------
  
    //! Get whether the memory operand has 32-bit GP base.
    ASMJIT_INLINE bool hasGpdBase() const {
      return (_packed[0].u32[0] & IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemGpdMask)) != 0;
    }
  
    //! Set whether the memory operand has 32-bit GP base.
    ASMJIT_INLINE X86Mem& setGpdBase() {
      _packed[0].u32[0] |= IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemGpdMask);
      return *this;
    }
  
    //! Set whether the memory operand has 32-bit GP base to `b`.
    ASMJIT_INLINE X86Mem& setGpdBase(uint32_t b) {
      _packed[0].u32[0] &=~IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemGpdMask);
      _packed[0].u32[0] |= IntUtil::pack32_4x8(0x00, 0x00, 0x00, b << kX86MemGpdIndex);
      return *this;
    }
  
    // --------------------------------------------------------------------------
    // [VSib]
    // --------------------------------------------------------------------------
  
    //! Get V-SIB type.
    ASMJIT_INLINE uint32_t getVSib() const {
      return (static_cast<uint32_t>(_vmem.flags) >> kX86MemVSibIndex) & kX86MemVSibBits;
    }
  
    //! Set V-SIB type.
    ASMJIT_INLINE X86Mem& _setVSib(uint32_t vsib) {
      _packed[0].u32[0] &=~IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemVSibMask);
      _packed[0].u32[0] |= IntUtil::pack32_4x8(0x00, 0x00, 0x00, vsib << kX86MemVSibIndex);
      return *this;
    }
  
    // --------------------------------------------------------------------------
    // [Size]
    // --------------------------------------------------------------------------
  
    //! Set memory operand size.
    ASMJIT_INLINE X86Mem& setSize(uint32_t size) {
      _vmem.size = static_cast<uint8_t>(size);
      return *this;
    }
  
    // --------------------------------------------------------------------------
    // [Base]
    // --------------------------------------------------------------------------
  
    //! Get whether the memory operand has base register.
    ASMJIT_INLINE bool hasBase() const {
      return _vmem.base != kInvalidValue;
    }
  
    //! Get memory operand base register code, variable id, or `kInvalidValue`.
    ASMJIT_INLINE uint32_t getBase() const {
      return _vmem.base;
    }
  
    //! Set memory operand base register code, variable id, or `kInvalidValue`.
    ASMJIT_INLINE X86Mem& setBase(uint32_t base) {
      _vmem.base = base;
      return *this;
    }
  
    // --------------------------------------------------------------------------
    // [Index]
    // --------------------------------------------------------------------------
  
    //! Get whether the memory operand has index.
    ASMJIT_INLINE bool hasIndex() const {
      return _vmem.index != kInvalidValue;
    }
  
    //! Get memory operand index register code, variable id, or `kInvalidValue`.
    ASMJIT_INLINE uint32_t getIndex() const {
      return _vmem.index;
    }
  
    //! Set memory operand index register code, variable id, or `kInvalidValue`.
    ASMJIT_INLINE X86Mem& setIndex(uint32_t index) {
      _vmem.index = index;
      return *this;
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86GpReg& index) {
      _vmem.index = index.getRegIndex();
      return _setVSib(kX86MemVSibGpz);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86GpReg& index, uint32_t shift) {
      _vmem.index = index.getRegIndex();
      return _setVSib(kX86MemVSibGpz).setShift(shift);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86XmmReg& index) {
      _vmem.index = index.getRegIndex();
      return _setVSib(kX86MemVSibXmm);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86XmmReg& index, uint32_t shift) {
      _vmem.index = index.getRegIndex();
      return _setVSib(kX86MemVSibXmm).setShift(shift);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86YmmReg& index) {
      _vmem.index = index.getRegIndex();
      return _setVSib(kX86MemVSibYmm);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86YmmReg& index, uint32_t shift) {
      _vmem.index = index.getRegIndex();
      return _setVSib(kX86MemVSibYmm).setShift(shift);
    }
  
  #if !defined(ASMJIT_DISABLE_COMPILER)
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86GpVar& index) {
      _vmem.index = ASMJIT_OP_ID(index);
      return _setVSib(kX86MemVSibGpz);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86GpVar& index, uint32_t shift) {
      _vmem.index = ASMJIT_OP_ID(index);
      return _setVSib(kX86MemVSibGpz).setShift(shift);
    }
  
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86XmmVar& index) {
      _vmem.index = ASMJIT_OP_ID(index);
      return _setVSib(kX86MemVSibXmm);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86XmmVar& index, uint32_t shift) {
      _vmem.index = ASMJIT_OP_ID(index);
      return _setVSib(kX86MemVSibXmm).setShift(shift);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86YmmVar& index) {
      _vmem.index = ASMJIT_OP_ID(index);
      return _setVSib(kX86MemVSibYmm);
    }
  
    //! Set memory index.
    ASMJIT_INLINE X86Mem& setIndex(const X86YmmVar& index, uint32_t shift) {
      _vmem.index = ASMJIT_OP_ID(index);
      return _setVSib(kX86MemVSibYmm).setShift(shift);
    }
  #endif // !ASMJIT_DISABLE_COMPILER
  
    //! Reset memory index.
    ASMJIT_INLINE X86Mem& resetIndex() {
      _vmem.index = kInvalidValue;
      return _setVSib(kX86MemVSibGpz);
    }
  
    // --------------------------------------------------------------------------
    // [Misc]
    // --------------------------------------------------------------------------
  
    //! Get whether the memory operand has base and index register.
    ASMJIT_INLINE bool hasBaseOrIndex() const {
      return _vmem.base != kInvalidValue || _vmem.index != kInvalidValue;
    }
  
    //! Get whether the memory operand has base and index register.
    ASMJIT_INLINE bool hasBaseAndIndex() const {
      return _vmem.base != kInvalidValue && _vmem.index != kInvalidValue;
    }
  
    // --------------------------------------------------------------------------
    // [Shift]
    // --------------------------------------------------------------------------
  
    //! Get whether the memory operand has shift used.
    ASMJIT_INLINE bool hasShift() const {
      return (_vmem.flags & kX86MemShiftMask) != 0;
    }
  
    //! Get memory operand index scale (0, 1, 2 or 3).
    ASMJIT_INLINE uint32_t getShift() const {
      return _vmem.flags >> kX86MemShiftIndex;
    }
  
    //! Set memory operand index scale (0, 1, 2 or 3).
    ASMJIT_INLINE X86Mem& setShift(uint32_t shift) {
      _packed[0].u32[0] &=~IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemShiftMask);
      _packed[0].u32[0] |= IntUtil::pack32_4x8(0x00, 0x00, 0x00, shift << kX86MemShiftIndex);
      return *this;
    }
  
    // --------------------------------------------------------------------------
    // [Displacement]
    // --------------------------------------------------------------------------
  
    //! Get memory operand relative displacement.
    ASMJIT_INLINE int32_t getDisplacement() const {
      return _vmem.displacement;
    }
  
    //! Set memory operand relative displacement.
    ASMJIT_INLINE X86Mem& setDisplacement(int32_t disp) {
      _vmem.displacement = disp;
      return *this;
    }
  
    //! Reset memory operand relative displacement.
    ASMJIT_INLINE X86Mem& resetDisplacement(int32_t disp) {
      _vmem.displacement = 0;
      return *this;
    }
  
    //! Adjust memory operand relative displacement by `disp`.
    ASMJIT_INLINE X86Mem& adjust(int32_t disp) {
      _vmem.displacement += disp;
      return *this;
    }
  
    //! Get new memory operand adjusted by `disp`.
    ASMJIT_INLINE X86Mem adjusted(int32_t disp) const {
      X86Mem result(*this);
      result.adjust(disp);
      return result;
    }
  
    // --------------------------------------------------------------------------
    // [Operator Overload]
    // --------------------------------------------------------------------------
  
    ASMJIT_INLINE X86Mem& operator=(const X86Mem& other) {
      _copy(other);
      return *this;
    }
  
    ASMJIT_INLINE bool operator==(const X86Mem& other) const {
      return (_packed[0] == other._packed[0]) & (_packed[1] == other._packed[1]) ;
    }
  
    ASMJIT_INLINE bool operator!=(const X86Mem& other) const {
      return !(*this == other);
    }
  
    // --------------------------------------------------------------------------
    // [Static]
    // --------------------------------------------------------------------------
  
    static ASMJIT_INLINE uint32_t _getGpdFlags(const Operand& base) {
      return (base._vreg.size & 0x4) << (kX86MemGpdIndex - 2);
    }
  };
  #endif // ASMJIT_EXPORTS_X86OPERAND_REGS
  
  // ============================================================================
  // [asmjit::X86RegData]
  // ============================================================================
  
  struct X86RegData {
    X86RipReg rip;
    X86GpReg noGp;
  
    X86SegReg seg[7];
  
    X86GpReg gpbLo[16];
    X86GpReg gpbHi[4];
  
    X86GpReg gpw[16];
    X86GpReg gpd[16];
    X86GpReg gpq[16];
  
    X86FpReg fp[8];
    X86MmReg mm[8];
    X86KReg k[8];
  
    X86XmmReg xmm[32];
    X86YmmReg ymm[32];
    X86ZmmReg zmm[32];
  };
  
  ASMJIT_VAR const X86RegData x86RegData;
  
  // ============================================================================
  // [asmjit::x86]
  // ============================================================================
  
  namespace x86 {
  
  // ============================================================================
  // [asmjit::x86 - Reg]
  // ============================================================================
  
  #define ASMJIT_DEF_REG(_Type_, _Name_, _Field_) \
    static const _Type_& _Name_ = x86RegData._Field_
  
  ASMJIT_DEF_REG(X86RipReg, rip, rip);        //!< RIP register.
  ASMJIT_DEF_REG(X86GpReg , noGpReg, noGp);   //!< No GP register (for `X86Mem` operand.).
  
  ASMJIT_DEF_REG(X86SegReg, es   , seg[1]);   //!< Cs segment register.
  ASMJIT_DEF_REG(X86SegReg, cs   , seg[2]);   //!< Ss segment register.
  ASMJIT_DEF_REG(X86SegReg, ss   , seg[3]);   //!< Ds segment register.
  ASMJIT_DEF_REG(X86SegReg, ds   , seg[4]);   //!< Es segment register.
  ASMJIT_DEF_REG(X86SegReg, fs   , seg[5]);   //!< Fs segment register.
  ASMJIT_DEF_REG(X86SegReg, gs   , seg[6]);   //!< Gs segment register.
  
  ASMJIT_DEF_REG(X86GpReg , al   , gpbLo[0]); //!< 8-bit Gpb-lo register.
  ASMJIT_DEF_REG(X86GpReg , cl   , gpbLo[1]); //!< 8-bit Gpb-lo register.
  ASMJIT_DEF_REG(X86GpReg , dl   , gpbLo[2]); //!< 8-bit Gpb-lo register.
  ASMJIT_DEF_REG(X86GpReg , bl   , gpbLo[3]); //!< 8-bit Gpb-lo register.
  ASMJIT_DEF_REG(X86GpReg , spl  , gpbLo[4]); //!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , bpl  , gpbLo[5]); //!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , sil  , gpbLo[6]); //!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , dil  , gpbLo[7]); //!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , r8b  , gpbLo[8]); //!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , r9b  , gpbLo[9]); //!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , r10b , gpbLo[10]);//!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , r11b , gpbLo[11]);//!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , r12b , gpbLo[12]);//!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , r13b , gpbLo[13]);//!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , r14b , gpbLo[14]);//!< 8-bit Gpb-lo register (X64).
  ASMJIT_DEF_REG(X86GpReg , r15b , gpbLo[15]);//!< 8-bit Gpb-lo register (X64).
  
  ASMJIT_DEF_REG(X86GpReg , ah   , gpbHi[0]); //!< 8-bit Gpb-hi register.
  ASMJIT_DEF_REG(X86GpReg , ch   , gpbHi[1]); //!< 8-bit Gpb-hi register.
  ASMJIT_DEF_REG(X86GpReg , dh   , gpbHi[2]); //!< 8-bit Gpb-hi register.
  ASMJIT_DEF_REG(X86GpReg , bh   , gpbHi[3]); //!< 8-bit Gpb-hi register.
  
  ASMJIT_DEF_REG(X86GpReg , ax   , gpw[0]);   //!< 16-bit Gpw register.
  ASMJIT_DEF_REG(X86GpReg , cx   , gpw[1]);   //!< 16-bit Gpw register.
  ASMJIT_DEF_REG(X86GpReg , dx   , gpw[2]);   //!< 16-bit Gpw register.
  ASMJIT_DEF_REG(X86GpReg , bx   , gpw[3]);   //!< 16-bit Gpw register.
  ASMJIT_DEF_REG(X86GpReg , sp   , gpw[4]);   //!< 16-bit Gpw register.
  ASMJIT_DEF_REG(X86GpReg , bp   , gpw[5]);   //!< 16-bit Gpw register.
  ASMJIT_DEF_REG(X86GpReg , si   , gpw[6]);   //!< 16-bit Gpw register.
  ASMJIT_DEF_REG(X86GpReg , di   , gpw[7]);   //!< 16-bit Gpw register.
  ASMJIT_DEF_REG(X86GpReg , r8w  , gpw[8]);   //!< 16-bit Gpw register (X64).
  ASMJIT_DEF_REG(X86GpReg , r9w  , gpw[9]);   //!< 16-bit Gpw register (X64).
  ASMJIT_DEF_REG(X86GpReg , r10w , gpw[10]);  //!< 16-bit Gpw register (X64).
  ASMJIT_DEF_REG(X86GpReg , r11w , gpw[11]);  //!< 16-bit Gpw register (X64).
  ASMJIT_DEF_REG(X86GpReg , r12w , gpw[12]);  //!< 16-bit Gpw register (X64).
  ASMJIT_DEF_REG(X86GpReg , r13w , gpw[13]);  //!< 16-bit Gpw register (X64).
  ASMJIT_DEF_REG(X86GpReg , r14w , gpw[14]);  //!< 16-bit Gpw register (X64).
  ASMJIT_DEF_REG(X86GpReg , r15w , gpw[15]);  //!< 16-bit Gpw register (X64).
  
  ASMJIT_DEF_REG(X86GpReg , eax  , gpd[0]);   //!< 32-bit Gpd register.
  ASMJIT_DEF_REG(X86GpReg , ecx  , gpd[1]);   //!< 32-bit Gpd register.
  ASMJIT_DEF_REG(X86GpReg , edx  , gpd[2]);   //!< 32-bit Gpd register.
  ASMJIT_DEF_REG(X86GpReg , ebx  , gpd[3]);   //!< 32-bit Gpd register.
  ASMJIT_DEF_REG(X86GpReg , esp  , gpd[4]);   //!< 32-bit Gpd register.
  ASMJIT_DEF_REG(X86GpReg , ebp  , gpd[5]);   //!< 32-bit Gpd register.
  ASMJIT_DEF_REG(X86GpReg , esi  , gpd[6]);   //!< 32-bit Gpd register.
  ASMJIT_DEF_REG(X86GpReg , edi  , gpd[7]);   //!< 32-bit Gpd register.
  ASMJIT_DEF_REG(X86GpReg , r8d  , gpd[8]);   //!< 32-bit Gpd register (X64).
  ASMJIT_DEF_REG(X86GpReg , r9d  , gpd[9]);   //!< 32-bit Gpd register (X64).
  ASMJIT_DEF_REG(X86GpReg , r10d , gpd[10]);  //!< 32-bit Gpd register (X64).
  ASMJIT_DEF_REG(X86GpReg , r11d , gpd[11]);  //!< 32-bit Gpd register (X64).
  ASMJIT_DEF_REG(X86GpReg , r12d , gpd[12]);  //!< 32-bit Gpd register (X64).
  ASMJIT_DEF_REG(X86GpReg , r13d , gpd[13]);  //!< 32-bit Gpd register (X64).
  ASMJIT_DEF_REG(X86GpReg , r14d , gpd[14]);  //!< 32-bit Gpd register (X64).
  ASMJIT_DEF_REG(X86GpReg , r15d , gpd[15]);  //!< 32-bit Gpd register (X64).
  
  ASMJIT_DEF_REG(X86GpReg , rax  , gpq[0]);   //!< 64-bit Gpq register (X64).
  ASMJIT_DEF_REG(X86GpReg , rcx  , gpq[1]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , rdx  , gpq[2]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , rbx  , gpq[3]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , rsp  , gpq[4]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , rbp  , gpq[5]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , rsi  , gpq[6]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , rdi  , gpq[7]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , r8   , gpq[8]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , r9   , gpq[9]);   //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , r10  , gpq[10]);  //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , r11  , gpq[11]);  //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , r12  , gpq[12]);  //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , r13  , gpq[13]);  //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , r14  , gpq[14]);  //!< 64-bit Gpq register (X64)
  ASMJIT_DEF_REG(X86GpReg , r15  , gpq[15]);  //!< 64-bit Gpq register (X64)
  
  ASMJIT_DEF_REG(X86FpReg , fp0  , fp[0]);    //!< 80-bit Fp register.
  ASMJIT_DEF_REG(X86FpReg , fp1  , fp[1]);    //!< 80-bit Fp register.
  ASMJIT_DEF_REG(X86FpReg , fp2  , fp[2]);    //!< 80-bit Fp register.
  ASMJIT_DEF_REG(X86FpReg , fp3  , fp[3]);    //!< 80-bit Fp register.
  ASMJIT_DEF_REG(X86FpReg , fp4  , fp[4]);    //!< 80-bit Fp register.
  ASMJIT_DEF_REG(X86FpReg , fp5  , fp[5]);    //!< 80-bit Fp register.
  ASMJIT_DEF_REG(X86FpReg , fp6  , fp[6]);    //!< 80-bit Fp register.
  ASMJIT_DEF_REG(X86FpReg , fp7  , fp[7]);    //!< 80-bit Fp register.
  
  ASMJIT_DEF_REG(X86MmReg , mm0  , mm[0]);    //!< 64-bit Mm register.
  ASMJIT_DEF_REG(X86MmReg , mm1  , mm[1]);    //!< 64-bit Mm register.
  ASMJIT_DEF_REG(X86MmReg , mm2  , mm[2]);    //!< 64-bit Mm register.
  ASMJIT_DEF_REG(X86MmReg , mm3  , mm[3]);    //!< 64-bit Mm register.
  ASMJIT_DEF_REG(X86MmReg , mm4  , mm[4]);    //!< 64-bit Mm register.
  ASMJIT_DEF_REG(X86MmReg , mm5  , mm[5]);    //!< 64-bit Mm register.
  ASMJIT_DEF_REG(X86MmReg , mm6  , mm[6]);    //!< 64-bit Mm register.
  ASMJIT_DEF_REG(X86MmReg , mm7  , mm[7]);    //!< 64-bit Mm register.
  
  ASMJIT_DEF_REG(X86KReg  , k0   , k[0]);     //!< 64-bit K register.
  ASMJIT_DEF_REG(X86KReg  , k1   , k[1]);     //!< 64-bit K register.
  ASMJIT_DEF_REG(X86KReg  , k2   , k[2]);     //!< 64-bit K register.
  ASMJIT_DEF_REG(X86KReg  , k3   , k[3]);     //!< 64-bit K register.
  ASMJIT_DEF_REG(X86KReg  , k4   , k[4]);     //!< 64-bit K register.
  ASMJIT_DEF_REG(X86KReg  , k5   , k[5]);     //!< 64-bit K register.
  ASMJIT_DEF_REG(X86KReg  , k6   , k[6]);     //!< 64-bit K register.
  ASMJIT_DEF_REG(X86KReg  , k7   , k[7]);     //!< 64-bit K register.
  
  ASMJIT_DEF_REG(X86XmmReg, xmm0 , xmm[0]);   //!< 128-bit Xmm register.
  ASMJIT_DEF_REG(X86XmmReg, xmm1 , xmm[1]);   //!< 128-bit Xmm register.
  ASMJIT_DEF_REG(X86XmmReg, xmm2 , xmm[2]);   //!< 128-bit Xmm register.
  ASMJIT_DEF_REG(X86XmmReg, xmm3 , xmm[3]);   //!< 128-bit Xmm register.
  ASMJIT_DEF_REG(X86XmmReg, xmm4 , xmm[4]);   //!< 128-bit Xmm register.
  ASMJIT_DEF_REG(X86XmmReg, xmm5 , xmm[5]);   //!< 128-bit Xmm register.
  ASMJIT_DEF_REG(X86XmmReg, xmm6 , xmm[6]);   //!< 128-bit Xmm register.
  ASMJIT_DEF_REG(X86XmmReg, xmm7 , xmm[7]);   //!< 128-bit Xmm register.
  ASMJIT_DEF_REG(X86XmmReg, xmm8 , xmm[8]);   //!< 128-bit Xmm register (X64).
  ASMJIT_DEF_REG(X86XmmReg, xmm9 , xmm[9]);   //!< 128-bit Xmm register (X64).
  ASMJIT_DEF_REG(X86XmmReg, xmm10, xmm[10]);  //!< 128-bit Xmm register (X64).
  ASMJIT_DEF_REG(X86XmmReg, xmm11, xmm[11]);  //!< 128-bit Xmm register (X64).
  ASMJIT_DEF_REG(X86XmmReg, xmm12, xmm[12]);  //!< 128-bit Xmm register (X64).
  ASMJIT_DEF_REG(X86XmmReg, xmm13, xmm[13]);  //!< 128-bit Xmm register (X64).
  ASMJIT_DEF_REG(X86XmmReg, xmm14, xmm[14]);  //!< 128-bit Xmm register (X64).
  ASMJIT_DEF_REG(X86XmmReg, xmm15, xmm[15]);  //!< 128-bit Xmm register (X64).
  ASMJIT_DEF_REG(X86XmmReg, xmm16, xmm[16]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm17, xmm[17]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm18, xmm[18]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm19, xmm[19]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm20, xmm[20]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm21, xmm[21]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm22, xmm[22]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm23, xmm[23]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm24, xmm[24]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm25, xmm[25]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm26, xmm[26]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm27, xmm[27]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm28, xmm[28]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm29, xmm[29]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm30, xmm[30]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86XmmReg, xmm31, xmm[31]);  //!< 128-bit Xmm register (X64 & AVX512VL+).
  
  ASMJIT_DEF_REG(X86YmmReg, ymm0 , ymm[0]);   //!< 256-bit Ymm register.
  ASMJIT_DEF_REG(X86YmmReg, ymm1 , ymm[1]);   //!< 256-bit Ymm register.
  ASMJIT_DEF_REG(X86YmmReg, ymm2 , ymm[2]);   //!< 256-bit Ymm register.
  ASMJIT_DEF_REG(X86YmmReg, ymm3 , ymm[3]);   //!< 256-bit Ymm register.
  ASMJIT_DEF_REG(X86YmmReg, ymm4 , ymm[4]);   //!< 256-bit Ymm register.
  ASMJIT_DEF_REG(X86YmmReg, ymm5 , ymm[5]);   //!< 256-bit Ymm register.
  ASMJIT_DEF_REG(X86YmmReg, ymm6 , ymm[6]);   //!< 256-bit Ymm register.
  ASMJIT_DEF_REG(X86YmmReg, ymm7 , ymm[7]);   //!< 256-bit Ymm register.
  ASMJIT_DEF_REG(X86YmmReg, ymm8 , ymm[8]);   //!< 256-bit Ymm register (X64).
  ASMJIT_DEF_REG(X86YmmReg, ymm9 , ymm[9]);   //!< 256-bit Ymm register (X64).
  ASMJIT_DEF_REG(X86YmmReg, ymm10, ymm[10]);  //!< 256-bit Ymm register (X64).
  ASMJIT_DEF_REG(X86YmmReg, ymm11, ymm[11]);  //!< 256-bit Ymm register (X64).
  ASMJIT_DEF_REG(X86YmmReg, ymm12, ymm[12]);  //!< 256-bit Ymm register (X64).
  ASMJIT_DEF_REG(X86YmmReg, ymm13, ymm[13]);  //!< 256-bit Ymm register (X64).
  ASMJIT_DEF_REG(X86YmmReg, ymm14, ymm[14]);  //!< 256-bit Ymm register (X64).
  ASMJIT_DEF_REG(X86YmmReg, ymm15, ymm[15]);  //!< 256-bit Ymm register (X64).
  ASMJIT_DEF_REG(X86YmmReg, ymm16, ymm[16]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm17, ymm[17]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm18, ymm[18]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm19, ymm[19]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm20, ymm[20]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm21, ymm[21]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm22, ymm[22]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm23, ymm[23]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm24, ymm[24]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm25, ymm[25]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm26, ymm[26]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm27, ymm[27]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm28, ymm[28]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm29, ymm[29]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm30, ymm[30]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  ASMJIT_DEF_REG(X86YmmReg, ymm31, ymm[31]);  //!< 256-bit Ymm register (X64 & AVX512VL+).
  
  ASMJIT_DEF_REG(X86ZmmReg, zmm0 , zmm[0]);   //!< 512-bit Zmm register.
  ASMJIT_DEF_REG(X86ZmmReg, zmm1 , zmm[1]);   //!< 512-bit Zmm register.
  ASMJIT_DEF_REG(X86ZmmReg, zmm2 , zmm[2]);   //!< 512-bit Zmm register.
  ASMJIT_DEF_REG(X86ZmmReg, zmm3 , zmm[3]);   //!< 512-bit Zmm register.
  ASMJIT_DEF_REG(X86ZmmReg, zmm4 , zmm[4]);   //!< 512-bit Zmm register.
  ASMJIT_DEF_REG(X86ZmmReg, zmm5 , zmm[5]);   //!< 512-bit Zmm register.
  ASMJIT_DEF_REG(X86ZmmReg, zmm6 , zmm[6]);   //!< 512-bit Zmm register.
  ASMJIT_DEF_REG(X86ZmmReg, zmm7 , zmm[7]);   //!< 512-bit Zmm register.
  ASMJIT_DEF_REG(X86ZmmReg, zmm8 , zmm[8]);   //!< 512-bit Zmm register (X64).
  ASMJIT_DEF_REG(X86ZmmReg, zmm9 , zmm[9]);   //!< 512-bit Zmm register (X64).
  ASMJIT_DEF_REG(X86ZmmReg, zmm10, zmm[10]);  //!< 512-bit Zmm register (X64).
  ASMJIT_DEF_REG(X86ZmmReg, zmm11, zmm[11]);  //!< 512-bit Zmm register (X64).
  ASMJIT_DEF_REG(X86ZmmReg, zmm12, zmm[12]);  //!< 512-bit Zmm register (X64).
  ASMJIT_DEF_REG(X86ZmmReg, zmm13, zmm[13]);  //!< 512-bit Zmm register (X64).
  ASMJIT_DEF_REG(X86ZmmReg, zmm14, zmm[14]);  //!< 512-bit Zmm register (X64).
  ASMJIT_DEF_REG(X86ZmmReg, zmm15, zmm[15]);  //!< 512-bit Zmm register (X64).
  ASMJIT_DEF_REG(X86ZmmReg, zmm16, zmm[16]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm17, zmm[17]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm18, zmm[18]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm19, zmm[19]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm20, zmm[20]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm21, zmm[21]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm22, zmm[22]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm23, zmm[23]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm24, zmm[24]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm25, zmm[25]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm26, zmm[26]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm27, zmm[27]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm28, zmm[28]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm29, zmm[29]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm30, zmm[30]);  //!< 512-bit Zmm register (X64 & AVX512+).
  ASMJIT_DEF_REG(X86ZmmReg, zmm31, zmm[31]);  //!< 512-bit Zmm register (X64 & AVX512+).
  #undef ASMJIT_DEF_REG
  
  // This is only defined by `x86operand_regs.cpp` when exporting registers.
  #if !defined(ASMJIT_EXPORTS_X86OPERAND_REGS)
  
  //! Create 8-bit Gpb-lo register operand.
  static ASMJIT_INLINE X86GpReg gpb_lo(uint32_t index) { return X86GpReg(kX86RegTypeGpbLo, index, 1); }
  //! Create 8-bit Gpb-hi register operand.
  static ASMJIT_INLINE X86GpReg gpb_hi(uint32_t index) { return X86GpReg(kX86RegTypeGpbHi, index, 1); }
  //! Create 16-bit Gpw register operand.
  static ASMJIT_INLINE X86GpReg gpw(uint32_t index) { return X86GpReg(kX86RegTypeGpw, index, 2); }
  //! Create 32-bit Gpd register operand.
  static ASMJIT_INLINE X86GpReg gpd(uint32_t index) { return X86GpReg(kX86RegTypeGpd, index, 4); }
  //! Create 64-bit Gpq register operand (X64).
  static ASMJIT_INLINE X86GpReg gpq(uint32_t index) { return X86GpReg(kX86RegTypeGpq, index, 8); }
  //! Create 80-bit Fp register operand.
  static ASMJIT_INLINE X86FpReg fp(uint32_t index) { return X86FpReg(kX86RegTypeFp, index, 10); }
  //! Create 64-bit Mm register operand.
  static ASMJIT_INLINE X86MmReg mm(uint32_t index) { return X86MmReg(kX86RegTypeMm, index, 8); }
  //! Create 64-bit K register operand.
  static ASMJIT_INLINE X86KReg k(uint32_t index) { return X86KReg(kX86RegTypeK, index, 8); }
  //! Create 128-bit Xmm register operand.
  static ASMJIT_INLINE X86XmmReg xmm(uint32_t index) { return X86XmmReg(kX86RegTypeXmm, index, 16); }
  //! Create 256-bit Ymm register operand.
  static ASMJIT_INLINE X86YmmReg ymm(uint32_t index) { return X86YmmReg(kX86RegTypeYmm, index, 32); }
  //! Create 512-bit Zmm register operand.
  static ASMJIT_INLINE X86ZmmReg zmm(uint32_t index) { return X86ZmmReg(kX86RegTypeZmm, index, 64); }
  
  // ============================================================================
  // [asmjit::x86 - Ptr (Reg)]
  // ============================================================================
  
  //! Create `[base.reg + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(base, disp, size);
  }
  //! Create `[base.reg + (index.reg << shift) + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(base, index, shift, disp, size);
  }
  //! Create `[base.reg + (xmm.reg << shift) + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(base, index, shift, disp, size);
  }
  //! Create `[base.reg + (ymm.reg << shift) + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(base, index, shift, disp, size);
  }
  
  //! Create `[label + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const Label& label, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(label, disp, size);
  }
  //! Create `[label + (index.reg << shift) + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0, uint32_t size = 0) { \
    return X86Mem(label, index, shift, disp, size); \
  }
  
  //! Create `[RIP + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86RipReg& rip, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(rip, disp, size); 
  }
  
  //! Create `[pAbs + disp]` absolute memory operand with no/custom size information.
  ASMJIT_API X86Mem ptr_abs(Ptr pAbs, int32_t disp = 0, uint32_t size = 0);
  //! Create `[pAbs + (index.reg << shift) + disp]` absolute memory operand with no/custom size information.
  ASMJIT_API X86Mem ptr_abs(Ptr pAbs, const X86Reg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0);
  
  //! \internal
  #define ASMJIT_EXPAND_PTR_REG(_Prefix_, _Size_) \
    /*! Create `[base.reg + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, int32_t disp = 0) { \
      return X86Mem(base, disp, _Size_); \
    } \
    /*! Create `[base.reg + (index.reg << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr(base, index, shift, disp, _Size_); \
    } \
    /*! Create `[base.reg + (xmm.reg << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr(base, index, shift, disp, _Size_); \
    } \
    /*! Create `[base.reg + (ymm.reg << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr(base, index, shift, disp, _Size_); \
    } \
    /*! Create `[label + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, int32_t disp = 0) { \
      return ptr(label, disp, _Size_); \
    } \
    /*! Create `[label + (index.reg << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0) { \
      return ptr(label, index, shift, disp, _Size_); \
    } \
    /*! Create `[RIP + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##ptr(const X86RipReg& rip, int32_t disp = 0) { \
      return ptr(rip, disp, _Size_); \
    } \
    /*! Create `[pAbs + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, int32_t disp = 0) { \
      return ptr_abs(pAbs, disp, _Size_); \
    } \
    /*! Create `[pAbs + (index.reg << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr_abs(pAbs, index, shift, disp, _Size_); \
    } \
    /*! Create `[pAbs + (xmm.reg << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr_abs(pAbs, index, shift, disp, _Size_); \
    } \
    /*! Create `[pAbs + (ymm.reg << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr_abs(pAbs, index, shift, disp, _Size_); \
    }
  
  ASMJIT_EXPAND_PTR_REG(byte, 1)
  ASMJIT_EXPAND_PTR_REG(word, 2)
  ASMJIT_EXPAND_PTR_REG(dword, 4)
  ASMJIT_EXPAND_PTR_REG(qword, 8)
  ASMJIT_EXPAND_PTR_REG(tword, 10)
  ASMJIT_EXPAND_PTR_REG(oword, 16)
  ASMJIT_EXPAND_PTR_REG(yword, 32)
  ASMJIT_EXPAND_PTR_REG(zword, 64)
  #undef ASMJIT_EXPAND_PTR_REG
  
  // ============================================================================
  // [asmjit::x86 - Ptr (Var)]
  // ============================================================================
  
  #if !defined(ASMJIT_DISABLE_COMPILER)
  //! Create `[base.var + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86GpVar& base, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(base, disp, size);
  }
  //! Create `[base.var + (index.var << shift) + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86GpVar& base, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(base, index, shift, disp, size);
  }
  //! Create `[base.var + (xmm.var << shift) + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86GpVar& base, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(base, index, shift, disp, size);
  }
  //! Create `[base.var + (ymm.var << shift) + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const X86GpVar& base, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) {
    return X86Mem(base, index, shift, disp, size);
  }
  //! Create `[label + (index.var << shift) + disp]` memory operand with no/custom size information.
  static ASMJIT_INLINE X86Mem ptr(const Label& label, const X86GpVar& index, uint32_t shift, int32_t disp = 0, uint32_t size = 0) { \
    return X86Mem(label, index, shift, disp, size); \
  }
  
  //! Create `[pAbs + (index.var << shift) + disp]` absolute memory operand with no/custom size information.
  ASMJIT_API X86Mem ptr_abs(Ptr pAbs, const X86Var& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0);
  
  //! \internal
  #define ASMJIT_EXPAND_PTR_VAR(_Prefix_, _Size_) \
    /*! Create `[base.var + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, int32_t disp = 0) { \
      return X86Mem(base, disp, _Size_); \
    } \
    /*! Create `[base.var + (index.var << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr(base, index, shift, disp, _Size_); \
    } \
    /*! Create `[base.var + (xmm.var << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr(base, index, shift, disp, _Size_); \
    } \
    /*! Create `[base.var + (ymm.var << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr(base, index, shift, disp, _Size_); \
    } \
    /*! Create `[label + (index.var << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, const X86GpVar& index, uint32_t shift, int32_t disp = 0) { \
      return ptr(label, index, shift, disp, _Size_); \
    } \
    /*! Create `[pAbs + (index.var << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr_abs(pAbs, reinterpret_cast<const X86Var&>(index), shift, disp, _Size_); \
    } \
    /*! Create `[pAbs + (xmm.var << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr_abs(pAbs, reinterpret_cast<const X86Var&>(index), shift, disp, _Size_); \
    } \
    /*! Create `[pAbs + (ymm.var << shift) + disp]` memory operand. */ \
    static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \
      return ptr_abs(pAbs, reinterpret_cast<const X86Var&>(index), shift, disp, _Size_); \
    }
  
  ASMJIT_EXPAND_PTR_VAR(byte, 1)
  ASMJIT_EXPAND_PTR_VAR(word, 2)
  ASMJIT_EXPAND_PTR_VAR(dword, 4)
  ASMJIT_EXPAND_PTR_VAR(qword, 8)
  ASMJIT_EXPAND_PTR_VAR(tword, 10)
  ASMJIT_EXPAND_PTR_VAR(oword, 16)
  ASMJIT_EXPAND_PTR_VAR(yword, 32)
  ASMJIT_EXPAND_PTR_VAR(zword, 64)
  #undef ASMJIT_EXPAND_PTR_VAR
  #endif // !ASMJIT_DISABLE_COMPILER
  
  #endif // !ASMJIT_EXPORTS_X86OPERAND_REGS
  
  } // x86 namespace
  
  //! \}
  
  } // asmjit namespace
  
  // [Cleanup]
  #undef ASMJIT_OP_ID
  
  // [Api-End]
  #include "../apiend.h"
  
  // [Guard]
  #endif // _ASMJIT_X86_X86OPERAND_H
  