ARMEmitter: Add comparison functions to register types

Gets rid of the need to compare indices directly in order to compare
register equality
This commit is contained in:
Lioncache committed 2023-03-01 21:15:46 -05:00
1 parent 0f45318040
commit 52b4378e49
3 files changed
+109 -88

No files matched your search

@@ -1,5 +1,8 @@
#pragma once
#include <FEXCore/Utils/EnumUtils.h>
#include <compare>
#include <cstdint>
namespace FEXCore::ARMEmitter {
@@ -15,6 +18,8 @@ namespace FEXCore::ARMEmitter {
constexpr explicit Register(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const Register&, const Register&) = default;
uint32_t Idx() const {
return Index;
}
@@ -41,9 +46,7 @@ namespace FEXCore::ARMEmitter {
constexpr explicit WRegister(uint32_t Idx)
: Index {Idx} {}
bool operator==(const WRegister &rhs) {
return Idx() == rhs.Idx();
}
friend constexpr auto operator<=>(const WRegister&, const WRegister&) = default;
uint32_t Idx() const {
return Index;
@@ -75,9 +78,7 @@ namespace FEXCore::ARMEmitter {
constexpr explicit XRegister(uint32_t Idx)
: Index {Idx} {}
bool operator==(const XRegister &rhs) {
return Idx() == rhs.Idx();
}
friend constexpr auto operator<=>(const XRegister&, const XRegister&) = default;
uint32_t Idx() const {
return Index;
@@ -294,6 +295,8 @@ namespace FEXCore::ARMEmitter {
constexpr explicit VRegister(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const VRegister&, const VRegister&) = default;
uint32_t Idx() const {
return Index;
}
@@ -321,6 +324,8 @@ namespace FEXCore::ARMEmitter {
constexpr explicit BRegister(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const BRegister&, const BRegister&) = default;
uint32_t Idx() const {
return Index;
}
@@ -352,6 +357,8 @@ namespace FEXCore::ARMEmitter {
constexpr explicit HRegister(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const HRegister&, const HRegister&) = default;
uint32_t Idx() const {
return Index;
}
@@ -383,6 +390,8 @@ namespace FEXCore::ARMEmitter {
constexpr explicit SRegister(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const SRegister&, const SRegister&) = default;
uint32_t Idx() const {
return Index;
}
@@ -415,6 +424,8 @@ namespace FEXCore::ARMEmitter {
constexpr explicit DRegister(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const DRegister&, const DRegister&) = default;
uint32_t Idx() const {
return Index;
}
@@ -447,6 +458,8 @@ namespace FEXCore::ARMEmitter {
constexpr explicit QRegister(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const QRegister&, const QRegister&) = default;
uint32_t Idx() const {
return Index;
}
@@ -478,6 +491,8 @@ namespace FEXCore::ARMEmitter {
constexpr explicit ZRegister(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const ZRegister&, const ZRegister&) = default;
uint32_t Idx() const {
return Index;
}
@@ -933,6 +948,8 @@ namespace FEXCore::ARMEmitter {
constexpr PRegister(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const PRegister&, const PRegister&) = default;
operator uint32_t() const {
return Index;
}
@@ -961,6 +978,8 @@ namespace FEXCore::ARMEmitter {
constexpr PRegisterZero(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const PRegisterZero&, const PRegisterZero&) = default;
operator uint32_t() const {
return Index;
}
@@ -989,6 +1008,8 @@ namespace FEXCore::ARMEmitter {
constexpr PRegisterMerge(uint32_t Idx)
: Index {Idx} {}
friend constexpr auto operator<=>(const PRegisterMerge&, const PRegisterMerge&) = default;
operator uint32_t() const {
return Index;
}
@@ -68,7 +68,7 @@ public:
void histcnt(SubRegSize size, ZRegister zd, PRegisterZero pv, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_AA_FMT(size == SubRegSize::i32Bit || size == SubRegSize::i64Bit, "SubRegSize must be 32-bit or 64-bit");
LOGMAN_THROW_A_FMT(pv <= PReg::p7, "histcnt can only use p0 to p7");
LOGMAN_THROW_A_FMT(pv <= PReg::p7.Zeroing(), "histcnt can only use p0 to p7");
uint32_t Op = 0b0100'0101'0010'0000'1100'0000'0000'0000;
Op |= FEXCore::ToUnderlying(size) << 22;
@@ -115,7 +115,7 @@ public:
void fcmla(SubRegSize size, ZRegister zda, PRegisterMerge pv, ZRegister zn, ZRegister zm, Rotation rot) {
LOGMAN_THROW_AA_FMT(size == SubRegSize::i16Bit || size == SubRegSize::i32Bit || size == SubRegSize::i64Bit,
"SubRegSize must be 16-bit, 32-bit, or 64-bit");
LOGMAN_THROW_A_FMT(pv <= PReg::p7, "fcmla can only use p0 to p7");
LOGMAN_THROW_A_FMT(pv <= PReg::p7.Merging(), "fcmla can only use p0 to p7");
uint32_t Op = 0b0110'0100'0000'0000'0000'0000'0000'0000;
Op |= FEXCore::ToUnderlying(size) << 22;
@@ -131,10 +131,10 @@ public:
void fcadd(SubRegSize size, ZRegister zd, PRegisterMerge pv, ZRegister zn, ZRegister zm, Rotation rot) {
LOGMAN_THROW_AA_FMT(size == SubRegSize::i16Bit || size == SubRegSize::i32Bit || size == SubRegSize::i64Bit,
"SubRegSize must be 16-bit, 32-bit, or 64-bit");
LOGMAN_THROW_A_FMT(pv <= PReg::p7, "fcadd can only use p0 to p7");
LOGMAN_THROW_A_FMT(pv <= PReg::p7.Merging(), "fcadd can only use p0 to p7");
LOGMAN_THROW_AA_FMT(rot == Rotation::ROTATE_90 || rot == Rotation::ROTATE_270,
"fcadd rotation may only be 90 or 270 degrees");
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "fcadd zd and zn must be the same register");
LOGMAN_THROW_A_FMT(zd == zn, "fcadd zd and zn must be the same register");
const uint32_t ConvertedRotation = rot == Rotation::ROTATE_90 ? 0 : 1;
@@ -424,7 +424,7 @@ public:
// XXX: BFCVTNT
// SVE2 floating-point pairwise operations
void faddp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0100'0001'0000'100 << 13;;
@@ -432,28 +432,28 @@ public:
}
void fmaxnmp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0100'0001'0000'100 << 13;;
SVEFloatPairwiseArithmetic(Op, 0b100, size, pg, zm, zd);
}
void fminnmp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0100'0001'0000'100 << 13;;
SVEFloatPairwiseArithmetic(Op, 0b101, size, pg, zm, zd);
}
void fmaxp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0100'0001'0000'100 << 13;;
SVEFloatPairwiseArithmetic(Op, 0b110, size, pg, zm, zd);
}
void fminp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0100'0001'0000'100 << 13;;
@@ -591,32 +591,32 @@ public:
// SVE integer min/max/difference (predicated)
void smax(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEIntegerMinMaxDifferencePredicated(0b00, 0, size, pg, zm, zd);
}
void umax(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEIntegerMinMaxDifferencePredicated(0b00, 1, size, pg, zm, zd);
}
void smin(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEIntegerMinMaxDifferencePredicated(0b01, 0, size, pg, zm, zd);
}
void umin(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEIntegerMinMaxDifferencePredicated(0b01, 1, size, pg, zm, zd);
}
void sabd(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEIntegerMinMaxDifferencePredicated(0b10, 0, size, pg, zm, zd);
}
void uabd(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEIntegerMinMaxDifferencePredicated(0b10, 1, size, pg, zm, zd);
}
@@ -663,25 +663,25 @@ public:
// SVE bitwise logical operations (predicated)
void orr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0000'0100'0001'1000'000 << 13;
SVEBitwiseLogicalPredicated(Op, 0b000, size, pg, zm, zd);
}
void eor(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0000'0100'0001'1000'000 << 13;
SVEBitwiseLogicalPredicated(Op, 0b001, size, pg, zm, zd);
}
void and_(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0000'0100'0001'1000'000 << 13;
SVEBitwiseLogicalPredicated(Op, 0b010, size, pg, zm, zd);
}
void bic(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0000'0100'0001'1000'000 << 13;
SVEBitwiseLogicalPredicated(Op, 0b011, size, pg, zm, zd);
}
@@ -776,35 +776,35 @@ public:
// SVE bitwise shift by vector (predicated)
void asr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEBitwiseShiftbyVector(0, 0, 0, size, pg, zm, zd);
}
void lsr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEBitwiseShiftbyVector(0, 0, 1, size, pg, zm, zd);
}
void lsl(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEBitwiseShiftbyVector(0, 1, 1, size, pg, zm, zd);
}
void asrr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEBitwiseShiftbyVector(1, 0, 0, size, pg, zm, zd);
}
void lsrr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEBitwiseShiftbyVector(1, 0, 1, size, pg, zm, zd);
}
void lslr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEBitwiseShiftbyVector(1, 1, 1, size, pg, zm, zd);
}
@@ -940,27 +940,27 @@ public:
// SVE2 bitwise ternary operations
void eor3(FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm, FEXCore::ARMEmitter::ZRegister zk) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVE2BitwiseTernary(0b00, 0, zm, zk, zd);
}
void bsl(FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm, FEXCore::ARMEmitter::ZRegister zk) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVE2BitwiseTernary(0b00, 1, zm, zk, zd);
}
void bcax(FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm, FEXCore::ARMEmitter::ZRegister zk) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVE2BitwiseTernary(0b01, 0, zm, zk, zd);
}
void bsl1n(FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm, FEXCore::ARMEmitter::ZRegister zk) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVE2BitwiseTernary(0b01, 1, zm, zk, zd);
}
void bsl2n(FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm, FEXCore::ARMEmitter::ZRegister zk) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVE2BitwiseTernary(0b10, 1, zm, zk, zd);
}
void nbsl(FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm, FEXCore::ARMEmitter::ZRegister zk) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVE2BitwiseTernary(0b11, 1, zm, zk, zd);
}
@@ -1179,7 +1179,7 @@ public:
template<OpType optype>
requires(optype == OpType::Destructive)
void splice(SubRegSize size, ZRegister zd, PRegister pv, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd needs to equal zn");
LOGMAN_THROW_A_FMT(zd == zn, "zd needs to equal zn");
SVEPermuteVectorPredicated(0b01100, 0b0, size, zd, pv, zm);
}
@@ -1220,21 +1220,21 @@ public:
// SVE conditionally broadcast element to vector
void clasta(SubRegSize size, ZRegister zd, PRegister pg, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd must be the same as zn");
LOGMAN_THROW_A_FMT(zd == zn, "zd must be the same as zn");
SVEPermuteVectorPredicated(0b01000, 0b0, size, zd, pg, zm);
}
void clastb(SubRegSize size, ZRegister zd, PRegister pg, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd must be the same as zn");
LOGMAN_THROW_A_FMT(zd == zn, "zd must be the same as zn");
SVEPermuteVectorPredicated(0b01001, 0b0, size, zd, pg, zm);
}
// SVE conditionally extract element to SIMD&FP scalar
void clasta(SubRegSize size, VRegister vd, PRegister pg, VRegister vn, ZRegister zm) {
LOGMAN_THROW_A_FMT(vd.Idx() == vn.Idx(), "vd must be the same as vn");
LOGMAN_THROW_A_FMT(vd == vn, "vd must be the same as vn");
SVEPermuteVectorPredicated(0b01010, 0b0, size, ZRegister{vd.Idx()}, pg, zm);
}
void clastb(SubRegSize size, VRegister vd, PRegister pg, VRegister vn, ZRegister zm) {
LOGMAN_THROW_A_FMT(vd.Idx() == vn.Idx(), "vd must be the same as vn");
LOGMAN_THROW_A_FMT(vd == vn, "vd must be the same as vn");
SVEPermuteVectorPredicated(0b01011, 0b0, size, ZRegister{vd.Idx()}, pg, zm);
}
@@ -1243,11 +1243,11 @@ public:
// SVE conditionally extract element to general register
void clasta(SubRegSize size, Register rd, PRegister pg, Register rn, ZRegister zm) {
LOGMAN_THROW_A_FMT(rd.Idx() == rn.Idx(), "rd must be the same as rn");
LOGMAN_THROW_A_FMT(rd == rn, "rd must be the same as rn");
SVEPermuteVectorPredicated(0b10000, 0b1, size, ZRegister{rd.Idx()}, pg, zm);
}
void clastb(SubRegSize size, Register rd, PRegister pg, Register rn, ZRegister zm) {
LOGMAN_THROW_A_FMT(rd.Idx() == rn.Idx(), "rd must be the same as rn");
LOGMAN_THROW_A_FMT(rd == rn, "rd must be the same as rn");
SVEPermuteVectorPredicated(0b10001, 0b1, size, ZRegister{rd.Idx()}, pg, zm);
}
@@ -1264,7 +1264,7 @@ public:
template<OpType optype>
requires(optype == OpType::Destructive)
void ext(ZRegister zd, ZRegister zdn, ZRegister zm, uint8_t Imm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
SVEPermuteVector(0, zd, zm, Imm);
}
@@ -1590,49 +1590,49 @@ public:
// SVE2 integer halving add/subtract (predicated)
void shadd(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'100 << 13;
SVE2IntegerHalvingPredicated(Op, 0, 0, 0, size, pg, zm, zd);
}
void uhadd(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'100 << 13;
SVE2IntegerHalvingPredicated(Op, 0, 0, 1, size, pg, zm, zd);
}
void shsub(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'100 << 13;
SVE2IntegerHalvingPredicated(Op, 0, 1, 0, size, pg, zm, zd);
}
void uhsub(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'100 << 13;
SVE2IntegerHalvingPredicated(Op, 0, 1, 1, size, pg, zm, zd);
}
void srhadd(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'100 << 13;
SVE2IntegerHalvingPredicated(Op, 1, 0, 0, size, pg, zm, zd);
}
void urhadd(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'100 << 13;
SVE2IntegerHalvingPredicated(Op, 1, 0, 1, size, pg, zm, zd);
}
void shsubr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'100 << 13;
SVE2IntegerHalvingPredicated(Op, 1, 1, 0, size, pg, zm, zd);
}
void uhsubr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'100 << 13;
SVE2IntegerHalvingPredicated(Op, 1, 1, 1, size, pg, zm, zd);
}
@@ -1640,31 +1640,31 @@ public:
// SVE2 integer pairwise arithmetic
void addp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'101 << 13;
SVEIntegerPairwiseArithmetic(Op, 0b00, 1, size, pg, zm, zd);
}
void smaxp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'101 << 13;
SVEIntegerPairwiseArithmetic(Op, 0b10, 0, size, pg, zm, zd);
}
void umaxp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'101 << 13;
SVEIntegerPairwiseArithmetic(Op, 0b10, 1, size, pg, zm, zd);
}
void sminp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'101 << 13;
SVEIntegerPairwiseArithmetic(Op, 0b11, 0, size, pg, zm, zd);
}
void uminp(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
constexpr uint32_t Op = 0b0100'0100'0001'0000'101 << 13;
SVEIntegerPairwiseArithmetic(Op, 0b11, 1, size, pg, zm, zd);
}
@@ -2039,79 +2039,79 @@ public:
// XXX: FTMAD
// SVE floating-point arithmetic (predicated)
void fadd(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b0000, size, pg, zm, zd);
}
void fsub(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b0001, size, pg, zm, zd);
}
void fmul(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b0010, size, pg, zm, zd);
}
void fsubr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b0011, size, pg, zm, zd);
}
void fmaxnm(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b0100, size, pg, zm, zd);
}
void fminnm(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b0101, size, pg, zm, zd);
}
void fmax(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b0110, size, pg, zm, zd);
}
void fmin(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b0111, size, pg, zm, zd);
}
void fabd(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b1000, size, pg, zm, zd);
}
void fscale(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b1001, size, pg, zm, zd);
}
void fmulx(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b1010, size, pg, zm, zd);
}
void fdivr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b1100, size, pg, zm, zd);
}
void fdiv(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "Dest needs to equal zdn");
LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit || size == FEXCore::ARMEmitter::SubRegSize::i64Bit, "Invalid float size");
constexpr uint32_t Op = 0b0110'0101'0000'0000'100 << 13;
SVEFloatArithmeticPredicated(Op, 0b1101, size, pg, zm, zd);
@@ -3271,7 +3271,7 @@ private:
void SVECharacterMatch(uint32_t op, uint32_t opc, SubRegSize size, PRegister pd, PRegisterZero pg, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_AA_FMT(size == SubRegSize::i8Bit || size == SubRegSize::i16Bit,
"match/nmatch can only use 8-bit or 16-bit element sizes");
LOGMAN_THROW_A_FMT(pg <= PReg::p7, "match/nmatch can only use p0-p7 as a governing predicate");
LOGMAN_THROW_A_FMT(pg <= PReg::p7.Zeroing(), "match/nmatch can only use p0-p7 as a governing predicate");
uint32_t Instr = op;
Instr |= FEXCore::ToUnderlying(size) << 22;
@@ -3298,8 +3298,8 @@ private:
}
void SVEAddSubVectorsPredicated(uint32_t op, uint32_t opc, SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(pg <= PReg::p7, "Add/Sub operation can only use p0-p7 as a governing predicate");
LOGMAN_THROW_A_FMT(zd == zn, "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(pg <= PReg::p7.Merging(), "Add/Sub operation can only use p0-p7 as a governing predicate");
uint32_t Instr = op;
Instr |= FEXCore::ToUnderlying(size) << 22;
@@ -3311,8 +3311,8 @@ private:
}
void SVEIntegerMulDivVectorsPredicated(uint32_t op, uint32_t opc, SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(pg <= PReg::p7, "Mul/Div operation can only use p0-p7 as a governing predicate");
LOGMAN_THROW_A_FMT(zd == zn, "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(pg <= PReg::p7.Merging(), "Mul/Div operation can only use p0-p7 as a governing predicate");
uint32_t Instr = op;
Instr |= FEXCore::ToUnderlying(size) << 22;
@@ -3364,8 +3364,8 @@ private:
void SVE2IntegerSaturatingAddSub(SubRegSize size, uint32_t opc, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_A_FMT(size != SubRegSize::i128Bit, "Can't use 128-bit element size");
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(pg <= PReg::p7, "Saturing add/subtract can only use p0-p7 as a governing predicate");
LOGMAN_THROW_A_FMT(zd == zn, "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(pg <= PReg::p7.Merging(), "Saturing add/subtract can only use p0-p7 as a governing predicate");
uint32_t Instr = 0b0100'0100'0001'1000'1000'0000'0000'0000;
Instr |= FEXCore::ToUnderlying(size) << 22;
@@ -3379,8 +3379,8 @@ private:
void SVEBitwiseShiftByWideElementPredicated(SubRegSize size, uint32_t opc, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit && size != SubRegSize::i128Bit,
"Can't use 64-bit or 128-bit element size");
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(pg <= PReg::p7, "Wide shift can only use p0-p7 as a governing predicate");
LOGMAN_THROW_A_FMT(zd == zn, "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(pg <= PReg::p7.Merging(), "Wide shift can only use p0-p7 as a governing predicate");
uint32_t Instr = 0b0000'0100'0001'1000'1000'0000'0000'0000;
Instr |= FEXCore::ToUnderlying(size) << 22;
@@ -3606,7 +3606,7 @@ private:
void SVE2ComplexIntAdd(SubRegSize size, uint32_t opc, Rotation rot, ZRegister zd, ZRegister zn, ZRegister zm) {
LOGMAN_THROW_A_FMT(size != SubRegSize::i128Bit, "Complex add cannot use 128-bit element size");
LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(zd == zn, "zd and zn must be the same register");
LOGMAN_THROW_A_FMT(rot == Rotation::ROTATE_90 || rot == Rotation::ROTATE_270,
"Rotation must be 90 or 270 degrees");
@@ -3807,7 +3807,7 @@ private:
void SVEBitWiseShiftImmediatePred(SubRegSize size, uint32_t opc, uint32_t L, uint32_t U, PRegister pg, ZRegister zd, ZRegister zdn, uint32_t Shift) {
LOGMAN_THROW_AA_FMT(size != SubRegSize::i128Bit, "Can't use 128-bit element size");
LOGMAN_THROW_A_FMT(zd.Idx() == zdn.Idx(), "zd needs to equal zdn");
LOGMAN_THROW_A_FMT(zd == zdn, "zd needs to equal zdn");
LOGMAN_THROW_A_FMT(pg <= PReg::p7, "Can only use p0-p7 as a governing predicate");
const auto ElementSize = SubRegSizeInBits(size);
@@ -245,9 +245,9 @@ DEF_OP(InlineSyscall) {
if (Op->Header.Args[i].IsInvalid()) break;
auto Reg = GetReg(Op->Header.Args[i].ID());
if (Reg.Idx() == ARMEmitter::Reg::r8.Idx() ||
Reg.Idx() == ARMEmitter::Reg::r4.Idx() ||
Reg.Idx() == ARMEmitter::Reg::r5.Idx()) {
if (Reg == ARMEmitter::Reg::r8 ||
Reg == ARMEmitter::Reg::r4 ||
Reg == ARMEmitter::Reg::r5) {
SpillMask |= (1U << Reg.Idx());
Intersects = true;
@@ -278,13 +278,13 @@ DEF_OP(InlineSyscall) {
// In the case of intersection with x4, x5, or x8 then these are currently SRA
// for registers RAX, RBX, and RSI. Which have just been spilled
// Just load back from the context. Could be slightly smarter but this is fairly uncommon
if (Reg.Idx() == FEXCore::ARMEmitter::Reg::r8.Idx()) {
if (Reg == ARMEmitter::Reg::r8) {
ldr(EmitSubSize, RegArgs[i].R(), STATE, offsetof(FEXCore::Core::CpuStateFrame, State.gregs[X86State::REG_RSI]));
}
else if (Reg.Idx() == FEXCore::ARMEmitter::Reg::r4.Idx()) {
else if (Reg == ARMEmitter::Reg::r4) {
ldr(EmitSubSize, RegArgs[i].R(), STATE, offsetof(FEXCore::Core::CpuStateFrame, State.gregs[X86State::REG_RAX]));
}
else if (Reg.Idx() == FEXCore::ARMEmitter::Reg::r5.Idx()) {
else if (Reg == ARMEmitter::Reg::r5) {
ldr(EmitSubSize, RegArgs[i].R(), STATE, offsetof(FEXCore::Core::CpuStateFrame, State.gregs[X86State::REG_RBX]));
}
else {