Core/DSPCore: Make the JIT blocks return the number of cycles executed.

The block_size seems to be not reliable, even after trying to more closely match
the interpreter by looking at the analysis for (addr+opcode->size-1) for detecting
the end of the block.

Since we need to "calculate" this number shortly before returning to
RunForCycles, it seemed logical to use the (up to now) unused return value
of the blocks.

Improves SMG2 here.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6266 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
pierre 2010-10-09 21:43:57 +00:00
parent ccb4645f24
commit 34909ecebc
2 changed files with 19 additions and 14 deletions

View File

@ -65,7 +65,7 @@ void DSPEmitter::ClearIRAM() {
// Must go out of block if exception is detected // Must go out of block if exception is detected
void DSPEmitter::checkExceptions() { void DSPEmitter::checkExceptions(u32 retval) {
/* /*
// check if there is an external interrupt // check if there is an external interrupt
if (! dsp_SR_is_flag_set(SR_EXT_INT_ENABLE)) if (! dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
@ -97,6 +97,7 @@ void DSPEmitter::checkExceptions() {
// ABI_RestoreStack(0); // ABI_RestoreStack(0);
ABI_PopAllCalleeSavedRegsAndAdjustStack(); ABI_PopAllCalleeSavedRegsAndAdjustStack();
MOV(32,R(EAX),Imm32(retval));
RET(); RET();
SetJumpTarget(skipCheck); SetJumpTarget(skipCheck);
@ -162,14 +163,15 @@ const u8 *DSPEmitter::Compile(int start_addr) {
// ABI_AlignStack(0); // ABI_AlignStack(0);
int addr = start_addr; int addr = start_addr;
checkExceptions();
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)
{ {
UDSPInstruction inst = dsp_imem_read(addr); UDSPInstruction inst = dsp_imem_read(addr);
const DSPOPCTemplate *opcode = GetOpTemplate(inst); const DSPOPCTemplate *opcode = GetOpTemplate(inst);
// Increment PC - we shouldn't need to do this for every instruction. only for branches and end of block. // Increment PC - we shouldn't need to do this for every instruction. only for branches and end of block.
// fallbacks to interpreter need this for fetching immedate values
#ifdef _M_IX86 // All32 #ifdef _M_IX86 // All32
ADD(16, M(&(g_dsp.pc)), Imm16(1)); ADD(16, M(&(g_dsp.pc)), Imm16(1));
#else #else
@ -178,9 +180,12 @@ const u8 *DSPEmitter::Compile(int start_addr) {
#endif #endif
EmitInstruction(inst); EmitInstruction(inst);
blockSize[start_addr]++;
// 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. COMMENTED OUT - this breaks Zelda TP. Bah.
//probably just misses a +opcode->size-1
// if (DSPAnalyzer::code_flags[addr] & DSPAnalyzer::CODE_LOOP_END) // if (DSPAnalyzer::code_flags[addr] & DSPAnalyzer::CODE_LOOP_END)
{ {
@ -207,14 +212,13 @@ const u8 *DSPEmitter::Compile(int start_addr) {
ABI_CallFunction((void *)&DSPInterpreter::HandleLoop); ABI_CallFunction((void *)&DSPInterpreter::HandleLoop);
// ABI_RestoreStack(0); // ABI_RestoreStack(0);
ABI_PopAllCalleeSavedRegsAndAdjustStack(); ABI_PopAllCalleeSavedRegsAndAdjustStack();
MOV(32,R(EAX),Imm32(blockSize[start_addr]));
RET(); RET();
SetJumpTarget(rLoopAddressExit); SetJumpTarget(rLoopAddressExit);
SetJumpTarget(rLoopCounterExit); SetJumpTarget(rLoopCounterExit);
} }
blockSize[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] & DSPAnalyzer::CODE_LOOP_END) ||
@ -224,10 +228,6 @@ const u8 *DSPEmitter::Compile(int start_addr) {
addr += opcode->size; addr += opcode->size;
} }
// ABI_RestoreStack(0);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
RET();
blocks[start_addr] = (CompiledCode)entryPoint; blocks[start_addr] = (CompiledCode)entryPoint;
if (blockSize[start_addr] == 0) if (blockSize[start_addr] == 0)
{ {
@ -237,6 +237,11 @@ const u8 *DSPEmitter::Compile(int start_addr) {
blockSize[start_addr] = 1; blockSize[start_addr] = 1;
} }
// ABI_RestoreStack(0);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
MOV(32,R(EAX),Imm32(blockSize[start_addr]));
RET();
return entryPoint; return entryPoint;
} }
@ -273,14 +278,14 @@ int STACKALIGN DSPEmitter::RunForCycles(int cycles)
// Execute the block if we have enough cycles // Execute the block if we have enough cycles
if (cycles > block_size) if (cycles > block_size)
{ {
blocks[block_addr](); int c = blocks[block_addr]();
if (DSPAnalyzer::code_flags[block_addr] & DSPAnalyzer::CODE_IDLE_SKIP) { if (DSPAnalyzer::code_flags[block_addr] & DSPAnalyzer::CODE_IDLE_SKIP) {
if (cycles > idle_cycles) if (cycles > idle_cycles)
cycles -= idle_cycles; cycles -= idle_cycles;
else else
cycles = 0; cycles = 0;
} else { } else {
cycles -= block_size; cycles -= c;
} }
} }
else { else {

View File

@ -25,7 +25,7 @@
#define MAX_BLOCKS 0x10000 #define MAX_BLOCKS 0x10000
typedef void (*CompiledCode)(); typedef u32 (*CompiledCode)();
class DSPEmitter : public Gen::XCodeBlock class DSPEmitter : public Gen::XCodeBlock
{ {
@ -49,7 +49,7 @@ public:
// Register helpers // Register helpers
void setCompileSR(u16 bit); void setCompileSR(u16 bit);
void clrCompileSR(u16 bit); void clrCompileSR(u16 bit);
void checkExceptions(); void checkExceptions(u32 retval);
// Memory helper functions // Memory helper functions
void increment_addr_reg(int reg); void increment_addr_reg(int reg);