[ABI] Renamed a64::Vec::ElementType to a64::VecElementType

This commit is contained in:
kobalicek
2023-12-27 13:04:27 +01:00
parent b4ad286890
commit 5ce45e0356
10 changed files with 131 additions and 147 deletions

View File

@@ -47,7 +47,6 @@ TODO
* [ ] Ports: * [ ] Ports:
* [ ] 32-bit ARM/Thumb port. * [ ] 32-bit ARM/Thumb port.
* [ ] 64-bit ARM (AArch64) port.
* [ ] RISC-V port. * [ ] RISC-V port.
Support Support

View File

@@ -21,12 +21,16 @@
ASMJIT_BEGIN_SUB_NAMESPACE(a64) ASMJIT_BEGIN_SUB_NAMESPACE(a64)
// a64::Assembler - Utils
// ======================
static ASMJIT_FORCE_INLINE constexpr uint32_t diff(RegType a, RegType b) noexcept { return uint32_t(a) - uint32_t(b); }
static ASMJIT_FORCE_INLINE constexpr uint32_t diff(VecElementType elementType, VecElementType baseType) noexcept { return uint32_t(elementType) - uint32_t(baseType); }
// a64::Assembler - Cond // a64::Assembler - Cond
// ===================== // =====================
static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept { static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept { return (uint32_t(cond) - 2u) & 0xFu; }
return (uint32_t(cond) - 2u) & 0xFu;
}
// a64::Assembler - Bits // a64::Assembler - Bits
// ===================== // =====================
@@ -49,10 +53,6 @@ static constexpr uint32_t kWX = InstDB::kWX;
static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) };
#undef VALUE #undef VALUE
static inline constexpr uint32_t diff(RegType a, RegType b) noexcept {
return uint32_t(a) - uint32_t(b);
}
// asmjit::a64::Assembler - SizeOp // asmjit::a64::Assembler - SizeOp
// =============================== // ===============================
@@ -118,25 +118,25 @@ struct SizeOpTable {
}; };
#define VALUE_BIN(x) { \ #define VALUE_BIN(x) { \
x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00 : \ x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00 : \
x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00Q : \ x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00Q : \
x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \ x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00 : \
x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : SizeOp::kInvalid \ x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00Q : SizeOp::kInvalid \
} }
#define VALUE_ANY(x) { \ #define VALUE_ANY(x) { \
x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00S : \ x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00S : \
x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k01S : \ x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k01S : \
x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k10S : \ x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k10S : \
x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k11S : \ x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k11S : \
x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \ x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00 : \
x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : \ x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00Q : \
x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01 : \ x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kH )) ? SizeOp::k01 : \
x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01Q : \ x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kH )) ? SizeOp::k01Q : \
x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10 : \ x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kS )) ? SizeOp::k10 : \
x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10Q : \ x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kS )) ? SizeOp::k10Q : \
x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11S : \ x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kD )) ? SizeOp::k11S : \
x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11Q : SizeOp::kInvalid \ x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kD )) ? SizeOp::k11Q : SizeOp::kInvalid \
} }
static const SizeOpTable sizeOpTable[SizeOpTable::kCount] = { static const SizeOpTable sizeOpTable[SizeOpTable::kCount] = {
@@ -254,16 +254,16 @@ static const Operand_& significantSimdOp(const Operand_& o0, const Operand_& o1,
return !(instFlags & InstDB::kInstFlagLong) ? o0 : o1; return !(instFlags & InstDB::kInstFlagLong) ? o0 : o1;
} }
static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, uint32_t elementType) noexcept { static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, VecElementType elementType) noexcept {
// Instruction data or Assembler is wrong if this triggers an assertion failure. // Instruction data or Assembler is wrong if this triggers an assertion failure.
ASMJIT_ASSERT(vecOpType < InstDB::kVO_Count); ASMJIT_ASSERT(vecOpType < InstDB::kVO_Count);
// ElementType uses 3 bits in the operand signature, it should never overflow. // ElementType uses 3 bits in the operand signature, it should never overflow.
ASMJIT_ASSERT(elementType <= 0x7u); ASMJIT_ASSERT(uint32_t(elementType) <= 0x7u);
const SizeOpMap& map = sizeOpMap[vecOpType]; const SizeOpMap& map = sizeOpMap[vecOpType];
const SizeOpTable& table = sizeOpTable[map.tableId]; const SizeOpTable& table = sizeOpTable[map.tableId];
size_t index = (Support::min<uint32_t>(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | elementType; size_t index = (Support::min<uint32_t>(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | uint32_t(elementType);
SizeOp op = table.array[index]; SizeOp op = table.array[index];
SizeOp modifiedOp { uint8_t(op.value & map.sizeOpMask) }; SizeOp modifiedOp { uint8_t(op.value & map.sizeOpMask) };
@@ -537,7 +537,7 @@ static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint
else { else {
// Vector operation [HSD]. // Vector operation [HSD].
uint32_t q = diff(reg.type(), RegType::kARM_VecD); uint32_t q = diff(reg.type(), RegType::kARM_VecD);
uint32_t sz = reg.elementType() - Vec::kElementTypeH; uint32_t sz = diff(reg.elementType(), VecElementType::kH);
if (q > 1u || sz > 2u || !Support::bitTest(szBits[vHf].sizeMask, sz)) if (q > 1u || sz > 2u || !Support::bitTest(szBits[vHf].sizeMask, sz))
return false; return false;
@@ -2768,7 +2768,7 @@ Case_BaseLdurStur:
// hD, vS.{4|8}h (16-bit) // hD, vS.{4|8}h (16-bit)
// sD, vS.4s (32-bit) // sD, vS.4s (32-bit)
uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
uint32_t elementSz = o1.as<Vec>().elementType() - Vec::kElementTypeH; uint32_t elementSz = diff(o1.as<Vec>().elementType(), VecElementType::kH);
// Size greater than 1 means 64-bit elements, not supported. // Size greater than 1 means 64-bit elements, not supported.
if ((sz | elementSz) > 1 || sz != elementSz) if ((sz | elementSz) > 1 || sz != elementSz)
@@ -2890,7 +2890,7 @@ Case_BaseLdurStur:
if (q > 1) if (q > 1)
goto InvalidInstruction; goto InvalidInstruction;
uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB; uint32_t sz = diff(o0.as<Vec>().elementType(), VecElementType::kB);
if (sz == 0 || sz > 3) if (sz == 0 || sz > 3)
goto InvalidInstruction; goto InvalidInstruction;
@@ -2982,7 +2982,7 @@ Case_BaseLdurStur:
if (q > 1) if (q > 1)
goto InvalidInstruction; goto InvalidInstruction;
uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB; uint32_t sz = diff(o0.as<Vec>().elementType(), VecElementType::kB);
if (sz == 0 || sz > 3) if (sz == 0 || sz > 3)
goto InvalidInstruction; goto InvalidInstruction;
@@ -3164,11 +3164,11 @@ Case_BaseLdurStur:
if (uint32_t(opcode.hasQ()) != q) if (uint32_t(opcode.hasQ()) != q)
goto InvalidInstruction; goto InvalidInstruction;
if (rL.isVecS4() && rN.elementType() == Vec::kElementTypeH && !opData.isCvtxn()) { if (rL.isVecS4() && rN.elementType() == VecElementType::kH && !opData.isCvtxn()) {
goto EmitOp_Rd0_Rn5; goto EmitOp_Rd0_Rn5;
} }
if (rL.isVecD2() && rN.elementType() == Vec::kElementTypeS) { if (rL.isVecD2() && rN.elementType() == VecElementType::kS) {
opcode |= B(22); opcode |= B(22);
goto EmitOp_Rd0_Rn5; goto EmitOp_Rd0_Rn5;
} }
@@ -3279,8 +3279,8 @@ Case_BaseLdurStur:
} }
if (uint32_t(o0.as<Reg>().type()) != uint32_t(o1.as<Reg>().type()) + qIsOptional || if (uint32_t(o0.as<Reg>().type()) != uint32_t(o1.as<Reg>().type()) + qIsOptional ||
o0.as<Vec>().elementType() != opData.tA || uint32_t(o0.as<Vec>().elementType()) != opData.tA ||
o1.as<Vec>().elementType() != opData.tB) uint32_t(o1.as<Vec>().elementType()) != opData.tB)
goto InvalidInstruction; goto InvalidInstruction;
if (!o2.as<Vec>().hasElementIndex()) { if (!o2.as<Vec>().hasElementIndex()) {
@@ -3292,7 +3292,7 @@ Case_BaseLdurStur:
goto EmitOp_Rd0_Rn5_Rm16; goto EmitOp_Rd0_Rn5_Rm16;
} }
else { else {
if (o2.as<Vec>().elementType() != opData.tElement) if (uint32_t(o2.as<Vec>().elementType()) != opData.tElement)
goto InvalidInstruction; goto InvalidInstruction;
if (o2.as<Reg>().id() > 15) if (o2.as<Reg>().id() > 15)
@@ -3442,7 +3442,7 @@ Case_BaseLdurStur:
} }
else { else {
uint32_t q = diff(o0.as<Vec>().type(), RegType::kARM_VecD); uint32_t q = diff(o0.as<Vec>().type(), RegType::kARM_VecD);
uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH; uint32_t sz = diff(o0.as<Vec>().elementType(), VecElementType::kH);
if (q > 1 || sz > 2) if (q > 1 || sz > 2)
goto InvalidInstruction; goto InvalidInstruction;
@@ -3496,7 +3496,7 @@ Case_BaseLdurStur:
if (q > 1) if (q > 1)
goto InvalidInstruction; goto InvalidInstruction;
uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH; uint32_t sz = diff(o0.as<Vec>().elementType(), VecElementType::kH);
if (sz > 2) if (sz > 2)
goto InvalidInstruction; goto InvalidInstruction;
@@ -3520,7 +3520,7 @@ Case_BaseLdurStur:
if (isign4 == ENC_OPS2(Reg, Reg)) { if (isign4 == ENC_OPS2(Reg, Reg)) {
// The first destination operand is scalar, which matches element-type of source vectors. // The first destination operand is scalar, which matches element-type of source vectors.
uint32_t L = (instFlags & InstDB::kInstFlagLong) != 0; uint32_t L = (instFlags & InstDB::kInstFlagLong) != 0;
if (diff(o0.as<Vec>().type(), RegType::kARM_VecB) != o1.as<Vec>().elementType() - Vec::kElementTypeB + L) if (diff(o0.as<Vec>().type(), RegType::kARM_VecB) != diff(o1.as<Vec>().elementType(), VecElementType::kB) + L)
goto InvalidInstruction; goto InvalidInstruction;
SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType()); SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
@@ -3620,7 +3620,7 @@ Case_BaseLdurStur:
if (!sizeOp.isValid()) if (!sizeOp.isValid())
goto InvalidInstruction; goto InvalidInstruction;
if (!checkSignature(o0, o1) || !o0.as<Reg>().isVecV() || o0.as<Vec>().elementType() != o2.as<Vec>().elementType() + 1) if (!checkSignature(o0, o1) || !o0.as<Reg>().isVecV() || uint32_t(o0.as<Vec>().elementType()) != uint32_t(o2.as<Vec>().elementType()) + 1u)
goto InvalidInstruction; goto InvalidInstruction;
opcode.reset(opData.opcode()); opcode.reset(opData.opcode());
@@ -3905,9 +3905,9 @@ Case_BaseLdurStur:
if (o0.as<Reg>().type() != o1.as<Reg>().type() || o1.as<Reg>().type() != o2.as<Reg>().type()) if (o0.as<Reg>().type() != o1.as<Reg>().type() || o1.as<Reg>().type() != o2.as<Reg>().type())
goto InvalidInstruction; goto InvalidInstruction;
if (o0.as<Vec>().elementType() != opData.tA || if (uint32_t(o0.as<Vec>().elementType()) != opData.tA ||
o1.as<Vec>().elementType() != opData.tB || uint32_t(o1.as<Vec>().elementType()) != opData.tB ||
o2.as<Vec>().elementType() != opData.tB) uint32_t(o2.as<Vec>().elementType()) != opData.tB)
goto InvalidInstruction; goto InvalidInstruction;
opcode.reset(uint32_t(opData.vectorOp) << 10); opcode.reset(uint32_t(opData.vectorOp) << 10);
@@ -3921,9 +3921,9 @@ Case_BaseLdurStur:
if (o0.as<Reg>().type() != o1.as<Reg>().type() || !o2.as<Reg>().isVecV()) if (o0.as<Reg>().type() != o1.as<Reg>().type() || !o2.as<Reg>().isVecV())
goto InvalidInstruction; goto InvalidInstruction;
if (o0.as<Vec>().elementType() != opData.tA || if (uint32_t(o0.as<Vec>().elementType()) != opData.tA ||
o1.as<Vec>().elementType() != opData.tB || uint32_t(o1.as<Vec>().elementType()) != opData.tB ||
o2.as<Vec>().elementType() != opData.tElement) uint32_t(o2.as<Vec>().elementType()) != opData.tElement)
goto InvalidInstruction; goto InvalidInstruction;
uint32_t elementIndex = o2.as<Vec>().elementIndex(); uint32_t elementIndex = o2.as<Vec>().elementIndex();
@@ -3949,13 +3949,13 @@ Case_BaseLdurStur:
case InstDB::kEncodingSimdDup: SimdDup: { case InstDB::kEncodingSimdDup: SimdDup: {
if (isign4 == ENC_OPS2(Reg, Reg)) { if (isign4 == ENC_OPS2(Reg, Reg)) {
// Truth table of valid encodings of `Q:1|ElementType:3` // Truth table of valid encodings of `Q:1|ElementType:3`
uint32_t kValidEncodings = B(Vec::kElementTypeB + 0) | uint32_t kValidEncodings = B(uint32_t(VecElementType::kB) + 0) |
B(Vec::kElementTypeH + 0) | B(uint32_t(VecElementType::kH) + 0) |
B(Vec::kElementTypeS + 0) | B(uint32_t(VecElementType::kS) + 0) |
B(Vec::kElementTypeB + 8) | B(uint32_t(VecElementType::kB) + 8) |
B(Vec::kElementTypeH + 8) | B(uint32_t(VecElementType::kH) + 8) |
B(Vec::kElementTypeS + 8) | B(uint32_t(VecElementType::kS) + 8) |
B(Vec::kElementTypeD + 8) ; B(uint32_t(VecElementType::kD) + 8) ;
uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
@@ -3964,7 +3964,7 @@ Case_BaseLdurStur:
// //
// NOTE: This is only scalar for `dup d, x` case, otherwise the value // NOTE: This is only scalar for `dup d, x` case, otherwise the value
// would be duplicated across all vector elements (1, 2, 4, 8, or 16). // would be duplicated across all vector elements (1, 2, 4, 8, or 16).
uint32_t elementType = o0.as<Vec>().elementType(); uint32_t elementType = uint32_t(o0.as<Vec>().elementType());
if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType))
goto InvalidInstruction; goto InvalidInstruction;
@@ -3985,7 +3985,7 @@ Case_BaseLdurStur:
// DUP - Vec (scalar) <- Vec[N]. // DUP - Vec (scalar) <- Vec[N].
uint32_t lsbIndex = diff(o0.as<Reg>().type(), RegType::kARM_VecB); uint32_t lsbIndex = diff(o0.as<Reg>().type(), RegType::kARM_VecB);
if (lsbIndex != o1.as<Vec>().elementType() - Vec::kElementTypeB || lsbIndex > 3) if (lsbIndex != diff(o1.as<Vec>().elementType(), VecElementType::kB) || lsbIndex > 3)
goto InvalidInstruction; goto InvalidInstruction;
uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex;
@@ -3998,7 +3998,7 @@ Case_BaseLdurStur:
} }
else { else {
// DUP - Vec (all) <- Vec[N]. // DUP - Vec (all) <- Vec[N].
uint32_t elementType = o0.as<Vec>().elementType(); uint32_t elementType = uint32_t(o0.as<Vec>().elementType());
if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType))
goto InvalidInstruction; goto InvalidInstruction;
@@ -4023,7 +4023,7 @@ Case_BaseLdurStur:
if (!o0.as<Vec>().hasElementIndex()) if (!o0.as<Vec>().hasElementIndex())
goto InvalidInstruction; goto InvalidInstruction;
uint32_t elementType = o0.as<Vec>().elementType(); uint32_t elementType = uint32_t(o0.as<Vec>().elementType());
uint32_t dstIndex = o0.as<Vec>().elementIndex(); uint32_t dstIndex = o0.as<Vec>().elementIndex();
uint32_t lsbIndex = elementType - 1u; uint32_t lsbIndex = elementType - 1u;
@@ -4735,7 +4735,7 @@ Case_SimdLdurStur:
uint32_t q = 0; uint32_t q = 0;
uint32_t rm = 0; uint32_t rm = 0;
uint32_t rn = m.baseId(); uint32_t rn = m.baseId();
uint32_t sz = v.elementType() - Vec::kElementTypeB; uint32_t sz = diff(v.elementType(), VecElementType::kB);
uint32_t opcSsize = sz; uint32_t opcSsize = sz;
uint32_t offsetPossibility = 0; uint32_t offsetPossibility = 0;

View File

@@ -31,14 +31,6 @@ public:
//! \} //! \}
//! \name Accessors
//! \{
//! Gets whether the current ARM mode is THUMB (alternative to 32-bit ARM encoding).
ASMJIT_INLINE_NODEBUG bool isInThumbMode() const noexcept { return _environment.isArchThumb(); }
//! \}
//! \name Emit //! \name Emit
//! \{ //! \{

View File

@@ -174,10 +174,10 @@ Error queryRWInfo(const BaseInst& inst, const Operand_* operands, size_t opCount
if (srcOp.isReg()) { if (srcOp.isReg()) {
if (srcOp.as<Vec>().hasElementIndex()) { if (srcOp.as<Vec>().hasElementIndex()) {
// Only part of the vector is accessed if element index [] is used. // Only part of the vector is accessed if element index [] is used.
uint32_t elementType = srcOp.as<Vec>().elementType(); VecElementType elementType = srcOp.as<Vec>().elementType();
uint32_t elementIndex = srcOp.as<Vec>().elementIndex(); uint32_t elementIndex = srcOp.as<Vec>().elementIndex();
uint32_t elementSize = elementTypeSize[elementType]; uint32_t elementSize = elementTypeSize[size_t(elementType)];
uint64_t accessMask = uint64_t(Support::lsbMask<uint32_t>(elementSize)) << (elementIndex * elementSize); uint64_t accessMask = uint64_t(Support::lsbMask<uint32_t>(elementSize)) << (elementIndex * elementSize);
op._readByteMask &= accessMask; op._readByteMask &= accessMask;

View File

@@ -59,14 +59,14 @@ enum RWInfoType : uint32_t {
// a64::InstDB - ElementType // a64::InstDB - ElementType
// ========================= // =========================
enum ElementType : uint8_t { enum InstElementType : uint8_t {
kET_None = Vec::kElementTypeNone, kET_None = uint8_t(VecElementType::kNone),
kET_B = Vec::kElementTypeB, kET_B = uint8_t(VecElementType::kB),
kET_H = Vec::kElementTypeH, kET_H = uint8_t(VecElementType::kH),
kET_S = Vec::kElementTypeS, kET_S = uint8_t(VecElementType::kS),
kET_D = Vec::kElementTypeD, kET_D = uint8_t(VecElementType::kD),
kET_2H = Vec::kElementTypeH2, kET_2H = uint8_t(VecElementType::kH2),
kET_4B = Vec::kElementTypeB4 kET_4B = uint8_t(VecElementType::kB4)
}; };
// a64::InstDB - GpType // a64::InstDB - GpType

View File

@@ -56,7 +56,7 @@ UNIT(a64_operand) {
EXPECT_EQ(vd_1.group(), RegGroup::kVec); EXPECT_EQ(vd_1.group(), RegGroup::kVec);
EXPECT_EQ(vd_1.id(), 15u); EXPECT_EQ(vd_1.id(), 15u);
EXPECT_TRUE(vd_1.isVecD2()); EXPECT_TRUE(vd_1.isVecD2());
EXPECT_EQ(vd_1.elementType(), Vec::kElementTypeD); EXPECT_EQ(vd_1.elementType(), VecElementType::kD);
EXPECT_TRUE(vd_1.hasElementIndex()); EXPECT_TRUE(vd_1.hasElementIndex());
EXPECT_EQ(vd_1.elementIndex(), 1u); EXPECT_EQ(vd_1.elementIndex(), 1u);
@@ -65,7 +65,7 @@ UNIT(a64_operand) {
EXPECT_EQ(vs_3.group(), RegGroup::kVec); EXPECT_EQ(vs_3.group(), RegGroup::kVec);
EXPECT_EQ(vs_3.id(), 15u); EXPECT_EQ(vs_3.id(), 15u);
EXPECT_TRUE(vs_3.isVecS4()); EXPECT_TRUE(vs_3.isVecS4());
EXPECT_EQ(vs_3.elementType(), Vec::kElementTypeS); EXPECT_EQ(vs_3.elementType(), VecElementType::kS);
EXPECT_TRUE(vs_3.hasElementIndex()); EXPECT_TRUE(vs_3.hasElementIndex());
EXPECT_EQ(vs_3.elementIndex(), 3u); EXPECT_EQ(vs_3.elementIndex(), 3u);
@@ -74,7 +74,7 @@ UNIT(a64_operand) {
EXPECT_EQ(vb_4.group(), RegGroup::kVec); EXPECT_EQ(vb_4.group(), RegGroup::kVec);
EXPECT_EQ(vb_4.id(), 15u); EXPECT_EQ(vb_4.id(), 15u);
EXPECT_TRUE(vb_4.isVecB4x4()); EXPECT_TRUE(vb_4.isVecB4x4());
EXPECT_EQ(vb_4.elementType(), Vec::kElementTypeB4); EXPECT_EQ(vb_4.elementType(), VecElementType::kB4);
EXPECT_TRUE(vb_4.hasElementIndex()); EXPECT_TRUE(vb_4.hasElementIndex());
EXPECT_EQ(vb_4.elementIndex(), 3u); EXPECT_EQ(vb_4.elementIndex(), 3u);
} }

View File

@@ -69,74 +69,60 @@ 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 element type (AArch64).
enum class VecElementType : uint32_t {
//! No element type specified.
kNone = 0,
//! Byte elements (B8 or B16).
kB,
//! Halfword elements (H4 or H8).
kH,
//! Singleword elements (S2 or S4).
kS,
//! Doubleword elements (D2).
kD,
//! Byte elements grouped by 4 bytes (B4).
//!
//! \note This element-type is only used by few instructions.
kB4,
//! Halfword elements grouped by 2 halfwords (H2).
//!
//! \note This element-type is only used by few instructions.
kH2,
//! Maximum value of \ref VecElementType
kMaxValue = kH2
};
//! Vector register (AArch64). //! Vector register (AArch64).
class Vec : public BaseVec { class Vec : public BaseVec {
public: public:
ASMJIT_DEFINE_ABSTRACT_REG(Vec, BaseVec) 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 //! \cond
//! Shortcuts. //! Shortcuts.
enum SignatureReg : uint32_t { enum SignatureReg : uint32_t {
kSignatureElementB = kElementTypeB << kSignatureRegElementTypeShift, kSignatureElementB = uint32_t(VecElementType::kB) << kSignatureRegElementTypeShift,
kSignatureElementH = kElementTypeH << kSignatureRegElementTypeShift, kSignatureElementH = uint32_t(VecElementType::kH) << kSignatureRegElementTypeShift,
kSignatureElementS = kElementTypeS << kSignatureRegElementTypeShift, kSignatureElementS = uint32_t(VecElementType::kS) << kSignatureRegElementTypeShift,
kSignatureElementD = kElementTypeD << kSignatureRegElementTypeShift, kSignatureElementD = uint32_t(VecElementType::kD) << kSignatureRegElementTypeShift,
kSignatureElementB4 = kElementTypeB4 << kSignatureRegElementTypeShift, kSignatureElementB4 = uint32_t(VecElementType::kB4) << kSignatureRegElementTypeShift,
kSignatureElementH2 = kElementTypeH2 << kSignatureRegElementTypeShift kSignatureElementH2 = uint32_t(VecElementType::kH2) << kSignatureRegElementTypeShift
}; };
//! \endcond //! \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). //! 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>(); } ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask | kSignatureRegElementFlagMask>(); }
//! Returns element type of the register. //! Returns whether the vector register has associated a vector element type.
ASMJIT_INLINE_NODEBUG constexpr uint32_t elementType() const noexcept { return _signature.getField<kSignatureRegElementTypeMask>(); } ASMJIT_INLINE_NODEBUG constexpr bool hasElementType() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask>(); }
//! Sets element type of the register to `elementType`. //! Returns vector element type of the register.
ASMJIT_INLINE_NODEBUG void setElementType(uint32_t elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(elementType); } ASMJIT_INLINE_NODEBUG constexpr VecElementType elementType() const noexcept { return VecElementType(_signature.getField<kSignatureRegElementTypeMask>()); }
//! Resets element type to none. //! Sets vector element type of the register to `elementType`.
ASMJIT_INLINE_NODEBUG void setElementType(VecElementType elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(uint32_t(elementType)); }
//! Resets vector element type to none.
ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); } 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 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 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 isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); }
@@ -197,12 +183,12 @@ public:
//! Cast this register to V.2D. //! Cast this register to V.2D.
ASMJIT_INLINE_NODEBUG VecV d2() const noexcept; ASMJIT_INLINE_NODEBUG VecV d2() const noexcept;
static ASMJIT_INLINE_NODEBUG constexpr OperandSignature _makeElementAccessSignature(uint32_t elementType, uint32_t elementIndex) noexcept { static ASMJIT_INLINE_NODEBUG constexpr OperandSignature _makeElementAccessSignature(VecElementType elementType, uint32_t elementIndex) noexcept {
return OperandSignature{ return OperandSignature{
uint32_t(RegTraits<RegType::kARM_VecV>::kSignature) | uint32_t(RegTraits<RegType::kARM_VecV>::kSignature) |
uint32_t(kSignatureRegElementFlagMask) | uint32_t(kSignatureRegElementFlagMask) |
uint32_t(elementType << kSignatureRegElementTypeShift) | (uint32_t(elementType) << kSignatureRegElementTypeShift) |
uint32_t(elementIndex << kSignatureRegElementIndexShift)}; (uint32_t(elementIndex << kSignatureRegElementIndexShift))};
} }
}; };
@@ -243,12 +229,12 @@ 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::q() const noexcept { return VecV(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::v() 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::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kB, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH, elementIndex), id()); } ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kH, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeS, elementIndex), id()); } ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kS, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeD, elementIndex), id()); } ASMJIT_INLINE_NODEBUG VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kD, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH2, elementIndex), id()); } ASMJIT_INLINE_NODEBUG VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kH2, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB4, elementIndex), id()); } ASMJIT_INLINE_NODEBUG VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kB4, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, 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 VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); }

