Added support for lo12 label operation

This commit is contained in:
kobalicek
2023-05-06 13:38:03 +02:00
parent bb47dc3ede
commit f21f4a4ba2
2 changed files with 80 additions and 37 deletions

View File

@@ -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,

View File

@@ -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,