arm: Implement LDRD reg/imm instructions.

This commit is contained in:
bunnei 2016-08-04 23:36:58 -04:00
parent 72608b7af6
commit 8c2300d477
2 changed files with 72 additions and 4 deletions

View file

@ -183,8 +183,8 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"), INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"),
//INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"), //INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"),
//INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"), //INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"),
//INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E
//INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E
INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"), INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"),
INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"), INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"),
//INST(&V::arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----"), //INST(&V::arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----"),

View file

@ -109,11 +109,79 @@ bool ArmTranslatorVisitor::arm_LDRBT() {
} }
bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {
return InterpretThisInstruction(); if (ConditionPassed(cond)) {
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b));
const auto address_b = ir.Add(address_a, ir.Imm32(4));
auto data_a = ir.ReadMemory32(address_a);
auto data_b = ir.ReadMemory32(address_b);
switch(d) {
case Reg::PC:
data_a = ir.Add(data_a, ir.Imm32(4));
break;
case Reg::LR:
data_b = ir.Add(data_b, ir.Imm32(4));
break;
}
if (d == Reg::PC) {
ir.ALUWritePC(data_a);
} else {
ir.SetRegister(d, data_a);
}
const Reg reg_b = static_cast<Reg>(std::min(d + 1, Reg::R15));
if (reg_b == Reg::PC) {
ir.ALUWritePC(data_b);
} else {
ir.SetRegister(reg_b, data_b);
}
if (d == Reg::PC || reg_b == Reg::PC) {
ir.SetTerm(IR::Term::ReturnToDispatch{});
return false;
}
}
return true;
} }
bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) { bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) {
return InterpretThisInstruction(); if (ConditionPassed(cond)) {
const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m));
const auto address_b = ir.Add(address_a, ir.Imm32(4));
auto data_a = ir.ReadMemory32(address_a);
auto data_b = ir.ReadMemory32(address_b);
switch(d) {
case Reg::PC:
data_a = ir.Add(data_a, ir.Imm32(4));
break;
case Reg::LR:
data_b = ir.Add(data_b, ir.Imm32(4));
break;
}
if (d == Reg::PC) {
ir.ALUWritePC(data_a);
} else {
ir.SetRegister(d, data_a);
}
const Reg reg_b = static_cast<Reg>(std::min(d + 1, Reg::R15));
if (reg_b == Reg::PC) {
ir.ALUWritePC(data_b);
} else {
ir.SetRegister(reg_b, data_b);
}
if (d == Reg::PC || reg_b == Reg::PC) {
ir.SetTerm(IR::Term::ReturnToDispatch{});
return false;
}
}
return true;
} }
bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) { bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) {