diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp index 59a90181c1..60f2cb435c 100644 --- a/pcsx2/Interpreter.cpp +++ b/pcsx2/Interpreter.cpp @@ -479,23 +479,48 @@ static void intEventTest() static void intExecute() { - try { - if (g_SkipBiosHack) { - do - execI(); - while (cpuRegs.pc != EELOAD_START); - eeloadReplaceOSDSYS(); + bool instruction_was_cancelled; + enum ExecuteState { + RESET, + REPLACE_OSDSYS_DONE, + GAME_STARTING_DONE + }; + ExecuteState state = RESET; + do { + instruction_was_cancelled = false; + try { + // The execution was splited in three parts so it is easier to + // resume it after a cancelled instruction. + switch (state) { + case RESET: + if (g_SkipBiosHack) { + do + execI(); + while (cpuRegs.pc != EELOAD_START); + eeloadReplaceOSDSYS(); + } + state = REPLACE_OSDSYS_DONE; + + case REPLACE_OSDSYS_DONE: + if (ElfEntry != 0xFFFFFFFF) { + do + execI(); + while (cpuRegs.pc != ElfEntry); + eeGameStarting(); + } + state = GAME_STARTING_DONE; + + case GAME_STARTING_DONE: + while (true) + execI(); + } } - if (ElfEntry != 0xFFFFFFFF) { - do - execI(); - while (cpuRegs.pc != ElfEntry); - eeGameStarting(); - } else { - while (true) - execI(); - } - } catch( Exception::ExitCpuExecute& ) { } + catch( Exception::ExitCpuExecute& ) { } + catch( Exception::CancelInstruction& ) { instruction_was_cancelled = true; } + + // For example a tlb miss will throw an exception. Cpu must be resumed + // to execute the handler + } while (instruction_was_cancelled); } static void intCheckExecutionState() diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index 4504a6fed7..cd027895a2 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -37,6 +37,12 @@ namespace Exception public: explicit ExitCpuExecute() { } }; + + class CancelInstruction + { + public: + explicit CancelInstruction() { } + }; } // -------------------------------------------------------------------------------------- diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index a26ba37bac..da746654b9 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -376,6 +376,9 @@ static __ri void vtlb_Miss(u32 addr,u32 mode) cpuTlbMissW(addr, cpuRegs.branch); else cpuTlbMissR(addr, cpuRegs.branch); + + // Exception handled. Current instruction need to be stopped + throw Exception::CancelInstruction(); } // The exception terminate the program on linux which is very annoying