From eb5819f88a180250cc622e2c00c6dd42f55126e4 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Wed, 27 Apr 2016 11:59:29 +1200 Subject: [PATCH] Make exceptions consistant across all JITs/Interpeters. They all handled it diffrently, so I've just moved it into Advance() This fixes Pokemon Box booting in JIT/JITIL which shared a bug where exceptions set in a scheduled event would be ignored untill the next slice (upto 20,000 cycles). --- Source/Core/Core/CoreTiming.cpp | 5 +++++ Source/Core/Core/PowerPC/CachedInterpreter.cpp | 1 - .../Core/PowerPC/Interpreter/Interpreter.cpp | 6 ------ Source/Core/Core/PowerPC/Jit64/JitAsm.cpp | 10 +++------- Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp | 17 +++++++---------- 5 files changed, 15 insertions(+), 24 deletions(-) diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp index c9a3fd4021..db3c084840 100644 --- a/Source/Core/Core/CoreTiming.cpp +++ b/Source/Core/Core/CoreTiming.cpp @@ -453,6 +453,11 @@ void Advance() g_slicelength = maxslicelength; 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() diff --git a/Source/Core/Core/PowerPC/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter.cpp index d394d56355..3b52caaa62 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter.cpp @@ -76,7 +76,6 @@ void CachedInterpreter::SingleStep() static void EndBlock(UGeckoInstruction data) { PC = NPC; - PowerPC::CheckExceptions(); PowerPC::ppcState.downcount -= data.hex; if (PowerPC::ppcState.downcount <= 0) { diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index f6312db207..280bb8d80a 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -278,12 +278,6 @@ void Interpreter::Run() } CoreTiming::Advance(); - - if (PowerPC::ppcState.Exceptions) - { - PowerPC::CheckExceptions(); - PC = NPC; - } } // Let the waiting thread know we are done leaving diff --git a/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp b/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp index 556b65282a..0b1638bbf3 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp @@ -202,16 +202,12 @@ void Jit64AsmRoutineManager::Generate() SetJumpTarget(bail); doTiming = GetCodePtr(); - // Test external exceptions. - TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER)); - FixupBranch noExtException = J_CC(CC_Z); + // make sure npc contains the next pc (needed for exception checking in CoreTiming::Advance) MOV(32, R(RSCRATCH), PPCSTATE(pc)); MOV(32, PPCSTATE(npc), R(RSCRATCH)); - ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(reinterpret_cast(&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)); J_CC(CC_Z, outerLoop); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp index 2a40b9fce7..e2d2b2cbcc 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp @@ -73,21 +73,18 @@ void JitArm64AsmRoutineManager::Generate() SetJumpTarget(bail); 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); BLR(X30); - // Does exception checking - LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(Exceptions)); - 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); + // Load the PC back into DISPATCHER_PC (the exception handler might have changed it) + LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); // 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()); LDR(INDEX_UNSIGNED, W0, X0, 0);