arm: Implement B/BL/BX instructions.

This commit is contained in:
bunnei 2016-08-02 19:52:17 -04:00
parent fc33f1d374
commit 691e4139fa
4 changed files with 77 additions and 3 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);