LLE JIT: Speed up the idle skip detection by moving the logic into the block and removing it from the dispatcher. This works because we can detect the idle skip blocks at compile time.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6488 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
skidau 2010-11-28 11:04:50 +00:00
parent ae2c934795
commit 9c1fb241c7
2 changed files with 28 additions and 37 deletions

View File

@ -353,13 +353,13 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
if (_iAddress != (0xCC000000 + DSP_MAIL_FROM_DSP_HI))
{
DEBUG_LOG(DSPINTERFACE, "DSPInterface(r16) 0x%08x (%02x) (%08x)", _iAddress, _uReturnValue, PowerPC::ppcState.pc);
DEBUG_LOG(DSPINTERFACE, "DSPInterface(r16) 0x%08x (0x%04x) (%08x)", _iAddress, _uReturnValue, PowerPC::ppcState.pc);
}
}
void Write16(const u16 _Value, const u32 _Address)
{
DEBUG_LOG(DSPINTERFACE, "DSPInterface(w16) 0x%04x 0x%08x", _Value, _Address);
DEBUG_LOG(DSPINTERFACE, "DSPInterface(w16) 0x%08x (0x%04x) (%08x)", _Address, _Value, PowerPC::ppcState.pc);
switch (_Address & 0xFFFF)
{

View File

@ -220,7 +220,14 @@ void DSPEmitter::Compile(int start_addr)
ABI_CallFunction((void *)&DSPInterpreter::HandleLoop);
// ABI_RestoreStack(0);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
MOV(32,R(EAX),Imm32(blockSize[start_addr]));
if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
{
MOV(32,R(EAX),Imm32(DSP_IDLE_SKIP_CYCLES));
}
else
{
MOV(32,R(EAX),Imm32(blockSize[start_addr]));
}
RET();
SetJumpTarget(rLoopAddressExit);
@ -246,7 +253,14 @@ void DSPEmitter::Compile(int start_addr)
// ABI_RestoreStack(0);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
MOV(32,R(EAX),Imm32(blockSize[start_addr]));
if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
{
MOV(32,R(EAX),Imm32(DSP_IDLE_SKIP_CYCLES));
}
else
{
MOV(32,R(EAX),Imm32(blockSize[start_addr]));
}
RET();
SetJumpTarget(rNoBranch);
@ -271,7 +285,14 @@ void DSPEmitter::Compile(int start_addr)
// ABI_RestoreStack(0);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
MOV(32,R(EAX),Imm32(blockSize[start_addr]));
if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
{
MOV(32,R(EAX),Imm32(DSP_IDLE_SKIP_CYCLES));
}
else
{
MOV(32,R(EAX),Imm32(blockSize[start_addr]));
}
RET();
}
@ -311,25 +332,6 @@ void DSPEmitter::CompileDispatcher()
CMP(32, R(ESI), R(EAX));
FixupBranch noCycles = J_CC(CC_B);
// Check for idle skip (C++ version below)
// if (code_flags[pc] & CODE_IDLE_SKIP)
// if (cycles > DSP_IDLE_SKIP_CYCLES) cycles -= DSP_IDLE_SKIP_CYCLES;
// else cycles = 0;
#ifdef _M_IX86
MOV(32, R(EDX), Imm32((u32)DSPAnalyzer::code_flags));
#else
MOV(64, R(RDX), Imm64((u64)DSPAnalyzer::code_flags));
#endif
TEST(8, MComplex(RDX, ECX, SCALE_1, 0), Imm8(DSPAnalyzer::CODE_IDLE_SKIP));
FixupBranch noIdleSkip = J_CC(CC_E);
SUB(32, R(ESI), Imm32(DSP_IDLE_SKIP_CYCLES));
FixupBranch idleSkip = J_CC(CC_A);
//MOV(32, M(&cyclesLeft), Imm32(0));
ABI_PopAllCalleeSavedRegsAndAdjustStack();
RET();
SetJumpTarget(idleSkip);
SetJumpTarget(noIdleSkip);
// Execute block. Cycles executed returned in EAX.
#ifdef _M_IX86
CALLptr(MComplex(EBX, ECX, SCALE_4, 0));
@ -374,18 +376,7 @@ int STACKALIGN DSPEmitter::RunForCycles(int cycles)
// Execute the block if we have enough cycles
if (cycles > block_size)
{
int c = blocks[block_addr]();
if (DSPAnalyzer::code_flags[block_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
{
if (cycles > idle_cycles)
cycles -= idle_cycles;
else
cycles = 0;
}
else
{
cycles -= c;
}
cycles -= blocks[block_addr]();
}
else
{
@ -394,7 +385,7 @@ int STACKALIGN DSPEmitter::RunForCycles(int cycles)
}
// DSP gave up the remaining cycles.
if (g_dsp.cr & CR_HALT)
if (g_dsp.cr & CR_HALT || cycles < 0)
return 0;
return cycles;