mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
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:
@ -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;
|
||||||
|
Reference in New Issue
Block a user