From 1d550f4496e48c5c38e4a7175a3c49205db3f49d Mon Sep 17 00:00:00 2001 From: skidau Date: Mon, 25 Mar 2013 00:47:44 +1100 Subject: [PATCH 1/4] Forced the external exception check to occur sooner by changing the downcount. Fixes issue 5825. --- Source/Core/Core/Src/CoreTiming.cpp | 18 ++++++++++++++++++ Source/Core/Core/Src/CoreTiming.h | 2 ++ .../Core/VideoCommon/Src/CommandProcessor.cpp | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index 525f7165f2..74ad817bf4 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -250,6 +250,8 @@ void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata if(tsLast) tsLast->next = ne; tsLast = ne; + + SetDowncount(ne->type, cyclesIntoFuture); } // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread @@ -260,6 +262,7 @@ void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) { std::lock_guard lk(externalEventSection); event_types[event_type].callback(userdata, 0); + SetDowncount(event_type, 0); } else ScheduleEvent_Threadsafe(0, event_type, userdata); @@ -413,6 +416,21 @@ void SetMaximumSlice(int maximumSliceLength) maxSliceLength = maximumSliceLength; } +void SetDowncount(int event_type, int cycles) +{ + if (event_types[event_type].name == "SetToken") + return; + + if (cycles == 0) + cycles = 100; // External Exception latency. Paper Mario TTYD freezes in fight scenes if this is zero. + + if (downcount > cycles) + { + slicelength -= (downcount - cycles); // Account for cycles already executed by adjusting the slicelength + downcount = cycles; + } +} + void ResetSliceLength() { maxSliceLength = MAX_SLICE_LENGTH; diff --git a/Source/Core/Core/Src/CoreTiming.h b/Source/Core/Core/Src/CoreTiming.h index db8dcecfc1..88c9de5948 100644 --- a/Source/Core/Core/Src/CoreTiming.h +++ b/Source/Core/Core/Src/CoreTiming.h @@ -92,6 +92,8 @@ void SetFakeTBStartValue(u64 val); u64 GetFakeTBStartTicks(); void SetFakeTBStartTicks(u64 val); +void SetDowncount(int event_type, int cycles); + extern int downcount; extern int slicelength; diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index 4b2eaba1e0..71b4591bf7 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -144,7 +144,7 @@ void Init() isHiWatermarkActive = false; isLoWatermarkActive = false; - et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper); + et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper); } void Read16(u16& _rReturnValue, const u32 _Address) From 4fa61a1e7ff247678da8500e81b4208128bc591a Mon Sep 17 00:00:00 2001 From: skidau Date: Mon, 25 Mar 2013 00:57:53 +1100 Subject: [PATCH 2/4] Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4. --- Source/Core/Core/Src/HW/GPFifo.cpp | 14 ----------- Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp | 24 ------------------- Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp | 2 +- Source/Core/Core/Src/PowerPC/Jit64IL/IR.h | 5 +--- .../Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp | 22 ----------------- .../Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp | 5 ---- .../Core/Core/Src/PowerPC/JitCommon/JitBase.h | 2 -- 7 files changed, 2 insertions(+), 72 deletions(-) diff --git a/Source/Core/Core/Src/HW/GPFifo.cpp b/Source/Core/Core/Src/HW/GPFifo.cpp index a7f7bd967b..ab3058bd8d 100644 --- a/Source/Core/Core/Src/HW/GPFifo.cpp +++ b/Source/Core/Core/Src/HW/GPFifo.cpp @@ -96,20 +96,6 @@ void STACKALIGN CheckGatherPipe() // move back the spill bytes memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount); - - // Profile where the FIFO writes are occurring. - if (jit && PC != 0 && (jit->js.fifoWriteAddresses.find(PC)) == (jit->js.fifoWriteAddresses.end())) - { - // Log only stores, fp stores and ps stores, filtering out other instructions arrived via optimizeGatherPipe - int type = GetOpInfo(Memory::ReadUnchecked_U32(PC))->type; - if (type == OPTYPE_STORE || type == OPTYPE_STOREFP || (type == OPTYPE_PS && !strcmp(GetOpInfo(Memory::ReadUnchecked_U32(PC))->opname, "psq_st"))) - { - jit->js.fifoWriteAddresses.insert(PC); - - // Invalidate the JIT block so that it gets recompiled with the external exception check included. - jit->GetBlockCache()->InvalidateICache(PC, 4); - } - } } } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index be4789e233..fd24b36406 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -611,30 +611,6 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc js.firstFPInstructionFound = true; } - // Add an external exception check if the instruction writes to the FIFO. - if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end()) - { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); - - TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT)); - FixupBranch clearInt = J_CC(CC_NZ, true); - TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT)); - FixupBranch noExtException = J_CC(CC_Z, true); - TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000)); - FixupBranch noExtIntEnable = J_CC(CC_Z, true); - TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH)); - FixupBranch noCPInt = J_CC(CC_Z, true); - - MOV(32, M(&PC), Imm32(ops[i].address)); - WriteExternalExceptionExit(); - - SetJumpTarget(noCPInt); - SetJumpTarget(noExtIntEnable); - SetJumpTarget(noExtException); - SetJumpTarget(clearInt); - } - if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING) { gpr.Flush(FLUSH_ALL); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp index 2a830a03cf..fdec5b747d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp @@ -1269,7 +1269,7 @@ static const unsigned alwaysUsedList[] = { Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR, BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop, SystemCall, InterpreterBranch, RFIExit, FPExceptionCheck, - DSIExceptionCheck, ISIException, ExtExceptionCheck, BreakPointCheck, + DSIExceptionCheck, ISIException, BreakPointCheck, Int3, Tramp, Nop }; static const unsigned extra8RegList[] = { diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h index 7fabd946f9..5bc7da9d8d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h @@ -168,7 +168,7 @@ enum Opcode { // used for exception checking, at least until someone // has a better idea of integrating it FPExceptionCheck, DSIExceptionCheck, - ISIException, ExtExceptionCheck, BreakPointCheck, + ISIException, BreakPointCheck, // "Opcode" representing a register too far away to // reference directly; this is a size optimization Tramp, @@ -411,9 +411,6 @@ public: InstLoc EmitISIException(InstLoc dest) { return EmitUOp(ISIException, dest); } - InstLoc EmitExtExceptionCheck(InstLoc pc) { - return EmitUOp(ExtExceptionCheck, pc); - } InstLoc EmitBreakPointCheck(InstLoc pc) { return EmitUOp(BreakPointCheck, pc); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index 7c12d613a3..88d815e33d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -762,7 +762,6 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak case FPExceptionCheck: case DSIExceptionCheck: case ISIException: - case ExtExceptionCheck: case BreakPointCheck: case Int3: case Tramp: @@ -1941,27 +1940,6 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak Jit->WriteExceptionExit(); break; } - case ExtExceptionCheck: { - unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); - - Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT)); - FixupBranch clearInt = Jit->J_CC(CC_NZ); - Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT)); - FixupBranch noExtException = Jit->J_CC(CC_Z); - Jit->TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000)); - FixupBranch noExtIntEnable = Jit->J_CC(CC_Z); - Jit->TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH)); - FixupBranch noCPInt = Jit->J_CC(CC_Z); - - Jit->MOV(32, M(&PC), Imm32(InstLoc)); - Jit->WriteExceptionExit(); - - Jit->SetJumpTarget(noCPInt); - Jit->SetJumpTarget(noExtIntEnable); - Jit->SetJumpTarget(noExtException); - Jit->SetJumpTarget(clearInt); - break; - } case BreakPointCheck: { unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index a60becfad9..f10df33d99 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -679,11 +679,6 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc ibuild.EmitFPExceptionCheck(ibuild.EmitIntConst(ops[i].address)); } - if (jit->js.fifoWriteAddresses.find(js.compilerPC) != jit->js.fifoWriteAddresses.end()) - { - ibuild.EmitExtExceptionCheck(ibuild.EmitIntConst(ops[i].address)); - } - if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING) { ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address)); diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h index 158171be0f..9b8c67474c 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h @@ -74,8 +74,6 @@ protected: u8* rewriteStart; JitBlock *curBlock; - - std::set fifoWriteAddresses; }; public: From dfa1845ae1b252bd61a9daa989cab4daf53dbdb4 Mon Sep 17 00:00:00 2001 From: skidau Date: Mon, 25 Mar 2013 01:01:29 +1100 Subject: [PATCH 3/4] Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4. --- Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index fd24b36406..3995fc9299 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -341,7 +341,7 @@ void Jit64::WriteRfiExitDestInEAX() Cleanup(); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); - JMP(asm_routines.outerLoop, true); + JMP(asm_routines.dispatcher, true); } void Jit64::WriteExceptionExit() From 0ccaaee38c0d21212668ed9e7741feb84c91c365 Mon Sep 17 00:00:00 2001 From: skidau Date: Tue, 26 Mar 2013 08:23:20 +1100 Subject: [PATCH 4/4] Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check. --- Source/Core/Core/Src/CoreTiming.cpp | 12 +----------- Source/Core/Core/Src/CoreTiming.h | 2 +- Source/Core/Core/Src/HW/DSP.cpp | 4 ++++ Source/Core/VideoCommon/Src/CommandProcessor.cpp | 9 +++------ 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index 74ad817bf4..ff9488b4fe 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -250,8 +250,6 @@ void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata if(tsLast) tsLast->next = ne; tsLast = ne; - - SetDowncount(ne->type, cyclesIntoFuture); } // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread @@ -262,7 +260,6 @@ void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) { std::lock_guard lk(externalEventSection); event_types[event_type].callback(userdata, 0); - SetDowncount(event_type, 0); } else ScheduleEvent_Threadsafe(0, event_type, userdata); @@ -416,14 +413,8 @@ void SetMaximumSlice(int maximumSliceLength) maxSliceLength = maximumSliceLength; } -void SetDowncount(int event_type, int cycles) +void ForceExceptionCheck(int cycles) { - if (event_types[event_type].name == "SetToken") - return; - - if (cycles == 0) - cycles = 100; // External Exception latency. Paper Mario TTYD freezes in fight scenes if this is zero. - if (downcount > cycles) { slicelength -= (downcount - cycles); // Account for cycles already executed by adjusting the slicelength @@ -486,7 +477,6 @@ void MoveEvents() void Advance() { - MoveEvents(); int cyclesExecuted = slicelength - downcount; diff --git a/Source/Core/Core/Src/CoreTiming.h b/Source/Core/Core/Src/CoreTiming.h index 88c9de5948..8e00b303f0 100644 --- a/Source/Core/Core/Src/CoreTiming.h +++ b/Source/Core/Core/Src/CoreTiming.h @@ -92,7 +92,7 @@ void SetFakeTBStartValue(u64 val); u64 GetFakeTBStartTicks(); void SetFakeTBStartTicks(u64 val); -void SetDowncount(int event_type, int cycles); +void ForceExceptionCheck(int cycles); extern int downcount; extern int slicelength; diff --git a/Source/Core/Core/Src/HW/DSP.cpp b/Source/Core/Core/Src/HW/DSP.cpp index 6fb6778d9d..a9acf6aedc 100644 --- a/Source/Core/Core/Src/HW/DSP.cpp +++ b/Source/Core/Core/Src/HW/DSP.cpp @@ -696,6 +696,10 @@ void Do_ARAM_DMA() g_dspState.DSPControl.DMAState = 1; CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16)); + // Force an early exception check. Fixes RE2 audio. + if (g_arDMA.Cnt.count == 4096) + CoreTiming::ForceExceptionCheck(100); + // Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks if (g_arDMA.Cnt.dir) { diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index 71b4591bf7..dacec67823 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -642,14 +642,11 @@ void SetCpStatusRegister() void SetCpControlRegister() { - // If the new fifo is being attached We make sure there wont be SetFinish event pending. - // This protection fix eternal darkness booting, because the second SetFinish event when it is booting - // seems invalid or has a bug and hang the game. - + // If the new fifo is being attached, force an exception check + // This fixes the hang while booting Eternal Darkness if (!fifo.bFF_GPReadEnable && m_CPCtrlReg.GPReadEnable && !m_CPCtrlReg.BPEnable) { - ProcessFifoEvents(); - PixelEngine::ResetSetFinish(); + CoreTiming::ForceExceptionCheck(0); } fifo.bFF_BPInt = m_CPCtrlReg.BPInt;