mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-29 04:01:27 +01:00
ARMEmitter: Handle SVE MIN/MAX immediate (unpredicated)
This commit is contained in:
1 parent
d629884147
commit
be52844ce0
2 files changed
+99
-2
No files matched your search
@@ -1459,7 +1459,19 @@ public:
|
||||
}
|
||||
|
||||
// SVE integer min/max immediate (unpredicated)
|
||||
// XXX:
|
||||
void smax(SubRegSize size, ZRegister zd, ZRegister zn, int32_t imm) {
|
||||
SVEMinMaxImmediateUnpred(0b000, size, zd, zn, imm);
|
||||
}
|
||||
void umax(SubRegSize size, ZRegister zd, ZRegister zn, int32_t imm) {
|
||||
SVEMinMaxImmediateUnpred(0b001, size, zd, zn, imm);
|
||||
}
|
||||
void smin(SubRegSize size, ZRegister zd, ZRegister zn, int32_t imm) {
|
||||
SVEMinMaxImmediateUnpred(0b010, size, zd, zn, imm);
|
||||
}
|
||||
void umin(SubRegSize size, ZRegister zd, ZRegister zn, int32_t imm) {
|
||||
SVEMinMaxImmediateUnpred(0b011, size, zd, zn, imm);
|
||||
}
|
||||
|
||||
// SVE integer multiply immediate (unpredicated)
|
||||
// XXX:
|
||||
|
||||
@@ -3181,6 +3193,29 @@ private:
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
void SVEMinMaxImmediateUnpred(uint32_t opc, SubRegSize size, ZRegister zd, ZRegister zn, int32_t imm) {
|
||||
LOGMAN_THROW_AA_FMT(size != SubRegSize::i128Bit, "Can't use 128-bit element size");
|
||||
LOGMAN_THROW_A_FMT(zd == zn, "zd needs to equal zn");
|
||||
|
||||
const bool is_signed = (opc & 1) == 0;
|
||||
if (is_signed) {
|
||||
LOGMAN_THROW_AA_FMT(imm >= -128 && imm <= 127,
|
||||
"Invalid immediate ({}). Must be within [-127, 128]", imm);
|
||||
} else {
|
||||
LOGMAN_THROW_AA_FMT(imm >= 0 && imm <= 255,
|
||||
"Invalid immediate ({}). Must be within [0, 255]", imm);
|
||||
}
|
||||
|
||||
const auto imm8 = static_cast<uint32_t>(imm) & 0xFF;
|
||||
|
||||
uint32_t Instr = 0b0010'0101'0010'1000'1100'0000'0000'0000;
|
||||
Instr |= FEXCore::ToUnderlying(size) << 22;
|
||||
Instr |= opc << 16;
|
||||
Instr |= imm8 << 5;
|
||||
Instr |= zd.Idx();
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
void SVEBroadcastImm(uint32_t opc, uint32_t sh, uint32_t imm, FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd) {
|
||||
constexpr uint32_t Op = 0b0010'0101'0011'1000'110 << 13;
|
||||
uint32_t Instr = Op;
|
||||
|
||||
+63
-1
@@ -2160,7 +2160,69 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer add/subtract immed
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer min/max immediate (unpredicated)") {
|
||||
// TODO: Implement in emitter.
|
||||
TEST_SINGLE(smax(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 0), "smax z30.b, z30.b, #0");
|
||||
TEST_SINGLE(smax(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, -128), "smax z30.b, z30.b, #-128");
|
||||
TEST_SINGLE(smax(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 127), "smax z30.b, z30.b, #127");
|
||||
|
||||
TEST_SINGLE(smax(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 0), "smax z30.h, z30.h, #0");
|
||||
TEST_SINGLE(smax(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, -128), "smax z30.h, z30.h, #-128");
|
||||
TEST_SINGLE(smax(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 127), "smax z30.h, z30.h, #127");
|
||||
|
||||
TEST_SINGLE(smax(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 0), "smax z30.s, z30.s, #0");
|
||||
TEST_SINGLE(smax(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, -128), "smax z30.s, z30.s, #-128");
|
||||
TEST_SINGLE(smax(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 127), "smax z30.s, z30.s, #127");
|
||||
|
||||
TEST_SINGLE(smax(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 0), "smax z30.d, z30.d, #0");
|
||||
TEST_SINGLE(smax(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, -128), "smax z30.d, z30.d, #-128");
|
||||
TEST_SINGLE(smax(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 127), "smax z30.d, z30.d, #127");
|
||||
|
||||
TEST_SINGLE(smin(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 0), "smin z30.b, z30.b, #0");
|
||||
TEST_SINGLE(smin(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, -128), "smin z30.b, z30.b, #-128");
|
||||
TEST_SINGLE(smin(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 127), "smin z30.b, z30.b, #127");
|
||||
|
||||
TEST_SINGLE(smin(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 0), "smin z30.h, z30.h, #0");
|
||||
TEST_SINGLE(smin(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, -128), "smin z30.h, z30.h, #-128");
|
||||
TEST_SINGLE(smin(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 127), "smin z30.h, z30.h, #127");
|
||||
|
||||
TEST_SINGLE(smin(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 0), "smin z30.s, z30.s, #0");
|
||||
TEST_SINGLE(smin(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, -128), "smin z30.s, z30.s, #-128");
|
||||
TEST_SINGLE(smin(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 127), "smin z30.s, z30.s, #127");
|
||||
|
||||
TEST_SINGLE(smin(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 0), "smin z30.d, z30.d, #0");
|
||||
TEST_SINGLE(smin(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, -128), "smin z30.d, z30.d, #-128");
|
||||
TEST_SINGLE(smin(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 127), "smin z30.d, z30.d, #127");
|
||||
|
||||
TEST_SINGLE(umax(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 0), "umax z30.b, z30.b, #0");
|
||||
TEST_SINGLE(umax(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 127), "umax z30.b, z30.b, #127");
|
||||
TEST_SINGLE(umax(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 255), "umax z30.b, z30.b, #255");
|
||||
|
||||
TEST_SINGLE(umax(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 0), "umax z30.h, z30.h, #0");
|
||||
TEST_SINGLE(umax(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 127), "umax z30.h, z30.h, #127");
|
||||
TEST_SINGLE(umax(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 255), "umax z30.h, z30.h, #255");
|
||||
|
||||
TEST_SINGLE(umax(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 0), "umax z30.s, z30.s, #0");
|
||||
TEST_SINGLE(umax(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 127), "umax z30.s, z30.s, #127");
|
||||
TEST_SINGLE(umax(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 255), "umax z30.s, z30.s, #255");
|
||||
|
||||
TEST_SINGLE(umax(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 0), "umax z30.d, z30.d, #0");
|
||||
TEST_SINGLE(umax(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 127), "umax z30.d, z30.d, #127");
|
||||
TEST_SINGLE(umax(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 255), "umax z30.d, z30.d, #255");
|
||||
|
||||
TEST_SINGLE(umin(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 0), "umin z30.b, z30.b, #0");
|
||||
TEST_SINGLE(umin(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 127), "umin z30.b, z30.b, #127");
|
||||
TEST_SINGLE(umin(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, 255), "umin z30.b, z30.b, #255");
|
||||
|
||||
TEST_SINGLE(umin(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 0), "umin z30.h, z30.h, #0");
|
||||
TEST_SINGLE(umin(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 127), "umin z30.h, z30.h, #127");
|
||||
TEST_SINGLE(umin(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, 255), "umin z30.h, z30.h, #255");
|
||||
|
||||
TEST_SINGLE(umin(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 0), "umin z30.s, z30.s, #0");
|
||||
TEST_SINGLE(umin(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 127), "umin z30.s, z30.s, #127");
|
||||
TEST_SINGLE(umin(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, 255), "umin z30.s, z30.s, #255");
|
||||
|
||||
TEST_SINGLE(umin(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 0), "umin z30.d, z30.d, #0");
|
||||
TEST_SINGLE(umin(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 127), "umin z30.d, z30.d, #127");
|
||||
TEST_SINGLE(umin(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, 255), "umin z30.d, z30.d, #255");
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer multiply immediate (unpredicated)") {
|
||||
|
||||
Reference in new issue
Block a user