diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index af18735e82..2a0a67d90d 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -20,8 +20,9 @@ #include "profiler/profiler.h" -#include "Core/Reporting.h" #include "Core/Config.h" +#include "Core/Core.h" +#include "Core/Reporting.h" #include "Core/MemMap.h" #include "Core/HLE/HLE.h" #include "Core/HLE/HLETables.h" @@ -446,6 +447,10 @@ void ArmJit::Comp_VBranch(MIPSOpcode op) } } +static void HitInvalidJump(uint32_t dest) { + Core_ExecException(dest, currentMIPS->pc - 8, ExecExceptionType::JUMP); +} + void ArmJit::Comp_Jump(MIPSOpcode op) { if (js.inDelaySlot) { ERROR_LOG_REPORT(JIT, "Branch in Jump delay slot at %08x in block starting at %08x", GetCompilerPC(), js.blockStart); @@ -462,6 +467,13 @@ void ArmJit::Comp_Jump(MIPSOpcode op) { js.compiling = false; } // TODO: Mark this block dirty or something? May be indication it will be changed by imports. + CompileDelaySlot(DELAYSLOT_NICE); + FlushAll(); + gpr.SetRegImm(SCRATCHREG1, GetCompilerPC() + 8); + MovToPC(SCRATCHREG1); + MOVI2R(R0, targetAddr); + QuickCallFunction(SCRATCHREG2, &HitInvalidJump); + WriteSyscallExit(); return; } diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index f20e5e2600..5cf32aa86d 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -703,6 +703,7 @@ void ArmJit::UpdateRoundingMode(u32 fcr31) { // I don't think this gives us that much benefit. void ArmJit::WriteExit(u32 destination, int exit_num) { + // TODO: Check destination is valid and trigger exception. WriteDownCount(); //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; @@ -723,6 +724,7 @@ void ArmJit::WriteExit(u32 destination, int exit_num) void ArmJit::WriteExitDestInR(ARMReg Reg) { + // TODO: If not fast memory, check for invalid address in reg and trigger exception. MovToPC(Reg); WriteDownCount(); // TODO: shouldn't need an indirect branch here... diff --git a/Core/MIPS/ARM64/Arm64CompBranch.cpp b/Core/MIPS/ARM64/Arm64CompBranch.cpp index f203229674..cdb984608e 100644 --- a/Core/MIPS/ARM64/Arm64CompBranch.cpp +++ b/Core/MIPS/ARM64/Arm64CompBranch.cpp @@ -20,8 +20,9 @@ #include "profiler/profiler.h" -#include "Core/Reporting.h" #include "Core/Config.h" +#include "Core/Core.h" +#include "Core/Reporting.h" #include "Core/MemMap.h" #include "Core/HLE/HLE.h" #include "Core/HLE/HLETables.h" @@ -461,6 +462,10 @@ void Arm64Jit::Comp_VBranch(MIPSOpcode op) } } +static void HitInvalidJump(uint32_t dest) { + Core_ExecException(dest, currentMIPS->pc - 8, ExecExceptionType::JUMP); +} + void Arm64Jit::Comp_Jump(MIPSOpcode op) { if (js.inDelaySlot) { ERROR_LOG_REPORT(JIT, "Branch in Jump delay slot at %08x in block starting at %08x", GetCompilerPC(), js.blockStart); @@ -477,6 +482,13 @@ void Arm64Jit::Comp_Jump(MIPSOpcode op) { js.compiling = false; } // TODO: Mark this block dirty or something? May be indication it will be changed by imports. + CompileDelaySlot(DELAYSLOT_NICE); + FlushAll(); + gpr.SetRegImm(SCRATCH1, GetCompilerPC() + 8); + MovToPC(SCRATCH1); + MOVI2R(W0, targetAddr); + QuickCallFunction(SCRATCH1, (const void *)&HitInvalidJump); + WriteSyscallExit(); return; } diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index 330c6b4761..3c39b7bf5a 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -677,6 +677,7 @@ void Arm64Jit::UpdateRoundingMode(u32 fcr31) { // though, as we need to have the SUBS flag set in the end. So with block linking in the mix, // I don't think this gives us that much benefit. void Arm64Jit::WriteExit(u32 destination, int exit_num) { + // TODO: Check destination is valid and trigger exception. WriteDownCount(); //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; @@ -696,6 +697,7 @@ void Arm64Jit::WriteExit(u32 destination, int exit_num) { } void Arm64Jit::WriteExitDestInR(ARM64Reg Reg) { + // TODO: If not fast memory, check for invalid address in reg and trigger exception. MovToPC(Reg); WriteDownCount(); // TODO: shouldn't need an indirect branch here... diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index c18d9ae5d5..a0c30a3582 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -617,7 +617,7 @@ void Jit::Comp_Jump(MIPSOpcode op) { CompileDelaySlot(DELAYSLOT_NICE); FlushAll(); MOV(32, MIPSSTATE_VAR(pc), Imm32(GetCompilerPC() + 8)); - ABI_CallFunctionC((const void *)&HitInvalidJump, targetAddr); + ABI_CallFunctionC(&HitInvalidJump, targetAddr); WriteSyscallExit(); return; } diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 4629d57f3d..2716f7233a 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -656,11 +656,18 @@ void Jit::Comp_Generic(MIPSOpcode op) { } } +static void HitInvalidBranch(uint32_t dest) { + Core_ExecException(dest, currentMIPS->pc, ExecExceptionType::JUMP); +} + void Jit::WriteExit(u32 destination, int exit_num) { _dbg_assert_msg_(JIT, exit_num < MAX_JIT_BLOCK_EXITS, "Expected a valid exit_num"); if (!Memory::IsValidAddress(destination)) { ERROR_LOG_REPORT(JIT, "Trying to write block exit to illegal destination %08x: pc = %08x", destination, currentMIPS->pc); + MOV(32, MIPSSTATE_VAR(pc), Imm32(GetCompilerPC())); + ABI_CallFunctionC(&HitInvalidBranch, destination); + js.afterOp |= JitState::AFTER_CORE_STATE; } // If we need to verify coreState and rewind, we may not jump yet. if (js.afterOp & (JitState::AFTER_CORE_STATE | JitState::AFTER_REWIND_PC_BAD_STATE)) { @@ -751,7 +758,7 @@ void Jit::WriteExitDestInReg(X64Reg reg) { // If we're ignoring, coreState didn't trip - so trip it now. CMP(32, R(EAX), Imm32(0)); FixupBranch skip = J_CC(CC_NE); - ABI_CallFunctionC((const void *)&HitInvalidJumpReg, GetCompilerPC()); + ABI_CallFunctionC(&HitInvalidJumpReg, GetCompilerPC()); SetJumpTarget(skip); SUB(32, MIPSSTATE_VAR(downcount), Imm8(0));