Index: pcsx2/x86/BaseblockEx.h =================================================================== --- pcsx2/x86/BaseblockEx.h (revision 685) +++ pcsx2/x86/BaseblockEx.h (working copy) @@ -20,7 +20,6 @@ #define _BASEBLOCKEX_H_ // used to keep block information -#define BLOCKTYPE_STARTPC 4 // startpc offset #define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot // Every potential jump point in the PS2's addressable memory has a BASEBLOCK @@ -28,17 +27,14 @@ // addressable memory. Yay! struct BASEBLOCK { - u32 m_pFnptr : 28; - u32 uType : 4; - u32 startpc; + u32 m_pFnptr; + u32 startpc : 30; + u32 uType : 2; - const uptr GetFnptr() const { return ((u32)m_pFnptr)<<4; } - void SetFnptr( uptr ptr ) - { - // 16 byte alignments only, please! - jASSUME( (ptr & 0xf) == 0 ); - m_pFnptr = ptr>>4; - } + const __inline uptr GetFnptr() const { return m_pFnptr; } + void __inline SetFnptr( uptr ptr ) { m_pFnptr = ptr; } + const __inline uptr GetStartPC() const { return startpc << 2; } + void __inline SetStartPC( uptr pc ) { startpc = pc >> 2; } }; // extra block info (only valid for start of fn) @@ -60,7 +56,10 @@ // This is an asinine macro that bases indexing on sizeof(BASEBLOCK) for no reason. (air) #define GET_BLOCKTYPE(b) ((b)->Type) -#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) +// x * (sizeof(BASEBLOCK) / 4) sacrifices safety for speed compared to +// x / 4 * sizeof(BASEBLOCK) or a higher level approach. +#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4))) +#define RECLUT_SETPAGE(reclut, page, p) do { reclut[page] = (uptr)(p) - ((page) << 14) * sizeof(BASEBLOCK); } while (0) // This is needed because of the retarded GETBLOCK macro above. C_ASSERT( sizeof(BASEBLOCK) == 8 ); @@ -74,4 +73,4 @@ extern BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu); -#endif \ No newline at end of file +#endif Index: pcsx2/x86/iR3000A.cpp =================================================================== --- pcsx2/x86/iR3000A.cpp (revision 685) +++ pcsx2/x86/iR3000A.cpp (working copy) @@ -101,7 +101,7 @@ #define PSX_GETBLOCK(x) PC_GETBLOCK_(x, psxRecLUT) #define PSXREC_CLEARM(mem) { \ - if ((mem) < g_psxMaxRecMem && psxRecLUT[(mem) >> 16]) { \ + if ((mem) < g_psxMaxRecMem && (psxRecLUT[(mem) >> 16] + mem)) { \ BASEBLOCK* p = PSX_GETBLOCK(mem); \ if( *(u32*)p ) psxRecClearMem(p); \ } \ @@ -114,7 +114,7 @@ // return pex; // otherwise, use the sorted list - return GetBaseBlockEx(p->startpc, 1); + return GetBaseBlockEx(p->GetStartPC(), 1); } //////////////////////////////////////////////////// @@ -594,23 +594,23 @@ // 0x80 comes from : (Ps2MemSize::IopRam / 0x10000) * 4 for (int i=0; i<0x80; i++) { - psxRecLUT[i + 0x0000] = (uptr)&recRAM[(i & 0x1f) << 14]; - psxRecLUT[i + 0x8000] = (uptr)&recRAM[(i & 0x1f) << 14]; - psxRecLUT[i + 0xa000] = (uptr)&recRAM[(i & 0x1f) << 14]; + RECLUT_SETPAGE(psxRecLUT, i + 0x0000, &recRAM[(i & 0x1f) << 14]); + RECLUT_SETPAGE(psxRecLUT, i + 0x8000, &recRAM[(i & 0x1f) << 14]); + RECLUT_SETPAGE(psxRecLUT, i + 0xa000, &recRAM[(i & 0x1f) << 14]); } for (int i=0; i<(Ps2MemSize::Rom / 0x10000); i++) { - psxRecLUT[i + 0x1fc0] = (uptr)&recROM[i << 14]; - psxRecLUT[i + 0x9fc0] = (uptr)&recROM[i << 14]; - psxRecLUT[i + 0xbfc0] = (uptr)&recROM[i << 14]; + RECLUT_SETPAGE(psxRecLUT, i + 0x1fc0, &recROM[i << 14]); + RECLUT_SETPAGE(psxRecLUT, i + 0x9fc0, &recROM[i << 14]); + RECLUT_SETPAGE(psxRecLUT, i + 0xbfc0, &recROM[i << 14]); } for (int i=0; i<(Ps2MemSize::Rom1 / 0x10000); i++) { - psxRecLUT[i + 0x1e00] = (uptr)&recROM1[i << 14]; - psxRecLUT[i + 0x9e00] = (uptr)&recROM1[i << 14]; - psxRecLUT[i + 0xbe00] = (uptr)&recROM1[i << 14]; + RECLUT_SETPAGE(psxRecLUT, i + 0x1e00, &recROM1[i << 14]); + RECLUT_SETPAGE(psxRecLUT, i + 0x9e00, &recROM1[i << 14]); + RECLUT_SETPAGE(psxRecLUT, i + 0xbe00, &recROM1[i << 14]); } if( s_pInstCache ) @@ -644,7 +644,7 @@ pblock = PSX_GETBLOCK(psxRegs.pc); - if ( !pblock->GetFnptr() || (pblock->startpc&PSX_MEMMASK) != (psxRegs.pc&PSX_MEMMASK) ) { + if ( !pblock->GetFnptr() || (pblock->GetStartPC()&PSX_MEMMASK) != (psxRegs.pc&PSX_MEMMASK) ) { psxRecRecompile(psxRegs.pc); } @@ -692,85 +692,68 @@ static u32 g_temp; // jumped to when invalid psxpc address +// EDX contains the jump addr to modify __declspec(naked) void psxDispatcher() { - // EDX contains the current psxpc to jump to, stack contains the jump addr to modify - __asm push edx + __asm { + mov eax, dword ptr [psxRegs.pc] + mov ecx, dword ptr [psxRecLUT] + mov ebx, eax + shr eax, 16 + mov ecx, dword ptr [ecx+eax*4] + mov eax, dword ptr [ecx+ebx*2] + test eax, eax + je notcompiled + lea ebx, [eax-4] + sub ebx, edx + mov dword ptr [edx], ebx + jmp eax - //jASSUME( psxRegs.pc <= PSX_MEMMASK ); - s_pDispatchBlock = PSX_GETBLOCK( psxRegs.pc ); + align 16 +notcompiled: + mov esi, edx + lea edi, [ecx+ebx*2] + push ebx + call psxRecRecompile + add esp, 4 - if( s_pDispatchBlock->startpc != psxRegs.pc ) - psxRecRecompile(psxRegs.pc); - - __asm - { - mov eax, s_pDispatchBlock - mov eax, dword ptr [eax] - } - -#ifdef _DEBUG - __asm mov g_temp, eax - assert( g_temp ); -#endif - - // Modify the prev block's jump address, and jump to the new block: - __asm - { - shl eax,4 - pop ecx // x86Ptr[0] to mod - mov edx, eax - sub edx, ecx - sub edx, 4 - mov dword ptr [ecx], edx - + mov eax, dword ptr [edi] + lea ebx, [eax-4] + sub ebx, esi + mov dword ptr [esi], ebx jmp eax } } +// edx - baseblock->GetStartPC() +// stack - x86Ptr[0] __declspec(naked) void psxDispatcherClear() { - // EDX contains the current psxpc - __asm mov psxRegs.pc, edx - __asm push edx + __asm { + mov [psxRegs.pc], edx + mov ecx, dword ptr [psxRecLUT] + mov ebx, edx + shr edx, 16 + mov ecx, dword ptr [ecx+edx*4] + mov eax, dword ptr [ecx+ebx*2] + test eax, eax + je notcompiled + add esp, 4 + jmp eax - //jASSUME( psxRegs.pc <= PSX_MEMMASK ); - - // calc PSX_GETBLOCK - s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); - - if( s_pDispatchBlock->startpc == psxRegs.pc ) { - assert( s_pDispatchBlock->GetFnptr() != 0 ); - - // already modded the code, jump to the new place - __asm - { - pop edx - add esp, 4 // ignore stack - mov eax, s_pDispatchBlock - mov eax, dword ptr [eax] - //and eax, 0x0fffffff - shl eax,4 - jmp eax - } - } - - __asm - { + align 16 +notcompiled: + lea edi, [ecx+ebx*2] + push ebx call psxRecRecompile - add esp, 4 // pop old param - mov eax, s_pDispatchBlock - mov eax, dword ptr [eax] + add esp, 4 + mov eax, dword ptr [edi] - pop ecx // old fnptr - - //and eax, 0x0fffffff - shl eax,4 + pop ecx mov byte ptr [ecx], 0xe9 // jmp32 - mov edx, eax - sub edx, ecx - sub edx, 5 - mov dword ptr [ecx+1], edx + lea ebx, [eax-5] + sub ebx, ecx + mov dword ptr [ecx+1], ebx jmp eax } @@ -779,26 +762,25 @@ // called when jumping to variable psxpc address __declspec(naked) void psxDispatcherReg() { - //jASSUME( psxRegs.pc <= PSX_MEMMASK ); - s_pDispatchBlock = PSX_GETBLOCK( psxRegs.pc ); + __asm { + mov eax, dword ptr [psxRegs.pc] + mov ecx, dword ptr [psxRecLUT] + mov ebx, eax + shr eax, 16 + mov ecx, dword ptr [ecx+eax*4] + mov eax, dword ptr [ecx+ebx*2] + test eax, eax + je notcompiled + jmp eax - if( s_pDispatchBlock->startpc != psxRegs.pc ) - psxRecRecompile(psxRegs.pc); + align 16 +notcompiled: + lea edi, [ecx+ebx*2] + push ebx + call psxRecRecompile + add esp, 4 - __asm - { - mov eax, s_pDispatchBlock - mov eax, dword ptr [eax] - } - -#ifdef _DEBUG - __asm mov g_temp, eax - assert( g_temp ); -#endif - - __asm - { - shl eax, 4 + mov eax, dword ptr [edi] jmp eax } } @@ -869,7 +851,7 @@ void rpsxMemConstClear(u32 mem) { // NOTE! This assumes recLUT never changes its mapping - if( !psxRecLUT[mem>>16] ) + if( !(psxRecLUT[mem>>16] + mem) ) return; CMP32ItoM((uptr)PSX_GETBLOCK(mem), 0); @@ -894,20 +876,20 @@ } assert( p->GetFnptr() != 0 ); - assert( p->startpc ); + assert( p->GetStartPC() ); x86Ptr[0] = (u8*)p->GetFnptr(); // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which - MOV32ItoR(EDX, p->startpc); + MOV32ItoR(EDX, p->GetStartPC()); assert( (uptr)x86Ptr[0] <= 0xffffffff ); PUSH32I((uptr)x86Ptr[0]); JMP32((uptr)psxDispatcherClear - ( (uptr)x86Ptr[0] + 5 )); assert( x86Ptr[0] == (u8*)p->GetFnptr() + IOP_MIN_BLOCK_BYTES ); - pstart = PSX_GETBLOCK(p->startpc); + pstart = PSX_GETBLOCK(p->GetStartPC()); pexblock = PSX_GETBLOCKEX(pstart); - assert( pexblock->startpc == pstart->startpc ); + assert( pexblock->startpc == pstart->GetStartPC() ); // don't delete if last is delay lastdelay = pexblock->size; @@ -1073,8 +1055,8 @@ { BASEBLOCK* pblock = PSX_GETBLOCK(temppc); - if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) { - if( psxpc == pblock->startpc ) + if( pblock->GetFnptr() != 0 && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) { + if( psxpc == pblock->GetStartPC() ) return 0; } @@ -1088,11 +1070,11 @@ BASEBLOCK* pblock = PSX_GETBLOCK(psxpc); // need *ppblock != s_pCurBlock because of branches - if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pblock->GetFnptr() != 0 && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) { - if( !delayslot && psxpc == pblock->startpc ) { + if( !delayslot && psxpc == pblock->GetStartPC() ) { // code already in place, so jump to it and exit recomp - assert( PSX_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + assert( PSX_GETBLOCKEX(pblock)->startpc == pblock->GetStartPC() ); _psxFlushCall(FLUSH_EVERYTHING); MOV32ItoM((uptr)&psxRegs.pc, psxpc); @@ -1110,9 +1092,9 @@ } else { - if( !(delayslot && pblock->startpc == psxpc) ) { + if( !(delayslot && pblock->GetStartPC() == psxpc) ) { u8* oldX86 = x86Ptr[0]; - //__Log("clear block %x\n", pblock->startpc); + //__Log("clear block %x\n", pblock->GetStartPC()); psxRecClearMem(pblock); x86Ptr[0] = oldX86; if( delayslot ) @@ -1248,11 +1230,11 @@ if( s_pCurBlock->GetFnptr() ) { // clear if already taken - assert( s_pCurBlock->startpc < startpc ); + assert( s_pCurBlock->GetStartPC() < startpc ); psxRecClearMem(s_pCurBlock); } - if( s_pCurBlock->startpc == startpc ) { + if( s_pCurBlock->GetStartPC() == startpc ) { s_pCurBlockEx = PSX_GETBLOCKEX(s_pCurBlock); assert( s_pCurBlockEx->startpc == startpc ); } @@ -1282,7 +1264,7 @@ psxbranch = 0; - s_pCurBlock->startpc = startpc; + s_pCurBlock->SetStartPC(startpc); s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] ); s_psxBlockCycles = 0; @@ -1305,9 +1287,9 @@ while(1) { BASEBLOCK* pblock = PSX_GETBLOCK(i); - if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pblock->GetFnptr() != 0 && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) { - if( i == pblock->startpc ) { + if( i == pblock->GetStartPC() ) { // branch = 3 willbranch3 = 1; s_nEndBlock = i; @@ -1407,16 +1389,20 @@ assert( (psxpc-startpc)>>2 <= 0xffff ); s_pCurBlockEx->size = (psxpc-startpc)>>2; +// This is just wrong, right? How can setting a jump to any point in this block +// to jump to the beginning of the block possibly be right? +#ifdef ZERO_TOLERANCE for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { s_pCurBlock[i].SetFnptr( s_pCurBlock->GetFnptr() ); - s_pCurBlock[i].startpc = s_pCurBlock->startpc; + s_pCurBlock[i].SetStartPC( p_CurBlock->startpc ); } // don't overwrite if delay slot if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { - s_pCurBlock[i].SetFnptr( s_pCurBlock->GetFnptr() ); - s_pCurBlock[i].startpc = s_pCurBlock->startpc; + s_pCurBlock[i].SetFnptr(0); + s_pCurBlock[i].SetStartPC(0); } +#endif // set the block ptr AddBaseBlockEx(s_pCurBlockEx, 1); @@ -1472,14 +1458,14 @@ s_pCurBlock = PSX_GETBLOCK(psxpc); assert( ptr != NULL ); - if( s_pCurBlock->startpc != psxpc ){ + if( s_pCurBlock->GetStartPC() != psxpc ){ psxRecRecompile(psxpc); } // could have reset - if( pcurblock->startpc == startpc ) { + if( pcurblock->GetStartPC() == startpc ) { assert( pcurblock->GetFnptr() ); - assert( s_pCurBlock->startpc == nEndBlock ); + assert( s_pCurBlock->GetStartPC() == nEndBlock ); *ptr = (u32)((uptr)s_pCurBlock->GetFnptr() - ( (uptr)ptr + 4 )); } else { Index: pcsx2/x86/ix86-32/iR5900-32.cpp =================================================================== --- pcsx2/x86/ix86-32/iR5900-32.cpp (revision 685) +++ pcsx2/x86/ix86-32/iR5900-32.cpp (working copy) @@ -120,7 +120,7 @@ // return pex; // otherwise, use the sorted list - return GetBaseBlockEx(p->startpc, 0); + return GetBaseBlockEx(p->GetStartPC(), 0); } //////////////////////////////////////////////////// @@ -556,28 +556,30 @@ for ( int i = 0x0000; i < 0x0200; i++ ) { - recLUT[ i + 0x0000 ] = (uptr)&recRAM[ i << 14 ]; - recLUT[ i + 0x2000 ] = (uptr)&recRAM[ i << 14 ]; - recLUT[ i + 0x3000 ] = (uptr)&recRAM[ i << 14 ]; + RECLUT_SETPAGE(recLUT, i + 0x0000, &recRAM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0x2000, &recRAM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0x3000, &recRAM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0x8000, &recRAM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0xa000, &recRAM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0xb000, &recRAM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0xc000, &recRAM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0xd000, &recRAM[ i << 14 ]); } for ( int i = 0x0000; i < 0x0040; i++ ) { - recLUT[ i + 0x1fc0 ] = (uptr)&recROM[ i << 14 ]; - recLUT[ i + 0x9fc0 ] = (uptr)&recROM[ i << 14 ]; - recLUT[ i + 0xbfc0 ] = (uptr)&recROM[ i << 14 ]; + RECLUT_SETPAGE(recLUT, i + 0x1fc0, &recROM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0x9fc0, &recROM[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0xbfc0, &recROM[ i << 14 ]); } for ( int i = 0x0000; i < 0x0004; i++ ) { - recLUT[ i + 0x1e00 ] = (uptr)&recROM1[ i << 14 ]; - recLUT[ i + 0x9e00 ] = (uptr)&recROM1[ i << 14 ]; - recLUT[ i + 0xbe00 ] = (uptr)&recROM1[ i << 14 ]; + RECLUT_SETPAGE(recLUT, i + 0x1e00, &recROM1[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0x9e00, &recROM1[ i << 14 ]); + RECLUT_SETPAGE(recLUT, i + 0xbe00, &recROM1[ i << 14 ]); } - memcpy_fast( recLUT + 0x8000, recLUT, 0x2000 * sizeof(uptr) ); - memcpy_fast( recLUT + 0xa000, recLUT, 0x2000 * sizeof(uptr) ); - // drk||Raziel says this is useful but I'm not sure why. Something to do with forward jumps. // Anyways, it causes random crashing for some reasom, possibly because of memory // corrupition elsewhere in the recs. I can't reproduce the problem here though, @@ -649,105 +651,92 @@ // EDX contains the jump addr to modify static __naked void Dispatcher() { - // EDX contains the jump addr to modify - __asm push edx - - // calc PC_GETBLOCK - s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); - - if( s_pDispatchBlock->startpc != cpuRegs.pc ) - recRecompile(cpuRegs.pc); - - __asm - { - mov eax, s_pDispatchBlock - mov eax, dword ptr [eax] - } - -#ifdef _DEBUG - __asm mov g_EEDispatchTemp, eax - assert( g_EEDispatchTemp ); -#endif - - // Modify the prev block's jump address, and jump to the new block: __asm { - shl eax, 4 - pop ecx // x86Ptr[0] to mod - mov edx, eax - sub edx, ecx - sub edx, 4 - mov dword ptr [ecx], edx + mov eax, dword ptr [cpuRegs.pc] + mov ecx, dword ptr [recLUT] + mov ebx, eax + shr eax, 16 + mov ecx, dword ptr [ecx+eax*4] + mov eax, dword ptr [ecx+ebx*2] + test eax, eax + je notcompiled + lea ebx, [eax-4] + sub ebx, edx + mov dword ptr [edx], ebx + jmp eax + align 16 +notcompiled: + mov esi, edx + lea edi, [ecx+ebx*2] + push ebx + call recRecompile + add esp, 4 + + mov eax, dword ptr [edi] + lea ebx, [eax-4] + sub ebx, esi + mov dword ptr [esi], ebx jmp eax } } -// edx - baseblock->startpc +// edx - baseblock->GetStartPC() // stack - x86Ptr[0] static __naked void DispatcherClear() { - // EDX contains the current pc - __asm mov cpuRegs.pc, edx - __asm push edx - - // calc PC_GETBLOCK - s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); - - if( s_pDispatchBlock != NULL && s_pDispatchBlock->startpc == cpuRegs.pc ) - { - assert( s_pDispatchBlock->GetFnptr() != 0 ); - - // already modded the code, jump to the new place - __asm { - pop edx - mov eax, s_pDispatchBlock - add esp, 4 // ignore stack - mov eax, dword ptr [eax] - shl eax, 4 - jmp eax - } - } - __asm { + mov [cpuRegs.pc], edx + mov ecx, dword ptr [recLUT] + mov ebx, edx + shr edx, 16 + mov ecx, dword ptr [ecx+edx*4] + mov eax, dword ptr [ecx+ebx*2] + test eax, eax + je notcompiled + add esp, 4 + jmp eax + + align 16 +notcompiled: + lea edi, [ecx+ebx*2] + push ebx call recRecompile - add esp, 4 // pop old param - mov eax, s_pDispatchBlock - mov eax, dword ptr [eax] + add esp, 4 + mov eax, dword ptr [edi] - pop ecx // old fnptr - - shl eax, 4 + pop ecx mov byte ptr [ecx], 0xe9 // jmp32 - mov edx, eax - sub edx, ecx - sub edx, 5 - mov dword ptr [ecx+1], edx + lea ebx, [eax-5] + sub ebx, ecx + mov dword ptr [ecx+1], ebx jmp eax } } // called when jumping to variable pc address -static __naked void DispatcherReg() +static void __naked DispatcherReg() { - s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + __asm { + mov eax, dword ptr [cpuRegs.pc] + mov ecx, dword ptr [recLUT] + mov ebx, eax + shr eax, 16 + mov ecx, dword ptr [ecx+eax*4] + mov eax, dword ptr [ecx+ebx*2] + test eax, eax + je notcompiled + jmp eax - if( s_pDispatchBlock->startpc != cpuRegs.pc ) - recRecompile(cpuRegs.pc); + align 16 +notcompiled: + lea edi, [ecx+ebx*2] + push ebx + call recRecompile + add esp, 4 - __asm - { - mov eax, s_pDispatchBlock - mov eax, dword ptr [eax] - } - -#ifdef _DEBUG - __asm mov g_EEDispatchTemp, eax - assert( g_EEDispatchTemp ); -#endif - - __asm { - shl eax, 4 + mov eax, dword ptr [edi] jmp eax } } @@ -928,21 +917,21 @@ } assert( p->GetFnptr() != 0 ); - assert( p->startpc ); + assert( p->GetStartPC() ); x86Ptr[0] = (u8*)p->GetFnptr(); // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which - MOV32ItoR(EDX, p->startpc); + MOV32ItoR(EDX, p->GetStartPC()); PUSH32I((u32)x86Ptr[0]); // will be replaced by JMP32 JMP32((u32)DispatcherClear - ( (u32)x86Ptr[0] + 5 )); assert( x86Ptr[0] == (u8*)p->GetFnptr() + EE_MIN_BLOCK_BYTES ); - pstart = PC_GETBLOCK(p->startpc); + pstart = PC_GETBLOCK(p->GetStartPC()); pexblock = PC_GETBLOCKEX(pstart); - assert( pexblock->startpc == pstart->startpc ); + assert( pexblock->startpc == pstart->GetStartPC() ); - if( pexblock->startpc != pstart->startpc ) { + if( pexblock->startpc != pstart->GetStartPC() ) { // some bug with ffx after beating a big snake in sewers RemoveBaseBlockEx(pexblock, 0); pexblock->size = 0; @@ -969,7 +958,7 @@ void REC_CLEARM( u32 mem ) { - if ((mem) < maxrecmem && recLUT[(mem) >> 16]) { + if ((mem) < maxrecmem && (recLUT[(mem) >> 16] + mem)) { BASEBLOCK* p = PC_GETBLOCK(mem); if( *(u32*)p ) recClearMem(p); } @@ -1283,8 +1272,8 @@ { BASEBLOCK* pblock = PC_GETBLOCK(temppc); - if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) { - if( pc == pblock->startpc ) + if( pblock->GetFnptr() != 0 && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) { + if( pc == pblock->GetStartPC() ) return 0; } @@ -1299,11 +1288,11 @@ BASEBLOCK* pblock = PC_GETBLOCK(pc); // need *ppblock != s_pCurBlock because of branches - if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pblock->GetFnptr() != 0 && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) { - if( !delayslot && pc == pblock->startpc ) { + if( !delayslot && pc == pblock->GetStartPC() ) { // code already in place, so jump to it and exit recomp - assert( PC_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + assert( PC_GETBLOCKEX(pblock)->startpc == pblock->GetStartPC() ); iFlushCall(FLUSH_EVERYTHING); MOV32ItoM((uptr)&cpuRegs.pc, pc); @@ -1321,9 +1310,9 @@ } else { - if( !(delayslot && pblock->startpc == pc) ) { + if( !(delayslot && pblock->GetStartPC() == pc) ) { u8* oldX86 = x86Ptr[0]; - //__Log("clear block %x\n", pblock->startpc); + //__Log("clear block %x\n", pblock->GetStartPC()); recClearMem(pblock); x86Ptr[0] = oldX86; if( delayslot ) @@ -1332,8 +1321,10 @@ } } +#if 1 if( delayslot ) pblock->uType = BLOCKTYPE_DELAYSLOT; +#endif s_pCode = (int *)PSM( pc ); assert(s_pCode); @@ -1543,11 +1534,11 @@ if( s_pCurBlock->GetFnptr() ) { // clear if already taken - assert( s_pCurBlock->startpc < startpc ); + assert( s_pCurBlock->GetStartPC() < startpc ); recClearMem(s_pCurBlock); } - if( s_pCurBlock->startpc == startpc ) { + if( s_pCurBlock->GetStartPC() == startpc ) { s_pCurBlockEx = PC_GETBLOCKEX(s_pCurBlock); assert( s_pCurBlockEx->startpc == startpc ); } @@ -1575,7 +1566,7 @@ x86Align(16); recPtr = x86Ptr[0]; s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] ); - s_pCurBlock->startpc = startpc; + s_pCurBlock->SetStartPC(startpc); branch = 0; @@ -1612,9 +1603,9 @@ while(1) { BASEBLOCK* pblock = PC_GETBLOCK(i); - if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pblock->GetFnptr() != 0 && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) { - if( i == pblock->startpc ) { + if( i == pblock->GetStartPC() ) { // branch = 3 willbranch3 = 1; s_nEndBlock = i; @@ -1943,16 +1934,20 @@ assert( (pc-startpc)>>2 <= 0xffff ); s_pCurBlockEx->size = (pc-startpc)>>2; +// This is just wrong, right? How can setting a jump to any point in this block +// to jump to the beginning of the block possibly be right? +#ifdef ZERO_TOLERANCE for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { s_pCurBlock[i].SetFnptr( s_pCurBlock->GetFnptr() ); - s_pCurBlock[i].startpc = s_pCurBlock->startpc; + s_pCurBlock[i].SetStartPC( p_CurBlock->startpc ); } // don't overwrite if delay slot if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { - s_pCurBlock[i].SetFnptr( s_pCurBlock->GetFnptr() ); - s_pCurBlock[i].startpc = s_pCurBlock->startpc; + s_pCurBlock[i].SetFnptr(0); + s_pCurBlock[i].SetStartPC(0); } +#endif // set the block ptr AddBaseBlockEx(s_pCurBlockEx, 0); @@ -2022,12 +2017,12 @@ s_pCurBlock = PC_GETBLOCK(pc); assert( ptr != NULL ); - if( s_pCurBlock->startpc != pc ) + if( s_pCurBlock->GetStartPC() != pc ) recRecompile(pc); - if( pcurblock->startpc == startpc ) { + if( pcurblock->GetStartPC() == startpc ) { assert( pcurblock->GetFnptr() ); - assert( s_pCurBlock->startpc == nEndBlock ); + assert( s_pCurBlock->GetStartPC() == nEndBlock ); *ptr = s_pCurBlock->GetFnptr() - ( (u32)ptr + 4 ); } else {