arm: Implement LDR reg/imm instructions.
This commit is contained in:
parent
856298577d
commit
b09ecb4532
2 changed files with 58 additions and 4 deletions
|
@ -177,8 +177,8 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
//INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnndddd00001001mmmm"), // v2S (v6: Deprecated)
|
//INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnndddd00001001mmmm"), // v2S (v6: Deprecated)
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store instructions
|
||||||
//INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"),
|
||||||
//INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
|
//INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
|
||||||
//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"),
|
||||||
|
|
|
@ -9,12 +9,66 @@
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace Arm {
|
namespace Arm {
|
||||||
|
|
||||||
|
static IR::Value GetAddressingMode(IREmitter& ir, bool P, bool U, bool W, Reg n, IR::Value index) {
|
||||||
|
IR::Value address;
|
||||||
|
if (P) {
|
||||||
|
// Pre-indexed addressing
|
||||||
|
if (n == Reg::PC && index.IsImmediate()) {
|
||||||
|
address = U ? ir.Imm32(ir.AlignPC(4) + index.GetU32()) : ir.Imm32(ir.AlignPC(4) - index.GetU32());
|
||||||
|
} else {
|
||||||
|
address = U ? ir.Add(ir.GetRegister(n), index) : ir.Sub(ir.GetRegister(n), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrote calculated address back to the base register
|
||||||
|
if (W) {
|
||||||
|
ir.SetRegister(n, address);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Post-indexed addressing
|
||||||
|
address = (n == Reg::PC) ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
|
||||||
|
|
||||||
|
if (U) {
|
||||||
|
ir.SetRegister(n, ir.Add(ir.GetRegister(n), index));
|
||||||
|
} else {
|
||||||
|
ir.SetRegister(n, ir.Sub(ir.GetRegister(n), index));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bunnei): Handle W=1 mode, which in this scenario does an unprivileged (User mode) access.
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12)));
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.BXWritePC(data);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(d, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
const auto data = ir.ReadMemory32(GetAddressingMode(ir, P, U, W, n, shifted.result));
|
||||||
|
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ir.BXWritePC(data);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.SetRegister(d, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) {
|
||||||
|
|
Loading…
Reference in a new issue