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:
parent
8b309e26dc
commit
6f93d77106
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue