mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-16 20:17:05 +03:00
Added support for lo12 label operation
This commit is contained in:
@@ -17,6 +17,41 @@ ASMJIT_BEGIN_SUB_NAMESPACE(arm)
|
||||
//! \addtogroup asmjit_arm
|
||||
//! \{
|
||||
|
||||
//! Data type that can be encoded with the instruction (AArch32 only).
|
||||
enum class DataType : uint32_t {
|
||||
//! No data type specified (default for all general purpose instructions).
|
||||
kNone = 0,
|
||||
//! 8-bit signed integer, specified as `.s8` in assembly.
|
||||
kS8 = 1,
|
||||
//! 16-bit signed integer, specified as `.s16` in assembly.
|
||||
kS16 = 2,
|
||||
//! 32-bit signed integer, specified as `.s32` in assembly.
|
||||
kS32 = 3,
|
||||
//! 64-bit signed integer, specified as `.s64` in assembly.
|
||||
kS64 = 4,
|
||||
//! 8-bit unsigned integer, specified as `.u8` in assembly.
|
||||
kU8 = 5,
|
||||
//! 16-bit unsigned integer, specified as `.u16` in assembly.
|
||||
kU16 = 6,
|
||||
//! 32-bit unsigned integer, specified as `.u32` in assembly.
|
||||
kU32 = 7,
|
||||
//! 64-bit unsigned integer, specified as `.u64` in assembly.
|
||||
kU64 = 8,
|
||||
//! 16-bit floating point (half precision), specified as `.f16` in assembly.
|
||||
kF16 = 10,
|
||||
//! 32-bit floating point (single precision), specified as `.f32` in assembly.
|
||||
kF32 = 11,
|
||||
//! 64-bit floating point (double precision), specified as `.f64` in assembly.
|
||||
kF64 = 12,
|
||||
//! 8-bit polynomial.
|
||||
kP8 = 13,
|
||||
//! 64-bit polynomial.
|
||||
kP64 = 15,
|
||||
|
||||
//! Maximum value of `DataType`.
|
||||
kMaxValue = 15
|
||||
};
|
||||
|
||||
//! Condition code (both AArch32 & AArch64).
|
||||
//!
|
||||
//! \note This enumeration doesn't match condition code that is used in AArch32/AArch64 opcodes. In general this
|
||||
@@ -75,41 +110,6 @@ enum class CondCode : uint8_t {
|
||||
//! Negates a condition code.
|
||||
static inline constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); }
|
||||
|
||||
//! Data type that can be encoded with the instruction (AArch32 only).
|
||||
enum class DataType : uint32_t {
|
||||
//! No data type specified (default for all general purpose instructions).
|
||||
kNone = 0,
|
||||
//! 8-bit signed integer, specified as `.s8` in assembly.
|
||||
kS8 = 1,
|
||||
//! 16-bit signed integer, specified as `.s16` in assembly.
|
||||
kS16 = 2,
|
||||
//! 32-bit signed integer, specified as `.s32` in assembly.
|
||||
kS32 = 3,
|
||||
//! 64-bit signed integer, specified as `.s64` in assembly.
|
||||
kS64 = 4,
|
||||
//! 8-bit unsigned integer, specified as `.u8` in assembly.
|
||||
kU8 = 5,
|
||||
//! 16-bit unsigned integer, specified as `.u16` in assembly.
|
||||
kU16 = 6,
|
||||
//! 32-bit unsigned integer, specified as `.u32` in assembly.
|
||||
kU32 = 7,
|
||||
//! 64-bit unsigned integer, specified as `.u64` in assembly.
|
||||
kU64 = 8,
|
||||
//! 16-bit floating point (half precision), specified as `.f16` in assembly.
|
||||
kF16 = 10,
|
||||
//! 32-bit floating point (single precision), specified as `.f32` in assembly.
|
||||
kF32 = 11,
|
||||
//! 64-bit floating point (double precision), specified as `.f64` in assembly.
|
||||
kF64 = 12,
|
||||
//! 8-bit polynomial.
|
||||
kP8 = 13,
|
||||
//! 64-bit polynomial.
|
||||
kP64 = 15,
|
||||
|
||||
//! Maximum value of `DataType`.
|
||||
kMaxValue = 15
|
||||
};
|
||||
|
||||
//! Shift operation predicate (ARM) describes either SHIFT or EXTEND operation.
|
||||
//!
|
||||
//! \note The constants are AsmJit specific. The first 5 values describe real constants on ARM32 and AArch64 hardware,
|
||||
|
||||
@@ -47,7 +47,7 @@ enum class RegType : uint8_t {
|
||||
//! No register - unused, invalid, multiple meanings.
|
||||
kNone = 0,
|
||||
|
||||
//! This is not a register type. This value is reserved for a \ref Label that used in \ref BaseMem as a base.
|
||||
//! This is not a register type. This value is reserved for a \ref Label used in \ref BaseMem as a base.
|
||||
//!
|
||||
//! Label tag is used as a sub-type, forming a unique signature across all operand types as 0x1 is never associated
|
||||
//! with any register type. This means that a memory operand's BASE register can be constructed from virtually any
|
||||
@@ -217,6 +217,18 @@ ASMJIT_DEFINE_ENUM_COMPARE(RegGroup)
|
||||
|
||||
typedef Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kMaxVirt> RegGroupVirtValues;
|
||||
|
||||
//! Label operation type.
|
||||
//!
|
||||
//! Operation type describes how a \ref Label should be used to calculate an instruction immediate value, typically
|
||||
//! used in places that require relocations.
|
||||
enum class LabelOp : uint32_t {
|
||||
//! No operation specified, \ref Label encoding is determined by the instruction.
|
||||
kNone = 0u,
|
||||
|
||||
//! Low 12 bits of the Label's absolute address are used as an immediate value (AArch64).
|
||||
kAArch64_Lo12 = 1u
|
||||
};
|
||||
|
||||
//! Operand signature is a 32-bit number describing \ref Operand and some of its payload.
|
||||
//!
|
||||
//! In AsmJit operand signature is used to store additional payload of register, memory, and immediate operands.
|
||||
@@ -273,6 +285,11 @@ struct OperandSignature {
|
||||
kPredicateShift = 20,
|
||||
kPredicateMask = 0x0Fu << kPredicateShift,
|
||||
|
||||
// Predicate used by either registers or immediate values (4 bits).
|
||||
// |....XXXX|........|........|........|
|
||||
kLabelOpShift = 24,
|
||||
kLabelOpMask = 0x0Fu << kLabelOpShift,
|
||||
|
||||
// Operand size (8 most significant bits).
|
||||
// |XXXXXXXX|........|........|........|
|
||||
kSizeShift = 24,
|
||||
@@ -382,6 +399,8 @@ struct OperandSignature {
|
||||
inline constexpr uint32_t predicate() const noexcept { return getField<kPredicateMask>(); }
|
||||
inline constexpr uint32_t size() const noexcept { return getField<kSizeMask>(); }
|
||||
|
||||
inline constexpr LabelOp labelOp() const noexcept { return LabelOp(getField<kLabelOpMask>()); }
|
||||
|
||||
inline void setOpType(OperandType opType) noexcept { setField<kOpTypeMask>(uint32_t(opType)); }
|
||||
inline void setRegType(RegType regType) noexcept { setField<kRegTypeMask>(uint32_t(regType)); }
|
||||
inline void setRegGroup(RegGroup regGroup) noexcept { setField<kRegGroupMask>(uint32_t(regGroup)); }
|
||||
@@ -392,6 +411,8 @@ struct OperandSignature {
|
||||
inline void setPredicate(uint32_t predicate) noexcept { setField<kPredicateMask>(predicate); }
|
||||
inline void setSize(uint32_t size) noexcept { setField<kSizeMask>(size); }
|
||||
|
||||
inline void setLabelOp(LabelOp op) noexcept { setField<kLabelOpMask>(uint32_t(op)); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Static Constructors
|
||||
@@ -438,6 +459,10 @@ struct OperandSignature {
|
||||
return OperandSignature{size << kSizeShift};
|
||||
}
|
||||
|
||||
static inline constexpr OperandSignature fromLabelOp(LabelOp labelOp) noexcept {
|
||||
return OperandSignature{uint32_t(labelOp) << kLabelOpShift};
|
||||
}
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -763,10 +788,18 @@ public:
|
||||
inline constexpr Label(const Label& other) noexcept
|
||||
: Operand(other) {}
|
||||
|
||||
//! Creates a cloned label operand of `other`, but with \ref LabelOp set to `op`.
|
||||
inline constexpr Label(const Label& other, LabelOp op) noexcept
|
||||
: Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel) | Signature::fromLabelOp(op), other.id(), 0, 0) {}
|
||||
|
||||
//! Creates a label operand of the given `id`.
|
||||
inline constexpr explicit Label(uint32_t id) noexcept
|
||||
: Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), id, 0, 0) {}
|
||||
|
||||
//! Creates a label operand of the given `id`.
|
||||
inline constexpr Label(uint32_t id, LabelOp op) noexcept
|
||||
: Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel) | Signature::fromLabelOp(op), id, 0, 0) {}
|
||||
|
||||
inline explicit Label(Globals::NoInit_) noexcept
|
||||
: Operand(Globals::NoInit) {}
|
||||
|
||||
@@ -795,6 +828,16 @@ public:
|
||||
//! Sets the label `id`.
|
||||
inline void setId(uint32_t id) noexcept { _baseId = id; }
|
||||
|
||||
//! Returns \ref LabelOp associated with this label.
|
||||
inline LabelOp op() const noexcept { return _signature.labelOp(); }
|
||||
//! Tests whether the label has associated \ref LabelOp.
|
||||
inline bool hasOp() const noexcept { return _signature.labelOp() != LabelOp::kNone; }
|
||||
//! Sets \ref LabelOp to be associated with this label.
|
||||
inline void setOp(LabelOp op) noexcept { _signature.setLabelOp(op); }
|
||||
|
||||
//! Returns a new \ref Label with associated \ref LabelOp::kAArch64_Lo12.
|
||||
inline Label lo12() const noexcept { return Label(*this, LabelOp::kAArch64_Lo12); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -1392,7 +1435,7 @@ public:
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Type of the an immediate value.
|
||||
//! Type of an immediate value.
|
||||
enum class ImmType : uint32_t {
|
||||
//! Immediate is integer.
|
||||
kInt = 0,
|
||||
|
||||
Reference in New Issue
Block a user