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
This commit is contained in:
skidau 2011-02-02 14:47:45 +00:00
parent 8b309e26dc
commit 6f93d77106
4 changed files with 37 additions and 15 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
}
}