TranslateArm: Implement LDM, LDMDA, LDMDB, LDMIB
This commit is contained in:
parent
46e4864707
commit
85549d7ae2
4 changed files with 86 additions and 5 deletions
|
@ -223,7 +223,10 @@ std::vector<ArmMatcher<V>> GetArmDecodeTable() {
|
|||
INST(&V::arm_STRT, "STRT (A2)", "----0110-010---------------0----"),
|
||||
|
||||
// Load/Store Multiple instructions
|
||||
INST(&V::arm_LDM, "LDM", "cccc100pu0w1nnnnxxxxxxxxxxxxxxxx"), // all
|
||||
INST(&V::arm_LDM, "LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx"), // all
|
||||
INST(&V::arm_LDMDA, "LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx"), // all
|
||||
INST(&V::arm_LDMDB, "LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx"), // all
|
||||
INST(&V::arm_LDMIB, "LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx"), // all
|
||||
INST(&V::arm_LDM_usr, "LDM (usr reg)", "----100--101--------------------"), // all
|
||||
INST(&V::arm_LDM_eret, "LDM (exce ret)", "----100--1-1----1---------------"), // all
|
||||
INST(&V::arm_STM, "STM", "cccc100pu0w0nnnnxxxxxxxxxxxxxxxx"), // all
|
||||
|
|
|
@ -367,7 +367,18 @@ public:
|
|||
std::string arm_STRT() { return "ice"; }
|
||||
|
||||
// Load/Store multiple instructions
|
||||
std::string arm_LDM(Cond cond, bool P, bool U, bool W, Reg n, RegList list) { return "ice"; }
|
||||
std::string arm_LDM(Cond cond, bool W, Reg n, RegList list) {
|
||||
return Common::StringFromFormat("ldm%s %s%s, {%s}", CondToString(cond), RegToString(n), W ? "!" : "", RegListToString(list).c_str());
|
||||
}
|
||||
std::string arm_LDMDA(Cond cond, bool W, Reg n, RegList list) {
|
||||
return Common::StringFromFormat("ldmda%s %s%s, {%s}", CondToString(cond), RegToString(n), W ? "!" : "", RegListToString(list).c_str());
|
||||
}
|
||||
std::string arm_LDMDB(Cond cond, bool W, Reg n, RegList list) {
|
||||
return Common::StringFromFormat("ldmdb%s %s%s, {%s}", CondToString(cond), RegToString(n), W ? "!" : "", RegListToString(list).c_str());
|
||||
}
|
||||
std::string arm_LDMIB(Cond cond, bool W, Reg n, RegList list) {
|
||||
return Common::StringFromFormat("ldmib%s %s%s, {%s}", CondToString(cond), RegToString(n), W ? "!" : "", RegListToString(list).c_str());
|
||||
}
|
||||
std::string arm_LDM_usr() { return "ice"; }
|
||||
std::string arm_LDM_eret() { return "ice"; }
|
||||
std::string arm_STM(Cond cond, bool P, bool U, bool W, Reg n, RegList list) { return "ice"; }
|
||||
|
|
|
@ -352,8 +352,72 @@ bool ArmTranslatorVisitor::arm_STRT() {
|
|||
return InterpretThisInstruction();
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_LDM(Cond cond, bool P, bool U, bool W, Reg n, RegList list) {
|
||||
return InterpretThisInstruction();
|
||||
static bool LDMHelper(IREmitter& ir, bool W, Reg n, RegList list, IR::Value start_address, IR::Value writeback_address) {
|
||||
auto address = start_address;
|
||||
for (size_t i = 0; i <= 14; i++) {
|
||||
if (Common::Bit(i, list)) {
|
||||
ir.SetRegister(static_cast<Reg>(i), ir.ReadMemory32(address));
|
||||
address = ir.Add(address, ir.Imm32(4));
|
||||
}
|
||||
}
|
||||
if (W) {
|
||||
ir.SetRegister(n, writeback_address);
|
||||
}
|
||||
if (Common::Bit<15>(list)) {
|
||||
ir.LoadWritePC(ir.ReadMemory32(address));
|
||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ArmTranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || Common::BitCount(list) < 1)
|
||||
return UnpredictableInstruction();
|
||||
// LDM <Rn>{!}, <reg_list>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto start_address = ir.GetRegister(n);
|
||||
auto writeback_address = ir.Add(start_address, ir.Imm32(u32(Common::BitCount(list) * 4)));
|
||||
return LDMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_LDMDA(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || Common::BitCount(list) < 1)
|
||||
return UnpredictableInstruction();
|
||||
// LDMDA <Rn>{!}, <reg_list>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list) - 4)));
|
||||
auto writeback_address = ir.Add(start_address, ir.Imm32(4));
|
||||
return LDMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_LDMDB(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || Common::BitCount(list) < 1)
|
||||
return UnpredictableInstruction();
|
||||
// LDMDB <Rn>{!}, <reg_list>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list))));
|
||||
auto writeback_address = start_address;
|
||||
return LDMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_LDMIB(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || Common::BitCount(list) < 1)
|
||||
return UnpredictableInstruction();
|
||||
// LDMIB <Rn>{!}, <reg_list>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4));
|
||||
auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list))));
|
||||
return LDMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_LDM_usr() {
|
||||
|
|
|
@ -186,7 +186,10 @@ struct ArmTranslatorVisitor final {
|
|||
bool arm_STRT();
|
||||
|
||||
// Load/Store multiple instructions
|
||||
bool arm_LDM(Cond cond, bool P, bool U, bool W, Reg n, RegList list);
|
||||
bool arm_LDM(Cond cond, bool W, Reg n, RegList list);
|
||||
bool arm_LDMDA(Cond cond, bool W, Reg n, RegList list);
|
||||
bool arm_LDMDB(Cond cond, bool W, Reg n, RegList list);
|
||||
bool arm_LDMIB(Cond cond, bool W, Reg n, RegList list);
|
||||
bool arm_LDM_usr();
|
||||
bool arm_LDM_eret();
|
||||
bool arm_STM(Cond cond, bool P, bool U, bool W, Reg n, RegList list);
|
||||
|
|
Loading…
Reference in a new issue