diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e62e98f..de4484b7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,9 @@ set(SRCS frontend/ir/ir_emitter.cpp frontend/translate/translate.cpp frontend/translate/translate_arm.cpp + frontend/translate/translate_arm/data_processing.cpp + frontend/translate/translate_arm/exception_generating.cpp + frontend/translate/translate_arm/reversal.cpp frontend/translate/translate_thumb.cpp ir_opt/dead_code_elimination_pass.cpp ir_opt/get_set_elimination_pass.cpp @@ -49,6 +52,7 @@ set(HEADERS frontend/ir/ir_emitter.h frontend/ir/opcodes.h frontend/translate/translate.h + frontend/translate/translate_arm/translate_arm.h interface/interface.h ir_opt/passes.h ) diff --git a/src/frontend/translate/translate_arm.cpp b/src/frontend/translate/translate_arm.cpp index fc56cad3..2170883b 100644 --- a/src/frontend/translate/translate_arm.cpp +++ b/src/frontend/translate/translate_arm.cpp @@ -8,307 +8,12 @@ #include "frontend/arm_types.h" #include "frontend/decoder/arm.h" #include "frontend/ir/ir.h" -#include "frontend/ir/ir_emitter.h" #include "frontend/translate/translate.h" +#include "frontend/translate/translate_arm/translate_arm.h" namespace Dynarmic { namespace Arm { -namespace { - -enum class ConditionalState { - /// We haven't met any conditional instructions yet. - None, - /// Current instruction is a conditional. This marks the end of this basic block. - Break, - /// This basic block is made up solely of conditional instructions. - Translating, -}; - -struct ArmTranslatorVisitor final { - explicit ArmTranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) { - ASSERT_MSG(!descriptor.TFlag(), "The processor must be in Arm mode"); - } - - IREmitter ir; - ConditionalState cond_state = ConditionalState::None; - - bool InterpretThisInstruction() { - ir.SetTerm(IR::Term::Interpret(ir.current_location)); - return false; - } - - bool UnpredictableInstruction() { - ASSERT_MSG(false, "UNPREDICTABLE"); - return false; - } - - bool LinkToNextInstruction() { - auto next_location = ir.current_location.AdvancePC(4); - ir.SetTerm(IR::Term::LinkBlock{next_location}); - return false; - } - - bool ConditionPassed(Cond cond) { - ASSERT_MSG(cond_state != ConditionalState::Translating, - "In the current impl, ConditionPassed should never be called again once a non-AL cond is hit. " - "(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; - } - - // non-AL cond - - if (!ir.block.instructions.empty()) { - // We've already emitted instructions. Quit for now, we'll make a new block here later. - cond_state = ConditionalState::Break; - ir.SetTerm(IR::Term::LinkBlock{ir.current_location}); - return false; - } - - // We've not emitted instructions yet. - // We'll emit one instruction, and set the block-entry conditional appropriately. - - cond_state = ConditionalState::Translating; - ir.block.cond = cond; - return true; - } - - static u32 rotr(u32 x, int shift) { - shift &= 31; - if (!shift) return x; - return (x >> shift) | (x << (32 - shift)); - } - - static 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) { - u32 imm32 = ArmExpandImm(rotate, imm8); - // CMP , # - if (ConditionPassed(cond)) { - auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1)); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); - } - return true; - } - - 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 # - if (ConditionPassed(cond)) { - ir.CallSupervisor(ir.Imm32(imm32)); - return LinkToNextInstruction(); - } - return true; - } - - bool arm_UDF() { - return InterpretThisInstruction(); - } - - bool arm_REV(Cond cond, Reg d, Reg m) { - // REV , - ASSERT(d != Reg::PC && m != Reg::PC); - - if (ConditionPassed(cond)) { - auto result = ir.ByteReverseWord(ir.GetRegister(m)); - ir.SetRegister(d, result); - } - return true; - } - - bool arm_REV16(Cond cond, Reg d, Reg m) { - return InterpretThisInstruction(); - } - - bool arm_REVSH(Cond cond, Reg d, Reg m) { - // REVSH , - ASSERT(d != Reg::PC && m != Reg::PC); - - if (ConditionPassed(cond)) { - auto rev_half = ir.ByteReverseHalf(ir.LeastSignificantHalf(ir.GetRegister(m))); - ir.SetRegister(d, ir.SignExtendHalfToWord(rev_half)); - } - return true; - } -}; - -} // local namespace - IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32) { ArmTranslatorVisitor visitor{descriptor}; @@ -342,5 +47,51 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memor return std::move(visitor.ir.block); } +bool ArmTranslatorVisitor::ConditionPassed(Cond cond) { + ASSERT_MSG(cond_state != ConditionalState::Translating, + "In the current impl, ConditionPassed should never be called again once a non-AL cond is hit. " + "(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; + } + + // non-AL cond + + if (!ir.block.instructions.empty()) { + // We've already emitted instructions. Quit for now, we'll make a new block here later. + cond_state = ConditionalState::Break; + ir.SetTerm(IR::Term::LinkBlock{ir.current_location}); + return false; + } + + // We've not emitted instructions yet. + // We'll emit one instruction, and set the block-entry conditional appropriately. + + cond_state = ConditionalState::Translating; + ir.block.cond = cond; + return true; +} + +bool ArmTranslatorVisitor::InterpretThisInstruction() { + ir.SetTerm(IR::Term::Interpret(ir.current_location)); + return false; +} + +bool ArmTranslatorVisitor::UnpredictableInstruction() { + ASSERT_MSG(false, "UNPREDICTABLE"); + return false; +} + +bool ArmTranslatorVisitor::LinkToNextInstruction() { + auto next_location = ir.current_location.AdvancePC(4); + ir.SetTerm(IR::Term::LinkBlock{next_location}); + return false; +} + } // namespace Arm } // namespace Dynarmic diff --git a/src/frontend/translate/translate_arm/data_processing.cpp b/src/frontend/translate/translate_arm/data_processing.cpp new file mode 100644 index 00000000..c07f8e71 --- /dev/null +++ b/src/frontend/translate/translate_arm/data_processing.cpp @@ -0,0 +1,191 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "translate_arm.h" + +namespace Dynarmic { +namespace Arm { + +bool ArmTranslatorVisitor::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 ArmTranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} + +bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { + u32 imm32 = ArmExpandImm(rotate, imm8); + // CMP , # + if (ConditionPassed(cond)) { + auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1)); + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } + return true; +} + +bool ArmTranslatorVisitor::arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) { + //auto result = ArmExpandImm_C(rotate, imm8); + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} +bool ArmTranslatorVisitor::arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) { + return InterpretThisInstruction(); +} + +} // namespace Arm +} // namespace Dynarmic diff --git a/src/frontend/translate/translate_arm/exception_generating.cpp b/src/frontend/translate/translate_arm/exception_generating.cpp new file mode 100644 index 00000000..bf25ce20 --- /dev/null +++ b/src/frontend/translate/translate_arm/exception_generating.cpp @@ -0,0 +1,31 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "translate_arm.h" + +namespace Dynarmic { +namespace Arm { + +bool ArmTranslatorVisitor::arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4) { + return InterpretThisInstruction(); +} + +bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm24 imm24) { + u32 imm32 = imm24; + // SVC # + if (ConditionPassed(cond)) { + ir.CallSupervisor(ir.Imm32(imm32)); + return LinkToNextInstruction(); + } + return true; +} + +bool ArmTranslatorVisitor::arm_UDF() { + return InterpretThisInstruction(); +} + +} // namespace Arm +} // namespace Dynarmic diff --git a/src/frontend/translate/translate_arm/reversal.cpp b/src/frontend/translate/translate_arm/reversal.cpp new file mode 100644 index 00000000..82cee812 --- /dev/null +++ b/src/frontend/translate/translate_arm/reversal.cpp @@ -0,0 +1,39 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "translate_arm.h" + +namespace Dynarmic { +namespace Arm { + +bool ArmTranslatorVisitor::arm_REV(Cond cond, Reg d, Reg m) { + // REV , + ASSERT(d != Reg::PC && m != Reg::PC); + + if (ConditionPassed(cond)) { + auto result = ir.ByteReverseWord(ir.GetRegister(m)); + ir.SetRegister(d, result); + } + return true; +} + +bool ArmTranslatorVisitor::arm_REV16(Cond cond, Reg d, Reg m) { + return InterpretThisInstruction(); +} + +bool ArmTranslatorVisitor::arm_REVSH(Cond cond, Reg d, Reg m) { + // REVSH , + ASSERT(d != Reg::PC && m != Reg::PC); + + if (ConditionPassed(cond)) { + auto rev_half = ir.ByteReverseHalf(ir.LeastSignificantHalf(ir.GetRegister(m))); + ir.SetRegister(d, ir.SignExtendHalfToWord(rev_half)); + } + return true; +} + +} // namespace Arm +} // namespace Dynarmic diff --git a/src/frontend/translate/translate_arm/translate_arm.h b/src/frontend/translate/translate_arm/translate_arm.h new file mode 100644 index 00000000..a2d3ee6c --- /dev/null +++ b/src/frontend/translate/translate_arm/translate_arm.h @@ -0,0 +1,111 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#pragma once + +#include "frontend/ir/ir_emitter.h" + +namespace Dynarmic { +namespace Arm { + +enum class ConditionalState { + /// We haven't met any conditional instructions yet. + None, + /// Current instruction is a conditional. This marks the end of this basic block. + Break, + /// This basic block is made up solely of conditional instructions. + Translating, +}; + +struct ArmTranslatorVisitor final { + explicit ArmTranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) { + ASSERT_MSG(!descriptor.TFlag(), "The processor must be in Arm mode"); + } + + IREmitter ir; + ConditionalState cond_state = ConditionalState::None; + + bool ConditionPassed(Cond cond); + bool InterpretThisInstruction(); + bool UnpredictableInstruction(); + bool LinkToNextInstruction(); + + static u32 rotr(u32 x, int shift) { + shift &= 31; + if (!shift) return x; + return (x >> shift) | (x << (32 - shift)); + } + + static u32 ArmExpandImm(int rotate, Imm8 imm8) { + return rotr(static_cast(imm8), rotate*2); + } + + // Data processing instructions + bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8); + bool arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m); + bool arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m); + bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8); + bool arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m); + bool arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m); + bool arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8); + bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8); + bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8); + bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); + bool arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m); + bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8); + bool arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m); + bool arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m); + bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8); + bool arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m); + bool arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m); + + // Exception generating instructions + bool arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4); + bool arm_SVC(Cond cond, Imm24 imm24); + bool arm_UDF(); + + // Reversal instructions + bool arm_REV(Cond cond, Reg d, Reg m); + bool arm_REV16(Cond cond, Reg d, Reg m); + bool arm_REVSH(Cond cond, Reg d, Reg m); + + // Floating-point three-register data processing instructions + bool vfp2_VADD(Cond cond, bool D, bool sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm); +}; + +} // namespace Arm +} // namespace Dynarmic