From 6f93d771065a59513e90244f3256d18444b4ad25 Mon Sep 17 00:00:00 2001 From: skidau Date: Wed, 2 Feb 2011 14:47:45 +0000 Subject: [PATCH] Fixed the DSP JIT timing when it is executing in a thread. This allows the Zelda ucode games to run when the "DSPLLE on thread" option has been enabled. However, the DSP Interpreter still hangs when this option is enabled. * Tightened the timing between the CPU and the DSP in thread mode so that it works closer to how the non-threaded mode works. The CPU now waits for all of the DSP cycles to be exhausted before adding more cycles. * DSP Idle skipping has been disabled as it messes up the timing when it is running in a thread. * Checked for external interrupt requests before entering the dispatcher and inside the dispatcher loop * Added a critical section around the mailbox read high function git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7040 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/DSP/DSPCore.cpp | 8 ++++---- Source/Core/Core/Src/DSP/DSPEmitter.cpp | 18 +++++++++++++++--- Source/Core/Core/Src/DSP/DSPHWInterface.cpp | 7 ++++++- Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp | 19 ++++++++++++------- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Source/Core/Core/Src/DSP/DSPCore.cpp b/Source/Core/Core/Src/DSP/DSPCore.cpp index 67c7cc6167..0d4ff5b962 100644 --- a/Source/Core/Core/Src/DSP/DSPCore.cpp +++ b/Source/Core/Core/Src/DSP/DSPCore.cpp @@ -250,10 +250,6 @@ int DSPCore_RunCycles(int cycles) { if (dspjit) { - cyclesLeft = cycles; - DSPCompiledCode pExecAddr = (DSPCompiledCode)dspjit->enterDispatcher; - pExecAddr(); - if (g_dsp.external_interrupt_waiting) { DSPCore_CheckExternalInterrupt(); @@ -261,6 +257,10 @@ int DSPCore_RunCycles(int cycles) DSPCore_SetExternalInterrupt(false); } + cyclesLeft = cycles; + DSPCompiledCode pExecAddr = (DSPCompiledCode)dspjit->enterDispatcher; + pExecAddr(); + return cyclesLeft; } diff --git a/Source/Core/Core/Src/DSP/DSPEmitter.cpp b/Source/Core/Core/Src/DSP/DSPEmitter.cpp index ec14a0d30c..21b3307f4f 100644 --- a/Source/Core/Core/Src/DSP/DSPEmitter.cpp +++ b/Source/Core/Core/Src/DSP/DSPEmitter.cpp @@ -20,6 +20,7 @@ #include "DSPEmitter.h" #include "DSPMemoryMap.h" #include "DSPCore.h" +#include "DSPHost.h" #include "DSPInterpreter.h" #include "DSPAnalyzer.h" #include "Jit/DSPJitUtil.h" @@ -269,7 +270,7 @@ void DSPEmitter::Compile(u16 start_addr) DSPJitRegCache c(gpr); HandleLoop(); SaveDSPRegs(); - if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) + if (!DSPHost_OnThread() && DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) { MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES)); } @@ -307,7 +308,7 @@ void DSPEmitter::Compile(u16 start_addr) DSPJitRegCache c(gpr); //don't update g_dsp.pc -- the branch insn already did SaveDSPRegs(); - if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) + if (!DSPHost_OnThread() && DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) { MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES)); } @@ -373,7 +374,7 @@ void DSPEmitter::Compile(u16 start_addr) } SaveDSPRegs(); - if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) + if (!DSPHost_OnThread() && DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) { MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES)); } @@ -401,6 +402,13 @@ void DSPEmitter::CompileDispatcher() const u8 *dispatcherLoop = GetCodePtr(); + FixupBranch exceptionExit; + if (DSPHost_OnThread()) + { + CMP(8, M(&g_dsp.external_interrupt_waiting), Imm8(0)); + exceptionExit = J_CC(CC_NE); + } + // Check for DSP halt #ifdef _M_IX86 TEST(8, M(&g_dsp.cr), Imm8(CR_HALT)); @@ -440,6 +448,10 @@ void DSPEmitter::CompileDispatcher() // DSP gave up the remaining cycles. SetJumpTarget(_halt); + if (DSPHost_OnThread()) + { + SetJumpTarget(exceptionExit); + } //MOV(32, M(&cyclesLeft), Imm32(0)); ABI_PopAllCalleeSavedRegsAndAdjustStack(); RET(); diff --git a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp index a2862affe3..5a78969de8 100644 --- a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp +++ b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp @@ -99,7 +99,12 @@ void gdsp_mbox_write_l(u8 mbx, u16 val) u16 gdsp_mbox_read_h(u8 mbx) { - return g_dsp.mbox[mbx][0]; // TODO: mask away the top bit? + if (DSPHost_OnThread()) + g_CriticalSection.Enter(); + u16 val = g_dsp.mbox[mbx][0]; // TODO: mask away the top bit? + if (DSPHost_OnThread()) + g_CriticalSection.Leave(); + return val; } diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp index 0183001be2..06a904dd62 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp @@ -86,12 +86,15 @@ void DSPLLE::dsp_thread(DSPLLE *lpParameter) { int cycles = (int)dsp_lle->m_cycle_count; if (cycles > 0) { - if (dspjit) + if (dspjit) + { DSPCore_RunCycles(cycles); + } else + { DSPInterpreter::RunCycles(cycles); - - Common::AtomicAdd(dsp_lle->m_cycle_count, -cycles); + } + Common::AtomicStore(dsp_lle->m_cycle_count, 0); } // yield? } @@ -261,8 +264,10 @@ void DSPLLE::DSP_WriteMailBoxLow(bool _CPUMailbox, u16 _uLowMail) void DSPLLE::DSP_Update(int cycles) { - unsigned int dsp_cycles = cycles / 6; //(jit?20:6); + int dsp_cycles = cycles / 6; + if (dsp_cycles <= 0) + return; // Sound stream update job has been handled by AudioDMA routine, which is more efficient /* // This gets called VERY OFTEN. The soundstream update might be expensive so only do it 200 times per second or something. @@ -289,10 +294,10 @@ void DSPLLE::DSP_Update(int cycles) } else { - // Wait for dsp thread to catch up reasonably. Note: this logic should be thought through. - while (m_cycle_count > dsp_cycles) + // Wait for dsp thread to complete its cycle. Note: this logic should be thought through. + while (m_cycle_count != 0) ; - Common::AtomicAdd(m_cycle_count, dsp_cycles); + Common::AtomicStore(m_cycle_count, dsp_cycles); } }