2593 lines
110 KiB
C++
2593 lines
110 KiB
C++
// [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]
|
|
#include "../base/assembler.h"
|
|
#include "../base/compiler.h"
|
|
#include "../base/operand.h"
|
|
#include "../base/utils.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]
|
|
// ============================================================================
|
|
|
|
class X86Reg;
|
|
class X86GpReg;
|
|
class X86FpReg;
|
|
class X86MmReg;
|
|
class X86KReg;
|
|
class X86XmmReg;
|
|
class X86YmmReg;
|
|
class X86ZmmReg;
|
|
|
|
class X86SegReg;
|
|
class X86RipReg;
|
|
|
|
#if !defined(ASMJIT_DISABLE_COMPILER)
|
|
class X86Var;
|
|
class X86GpVar;
|
|
class X86MmVar;
|
|
class X86KVar;
|
|
class X86XmmVar;
|
|
class X86YmmVar;
|
|
class X86ZmmVar;
|
|
#endif // !ASMJIT_DISABLE_COMPILER
|
|
|
|
//! \addtogroup asmjit_x86
|
|
//! \{
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86RegClass]
|
|
// ============================================================================
|
|
|
|
//! X86/X64 register 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) {
|
|
//! Low GPB register (AL, BL, CL, DL, ...).
|
|
kX86RegTypeGpbLo = 0x01,
|
|
//! High GPB register (AH, BH, CH, DH only).
|
|
kX86RegTypeGpbHi = 0x02,
|
|
|
|
//! \internal
|
|
//!
|
|
//! High GPB register patched to a native index (4-7).
|
|
_kX86RegTypePatchedGpbHi = kX86RegTypeGpbLo | kX86RegTypeGpbHi,
|
|
|
|
//! GPW register.
|
|
kX86RegTypeGpw = 0x10,
|
|
//! GPD register.
|
|
kX86RegTypeGpd = 0x20,
|
|
//! GPQ register (X64).
|
|
kX86RegTypeGpq = 0x30,
|
|
|
|
//! FPU register.
|
|
kX86RegTypeFp = 0x40,
|
|
//! MMX 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
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86VarType]
|
|
// ============================================================================
|
|
|
|
//! X86/X64 variable type.
|
|
ASMJIT_ENUM(X86VarType) {
|
|
//! Variable is SP-FP (FPU).
|
|
kX86VarTypeFp32 = kVarTypeFp32,
|
|
//! Variable is DP-FP (FPU).
|
|
kX86VarTypeFp64 = kVarTypeFp64,
|
|
|
|
//! Variable is MMX (MMX).
|
|
kX86VarTypeMm = 12,
|
|
|
|
//! Variable is K (AVX512+)
|
|
kX86VarTypeK,
|
|
|
|
//! Variable is XMM (SSE+).
|
|
kX86VarTypeXmm,
|
|
//! Variable is a scalar XMM SP-FP number.
|
|
kX86VarTypeXmmSs,
|
|
//! Variable is a packed XMM SP-FP number (4 floats).
|
|
kX86VarTypeXmmPs,
|
|
//! Variable is a scalar XMM DP-FP number.
|
|
kX86VarTypeXmmSd,
|
|
//! Variable is a packed XMM DP-FP number (2 doubles).
|
|
kX86VarTypeXmmPd,
|
|
|
|
//! Variable is YMM (AVX+).
|
|
kX86VarTypeYmm,
|
|
//! Variable is a packed YMM SP-FP number (8 floats).
|
|
kX86VarTypeYmmPs,
|
|
//! Variable is a packed YMM DP-FP number (4 doubles).
|
|
kX86VarTypeYmmPd,
|
|
|
|
//! Variable is ZMM (AVX512+).
|
|
kX86VarTypeZmm,
|
|
//! Variable is a packed ZMM SP-FP number (16 floats).
|
|
kX86VarTypeZmmPs,
|
|
//! Variable is a packed ZMM DP-FP number (8 doubles).
|
|
kX86VarTypeZmmPd,
|
|
|
|
//! Count of variable types.
|
|
kX86VarTypeCount,
|
|
|
|
//! \internal
|
|
//! \{
|
|
_kX86VarTypeMmStart = kX86VarTypeMm,
|
|
_kX86VarTypeMmEnd = kX86VarTypeMm,
|
|
|
|
_kX86VarTypeXmmStart = kX86VarTypeXmm,
|
|
_kX86VarTypeXmmEnd = kX86VarTypeXmmPd,
|
|
|
|
_kX86VarTypeYmmStart = kX86VarTypeYmm,
|
|
_kX86VarTypeYmmEnd = kX86VarTypeYmmPd,
|
|
|
|
_kX86VarTypeZmmStart = kX86VarTypeZmm,
|
|
_kX86VarTypeZmmEnd = kX86VarTypeZmmPd
|
|
//! \}
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86RegCount]
|
|
// ============================================================================
|
|
|
|
//! \internal
|
|
//!
|
|
//! X86/X64 registers count.
|
|
//!
|
|
//! 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
|
|
//! each register class except `fp`. This can change in the future after a
|
|
//! new instruction set, which adds more registers, is introduced.
|
|
struct X86RegCount {
|
|
// --------------------------------------------------------------------------
|
|
// [Zero]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Reset all counters to zero.
|
|
ASMJIT_INLINE void reset() noexcept { _packed = 0; }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Get]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get register count by a register class `rc`.
|
|
ASMJIT_INLINE uint32_t get(uint32_t rc) const noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
|
|
uint32_t shift = Utils::byteShiftOfDWordStruct(rc);
|
|
return (_packed >> shift) & static_cast<uint32_t>(0xFF);
|
|
}
|
|
|
|
//! Get Gp count.
|
|
ASMJIT_INLINE uint32_t getGp() const noexcept { return get(kX86RegClassGp); }
|
|
//! Get Mm count.
|
|
ASMJIT_INLINE uint32_t getMm() const noexcept { return get(kX86RegClassMm); }
|
|
//! Get K count.
|
|
ASMJIT_INLINE uint32_t getK() const noexcept { return get(kX86RegClassK); }
|
|
//! Get XMM/YMM/ZMM count.
|
|
ASMJIT_INLINE uint32_t getXyz() const noexcept { return get(kX86RegClassXyz); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Set]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Set register count by a register class `rc`.
|
|
ASMJIT_INLINE void set(uint32_t rc, uint32_t n) noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
ASMJIT_ASSERT(n <= 0xFF);
|
|
|
|
uint32_t shift = Utils::byteShiftOfDWordStruct(rc);
|
|
_packed = (_packed & ~static_cast<uint32_t>(0xFF << shift)) + (n << shift);
|
|
}
|
|
|
|
//! Set Gp count.
|
|
ASMJIT_INLINE void setGp(uint32_t n) noexcept { set(kX86RegClassGp, n); }
|
|
//! Set Mm count.
|
|
ASMJIT_INLINE void setMm(uint32_t n) noexcept { set(kX86RegClassMm, n); }
|
|
//! Set K count.
|
|
ASMJIT_INLINE void setK(uint32_t n) noexcept { set(kX86RegClassK, n); }
|
|
//! Set XMM/YMM/ZMM count.
|
|
ASMJIT_INLINE void setXyz(uint32_t n) noexcept { set(kX86RegClassXyz, n); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Add]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Add register count by a register class `rc`.
|
|
ASMJIT_INLINE void add(uint32_t rc, uint32_t n = 1) noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
ASMJIT_ASSERT(0xFF - static_cast<uint32_t>(_regs[rc]) >= n);
|
|
|
|
uint32_t shift = Utils::byteShiftOfDWordStruct(rc);
|
|
_packed += n << shift;
|
|
}
|
|
|
|
//! Add GP count.
|
|
ASMJIT_INLINE void addGp(uint32_t n) noexcept { add(kX86RegClassGp, n); }
|
|
//! Add MMX count.
|
|
ASMJIT_INLINE void addMm(uint32_t n) noexcept { add(kX86RegClassMm, n); }
|
|
//! Add K count.
|
|
ASMJIT_INLINE void addK(uint32_t n) noexcept { add(kX86RegClassK, n); }
|
|
//! Add XMM/YMM/ZMM count.
|
|
ASMJIT_INLINE void addXyz(uint32_t n) noexcept { add(kX86RegClassXyz, n); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Misc]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Build register indexes based on the given `count` of registers.
|
|
ASMJIT_INLINE void indexFromRegCount(const X86RegCount& count) noexcept {
|
|
uint32_t x = static_cast<uint32_t>(count._regs[0]);
|
|
uint32_t y = static_cast<uint32_t>(count._regs[1]) + x;
|
|
uint32_t z = static_cast<uint32_t>(count._regs[2]) + y;
|
|
|
|
ASMJIT_ASSERT(y <= 0xFF);
|
|
ASMJIT_ASSERT(z <= 0xFF);
|
|
_packed = Utils::pack32_4x8(0, x, y, z);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Members]
|
|
// --------------------------------------------------------------------------
|
|
|
|
union {
|
|
struct {
|
|
//! Count of GP registers.
|
|
uint8_t _gp;
|
|
//! Count of MMX registers.
|
|
uint8_t _mm;
|
|
//! Count of K registers.
|
|
uint8_t _k;
|
|
//! Count of XMM/YMM/ZMM registers.
|
|
uint8_t _xyz;
|
|
};
|
|
|
|
uint8_t _regs[4];
|
|
uint32_t _packed;
|
|
};
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86RegMask]
|
|
// ============================================================================
|
|
|
|
//! \internal
|
|
//!
|
|
//! X86/X64 registers mask.
|
|
struct X86RegMask {
|
|
// --------------------------------------------------------------------------
|
|
// [Reset]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Reset all register masks to zero.
|
|
ASMJIT_INLINE void reset() noexcept {
|
|
_packed.reset();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [IsEmpty / Has]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get whether all register masks are zero (empty).
|
|
ASMJIT_INLINE bool isEmpty() const noexcept {
|
|
return _packed.isZero();
|
|
}
|
|
|
|
ASMJIT_INLINE bool has(uint32_t rc, uint32_t mask = 0xFFFFFFFF) const noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
|
|
switch (rc) {
|
|
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 noexcept { return has(kX86RegClassGp, mask); }
|
|
ASMJIT_INLINE bool hasMm(uint32_t mask = 0xFFFFFFFF) const noexcept { return has(kX86RegClassMm, mask); }
|
|
ASMJIT_INLINE bool hasK(uint32_t mask = 0xFFFFFFFF) const noexcept { return has(kX86RegClassK, mask); }
|
|
ASMJIT_INLINE bool hasXyz(uint32_t mask = 0xFFFFFFFF) const noexcept { return has(kX86RegClassXyz, mask); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Get]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE uint32_t get(uint32_t rc) const noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
|
|
switch (rc) {
|
|
case kX86RegClassGp : return _gp;
|
|
case kX86RegClassMm : return _mm;
|
|
case kX86RegClassK : return _k;
|
|
case kX86RegClassXyz: return _xyz;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ASMJIT_INLINE uint32_t getGp() const noexcept { return get(kX86RegClassGp); }
|
|
ASMJIT_INLINE uint32_t getMm() const noexcept { return get(kX86RegClassMm); }
|
|
ASMJIT_INLINE uint32_t getK() const noexcept { return get(kX86RegClassK); }
|
|
ASMJIT_INLINE uint32_t getXyz() const noexcept { return get(kX86RegClassXyz); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Zero]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE void zero(uint32_t rc) noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
|
|
switch (rc) {
|
|
case kX86RegClassGp : _gp = 0; break;
|
|
case kX86RegClassMm : _mm = 0; break;
|
|
case kX86RegClassK : _k = 0; break;
|
|
case kX86RegClassXyz: _xyz = 0; break;
|
|
}
|
|
}
|
|
|
|
ASMJIT_INLINE void zeroGp() noexcept { zero(kX86RegClassGp); }
|
|
ASMJIT_INLINE void zeroMm() noexcept { zero(kX86RegClassMm); }
|
|
ASMJIT_INLINE void zeroK() noexcept { zero(kX86RegClassK); }
|
|
ASMJIT_INLINE void zeroXyz() noexcept { zero(kX86RegClassXyz); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Set]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE void set(const X86RegMask& other) noexcept {
|
|
_packed = other._packed;
|
|
}
|
|
|
|
ASMJIT_INLINE void set(uint32_t rc, uint32_t mask) noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
|
|
switch (rc) {
|
|
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) noexcept { return set(kX86RegClassGp, mask); }
|
|
ASMJIT_INLINE void setMm(uint32_t mask) noexcept { return set(kX86RegClassMm, mask); }
|
|
ASMJIT_INLINE void setK(uint32_t mask) noexcept { return set(kX86RegClassK, mask); }
|
|
ASMJIT_INLINE void setXyz(uint32_t mask) noexcept { return set(kX86RegClassXyz, mask); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [And]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE void and_(const X86RegMask& other) noexcept {
|
|
_packed.and_(other._packed);
|
|
}
|
|
|
|
ASMJIT_INLINE void and_(uint32_t rc, uint32_t mask) noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
|
|
switch (rc) {
|
|
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) noexcept { and_(kX86RegClassGp, mask); }
|
|
ASMJIT_INLINE void andMm(uint32_t mask) noexcept { and_(kX86RegClassMm, mask); }
|
|
ASMJIT_INLINE void andK(uint32_t mask) noexcept { and_(kX86RegClassK, mask); }
|
|
ASMJIT_INLINE void andXyz(uint32_t mask) noexcept { and_(kX86RegClassXyz, mask); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [AndNot]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE void andNot(const X86RegMask& other) noexcept {
|
|
_packed.andNot(other._packed);
|
|
}
|
|
|
|
ASMJIT_INLINE void andNot(uint32_t rc, uint32_t mask) noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
|
|
switch (rc) {
|
|
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) noexcept { andNot(kX86RegClassGp, mask); }
|
|
ASMJIT_INLINE void andNotMm(uint32_t mask) noexcept { andNot(kX86RegClassMm, mask); }
|
|
ASMJIT_INLINE void andNotK(uint32_t mask) noexcept { andNot(kX86RegClassK, mask); }
|
|
ASMJIT_INLINE void andNotXyz(uint32_t mask) noexcept { andNot(kX86RegClassXyz, mask); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Or]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE void or_(const X86RegMask& other) noexcept {
|
|
_packed.or_(other._packed);
|
|
}
|
|
|
|
ASMJIT_INLINE void or_(uint32_t rc, uint32_t mask) noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
switch (rc) {
|
|
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) noexcept { return or_(kX86RegClassGp, mask); }
|
|
ASMJIT_INLINE void orMm(uint32_t mask) noexcept { return or_(kX86RegClassMm, mask); }
|
|
ASMJIT_INLINE void orK(uint32_t mask) noexcept { return or_(kX86RegClassK, mask); }
|
|
ASMJIT_INLINE void orXyz(uint32_t mask) noexcept { return or_(kX86RegClassXyz, mask); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Xor]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE void xor_(const X86RegMask& other) noexcept {
|
|
_packed.xor_(other._packed);
|
|
}
|
|
|
|
ASMJIT_INLINE void xor_(uint32_t rc, uint32_t mask) noexcept {
|
|
ASMJIT_ASSERT(rc < _kX86RegClassManagedCount);
|
|
|
|
switch (rc) {
|
|
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) noexcept { xor_(kX86RegClassGp, mask); }
|
|
ASMJIT_INLINE void xorMm(uint32_t mask) noexcept { xor_(kX86RegClassMm, mask); }
|
|
ASMJIT_INLINE void xorK(uint32_t mask) noexcept { xor_(kX86RegClassK, mask); }
|
|
ASMJIT_INLINE void xorXyz(uint32_t mask) noexcept { xor_(kX86RegClassXyz, mask); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Members]
|
|
// --------------------------------------------------------------------------
|
|
|
|
union {
|
|
struct {
|
|
//! GP registers mask (16 bits).
|
|
uint16_t _gp;
|
|
//! MMX 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::<Fake>Reg]
|
|
// ============================================================================
|
|
|
|
// This is only defined by `x86operand_regs.cpp` when exporting registers.
|
|
#if defined(ASMJIT_EXPORTS_X86_REGS)
|
|
|
|
// Remap all classes to POD structs so they can be statically initialized
|
|
// without calling a constructor. Compiler will store these in .DATA section.
|
|
//
|
|
// Kept in union to prevent LTO warnings.
|
|
class X86RipReg { public: union { Operand::VRegOp _vreg; }; };
|
|
class X86SegReg { public: union { Operand::VRegOp _vreg; }; };
|
|
class X86GpReg { public: union { Operand::VRegOp _vreg; }; };
|
|
class X86FpReg { public: union { Operand::VRegOp _vreg; }; };
|
|
class X86KReg { public: union { Operand::VRegOp _vreg; }; };
|
|
class X86MmReg { public: union { Operand::VRegOp _vreg; }; };
|
|
class X86XmmReg { public: union { Operand::VRegOp _vreg; }; };
|
|
class X86YmmReg { public: union { Operand::VRegOp _vreg; }; };
|
|
class X86ZmmReg { public: union { Operand::VRegOp _vreg; }; };
|
|
|
|
#else
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86Reg]
|
|
// ============================================================================
|
|
|
|
//! X86/X86 register base class.
|
|
class X86Reg : public Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy X86 register.
|
|
ASMJIT_INLINE X86Reg() noexcept : Reg() {}
|
|
//! Create a reference to `other` X86 register.
|
|
ASMJIT_INLINE X86Reg(const X86Reg& other) noexcept : Reg(other) {}
|
|
//! Create a reference to `other` X86 register and change the index to `index`.
|
|
ASMJIT_INLINE X86Reg(const X86Reg& other, uint32_t index) noexcept : Reg(other, index) {}
|
|
//! Create a custom X86 register.
|
|
ASMJIT_INLINE X86Reg(uint32_t type, uint32_t index, uint32_t size) noexcept : Reg(type, index, size) {}
|
|
//! Create non-initialized X86 register.
|
|
explicit ASMJIT_INLINE X86Reg(const _NoInit&) noexcept : Reg(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86Reg Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_REG_OP(X86Reg)
|
|
|
|
//! Get whether the register is a GP register (any size).
|
|
ASMJIT_INLINE bool isGp() const noexcept { return _vreg.type <= kX86RegTypeGpq; }
|
|
//! Get whether the register is a GPB register (8-bit).
|
|
ASMJIT_INLINE bool isGpb() const noexcept { return _vreg.type <= _kX86RegTypePatchedGpbHi; }
|
|
//! Get whether the register is a low GPB register (8-bit).
|
|
ASMJIT_INLINE bool isGpbLo() const noexcept { return _vreg.type == kX86RegTypeGpbLo; }
|
|
//! Get whether the register is a high GPB register (8-bit).
|
|
ASMJIT_INLINE bool isGpbHi() const noexcept { return _vreg.type == kX86RegTypeGpbHi; }
|
|
//! Get whether the register is a GPW register (16-bit).
|
|
ASMJIT_INLINE bool isGpw() const noexcept { return _vreg.type == kX86RegTypeGpw; }
|
|
//! Get whether the register is a GPD register (32-bit).
|
|
ASMJIT_INLINE bool isGpd() const noexcept { return _vreg.type == kX86RegTypeGpd; }
|
|
//! Get whether the register is a GPQ register (64-bit).
|
|
ASMJIT_INLINE bool isGpq() const noexcept { return _vreg.type == kX86RegTypeGpq; }
|
|
|
|
//! Get whether the register is an FPU register (80-bit).
|
|
ASMJIT_INLINE bool isFp() const noexcept { return _vreg.type == kX86RegTypeFp; }
|
|
//! Get whether the register is an MMX register (64-bit).
|
|
ASMJIT_INLINE bool isMm() const noexcept { return _vreg.type == kX86RegTypeMm; }
|
|
|
|
//! Get whether the register is a K register (64-bit).
|
|
ASMJIT_INLINE bool isK() const noexcept { return _vreg.type == kX86RegTypeK; }
|
|
|
|
//! Get whether the register is an XMM register (128-bit).
|
|
ASMJIT_INLINE bool isXmm() const noexcept { return _vreg.type == kX86RegTypeXmm; }
|
|
//! Get whether the register is a YMM register (256-bit).
|
|
ASMJIT_INLINE bool isYmm() const noexcept { return _vreg.type == kX86RegTypeYmm; }
|
|
//! Get whether the register is a ZMM register (512-bit).
|
|
ASMJIT_INLINE bool isZmm() const noexcept { return _vreg.type == kX86RegTypeZmm; }
|
|
|
|
//! Get whether the register is RIP.
|
|
ASMJIT_INLINE bool isRip() const noexcept { return _vreg.type == kX86RegTypeRip; }
|
|
//! Get whether the register is a segment register.
|
|
ASMJIT_INLINE bool isSeg() const noexcept { return _vreg.type == kX86RegTypeSeg; }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Statics]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get whether the `op` operand is low or high GPB register.
|
|
static ASMJIT_INLINE bool isGpbReg(const Operand& op) noexcept {
|
|
const uint32_t mask = Utils::pack32_2x8_1x16(
|
|
0xFF, 0xFF, ~(_kX86RegTypePatchedGpbHi << 8) & 0xFF00);
|
|
|
|
return (op._packed[0].u32[0] & mask) == Utils::pack32_2x8_1x16(kTypeReg, 1, 0x0000);
|
|
}
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86RipReg]
|
|
// ============================================================================
|
|
|
|
//! X86/X64 RIP register.
|
|
class X86RipReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a RIP register.
|
|
ASMJIT_INLINE X86RipReg() noexcept : X86Reg(kX86RegTypeRip, 0, 0) {}
|
|
//! Create a reference to `other` RIP register.
|
|
ASMJIT_INLINE X86RipReg(const X86RipReg& other) noexcept : X86Reg(other) {}
|
|
//! Create non-initialized RIP register.
|
|
explicit ASMJIT_INLINE X86RipReg(const _NoInit&) noexcept : X86Reg(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86RipReg Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_REG_OP(X86RipReg)
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86SegReg]
|
|
// ============================================================================
|
|
|
|
//! X86/X64 segment register.
|
|
class X86SegReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy segment register.
|
|
ASMJIT_INLINE X86SegReg() noexcept : X86Reg() {}
|
|
//! Create a reference to `other` segment register.
|
|
ASMJIT_INLINE X86SegReg(const X86SegReg& other) noexcept : X86Reg(other) {}
|
|
//! Create a reference to `other` segment register and change the index to `index`.
|
|
ASMJIT_INLINE X86SegReg(const X86SegReg& other, uint32_t index) noexcept : X86Reg(other, index) {}
|
|
//! Create a custom segment register.
|
|
ASMJIT_INLINE X86SegReg(uint32_t type, uint32_t index, uint32_t size) noexcept : X86Reg(type, index, size) {}
|
|
//! Create non-initialized segment register.
|
|
explicit ASMJIT_INLINE X86SegReg(const _NoInit&) noexcept : X86Reg(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86SegReg Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_REG_OP(X86SegReg)
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86GpReg]
|
|
// ============================================================================
|
|
|
|
//! X86/X64 general purpose register (GPB, GPW, GPD, GPQ).
|
|
class X86GpReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy Gp register.
|
|
ASMJIT_INLINE X86GpReg() noexcept : X86Reg() {}
|
|
//! Create a reference to `other` Gp register.
|
|
ASMJIT_INLINE X86GpReg(const X86GpReg& other) noexcept : X86Reg(other) {}
|
|
//! Create a reference to `other` Gp register and change the index to `index`.
|
|
ASMJIT_INLINE X86GpReg(const X86GpReg& other, uint32_t index) noexcept : X86Reg(other, index) {}
|
|
//! Create a custom Gp register.
|
|
ASMJIT_INLINE X86GpReg(uint32_t type, uint32_t index, uint32_t size) noexcept : X86Reg(type, index, size) {}
|
|
//! Create non-initialized Gp register.
|
|
explicit ASMJIT_INLINE X86GpReg(const _NoInit&) noexcept : X86Reg(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86GpReg Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_REG_OP(X86GpReg)
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86GpReg Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Cast this register to the same register type/size as `other`.
|
|
//!
|
|
//! This function has been designed to help with maintaining code that runs
|
|
//! in both 32-bit and 64-bit modes. If you have registers that have mixed
|
|
//! types, use `X86GpReg::as()` to cast one type to another.
|
|
ASMJIT_INLINE X86GpReg as(const X86GpReg& other) const noexcept {
|
|
return X86GpReg(other.getRegType(), getRegIndex(), other.getSize());
|
|
}
|
|
|
|
//! Cast this register to 8-bit (LO) part.
|
|
ASMJIT_INLINE X86GpReg r8() const noexcept { return X86GpReg(kX86RegTypeGpbLo, getRegIndex(), 1); }
|
|
//! Cast this register to 8-bit (LO) part.
|
|
ASMJIT_INLINE X86GpReg r8Lo() const noexcept { return X86GpReg(kX86RegTypeGpbLo, getRegIndex(), 1); }
|
|
//! Cast this register to 8-bit (HI) part.
|
|
ASMJIT_INLINE X86GpReg r8Hi() const noexcept { return X86GpReg(kX86RegTypeGpbHi, getRegIndex(), 1); }
|
|
|
|
//! Cast this register to 16-bit.
|
|
ASMJIT_INLINE X86GpReg r16() const noexcept { return X86GpReg(kX86RegTypeGpw, getRegIndex(), 2); }
|
|
//! Cast this register to 32-bit.
|
|
ASMJIT_INLINE X86GpReg r32() const noexcept { return X86GpReg(kX86RegTypeGpd, getRegIndex(), 4); }
|
|
//! Cast this register to 64-bit.
|
|
ASMJIT_INLINE X86GpReg r64() const noexcept { return X86GpReg(kX86RegTypeGpq, getRegIndex(), 8); }
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86FpReg]
|
|
// ============================================================================
|
|
|
|
//! X86/X64 80-bit Fp register.
|
|
class X86FpReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy Fp register.
|
|
ASMJIT_INLINE X86FpReg() noexcept : X86Reg() {}
|
|
//! Create a reference to `other` Fp register.
|
|
ASMJIT_INLINE X86FpReg(const X86FpReg& other) noexcept : X86Reg(other) {}
|
|
//! Create a reference to `other` Fp register and change the index to `index`.
|
|
ASMJIT_INLINE X86FpReg(const X86FpReg& other, uint32_t index) noexcept : X86Reg(other, index) {}
|
|
//! Create a custom Fp register.
|
|
ASMJIT_INLINE X86FpReg(uint32_t type, uint32_t index, uint32_t size) noexcept : X86Reg(type, index, size) {}
|
|
//! Create non-initialized Fp register.
|
|
explicit ASMJIT_INLINE X86FpReg(const _NoInit&) noexcept : 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 low DWORD and clears high DWORD.
|
|
//! - `movq` - writes 8-bytes in `QWORD`.
|
|
class X86MmReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy Mm register.
|
|
ASMJIT_INLINE X86MmReg() noexcept : X86Reg() {}
|
|
//! Create a reference to `other` Mm register.
|
|
ASMJIT_INLINE X86MmReg(const X86MmReg& other) noexcept : X86Reg(other) {}
|
|
//! Create a reference to `other` Mm register and change the index to `index`.
|
|
ASMJIT_INLINE X86MmReg(const X86MmReg& other, uint32_t index) noexcept : X86Reg(other, index) {}
|
|
//! Create a custom Mm register.
|
|
ASMJIT_INLINE X86MmReg(uint32_t type, uint32_t index, uint32_t size) noexcept : X86Reg(type, index, size) {}
|
|
//! Create non-initialized Mm register.
|
|
explicit ASMJIT_INLINE X86MmReg(const _NoInit&) noexcept : X86Reg(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86MmReg Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_REG_OP(X86MmReg)
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86KReg]
|
|
// ============================================================================
|
|
|
|
//! X86/X64 64-bit K register (AVX512+).
|
|
class X86KReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy K register.
|
|
ASMJIT_INLINE X86KReg() noexcept : X86Reg() {}
|
|
//! Create a reference to `other` K register.
|
|
ASMJIT_INLINE X86KReg(const X86KReg& other) noexcept : X86Reg(other) {}
|
|
//! Create a reference to `other` K register and change the index to `index`.
|
|
ASMJIT_INLINE X86KReg(const X86KReg& other, uint32_t index) noexcept : X86Reg(other, index) {}
|
|
//! Create a custom K register.
|
|
ASMJIT_INLINE X86KReg(uint32_t type, uint32_t index, uint32_t size) noexcept : X86Reg(type, index, size) {}
|
|
//! Create non-initialized K register.
|
|
explicit ASMJIT_INLINE X86KReg(const _NoInit&) noexcept : 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
|
|
//! +-----------------------------------------------+
|
|
//! | DQWORD |
|
|
//! +-----------------------+-----------------------+
|
|
//! | 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 clears the rest.
|
|
//! - `movq` - writes 8-bytes in low QWORD and clears the rest.
|
|
//! - `movq2dq` - writes 8 bytes in low QWORD and clears 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 low 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 DQWORD.
|
|
//!
|
|
//! - `movlps`,
|
|
//! `movlpd`,
|
|
//! `movhlps` - writes 8-bytes in low QWORD and keeps the rest untouched.
|
|
//!
|
|
//! - `movhps`,
|
|
//! `movhpd`,
|
|
//! `movlhps` - writes 8-bytes in high QWORD and keeps the rest untouched.
|
|
//!
|
|
//! - `movddup`,
|
|
//! - `movsldup`,
|
|
//! - `movshdup` - writes 16 bytes in DQWORD.
|
|
class X86XmmReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy XMM register.
|
|
ASMJIT_INLINE X86XmmReg() noexcept : X86Reg() {}
|
|
//! Create a reference to `other` XMM register.
|
|
ASMJIT_INLINE X86XmmReg(const X86XmmReg& other) noexcept : X86Reg(other) {}
|
|
//! Create a reference to `other` XMM register and change the index to `index`.
|
|
ASMJIT_INLINE X86XmmReg(const X86XmmReg& other, uint32_t index) noexcept : X86Reg(other, index) {}
|
|
//! Create a custom XMM register.
|
|
ASMJIT_INLINE X86XmmReg(uint32_t type, uint32_t index, uint32_t size) noexcept : X86Reg(type, index, size) {}
|
|
//! Create non-initialized XMM register.
|
|
explicit ASMJIT_INLINE X86XmmReg(const _NoInit&) noexcept : X86Reg(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86XmmReg Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_REG_OP(X86XmmReg)
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86XmmReg Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Cast this register to XMM (clone).
|
|
ASMJIT_INLINE X86XmmReg xmm() const noexcept { return X86XmmReg(kX86RegTypeXmm, getRegIndex(), 16); }
|
|
//! Cast this register to YMM.
|
|
ASMJIT_INLINE X86YmmReg ymm() const noexcept;
|
|
//! Cast this register to ZMM.
|
|
ASMJIT_INLINE X86ZmmReg zmm() const noexcept;
|
|
};
|
|
|
|
// ============================================================================
|
|
// [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|
|
|
//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
//! ~~~
|
|
class X86YmmReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy YMM register.
|
|
ASMJIT_INLINE X86YmmReg() noexcept : X86Reg() {}
|
|
//! Create a reference to `other` YMM register.
|
|
ASMJIT_INLINE X86YmmReg(const X86YmmReg& other) noexcept : X86Reg(other) {}
|
|
//! Create a reference to `other` YMM register and change the index to `index`.
|
|
ASMJIT_INLINE X86YmmReg(const X86YmmReg& other, uint32_t index) noexcept : X86Reg(other, index) {}
|
|
//! Create a custom YMM register.
|
|
ASMJIT_INLINE X86YmmReg(uint32_t type, uint32_t index, uint32_t size) noexcept : X86Reg(type, index, size) {}
|
|
//! Create non-initialized YMM register.
|
|
explicit ASMJIT_INLINE X86YmmReg(const _NoInit&) noexcept : X86Reg(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86YmmReg Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_REG_OP(X86YmmReg)
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86YmmReg Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Cast this register to XMM.
|
|
ASMJIT_INLINE X86XmmReg xmm() const noexcept{ return X86XmmReg(kX86RegTypeXmm, getRegIndex(), 16); }
|
|
//! Cast this register to YMM (clone).
|
|
ASMJIT_INLINE X86YmmReg ymm() const noexcept { return X86YmmReg(kX86RegTypeYmm, getRegIndex(), 32); }
|
|
//! Cast this register to ZMM.
|
|
ASMJIT_INLINE X86ZmmReg zmm() const noexcept;
|
|
};
|
|
|
|
ASMJIT_INLINE X86YmmReg X86XmmReg::ymm() const noexcept { return X86YmmReg(kX86RegTypeYmm, getRegIndex(), 32); }
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86ZmmReg]
|
|
// ============================================================================
|
|
|
|
//! X86/X64 512-bit ZMM register (AVX512+).
|
|
class X86ZmmReg : public X86Reg {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a dummy ZMM register.
|
|
ASMJIT_INLINE X86ZmmReg() noexcept : X86Reg() {}
|
|
//! Create a reference to `other` ZMM register.
|
|
ASMJIT_INLINE X86ZmmReg(const X86ZmmReg& other) noexcept : X86Reg(other) {}
|
|
//! Create a reference to `other` ZMM register and change the index to `index`.
|
|
ASMJIT_INLINE X86ZmmReg(const X86ZmmReg& other, uint32_t index) noexcept : X86Reg(other, index) {}
|
|
//! Create a custom ZMM register.
|
|
ASMJIT_INLINE X86ZmmReg(uint32_t type, uint32_t index, uint32_t size) noexcept : X86Reg(type, index, size) {}
|
|
//! Create non-initialized ZMM register.
|
|
explicit ASMJIT_INLINE X86ZmmReg(const _NoInit&) noexcept : X86Reg(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86ZmmReg Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_REG_OP(X86ZmmReg)
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86ZmmReg Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Cast this register to XMM.
|
|
ASMJIT_INLINE X86XmmReg xmm() const noexcept { return X86XmmReg(kX86RegTypeXmm, getRegIndex(), 16); }
|
|
//! Cast this register to YMM.
|
|
ASMJIT_INLINE X86YmmReg ymm() const noexcept { return X86YmmReg(kX86RegTypeYmm, getRegIndex(), 32); }
|
|
//! Cast this register to ZMM (clone).
|
|
ASMJIT_INLINE X86ZmmReg zmm() const noexcept { return X86ZmmReg(kX86RegTypeZmm, getRegIndex(), 64); }
|
|
};
|
|
|
|
ASMJIT_INLINE X86ZmmReg X86XmmReg::zmm() const noexcept { return X86ZmmReg(kX86RegTypeZmm, getRegIndex(), 64); }
|
|
ASMJIT_INLINE X86ZmmReg X86YmmReg::zmm() const noexcept { return X86ZmmReg(kX86RegTypeZmm, getRegIndex(), 64); }
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86Mem]
|
|
// ============================================================================
|
|
|
|
//! X86 memory operand.
|
|
class X86Mem : public BaseMem {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86Mem() noexcept : BaseMem(NoInit) {
|
|
reset();
|
|
}
|
|
|
|
ASMJIT_INLINE X86Mem(const Label& label, int32_t disp, uint32_t size = 0) noexcept : BaseMem(NoInit) {
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_UNUSED(rip);
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, size, kMemTypeRip, 0, kInvalidValue);
|
|
_init_packed_d2_d3(kInvalidValue, disp);
|
|
}
|
|
|
|
ASMJIT_INLINE X86Mem(const X86GpReg& base, int32_t disp, uint32_t size = 0) noexcept : BaseMem(NoInit) {
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(NoInit) {
|
|
ASMJIT_ASSERT(shift <= 3);
|
|
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept : BaseMem(other) {}
|
|
explicit ASMJIT_INLINE X86Mem(const _NoInit&) noexcept : BaseMem(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86Mem Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Clone X86Mem operand.
|
|
ASMJIT_INLINE X86Mem clone() const noexcept {
|
|
return X86Mem(*this);
|
|
}
|
|
|
|
//! Reset X86Mem operand.
|
|
ASMJIT_INLINE void reset() noexcept {
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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) noexcept {
|
|
_init_packed_op_sz_b0_b1_id(kTypeMem, 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 noexcept {
|
|
return (_vmem.flags & kX86MemSegMask) != (kX86SegDefault << kX86MemSegIndex);
|
|
}
|
|
|
|
//! Get memory operand segment, see `X86Seg`.
|
|
ASMJIT_INLINE uint32_t getSegment() const noexcept{
|
|
return (static_cast<uint32_t>(_vmem.flags) >> kX86MemSegIndex) & kX86MemSegBits;
|
|
}
|
|
|
|
//! Set memory operand segment, see `X86Seg`.
|
|
ASMJIT_INLINE X86Mem& setSegment(uint32_t segIndex) noexcept {
|
|
_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) noexcept {
|
|
return setSegment(seg.getRegIndex());
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Gpd]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get whether the memory operand has 32-bit GP base.
|
|
ASMJIT_INLINE bool hasGpdBase() const noexcept {
|
|
return (_packed[0].u32[0] & Utils::pack32_4x8(0x00, 0x00, 0x00, kX86MemGpdMask)) != 0;
|
|
}
|
|
|
|
//! Set whether the memory operand has 32-bit GP base.
|
|
ASMJIT_INLINE X86Mem& setGpdBase() noexcept {
|
|
_packed[0].u32[0] |= Utils::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) noexcept {
|
|
_packed[0].u32[0] &=~Utils::pack32_4x8(0x00, 0x00, 0x00, kX86MemGpdMask);
|
|
_packed[0].u32[0] |= Utils::pack32_4x8(0x00, 0x00, 0x00, b << kX86MemGpdIndex);
|
|
return *this;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [VSib]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get V-SIB type.
|
|
ASMJIT_INLINE uint32_t getVSib() const noexcept {
|
|
return (static_cast<uint32_t>(_vmem.flags) >> kX86MemVSibIndex) & kX86MemVSibBits;
|
|
}
|
|
|
|
//! Set V-SIB type.
|
|
ASMJIT_INLINE X86Mem& _setVSib(uint32_t vsib) noexcept {
|
|
_packed[0].u32[0] &=~Utils::pack32_4x8(0x00, 0x00, 0x00, kX86MemVSibMask);
|
|
_packed[0].u32[0] |= Utils::pack32_4x8(0x00, 0x00, 0x00, vsib << kX86MemVSibIndex);
|
|
return *this;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Size]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Set memory operand size.
|
|
ASMJIT_INLINE X86Mem& setSize(uint32_t size) noexcept {
|
|
_vmem.size = static_cast<uint8_t>(size);
|
|
return *this;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Base]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get whether the memory operand has base register.
|
|
ASMJIT_INLINE bool hasBase() const noexcept {
|
|
return _vmem.base != kInvalidValue;
|
|
}
|
|
|
|
//! Get memory operand base register code, variable id, or `kInvalidValue`.
|
|
ASMJIT_INLINE uint32_t getBase() const noexcept {
|
|
return _vmem.base;
|
|
}
|
|
|
|
//! Set memory operand base register code, variable id, or `kInvalidValue`.
|
|
ASMJIT_INLINE X86Mem& setBase(uint32_t base) noexcept {
|
|
_vmem.base = base;
|
|
return *this;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Index]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get whether the memory operand has index.
|
|
ASMJIT_INLINE bool hasIndex() const noexcept {
|
|
return _vmem.index != kInvalidValue;
|
|
}
|
|
|
|
//! Get memory operand index register code, variable id, or `kInvalidValue`.
|
|
ASMJIT_INLINE uint32_t getIndex() const noexcept {
|
|
return _vmem.index;
|
|
}
|
|
|
|
//! Set memory operand index register code, variable id, or `kInvalidValue`.
|
|
ASMJIT_INLINE X86Mem& setIndex(uint32_t index) noexcept {
|
|
_vmem.index = index;
|
|
return *this;
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86GpReg& index) noexcept {
|
|
_vmem.index = index.getRegIndex();
|
|
return _setVSib(kX86MemVSibGpz);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86GpReg& index, uint32_t shift) noexcept {
|
|
_vmem.index = index.getRegIndex();
|
|
return _setVSib(kX86MemVSibGpz).setShift(shift);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86XmmReg& index) noexcept {
|
|
_vmem.index = index.getRegIndex();
|
|
return _setVSib(kX86MemVSibXmm);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86XmmReg& index, uint32_t shift) noexcept {
|
|
_vmem.index = index.getRegIndex();
|
|
return _setVSib(kX86MemVSibXmm).setShift(shift);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86YmmReg& index) noexcept {
|
|
_vmem.index = index.getRegIndex();
|
|
return _setVSib(kX86MemVSibYmm);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86YmmReg& index, uint32_t shift) noexcept {
|
|
_vmem.index = index.getRegIndex();
|
|
return _setVSib(kX86MemVSibYmm).setShift(shift);
|
|
}
|
|
|
|
#if !defined(ASMJIT_DISABLE_COMPILER)
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86GpVar& index) noexcept {
|
|
_vmem.index = ASMJIT_OP_ID(index);
|
|
return _setVSib(kX86MemVSibGpz);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86GpVar& index, uint32_t shift) noexcept {
|
|
_vmem.index = ASMJIT_OP_ID(index);
|
|
return _setVSib(kX86MemVSibGpz).setShift(shift);
|
|
}
|
|
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86XmmVar& index) noexcept {
|
|
_vmem.index = ASMJIT_OP_ID(index);
|
|
return _setVSib(kX86MemVSibXmm);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86XmmVar& index, uint32_t shift) noexcept {
|
|
_vmem.index = ASMJIT_OP_ID(index);
|
|
return _setVSib(kX86MemVSibXmm).setShift(shift);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86YmmVar& index) noexcept {
|
|
_vmem.index = ASMJIT_OP_ID(index);
|
|
return _setVSib(kX86MemVSibYmm);
|
|
}
|
|
|
|
//! Set memory index.
|
|
ASMJIT_INLINE X86Mem& setIndex(const X86YmmVar& index, uint32_t shift) noexcept {
|
|
_vmem.index = ASMJIT_OP_ID(index);
|
|
return _setVSib(kX86MemVSibYmm).setShift(shift);
|
|
}
|
|
#endif // !ASMJIT_DISABLE_COMPILER
|
|
|
|
//! Reset memory index.
|
|
ASMJIT_INLINE X86Mem& resetIndex() noexcept {
|
|
_vmem.index = kInvalidValue;
|
|
return _setVSib(kX86MemVSibGpz);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Misc]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get whether the memory operand has base and index register.
|
|
ASMJIT_INLINE bool hasBaseOrIndex() const noexcept {
|
|
return _vmem.base != kInvalidValue || _vmem.index != kInvalidValue;
|
|
}
|
|
|
|
//! Get whether the memory operand has base and index register.
|
|
ASMJIT_INLINE bool hasBaseAndIndex() const noexcept {
|
|
return _vmem.base != kInvalidValue && _vmem.index != kInvalidValue;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Shift]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get whether the memory operand has shift used.
|
|
ASMJIT_INLINE bool hasShift() const noexcept {
|
|
return (_vmem.flags & kX86MemShiftMask) != 0;
|
|
}
|
|
|
|
//! Get memory operand index shift (0, 1, 2 or 3).
|
|
ASMJIT_INLINE uint32_t getShift() const noexcept {
|
|
return _vmem.flags >> kX86MemShiftIndex;
|
|
}
|
|
|
|
//! Set memory operand index shift (0, 1, 2 or 3).
|
|
ASMJIT_INLINE X86Mem& setShift(uint32_t shift) noexcept {
|
|
_packed[0].u32[0] &=~Utils::pack32_4x8(0x00, 0x00, 0x00, kX86MemShiftMask);
|
|
_packed[0].u32[0] |= Utils::pack32_4x8(0x00, 0x00, 0x00, shift << kX86MemShiftIndex);
|
|
return *this;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Displacement]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get memory operand relative displacement.
|
|
ASMJIT_INLINE int32_t getDisplacement() const noexcept {
|
|
return _vmem.displacement;
|
|
}
|
|
|
|
//! Set memory operand relative displacement.
|
|
ASMJIT_INLINE X86Mem& setDisplacement(int32_t disp) noexcept {
|
|
_vmem.displacement = disp;
|
|
return *this;
|
|
}
|
|
|
|
//! Reset memory operand relative displacement.
|
|
ASMJIT_INLINE X86Mem& resetDisplacement() noexcept {
|
|
_vmem.displacement = 0;
|
|
return *this;
|
|
}
|
|
|
|
//! Adjust memory operand relative displacement by `disp`.
|
|
ASMJIT_INLINE X86Mem& adjust(int32_t disp) noexcept {
|
|
_vmem.displacement += disp;
|
|
return *this;
|
|
}
|
|
|
|
//! Get new memory operand adjusted by `disp`.
|
|
ASMJIT_INLINE X86Mem adjusted(int32_t disp) const noexcept {
|
|
X86Mem result(*this);
|
|
result.adjust(disp);
|
|
return result;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Operator Overload]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86Mem& operator=(const X86Mem& other) noexcept {
|
|
_copy(other);
|
|
return *this;
|
|
}
|
|
|
|
ASMJIT_INLINE bool operator==(const X86Mem& other) const noexcept {
|
|
return (_packed[0] == other._packed[0]) && (_packed[1] == other._packed[1]) ;
|
|
}
|
|
|
|
ASMJIT_INLINE bool operator!=(const X86Mem& other) const noexcept {
|
|
return !(*this == other);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Statics]
|
|
// --------------------------------------------------------------------------
|
|
|
|
static ASMJIT_INLINE uint32_t _getGpdFlags(const Operand& base) noexcept {
|
|
return (base._vreg.size & 0x4) << (kX86MemGpdIndex - 2);
|
|
}
|
|
};
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86Var]
|
|
// ============================================================================
|
|
|
|
#if !defined(ASMJIT_DISABLE_COMPILER)
|
|
//! Base class for all X86 variables.
|
|
class X86Var : public Var {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a new uninitialized `X86Var` instance.
|
|
ASMJIT_INLINE X86Var() noexcept : Var(NoInit) { reset(); }
|
|
//! Create a clone of `other`.
|
|
ASMJIT_INLINE X86Var(const X86Var& other) noexcept : Var(other) {}
|
|
//! Create a new uninitialized `X86Var` instance (internal).
|
|
explicit ASMJIT_INLINE X86Var(const _NoInit&) noexcept : Var(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86Var Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Clone X86Var operand.
|
|
ASMJIT_INLINE X86Var clone() const noexcept { return X86Var(*this); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Type]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Get register type.
|
|
ASMJIT_INLINE uint32_t getRegType() const noexcept { return _vreg.type; }
|
|
//! Get variable type.
|
|
ASMJIT_INLINE uint32_t getVarType() const noexcept { return _vreg.vType; }
|
|
|
|
//! Get whether the variable is a general purpose register.
|
|
ASMJIT_INLINE bool isGp() const noexcept { return _vreg.type <= kX86RegTypeGpq; }
|
|
//! Get whether the variable is a GPB (8-bit) register.
|
|
ASMJIT_INLINE bool isGpb() const noexcept { return _vreg.type <= kX86RegTypeGpbHi; }
|
|
//! Get whether the variable is a low GPB (8-bit) register.
|
|
ASMJIT_INLINE bool isGpbLo() const noexcept { return _vreg.type == kX86RegTypeGpbLo; }
|
|
//! Get whether the variable is a high GPB (8-bit) register.
|
|
ASMJIT_INLINE bool isGpbHi() const noexcept { return _vreg.type == kX86RegTypeGpbHi; }
|
|
//! Get whether the variable is a GPW (16-bit) register.
|
|
ASMJIT_INLINE bool isGpw() const noexcept { return _vreg.type == kX86RegTypeGpw; }
|
|
//! Get whether the variable is a GPD (32-bit) register.
|
|
ASMJIT_INLINE bool isGpd() const noexcept { return _vreg.type == kX86RegTypeGpd; }
|
|
//! Get whether the variable is a GPQ (64-bit) register.
|
|
ASMJIT_INLINE bool isGpq() const noexcept { return _vreg.type == kX86RegTypeGpq; }
|
|
|
|
//! Get whether the variable is MMX (64-bit) register.
|
|
ASMJIT_INLINE bool isMm() const noexcept { return _vreg.type == kX86RegTypeMm; }
|
|
//! Get whether the variable is K (64-bit) register.
|
|
ASMJIT_INLINE bool isK() const noexcept { return _vreg.type == kX86RegTypeK; }
|
|
|
|
//! Get whether the variable is XMM (128-bit) register.
|
|
ASMJIT_INLINE bool isXmm() const noexcept { return _vreg.type == kX86RegTypeXmm; }
|
|
//! Get whether the variable is YMM (256-bit) register.
|
|
ASMJIT_INLINE bool isYmm() const noexcept { return _vreg.type == kX86RegTypeYmm; }
|
|
//! Get whether the variable is ZMM (512-bit) register.
|
|
ASMJIT_INLINE bool isZmm() const noexcept { return _vreg.type == kX86RegTypeZmm; }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Memory Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Cast this variable to a memory operand.
|
|
//!
|
|
//! NOTE: Size of operand depends on native variable type, you can use other
|
|
//! variants if you want specific one.
|
|
ASMJIT_INLINE X86Mem m(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, getSize());
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, getSize());
|
|
}
|
|
|
|
//! Cast this variable to 8-bit memory operand.
|
|
ASMJIT_INLINE X86Mem m8(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, 1);
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m8(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 1);
|
|
}
|
|
|
|
//! Cast this variable to 16-bit memory operand.
|
|
ASMJIT_INLINE X86Mem m16(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, 2);
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m16(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 2);
|
|
}
|
|
|
|
//! Cast this variable to 32-bit memory operand.
|
|
ASMJIT_INLINE X86Mem m32(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, 4);
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m32(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 4);
|
|
}
|
|
|
|
//! Cast this variable to 64-bit memory operand.
|
|
ASMJIT_INLINE X86Mem m64(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, 8);
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m64(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 8);
|
|
}
|
|
|
|
//! Cast this variable to 80-bit memory operand (long double).
|
|
ASMJIT_INLINE X86Mem m80(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, 10);
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m80(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 10);
|
|
}
|
|
|
|
//! Cast this variable to 128-bit memory operand.
|
|
ASMJIT_INLINE X86Mem m128(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, 16);
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m128(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 16);
|
|
}
|
|
|
|
//! Cast this variable to 256-bit memory operand.
|
|
ASMJIT_INLINE X86Mem m256(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, 32);
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m256(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 32);
|
|
}
|
|
|
|
//! Cast this variable to 256-bit memory operand.
|
|
ASMJIT_INLINE X86Mem m512(int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, disp, 64);
|
|
}
|
|
|
|
//! \overload
|
|
ASMJIT_INLINE X86Mem m512(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const noexcept {
|
|
return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 64);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Operator Overload]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86Var& operator=(const X86Var& other) noexcept {
|
|
_copy(other);
|
|
return *this;
|
|
}
|
|
|
|
ASMJIT_INLINE bool operator==(const X86Var& other) const noexcept {
|
|
return _packed[0] == other._packed[0];
|
|
}
|
|
|
|
ASMJIT_INLINE bool operator!=(const X86Var& other) const noexcept {
|
|
return _packed[0] != other._packed[0];
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Private]
|
|
// --------------------------------------------------------------------------
|
|
|
|
protected:
|
|
ASMJIT_INLINE X86Var(const X86Var& other, uint32_t reg, uint32_t size) noexcept : Var(NoInit) {
|
|
_init_packed_op_sz_w0_id(kTypeVar, size, (reg << 8) + other._vreg.index, other._base.id);
|
|
_vreg.vType = other._vreg.vType;
|
|
}
|
|
};
|
|
#endif // !ASMJIT_DISABLE_COMPILER
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86GpVar]
|
|
// ============================================================================
|
|
|
|
#if !defined(ASMJIT_DISABLE_COMPILER)
|
|
//! Gp variable.
|
|
class X86GpVar : public X86Var {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
protected:
|
|
ASMJIT_INLINE X86GpVar(const X86GpVar& other, uint32_t reg, uint32_t size) noexcept
|
|
: X86Var(other, reg, size) {}
|
|
|
|
public:
|
|
//! Create a new uninitialized `X86GpVar` instance.
|
|
ASMJIT_INLINE X86GpVar() noexcept : X86Var() {}
|
|
//! Create a clone of `other`.
|
|
ASMJIT_INLINE X86GpVar(const X86GpVar& other) noexcept : X86Var(other) {}
|
|
//! Create a new uninitialized `X86GpVar` instance (internal).
|
|
explicit ASMJIT_INLINE X86GpVar(const _NoInit&) noexcept : X86Var(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86GpVar Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Clone X86GpVar operand.
|
|
ASMJIT_INLINE X86GpVar clone() const noexcept { return X86GpVar(*this); }
|
|
//! Reset X86GpVar operand.
|
|
ASMJIT_INLINE void reset() noexcept { X86Var::reset(); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86GpVar Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Cast this variable to the same register type/size as `other`.
|
|
//!
|
|
//! This function has been designed to help with maintaining code that runs
|
|
//! in both 32-bit and 64-bit modes. If you have variables that have mixed
|
|
//! types, use `X86GpVar::as()` to cast one type to another.
|
|
ASMJIT_INLINE X86GpVar as(const X86GpVar& other) const noexcept {
|
|
return X86GpVar(*this, other.getRegType(), other.getSize());
|
|
}
|
|
|
|
//! Cast this variable to 8-bit (LO) part of variable.
|
|
ASMJIT_INLINE X86GpVar r8() const noexcept { return X86GpVar(*this, kX86RegTypeGpbLo, 1); }
|
|
//! Cast this variable to 8-bit (LO) part of variable.
|
|
ASMJIT_INLINE X86GpVar r8Lo() const noexcept { return X86GpVar(*this, kX86RegTypeGpbLo, 1); }
|
|
//! Cast this variable to 8-bit (HI) part of variable.
|
|
ASMJIT_INLINE X86GpVar r8Hi() const noexcept { return X86GpVar(*this, kX86RegTypeGpbHi, 1); }
|
|
|
|
//! Cast this variable to 16-bit part of variable.
|
|
ASMJIT_INLINE X86GpVar r16() const noexcept { return X86GpVar(*this, kX86RegTypeGpw, 2); }
|
|
//! Cast this variable to 32-bit part of variable.
|
|
ASMJIT_INLINE X86GpVar r32() const noexcept { return X86GpVar(*this, kX86RegTypeGpd, 4); }
|
|
//! Cast this variable to 64-bit part of variable.
|
|
ASMJIT_INLINE X86GpVar r64() const noexcept { return X86GpVar(*this, kX86RegTypeGpq, 8); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Operator Overload]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86GpVar& operator=(const X86GpVar& other) noexcept { _copy(other); return *this; }
|
|
|
|
ASMJIT_INLINE bool operator==(const X86GpVar& other) const noexcept { return X86Var::operator==(other); }
|
|
ASMJIT_INLINE bool operator!=(const X86GpVar& other) const noexcept { return X86Var::operator!=(other); }
|
|
};
|
|
#endif // !ASMJIT_DISABLE_COMPILER
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86MmVar]
|
|
// ============================================================================
|
|
|
|
#if !defined(ASMJIT_DISABLE_COMPILER)
|
|
//! Mm variable.
|
|
class X86MmVar : public X86Var {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Create a new uninitialized `X86MmVar` instance.
|
|
ASMJIT_INLINE X86MmVar() noexcept : X86Var() {}
|
|
//! Create a clone of `other`.
|
|
ASMJIT_INLINE X86MmVar(const X86MmVar& other) noexcept : X86Var(other) {}
|
|
|
|
//! Create a new uninitialized `X86MmVar` instance (internal).
|
|
explicit ASMJIT_INLINE X86MmVar(const _NoInit&) noexcept : X86Var(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86MmVar Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Clone X86MmVar operand.
|
|
ASMJIT_INLINE X86MmVar clone() const noexcept { return X86MmVar(*this); }
|
|
//! Reset X86MmVar operand.
|
|
ASMJIT_INLINE void reset() noexcept { X86Var::reset(); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Operator Overload]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86MmVar& operator=(const X86MmVar& other) noexcept { _copy(other); return *this; }
|
|
|
|
ASMJIT_INLINE bool operator==(const X86MmVar& other) const noexcept { return X86Var::operator==(other); }
|
|
ASMJIT_INLINE bool operator!=(const X86MmVar& other) const noexcept { return X86Var::operator!=(other); }
|
|
};
|
|
#endif // !ASMJIT_DISABLE_COMPILER
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86XmmVar]
|
|
// ============================================================================
|
|
|
|
#if !defined(ASMJIT_DISABLE_COMPILER)
|
|
//! XMM variable.
|
|
class X86XmmVar : public X86Var {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
protected:
|
|
ASMJIT_INLINE X86XmmVar(const X86Var& other, uint32_t reg, uint32_t size) noexcept
|
|
: X86Var(other, reg, size) {}
|
|
|
|
friend class X86YmmVar;
|
|
friend class X86ZmmVar;
|
|
|
|
public:
|
|
//! Create a new uninitialized `X86XmmVar` instance.
|
|
ASMJIT_INLINE X86XmmVar() noexcept : X86Var() {}
|
|
//! Create a clone of `other`.
|
|
ASMJIT_INLINE X86XmmVar(const X86XmmVar& other) noexcept : X86Var(other) {}
|
|
//! Create a new uninitialized `X86XmmVar` instance (internal).
|
|
explicit ASMJIT_INLINE X86XmmVar(const _NoInit&) noexcept : X86Var(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86XmmVar Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Clone X86XmmVar operand.
|
|
ASMJIT_INLINE X86XmmVar clone() const noexcept { return X86XmmVar(*this); }
|
|
//! Reset X86XmmVar operand.
|
|
ASMJIT_INLINE void reset() noexcept { X86Var::reset(); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86XmmVar Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86XmmVar xmm() const noexcept { return X86XmmVar(*this); }
|
|
ASMJIT_INLINE X86YmmVar ymm() const noexcept;
|
|
ASMJIT_INLINE X86ZmmVar zmm() const noexcept;
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Operator Overload]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86XmmVar& operator=(const X86XmmVar& other) noexcept { _copy(other); return *this; }
|
|
|
|
ASMJIT_INLINE bool operator==(const X86XmmVar& other) const noexcept { return X86Var::operator==(other); }
|
|
ASMJIT_INLINE bool operator!=(const X86XmmVar& other) const noexcept { return X86Var::operator!=(other); }
|
|
};
|
|
#endif // !ASMJIT_DISABLE_COMPILER
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86YmmVar]
|
|
// ============================================================================
|
|
|
|
#if !defined(ASMJIT_DISABLE_COMPILER)
|
|
//! YMM variable.
|
|
class X86YmmVar : public X86Var {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
protected:
|
|
ASMJIT_INLINE X86YmmVar(const X86Var& other, uint32_t reg, uint32_t size) noexcept
|
|
: X86Var(other, reg, size) {}
|
|
|
|
friend class X86XmmVar;
|
|
friend class X86ZmmVar;
|
|
|
|
public:
|
|
//! Create a new uninitialized `X86YmmVar` instance.
|
|
ASMJIT_INLINE X86YmmVar() noexcept : X86Var() {}
|
|
//! Create a clone of `other`.
|
|
ASMJIT_INLINE X86YmmVar(const X86YmmVar& other) noexcept : X86Var(other) {}
|
|
//! Create a new uninitialized `X86YmmVar` instance (internal).
|
|
explicit ASMJIT_INLINE X86YmmVar(const _NoInit&) noexcept : X86Var(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86YmmVar Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Clone X86YmmVar operand.
|
|
ASMJIT_INLINE X86YmmVar clone() const noexcept { return X86YmmVar(*this); }
|
|
//! Reset X86YmmVar operand.
|
|
ASMJIT_INLINE void reset() noexcept { X86Var::reset(); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86YmmVar Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86XmmVar xmm() const noexcept { return X86XmmVar(*this, kX86RegTypeXmm, 8); }
|
|
ASMJIT_INLINE X86YmmVar ymm() const noexcept { return X86YmmVar(*this); }
|
|
ASMJIT_INLINE X86ZmmVar zmm() const noexcept;
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Operator Overload]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86YmmVar& operator=(const X86YmmVar& other) noexcept { _copy(other); return *this; }
|
|
|
|
ASMJIT_INLINE bool operator==(const X86YmmVar& other) const noexcept { return X86Var::operator==(other); }
|
|
ASMJIT_INLINE bool operator!=(const X86YmmVar& other) const noexcept { return X86Var::operator!=(other); }
|
|
};
|
|
|
|
ASMJIT_INLINE X86YmmVar X86XmmVar::ymm() const noexcept { return X86YmmVar(*this, kX86RegTypeYmm, 16); }
|
|
#endif // !ASMJIT_DISABLE_COMPILER
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86ZmmVar]
|
|
// ============================================================================
|
|
|
|
#if !defined(ASMJIT_DISABLE_COMPILER)
|
|
//! ZMM variable.
|
|
class X86ZmmVar : public X86Var {
|
|
public:
|
|
// --------------------------------------------------------------------------
|
|
// [Construction / Destruction]
|
|
// --------------------------------------------------------------------------
|
|
|
|
protected:
|
|
ASMJIT_INLINE X86ZmmVar(const X86Var& other, uint32_t reg, uint32_t size) noexcept
|
|
: X86Var(other, reg, size) {}
|
|
|
|
friend class X86XmmVar;
|
|
friend class X86YmmVar;
|
|
|
|
public:
|
|
//! Create a new uninitialized `X86ZmmVar` instance.
|
|
ASMJIT_INLINE X86ZmmVar() noexcept : X86Var() {}
|
|
//! Create a clone of `other`.
|
|
ASMJIT_INLINE X86ZmmVar(const X86ZmmVar& other) noexcept : X86Var(other) {}
|
|
//! Create a new uninitialized `X86ZmmVar` instance (internal).
|
|
explicit ASMJIT_INLINE X86ZmmVar(const _NoInit&) noexcept : X86Var(NoInit) {}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86ZmmVar Specific]
|
|
// --------------------------------------------------------------------------
|
|
|
|
//! Clone X86ZmmVar operand.
|
|
ASMJIT_INLINE X86ZmmVar clone() const noexcept { return X86ZmmVar(*this); }
|
|
//! Reset X86ZmmVar operand.
|
|
ASMJIT_INLINE void reset() noexcept { X86Var::reset(); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [X86ZmmVar Cast]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86XmmVar xmm() const noexcept { return X86XmmVar(*this, kX86RegTypeYmm, 8); }
|
|
ASMJIT_INLINE X86YmmVar ymm() const noexcept { return X86YmmVar(*this, kX86RegTypeYmm, 16); }
|
|
ASMJIT_INLINE X86ZmmVar zmm() const noexcept { return X86ZmmVar(*this); }
|
|
|
|
// --------------------------------------------------------------------------
|
|
// [Operator Overload]
|
|
// --------------------------------------------------------------------------
|
|
|
|
ASMJIT_INLINE X86ZmmVar& operator=(const X86ZmmVar& other) noexcept { _copy(other); return *this; }
|
|
|
|
ASMJIT_INLINE bool operator==(const X86ZmmVar& other) const noexcept { return X86Var::operator==(other); }
|
|
ASMJIT_INLINE bool operator!=(const X86ZmmVar& other) const noexcept { return X86Var::operator!=(other); }
|
|
};
|
|
|
|
ASMJIT_INLINE X86ZmmVar X86XmmVar::zmm() const noexcept { return X86ZmmVar(*this, kX86RegTypeZmm, 32); }
|
|
ASMJIT_INLINE X86ZmmVar X86YmmVar::zmm() const noexcept { return X86ZmmVar(*this, kX86RegTypeZmm, 32); }
|
|
#endif // !ASMJIT_DISABLE_COMPILER
|
|
#endif
|
|
|
|
// ============================================================================
|
|
// [asmjit::X86RegData]
|
|
// ============================================================================
|
|
|
|
struct X86RegData {
|
|
X86GpReg gpd[16];
|
|
X86GpReg gpq[16];
|
|
|
|
X86GpReg gpbLo[16];
|
|
X86GpReg gpbHi[4];
|
|
X86GpReg gpw[16];
|
|
|
|
X86XmmReg xmm[32];
|
|
X86YmmReg ymm[32];
|
|
X86ZmmReg zmm[32];
|
|
|
|
X86KReg k[8];
|
|
X86FpReg fp[8];
|
|
X86MmReg mm[8];
|
|
|
|
X86SegReg seg[7];
|
|
|
|
X86GpReg noGp;
|
|
X86RipReg rip;
|
|
};
|
|
ASMJIT_VARAPI const X86RegData x86RegData;
|
|
|
|
// ============================================================================
|
|
// [asmjit::x86]
|
|
// ============================================================================
|
|
|
|
// The macro is only defined by `x86operand_regs.cpp` when exporting registers.
|
|
#if !defined(ASMJIT_EXPORTS_X86_REGS)
|
|
|
|
namespace x86 {
|
|
|
|
// ============================================================================
|
|
// [asmjit::x86 - Reg]
|
|
// ============================================================================
|
|
|
|
#define ASMJIT_DEF_REG(_Type_, _Name_, _Field_) \
|
|
static const _Type_& _Name_ = x86RegData._Field_;
|
|
|
|
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(X86GpReg , al , gpbLo[0]) //!< 8-bit low GPB register.
|
|
ASMJIT_DEF_REG(X86GpReg , cl , gpbLo[1]) //!< 8-bit low GPB register.
|
|
ASMJIT_DEF_REG(X86GpReg , dl , gpbLo[2]) //!< 8-bit low GPB register.
|
|
ASMJIT_DEF_REG(X86GpReg , bl , gpbLo[3]) //!< 8-bit low GPB register.
|
|
ASMJIT_DEF_REG(X86GpReg , spl , gpbLo[4]) //!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , bpl , gpbLo[5]) //!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , sil , gpbLo[6]) //!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , dil , gpbLo[7]) //!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , r8b , gpbLo[8]) //!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , r9b , gpbLo[9]) //!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , r10b , gpbLo[10])//!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , r11b , gpbLo[11])//!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , r12b , gpbLo[12])//!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , r13b , gpbLo[13])//!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , r14b , gpbLo[14])//!< 8-bit low GPB register (X64).
|
|
ASMJIT_DEF_REG(X86GpReg , r15b , gpbLo[15])//!< 8-bit low GPB register (X64).
|
|
|
|
ASMJIT_DEF_REG(X86GpReg , ah , gpbHi[0]) //!< 8-bit high GPB register.
|
|
ASMJIT_DEF_REG(X86GpReg , ch , gpbHi[1]) //!< 8-bit high GPB register.
|
|
ASMJIT_DEF_REG(X86GpReg , dh , gpbHi[2]) //!< 8-bit high GPB register.
|
|
ASMJIT_DEF_REG(X86GpReg , bh , gpbHi[3]) //!< 8-bit high GPB 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(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+).
|
|
|
|
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(X86FpReg , fp0 , fp[0]) //!< 80-bit FPU register.
|
|
ASMJIT_DEF_REG(X86FpReg , fp1 , fp[1]) //!< 80-bit FPU register.
|
|
ASMJIT_DEF_REG(X86FpReg , fp2 , fp[2]) //!< 80-bit FPU register.
|
|
ASMJIT_DEF_REG(X86FpReg , fp3 , fp[3]) //!< 80-bit FPU register.
|
|
ASMJIT_DEF_REG(X86FpReg , fp4 , fp[4]) //!< 80-bit FPU register.
|
|
ASMJIT_DEF_REG(X86FpReg , fp5 , fp[5]) //!< 80-bit FPU register.
|
|
ASMJIT_DEF_REG(X86FpReg , fp6 , fp[6]) //!< 80-bit FPU register.
|
|
ASMJIT_DEF_REG(X86FpReg , fp7 , fp[7]) //!< 80-bit FPU register.
|
|
|
|
ASMJIT_DEF_REG(X86MmReg , mm0 , mm[0]) //!< 64-bit MMX register.
|
|
ASMJIT_DEF_REG(X86MmReg , mm1 , mm[1]) //!< 64-bit MMX register.
|
|
ASMJIT_DEF_REG(X86MmReg , mm2 , mm[2]) //!< 64-bit MMX register.
|
|
ASMJIT_DEF_REG(X86MmReg , mm3 , mm[3]) //!< 64-bit MMX register.
|
|
ASMJIT_DEF_REG(X86MmReg , mm4 , mm[4]) //!< 64-bit MMX register.
|
|
ASMJIT_DEF_REG(X86MmReg , mm5 , mm[5]) //!< 64-bit MMX register.
|
|
ASMJIT_DEF_REG(X86MmReg , mm6 , mm[6]) //!< 64-bit MMX register.
|
|
ASMJIT_DEF_REG(X86MmReg , mm7 , mm[7]) //!< 64-bit MMX register.
|
|
|
|
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 , noGpReg, noGp) //!< No GP register (for `X86Mem` operand).
|
|
ASMJIT_DEF_REG(X86RipReg, rip, rip) //!< RIP register.
|
|
|
|
#undef ASMJIT_DEF_REG
|
|
|
|
//! Create 8-bit low GPB register operand.
|
|
static ASMJIT_INLINE X86GpReg gpb_lo(uint32_t index) noexcept { return X86GpReg(kX86RegTypeGpbLo, index, 1); }
|
|
//! Create 8-bit high GPB register operand.
|
|
static ASMJIT_INLINE X86GpReg gpb_hi(uint32_t index) noexcept { return X86GpReg(kX86RegTypeGpbHi, index, 1); }
|
|
//! Create 16-bit GPW register operand.
|
|
static ASMJIT_INLINE X86GpReg gpw(uint32_t index) noexcept { return X86GpReg(kX86RegTypeGpw, index, 2); }
|
|
//! Create 32-bit GPD register operand.
|
|
static ASMJIT_INLINE X86GpReg gpd(uint32_t index) noexcept { return X86GpReg(kX86RegTypeGpd, index, 4); }
|
|
//! Create 64-bit GPQ register operand (X64).
|
|
static ASMJIT_INLINE X86GpReg gpq(uint32_t index) noexcept { return X86GpReg(kX86RegTypeGpq, index, 8); }
|
|
//! Create 80-bit Fp register operand.
|
|
static ASMJIT_INLINE X86FpReg fp(uint32_t index) noexcept { return X86FpReg(kX86RegTypeFp, index, 10); }
|
|
//! Create 64-bit Mm register operand.
|
|
static ASMJIT_INLINE X86MmReg mm(uint32_t index) noexcept { return X86MmReg(kX86RegTypeMm, index, 8); }
|
|
//! Create 64-bit K register operand.
|
|
static ASMJIT_INLINE X86KReg k(uint32_t index) noexcept { return X86KReg(kX86RegTypeK, index, 8); }
|
|
//! Create 128-bit XMM register operand.
|
|
static ASMJIT_INLINE X86XmmReg xmm(uint32_t index) noexcept { return X86XmmReg(kX86RegTypeXmm, index, 16); }
|
|
//! Create 256-bit YMM register operand.
|
|
static ASMJIT_INLINE X86YmmReg ymm(uint32_t index) noexcept { return X86YmmReg(kX86RegTypeYmm, index, 32); }
|
|
//! Create 512-bit ZMM register operand.
|
|
static ASMJIT_INLINE X86ZmmReg zmm(uint32_t index) noexcept { 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) noexcept {
|
|
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) noexcept {
|
|
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) noexcept {
|
|
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) noexcept {
|
|
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) noexcept {
|
|
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) noexcept { \
|
|
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) noexcept {
|
|
return X86Mem(rip_, disp, size);
|
|
}
|
|
|
|
//! Create `[p + disp]` absolute memory operand with no/custom size information.
|
|
ASMJIT_API X86Mem ptr_abs(Ptr p, int32_t disp = 0, uint32_t size = 0) noexcept;
|
|
//! Create `[p + (index.reg << shift) + disp]` absolute memory operand with no/custom size information.
|
|
ASMJIT_API X86Mem ptr_abs(Ptr p, const X86Reg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) noexcept;
|
|
|
|
//! \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) noexcept { \
|
|
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) noexcept { \
|
|
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) noexcept { \
|
|
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) noexcept { \
|
|
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) noexcept { \
|
|
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) noexcept { \
|
|
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) noexcept { \
|
|
return ptr(rip_, disp, size); \
|
|
} \
|
|
/*! Create `[p + disp]` memory operand. */ \
|
|
static ASMJIT_INLINE X86Mem prefix##_ptr##_abs(Ptr p, int32_t disp = 0) noexcept { \
|
|
return ptr_abs(p, disp, size); \
|
|
} \
|
|
/*! Create `[p + (index.reg << shift) + disp]` memory operand. */ \
|
|
static ASMJIT_INLINE X86Mem prefix##_ptr##_abs(Ptr p, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) noexcept { \
|
|
return ptr_abs(p, index, shift, disp, size); \
|
|
} \
|
|
/*! Create `[p + (xmm.reg << shift) + disp]` memory operand. */ \
|
|
static ASMJIT_INLINE X86Mem prefix##_ptr##_abs(Ptr p, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0) noexcept { \
|
|
return ptr_abs(p, index, shift, disp, size); \
|
|
} \
|
|
/*! Create `[p + (ymm.reg << shift) + disp]` memory operand. */ \
|
|
static ASMJIT_INLINE X86Mem prefix##_ptr##_abs(Ptr p, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0) noexcept { \
|
|
return ptr_abs(p, 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) noexcept {
|
|
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) noexcept {
|
|
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) noexcept {
|
|
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) noexcept {
|
|
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) noexcept { \
|
|
return X86Mem(label, index, shift, disp, size); \
|
|
}
|
|
|
|
//! Create `[p + (index.var << shift) + disp]` absolute memory operand with no/custom size information.
|
|
ASMJIT_API X86Mem ptr_abs(Ptr p, const X86Var& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) noexcept;
|
|
|
|
//! \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) noexcept { \
|
|
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) noexcept { \
|
|
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) noexcept { \
|
|
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) noexcept { \
|
|
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) noexcept { \
|
|
return ptr(label, index, shift, disp, size); \
|
|
} \
|
|
/*! Create `[p + (index.var << shift) + disp]` memory operand. */ \
|
|
static ASMJIT_INLINE X86Mem prefix##_ptr##_abs(Ptr p, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) noexcept { \
|
|
return ptr_abs(p, reinterpret_cast<const X86Var&>(index), shift, disp, size); \
|
|
} \
|
|
/*! Create `[p + (xmm.var << shift) + disp]` memory operand. */ \
|
|
static ASMJIT_INLINE X86Mem prefix##_ptr##_abs(Ptr p, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0) noexcept { \
|
|
return ptr_abs(p, reinterpret_cast<const X86Var&>(index), shift, disp, size); \
|
|
} \
|
|
/*! Create `[p + (ymm.var << shift) + disp]` memory operand. */ \
|
|
static ASMJIT_INLINE X86Mem prefix##_ptr##_abs(Ptr p, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0) noexcept { \
|
|
return ptr_abs(p, 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
|
|
|
|
} // x86 namespace
|
|
|
|
#endif // !ASMJIT_EXPORTS_X86_REGS
|
|
|
|
//! \}
|
|
|
|
} // asmjit namespace
|
|
|
|
// [Cleanup]
|
|
#undef ASMJIT_OP_ID
|
|
|
|
// [Api-End]
|
|
#include "../apiend.h"
|
|
|
|
// [Guard]
|
|
#endif // _ASMJIT_X86_X86OPERAND_H
|