From d09e2abb0d963d794b9ff04b17b161f68b61b84b Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 6 Sep 2014 18:59:38 +1000 Subject: [PATCH] Compile the ARAM DMA exception checks into the JIT block in a similar style to FIFO writes. This ensures that the ARAM DMA is handled soon after the DMA completes. Fixes issue 7122 and issue 7342. --- Source/Core/Core/HW/DSP.cpp | 30 +++++++++++--------- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 12 ++++++-- Source/Core/Core/PowerPC/JitCommon/JitBase.h | 1 + 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/Source/Core/Core/HW/DSP.cpp b/Source/Core/Core/HW/DSP.cpp index 5b16f23139..82c7149c71 100644 --- a/Source/Core/Core/HW/DSP.cpp +++ b/Source/Core/Core/HW/DSP.cpp @@ -38,6 +38,7 @@ #include "Core/HW/MMIO.h" #include "Core/HW/ProcessorInterface.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/PowerPC/JitCommon/JitBase.h" namespace DSP { @@ -441,6 +442,21 @@ static void UpdateInterrupts() bool ints_set = (((g_dspState.DSPControl.Hex >> 1) & g_dspState.DSPControl.Hex & (INT_DSP | INT_ARAM | INT_AID)) != 0); ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_DSP, ints_set); + + if ((g_dspState.DSPControl.Hex >> 1) & g_dspState.DSPControl.Hex & (INT_DSP | INT_ARAM | INT_AID)) + { + if (jit && PC != 0 && (jit->js.dspARAMAddresses.find(PC)) == (jit->js.dspARAMAddresses.end()) && (g_dspState.DSPControl.ARAM & g_dspState.DSPControl.ARAM_mask)) + { + int type = GetOpInfo(Memory::ReadUnchecked_U32(PC))->type; + if (type == OPTYPE_STORE || type == OPTYPE_STOREFP || (type == OPTYPE_PS && GetOpInfo(Memory::ReadUnchecked_U32(PC))->opname == "psq_st")) + { + jit->js.dspARAMAddresses.insert(PC); + + // Invalidate the JIT block so that it gets recompiled with the external exception check included. + jit->GetBlockCache()->InvalidateICache(PC, 4); + } + } + } } static void GenerateDSPInterrupt(u64 DSPIntType, int cyclesLate) @@ -518,25 +534,11 @@ static void Do_ARAM_DMA() g_dspState.DSPControl.DMAState = 1; if (g_arDMA.Cnt.count == 32) { - // Beyond Good and Evil (GGEE41) sends count 32 - // Lost Kingdoms 2 needs the exception check here in DSP HLE mode CompleteARAM(0, 0); - CoreTiming::ForceExceptionCheck(100); } else { CoreTiming::ScheduleEvent_Threadsafe(0, et_CompleteARAM); - - // Force an early exception check on large transfers. Fixes RE2 audio. - // NFS:HP2 (<= 6144) - // Viewtiful Joe (<= 6144) - // Sonic Mega Collection (> 2048) - // Paper Mario battles (> 32) - // Mario Super Baseball (> 32) - // Knockout Kings 2003 loading (> 32) - // WWE DOR (> 32) - if (g_arDMA.Cnt.count > 2048 && g_arDMA.Cnt.count <= 6144) - CoreTiming::ForceExceptionCheck(100); } // Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 9b88538935..89a61e59d3 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -697,7 +697,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc } // Add an external exception check if the instruction writes to the FIFO. - if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end()) + if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end() || + jit->js.dspARAMAddresses.find(ops[i].address) != jit->js.dspARAMAddresses.end()) { TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT)); FixupBranch clearInt = J_CC(CC_NZ); @@ -707,7 +708,14 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc SetJumpTarget(extException); TEST(32, 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)); + if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end()) + { + TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH)); + } + else + { + TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_DSP)); + } FixupBranch noCPInt = J_CC(CC_Z, true); gpr.Flush(FLUSH_MAINTAIN_STATE); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/PowerPC/JitCommon/JitBase.h index 52463ec619..fc40d3cfd0 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.h @@ -97,6 +97,7 @@ protected: JitBlock *curBlock; std::unordered_set fifoWriteAddresses; + std::unordered_set dspARAMAddresses; }; PPCAnalyst::CodeBlock code_block;