CodeEmitter/LoadstoreOps: Add Load/store register (PAC) group

Eh, what the heck. Gets rid of the last TODO marker in the base load-stores.
This commit is contained in:
Lioncache committed 2025-04-19 13:00:00 -04:00
1 parent c8371087e6
commit 4e6f183f77
2 files changed
+49 -2

No files matched your search

+30 -1
View File
@@ -4182,7 +4182,12 @@ public:
}
// Loadstore PAC
// TODO
void ldraa(XRegister rt, XRegister rn, IndexType type, int32_t offset = 0) {
LoadStorePAC(0b11, 0, 0, offset, type, rn, rt);
}
void ldrab(XRegister rt, XRegister rn, IndexType type, int32_t offset = 0) {
LoadStorePAC(0b11, 0, 1, offset, type, rn, rt);
}
// Loadstore unsigned immediate
// Maximum values of unsigned immediate offsets for particular data sizes.
@@ -4411,6 +4416,30 @@ private:
dc32(Instr);
}
void LoadStorePAC(uint32_t size, uint32_t VR, uint32_t M, int32_t imm, IndexType type, Register rn, Register rt) {
LOGMAN_THROW_A_FMT((imm % 8) == 0, "Immediate ({}) must be divisible by 8", imm);
LOGMAN_THROW_A_FMT(imm >= -4096 && imm <= 4088, "Immediate ({}) must be within [-4096, 4088]", imm);
LOGMAN_THROW_A_FMT(type == IndexType::OFFSET || type == IndexType::PRE, "PAC may only use offset or pre-indexed values");
// The immediate is scaled down in order to fit within the available 10 immediate bits.
const auto scaled_imm = static_cast<uint32_t>(imm / 8);
const auto imm9 = scaled_imm & 0b1'1111'1111;
const auto S = (scaled_imm >> 9) & 1;
const auto W = type == IndexType::OFFSET ? 0U : 1U;
uint32_t Instr = 0b0011'1000'0010'0000'0000'0100'0000'0000;
Instr |= size << 30;
Instr |= VR << 26;
Instr |= M << 23;
Instr |= S << 22;
Instr |= imm9 << 12;
Instr |= W << 11;
Instr |= rn.Idx() << 5;
Instr |= rt.Idx();
dc32(Instr);
}
// Loadstore unsigned immediate
template<typename T>
void LoadStoreUnsigned(uint32_t size, uint32_t V, uint32_t opc, T rt, Register rn, uint32_t Imm) {
+19 -1
View File
@@ -2906,7 +2906,25 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: Loadstore: Loadstore register-regis
}
TEST_CASE_METHOD(TestDisassembler, "Emitter: Loadstore: Loadstore PAC") {
// TODO: Implement in emitter.
TEST_SINGLE(ldraa(XReg::x30, XReg::x29, ARMEmitter::IndexType::OFFSET, 0), "ldraa x30, [x29]");
TEST_SINGLE(ldraa(XReg::x30, XReg::x29, ARMEmitter::IndexType::OFFSET, -4096), "ldraa x30, [x29, #-4096]");
TEST_SINGLE(ldraa(XReg::x30, XReg::x29, ARMEmitter::IndexType::OFFSET, 512), "ldraa x30, [x29, #512]");
TEST_SINGLE(ldraa(XReg::x30, XReg::x29, ARMEmitter::IndexType::OFFSET, 4088), "ldraa x30, [x29, #4088]");
TEST_SINGLE(ldraa(XReg::x30, XReg::x29, ARMEmitter::IndexType::PRE, 0), "ldraa x30, [x29]!");
TEST_SINGLE(ldraa(XReg::x30, XReg::x29, ARMEmitter::IndexType::PRE, -4096), "ldraa x30, [x29, #-4096]!");
TEST_SINGLE(ldraa(XReg::x30, XReg::x29, ARMEmitter::IndexType::PRE, 512), "ldraa x30, [x29, #512]!");
TEST_SINGLE(ldraa(XReg::x30, XReg::x29, ARMEmitter::IndexType::PRE, 4088), "ldraa x30, [x29, #4088]!");
TEST_SINGLE(ldrab(XReg::x30, XReg::x29, ARMEmitter::IndexType::OFFSET, 0), "ldrab x30, [x29]");
TEST_SINGLE(ldrab(XReg::x30, XReg::x29, ARMEmitter::IndexType::OFFSET, -4096), "ldrab x30, [x29, #-4096]");
TEST_SINGLE(ldrab(XReg::x30, XReg::x29, ARMEmitter::IndexType::OFFSET, 512), "ldrab x30, [x29, #512]");
TEST_SINGLE(ldrab(XReg::x30, XReg::x29, ARMEmitter::IndexType::OFFSET, 4088), "ldrab x30, [x29, #4088]");
TEST_SINGLE(ldrab(XReg::x30, XReg::x29, ARMEmitter::IndexType::PRE, 0), "ldrab x30, [x29]!");
TEST_SINGLE(ldrab(XReg::x30, XReg::x29, ARMEmitter::IndexType::PRE, -4096), "ldrab x30, [x29, #-4096]!");
TEST_SINGLE(ldrab(XReg::x30, XReg::x29, ARMEmitter::IndexType::PRE, 512), "ldrab x30, [x29, #512]!");
TEST_SINGLE(ldrab(XReg::x30, XReg::x29, ARMEmitter::IndexType::PRE, 4088), "ldrab x30, [x29, #4088]!");
}
TEST_CASE_METHOD(TestDisassembler, "Emitter: Loadstore: Loadstore unsigned immediate") {