Merge pull request #3800 from phire/unexceptional-exceptions

Make exceptions consistent across all JITs/Interpreters (Fixes Pokemon Box)
This commit is contained in:
Mathew Maidment 2016-04-29 19:48:55 -04:00
commit b99b685f22
5 changed files with 15 additions and 24 deletions

View File

@ -453,6 +453,11 @@ void Advance()
g_slicelength = maxslicelength; g_slicelength = maxslicelength;
PowerPC::ppcState.downcount = CyclesToDowncount(g_slicelength); PowerPC::ppcState.downcount = CyclesToDowncount(g_slicelength);
} }
// Check for any external exceptions.
// It's important to do this after processing events otherwise any exceptions will be delayed until the next slice:
// Pokemon Box refuses to boot if the first exception from the audio DMA is received late
PowerPC::CheckExternalExceptions();
} }
void LogPendingEvents() void LogPendingEvents()

View File

@ -76,7 +76,6 @@ void CachedInterpreter::SingleStep()
static void EndBlock(UGeckoInstruction data) static void EndBlock(UGeckoInstruction data)
{ {
PC = NPC; PC = NPC;
PowerPC::CheckExceptions();
PowerPC::ppcState.downcount -= data.hex; PowerPC::ppcState.downcount -= data.hex;
if (PowerPC::ppcState.downcount <= 0) if (PowerPC::ppcState.downcount <= 0)
{ {

View File

@ -278,12 +278,6 @@ void Interpreter::Run()
} }
CoreTiming::Advance(); CoreTiming::Advance();
if (PowerPC::ppcState.Exceptions)
{
PowerPC::CheckExceptions();
PC = NPC;
}
} }
// Let the waiting thread know we are done leaving // Let the waiting thread know we are done leaving

View File

@ -202,16 +202,12 @@ void Jit64AsmRoutineManager::Generate()
SetJumpTarget(bail); SetJumpTarget(bail);
doTiming = GetCodePtr(); doTiming = GetCodePtr();
// Test external exceptions. // make sure npc contains the next pc (needed for exception checking in CoreTiming::Advance)
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER));
FixupBranch noExtException = J_CC(CC_Z);
MOV(32, R(RSCRATCH), PPCSTATE(pc)); MOV(32, R(RSCRATCH), PPCSTATE(pc));
MOV(32, PPCSTATE(npc), R(RSCRATCH)); MOV(32, PPCSTATE(npc), R(RSCRATCH));
ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions));
ABI_PopRegistersAndAdjustStack({}, 0);
SetJumpTarget(noExtException);
// Check the state pointer to see if we are exiting
// Gets checked on at the end of every slice
TEST(32, M(PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); TEST(32, M(PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
J_CC(CC_Z, outerLoop); J_CC(CC_Z, outerLoop);

View File

@ -73,21 +73,18 @@ void JitArm64AsmRoutineManager::Generate()
SetJumpTarget(bail); SetJumpTarget(bail);
doTiming = GetCodePtr(); doTiming = GetCodePtr();
// Write the current PC out to PPCSTATE
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
MOVI2R(X30, (u64)&CoreTiming::Advance); MOVI2R(X30, (u64)&CoreTiming::Advance);
BLR(X30); BLR(X30);
// Does exception checking // Load the PC back into DISPATCHER_PC (the exception handler might have changed it)
LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(Exceptions)); LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
FixupBranch no_exceptions = CBZ(W0);
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
MOVI2R(X30, (u64)&PowerPC::CheckExceptions);
BLR(X30);
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
SetJumpTarget(no_exceptions);
// Check the state pointer to see if we are exiting // Check the state pointer to see if we are exiting
// Gets checked on every exception check // Gets checked on at the end of every slice
MOVI2R(X0, (u64)PowerPC::GetStatePtr()); MOVI2R(X0, (u64)PowerPC::GetStatePtr());
LDR(INDEX_UNSIGNED, W0, X0, 0); LDR(INDEX_UNSIGNED, W0, X0, 0);