LLE JIT: Added simple block linking at immediate CALL's and JUMP's. The code checks if the block being jump to has already been compiled and jumps there if it has, bypassing the dispatcher. This results in a speed-up of around 7 - 10%.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6585 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
skidau 2010-12-15 07:08:36 +00:00
parent e61133625a
commit c584bd5333
3 changed files with 40 additions and 0 deletions

View File

@ -39,6 +39,7 @@ DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1)
AllocCodeSpace(COMPILED_CODE_SIZE); AllocCodeSpace(COMPILED_CODE_SIZE);
blocks = new CompiledCode[MAX_BLOCKS]; blocks = new CompiledCode[MAX_BLOCKS];
blockLinks = new CompiledCode[MAX_BLOCKS];
blockSize = new u16[0x10000]; blockSize = new u16[0x10000];
compileSR = 0; compileSR = 0;
@ -52,6 +53,7 @@ DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1)
for(int i = 0x0000; i < MAX_BLOCKS; i++) for(int i = 0x0000; i < MAX_BLOCKS; i++)
{ {
blocks[i] = (CompiledCode)stubEntryPoint; blocks[i] = (CompiledCode)stubEntryPoint;
blockLinks[i] = 0;
blockSize[i] = 0; blockSize[i] = 0;
} }
} }
@ -59,6 +61,7 @@ DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1)
DSPEmitter::~DSPEmitter() DSPEmitter::~DSPEmitter()
{ {
delete[] blocks; delete[] blocks;
delete[] blockLinks;
delete[] blockSize; delete[] blockSize;
FreeCodeSpace(); FreeCodeSpace();
} }
@ -68,6 +71,7 @@ void DSPEmitter::ClearIRAM() {
for(int i = 0x0000; i < 0x1000; i++) for(int i = 0x0000; i < 0x1000; i++)
{ {
blocks[i] = (CompiledCode)stubEntryPoint; blocks[i] = (CompiledCode)stubEntryPoint;
blockLinks[i] = 0;
blockSize[i] = 0; blockSize[i] = 0;
} }
} }
@ -202,6 +206,9 @@ void DSPEmitter::Compile(int start_addr)
if (g_dsp.exceptions == 0) if (g_dsp.exceptions == 0)
return; return;
*/ */
blockLinkEntry = GetCodePtr();
ABI_CallFunction((void *)&DSPCore_CheckExternalInterrupt); ABI_CallFunction((void *)&DSPCore_CheckExternalInterrupt);
compilePC = start_addr; compilePC = start_addr;
@ -327,6 +334,7 @@ void DSPEmitter::Compile(int start_addr)
} }
blocks[start_addr] = (CompiledCode)entryPoint; blocks[start_addr] = (CompiledCode)entryPoint;
blockLinks[start_addr] = (CompiledCode)blockLinkEntry;
if (blockSize[start_addr] == 0) if (blockSize[start_addr] == 0)
{ {
// just a safeguard, should never happen anymore. // just a safeguard, should never happen anymore.

View File

@ -156,9 +156,11 @@ public:
// CALL this to start the dispatcher // CALL this to start the dispatcher
const u8 *enterDispatcher; const u8 *enterDispatcher;
u16 compilePC; u16 compilePC;
CompiledCode *blockLinks;
private: private:
CompiledCode *blocks; CompiledCode *blocks;
const u8 *blockLinkEntry;
u16 *blockSize; u16 *blockSize;
u16 compileSR; u16 compileSR;

View File

@ -139,9 +139,24 @@ void r_jcc(const UDSPInstruction opc, DSPEmitter& emitter)
u16 dest = dsp_imem_read(emitter.compilePC + 1); u16 dest = dsp_imem_read(emitter.compilePC + 1);
#ifdef _M_IX86 // All32 #ifdef _M_IX86 // All32
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest)); emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
// Jump directly to the called block if it has already been compiled.
// TODO: Subtract cycles from cyclesLeft
if (emitter.blockLinks[dest])
{
emitter.JMPptr(M(&emitter.blockLinks[dest]));
}
#else #else
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
emitter.MOV(16, MDisp(RAX,0), Imm16(dest)); emitter.MOV(16, MDisp(RAX,0), Imm16(dest));
// Jump directly to the next block if it has already been compiled.
// TODO: Subtract cycles from cyclesLeft
if (emitter.blockLinks[dest])
{
emitter.MOV(64, R(RAX), ImmPtr(emitter.blockLinks[dest]));
emitter.JMPptr(R(RAX));
}
#endif #endif
} }
// Generic jmp implementation // Generic jmp implementation
@ -190,9 +205,24 @@ void r_call(const UDSPInstruction opc, DSPEmitter& emitter)
emitter.ABI_CallFunctionCC16((void *)dsp_reg_store_stack, DSP_STACK_C, emitter.compilePC + 2); emitter.ABI_CallFunctionCC16((void *)dsp_reg_store_stack, DSP_STACK_C, emitter.compilePC + 2);
#ifdef _M_IX86 // All32 #ifdef _M_IX86 // All32
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest)); emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
// Jump directly to the called block if it has already been compiled.
// TODO: Subtract cycles from cyclesLeft
if (emitter.blockLinks[dest])
{
emitter.JMPptr(M(&emitter.blockLinks[dest]));
}
#else #else
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
emitter.MOV(16, MDisp(RAX,0), Imm16(dest)); emitter.MOV(16, MDisp(RAX,0), Imm16(dest));
// Jump directly to the called block if it has already been compiled.
// TODO: Subtract cycles from cyclesLeft
if (emitter.blockLinks[dest])
{
emitter.MOV(64, R(RAX), ImmPtr(emitter.blockLinks[dest]));
emitter.JMPptr(R(RAX));
}
#endif #endif
} }
// Generic call implementation // Generic call implementation