diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index 20fed89a..63292053 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -6,7 +6,7 @@ INST(thumb32_STMIA, "STMIA/STMEA", "1110100010W0nnnn0iiiii INST(thumb32_LDMIA, "LDMIA/LDMFD", "1110100010W1nnnniiiiiiiiiiiiiiii") //INST(thumb32_PUSH, "PUSH", "1110100100101101----------------") INST(thumb32_STMDB, "STMDB/STMFD", "1110100100W0nnnn0iiiiiiiiiiiiiii") -//INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100-1--------------------") +INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100W1nnnniiiiiiiiiiiiiiii") //INST(thumb32_SRS_1, "SRS", "1110100110-0--------------------") //INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------") diff --git a/src/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp b/src/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp index 6b76d6d5..b538bfef 100644 --- a/src/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp +++ b/src/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp @@ -51,6 +51,31 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, return true; } +bool ThumbTranslatorVisitor::thumb32_LDMDB(bool W, Reg n, Imm<16> reg_list) { + const auto regs_imm = reg_list.ZeroExtend(); + const auto num_regs = static_cast(Common::BitCount(regs_imm)); + + if (n == Reg::PC || num_regs < 2) { + return UnpredictableInstruction(); + } + if (reg_list.Bit<15>() && reg_list.Bit<14>()) { + return UnpredictableInstruction(); + } + if (W && Common::Bit(static_cast(n), regs_imm)) { + return UnpredictableInstruction(); + } + if (reg_list.Bit<13>()) { + return UnpredictableInstruction(); + } + if (reg_list.Bit<15>() && ITBlockCheck(ir)) { + return UnpredictableInstruction(); + } + + // Start address is the same as the writeback address. + const IR::U32 start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(4 * num_regs)); + return LDMHelper(ir, W, n, regs_imm, start_address, start_address); +} + bool ThumbTranslatorVisitor::thumb32_LDMIA(bool W, Reg n, Imm<16> reg_list) { const auto regs_imm = reg_list.ZeroExtend(); const auto num_regs = static_cast(Common::BitCount(regs_imm)); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index a4728a16..5a066cdd 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -172,6 +172,7 @@ struct ThumbTranslatorVisitor final { bool thumb16_B_t2(Imm<11> imm11); // thumb32 load/store multiple instructions + bool thumb32_LDMDB(bool W, Reg n, Imm<16> reg_list); bool thumb32_LDMIA(bool W, Reg n, Imm<16> reg_list); bool thumb32_STMIA(bool W, Reg n, Imm<15> reg_list); bool thumb32_STMDB(bool W, Reg n, Imm<15> reg_list);