TranslateArm: Implement STM, STMDA, STMDB, STMIB

This commit is contained in:
MerryMage 2016-08-08 22:49:11 +01:00
parent 5d26899ac9
commit d0d51ba346
4 changed files with 83 additions and 6 deletions

View file

@ -229,7 +229,10 @@ std::vector<ArmMatcher<V>> GetArmDecodeTable() {
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
INST(&V::arm_STM, "STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx"), // all
INST(&V::arm_STMDA, "STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx"), // all
INST(&V::arm_STMDB, "STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx"), // all
INST(&V::arm_STMIB, "STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx"), // all
INST(&V::arm_STM_usr, "STM (usr reg)", "----100--100--------------------"), // all
// Miscellaneous instructions

View file

@ -381,7 +381,18 @@ public:
}
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"; }
std::string arm_STM(Cond cond, bool W, Reg n, RegList list) {
return Common::StringFromFormat("stm%s %s%s, {%s}", CondToString(cond), RegToString(n), W ? "!" : "", RegListToString(list).c_str());
}
std::string arm_STMDA(Cond cond, bool W, Reg n, RegList list) {
return Common::StringFromFormat("stmda%s %s%s, {%s}", CondToString(cond), RegToString(n), W ? "!" : "", RegListToString(list).c_str());
}
std::string arm_STMDB(Cond cond, bool W, Reg n, RegList list) {
return Common::StringFromFormat("stmdb%s %s%s, {%s}", CondToString(cond), RegToString(n), W ? "!" : "", RegListToString(list).c_str());
}
std::string arm_STMIB(Cond cond, bool W, Reg n, RegList list) {
return Common::StringFromFormat("stmib%s %s%s, {%s}", CondToString(cond), RegToString(n), W ? "!" : "", RegListToString(list).c_str());
}
std::string arm_STM_usr() { return "ice"; }
// Miscellaneous instructions

View file

@ -371,7 +371,6 @@ static bool LDMHelper(IREmitter& ir, bool W, Reg n, RegList list, IR::Value star
return true;
}
bool ArmTranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || Common::BitCount(list) < 1)
return UnpredictableInstruction();
@ -428,8 +427,69 @@ bool ArmTranslatorVisitor::arm_LDM_eret() {
return InterpretThisInstruction();
}
bool ArmTranslatorVisitor::arm_STM(Cond cond, bool P, bool U, bool W, Reg n, RegList list) {
return InterpretThisInstruction();
static bool STMHelper(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.WriteMemory32(address, ir.GetRegister(static_cast<Reg>(i)));
address = ir.Add(address, ir.Imm32(4));
}
}
if (W) {
ir.SetRegister(n, writeback_address);
}
if (Common::Bit<15>(list)) {
ir.WriteMemory32(address, ir.Imm32(ir.PC()));
}
return true;
}
bool ArmTranslatorVisitor::arm_STM(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || Common::BitCount(list) < 1)
return UnpredictableInstruction();
// STM <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 STMHelper(ir, W, n, list, start_address, writeback_address);
}
return true;
}
bool ArmTranslatorVisitor::arm_STMDA(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || Common::BitCount(list) < 1)
return UnpredictableInstruction();
// STMDA <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 STMHelper(ir, W, n, list, start_address, writeback_address);
}
return true;
}
bool ArmTranslatorVisitor::arm_STMDB(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || Common::BitCount(list) < 1)
return UnpredictableInstruction();
// STMDB <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 STMHelper(ir, W, n, list, start_address, writeback_address);
}
return true;
}
bool ArmTranslatorVisitor::arm_STMIB(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || Common::BitCount(list) < 1)
return UnpredictableInstruction();
// STMIB <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 STMHelper(ir, W, n, list, start_address, writeback_address);
}
return true;
}
bool ArmTranslatorVisitor::arm_STM_usr() {

View file

@ -192,7 +192,10 @@ struct ArmTranslatorVisitor final {
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);
bool arm_STM(Cond cond, bool W, Reg n, RegList list);
bool arm_STMDA(Cond cond, bool W, Reg n, RegList list);
bool arm_STMDB(Cond cond, bool W, Reg n, RegList list);
bool arm_STMIB(Cond cond, bool W, Reg n, RegList list);
bool arm_STM_usr();
// Miscellaneous instructions