diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f160e42..31331121 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,7 @@ set(SRCS frontend/ir/ir_emitter.cpp frontend/translate/translate.cpp frontend/translate/translate_arm.cpp + frontend/translate/translate_arm/branch.cpp frontend/translate/translate_arm/data_processing.cpp frontend/translate/translate_arm/exception_generating.cpp frontend/translate/translate_arm/extension.cpp diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index e8bbe5d8..0367b8d8 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -66,9 +66,9 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) { // Branch instructions //INST(&V::arm_BLX_imm, "BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv"), // v5 //INST(&V::arm_BLX_reg, "BLX (reg)", "cccc000100101111111111110011mmmm"), // v5 - //INST(&V::arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv"), // all - //INST(&V::arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv"), // all - //INST(&V::arm_BX, "BX", "cccc000100101111111111110001mmmm"), // v4T + INST(&V::arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv"), // all + INST(&V::arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv"), // all + INST(&V::arm_BX, "BX", "cccc000100101111111111110001mmmm"), // v4T //INST(&V::arm_BXJ, "BXJ", "cccc000100101111111111110010mmmm"), // v5J // Coprocessor instructions diff --git a/src/frontend/translate/translate_arm/branch.cpp b/src/frontend/translate/translate_arm/branch.cpp new file mode 100644 index 00000000..c2703d71 --- /dev/null +++ b/src/frontend/translate/translate_arm/branch.cpp @@ -0,0 +1,65 @@ +/* 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 "common/bit_util.h" + +#include "translate_arm.h" + +namespace Dynarmic { +namespace Arm { + +bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24) +{ + s32 imm32 = Common::SignExtend<26, s32>(imm24 << 2) + 8; + // B <cond> <label> + if (ConditionPassed(cond)) + { + auto new_location = ir.current_location.AdvancePC(imm32); + ir.SetTerm(IR::Term::LinkBlock{ new_location }); + return false; + } + return true; +} + +bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) +{ + s32 imm32 = Common::SignExtend<26, s32>(imm24 << 2) + 8; + // BL <cond> <label> + if (ConditionPassed(cond)) + { + ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4)); + auto new_location = ir.current_location.AdvancePC(imm32); + ir.SetTerm(IR::Term::LinkBlock{ new_location }); + return false; + } + return true; +} + +bool ArmTranslatorVisitor::arm_BLX_imm(Cond cond, Imm24 imm24) +{ + return InterpretThisInstruction(); +} + +bool ArmTranslatorVisitor::arm_BLX_reg(Cond cond, Reg m) { + return InterpretThisInstruction(); +} + +bool ArmTranslatorVisitor::arm_BX(Cond cond, Reg m) { + // BX <cond> <Rm> + if (ConditionPassed(cond)) { + ir.BXWritePC(ir.GetRegister(m)); + ir.SetTerm(IR::Term::ReturnToDispatch{}); + return false; + } + return true; +} + +bool ArmTranslatorVisitor::arm_BXJ(Cond cond, Reg m) { + return InterpretThisInstruction(); +} + +} // namespace Arm +} // namespace Dynarmic diff --git a/src/frontend/translate/translate_arm/translate_arm.h b/src/frontend/translate/translate_arm/translate_arm.h index f24a6e0b..12bd6499 100644 --- a/src/frontend/translate/translate_arm/translate_arm.h +++ b/src/frontend/translate/translate_arm/translate_arm.h @@ -62,6 +62,14 @@ struct ArmTranslatorVisitor final { IREmitter::ResultAndCarry EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in); IR::Value SignZeroExtendRor(Reg m, SignExtendRotation rotate); + // Branch instructions + bool arm_B(Cond cond, Imm24 imm24); + bool arm_BL(Cond cond, Imm24 imm24); + bool arm_BLX_imm(Cond cond, Imm24 imm24); + bool arm_BLX_reg(Cond cond, Reg m); + bool arm_BX(Cond cond, Reg m); + bool arm_BXJ(Cond cond, Reg m); + // 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);