From b09ecb453261bfbaf2d1a6be17b5232780807304 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 3 Aug 2016 16:59:43 -0400 Subject: [PATCH 01/11] 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) { From caab1bbc7c9e9921c08e5af84d45feccb53136ac Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 19:35:17 -0400 Subject: [PATCH 02/11] arm: Implement STR reg/imm instructions. --- src/frontend/decoder/arm.h | 4 ++-- .../translate/translate_arm/load_store.cpp | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 72de5e93..3e586e5f 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -199,8 +199,8 @@ boost::optional&> DecodeArm(u32 instruction) { //INST(&V::arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----"), //INST(&V::arm_LDRT, "LDRT (A1)", "cccc0100u011nnnnttttvvvvvvvvvvvv"), //INST(&V::arm_LDRT, "LDRT (A2)", "cccc0110u011nnnnttttvvvvvrr0mmmm"), - //INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"), - //INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"), + INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"), + INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"), //INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"), //INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"), //INST(&V::arm_STRBT, "STRBT (A1)", "cccc0100u110nnnnttttvvvvvvvvvvvv"), diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index e5a600ce..6e61ed36 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -132,11 +132,22 @@ bool ArmTranslatorVisitor::arm_LDRT() { } bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) { - return InterpretThisInstruction(); + if (ConditionPassed(cond)) { + const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12)); + ir.WriteMemory32(address, ir.GetRegister(d)); + } + + return true; } bool ArmTranslatorVisitor::arm_STR_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 address = GetAddressingMode(ir, P, U, W, n, shifted.result); + ir.WriteMemory32(address, ir.GetRegister(d)); + } + + return true; } bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) { From a5e2116e12f0e45cd8335bf9552def0b6cf02549 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 19:35:46 -0400 Subject: [PATCH 03/11] fuzz_arm: Log write records on failure. --- tests/arm/fuzz_arm.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/arm/fuzz_arm.cpp b/tests/arm/fuzz_arm.cpp index 40a7e39b..d1c2431f 100644 --- a/tests/arm/fuzz_arm.cpp +++ b/tests/arm/fuzz_arm.cpp @@ -248,6 +248,16 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe } printf("CPSR: %08x %08x %s\n", interp.Cpsr, jit.Cpsr(), interp.Cpsr != jit.Cpsr() ? "*" : ""); + printf("\nInterp Write Records:\n"); + for (auto& record : interp_write_records) { + printf("%zu [%x] = %llx" PRIu64 "\n", record.size, record.address, record.data); + } + + printf("\nJIT Write Records:\n"); + for (auto& record : jit_write_records) { + printf("%zu [%x] = %llx" PRIu64 "\n", record.size, record.address, record.data); + } + Dynarmic::Arm::LocationDescriptor descriptor = {0, false, false, 0}; Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate(descriptor, &MemoryRead32); Dynarmic::Optimization::GetSetElimination(ir_block); From 9f77662b2424de54a929e7dd10cb73eb47ed0bee Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 19:50:01 -0400 Subject: [PATCH 04/11] arm: Implement STRB reg/imm instructions. --- src/frontend/decoder/arm.h | 4 ++-- .../translate/translate_arm/load_store.cpp | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 3e586e5f..39fa1918 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -201,8 +201,8 @@ boost::optional&> DecodeArm(u32 instruction) { //INST(&V::arm_LDRT, "LDRT (A2)", "cccc0110u011nnnnttttvvvvvrr0mmmm"), INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"), INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"), - //INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"), - //INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"), + INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"), + INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"), //INST(&V::arm_STRBT, "STRBT (A1)", "cccc0100u110nnnnttttvvvvvvvvvvvv"), //INST(&V::arm_STRBT, "STRBT (A2)", "cccc0110u110nnnnttttvvvvvrr0mmmm"), //INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index 6e61ed36..7adf59e6 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -151,11 +151,24 @@ bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, } bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) { - return InterpretThisInstruction(); + if (ConditionPassed(cond)) { + const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12)); + const auto value = (d == Reg::PC) ? ir.Imm8(ir.PC() - 8) : ir.GetRegister(d); + ir.WriteMemory8(address, value); + } + + return true; } bool ArmTranslatorVisitor::arm_STRB_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 address = GetAddressingMode(ir, P, U, W, n, shifted.result); + const auto value = (d == Reg::PC) ? ir.Imm8(ir.PC() - 8) : ir.GetRegister(d); + ir.WriteMemory8(address, value); + } + + return true; } bool ArmTranslatorVisitor::arm_STRBT() { From e931dc249690a90eabf2462733018632f172bfd8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 20:47:08 -0400 Subject: [PATCH 05/11] arm: Implement STRH reg/imm instructions. --- src/frontend/decoder/arm.h | 4 ++-- .../translate/translate_arm/load_store.cpp | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 39fa1918..ff255c9c 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -207,8 +207,8 @@ boost::optional&> DecodeArm(u32 instruction) { //INST(&V::arm_STRBT, "STRBT (A2)", "cccc0110u110nnnnttttvvvvvrr0mmmm"), //INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E //INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E - //INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"), - //INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnndddd00001011mmmm"), + INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"), + INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnndddd00001011mmmm"), //INST(&V::arm_STRHT, "STRHT (A1)", "----0000-110------------1011----"), //INST(&V::arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----"), //INST(&V::arm_STRT, "STRT (A1)", "cccc0100u010nnnnttttvvvvvvvvvvvv"), diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index 7adf59e6..e037ad0a 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -184,11 +184,23 @@ bool ArmTranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n } bool ArmTranslatorVisitor::arm_STRH_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 = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b)); + const auto value = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d); + ir.WriteMemory16(address, value); + } + + return true; } bool ArmTranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) { - return InterpretThisInstruction(); + if (ConditionPassed(cond)) { + const auto address = GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m)); + const auto value = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d); + ir.WriteMemory16(address, value); + } + + return true; } bool ArmTranslatorVisitor::arm_STRHT() { From dfb318f2088d110d802d5e4425b3c331b8e2d374 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 22:47:27 -0400 Subject: [PATCH 06/11] arm: Implement STRD reg/imm instructions. --- src/frontend/decoder/arm.h | 4 ++-- .../translate/translate_arm/load_store.cpp | 24 +++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index ff255c9c..95802411 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -205,8 +205,8 @@ boost::optional&> DecodeArm(u32 instruction) { INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"), //INST(&V::arm_STRBT, "STRBT (A1)", "cccc0100u110nnnnttttvvvvvvvvvvvv"), //INST(&V::arm_STRBT, "STRBT (A2)", "cccc0110u110nnnnttttvvvvvrr0mmmm"), - //INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E - //INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E + INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E + INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"), INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnndddd00001011mmmm"), //INST(&V::arm_STRHT, "STRHT (A1)", "----0000-110------------1011----"), diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index e037ad0a..898d2f90 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -176,11 +176,31 @@ bool ArmTranslatorVisitor::arm_STRBT() { } bool ArmTranslatorVisitor::arm_STRD_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)); + const auto value_a = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d); + const Reg reg_b = static_cast(std::min(d + 1, Reg::R15)); + const auto value_b = (reg_b == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(reg_b); + ir.WriteMemory32(address_a, value_a); + ir.WriteMemory32(address_b, value_b); + } + + return true; } bool ArmTranslatorVisitor::arm_STRD_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)); + const auto value_a = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d); + const Reg reg_b = static_cast(std::min(d + 1, Reg::R15)); + const auto value_b = (reg_b == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(reg_b); + ir.WriteMemory32(address_a, value_a); + ir.WriteMemory32(address_b, value_b); + } + + return true; } bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) { From 192a0fba7a3a5f57514567161e3ac6314c50c106 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 23:12:11 -0400 Subject: [PATCH 07/11] arm: Implement LDRB reg/imm instructions. --- src/frontend/decoder/arm.h | 4 +-- .../translate/translate_arm/load_store.cpp | 29 +++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 95802411..2b8972d2 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -179,8 +179,8 @@ boost::optional&> DecodeArm(u32 instruction) { // Load/Store instructions 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_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"), + INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"), //INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"), //INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"), //INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index 898d2f90..616e12c8 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -72,11 +72,36 @@ bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, } bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) { - return InterpretThisInstruction(); + if (ConditionPassed(cond)) { + const auto data = ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12))); + + if (d == Reg::PC) { + ir.ALUWritePC(ir.Add(data, ir.Imm32(4))); + ir.SetTerm(IR::Term::ReturnToDispatch{}); + return false; + } + + ir.SetRegister(d, data); + } + + return true; } bool ArmTranslatorVisitor::arm_LDRB_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.ReadMemory8(GetAddressingMode(ir, P, U, W, n, shifted.result)); + + if (d == Reg::PC) { + ir.ALUWritePC(ir.Add(data, ir.Imm32(4))); + ir.SetTerm(IR::Term::ReturnToDispatch{}); + return false; + } + + ir.SetRegister(d, data); + } + + return true; } bool ArmTranslatorVisitor::arm_LDRBT() { From ec3a98cf95557dc6b0b76876ac4ea7d3a0209d28 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 23:12:45 -0400 Subject: [PATCH 08/11] arm: Implement LDRH reg/imm instructions. --- src/frontend/decoder/arm.h | 4 +-- .../translate/translate_arm/load_store.cpp | 28 +++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 2b8972d2..10017d87 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -185,8 +185,8 @@ boost::optional&> DecodeArm(u32 instruction) { //INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"), //INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E //INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E - //INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"), - //INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"), + INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"), + INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"), //INST(&V::arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----"), //INST(&V::arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----"), //INST(&V::arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnddddvvvv1101vvvv"), diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index 616e12c8..47245efd 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -117,11 +117,35 @@ bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n } bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) { - return InterpretThisInstruction(); + if (ConditionPassed(cond)) { + const auto data = ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))); + + if (d == Reg::PC) { + ir.ALUWritePC(ir.Add(data, ir.Imm32(4))); + ir.SetTerm(IR::Term::ReturnToDispatch{}); + return false; + } + + ir.SetRegister(d, data); + } + + return true; } bool ArmTranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) { - return InterpretThisInstruction(); + if (ConditionPassed(cond)) { + const auto data = ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))); + + if (d == Reg::PC) { + ir.ALUWritePC(ir.Add(data, ir.Imm32(4))); + ir.SetTerm(IR::Term::ReturnToDispatch{}); + return false; + } + + ir.SetRegister(d, data); + } + + return true; } bool ArmTranslatorVisitor::arm_LDRHT() { From 72608b7af63e17adbbfaa99f9e77eb6a70a8370c Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 23:14:15 -0400 Subject: [PATCH 09/11] arm: Handle Cond::NV (some 3DS games use this despite being obsolete). --- src/frontend/translate/translate_arm.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/frontend/translate/translate_arm.cpp b/src/frontend/translate/translate_arm.cpp index cff8de81..25f52676 100644 --- a/src/frontend/translate/translate_arm.cpp +++ b/src/frontend/translate/translate_arm.cpp @@ -53,13 +53,17 @@ bool ArmTranslatorVisitor::ConditionPassed(Cond cond) { "(i.e.: one and only one conditional instruction per block)"); ASSERT_MSG(cond_state != ConditionalState::Break, "This should never happen. We requested a break but that wasn't honored."); - ASSERT_MSG(cond != Cond::NV, "NV conditional is obsolete"); if (cond == Cond::AL) { // Everything is fine with the world return true; } + if (cond == Cond::NV) { + // NV conditional is obsolete, but still seems to be used in some places! + return false; + } + // non-AL cond if (!ir.block.instructions.empty()) { From 8c2300d477cb8d637b324e0f9fae7631a903be7c Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 4 Aug 2016 23:36:58 -0400 Subject: [PATCH 10/11] arm: Implement LDRD reg/imm instructions. --- src/frontend/decoder/arm.h | 4 +- .../translate/translate_arm/load_store.cpp | 72 ++++++++++++++++++- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 10017d87..ddda1e1e 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -183,8 +183,8 @@ boost::optional&> DecodeArm(u32 instruction) { INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"), //INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"), //INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"), - //INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E - //INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E + INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E + INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"), INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"), //INST(&V::arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----"), diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index 47245efd..086e2ed0 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -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) { - 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(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) { - 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(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) { From 2448d52394244b4ec2fa155afda1923a2f2062d4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 5 Aug 2016 20:51:32 -0400 Subject: [PATCH 11/11] load_store: Use correct types for LDR/STR. --- .../translate/translate_arm/load_store.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index 086e2ed0..4ea1f12f 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -73,7 +73,7 @@ bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12) { if (ConditionPassed(cond)) { - const auto data = ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12))); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12)))); if (d == Reg::PC) { ir.ALUWritePC(ir.Add(data, ir.Imm32(4))); @@ -90,7 +90,7 @@ bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { if (ConditionPassed(cond)) { const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()); - const auto data = ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, shifted.result)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(GetAddressingMode(ir, P, U, W, n, shifted.result))); if (d == Reg::PC) { ir.ALUWritePC(ir.Add(data, ir.Imm32(4))); @@ -186,7 +186,7 @@ bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) { if (ConditionPassed(cond)) { - const auto data = ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b))); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b)))); if (d == Reg::PC) { ir.ALUWritePC(ir.Add(data, ir.Imm32(4))); @@ -202,7 +202,7 @@ bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n bool ArmTranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) { if (ConditionPassed(cond)) { - const auto data = ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m))); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m)))); if (d == Reg::PC) { ir.ALUWritePC(ir.Add(data, ir.Imm32(4))); @@ -271,7 +271,7 @@ bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n if (ConditionPassed(cond)) { const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm12)); const auto value = (d == Reg::PC) ? ir.Imm8(ir.PC() - 8) : ir.GetRegister(d); - ir.WriteMemory8(address, value); + ir.WriteMemory8(address, ir.LeastSignificantByte(value)); } return true; @@ -282,7 +282,7 @@ bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()); const auto address = GetAddressingMode(ir, P, U, W, n, shifted.result); const auto value = (d == Reg::PC) ? ir.Imm8(ir.PC() - 8) : ir.GetRegister(d); - ir.WriteMemory8(address, value); + ir.WriteMemory8(address, ir.LeastSignificantByte(value)); } return true; @@ -324,7 +324,7 @@ bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n if (ConditionPassed(cond)) { const auto address = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b)); const auto value = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d); - ir.WriteMemory16(address, value); + ir.WriteMemory16(address, ir.LeastSignificantHalf(value)); } return true; @@ -334,7 +334,7 @@ bool ArmTranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n if (ConditionPassed(cond)) { const auto address = GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m)); const auto value = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d); - ir.WriteMemory16(address, value); + ir.WriteMemory16(address, ir.LeastSignificantHalf(value)); } return true;