TranslateArm: Implement BLX (imm), BLX (reg) and BXJ

This commit is contained in:
MerryMage 2016-08-07 20:19:37 +01:00
parent 939bb5c0cb
commit 1af5bef32c
4 changed files with 43 additions and 21 deletions

View file

@ -119,8 +119,8 @@ struct LocationDescriptor {
return LocationDescriptor(new_arm_pc, tflag, eflag, fpscr); return LocationDescriptor(new_arm_pc, tflag, eflag, fpscr);
} }
LocationDescriptor AdvancePC(s32 amount) const { LocationDescriptor AdvancePC(int amount) const {
return LocationDescriptor(arm_pc + amount, tflag, eflag, fpscr); return LocationDescriptor(static_cast<u32>(arm_pc + amount), tflag, eflag, fpscr);
} }
LocationDescriptor SetTFlag(bool new_tflag) const { LocationDescriptor SetTFlag(bool new_tflag) const {

View file

@ -11,12 +11,10 @@
namespace Dynarmic { namespace Dynarmic {
namespace Arm { namespace Arm {
bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24) bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24) {
{ u32 imm32 = Common::SignExtend<26, u32>(imm24 << 2) + 8;
s32 imm32 = Common::SignExtend<26, s32>(imm24 << 2) + 8; // B <label>
// B <cond> <label> if (ConditionPassed(cond)) {
if (ConditionPassed(cond))
{
auto new_location = ir.current_location.AdvancePC(imm32); auto new_location = ir.current_location.AdvancePC(imm32);
ir.SetTerm(IR::Term::LinkBlock{ new_location }); ir.SetTerm(IR::Term::LinkBlock{ new_location });
return false; return false;
@ -24,12 +22,10 @@ bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24)
return true; return true;
} }
bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) {
{ u32 imm32 = Common::SignExtend<26, u32>(imm24 << 2) + 8;
s32 imm32 = Common::SignExtend<26, s32>(imm24 << 2) + 8; // BL <label>
// BL <cond> <label> if (ConditionPassed(cond)) {
if (ConditionPassed(cond))
{
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4)); ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
auto new_location = ir.current_location.AdvancePC(imm32); auto new_location = ir.current_location.AdvancePC(imm32);
ir.SetTerm(IR::Term::LinkBlock{ new_location }); ir.SetTerm(IR::Term::LinkBlock{ new_location });
@ -38,17 +34,28 @@ bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24)
return true; return true;
} }
bool ArmTranslatorVisitor::arm_BLX_imm(Cond cond, Imm24 imm24) bool ArmTranslatorVisitor::arm_BLX_imm(bool H, Imm24 imm24) {
{ u32 imm32 = Common::SignExtend<26, u32>((imm24 << 2)) + (H ? 2 : 0) + 8;
return InterpretThisInstruction(); // BLX <label>
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
auto new_location = ir.current_location.AdvancePC(imm32).SetTFlag(true);
ir.SetTerm(IR::Term::LinkBlock{ new_location });
return false;
} }
bool ArmTranslatorVisitor::arm_BLX_reg(Cond cond, Reg m) { bool ArmTranslatorVisitor::arm_BLX_reg(Cond cond, Reg m) {
return InterpretThisInstruction(); // BLX <Rm>
if (ConditionPassed(cond)) {
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
ir.BXWritePC(ir.GetRegister(m));
ir.SetTerm(IR::Term::ReturnToDispatch{});
return false;
}
return true;
} }
bool ArmTranslatorVisitor::arm_BX(Cond cond, Reg m) { bool ArmTranslatorVisitor::arm_BX(Cond cond, Reg m) {
// BX <cond> <Rm> // BX <Rm>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
ir.BXWritePC(ir.GetRegister(m)); ir.BXWritePC(ir.GetRegister(m));
ir.SetTerm(IR::Term::ReturnToDispatch{}); ir.SetTerm(IR::Term::ReturnToDispatch{});
@ -58,7 +65,8 @@ bool ArmTranslatorVisitor::arm_BX(Cond cond, Reg m) {
} }
bool ArmTranslatorVisitor::arm_BXJ(Cond cond, Reg m) { bool ArmTranslatorVisitor::arm_BXJ(Cond cond, Reg m) {
return InterpretThisInstruction(); // Jazelle not supported
return arm_BX(cond, m);
} }
} // namespace Arm } // namespace Arm

View file

@ -65,7 +65,7 @@ struct ArmTranslatorVisitor final {
// Branch instructions // Branch instructions
bool arm_B(Cond cond, Imm24 imm24); bool arm_B(Cond cond, Imm24 imm24);
bool arm_BL(Cond cond, Imm24 imm24); bool arm_BL(Cond cond, Imm24 imm24);
bool arm_BLX_imm(Cond cond, Imm24 imm24); bool arm_BLX_imm(bool H, Imm24 imm24);
bool arm_BLX_reg(Cond cond, Reg m); bool arm_BLX_reg(Cond cond, Reg m);
bool arm_BX(Cond cond, Reg m); bool arm_BX(Cond cond, Reg m);
bool arm_BXJ(Cond cond, Reg m); bool arm_BXJ(Cond cond, Reg m);

View file

@ -560,6 +560,20 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
} }
} }
TEST_CASE("Fuzz ARM branch instructions", "[JitX64]") {
const std::array<InstructionGenerator, 6> instructions = {{
InstructionGenerator("1111101hvvvvvvvvvvvvvvvvvvvvvvvv"),
InstructionGenerator("cccc000100101111111111110011mmmm"),
InstructionGenerator("cccc1010vvvvvvvvvvvvvvvvvvvvvvvv"),
InstructionGenerator("cccc1011vvvvvvvvvvvvvvvvvvvvvvvv"),
InstructionGenerator("cccc000100101111111111110001mmmm"),
InstructionGenerator("cccc000100101111111111110010mmmm"),
}};
FuzzJitArm(1, 1, 10000, [&instructions]() -> u32 {
return instructions[RandInt<size_t>(0, instructions.size() - 1)].Generate();
});
}
TEST_CASE("Fuzz ARM reversal instructions", "[JitX64]") { TEST_CASE("Fuzz ARM reversal instructions", "[JitX64]") {
const auto is_valid = [](u32 instr) -> bool { const auto is_valid = [](u32 instr) -> bool {
// R15 is UNPREDICTABLE // R15 is UNPREDICTABLE