mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-27 13:00:47 +01:00
ArmEmitter: Adds three more classes of ASIMD instructions
Adds three classes: - Advanced SIMD three same (FP16) - Advanced SIMD two-register miscellaneous (FP16) - Advanced SIMD three-register extension A handful of the three-register extension unit tests are disabled because the vixl disassembler doesn't support them. Only six more classes of ASIMD operations remaining once this is merged.
This commit is contained in:
1 parent
1521e0a248
commit
d787a38744
3 files changed
+632
-6
No files matched your search
+465
-3
@@ -335,6 +335,59 @@ public:
|
||||
ASIMDScalarCopy(Op, Q, imm5, 0b0000, rd.V(), rn.V());
|
||||
}
|
||||
|
||||
// Advanced SIMD three same (FP16)
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void ASIMDThreeSameFP16(uint32_t U, uint32_t a, uint32_t opcode, T rm, T rn, T rd) {
|
||||
constexpr uint32_t Q = std::is_same_v<FEXCore::ARMEmitter::QRegister, T> ? 1U << 30 : 0;
|
||||
constexpr uint32_t Op = 0b0000'1110'0100'0000'0000'01 << 10;
|
||||
|
||||
uint32_t Instr = Op;
|
||||
Instr |= Q;
|
||||
Instr |= U << 29;
|
||||
Instr |= a << 23;
|
||||
Instr |= rm.Idx() << 16;
|
||||
Instr |= opcode << 11;
|
||||
Instr |= rn.Idx() << 5;
|
||||
Instr |= rd.Idx();
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// Advanced SIMD two-register miscellaneous (FP16)
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void ASIMDTwoRegMiscFP16(uint32_t U, uint32_t a, uint32_t opcode, T rn, T rd) {
|
||||
constexpr uint32_t Q = std::is_same_v<FEXCore::ARMEmitter::QRegister, T> ? 1U << 30 : 0;
|
||||
constexpr uint32_t Op = 0b0000'1110'0111'1000'0000'10 << 10;
|
||||
|
||||
uint32_t Instr = Op;
|
||||
Instr |= Q;
|
||||
Instr |= U << 29;
|
||||
Instr |= a << 23;
|
||||
Instr |= opcode << 12;
|
||||
Instr |= rn.Idx() << 5;
|
||||
Instr |= rd.Idx();
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// Advanced SIMD three-register extension
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void ASIMDThreeRegisterExt(uint32_t U, uint32_t opcode, FEXCore::ARMEmitter::SubRegSize size, T rm, T rn, T rd) {
|
||||
constexpr uint32_t Q = std::is_same_v<FEXCore::ARMEmitter::QRegister, T> ? 1U << 30 : 0;
|
||||
constexpr uint32_t Op = 0b0000'1110'0000'0000'1000'01 << 10;
|
||||
|
||||
uint32_t Instr = Op;
|
||||
Instr |= Q;
|
||||
Instr |= U << 29;
|
||||
Instr |= FEXCore::ToUnderlying(size) << 22;
|
||||
Instr |= rm.Idx() << 16;
|
||||
Instr |= opcode << 11;
|
||||
Instr |= rn.Idx() << 5;
|
||||
Instr |= rd.Idx();
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void dup(FEXCore::ARMEmitter::SubRegSize size, T rd, FEXCore::ARMEmitter::Register rn) {
|
||||
@@ -532,11 +585,420 @@ public:
|
||||
|
||||
|
||||
// Advanced SIMD three same (FP16)
|
||||
// TODO
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmaxnm(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 0, 0b000, rm, rn, rd);
|
||||
}
|
||||
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmla(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 0, 0b001, rm, rn, rd);
|
||||
}
|
||||
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fadd(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 0, 0b010, rm, rn, rd);
|
||||
}
|
||||
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmulx(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 0, 0b011, rm, rn, rd);
|
||||
}
|
||||
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcmeq(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 0, 0b100, rm, rn, rd);
|
||||
}
|
||||
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmax(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 0, 0b110, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frecps(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 0, 0b111, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fminnm(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 1, 0b000, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmls(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 1, 0b001, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fsub(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 1, 0b010, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmin(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 1, 0b110, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frsqrts(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(0, 1, 0b111, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmaxnmp(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 0, 0b000, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void faddp(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 0, 0b010, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmul(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 0, 0b011, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcmge(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 0, 0b100, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void facge(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 0, 0b101, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fmaxp(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 0, 0b110, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fdiv(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 0, 0b111, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fminnmp(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 1, 0b000, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fabd(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 1, 0b010, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcmgt(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 1, 0b100, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void facgt(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 1, 0b101, rm, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fminp(T rd, T rn, T rm) {
|
||||
ASIMDThreeSameFP16(1, 1, 0b110, rm, rn, rd);
|
||||
}
|
||||
|
||||
// Advanced SIMD two-register miscellaneous (FP16)
|
||||
// TODO
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frintn(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 0, 0b11000, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frintm(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 0, 0b11001, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtns(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 0, 0b11010, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtms(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 0, 0b11011, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtas(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 0, 0b11100, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void scvtf(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 0, 0b11101, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcmgt(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b01100, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcmeq(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b01101, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcmlt(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b01110, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fabs(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b01111, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frintp(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b11000, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frintz(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b11001, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtps(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b11010, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtzs(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b11011, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frecpe(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(0, 1, 0b11101, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frinta(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 0, 0b11000, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frintx(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 0, 0b11001, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtnu(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 0, 0b11010, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtmu(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 0, 0b11011, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtau(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 0, 0b11100, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void ucvtf(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 0, 0b11101, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcmge(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 1, 0b01100, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcmle(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 1, 0b01101, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fneg(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 1, 0b01111, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frinti(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 1, 0b11001, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtpu(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 1, 0b11010, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fcvtzu(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 1, 0b11011, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void frsqrte(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 1, 0b11101, rn, rd);
|
||||
}
|
||||
template<FEXCore::ARMEmitter::SubRegSize size, typename T>
|
||||
requires(size == FEXCore::ARMEmitter::SubRegSize::i16Bit &&
|
||||
(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>))
|
||||
void fsqrt(T rd, T rn) {
|
||||
ASIMDTwoRegMiscFP16(1, 1, 0b11111, rn, rd);
|
||||
}
|
||||
|
||||
// Advanced SIMD three-register extension
|
||||
// TODO
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void sdot(FEXCore::ARMEmitter::SubRegSize size, T rd, T rn, T rm) {
|
||||
if constexpr (std::is_same_v<FEXCore::ARMEmitter::DRegister, T>) {
|
||||
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported");
|
||||
}
|
||||
ASIMDThreeRegisterExt(0, 0b0010, size, rm, rn, rd);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void usdot(T rd, T rn, T rm) {
|
||||
ASIMDThreeRegisterExt(0, 0b0011, FEXCore::ARMEmitter::SubRegSize::i32Bit, rm, rn, rd);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void sqrdmlah(FEXCore::ARMEmitter::SubRegSize size, T rd, T rn, T rm) {
|
||||
if constexpr (std::is_same_v<FEXCore::ARMEmitter::DRegister, T>) {
|
||||
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported");
|
||||
}
|
||||
ASIMDThreeRegisterExt(1, 0b0000, size, rm, rn, rd);
|
||||
}
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void sqrdmlsh(FEXCore::ARMEmitter::SubRegSize size, T rd, T rn, T rm) {
|
||||
if constexpr (std::is_same_v<FEXCore::ARMEmitter::DRegister, T>) {
|
||||
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported");
|
||||
}
|
||||
ASIMDThreeRegisterExt(1, 0b0001, size, rm, rn, rd);
|
||||
}
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void udot(FEXCore::ARMEmitter::SubRegSize size, T rd, T rn, T rm) {
|
||||
if constexpr (std::is_same_v<FEXCore::ARMEmitter::DRegister, T>) {
|
||||
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported");
|
||||
}
|
||||
ASIMDThreeRegisterExt(1, 0b0010, size, rm, rn, rd);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void fcmla(FEXCore::ARMEmitter::SubRegSize size, T rd, T rn, T rm, FEXCore::ARMEmitter::Rotation Rot) {
|
||||
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i8Bit, "8-bit subregsize not supported");
|
||||
|
||||
if constexpr (std::is_same_v<FEXCore::ARMEmitter::DRegister, T>) {
|
||||
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported");
|
||||
}
|
||||
ASIMDThreeRegisterExt(1, 0b1000 | FEXCore::ToUnderlying(Rot), size, rm, rn, rd);
|
||||
}
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void fcadd(FEXCore::ARMEmitter::SubRegSize size, T rd, T rn, T rm, FEXCore::ARMEmitter::Rotation Rot) {
|
||||
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i8Bit, "8-bit subregsize not supported");
|
||||
|
||||
if constexpr (std::is_same_v<FEXCore::ARMEmitter::DRegister, T>) {
|
||||
LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported");
|
||||
}
|
||||
LOGMAN_THROW_A_FMT(Rot == FEXCore::ARMEmitter::Rotation::ROTATE_90 || Rot == FEXCore::ARMEmitter::Rotation::ROTATE_270, "Invalid rotation");
|
||||
const uint32_t ConvertedRotation =
|
||||
Rot == FEXCore::ARMEmitter::Rotation::ROTATE_90 ? 0b00 : 0b10;
|
||||
ASIMDThreeRegisterExt(1, 0b1100 | ConvertedRotation, size, rm, rn, rd);
|
||||
}
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
void bfdot(T rd, T rn, T rm) {
|
||||
ASIMDThreeRegisterExt(1, 0b1111, FEXCore::ARMEmitter::SubRegSize::i16Bit, rm, rn, rd);
|
||||
}
|
||||
void bfmlalb(ARMEmitter::VRegister rd, ARMEmitter::VRegister rn, ARMEmitter::VRegister rm) {
|
||||
ASIMDThreeRegisterExt(1, 0b1111, FEXCore::ARMEmitter::SubRegSize::i64Bit, rm.D(), rn.D(), rd.D());
|
||||
}
|
||||
void bfmlalt(ARMEmitter::VRegister rd, ARMEmitter::VRegister rn, ARMEmitter::VRegister rm) {
|
||||
ASIMDThreeRegisterExt(1, 0b1111, FEXCore::ARMEmitter::SubRegSize::i64Bit, rm.Q(), rn.Q(), rd.Q());
|
||||
}
|
||||
void smmla(ARMEmitter::VRegister rd, ARMEmitter::VRegister rn, ARMEmitter::VRegister rm) {
|
||||
ASIMDThreeRegisterExt(0, 0b0100, FEXCore::ARMEmitter::SubRegSize::i32Bit, rm.Q(), rn.Q(), rd.Q());
|
||||
}
|
||||
void usmmla(ARMEmitter::VRegister rd, ARMEmitter::VRegister rn, ARMEmitter::VRegister rm) {
|
||||
ASIMDThreeRegisterExt(0, 0b0101, FEXCore::ARMEmitter::SubRegSize::i32Bit, rm.Q(), rn.Q(), rd.Q());
|
||||
}
|
||||
void bfmmla(ARMEmitter::VRegister rd, ARMEmitter::VRegister rn, ARMEmitter::VRegister rm) {
|
||||
ASIMDThreeRegisterExt(1, 0b1101, FEXCore::ARMEmitter::SubRegSize::i16Bit, rm.Q(), rn.Q(), rd.Q());
|
||||
}
|
||||
void ummla(ARMEmitter::VRegister rd, ARMEmitter::VRegister rn, ARMEmitter::VRegister rm) {
|
||||
ASIMDThreeRegisterExt(1, 0b0100, FEXCore::ARMEmitter::SubRegSize::i32Bit, rm.Q(), rn.Q(), rd.Q());
|
||||
}
|
||||
|
||||
// Advanced SIMD two-register miscellaneous
|
||||
template<typename T>
|
||||
requires(std::is_same_v<FEXCore::ARMEmitter::QRegister, T> || std::is_same_v<FEXCore::ARMEmitter::DRegister, T>)
|
||||
|
||||
@@ -535,6 +535,14 @@ namespace FEXCore::ARMEmitter {
|
||||
ForwardLabel Forward;
|
||||
};
|
||||
|
||||
// Some FCMA ASIMD instructions support a rotation argument.
|
||||
enum class Rotation : uint32_t {
|
||||
ROTATE_0 = 0b00,
|
||||
ROTATE_90 = 0b01,
|
||||
ROTATE_180 = 0b10,
|
||||
ROTATE_270 = 0b11,
|
||||
};
|
||||
|
||||
// This is an emitter that is designed around the smallest code bloat as possible.
|
||||
// Eschewing most developer convenience in order to keep code as small as possible.
|
||||
|
||||
|
||||
+159
-3
@@ -249,13 +249,169 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD copy") {
|
||||
TEST_SINGLE(ins(SubRegSize::i64Bit, VReg::v30, 1, VReg::v29, 0), "mov v30.d[1], v29.d[0]");
|
||||
}
|
||||
TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD three same (FP16)") {
|
||||
// TODO: Implement in emitter.
|
||||
TEST_SINGLE(fmaxnm<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmaxnm v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fmla<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmla v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fadd<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fadd v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fmulx<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmulx v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fcmeq<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fcmeq v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fmax<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmax v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(frecps<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "frecps v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fminnm<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fminnm v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fmls<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmls v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fsub<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fsub v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fmin<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmin v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(frsqrts<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "frsqrts v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fmaxnmp<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmaxnmp v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(faddp<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "faddp v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fmul<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmul v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fcmge<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fcmge v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(facge<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "facge v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fmaxp<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fmaxp v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fdiv<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fdiv v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fminnmp<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fminnmp v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fabd<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fabd v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fcmgt<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fcmgt v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(facgt<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "facgt v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(fminp<SubRegSize::i16Bit>(QReg::q30, QReg::q29, QReg::q28), "fminp v30.8h, v29.8h, v28.8h");
|
||||
}
|
||||
TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD two-register miscellaneous (FP16)") {
|
||||
// TODO: Implement in emitter.
|
||||
TEST_SINGLE(frintn<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frintn v30.8h, v29.8h");
|
||||
TEST_SINGLE(frintm<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frintm v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtns<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtns v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtms<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtms v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtas<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtas v30.8h, v29.8h");
|
||||
TEST_SINGLE(scvtf<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "scvtf v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcmgt<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcmgt v30.8h, v29.8h, #0.0");
|
||||
TEST_SINGLE(fcmeq<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcmeq v30.8h, v29.8h, #0.0");
|
||||
TEST_SINGLE(fcmlt<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcmlt v30.8h, v29.8h, #0.0");
|
||||
TEST_SINGLE(fabs<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fabs v30.8h, v29.8h");
|
||||
TEST_SINGLE(frintp<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frintp v30.8h, v29.8h");
|
||||
TEST_SINGLE(frintz<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frintz v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtps<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtps v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtzs<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtzs v30.8h, v29.8h");
|
||||
TEST_SINGLE(frecpe<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frecpe v30.8h, v29.8h");
|
||||
TEST_SINGLE(frinta<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frinta v30.8h, v29.8h");
|
||||
TEST_SINGLE(frintx<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frintx v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtnu<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtnu v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtmu<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtmu v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtau<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtau v30.8h, v29.8h");
|
||||
TEST_SINGLE(ucvtf<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "ucvtf v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcmge<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcmge v30.8h, v29.8h, #0.0");
|
||||
TEST_SINGLE(fcmle<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcmle v30.8h, v29.8h, #0.0");
|
||||
TEST_SINGLE(fneg<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fneg v30.8h, v29.8h");
|
||||
TEST_SINGLE(frinti<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frinti v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtpu<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtpu v30.8h, v29.8h");
|
||||
TEST_SINGLE(fcvtzu<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fcvtzu v30.8h, v29.8h");
|
||||
TEST_SINGLE(frsqrte<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "frsqrte v30.8h, v29.8h");
|
||||
TEST_SINGLE(fsqrt<SubRegSize::i16Bit>(QReg::q30, QReg::q29), "fsqrt v30.8h, v29.8h");
|
||||
}
|
||||
TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD three-register extension") {
|
||||
// TODO: Implement in emitter.
|
||||
TEST_SINGLE(sdot(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28), "sdot v30.16b, v29.16b, v28.16b");
|
||||
TEST_SINGLE(sdot(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "sdot v30.8h, v29.16b, v28.16b");
|
||||
TEST_SINGLE(sdot(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28), "sdot v30.4s, v29.16b, v28.16b");
|
||||
TEST_SINGLE(sdot(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28), "sdot v30.2d, v29.16b, v28.16b");
|
||||
TEST_SINGLE(sdot(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28), "sdot v30.8b, v29.8b, v28.8b");
|
||||
TEST_SINGLE(sdot(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28), "sdot v30.4h, v29.8b, v28.8b");
|
||||
TEST_SINGLE(sdot(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28), "sdot v30.2s, v29.8b, v28.8b");
|
||||
//TEST_SINGLE(sdot(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28), "sdot v30.1d, v29.8b, v28.8b");
|
||||
|
||||
TEST_SINGLE(usdot(QReg::q30, QReg::q29, QReg::q28), "usdot v30.4s, v29.16b, v28.16b");
|
||||
TEST_SINGLE(usdot(DReg::d30, DReg::d29, DReg::d28), "usdot v30.2s, v29.8b, v28.8b");
|
||||
|
||||
TEST_SINGLE(sqrdmlah(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28), "sqrdmlah v30.16b, v29.16b, v28.16b");
|
||||
TEST_SINGLE(sqrdmlah(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "sqrdmlah v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(sqrdmlah(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28), "sqrdmlah v30.4s, v29.4s, v28.4s");
|
||||
TEST_SINGLE(sqrdmlah(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28), "sqrdmlah v30.2d, v29.2d, v28.2d");
|
||||
TEST_SINGLE(sqrdmlah(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28), "sqrdmlah v30.8b, v29.8b, v28.8b");
|
||||
TEST_SINGLE(sqrdmlah(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28), "sqrdmlah v30.4h, v29.4h, v28.4h");
|
||||
TEST_SINGLE(sqrdmlah(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28), "sqrdmlah v30.2s, v29.2s, v28.2s");
|
||||
//TEST_SINGLE(sqrdmlah(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28), "sqrdmlah v30.1d, v29.1d, v28.1d");
|
||||
|
||||
TEST_SINGLE(sqrdmlsh(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28), "sqrdmlsh v30.16b, v29.16b, v28.16b");
|
||||
TEST_SINGLE(sqrdmlsh(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "sqrdmlsh v30.8h, v29.8h, v28.8h");
|
||||
TEST_SINGLE(sqrdmlsh(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28), "sqrdmlsh v30.4s, v29.4s, v28.4s");
|
||||
TEST_SINGLE(sqrdmlsh(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28), "sqrdmlsh v30.2d, v29.2d, v28.2d");
|
||||
TEST_SINGLE(sqrdmlsh(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28), "sqrdmlsh v30.8b, v29.8b, v28.8b");
|
||||
TEST_SINGLE(sqrdmlsh(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28), "sqrdmlsh v30.4h, v29.4h, v28.4h");
|
||||
TEST_SINGLE(sqrdmlsh(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28), "sqrdmlsh v30.2s, v29.2s, v28.2s");
|
||||
//TEST_SINGLE(sqrdmlsh(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28), "sqrdmlsh v30.1d, v29.1d, v28.1d");
|
||||
|
||||
TEST_SINGLE(udot(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28), "udot v30.16b, v29.16b, v28.16b");
|
||||
TEST_SINGLE(udot(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "udot v30.8h, v29.16b, v28.16b");
|
||||
TEST_SINGLE(udot(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28), "udot v30.4s, v29.16b, v28.16b");
|
||||
TEST_SINGLE(udot(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28), "udot v30.2d, v29.16b, v28.16b");
|
||||
TEST_SINGLE(udot(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28), "udot v30.8b, v29.8b, v28.8b");
|
||||
TEST_SINGLE(udot(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28), "udot v30.4h, v29.8b, v28.8b");
|
||||
TEST_SINGLE(udot(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28), "udot v30.2s, v29.8b, v28.8b");
|
||||
//TEST_SINGLE(udot(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28), "udot v30.1d, v29.8b, v28.8b");
|
||||
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_0), "fcmla v30.16b, v29.16b, v28.16b, #0");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_0), "fcmla v30.8h, v29.8h, v28.8h, #0");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_0), "fcmla v30.4s, v29.4s, v28.4s, #0");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_0), "fcmla v30.2d, v29.2d, v28.2d, #0");
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_0), "fcmla v30.8b, v29.8b, v28.8b, #0");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_0), "fcmla v30.4h, v29.4h, v28.4h, #0");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_0), "fcmla v30.2s, v29.2s, v28.2s, #0");
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_0), "fcmla v30.1d, v29.1d, v28.1d, #0");
|
||||
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_90), "fcmla v30.16b, v29.16b, v28.16b, #90");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_90), "fcmla v30.8h, v29.8h, v28.8h, #90");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_90), "fcmla v30.4s, v29.4s, v28.4s, #90");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_90), "fcmla v30.2d, v29.2d, v28.2d, #90");
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_90), "fcmla v30.8b, v29.8b, v28.8b, #90");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_90), "fcmla v30.4h, v29.4h, v28.4h, #90");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_90), "fcmla v30.2s, v29.2s, v28.2s, #90");
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_90), "fcmla v30.1d, v29.1d, v28.1d, #90");
|
||||
|
||||
// Vixl disassembler has a bug that claims 8-bit fcmla exists
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_180), "fcmla v30.16b, v29.16b, v28.16b, #180");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_180), "fcmla v30.8h, v29.8h, v28.8h, #180");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_180), "fcmla v30.4s, v29.4s, v28.4s, #180");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_180), "fcmla v30.2d, v29.2d, v28.2d, #180");
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_180), "fcmla v30.8b, v29.8b, v28.8b, #180");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_180), "fcmla v30.4h, v29.4h, v28.4h, #180");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_180), "fcmla v30.2s, v29.2s, v28.2s, #180");
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_180), "fcmla v30.1d, v29.1d, v28.1d, #180");
|
||||
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_270), "fcmla v30.16b, v29.16b, v28.16b, #270");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_270), "fcmla v30.8h, v29.8h, v28.8h, #270");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_270), "fcmla v30.4s, v29.4s, v28.4s, #270");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_270), "fcmla v30.2d, v29.2d, v28.2d, #270");
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_270), "fcmla v30.8b, v29.8b, v28.8b, #270");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_270), "fcmla v30.4h, v29.4h, v28.4h, #270");
|
||||
TEST_SINGLE(fcmla(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_270), "fcmla v30.2s, v29.2s, v28.2s, #270");
|
||||
//TEST_SINGLE(fcmla(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_270), "fcmla v30.1d, v29.1d, v28.1d, #270");
|
||||
|
||||
// Vixl disassembler has a bug that claims 8-bit fcadd exists
|
||||
//TEST_SINGLE(fcadd(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_90), "fcadd v30.16b, v29.16b, v28.16b, #90");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_90), "fcadd v30.8h, v29.8h, v28.8h, #90");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_90), "fcadd v30.4s, v29.4s, v28.4s, #90");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_90), "fcadd v30.2d, v29.2d, v28.2d, #90");
|
||||
//TEST_SINGLE(fcadd(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_90), "fcadd v30.8b, v29.8b, v28.8b, #90");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_90), "fcadd v30.4h, v29.4h, v28.4h, #90");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_90), "fcadd v30.2s, v29.2s, v28.2s, #90");
|
||||
//TEST_SINGLE(fcadd(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_90), "fcadd v30.1d, v29.1d, v28.1d, #90");
|
||||
|
||||
//TEST_SINGLE(fcadd(SubRegSize::i8Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_270), "fcadd v30.16b, v29.16b, v28.16b, #270");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_270), "fcadd v30.8h, v29.8h, v28.8h, #270");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_270), "fcadd v30.4s, v29.4s, v28.4s, #270");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i64Bit, QReg::q30, QReg::q29, QReg::q28, Rotation::ROTATE_270), "fcadd v30.2d, v29.2d, v28.2d, #270");
|
||||
//TEST_SINGLE(fcadd(SubRegSize::i8Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_270), "fcadd v30.8b, v29.8b, v28.8b, #270");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i16Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_270), "fcadd v30.4h, v29.4h, v28.4h, #270");
|
||||
TEST_SINGLE(fcadd(SubRegSize::i32Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_270), "fcadd v30.2s, v29.2s, v28.2s, #270");
|
||||
//TEST_SINGLE(fcadd(SubRegSize::i64Bit, DReg::d30, DReg::d29, DReg::d28, Rotation::ROTATE_270), "fcadd v30.1d, v29.1d, v28.1d, #270");
|
||||
|
||||
// TODO: Enable once vixl disassembler supports these instructions
|
||||
// TEST_SINGLE(bfdot(QReg::q30, QReg::q29, QReg::q28), "bfdot v30.4s, v29.8h, v28.8h");
|
||||
// TEST_SINGLE(bfdot(DReg::d30, DReg::d29, DReg::d28), "bfdot v30.2s, v29.4h, v28.4h");
|
||||
// TEST_SINGLE(bfmlalb(VReg::v30, VReg::v29, VReg::v28), "bfmlalb v30.4s, v29.8h, v28.8h");
|
||||
// TEST_SINGLE(bfmlalt(VReg::v30, VReg::v29, VReg::v28), "bfmlalt v30.4s, v29.8h, v28.8h");
|
||||
|
||||
TEST_SINGLE(smmla(VReg::v30, VReg::v29, VReg::v28), "smmla v30.4s, v29.16b, v28.16b");
|
||||
TEST_SINGLE(usmmla(VReg::v30, VReg::v29, VReg::v28), "usmmla v30.4s, v29.16b, v28.16b");
|
||||
// TODO: Enable once vixl disassembler supports these instructions
|
||||
//TEST_SINGLE(bfmmla(VReg::v30, VReg::v29, VReg::v28), "bfmmla v30.4s, v29.8h, v28.8h");
|
||||
TEST_SINGLE(ummla(VReg::v30, VReg::v29, VReg::v28), "ummla v30.4s, v29.16b, v28.16b");
|
||||
}
|
||||
TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD two-register miscellaneous") {
|
||||
// Commented out lines showcase unallocated encodings.
|
||||
|
||||
Reference in new issue
Block a user