From ae71e63872dac1e8cfedccfc3529b86e67439270 Mon Sep 17 00:00:00 2001 From: skidau Date: Mon, 3 Jan 2011 14:19:11 +0000 Subject: [PATCH] LLE JIT: Minimised exception checking. Instructions which need to check for exceptions are now marked in the analyser. Moved the checking for external interrupts to the point where the CPU writes to the control register. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6729 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DSPCore/Src/DSPAnalyzer.cpp | 12 +++++++++ Source/Core/DSPCore/Src/DSPAnalyzer.h | 1 + Source/Core/DSPCore/Src/DSPEmitter.cpp | 31 ++-------------------- Source/Plugins/Plugin_DSP_LLE/Src/main.cpp | 9 +++++++ 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/Source/Core/DSPCore/Src/DSPAnalyzer.cpp b/Source/Core/DSPCore/Src/DSPAnalyzer.cpp index b4300867ac..8f6b0d4e35 100644 --- a/Source/Core/DSPCore/Src/DSPAnalyzer.cpp +++ b/Source/Core/DSPCore/Src/DSPAnalyzer.cpp @@ -123,6 +123,18 @@ void AnalyzeRange(int start_addr, int end_addr) code_flags[last_arithmetic] |= CODE_UPDATE_SR; } + // If an instruction potentially raises exceptions, mark the following + // instruction as needing to check for exceptions + if (opcode->opcode == 0x00c0 || + opcode->opcode == 0x1800 || + opcode->opcode == 0x1880 || + opcode->opcode == 0x1900 || + opcode->opcode == 0x1980 || + opcode->opcode == 0x2000 || + opcode->extended + ) + code_flags[addr + opcode->size] |= CODE_CHECK_INT; + addr += opcode->size; } diff --git a/Source/Core/DSPCore/Src/DSPAnalyzer.h b/Source/Core/DSPCore/Src/DSPAnalyzer.h index aeb3b9e480..9c05dae708 100644 --- a/Source/Core/DSPCore/Src/DSPAnalyzer.h +++ b/Source/Core/DSPCore/Src/DSPAnalyzer.h @@ -33,6 +33,7 @@ enum CODE_LOOP_START = 4, CODE_LOOP_END = 8, CODE_UPDATE_SR = 16, + CODE_CHECK_INT = 32, }; // Easy to query array covering the whole of instruction memory. diff --git a/Source/Core/DSPCore/Src/DSPEmitter.cpp b/Source/Core/DSPCore/Src/DSPEmitter.cpp index 5835196a60..8d36465ee8 100644 --- a/Source/Core/DSPCore/Src/DSPEmitter.cpp +++ b/Source/Core/DSPCore/Src/DSPEmitter.cpp @@ -210,34 +210,6 @@ void DSPEmitter::Compile(u16 start_addr) blockLinkEntry = GetCodePtr(); -// ASM version of DSPCore_CheckExternalInterrupt. -#ifdef _M_IX86 // All32 - TEST(16, M(&g_dsp.cr), Imm16(CR_EXTERNAL_INT)); - FixupBranch noExternalInterrupt = J_CC(CC_Z); - TEST(16, M(&g_dsp.r.sr), Imm16(SR_EXT_INT_ENABLE)); - FixupBranch externalInterruptDisabled = J_CC(CC_Z); - OR(8, M(&g_dsp.exceptions), Imm8(1 << EXP_INT)); - AND(16, M(&g_dsp.cr), Imm16(~CR_EXTERNAL_INT)); - SetJumpTarget(externalInterruptDisabled); - SetJumpTarget(noExternalInterrupt); -#else - /* // TODO: Needs to be optimised - MOV(64, R(RAX), ImmPtr(&g_dsp.cr)); - TEST(16, MatR(RAX), Imm16(CR_EXTERNAL_INT)); - FixupBranch noExternalInterrupt = J_CC(CC_Z); - MOV(64, R(RAX), ImmPtr(&g_dsp.r.sr)); - TEST(16, MatR(RAX), Imm16(SR_EXT_INT_ENABLE)); - FixupBranch externalInterruptDisabled = J_CC(CC_Z); - MOV(64, R(RAX), ImmPtr(&g_dsp.exceptions)); - OR(8, MatR(RAX), Imm8(1 << EXP_INT)); - MOV(64, R(RAX), ImmPtr(&g_dsp.cr)); - AND(16, MatR(RAX), Imm16(~CR_EXTERNAL_INT)); - SetJumpTarget(externalInterruptDisabled); - SetJumpTarget(noExternalInterrupt); - */ - ABI_CallFunction((void *)&DSPCore_CheckExternalInterrupt); -#endif - compilePC = start_addr; bool fixup_pc = false; blockSize[start_addr] = 0; @@ -246,7 +218,8 @@ void DSPEmitter::Compile(u16 start_addr) while (compilePC < start_addr + MAX_BLOCK_SIZE) { - checkExceptions(blockSize[start_addr]); + if (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_CHECK_INT) + checkExceptions(blockSize[start_addr]); UDSPInstruction inst = dsp_imem_read(compilePC); const DSPOPCTemplate *opcode = GetOpTemplate(inst); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp index f3b46a0524..e1971bd4ae 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp @@ -278,6 +278,15 @@ u16 DSP_WriteControlRegister(u16 _uFlag) } } DSPInterpreter::WriteCR(_uFlag); + + // Check if the CPU has set an external interrupt (CR_EXTERNAL_INT) + // and immediately process it, if it has. + if (_uFlag & 2) + { + DSPCore_CheckExternalInterrupt(); + DSPCore_CheckExceptions(); + } + return DSPInterpreter::ReadCR(); }