From 4b1c27e64fc7854778df25b49d00e879643da50c Mon Sep 17 00:00:00 2001 From: MerryMage Date: Thu, 14 Jul 2016 20:02:41 +0100 Subject: [PATCH] Implement arm_ADC_imm --- src/frontend/decoder/arm.h | 4 +- .../disassembler/disassembler_arm.cpp | 2 +- src/frontend/translate/translate_arm.cpp | 180 +++++++++++++++++- src/frontend/translate/translate_thumb.cpp | 6 +- tests/arm/fuzz_arm.cpp | 11 +- 5 files changed, 193 insertions(+), 10 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 85e83ac0..62f8cfda 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -59,7 +59,7 @@ private: }; template -static const std::array, 2> g_arm_instruction_table = { +static const std::array, 3> g_arm_instruction_table = { #define INST(fn, name, bitstring) detail::detail::GetMatcher(name, bitstring) @@ -88,7 +88,7 @@ static const std::array, 2> g_arm_instruction_table = { //INST(&V::arm_STC, "STC", "----110----0--------------------"), // v2 // Data Processing instructions - //INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv"), // all + INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv"), // all //INST(&V::arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm"), // all //INST(&V::arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm"), // all //INST(&V::arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv"), // all diff --git a/src/frontend/disassembler/disassembler_arm.cpp b/src/frontend/disassembler/disassembler_arm.cpp index 1f8ce1d7..0ded3cc1 100644 --- a/src/frontend/disassembler/disassembler_arm.cpp +++ b/src/frontend/disassembler/disassembler_arm.cpp @@ -521,7 +521,7 @@ public: std::string DisassembleArm(u32 instruction) { DisassemblerVisitor visitor; auto decoder = DecodeArm(instruction); - return !decoder ? "UNKNOWN" : decoder->call(visitor, instruction); + return !decoder ? Common::StringFromFormat("UNKNOWN: %x", instruction) : decoder->call(visitor, instruction); } } // namespace Arm diff --git a/src/frontend/translate/translate_arm.cpp b/src/frontend/translate/translate_arm.cpp index 80757be9..71b9fe26 100644 --- a/src/frontend/translate/translate_arm.cpp +++ b/src/frontend/translate/translate_arm.cpp @@ -33,7 +33,7 @@ struct ArmTranslatorVisitor final { IREmitter ir; ConditionalState cond_state = ConditionalState::None; - bool TranslateThisInstruction() { + bool InterpretThisInstruction() { ir.SetTerm(IR::Term::Interpret(ir.current_location)); return false; } @@ -80,6 +80,182 @@ struct ArmTranslatorVisitor final { return true; } + u32 rotr(u32 x, int shift) { + shift &= 31; + if (!shift) return x; + return (x >> shift) | (x << (32 - shift)); + } + + u32 ArmExpandImm(int rotate, Imm8 imm8) { + return rotr(static_cast(imm8), rotate*2); + } + + bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + u32 imm32 = ArmExpandImm(rotate, imm8); + // ADC{S} , , # + if (ConditionPassed(cond)) { + auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.GetCFlag()); + + if (d == Reg::PC) { + ASSERT(!S); + ir.ALUWritePC(result.result); + ir.SetTerm(IR::Term::ReturnToDispatch{}); + return false; + } + + ir.SetRegister(d, result.result); + if (S) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } + } + return true; + }; + + bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); + } + bool arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); + } + bool arm_SVC(Cond cond, Imm24 imm24) { u32 imm32 = imm24; // SVC # @@ -91,7 +267,7 @@ struct ArmTranslatorVisitor final { } bool arm_UDF() { - return TranslateThisInstruction(); + return InterpretThisInstruction(); } }; diff --git a/src/frontend/translate/translate_thumb.cpp b/src/frontend/translate/translate_thumb.cpp index 7c777244..a6a1ad2a 100644 --- a/src/frontend/translate/translate_thumb.cpp +++ b/src/frontend/translate/translate_thumb.cpp @@ -24,7 +24,7 @@ struct ThumbTranslatorVisitor final { IREmitter ir; - bool TranslateThisInstruction() { + bool InterpretThisInstruction() { ir.SetTerm(IR::Term::Interpret(ir.current_location)); return false; } @@ -441,7 +441,7 @@ struct ThumbTranslatorVisitor final { } bool thumb16_UDF() { - return TranslateThisInstruction(); + return InterpretThisInstruction(); } bool thumb16_SVC(Imm8 imm8) { @@ -505,7 +505,7 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryRead32FuncType mem } else { should_continue = visitor.thumb32_UDF(); }*/ - should_continue = visitor.TranslateThisInstruction(); + should_continue = visitor.InterpretThisInstruction(); } visitor.ir.current_location.arm_pc += (inst_size == ThumbInstSize::Thumb16) ? 2 : 4; diff --git a/tests/arm/fuzz_arm.cpp b/tests/arm/fuzz_arm.cpp index 22c30368..f21108da 100644 --- a/tests/arm/fuzz_arm.cpp +++ b/tests/arm/fuzz_arm.cpp @@ -88,6 +88,9 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit) { InterpreterClearCache(); InterpreterMainLoop(&interp_state); + bool T = Dynarmic::Common::Bit<5>(interp_state.Cpsr); + interp_state.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC; + jit->Regs() = interp_state.Reg; jit->Cpsr() = interp_state.Cpsr; } @@ -159,7 +162,7 @@ static bool DoesBehaviorMatch(const ARMul_State& interp, const Dynarmic::Jit& ji } -void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_execute_count, const size_t run_count, const std::function instruction_generator) { +void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_execute_count, const size_t run_count, const std::function instruction_generator) { // Prepare memory code_mem.fill(0xEAFFFFFE); // b +#0 @@ -191,6 +194,10 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe interp.NumInstrsToExecute = instructions_to_execute_count; InterpreterMainLoop(&interp); auto interp_write_records = write_records; + { + bool T = Dynarmic::Common::Bit<5>(interp.Cpsr); + interp.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC; + } // Run jit write_records.clear(); @@ -340,7 +347,7 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") { }; SECTION("short blocks") { - FuzzJitArm(5, 6, 5000, instruction_select(/*Rd_can_be_r15=*/false)); + FuzzJitArm(5, 6, 10000, instruction_select(/*Rd_can_be_r15=*/false)); } SECTION("long blocks") {