From c584bd533383ca6ec1fec35ff0b0794d6c64fe5e Mon Sep 17 00:00:00 2001 From: skidau Date: Wed, 15 Dec 2010 07:08:36 +0000 Subject: [PATCH] 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 --- Source/Core/DSPCore/Src/DSPEmitter.cpp | 8 ++++++ Source/Core/DSPCore/Src/DSPEmitter.h | 2 ++ Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp | 30 ++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/Source/Core/DSPCore/Src/DSPEmitter.cpp b/Source/Core/DSPCore/Src/DSPEmitter.cpp index a9da27e405..27c636d6dc 100644 --- a/Source/Core/DSPCore/Src/DSPEmitter.cpp +++ b/Source/Core/DSPCore/Src/DSPEmitter.cpp @@ -39,6 +39,7 @@ DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1) AllocCodeSpace(COMPILED_CODE_SIZE); blocks = new CompiledCode[MAX_BLOCKS]; + blockLinks = new CompiledCode[MAX_BLOCKS]; blockSize = new u16[0x10000]; compileSR = 0; @@ -52,6 +53,7 @@ DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1) for(int i = 0x0000; i < MAX_BLOCKS; i++) { blocks[i] = (CompiledCode)stubEntryPoint; + blockLinks[i] = 0; blockSize[i] = 0; } } @@ -59,6 +61,7 @@ DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1) DSPEmitter::~DSPEmitter() { delete[] blocks; + delete[] blockLinks; delete[] blockSize; FreeCodeSpace(); } @@ -68,6 +71,7 @@ void DSPEmitter::ClearIRAM() { for(int i = 0x0000; i < 0x1000; i++) { blocks[i] = (CompiledCode)stubEntryPoint; + blockLinks[i] = 0; blockSize[i] = 0; } } @@ -202,6 +206,9 @@ void DSPEmitter::Compile(int start_addr) if (g_dsp.exceptions == 0) return; */ + + blockLinkEntry = GetCodePtr(); + ABI_CallFunction((void *)&DSPCore_CheckExternalInterrupt); compilePC = start_addr; @@ -327,6 +334,7 @@ void DSPEmitter::Compile(int start_addr) } blocks[start_addr] = (CompiledCode)entryPoint; + blockLinks[start_addr] = (CompiledCode)blockLinkEntry; if (blockSize[start_addr] == 0) { // just a safeguard, should never happen anymore. diff --git a/Source/Core/DSPCore/Src/DSPEmitter.h b/Source/Core/DSPCore/Src/DSPEmitter.h index 017203e952..a5fb0f2f0c 100644 --- a/Source/Core/DSPCore/Src/DSPEmitter.h +++ b/Source/Core/DSPCore/Src/DSPEmitter.h @@ -156,9 +156,11 @@ public: // CALL this to start the dispatcher const u8 *enterDispatcher; u16 compilePC; + CompiledCode *blockLinks; private: CompiledCode *blocks; + const u8 *blockLinkEntry; u16 *blockSize; u16 compileSR; diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp index a588189824..ff1700ce65 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp @@ -139,9 +139,24 @@ void r_jcc(const UDSPInstruction opc, DSPEmitter& emitter) u16 dest = dsp_imem_read(emitter.compilePC + 1); #ifdef _M_IX86 // All32 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 emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); 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 } // 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); #ifdef _M_IX86 // All32 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 emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); 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 } // Generic call implementation