TranslateArm: Implement BLX (imm), BLX (reg) and BXJ
This commit is contained in:
parent
939bb5c0cb
commit
1af5bef32c
4 changed files with 43 additions and 21 deletions
|
@ -119,8 +119,8 @@ struct LocationDescriptor {
|
|||
return LocationDescriptor(new_arm_pc, tflag, eflag, fpscr);
|
||||
}
|
||||
|
||||
LocationDescriptor AdvancePC(s32 amount) const {
|
||||
return LocationDescriptor(arm_pc + amount, tflag, eflag, fpscr);
|
||||
LocationDescriptor AdvancePC(int amount) const {
|
||||
return LocationDescriptor(static_cast<u32>(arm_pc + amount), tflag, eflag, fpscr);
|
||||
}
|
||||
|
||||
LocationDescriptor SetTFlag(bool new_tflag) const {
|
||||
|
|
|
@ -11,12 +11,10 @@
|
|||
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))
|
||||
{
|
||||
bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24) {
|
||||
u32 imm32 = Common::SignExtend<26, u32>(imm24 << 2) + 8;
|
||||
// B <label>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto new_location = ir.current_location.AdvancePC(imm32);
|
||||
ir.SetTerm(IR::Term::LinkBlock{ new_location });
|
||||
return false;
|
||||
|
@ -24,12 +22,10 @@ bool ArmTranslatorVisitor::arm_B(Cond cond, Imm24 imm24)
|
|||
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))
|
||||
{
|
||||
bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24) {
|
||||
u32 imm32 = Common::SignExtend<26, u32>(imm24 << 2) + 8;
|
||||
// BL <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 });
|
||||
|
@ -38,17 +34,28 @@ bool ArmTranslatorVisitor::arm_BL(Cond cond, Imm24 imm24)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_BLX_imm(Cond cond, Imm24 imm24)
|
||||
{
|
||||
return InterpretThisInstruction();
|
||||
bool ArmTranslatorVisitor::arm_BLX_imm(bool H, Imm24 imm24) {
|
||||
u32 imm32 = Common::SignExtend<26, u32>((imm24 << 2)) + (H ? 2 : 0) + 8;
|
||||
// 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) {
|
||||
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) {
|
||||
// BX <cond> <Rm>
|
||||
// BX <Rm>
|
||||
if (ConditionPassed(cond)) {
|
||||
ir.BXWritePC(ir.GetRegister(m));
|
||||
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) {
|
||||
return InterpretThisInstruction();
|
||||
// Jazelle not supported
|
||||
return arm_BX(cond, m);
|
||||
}
|
||||
|
||||
} // namespace Arm
|
||||
|
|
|
@ -65,7 +65,7 @@ struct ArmTranslatorVisitor final {
|
|||
// 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_imm(bool H, Imm24 imm24);
|
||||
bool arm_BLX_reg(Cond cond, Reg m);
|
||||
bool arm_BX(Cond cond, Reg m);
|
||||
bool arm_BXJ(Cond cond, Reg m);
|
||||
|
|
|
@ -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]") {
|
||||
const auto is_valid = [](u32 instr) -> bool {
|
||||
// R15 is UNPREDICTABLE
|
||||
|
|
Loading…
Reference in a new issue