diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 0b661e1d7..9fa7057c0 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -3888,6 +3888,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { LOAD_NZCVT; DISPATCH: { + if (num_instrs >= cpu->NumInstrsToExecute) goto END; + if (!cpu->NirqSig) { if (!(cpu->Cpsr & 0x80)) { goto END; diff --git a/src/core/arm/jit_x64/instructions/data_processing.cpp b/src/core/arm/jit_x64/instructions/data_processing.cpp index f7223f26e..c8916c123 100644 --- a/src/core/arm/jit_x64/instructions/data_processing.cpp +++ b/src/core/arm/jit_x64/instructions/data_processing.cpp @@ -49,10 +49,14 @@ void JitX64::CompileDataProcessingHelper_Reverse(ArmReg Rn_index, ArmReg Rd_inde body(tmp); - // TODO: Efficiency: Could implement this as a register rebind instead of needing to MOV. - reg_alloc.LockAndDirtyArm(Rd_index); - code->MOV(32, reg_alloc.ArmR(Rd_index), R(tmp)); - reg_alloc.UnlockArm(Rd_index); + if (Rd_index != 15) { + // TODO: Efficiency: Could implement this as a register rebind instead of needing to MOV. + reg_alloc.LockAndDirtyArm(Rd_index); + code->MOV(32, reg_alloc.ArmR(Rd_index), R(tmp)); + reg_alloc.UnlockArm(Rd_index); + } else { + code->MOV(32, MJitStateArmPC(), R(tmp)); + } reg_alloc.UnlockTemp(tmp); } diff --git a/src/core/arm/jit_x64/reg_alloc.h b/src/core/arm/jit_x64/reg_alloc.h index f07a0f5fb..7687f6e0b 100644 --- a/src/core/arm/jit_x64/reg_alloc.h +++ b/src/core/arm/jit_x64/reg_alloc.h @@ -61,7 +61,7 @@ private: ArmReg arm_reg = -1; ///< Only holds a valid value when state == DirtyArmReg / CleanArmReg }; - std::array arm_gpr; + std::array arm_gpr; std::array x64_gpr; Gen::XEmitter* code = nullptr; diff --git a/src/tests/core/arm/jit_x64/fuzz_arm_data_processing.cpp b/src/tests/core/arm/jit_x64/fuzz_arm_data_processing.cpp index a4e744238..498c09747 100644 --- a/src/tests/core/arm/jit_x64/fuzz_arm_data_processing.cpp +++ b/src/tests/core/arm/jit_x64/fuzz_arm_data_processing.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include #include @@ -217,6 +218,34 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") { return instructions[inst_index].first | (assemble_randoms & (~instructions[inst_index].second)); }; - FuzzJit(5, 10000, instruction_select_without_R15); - FuzzJit(1024, 500, instruction_select_without_R15); + SECTION("short blocks") { + FuzzJit(5, 5000, instruction_select_without_R15); + } + + SECTION("long blocks") { + FuzzJit(1024, 200, instruction_select_without_R15); + } + + auto instruction_select_only_R15 = [&]() -> u32 { + size_t inst_index = RandInt(0, instructions.size() - 1); + + u32 cond = 0xE; + // Have a one-in-twenty-five chance of actually having a cond. + if (RandInt(1, 25) == 1) { + cond = RandInt(0x0, 0xD); + } + + u32 Rn = RandInt(0, 15); + u32 Rd = 15; + u32 S = 0; + u32 shifter_operand = RandInt(0, 0xFFF); + + u32 assemble_randoms = (shifter_operand << 0) | (Rd << 12) | (Rn << 16) | (S << 20) | (cond << 28); + + return instructions[inst_index].first | (assemble_randoms & (~instructions[inst_index].second)); + }; + + SECTION("R15") { + FuzzJit(1, 10000, instruction_select_only_R15); + } } \ No newline at end of file