mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-18 13:04:36 +03:00
Added more memory addressing types to Mem operand
This commit is contained in:
@@ -90,20 +90,20 @@ struct Operand_ {
|
||||
kSignatureMemBaseIndexMask = kSignatureMemBaseIndexBits << kSignatureMemBaseIndexShift,
|
||||
|
||||
// Memory should be encoded as absolute immediate (X86|X64).
|
||||
// |........|........|..X.....|........|
|
||||
kSignatureMemAbsoluteShift = 13,
|
||||
kSignatureMemAbsoluteBits = 0x01U,
|
||||
kSignatureMemAbsoluteFlag = kSignatureMemAbsoluteBits << kSignatureMemAbsoluteShift,
|
||||
// |........|........|.XX.....|........|
|
||||
kSignatureMemAddrTypeShift = 13,
|
||||
kSignatureMemAddrTypeBits = 0x03U,
|
||||
kSignatureMemAddrTypeMask = kSignatureMemAddrTypeBits << kSignatureMemAddrTypeShift,
|
||||
|
||||
// This memory operand represents a function argument's stack location (CodeCompiler)
|
||||
// |........|........|.X......|........|
|
||||
kSignatureMemArgHomeShift = 14,
|
||||
kSignatureMemArgHomeShift = 15,
|
||||
kSignatureMemArgHomeBits = 0x01U,
|
||||
kSignatureMemArgHomeFlag = kSignatureMemArgHomeBits << kSignatureMemArgHomeShift,
|
||||
|
||||
// This memory operand represents a virtual register's home-slot (CodeCompiler).
|
||||
// |........|........|X.......|........|
|
||||
kSignatureMemRegHomeShift = 15,
|
||||
kSignatureMemRegHomeShift = 16,
|
||||
kSignatureMemRegHomeBits = 0x01U,
|
||||
kSignatureMemRegHomeFlag = kSignatureMemRegHomeBits << kSignatureMemRegHomeShift
|
||||
};
|
||||
@@ -243,16 +243,12 @@ struct Operand_ {
|
||||
//! Improper use of `setSignature()` can lead to hard-to-debug errors.
|
||||
ASMJIT_INLINE void setSignature(uint32_t signature) noexcept { _signature = signature; }
|
||||
|
||||
ASMJIT_INLINE bool _hasSignatureData(uint32_t bits) const noexcept {
|
||||
return (_signature & bits) != 0;
|
||||
}
|
||||
ASMJIT_INLINE bool _hasSignatureData(uint32_t bits) const noexcept { return (_signature & bits) != 0; }
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Unpacks information from operand's signature.
|
||||
ASMJIT_INLINE uint32_t _getSignatureData(uint32_t bits, uint32_t shift) const noexcept {
|
||||
return (_signature >> shift) & bits;
|
||||
}
|
||||
ASMJIT_INLINE uint32_t _getSignatureData(uint32_t bits, uint32_t shift) const noexcept { return (_signature >> shift) & bits; }
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
@@ -264,6 +260,9 @@ struct Operand_ {
|
||||
|
||||
ASMJIT_INLINE void _addSignatureData(uint32_t data) noexcept { _signature |= data; }
|
||||
|
||||
//! Clears specified bits in operand's signature.
|
||||
ASMJIT_INLINE void _clearSignatureData(uint32_t bits, uint32_t shift) noexcept { _signature &= ~(bits << shift); }
|
||||
|
||||
//! Get type of the operand, see \ref OpType.
|
||||
ASMJIT_INLINE uint32_t getOp() const noexcept { return _getSignatureData(kSignatureOpBits, kSignatureOpShift); }
|
||||
//! Get if the operand is none (\ref kOpNone).
|
||||
@@ -818,6 +817,20 @@ public:
|
||||
//! prefix and index shift (scale).
|
||||
class Mem : public Operand {
|
||||
public:
|
||||
enum AddrType {
|
||||
kAddrTypeDefault = 0,
|
||||
kAddrTypeAbs = 1,
|
||||
kAddrTypeRel = 2,
|
||||
kAddrTypeWrt = 3
|
||||
};
|
||||
|
||||
// Shortcuts.
|
||||
enum SignatureMem {
|
||||
kSignatureMemAbs = kAddrTypeAbs << kSignatureMemAddrTypeShift,
|
||||
kSignatureMemRel = kAddrTypeRel << kSignatureMemAddrTypeShift,
|
||||
kSignatureMemWrt = kAddrTypeWrt << kSignatureMemAddrTypeShift
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -854,15 +867,25 @@ public:
|
||||
_init_packed_d2_d3(0, 0);
|
||||
}
|
||||
|
||||
ASMJIT_INLINE bool isAbs() const noexcept { return _hasSignatureData(kSignatureMemAbsoluteFlag); }
|
||||
ASMJIT_INLINE bool hasAddrType() const noexcept { return _hasSignatureData(kSignatureMemAddrTypeMask); }
|
||||
ASMJIT_INLINE uint32_t getAddrType() const noexcept { return _getSignatureData(kSignatureMemAddrTypeBits, kSignatureMemAddrTypeShift); }
|
||||
ASMJIT_INLINE void setAddrType(uint32_t addrType) noexcept { return _setSignatureData(addrType, kSignatureMemAddrTypeBits, kSignatureMemAddrTypeShift); }
|
||||
ASMJIT_INLINE void resetAddrType() noexcept { return _clearSignatureData(kSignatureMemAddrTypeBits, kSignatureMemAddrTypeShift); }
|
||||
|
||||
ASMJIT_INLINE bool isAbs() const noexcept { return getAddrType() == kAddrTypeAbs; }
|
||||
ASMJIT_INLINE bool isRel() const noexcept { return getAddrType() == kAddrTypeRel; }
|
||||
ASMJIT_INLINE bool isWrt() const noexcept { return getAddrType() == kAddrTypeWrt; }
|
||||
|
||||
ASMJIT_INLINE void setAbs() noexcept { setAddrType(kAddrTypeAbs); }
|
||||
ASMJIT_INLINE void setRel() noexcept { setAddrType(kAddrTypeRel); }
|
||||
ASMJIT_INLINE void setWrt() noexcept { setAddrType(kAddrTypeWrt); }
|
||||
|
||||
ASMJIT_INLINE bool isArgHome() const noexcept { return _hasSignatureData(kSignatureMemArgHomeFlag); }
|
||||
ASMJIT_INLINE bool isRegHome() const noexcept { return _hasSignatureData(kSignatureMemRegHomeFlag); }
|
||||
|
||||
ASMJIT_INLINE void setAbs() noexcept { _signature |= kSignatureMemAbsoluteFlag; }
|
||||
ASMJIT_INLINE void setArgHome() noexcept { _signature |= kSignatureMemArgHomeFlag; }
|
||||
ASMJIT_INLINE void setRegHome() noexcept { _signature |= kSignatureMemRegHomeFlag; }
|
||||
|
||||
ASMJIT_INLINE void clearAbs() noexcept { _signature &= ~kSignatureMemAbsoluteFlag; }
|
||||
ASMJIT_INLINE void clearArgHome() noexcept { _signature &= ~kSignatureMemArgHomeFlag; }
|
||||
ASMJIT_INLINE void clearRegHome() noexcept { _signature &= ~kSignatureMemRegHomeFlag; }
|
||||
|
||||
@@ -873,46 +896,28 @@ public:
|
||||
//! Get whether the memory operand has BASE and INDEX register.
|
||||
ASMJIT_INLINE bool hasBaseOrIndex() const noexcept { return (_signature & kSignatureMemBaseIndexMask) != 0; }
|
||||
//! Get whether the memory operand has BASE and INDEX register.
|
||||
ASMJIT_INLINE bool hasBaseAndIndex() const noexcept {
|
||||
return (_signature & kSignatureMemBaseTypeMask) != 0 &&
|
||||
(_signature & kSignatureMemIndexTypeMask) != 0;
|
||||
}
|
||||
ASMJIT_INLINE bool hasBaseAndIndex() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0 && (_signature & kSignatureMemIndexTypeMask) != 0; }
|
||||
|
||||
//! Get if the BASE operand is a register.
|
||||
ASMJIT_INLINE bool hasBaseReg() const noexcept {
|
||||
// Registers start after kLabelTag.
|
||||
return (_signature & kSignatureMemBaseTypeMask) > (Label::kLabelTag << kSignatureMemBaseTypeShift);
|
||||
}
|
||||
//! Get if the BASE operand is a register (registers start after `kLabelTag`).
|
||||
ASMJIT_INLINE bool hasBaseReg() const noexcept { return (_signature & kSignatureMemBaseTypeMask) > (Label::kLabelTag << kSignatureMemBaseTypeShift); }
|
||||
//! Get if the BASE operand is a label.
|
||||
ASMJIT_INLINE bool hasBaseLabel() const noexcept {
|
||||
return (_signature & kSignatureMemBaseTypeMask) == (Label::kLabelTag << kSignatureMemBaseTypeShift);
|
||||
}
|
||||
|
||||
//! Get if the INDEX operand is a register.
|
||||
ASMJIT_INLINE bool hasIndexReg() const noexcept {
|
||||
// Registers start after kLabelTag.
|
||||
return (_signature & kSignatureMemIndexTypeMask) > (Label::kLabelTag << kSignatureMemIndexTypeShift);
|
||||
}
|
||||
ASMJIT_INLINE bool hasBaseLabel() const noexcept { return (_signature & kSignatureMemBaseTypeMask) == (Label::kLabelTag << kSignatureMemBaseTypeShift); }
|
||||
//! Get if the INDEX operand is a register (registers start after `kLabelTag`).
|
||||
ASMJIT_INLINE bool hasIndexReg() const noexcept { return (_signature & kSignatureMemIndexTypeMask) > (Label::kLabelTag << kSignatureMemIndexTypeShift); }
|
||||
|
||||
//! Get type of a BASE register (0 if this memory operand doesn't use the BASE register).
|
||||
//!
|
||||
//! NOTE: If the returned type is one (a value never associated to a register
|
||||
//! type) the BASE is not register, but it's a label. One equals to `kLabelTag`.
|
||||
//! You should always check `hasBaseLabel()` before using `getBaseId()` result.
|
||||
ASMJIT_INLINE uint32_t getBaseType() const noexcept {
|
||||
return _getSignatureData(kSignatureMemBaseTypeBits, kSignatureMemBaseTypeShift);
|
||||
}
|
||||
ASMJIT_INLINE uint32_t getBaseType() const noexcept { return _getSignatureData(kSignatureMemBaseTypeBits, kSignatureMemBaseTypeShift); }
|
||||
//! Get type of an INDEX register (0 if this memory operand doesn't use the INDEX register).
|
||||
ASMJIT_INLINE uint32_t getIndexType() const noexcept {
|
||||
return _getSignatureData(kSignatureMemIndexTypeBits, kSignatureMemIndexTypeShift);
|
||||
}
|
||||
ASMJIT_INLINE uint32_t getIndexType() const noexcept { return _getSignatureData(kSignatureMemIndexTypeBits, kSignatureMemIndexTypeShift); }
|
||||
|
||||
//! Get both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a single integer.
|
||||
//!
|
||||
//! This is used internally for BASE+INDEX validation.
|
||||
ASMJIT_INLINE uint32_t getBaseIndexType() const noexcept {
|
||||
return _getSignatureData(kSignatureMemBaseIndexBits, kSignatureMemBaseIndexShift);
|
||||
}
|
||||
ASMJIT_INLINE uint32_t getBaseIndexType() const noexcept { return _getSignatureData(kSignatureMemBaseIndexBits, kSignatureMemBaseIndexShift); }
|
||||
|
||||
//! Get id of the BASE register or label (if the BASE was specified as label).
|
||||
ASMJIT_INLINE uint32_t getBaseId() const noexcept { return _mem.base; }
|
||||
|
||||
@@ -161,8 +161,6 @@ namespace asmjit {
|
||||
|
||||
template<typename This>
|
||||
struct X86EmitterExplicitT {
|
||||
ASMJIT_INLINE X86EmitterExplicitT() noexcept {}
|
||||
|
||||
// These typedefs are used to describe implicit operands passed explicitly.
|
||||
typedef X86Gp AL;
|
||||
typedef X86Gp AH;
|
||||
@@ -279,12 +277,12 @@ struct X86EmitterExplicitT {
|
||||
//! \overload
|
||||
ASMJIT_INLINE X86Mem intptr_ptr_abs(uint64_t base) const noexcept {
|
||||
uint32_t nativeGpSize = static_cast<const This*>(this)->getGpSize();
|
||||
return X86Mem(base, nativeGpSize, Mem::kSignatureMemAbsoluteFlag);
|
||||
return X86Mem(base, nativeGpSize, Mem::kSignatureMemAbs);
|
||||
}
|
||||
//! \overload
|
||||
ASMJIT_INLINE X86Mem intptr_ptr_abs(uint64_t base, const X86Gp& index, uint32_t shift = 0) const noexcept {
|
||||
uint32_t nativeGpSize = static_cast<const This*>(this)->getGpSize();
|
||||
return X86Mem(base, index, shift, nativeGpSize, Mem::kSignatureMemAbsoluteFlag);
|
||||
return X86Mem(base, index, shift, nativeGpSize, Mem::kSignatureMemAbs);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -5097,9 +5095,7 @@ struct X86EmitterImplicitT : public X86EmitterExplicitT<This> {
|
||||
//! NOTE: This class cannot be created, you can only cast to it and use it as
|
||||
//! emitter that emits to either X86Assembler, X86Builder, or X86Compiler (use
|
||||
//! with caution with X86Compiler as it expects virtual registers to be used).
|
||||
class X86Emitter
|
||||
: public CodeEmitter,
|
||||
public X86EmitterImplicitT<X86Emitter> {
|
||||
class X86Emitter : public CodeEmitter, public X86EmitterImplicitT<X86Emitter> {
|
||||
ASMJIT_NONCONSTRUCTIBLE(X86Emitter)
|
||||
};
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@ class X86Mem : public Mem {
|
||||
public:
|
||||
//! Additional bits of operand's signature used by `X86Mem`.
|
||||
ASMJIT_ENUM(AdditionalBits) {
|
||||
kSignatureMemShiftShift = 16,
|
||||
kSignatureMemShiftShift = 19,
|
||||
kSignatureMemShiftBits = 0x03U,
|
||||
kSignatureMemShiftMask = kSignatureMemShiftBits << kSignatureMemShiftShift,
|
||||
|
||||
kSignatureMemSegmentShift = 18,
|
||||
kSignatureMemSegmentShift = 21,
|
||||
kSignatureMemSegmentBits = 0x07U,
|
||||
kSignatureMemSegmentMask = kSignatureMemSegmentBits << kSignatureMemSegmentShift
|
||||
};
|
||||
@@ -1052,7 +1052,7 @@ static ASMJIT_INLINE X86Mem ptr(uint64_t base, const X86Vec& index, uint32_t shi
|
||||
} \
|
||||
/*! Create a `[base + (vec_index << shift) + offset]` memory operand. */ \
|
||||
static ASMJIT_INLINE X86Mem FUNC(uint64_t base, const X86Vec& index, uint32_t shift = 0) noexcept { \
|
||||
return X86Mem(base, index, shift, SIZE, Mem::kSignatureMemAbsoluteFlag); \
|
||||
return X86Mem(base, index, shift, SIZE, Mem::kSignatureMemAbs); \
|
||||
} \
|
||||
/*! Create a `[base + offset]` memory operand. */ \
|
||||
static ASMJIT_INLINE X86Mem FUNC##_abs(uint64_t base) noexcept { \
|
||||
@@ -1060,17 +1060,18 @@ static ASMJIT_INLINE X86Mem ptr(uint64_t base, const X86Vec& index, uint32_t shi
|
||||
} \
|
||||
/*! Create a `[base + (index << shift) + offset]` memory operand. */ \
|
||||
static ASMJIT_INLINE X86Mem FUNC##_abs(uint64_t base, const X86Gp& index, uint32_t shift = 0) noexcept { \
|
||||
return X86Mem(base, index, shift, SIZE, Mem::kSignatureMemAbsoluteFlag); \
|
||||
return X86Mem(base, index, shift, SIZE, Mem::kSignatureMemAbs); \
|
||||
} \
|
||||
/*! Create a `[base + (vec_index << shift) + offset]` memory operand. */ \
|
||||
static ASMJIT_INLINE X86Mem FUNC##_abs(uint64_t base, const X86Vec& index, uint32_t shift = 0) noexcept { \
|
||||
return X86Mem(base, index, shift, SIZE, Mem::kSignatureMemAbsoluteFlag); \
|
||||
return X86Mem(base, index, shift, SIZE, Mem::kSignatureMemAbs); \
|
||||
}
|
||||
|
||||
// Define memory operand constructors that use platform independent naming.
|
||||
ASMJIT_X86_PTR_FN(ptr_8, 1)
|
||||
ASMJIT_X86_PTR_FN(ptr_16, 2)
|
||||
ASMJIT_X86_PTR_FN(ptr_32, 4)
|
||||
ASMJIT_X86_PTR_FN(ptr_48, 6)
|
||||
ASMJIT_X86_PTR_FN(ptr_64, 8)
|
||||
ASMJIT_X86_PTR_FN(ptr_80, 10)
|
||||
ASMJIT_X86_PTR_FN(ptr_128, 16)
|
||||
|
||||
Reference in New Issue
Block a user