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);
|
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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue