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:
parent
e61133625a
commit
c584bd5333
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue