TranslateArm: Implement LDM, LDMDA, LDMDB, LDMIB

This commit is contained in:
MerryMage 2016-08-08 22:21:10 +01:00
parent 46e4864707
commit 85549d7ae2
4 changed files with 86 additions and 5 deletions

View file

@ -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

View file

@ -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"; }

View file

@ -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() {

View file

@ -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);