thumb32: Implement STMDB/STMFD

This commit is contained in:
Lioncash 2021-03-12 18:53:25 -05:00
parent 91c4d59da9
commit 714ccf13dd
3 changed files with 33 additions and 3 deletions

View file

@ -5,7 +5,7 @@ INST(thumb32_STMIA, "STMIA/STMEA", "1110100010W0nnnn0iiiii
//INST(thumb32_POP, "POP", "1110100010111101----------------") //INST(thumb32_POP, "POP", "1110100010111101----------------")
//INST(thumb32_LDMIA, "LDMIA/LDMFD", "1110100010-1--------------------") //INST(thumb32_LDMIA, "LDMIA/LDMFD", "1110100010-1--------------------")
//INST(thumb32_PUSH, "PUSH", "1110100100101101----------------") //INST(thumb32_PUSH, "PUSH", "1110100100101101----------------")
//INST(thumb32_STMDB, "STMDB/STMFD", "1110100100-0--------------------") INST(thumb32_STMDB, "STMDB/STMFD", "1110100100W0nnnn0iiiiiiiiiiiiiii")
//INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100-1--------------------") //INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100-1--------------------")
//INST(thumb32_SRS_1, "SRS", "1110100110-0--------------------") //INST(thumb32_SRS_1, "SRS", "1110100110-0--------------------")
//INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------") //INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------")

View file

@ -26,10 +26,9 @@ bool ThumbTranslatorVisitor::thumb32_STMIA(bool W, Reg n, Imm<15> reg_list) {
for (size_t i = 0; i < 15; i++) { for (size_t i = 0; i < 15; i++) {
if (Common::Bit(i, regs_imm)) { if (Common::Bit(i, regs_imm)) {
ir.WriteMemory32(address, ir.GetRegister(static_cast<Reg>(i))); ir.WriteMemory32(address, ir.GetRegister(static_cast<Reg>(i)));
}
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
} }
}
if (W) { if (W) {
ir.SetRegister(n, address); ir.SetRegister(n, address);
@ -37,4 +36,34 @@ bool ThumbTranslatorVisitor::thumb32_STMIA(bool W, Reg n, Imm<15> reg_list) {
return true; return true;
} }
bool ThumbTranslatorVisitor::thumb32_STMDB(bool W, Reg n, Imm<15> reg_list) {
const auto regs_imm = reg_list.ZeroExtend();
const auto num_regs = static_cast<u32>(Common::BitCount(regs_imm));
if (n == Reg::PC || num_regs < 2) {
return UnpredictableInstruction();
}
if (W && Common::Bit(static_cast<size_t>(n), regs_imm)) {
return UnpredictableInstruction();
}
if (reg_list.Bit<13>()) {
return UnpredictableInstruction();
}
const IR::U32 start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(4 * num_regs));
IR::U32 address = start_address;
for (size_t i = 0; i < 15; i++) {
if (Common::Bit(i, regs_imm)) {
ir.WriteMemory32(address, ir.GetRegister(static_cast<Reg>(i)));
address = ir.Add(address, ir.Imm32(4));
}
}
if (W) {
ir.SetRegister(n, start_address);
}
return true;
}
} // namespace Dynarmic::A32 } // namespace Dynarmic::A32

View file

@ -173,6 +173,7 @@ struct ThumbTranslatorVisitor final {
// thumb32 load/store multiple instructions // thumb32 load/store multiple instructions
bool thumb32_STMIA(bool W, Reg n, Imm<15> reg_list); bool thumb32_STMIA(bool W, Reg n, Imm<15> reg_list);
bool thumb32_STMDB(bool W, Reg n, Imm<15> reg_list);
// thumb32 data processing (shifted register) instructions // thumb32 data processing (shifted register) instructions
bool thumb32_TST_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m); bool thumb32_TST_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m);