From b09ecb453261bfbaf2d1a6be17b5232780807304 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 3 Aug 2016 16:59:43 -0400 Subject: [PATCH] arm: Implement LDR reg/imm instructions. --- src/frontend/decoder/arm.h | 4 +- .../translate/translate_arm/load_store.cpp | 58 ++++++++++++++++++- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 15cfa982..72de5e93 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -177,8 +177,8 @@ boost::optional&> DecodeArm(u32 instruction) { //INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnndddd00001001mmmm"), // v2S (v6: Deprecated) // Load/Store instructions - //INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"), - //INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"), + INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"), + INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"), //INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"), //INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"), //INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"), diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index 1d7df9fd..e5a600ce 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -9,12 +9,66 @@ namespace Dynarmic { 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) { - 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) { - 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) {