View File

@@ -230,7 +230,7 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstB
if (reg.as<Vec>().hasElementIndex()) { if (reg.as<Vec>().hasElementIndex()) {
// Only the first 0..15 registers can be used if the register uses // Only the first 0..15 registers can be used if the register uses
// element accessor that accesses half-words (h[0..7] elements). // element accessor that accesses half-words (h[0..7] elements).
if (instInfo.hasFlag(InstDB::kInstFlagVH0_15) && reg.as<Vec>().elementType() == Vec::kElementTypeH) { if (instInfo.hasFlag(InstDB::kInstFlagVH0_15) && reg.as<Vec>().elementType() == VecElementType::kH) {
if (Support::test(flags, RATiedFlags::kUse)) if (Support::test(flags, RATiedFlags::kUse))
useId &= 0x0000FFFFu; useId &= 0x0000FFFFu;
else else

View File

@@ -318,9 +318,9 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(
ASMJIT_PROPAGATE(sb.appendFormat("%c%u", letter, rId)); ASMJIT_PROPAGATE(sb.appendFormat("%c%u", letter, rId));
} }
constexpr uint32_t kElementTypeCount = uint32_t(a64::VecElementType::kMaxValue) + 1;
if (elementType) { if (elementType) {
if (elementType > a64::Vec::kElementTypeCount) elementType = Support::min(elementType, kElementTypeCount);
elementType = a64::Vec::kElementTypeCount;
FormatElementData elementData = formatElementDataTable[elementType]; FormatElementData elementData = formatElementDataTable[elementType];
uint32_t elementCount = elementData.elementCount; uint32_t elementCount = elementData.elementCount;

View File

@@ -239,6 +239,13 @@ 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-27
//!
//! Core changes:
//!
//! - Renamed `a64::Vec::ElementType` to `a64::VecElementType` and made it a typed enum. This enum was used mostly
//! internally, but there is a public API using it, so it's a breaking change.
//!
//! ### Changes committed at 2023-12-26 //! ### Changes committed at 2023-12-26
//! //!
//! Core changes: //! Core changes:
@@ -1045,7 +1052,7 @@ namespace asmjit {
//! //!
//! // Type-unsafe, but possible. //! // Type-unsafe, but possible.
//! a.emit(x86::Inst::kIdMov, dst, m); //! a.emit(x86::Inst::kIdMov, dst, m);
//! // Also possible, `emit()` is typeless and can be used with raw Operand. //! // Also possible, `emit()` is type-less and can be used with raw Operand.
//! a.emit(x86::Inst::kIdMov, dst, op); //! a.emit(x86::Inst::kIdMov, dst, op);
//! } //! }
//! ``` //! ```
@@ -1139,7 +1146,7 @@ namespace asmjit {
//! mem.size(); // 4. //! mem.size(); // 4.
//! mem.offset(); // 12. //! mem.offset(); // 12.
//! //!
//! mem.setSize(0); // Sets the size to 0 (makes it sizeless). //! mem.setSize(0); // Sets the size to 0 (makes it size-less).
//! mem.addOffset(-1); // Adds -1 to the offset and makes it 11. //! mem.addOffset(-1); // Adds -1 to the offset and makes it 11.
//! mem.setOffset(0); // Sets the offset to 0. //! mem.setOffset(0); // Sets the offset to 0.
//! mem.setBase(rcx); // Changes BASE to RCX. //! mem.setBase(rcx); // Changes BASE to RCX.