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(); }