[ABI] Moved vector operand from arm to a64 namespace

This is unfortunately API/ABI break, which cannot be deprecated
instead of removed as arm::Vec would collide with a64::Vec if present.

This is a preparetion for ARM32 tooling.
This commit is contained in:
kobalicek
2023-12-27 02:26:36 +01:00
parent b25df5554d
commit f27334eaf8
6 changed files with 244 additions and 214 deletions

View File

@@ -16,6 +16,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64)
class GpW; class GpW;
class GpX; class GpX;
class VecB;
class VecH;
class VecS;
class VecD;
class VecV;
//! General purpose register (AArch64). //! General purpose register (AArch64).
class Gp : public Reg { class Gp : public Reg {
public: public:
@@ -25,9 +31,9 @@ public:
enum Id : uint32_t { enum Id : uint32_t {
//! Register that depends on OS, could be used as TLS offset. //! Register that depends on OS, could be used as TLS offset.
kIdOs = 18, kIdOs = 18,
//! Frame pointer. //! Frame pointer register id.
kIdFp = 29, kIdFp = 29,
//! Link register. //! Link register id.
kIdLr = 30, kIdLr = 30,
//! Stack register id. //! Stack register id.
kIdSp = 31, kIdSp = 31,
@@ -63,18 +69,211 @@ ASMJIT_INLINE_NODEBUG GpW Gp::w() const noexcept { return GpW(id()); }
ASMJIT_INLINE_NODEBUG GpX Gp::x() const noexcept { return GpX(id()); } ASMJIT_INLINE_NODEBUG GpX Gp::x() const noexcept { return GpX(id()); }
#endif #endif
//! Vector register (AArch64).
class Vec : public BaseVec {
public:
ASMJIT_DEFINE_ABSTRACT_REG(Vec, BaseVec)
//! Element type (AArch64 only).
enum ElementType : uint32_t {
//! No element type specified.
kElementTypeNone = 0,
//! Byte elements (B8 or B16).
kElementTypeB,
//! Halfword elements (H4 or H8).
kElementTypeH,
//! Singleword elements (S2 or S4).
kElementTypeS,
//! Doubleword elements (D2).
kElementTypeD,
//! Byte elements grouped by 4 bytes (B4).
//!
//! \note This element-type is only used by few instructions.
kElementTypeB4,
//! Halfword elements grouped by 2 halfwords (H2).
//!
//! \note This element-type is only used by few instructions.
kElementTypeH2,
//! Count of element types.
kElementTypeCount
};
//! \cond
//! Shortcuts.
enum SignatureReg : uint32_t {
kSignatureElementB = kElementTypeB << kSignatureRegElementTypeShift,
kSignatureElementH = kElementTypeH << kSignatureRegElementTypeShift,
kSignatureElementS = kElementTypeS << kSignatureRegElementTypeShift,
kSignatureElementD = kElementTypeD << kSignatureRegElementTypeShift,
kSignatureElementB4 = kElementTypeB4 << kSignatureRegElementTypeShift,
kSignatureElementH2 = kElementTypeH2 << kSignatureRegElementTypeShift
};
//! \endcond
//! Returns whether the register has associated an element type.
ASMJIT_INLINE_NODEBUG constexpr bool hasElementType() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask>(); }
//! Returns whether the register has element index (it's an element index access).
ASMJIT_INLINE_NODEBUG constexpr bool hasElementIndex() const noexcept { return _signature.hasField<kSignatureRegElementFlagMask>(); }
//! Returns whether the register has element type or element index (or both).
ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask | kSignatureRegElementFlagMask>(); }
//! Returns element type of the register.
ASMJIT_INLINE_NODEBUG constexpr uint32_t elementType() const noexcept { return _signature.getField<kSignatureRegElementTypeMask>(); }
//! Sets element type of the register to `elementType`.
ASMJIT_INLINE_NODEBUG void setElementType(uint32_t elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(elementType); }
//! Resets element type to none.
ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); }
//! Returns element index of the register.
ASMJIT_INLINE_NODEBUG constexpr uint32_t elementIndex() const noexcept { return _signature.getField<kSignatureRegElementIndexMask>(); }
//! Sets element index of the register to `elementType`.
ASMJIT_INLINE_NODEBUG void setElementIndex(uint32_t elementIndex) noexcept {
_signature |= kSignatureRegElementFlagMask;
_signature.setField<kSignatureRegElementIndexMask>(elementIndex);
}
//! Resets element index of the register.
ASMJIT_INLINE_NODEBUG void resetElementIndex() noexcept {
_signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask);
}
ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2); }
//! Creates a cloned register with element access.
ASMJIT_INLINE_NODEBUG Vec at(uint32_t elementIndex) const noexcept {
return Vec((signature() & ~kSignatureRegElementIndexMask) | (elementIndex << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id());
}
//! Cast this register to an 8-bit B register (AArch64 only).
ASMJIT_INLINE_NODEBUG VecB b() const noexcept;
//! Cast this register to a 16-bit H register (AArch64 only).
ASMJIT_INLINE_NODEBUG VecH h() const noexcept;
//! Cast this register to a 32-bit S register.
ASMJIT_INLINE_NODEBUG VecS s() const noexcept;
//! Cast this register to a 64-bit D register.
ASMJIT_INLINE_NODEBUG VecD d() const noexcept;
//! Cast this register to a 128-bit Q register.
ASMJIT_INLINE_NODEBUG VecV q() const noexcept;
//! Cast this register to a 128-bit V register.
ASMJIT_INLINE_NODEBUG VecV v() const noexcept;
//! Cast this register to a 128-bit V.B[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV b(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.H[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV h(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.S[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV s(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.D[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV d(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.H2[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV h2(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.B4[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV b4(uint32_t elementIndex) const noexcept;
//! Cast this register to V.8B.
ASMJIT_INLINE_NODEBUG VecD b8() const noexcept;
//! Cast this register to V.16B.
ASMJIT_INLINE_NODEBUG VecV b16() const noexcept;
//! Cast this register to V.2H.
ASMJIT_INLINE_NODEBUG VecS h2() const noexcept;
//! Cast this register to V.4H.
ASMJIT_INLINE_NODEBUG VecD h4() const noexcept;
//! Cast this register to V.8H.
ASMJIT_INLINE_NODEBUG VecV h8() const noexcept;
//! Cast this register to V.2S.
ASMJIT_INLINE_NODEBUG VecD s2() const noexcept;
//! Cast this register to V.4S.
ASMJIT_INLINE_NODEBUG VecV s4() const noexcept;
//! Cast this register to V.2D.
ASMJIT_INLINE_NODEBUG VecV d2() const noexcept;
static ASMJIT_INLINE_NODEBUG constexpr OperandSignature _makeElementAccessSignature(uint32_t elementType, uint32_t elementIndex) noexcept {
return OperandSignature{
uint32_t(RegTraits<RegType::kARM_VecV>::kSignature) |
uint32_t(kSignatureRegElementFlagMask) |
uint32_t(elementType << kSignatureRegElementTypeShift) |
uint32_t(elementIndex << kSignatureRegElementIndexShift)};
}
};
//! 8-bit view (S) of VFP/SIMD register.
class VecB : public Vec {
public:
ASMJIT_DEFINE_FINAL_REG(VecB, Vec, RegTraits<RegType::kARM_VecB>)
};
//! 16-bit view (S) of VFP/SIMD register.
class VecH : public Vec {
public:
ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits<RegType::kARM_VecH>)
};
//! 32-bit view (S) of VFP/SIMD register.
class VecS : public Vec {
public:
ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits<RegType::kARM_VecS>)
};
//! 64-bit view (D) of VFP/SIMD register.
class VecD : public Vec {
public:
ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits<RegType::kARM_VecD>)
};
//! 128-bit vector register (Q or V).
class VecV : public Vec {
public:
ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits<RegType::kARM_VecV>)
};
ASMJIT_INLINE_NODEBUG VecB Vec::b() const noexcept { return VecB(id()); }
ASMJIT_INLINE_NODEBUG VecH Vec::h() const noexcept { return VecH(id()); }
ASMJIT_INLINE_NODEBUG VecS Vec::s() const noexcept { return VecS(id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::d() const noexcept { return VecD(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::q() const noexcept { return VecV(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::v() const noexcept { return VecV(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeS, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeD, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH2, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB4, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); }
ASMJIT_INLINE_NODEBUG VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); }
#ifndef _DOXYGEN #ifndef _DOXYGEN
namespace regs { namespace regs {
#endif #endif
//! Creates a 32-bit W register operand (ARM/AArch64). //! Creates a 32-bit W register operand.
static ASMJIT_INLINE_NODEBUG constexpr GpW w(uint32_t id) noexcept { return GpW(id); } static ASMJIT_INLINE_NODEBUG constexpr GpW w(uint32_t id) noexcept { return GpW(id); }
//! Creates a 64-bit X register operand (AArch64). //! Creates a 64-bit X register operand.
static ASMJIT_INLINE_NODEBUG constexpr GpX x(uint32_t id) noexcept { return GpX(id); } static ASMJIT_INLINE_NODEBUG constexpr GpX x(uint32_t id) noexcept { return GpX(id); }
using ::asmjit::arm::regs::s; //! Creates a 32-bit S register operand.
using ::asmjit::arm::regs::d; static ASMJIT_INLINE_NODEBUG constexpr VecS s(uint32_t id) noexcept { return VecS(id); }
using ::asmjit::arm::regs::v; //! Creates a 64-bit D register operand.
static ASMJIT_INLINE_NODEBUG constexpr VecD d(uint32_t id) noexcept { return VecD(id); }
//! Creates a 1282-bit V register operand.
static ASMJIT_INLINE_NODEBUG constexpr VecV v(uint32_t id) noexcept { return VecV(id); }
static constexpr GpW w0 = GpW(0); static constexpr GpW w0 = GpW(0);
static constexpr GpW w1 = GpW(1); static constexpr GpW w1 = GpW(1);
@@ -433,6 +632,9 @@ ASMJIT_END_SUB_NAMESPACE
ASMJIT_BEGIN_NAMESPACE ASMJIT_BEGIN_NAMESPACE
ASMJIT_DEFINE_TYPE_ID(a64::GpW, TypeId::kInt32); ASMJIT_DEFINE_TYPE_ID(a64::GpW, TypeId::kInt32);
ASMJIT_DEFINE_TYPE_ID(a64::GpX, TypeId::kInt64); ASMJIT_DEFINE_TYPE_ID(a64::GpX, TypeId::kInt64);
ASMJIT_DEFINE_TYPE_ID(a64::VecS, TypeId::kFloat32x1);
ASMJIT_DEFINE_TYPE_ID(a64::VecD, TypeId::kFloat64x1);
ASMJIT_DEFINE_TYPE_ID(a64::VecV, TypeId::kInt32x4);
ASMJIT_END_NAMESPACE ASMJIT_END_NAMESPACE
//! \endcond //! \endcond

View File

@@ -394,10 +394,10 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand(
if (op.isReg()) { if (op.isReg()) {
const BaseReg& reg = op.as<BaseReg>(); const BaseReg& reg = op.as<BaseReg>();
uint32_t elementType = op.as<Vec>().elementType(); uint32_t elementType = op._signature.getField<BaseVec::kSignatureRegElementTypeMask>();
uint32_t elementIndex = op.as<Vec>().elementIndex(); uint32_t elementIndex = op.as<BaseVec>().elementIndex();
if (!op.as<Vec>().hasElementIndex()) if (!op.as<BaseVec>().hasElementIndex())
elementIndex = 0xFFFFFFFFu; elementIndex = 0xFFFFFFFFu;
return formatRegister(sb, flags, emitter, arch, reg.type(), reg.id(), elementType, elementIndex); return formatRegister(sb, flags, emitter, arch, reg.type(), reg.id(), elementType, elementIndex);

View File

@@ -19,13 +19,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(arm)
class Reg; class Reg;
class Mem; class Mem;
class Vec;
class VecB;
class VecH;
class VecS;
class VecD;
class VecV;
//! Register traits (AArch32/AArch64). //! Register traits (AArch32/AArch64).
//! //!
//! Register traits contains information about a particular register type. It's used by asmjit to setup register //! Register traits contains information about a particular register type. It's used by asmjit to setup register
@@ -44,7 +37,7 @@ ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecB , RegGroup::kVec , 1 ,
ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecH , RegGroup::kVec , 2 , TypeId::kVoid ); // AArch64 ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecH , RegGroup::kVec , 2 , TypeId::kVoid ); // AArch64
ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecS , RegGroup::kVec , 4 , TypeId::kInt32x1 ); // AArch32 & AArch64 ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecS , RegGroup::kVec , 4 , TypeId::kInt32x1 ); // AArch32 & AArch64
ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecD , RegGroup::kVec , 8 , TypeId::kInt32x2 ); // AArch32 & AArch64 ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecD , RegGroup::kVec , 8 , TypeId::kInt32x2 ); // AArch32 & AArch64
ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecV , RegGroup::kVec , 16, TypeId::kInt32x4 ); // AArch32 & AArch64 ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecQ , RegGroup::kVec , 16, TypeId::kInt32x4 ); // AArch32 & AArch64
ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_PC , RegGroup::kPC , 8 , TypeId::kInt64 ); // AArch64 ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_PC , RegGroup::kPC , 8 , TypeId::kInt64 ); // AArch64
//! \endcond //! \endcond
@@ -122,14 +115,8 @@ public:
class BaseVec : public Reg { class BaseVec : public Reg {
public: public:
ASMJIT_DEFINE_ABSTRACT_REG(BaseVec, Reg) ASMJIT_DEFINE_ABSTRACT_REG(BaseVec, Reg)
};
//! Vector register (ARM). //! Additional signature bits used by a vector register.
class Vec : public BaseVec {
public:
ASMJIT_DEFINE_ABSTRACT_REG(Vec, BaseVec)
//! Additional signature bits used by arm::Vec.
enum AdditionalBits : uint32_t { enum AdditionalBits : uint32_t {
// Register element type (3 bits). // Register element type (3 bits).
// |........|........|.XXX....|........| // |........|........|.XXX....|........|
@@ -147,57 +134,8 @@ public:
kSignatureRegElementIndexMask = 0x0F << kSignatureRegElementIndexShift kSignatureRegElementIndexMask = 0x0F << kSignatureRegElementIndexShift
}; };
//! Element type (AArch64 only).
enum ElementType : uint32_t {
//! No element type specified.
kElementTypeNone = 0,
//! Byte elements (B8 or B16).
kElementTypeB,
//! Halfword elements (H4 or H8).
kElementTypeH,
//! Singleword elements (S2 or S4).
kElementTypeS,
//! Doubleword elements (D2).
kElementTypeD,
//! Byte elements grouped by 4 bytes (B4).
//!
//! \note This element-type is only used by few instructions.
kElementTypeB4,
//! Halfword elements grouped by 2 halfwords (H2).
//!
//! \note This element-type is only used by few instructions.
kElementTypeH2,
//! Count of element types.
kElementTypeCount
};
//! \cond
//! Shortcuts.
enum SignatureReg : uint32_t {
kSignatureElementB = kElementTypeB << kSignatureRegElementTypeShift,
kSignatureElementH = kElementTypeH << kSignatureRegElementTypeShift,
kSignatureElementS = kElementTypeS << kSignatureRegElementTypeShift,
kSignatureElementD = kElementTypeD << kSignatureRegElementTypeShift,
kSignatureElementB4 = kElementTypeB4 << kSignatureRegElementTypeShift,
kSignatureElementH2 = kElementTypeH2 << kSignatureRegElementTypeShift
};
//! \endcond
//! Returns whether the register has associated an element type.
ASMJIT_INLINE_NODEBUG constexpr bool hasElementType() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask>(); }
//! Returns whether the register has element index (it's an element index access). //! Returns whether the register has element index (it's an element index access).
ASMJIT_INLINE_NODEBUG constexpr bool hasElementIndex() const noexcept { return _signature.hasField<kSignatureRegElementFlagMask>(); } ASMJIT_INLINE_NODEBUG constexpr bool hasElementIndex() const noexcept { return _signature.hasField<kSignatureRegElementFlagMask>(); }
//! Returns whether the register has element type or element index (or both).
ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask | kSignatureRegElementFlagMask>(); }
//! Returns element type of the register.
ASMJIT_INLINE_NODEBUG constexpr uint32_t elementType() const noexcept { return _signature.getField<kSignatureRegElementTypeMask>(); }
//! Sets element type of the register to `elementType`.
ASMJIT_INLINE_NODEBUG void setElementType(uint32_t elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(elementType); }
//! Resets element type to none.
ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); }
//! Returns element index of the register. //! Returns element index of the register.
ASMJIT_INLINE_NODEBUG constexpr uint32_t elementIndex() const noexcept { return _signature.getField<kSignatureRegElementIndexMask>(); } ASMJIT_INLINE_NODEBUG constexpr uint32_t elementIndex() const noexcept { return _signature.getField<kSignatureRegElementIndexMask>(); }
//! Sets element index of the register to `elementType`. //! Sets element index of the register to `elementType`.
@@ -209,128 +147,8 @@ public:
ASMJIT_INLINE_NODEBUG void resetElementIndex() noexcept { ASMJIT_INLINE_NODEBUG void resetElementIndex() noexcept {
_signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask); _signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask);
} }
ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2); }
//! Creates a cloned register with element access.
ASMJIT_INLINE_NODEBUG Vec at(uint32_t elementIndex) const noexcept {
return Vec((signature() & ~kSignatureRegElementIndexMask) | (elementIndex << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id());
}
//! Cast this register to an 8-bit B register (AArch64 only).
ASMJIT_INLINE_NODEBUG VecB b() const noexcept;
//! Cast this register to a 16-bit H register (AArch64 only).
ASMJIT_INLINE_NODEBUG VecH h() const noexcept;
//! Cast this register to a 32-bit S register.
ASMJIT_INLINE_NODEBUG VecS s() const noexcept;
//! Cast this register to a 64-bit D register.
ASMJIT_INLINE_NODEBUG VecD d() const noexcept;
//! Cast this register to a 128-bit Q register.
ASMJIT_INLINE_NODEBUG VecV q() const noexcept;
//! Cast this register to a 128-bit V register.
ASMJIT_INLINE_NODEBUG VecV v() const noexcept;
//! Cast this register to a 128-bit V.B[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV b(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.H[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV h(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.S[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV s(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.D[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV d(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.H2[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV h2(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.B4[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV b4(uint32_t elementIndex) const noexcept;
//! Cast this register to V.8B.
ASMJIT_INLINE_NODEBUG VecD b8() const noexcept;
//! Cast this register to V.16B.
ASMJIT_INLINE_NODEBUG VecV b16() const noexcept;
//! Cast this register to V.2H.
ASMJIT_INLINE_NODEBUG VecS h2() const noexcept;
//! Cast this register to V.4H.
ASMJIT_INLINE_NODEBUG VecD h4() const noexcept;
//! Cast this register to V.8H.
ASMJIT_INLINE_NODEBUG VecV h8() const noexcept;
//! Cast this register to V.2S.
ASMJIT_INLINE_NODEBUG VecD s2() const noexcept;
//! Cast this register to V.4S.
ASMJIT_INLINE_NODEBUG VecV s4() const noexcept;
//! Cast this register to V.2D.
ASMJIT_INLINE_NODEBUG VecV d2() const noexcept;
static ASMJIT_INLINE_NODEBUG constexpr OperandSignature _makeElementAccessSignature(uint32_t elementType, uint32_t elementIndex) noexcept {
return OperandSignature{
uint32_t(RegTraits<RegType::kARM_VecV>::kSignature) |
uint32_t(kSignatureRegElementFlagMask) |
uint32_t(elementType << kSignatureRegElementTypeShift) |
uint32_t(elementIndex << kSignatureRegElementIndexShift)};
}
}; };
//! 8-bit view (S) of VFP/SIMD register.
class VecB : public Vec { ASMJIT_DEFINE_FINAL_REG(VecB, Vec, RegTraits<RegType::kARM_VecB>) };
//! 16-bit view (S) of VFP/SIMD register.
class VecH : public Vec { ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits<RegType::kARM_VecH>) };
//! 32-bit view (S) of VFP/SIMD register.
class VecS : public Vec { ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits<RegType::kARM_VecS>) };
//! 64-bit view (D) of VFP/SIMD register.
class VecD : public Vec { ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits<RegType::kARM_VecD>) };
//! 128-bit vector register (Q or V).
class VecV : public Vec { ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits<RegType::kARM_VecV>) };
ASMJIT_INLINE_NODEBUG VecB Vec::b() const noexcept { return VecB(id()); }
ASMJIT_INLINE_NODEBUG VecH Vec::h() const noexcept { return VecH(id()); }
ASMJIT_INLINE_NODEBUG VecS Vec::s() const noexcept { return VecS(id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::d() const noexcept { return VecD(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::q() const noexcept { return VecV(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::v() const noexcept { return VecV(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeS, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeD, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH2, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB4, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); }
ASMJIT_INLINE_NODEBUG VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); }
#ifndef _DOXYGEN
namespace regs {
#endif
//! Creates a 32-bit S register operand (ARM/AArch64).
static ASMJIT_INLINE_NODEBUG constexpr VecS s(uint32_t id) noexcept { return VecS(id); }
//! Creates a 64-bit D register operand (ARM/AArch64).
static ASMJIT_INLINE_NODEBUG constexpr VecD d(uint32_t id) noexcept { return VecD(id); }
//! Creates a 1282-bit V register operand (ARM/AArch64).
static ASMJIT_INLINE_NODEBUG constexpr VecV v(uint32_t id) noexcept { return VecV(id); }
#ifndef _DOXYGEN
} // {regs}
// Make `arm::regs` accessible through `arm` namespace as well.
using namespace regs;
#endif
//! Memory operand (ARM). //! Memory operand (ARM).
class Mem : public BaseMem { class Mem : public BaseMem {
public: public:
@@ -564,12 +382,4 @@ static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base) noexcept { return
ASMJIT_END_SUB_NAMESPACE ASMJIT_END_SUB_NAMESPACE
//! \cond INTERNAL
ASMJIT_BEGIN_NAMESPACE
ASMJIT_DEFINE_TYPE_ID(arm::VecS, TypeId::kFloat32x1);
ASMJIT_DEFINE_TYPE_ID(arm::VecD, TypeId::kFloat64x1);
ASMJIT_DEFINE_TYPE_ID(arm::VecV, TypeId::kInt32x4);
ASMJIT_END_NAMESPACE
//! \endcond
#endif // ASMJIT_ARM_ARMOPERAND_H_INCLUDED #endif // ASMJIT_ARM_ARMOPERAND_H_INCLUDED

View File

@@ -239,6 +239,22 @@ namespace asmjit {
//! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_DEPRECATED` //! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_DEPRECATED`
//! it's not using anything, which was deprecated. //! it's not using anything, which was deprecated.
//! //!
//! ### Changes committed at 2023-12-26
//!
//! Core changes:
//!
//! - Reworked InstNode and InstExNode to be friendlier to static analysis and to not cause undefined behavior.
//! InstNode has no operands visually embedded within the struct so there is no _opArray (which was internal).
//! This means that sizeof(InstNode) changed, but since it's allocated by AsmJit this should be fine. Moreover,
//! there is no longer InstExNode as that was more a hack, instead there is now InstNodeWithOperands, which is
//! a template and specifies the number of operands embedded (InstNode accesses these). All nodes that inherited
//! InstExNode now just inherit InstNodeWithOperands<InstNode::kBaseOpCapacity>, which would provide the same
//! number of nodes as InstNode.
//!
//! - Moved GP and Vec registers from asmjit::arm namespace to asmjit::a64 namespace. At this time there was
//! no prior deprecation as having arm::Vec would collide with a64::Vec as arm namespace is used within a64
//! namespace. Just change `arm::Gp` to `a64::Gp` and `arm::Vec` to `a64::Vec`.
//!
//! ### Changes committed at 2023-09-10 //! ### Changes committed at 2023-09-10
//! //!
//! Core changes: //! Core changes:

View File

@@ -152,7 +152,9 @@ enum class RegType : uint8_t {
kARM_VecS = kVec32, kARM_VecS = kVec32,
//! 64-bit view of VFP/ASIMD register (D). //! 64-bit view of VFP/ASIMD register (D).
kARM_VecD = kVec64, kARM_VecD = kVec64,
//! 128-bit view of VFP/ASIMD register (Q|V). //! 128-bit view of VFP/ASIMD register (Q).
kARM_VecQ = kVec128,
//! 128-bit view of VFP/ASIMD register (V).
kARM_VecV = kVec128, kARM_VecV = kVec128,
//! Maximum value of `RegType`. //! Maximum value of `RegType`.

View File

@@ -211,9 +211,9 @@ public:
funcNode->setArg(1, src1); funcNode->setArg(1, src1);
funcNode->setArg(2, src2); funcNode->setArg(2, src2);
arm::Vec v1 = cc.newVecQ("vec1"); a64::Vec v1 = cc.newVecQ("vec1");
arm::Vec v2 = cc.newVecQ("vec2"); a64::Vec v2 = cc.newVecQ("vec2");
arm::Vec v3 = cc.newVecQ("vec3"); a64::Vec v3 = cc.newVecQ("vec3");
cc.ldr(v2, a64::ptr(src1)); cc.ldr(v2, a64::ptr(src1));
cc.ldr(v3, a64::ptr(src2)); cc.ldr(v3, a64::ptr(src2));
@@ -465,9 +465,9 @@ public:
virtual void compile(a64::Compiler& cc) { virtual void compile(a64::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>()); FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>());
arm::Vec x = cc.newVecD("x"); a64::Vec x = cc.newVecD("x");
arm::Vec y = cc.newVecD("y"); a64::Vec y = cc.newVecD("y");
arm::Vec r = cc.newVecD("r"); a64::Vec r = cc.newVecD("r");
a64::Gp fn = cc.newUIntPtr("fn"); a64::Gp fn = cc.newUIntPtr("fn");
funcNode->setArg(0, x); funcNode->setArg(0, x);
@@ -517,9 +517,9 @@ public:
virtual void compile(a64::Compiler& cc) { virtual void compile(a64::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>()); FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>());
arm::Vec x = cc.newVecD("x"); a64::Vec x = cc.newVecD("x");
arm::Vec y = cc.newVecD("y"); a64::Vec y = cc.newVecD("y");
arm::Vec r = cc.newVecD("r"); a64::Vec r = cc.newVecD("r");
a64::Gp fn = cc.newUIntPtr("fn"); a64::Gp fn = cc.newUIntPtr("fn");
funcNode->setArg(0, x); funcNode->setArg(0, x);
@@ -582,8 +582,8 @@ public:
virtual void compile(a64::Compiler& cc) { virtual void compile(a64::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float, uint32_t>()); FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float, uint32_t>());
arm::Vec a = cc.newVecS("a"); a64::Vec a = cc.newVecS("a");
arm::Vec b = cc.newVecS("b"); a64::Vec b = cc.newVecS("b");
a64::Gp op = cc.newUInt32("op"); a64::Gp op = cc.newUInt32("op");
a64::Gp target = cc.newIntPtr("target"); a64::Gp target = cc.newIntPtr("target");