Core/DSPCore: Only check for internal exceptions in DSPEmitter::checkException, but

call it for every instruction, like in DSPInterpreter::Step. Fix the analysis lookups
for DSP_IDLE_SKIP and DSP_LOOP_END.

After this patch, the block_size and the return value from the block always match,
except when an internal exception is detected. This will change in a later patch,
so we actually get some benefits from checking if we need to call HandleLoop().


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6280 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
pierre
2010-10-14 11:37:59 +00:00
parent 6e6a0be8c4
commit 47eb5c3416

View File

@ -71,24 +71,6 @@ void DSPEmitter::ClearIRAM() {
// Must go out of block if exception is detected // Must go out of block if exception is detected
void DSPEmitter::checkExceptions(u32 retval) { void DSPEmitter::checkExceptions(u32 retval) {
/*
// check if there is an external interrupt
if (! dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
return;
if (! (g_dsp.cr & CR_EXTERNAL_INT))
return;
g_dsp.cr &= ~CR_EXTERNAL_INT;
// Check for other exceptions
if (dsp_SR_is_flag_set(SR_INT_ENABLE))
return;
if (g_dsp.exceptions == 0)
return;
*/
ABI_CallFunction((void *)&DSPCore_CheckExternalInterrupt);
// Check for interrupts and exceptions // Check for interrupts and exceptions
#ifdef _M_IX86 // All32 #ifdef _M_IX86 // All32
TEST(8, M(&g_dsp.exceptions), Imm8(0xff)); TEST(8, M(&g_dsp.exceptions), Imm8(0xff));
@ -167,11 +149,31 @@ const u8 *DSPEmitter::Compile(int start_addr) {
ABI_PushAllCalleeSavedRegsAndAdjustStack(); ABI_PushAllCalleeSavedRegsAndAdjustStack();
// ABI_AlignStack(0); // ABI_AlignStack(0);
/*
// check if there is an external interrupt
if (! dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
return;
if (! (g_dsp.cr & CR_EXTERNAL_INT))
return;
g_dsp.cr &= ~CR_EXTERNAL_INT;
// Check for other exceptions
if (dsp_SR_is_flag_set(SR_INT_ENABLE))
return;
if (g_dsp.exceptions == 0)
return;
*/
ABI_CallFunction((void *)&DSPCore_CheckExternalInterrupt);
int addr = start_addr; int addr = start_addr;
blockSize[start_addr] = 0; blockSize[start_addr] = 0;
checkExceptions(blockSize[start_addr]);
while (addr < start_addr + MAX_BLOCK_SIZE) while (addr < start_addr + MAX_BLOCK_SIZE)
{ {
checkExceptions(blockSize[start_addr]);
UDSPInstruction inst = dsp_imem_read(addr); UDSPInstruction inst = dsp_imem_read(addr);
const DSPOPCTemplate *opcode = GetOpTemplate(inst); const DSPOPCTemplate *opcode = GetOpTemplate(inst);
@ -187,12 +189,11 @@ const u8 *DSPEmitter::Compile(int start_addr) {
EmitInstruction(inst); EmitInstruction(inst);
blockSize[start_addr]++; blockSize[start_addr]++;
addr += opcode->size;
// Handle loop condition, only if current instruction was flagged as a loop destination // Handle loop condition, only if current instruction was flagged as a loop destination
// by the analyzer. COMMENTED OUT - this breaks Zelda TP. Bah. // by the analyzer.
//probably just misses a +opcode->size-1 if (DSPAnalyzer::code_flags[addr-1] & DSPAnalyzer::CODE_LOOP_END)
// if (DSPAnalyzer::code_flags[addr] & DSPAnalyzer::CODE_LOOP_END)
{ {
// TODO: Change to TEST for some reason (who added this comment?) // TODO: Change to TEST for some reason (who added this comment?)
#ifdef _M_IX86 // All32 #ifdef _M_IX86 // All32
@ -226,11 +227,10 @@ const u8 *DSPEmitter::Compile(int start_addr) {
// End the block if we're at a loop end. // End the block if we're at a loop end.
if (opcode->branch || if (opcode->branch ||
(DSPAnalyzer::code_flags[addr] & DSPAnalyzer::CODE_LOOP_END) || (DSPAnalyzer::code_flags[addr-1] & DSPAnalyzer::CODE_LOOP_END) ||
(DSPAnalyzer::code_flags[addr] & DSPAnalyzer::CODE_IDLE_SKIP)) { (DSPAnalyzer::code_flags[addr] & DSPAnalyzer::CODE_IDLE_SKIP)) {
break; break;
} }
addr += opcode->size;
} }
blocks[start_addr] = (CompiledCode)entryPoint; blocks[start_addr] = (CompiledCode)entryPoint;