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
This commit is contained in:
skidau 2011-01-03 14:19:11 +00:00
parent a6637c257f
commit ae71e63872
4 changed files with 24 additions and 29 deletions

View File

@ -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;
}

View File

@ -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.

View File

@ -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);

View File

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