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)
|
if (dspjit)
|
||||||
{
|
{
|
||||||
cyclesLeft = cycles;
|
|
||||||
DSPCompiledCode pExecAddr = (DSPCompiledCode)dspjit->enterDispatcher;
|
|
||||||
pExecAddr();
|
|
||||||
|
|
||||||
if (g_dsp.external_interrupt_waiting)
|
if (g_dsp.external_interrupt_waiting)
|
||||||
{
|
{
|
||||||
DSPCore_CheckExternalInterrupt();
|
DSPCore_CheckExternalInterrupt();
|
||||||
|
@ -261,6 +257,10 @@ int DSPCore_RunCycles(int cycles)
|
||||||
DSPCore_SetExternalInterrupt(false);
|
DSPCore_SetExternalInterrupt(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cyclesLeft = cycles;
|
||||||
|
DSPCompiledCode pExecAddr = (DSPCompiledCode)dspjit->enterDispatcher;
|
||||||
|
pExecAddr();
|
||||||
|
|
||||||
return cyclesLeft;
|
return cyclesLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "DSPEmitter.h"
|
#include "DSPEmitter.h"
|
||||||
#include "DSPMemoryMap.h"
|
#include "DSPMemoryMap.h"
|
||||||
#include "DSPCore.h"
|
#include "DSPCore.h"
|
||||||
|
#include "DSPHost.h"
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
#include "DSPAnalyzer.h"
|
#include "DSPAnalyzer.h"
|
||||||
#include "Jit/DSPJitUtil.h"
|
#include "Jit/DSPJitUtil.h"
|
||||||
|
@ -269,7 +270,7 @@ void DSPEmitter::Compile(u16 start_addr)
|
||||||
DSPJitRegCache c(gpr);
|
DSPJitRegCache c(gpr);
|
||||||
HandleLoop();
|
HandleLoop();
|
||||||
SaveDSPRegs();
|
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));
|
MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES));
|
||||||
}
|
}
|
||||||
|
@ -307,7 +308,7 @@ void DSPEmitter::Compile(u16 start_addr)
|
||||||
DSPJitRegCache c(gpr);
|
DSPJitRegCache c(gpr);
|
||||||
//don't update g_dsp.pc -- the branch insn already did
|
//don't update g_dsp.pc -- the branch insn already did
|
||||||
SaveDSPRegs();
|
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));
|
MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES));
|
||||||
}
|
}
|
||||||
|
@ -373,7 +374,7 @@ void DSPEmitter::Compile(u16 start_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveDSPRegs();
|
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));
|
MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES));
|
||||||
}
|
}
|
||||||
|
@ -401,6 +402,13 @@ void DSPEmitter::CompileDispatcher()
|
||||||
|
|
||||||
const u8 *dispatcherLoop = GetCodePtr();
|
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
|
// Check for DSP halt
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
TEST(8, M(&g_dsp.cr), Imm8(CR_HALT));
|
TEST(8, M(&g_dsp.cr), Imm8(CR_HALT));
|
||||||
|
@ -440,6 +448,10 @@ void DSPEmitter::CompileDispatcher()
|
||||||
|
|
||||||
// DSP gave up the remaining cycles.
|
// DSP gave up the remaining cycles.
|
||||||
SetJumpTarget(_halt);
|
SetJumpTarget(_halt);
|
||||||
|
if (DSPHost_OnThread())
|
||||||
|
{
|
||||||
|
SetJumpTarget(exceptionExit);
|
||||||
|
}
|
||||||
//MOV(32, M(&cyclesLeft), Imm32(0));
|
//MOV(32, M(&cyclesLeft), Imm32(0));
|
||||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||||
RET();
|
RET();
|
||||||
|
|
|
@ -99,7 +99,12 @@ void gdsp_mbox_write_l(u8 mbx, u16 val)
|
||||||
|
|
||||||
u16 gdsp_mbox_read_h(u8 mbx)
|
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;
|
int cycles = (int)dsp_lle->m_cycle_count;
|
||||||
if (cycles > 0) {
|
if (cycles > 0) {
|
||||||
if (dspjit)
|
if (dspjit)
|
||||||
|
{
|
||||||
DSPCore_RunCycles(cycles);
|
DSPCore_RunCycles(cycles);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DSPInterpreter::RunCycles(cycles);
|
DSPInterpreter::RunCycles(cycles);
|
||||||
|
}
|
||||||
Common::AtomicAdd(dsp_lle->m_cycle_count, -cycles);
|
Common::AtomicStore(dsp_lle->m_cycle_count, 0);
|
||||||
}
|
}
|
||||||
// yield?
|
// yield?
|
||||||
}
|
}
|
||||||
|
@ -261,8 +264,10 @@ void DSPLLE::DSP_WriteMailBoxLow(bool _CPUMailbox, u16 _uLowMail)
|
||||||
|
|
||||||
void DSPLLE::DSP_Update(int cycles)
|
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
|
// 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.
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// Wait for dsp thread to catch up reasonably. Note: this logic should be thought through.
|
// Wait for dsp thread to complete its cycle. Note: this logic should be thought through.
|
||||||
while (m_cycle_count > dsp_cycles)
|
while (m_cycle_count != 0)
|
||||||
;
|
;
|
||||||
Common::AtomicAdd(m_cycle_count, dsp_cycles);
|
Common::AtomicStore(m_cycle_count, dsp_cycles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue