pcsx2: interpreter: add an exception for tlb miss

When a tlb miss is detected current instruction must be skipped. We need
to immediately switch to the handler

Typical instruction bug case:
 lw a0, 0x8(a0)

a0 mustn't be loaded if we have a miss

v2: create a dedicated exception for tlb miss

v3:
* rename exception to CancelInstruction
* add a basic state machine on the exec loop so we keep same behavior
  for eeloadReplaceOSDSYS and eeGameStarting

v4: remove assert
This commit is contained in:
Gregory Hainaut 2014-11-14 22:46:31 +01:00
parent 374048e1c6
commit a30bd86311
3 changed files with 50 additions and 16 deletions

View File

@ -479,23 +479,48 @@ static void intEventTest()
static void intExecute() static void intExecute()
{ {
bool instruction_was_cancelled;
enum ExecuteState {
RESET,
REPLACE_OSDSYS_DONE,
GAME_STARTING_DONE
};
ExecuteState state = RESET;
do {
instruction_was_cancelled = false;
try { 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) { if (g_SkipBiosHack) {
do do
execI(); execI();
while (cpuRegs.pc != EELOAD_START); while (cpuRegs.pc != EELOAD_START);
eeloadReplaceOSDSYS(); eeloadReplaceOSDSYS();
} }
state = REPLACE_OSDSYS_DONE;
case REPLACE_OSDSYS_DONE:
if (ElfEntry != 0xFFFFFFFF) { if (ElfEntry != 0xFFFFFFFF) {
do do
execI(); execI();
while (cpuRegs.pc != ElfEntry); while (cpuRegs.pc != ElfEntry);
eeGameStarting(); eeGameStarting();
} else { }
state = GAME_STARTING_DONE;
case GAME_STARTING_DONE:
while (true) while (true)
execI(); 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() static void intCheckExecutionState()

View File

@ -37,6 +37,12 @@ namespace Exception
public: public:
explicit ExitCpuExecute() { } explicit ExitCpuExecute() { }
}; };
class CancelInstruction
{
public:
explicit CancelInstruction() { }
};
} }
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------

View File

@ -376,6 +376,9 @@ static __ri void vtlb_Miss(u32 addr,u32 mode)
cpuTlbMissW(addr, cpuRegs.branch); cpuTlbMissW(addr, cpuRegs.branch);
else else
cpuTlbMissR(addr, cpuRegs.branch); 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 // The exception terminate the program on linux which is very annoying