From f27334eaf89129f1d239ff0df9dc0bada333a825 Mon Sep 17 00:00:00 2001 From: kobalicek Date: Wed, 27 Dec 2023 02:26:36 +0100 Subject: [PATCH] [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. --- src/asmjit/arm/a64operand.h | 216 +++++++++++++++++++++++++++++- src/asmjit/arm/armformatter.cpp | 6 +- src/asmjit/arm/armoperand.h | 194 +-------------------------- src/asmjit/core.h | 16 +++ src/asmjit/core/operand.h | 4 +- test/asmjit_test_compiler_a64.cpp | 22 +-- 6 files changed, 244 insertions(+), 214 deletions(-) diff --git a/src/asmjit/arm/a64operand.h b/src/asmjit/arm/a64operand.h index f69288d..0d1cdd2 100644 --- a/src/asmjit/arm/a64operand.h +++ b/src/asmjit/arm/a64operand.h @@ -16,6 +16,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) class GpW; class GpX; +class VecB; +class VecH; +class VecS; +class VecD; +class VecV; + //! General purpose register (AArch64). class Gp : public Reg { public: @@ -25,9 +31,9 @@ public: enum Id : uint32_t { //! Register that depends on OS, could be used as TLS offset. kIdOs = 18, - //! Frame pointer. + //! Frame pointer register id. kIdFp = 29, - //! Link register. + //! Link register id. kIdLr = 30, //! Stack register id. 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()); } #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(); } + //! Returns whether the register has element index (it's an element index access). + ASMJIT_INLINE_NODEBUG constexpr bool hasElementIndex() const noexcept { return _signature.hasField(); } + //! Returns whether the register has element type or element index (or both). + ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField(); } + + //! Returns element type of the register. + ASMJIT_INLINE_NODEBUG constexpr uint32_t elementType() const noexcept { return _signature.getField(); } + //! Sets element type of the register to `elementType`. + ASMJIT_INLINE_NODEBUG void setElementType(uint32_t elementType) noexcept { _signature.setField(elementType); } + //! Resets element type to none. + ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField(0); } + + //! Returns element index of the register. + ASMJIT_INLINE_NODEBUG constexpr uint32_t elementIndex() const noexcept { return _signature.getField(); } + //! Sets element index of the register to `elementType`. + ASMJIT_INLINE_NODEBUG void setElementIndex(uint32_t elementIndex) noexcept { + _signature |= kSignatureRegElementFlagMask; + _signature.setField(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::kSignature | kSignatureElementB); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementS); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature); } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementS); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementD); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB4); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::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::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) +}; + +//! 16-bit view (S) of VFP/SIMD register. +class VecH : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits) +}; + +//! 32-bit view (S) of VFP/SIMD register. +class VecS : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits) +}; + +//! 64-bit view (D) of VFP/SIMD register. +class VecD : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits) +}; + +//! 128-bit vector register (Q or V). +class VecV : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits) +}; + +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 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); } -//! 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); } -using ::asmjit::arm::regs::s; -using ::asmjit::arm::regs::d; -using ::asmjit::arm::regs::v; +//! Creates a 32-bit S register operand. +static ASMJIT_INLINE_NODEBUG constexpr VecS s(uint32_t id) noexcept { return VecS(id); } +//! 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 w1 = GpW(1); @@ -433,6 +632,9 @@ ASMJIT_END_SUB_NAMESPACE ASMJIT_BEGIN_NAMESPACE ASMJIT_DEFINE_TYPE_ID(a64::GpW, TypeId::kInt32); 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 //! \endcond diff --git a/src/asmjit/arm/armformatter.cpp b/src/asmjit/arm/armformatter.cpp index 4a6b457..f6b2dcb 100644 --- a/src/asmjit/arm/armformatter.cpp +++ b/src/asmjit/arm/armformatter.cpp @@ -394,10 +394,10 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( if (op.isReg()) { const BaseReg& reg = op.as(); - uint32_t elementType = op.as().elementType(); - uint32_t elementIndex = op.as().elementIndex(); + uint32_t elementType = op._signature.getField(); + uint32_t elementIndex = op.as().elementIndex(); - if (!op.as().hasElementIndex()) + if (!op.as().hasElementIndex()) elementIndex = 0xFFFFFFFFu; return formatRegister(sb, flags, emitter, arch, reg.type(), reg.id(), elementType, elementIndex); diff --git a/src/asmjit/arm/armoperand.h b/src/asmjit/arm/armoperand.h index 6b53524..96167e7 100644 --- a/src/asmjit/arm/armoperand.h +++ b/src/asmjit/arm/armoperand.h @@ -19,13 +19,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(arm) class Reg; class Mem; -class Vec; -class VecB; -class VecH; -class VecS; -class VecD; -class VecV; - //! Register traits (AArch32/AArch64). //! //! 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_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_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 //! \endcond @@ -122,14 +115,8 @@ public: class BaseVec : public Reg { public: ASMJIT_DEFINE_ABSTRACT_REG(BaseVec, Reg) -}; -//! Vector register (ARM). -class Vec : public BaseVec { -public: - ASMJIT_DEFINE_ABSTRACT_REG(Vec, BaseVec) - - //! Additional signature bits used by arm::Vec. + //! Additional signature bits used by a vector register. enum AdditionalBits : uint32_t { // Register element type (3 bits). // |........|........|.XXX....|........| @@ -147,57 +134,8 @@ public: 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(); } //! Returns whether the register has element index (it's an element index access). ASMJIT_INLINE_NODEBUG constexpr bool hasElementIndex() const noexcept { return _signature.hasField(); } - //! Returns whether the register has element type or element index (or both). - ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField(); } - - //! Returns element type of the register. - ASMJIT_INLINE_NODEBUG constexpr uint32_t elementType() const noexcept { return _signature.getField(); } - //! Sets element type of the register to `elementType`. - ASMJIT_INLINE_NODEBUG void setElementType(uint32_t elementType) noexcept { _signature.setField(elementType); } - //! Resets element type to none. - ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField(0); } - //! Returns element index of the register. ASMJIT_INLINE_NODEBUG constexpr uint32_t elementIndex() const noexcept { return _signature.getField(); } //! Sets element index of the register to `elementType`. @@ -209,128 +147,8 @@ public: ASMJIT_INLINE_NODEBUG void resetElementIndex() noexcept { _signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask); } - - ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementS); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature); } - - ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementS); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementD); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB4); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::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::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) }; -//! 16-bit view (S) of VFP/SIMD register. -class VecH : public Vec { ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits) }; -//! 32-bit view (S) of VFP/SIMD register. -class VecS : public Vec { ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits) }; -//! 64-bit view (D) of VFP/SIMD register. -class VecD : public Vec { ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits) }; -//! 128-bit vector register (Q or V). -class VecV : public Vec { ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits) }; - -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). class Mem : public BaseMem { public: @@ -564,12 +382,4 @@ static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base) noexcept { return 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 diff --git a/src/asmjit/core.h b/src/asmjit/core.h index e1bce63..b8c3636 100644 --- a/src/asmjit/core.h +++ b/src/asmjit/core.h @@ -239,6 +239,22 @@ namespace asmjit { //! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_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, 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 //! //! Core changes: diff --git a/src/asmjit/core/operand.h b/src/asmjit/core/operand.h index dd3baa7..e7ba57d 100644 --- a/src/asmjit/core/operand.h +++ b/src/asmjit/core/operand.h @@ -152,7 +152,9 @@ enum class RegType : uint8_t { kARM_VecS = kVec32, //! 64-bit view of VFP/ASIMD register (D). 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, //! Maximum value of `RegType`. diff --git a/test/asmjit_test_compiler_a64.cpp b/test/asmjit_test_compiler_a64.cpp index 98c1190..bc859fe 100644 --- a/test/asmjit_test_compiler_a64.cpp +++ b/test/asmjit_test_compiler_a64.cpp @@ -211,9 +211,9 @@ public: funcNode->setArg(1, src1); funcNode->setArg(2, src2); - arm::Vec v1 = cc.newVecQ("vec1"); - arm::Vec v2 = cc.newVecQ("vec2"); - arm::Vec v3 = cc.newVecQ("vec3"); + a64::Vec v1 = cc.newVecQ("vec1"); + a64::Vec v2 = cc.newVecQ("vec2"); + a64::Vec v3 = cc.newVecQ("vec3"); cc.ldr(v2, a64::ptr(src1)); cc.ldr(v3, a64::ptr(src2)); @@ -465,9 +465,9 @@ public: virtual void compile(a64::Compiler& cc) { FuncNode* funcNode = cc.addFunc(FuncSignatureT()); - arm::Vec x = cc.newVecD("x"); - arm::Vec y = cc.newVecD("y"); - arm::Vec r = cc.newVecD("r"); + a64::Vec x = cc.newVecD("x"); + a64::Vec y = cc.newVecD("y"); + a64::Vec r = cc.newVecD("r"); a64::Gp fn = cc.newUIntPtr("fn"); funcNode->setArg(0, x); @@ -517,9 +517,9 @@ public: virtual void compile(a64::Compiler& cc) { FuncNode* funcNode = cc.addFunc(FuncSignatureT()); - arm::Vec x = cc.newVecD("x"); - arm::Vec y = cc.newVecD("y"); - arm::Vec r = cc.newVecD("r"); + a64::Vec x = cc.newVecD("x"); + a64::Vec y = cc.newVecD("y"); + a64::Vec r = cc.newVecD("r"); a64::Gp fn = cc.newUIntPtr("fn"); funcNode->setArg(0, x); @@ -582,8 +582,8 @@ public: virtual void compile(a64::Compiler& cc) { FuncNode* funcNode = cc.addFunc(FuncSignatureT()); - arm::Vec a = cc.newVecS("a"); - arm::Vec b = cc.newVecS("b"); + a64::Vec a = cc.newVecS("a"); + a64::Vec b = cc.newVecS("b"); a64::Gp op = cc.newUInt32("op"); a64::Gp target = cc.newIntPtr("target");