rendered paste bodyIndex: pcsx2/x86/BaseblockEx.cpp===================================================================--- pcsx2/x86/BaseblockEx.cpp (revision 685)+++ pcsx2/x86/BaseblockEx.cpp (working copy)@@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#define _SECURE_SCL 0+ #include "PrecompiledHeader.h" #include "BaseblockEx.h" @@ -77,10 +79,15 @@ int BASEBLOCKS::Get(u32 startpc) { switch(blocks.size()) {+ case 0:+ return -1; case 1:- return 0;- case 2:- return blocks.front()->startpc < startpc;+ if (blocks.front()->startpc + blocks.front()->size*4 <= startpc)+ return -1;+ else+ return 0;+ /*case 2:+ return blocks.front()->startpc < startpc;*/ default: {@@ -94,8 +101,12 @@ else imin = imid+1; } - assert( blocks[imin]->startpc == startpc );- return imin;+ //assert( blocks[imin]->startpc == startpc );+ if (startpc < blocks[imin]->startpc ||+ startpc >= blocks[imin]->startpc + blocks[imin]->size*4)+ return -1;+ else+ return imin; } } }@@ -130,7 +141,11 @@ BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu) {- return s_vecBaseBlocksEx[cpu].blocks[s_vecBaseBlocksEx[cpu].Get(startpc)];+ int i = s_vecBaseBlocksEx[cpu].Get(startpc);+ if (i < 0)+ return 0;+ else+ return s_vecBaseBlocksEx[cpu].blocks[i]; } void RemoveBaseBlockEx(BASEBLOCKEX* pex, int cpu)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 );Index: pcsx2/x86/iR3000A.cpp===================================================================--- pcsx2/x86/iR3000A.cpp (revision 685)+++ pcsx2/x86/iR3000A.cpp (working copy)@@ -44,7 +44,7 @@ u32 g_psxMaxRecMem = 0; u32 s_psxrecblocks[] = {0}; -uptr *psxRecLUT;+uptr psxRecLUT[0x10000]; #define PSX_NUMBLOCKS (1<<12) #define MAPBASE 0x48000000@@ -92,6 +92,8 @@ extern void (*rpsxBSC[64])(); void rpsxpropBSC(EEINST* prev, EEINST* pinst); +static void psxInitRecLUT(BASEBLOCK* base, int count);+ #ifdef _DEBUG u32 psxdump = 0; #else@@ -101,9 +103,8 @@ #define PSX_GETBLOCK(x) PC_GETBLOCK_(x, psxRecLUT) #define PSXREC_CLEARM(mem) { \- if ((mem) < g_psxMaxRecMem && psxRecLUT[(mem) >> 16]) { \- BASEBLOCK* p = PSX_GETBLOCK(mem); \- if( *(u32*)p ) psxRecClearMem(p); \+ if ((mem) < g_psxMaxRecMem && (psxRecLUT[(mem) >> 16] + mem)) { \+ psxRecClearMem(mem); \ } \ } \ @@ -114,7 +115,7 @@ // return pex; // otherwise, use the sorted list- return GetBaseBlockEx(p->startpc, 1);+ return GetBaseBlockEx(p->GetStartPC(), 1); } ////////////////////////////////////////////////////@@ -546,9 +547,6 @@ if( recMem == NULL ) throw Exception::OutOfMemory( "R3000a Init > failed to allocate memory for the recompiler." ); - if( psxRecLUT == NULL )- psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr));- // Goal: Allocate BASEBLOCKs for every possible branch target in IOP memory. // Any 4-byte aligned address makes a valid branch target as per MIPS design (all instructions are // always 4 bytes long).@@ -586,31 +584,33 @@ DbgCon::Status( "iR3000A > Resetting recompiler memory and structures!" ); - memzero_ptr<0x010000 * sizeof(uptr)>( psxRecLUT );+ memzero_ptr<sizeof(psxRecLUT)>( psxRecLUT ); memset_8<0xcd,RECMEM_SIZE>( recMem );- memzero_ptr<m_recBlockAllocSize>( m_recBlockAlloc );+ memzero_ptr<PSX_NUMBLOCKS*sizeof(BASEBLOCKEX)>(recBlocks);+ psxInitRecLUT((BASEBLOCK*)m_recBlockAlloc,+ (((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4))); // We're only mapping 20 pages here in 4 places. // 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 )@@ -630,7 +630,6 @@ SafeSysMunmap(recMem, RECMEM_SIZE); safe_aligned_free( m_recBlockAlloc ); - safe_free(psxRecLUT); safe_free( s_pInstCache ); s_nInstCacheSize = 0; }@@ -644,7 +643,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); } @@ -691,86 +690,82 @@ static u32 g_temp; +// The address for all clear blocks, recompile the current pc then run+__declspec(naked) void psxJITCompile()+{+ __asm {+ mov esi, dword ptr [psxRegs.pc]+ push esi+ call psxRecRecompile+ add esp, 4+ mov ebx, esi+ shr esi, 16+ mov ecx, dword ptr [psxRecLUT+esi*4]+ jmp dword ptr [ecx+ebx*2]+ }+}+ // 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 ebx, eax+ shr eax, 16+ mov ecx, dword ptr [psxRecLUT+eax*4]+ mov eax, dword ptr [ecx+ebx*2]+ cmp eax, offset psxJITCompile+ 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 ebx, edx+ shr edx, 16+ mov ecx, dword ptr [psxRecLUT+edx*4]+ mov eax, dword ptr [ecx+ebx*2]+ cmp eax, psxJITCompile+ 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,30 +774,24 @@ // called when jumping to variable psxpc address __declspec(naked) void psxDispatcherReg() {- //jASSUME( psxRegs.pc <= PSX_MEMMASK );- s_pDispatchBlock = PSX_GETBLOCK( psxRegs.pc );-- if( s_pDispatchBlock->startpc != psxRegs.pc )- psxRecRecompile(psxRegs.pc);-- __asm- {- mov eax, s_pDispatchBlock- mov eax, dword ptr [eax]+ __asm {+ mov eax, dword ptr [psxRegs.pc]+ mov ebx, eax+ shr eax, 16+ mov ecx, dword ptr [psxRecLUT+eax*4]+ jmp dword ptr [ecx+ebx*2] }+}+#endif // _MSC_VER -#ifdef _DEBUG- __asm mov g_temp, eax- assert( g_temp );-#endif-- __asm- {- shl eax, 4- jmp eax+static void psxInitRecLUT(BASEBLOCK* base, int count)+{+ for (int i = 0; i < count; i++) {+ base[i].SetFnptr((uptr)psxJITCompile);+ base[i].SetStartPC(0);+ base[i].uType = 0; } }-#endif // _MSC_VER static void recExecute() {@@ -869,57 +858,45 @@ 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); j8Ptr[6] = JE8(0); - _callFunctionArg1((uptr)psxRecClearMem, MEM_CONSTTAG, (uptr)PSX_GETBLOCK(mem));+ _callFunctionArg1((uptr)psxRecClearMem, MEM_CONSTTAG, mem); x86SetJ8(j8Ptr[6]); } -void psxRecClearMem(BASEBLOCK* p)+void psxRecClearMem(u32 pc) { BASEBLOCKEX* pexblock; BASEBLOCK* pstart;- int lastdelay;- - assert( p != NULL );+ BASEBLOCK* p;+ + p= PSX_GETBLOCK(pc);+ pc = p->GetStartPC();+ if (!pc)+ return;+ pexblock = GetBaseBlockEx(pc, 1);+ if (!pexblock)+ return;+ pstart = PSX_GETBLOCK(pexblock->startpc); - if( p->uType & BLOCKTYPE_DELAYSLOT ) {- psxRecClearMem(p-1);- if( p->GetFnptr() == 0 )- return;- }- - assert( p->GetFnptr() != 0 );- assert( p->startpc );+ for (int i = 0; i < pexblock->size; i++) {+ x86Ptr[0] = (u8*)pstart[i].GetFnptr();+ if (x86Ptr[0] == (u8*)psxJITCompile)+ continue; - 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);- 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);- pexblock = PSX_GETBLOCKEX(pstart);- assert( pexblock->startpc == pstart->startpc );-- // don't delete if last is delay- lastdelay = pexblock->size;- if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) {- assert( pstart[pexblock->size-1].GetFnptr() != pstart->GetFnptr() );- if( pstart[pexblock->size-1].GetFnptr() != 0 ) {- pstart[pexblock->size-1].uType = 0;- --lastdelay;- }+ // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which+ MOV32ItoR(EDX, pexblock->startpc + i*4);+ assert( (uptr)x86Ptr[0] <= 0xffffffff );+ PUSH32I((uptr)x86Ptr[0]); // will be replaced by JMP32+ JMP32((uptr)psxDispatcherClear - ( (uptr)x86Ptr[0] + 5 ));+ assert( x86Ptr[0] == (u8*)p->GetFnptr() + IOP_MIN_BLOCK_BYTES ); } - memset(pstart, 0, lastdelay*sizeof(BASEBLOCK));+ psxInitRecLUT(pstart, pexblock->size); RemoveBaseBlockEx(pexblock, 1); pexblock->size = 0;@@ -1073,8 +1050,8 @@ { BASEBLOCK* pblock = PSX_GETBLOCK(temppc); - if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) {- if( psxpc == pblock->startpc )+ if( pblock->GetFnptr() != (uptr)psxJITCompile && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) {+ if( psxpc == pblock->GetStartPC() ) return 0; } @@ -1088,11 +1065,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() != (uptr)psxJITCompile && 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,10 +1087,10 @@ } else { - if( !(delayslot && pblock->startpc == psxpc) ) {+ if( !(delayslot && pblock->GetStartPC() == psxpc) ) { u8* oldX86 = x86Ptr[0];- //__Log("clear block %x\n", pblock->startpc);- psxRecClearMem(pblock);+ //__Log("clear block %x\n", pblock->GetStartPC());+ psxRecClearMem(psxpc); x86Ptr[0] = oldX86; if( delayslot ) SysPrintf("delay slot %x\n", psxpc);@@ -1246,13 +1223,13 @@ s_pCurBlock = PSX_GETBLOCK(startpc); - if( s_pCurBlock->GetFnptr() ) {+ if( s_pCurBlock->GetFnptr() != (uptr)psxJITCompile ) { // clear if already taken- assert( s_pCurBlock->startpc < startpc );- psxRecClearMem(s_pCurBlock); + assert( s_pCurBlock->GetStartPC() < startpc );+ psxRecClearMem(startpc); } - if( s_pCurBlock->startpc == startpc ) {+ if( s_pCurBlock->GetStartPC() == startpc ) { s_pCurBlockEx = PSX_GETBLOCKEX(s_pCurBlock); assert( s_pCurBlockEx->startpc == startpc ); }@@ -1282,7 +1259,7 @@ psxbranch = 0; - s_pCurBlock->startpc = startpc;+ s_pCurBlock->SetStartPC(startpc); s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] ); s_psxBlockCycles = 0; @@ -1305,9 +1282,9 @@ while(1) { BASEBLOCK* pblock = PSX_GETBLOCK(i);- if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) {+ if( pblock->GetFnptr() != (uptr)psxJITCompile && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) { - if( i == pblock->startpc ) {+ if( i == pblock->GetStartPC() ) { // branch = 3 willbranch3 = 1; s_nEndBlock = i;@@ -1407,16 +1384,25 @@ assert( (psxpc-startpc)>>2 <= 0xffff ); s_pCurBlockEx->size = (psxpc-startpc)>>2; + for(i = 1; i <= (u32)s_pCurBlockEx->size-1; ++i) {+ if (!s_pCurBlock[i].GetStartPC())+ s_pCurBlock[i].SetStartPC( startpc );+ }++// 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,23 +1458,23 @@ 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 ) {- assert( pcurblock->GetFnptr() );- assert( s_pCurBlock->startpc == nEndBlock );+ if( pcurblock->GetStartPC() == startpc ) {+ assert( pcurblock->GetFnptr() != (uptr)psxJITCompile );+ assert( s_pCurBlock->GetStartPC() == nEndBlock ); *ptr = (u32)((uptr)s_pCurBlock->GetFnptr() - ( (uptr)ptr + 4 )); } else { psxRecRecompile(startpc);- assert( pcurblock->GetFnptr() != 0 );+ assert( pcurblock->GetFnptr() != (uptr)psxJITCompile ); } } else- assert( s_pCurBlock->GetFnptr() != 0 );+ assert( s_pCurBlock->GetFnptr() != (uptr)psxJITCompile ); } R3000Acpu psxRec = {Index: pcsx2/x86/iR3000A.h===================================================================--- pcsx2/x86/iR3000A.h (revision 685)+++ pcsx2/x86/iR3000A.h (working copy)@@ -38,7 +38,7 @@ #define PSX_HI XMMGPR_HI #define PSX_LO XMMGPR_LO -extern uptr *psxRecLUT;+extern uptr psxRecLUT[]; u8 _psxLoadWritesRs(u32 tempcode); u8 _psxIsLoadStore(u32 tempcode);@@ -70,7 +70,7 @@ void psxSetBranchReg(u32 reg); void psxSetBranchImm( u32 imm ); void psxRecompileNextInstruction(int delayslot);-void psxRecClearMem(BASEBLOCK* p);+void psxRecClearMem(u32 p); //////////////////////////////////////////////////////////////////// // IOP Constant Propagation Defines, Vars, and API - From here down!Index: pcsx2/x86/iR5900.h===================================================================--- pcsx2/x86/iR5900.h (revision 685)+++ pcsx2/x86/iR5900.h (working copy)@@ -51,7 +51,7 @@ extern u32 pc; extern int branch;-extern uptr* recLUT;+extern uptr recLUT[]; extern u32 maxrecmem; extern u32 pc; // recompiler pc (also used by the SuperVU! .. why? (air))@@ -92,7 +92,7 @@ // Used to clear recompiled code blocks during memory/dma write operations.-void recClearMem(BASEBLOCK* p);+void recClearMem(u32 pc); void REC_CLEARM( u32 mem ); // used when processing branchesIndex: 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)@@ -52,7 +52,7 @@ bool g_EEFreezeRegs = false; u32 maxrecmem = 0;-uptr *recLUT = NULL;+uptr recLUT[0x10000]; u32 s_nBlockCycles = 0; // cycles of current block recompiling //u8* dyna_block_discard_recmem=0;@@ -112,15 +112,16 @@ #endif static void iBranchTest(u32 newpc, bool noDispatch=false);+static void InitRecLUT(BASEBLOCK* base, int count); -BASEBLOCKEX* PC_GETBLOCKEX(BASEBLOCK* p)+BASEBLOCKEX* PC_GETBLOCKEX(u32 pc) { // BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); // if( pex >= recBlocks && pex < recBlocks+EE_NUMBLOCKS ) // return pex; // otherwise, use the sorted list- return GetBaseBlockEx(p->startpc, 0);+ return GetBaseBlockEx(pc, 0); } ////////////////////////////////////////////////////@@ -480,9 +481,6 @@ if ( !( cpucaps.hasStreamingSIMD2Extensions ) ) throw Exception::HardwareDeficiency( _( "Processor doesn't support SSE2" ) ); - if( recLUT == NULL )- recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 );- if( recMem == NULL ) { // Note: the VUrec depends on being able to grab an allocatione below the 0x10000000 line,@@ -539,7 +537,11 @@ memset_8<0xcd, REC_CACHEMEM>(recMem); memzero_ptr<m_recBlockAllocSize>( m_recBlockAlloc );+ memzero_ptr<EE_NUMBLOCKS*sizeof(BASEBLOCKEX)>(recBlocks);+ InitRecLUT((BASEBLOCK*)m_recBlockAlloc,+ (((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4))); + if( s_pInstCache ) memset( s_pInstCache, 0, sizeof(EEINST)*s_nInstCacheSize ); @@ -552,32 +554,34 @@ __asm__("emms"); #endif - memzero_ptr<0x010000 * sizeof(uptr)>( recLUT );+ memzero_ptr<sizeof recLUT>( recLUT ); 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,@@ -604,7 +608,6 @@ ResetBaseBlockEx(0); SafeSysMunmap( recMem, REC_CACHEMEM );- safe_aligned_free( recLUT ); safe_aligned_free( m_recBlockAlloc ); recRAM = recROM = recROM1 = NULL; recBlocks = NULL;@@ -645,110 +648,96 @@ #ifdef _MSC_VER +// The address for all clear blocks, recompile the current pc then run+__declspec(naked) void JITCompile()+{+ __asm {+ mov esi, dword ptr [cpuRegs.pc]+ push esi+ call recRecompile+ add esp, 4+ mov ebx, esi+ shr esi, 16+ mov ecx, dword ptr [recLUT+esi*4]+ jmp dword ptr [ecx+ebx*2]+ }+}+ // jumped to when invalid pc address // 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 ebx, eax+ shr eax, 16+ mov ecx, dword ptr [recLUT+eax*4]+ mov eax, dword ptr [ecx+ebx*2]+ cmp eax, offset JITCompile+ 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 ebx, edx+ shr edx, 16+ mov ecx, dword ptr [recLUT+edx*4]+ mov eax, dword ptr [ecx+ebx*2]+ cmp eax, offset JITCompile+ 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);-- 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- __asm {- shl eax, 4- jmp eax+ mov eax, dword ptr [cpuRegs.pc]+ mov ebx, eax+ shr eax, 16+ mov ecx, dword ptr [recLUT+eax*4]+ jmp dword ptr [ecx+ebx*2] } } @@ -852,6 +841,15 @@ } #endif +static void InitRecLUT(BASEBLOCK* base, int count)+{+ for (int i = 0; i < count; i++) {+ base[i].SetFnptr((uptr)JITCompile);+ base[i].SetStartPC(0);+ base[i].uType = 0;+ }+}+ namespace R5900 { namespace Dynarec { namespace OpcodeImpl {@@ -899,11 +897,20 @@ static const int EE_MIN_BLOCK_BYTES = 15; -void recClearMem(BASEBLOCK* p)+void recClearMem(u32 pc) { BASEBLOCKEX* pexblock; BASEBLOCK* pstart;- int lastdelay;+ BASEBLOCK* p;+ + p= PC_GETBLOCK(pc);+ pc = p->GetStartPC();+ if (!pc)+ return;+ pexblock = PC_GETBLOCKEX(pc);+ if (!pexblock)+ return;+ pstart = PC_GETBLOCK(pexblock->startpc); // necessary since recompiler doesn't call femms/emms #ifdef __INTEL_COMPILER@@ -918,49 +925,20 @@ __asm__("emms"); #endif #endif- - assert( p != NULL ); - if( p->uType & BLOCKTYPE_DELAYSLOT ) {- recClearMem(p-1);- if( p->GetFnptr() == 0 )- return;- }+ for (int i = 0; i < pexblock->size; i++) {+ x86Ptr[0] = (u8*)pstart[i].GetFnptr();+ if (x86Ptr[0] == (u8*)JITCompile)+ continue; - assert( p->GetFnptr() != 0 );- assert( p->startpc );-- 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);- 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);- pexblock = PC_GETBLOCKEX(pstart);- assert( pexblock->startpc == pstart->startpc );-- if( pexblock->startpc != pstart->startpc ) {- // some bug with ffx after beating a big snake in sewers- RemoveBaseBlockEx(pexblock, 0);- pexblock->size = 0;- pexblock->startpc = 0;- return;- }-- // don't delete if last is delay- lastdelay = pexblock->size;- if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) {- assert( pstart[pexblock->size-1].GetFnptr() != pstart->GetFnptr() );- if( pstart[pexblock->size-1].GetFnptr() != 0 ) {- pstart[pexblock->size-1].uType = 0;- --lastdelay;- }+ // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which+ MOV32ItoR(EDX, pexblock->startpc + i*4);+ 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 ); } - memset(pstart, 0, lastdelay*sizeof(BASEBLOCK));+ InitRecLUT(pstart, pexblock->size); RemoveBaseBlockEx(pexblock, 0); pexblock->size = 0;@@ -969,9 +947,8 @@ void REC_CLEARM( u32 mem ) {- if ((mem) < maxrecmem && recLUT[(mem) >> 16]) {- BASEBLOCK* p = PC_GETBLOCK(mem);- if( *(u32*)p ) recClearMem(p);+ if ((mem) < maxrecmem && (recLUT[(mem) >> 16] + mem)) {+ recClearMem(mem); } } @@ -1283,8 +1260,8 @@ { BASEBLOCK* pblock = PC_GETBLOCK(temppc); - if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) {- if( pc == pblock->startpc )+ if( pblock->GetFnptr() != (uptr)JITCompile && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) {+ if( pc == pblock->GetStartPC() ) return 0; } @@ -1299,11 +1276,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() != (uptr)JITCompile && 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(pc)->startpc == pblock->GetStartPC() ); iFlushCall(FLUSH_EVERYTHING); MOV32ItoM((uptr)&cpuRegs.pc, pc);@@ -1321,10 +1298,10 @@ } else { - if( !(delayslot && pblock->startpc == pc) ) {+ if( !(delayslot && pblock->GetStartPC() == pc) ) { u8* oldX86 = x86Ptr[0];- //__Log("clear block %x\n", pblock->startpc);- recClearMem(pblock);+ //__Log("clear block %x\n", pblock->GetStartPC());+ recClearMem(pc); x86Ptr[0] = oldX86; if( delayslot ) Console::Notice("delay slot %x", params pc);@@ -1332,8 +1309,10 @@ } } +#if 1 if( delayslot ) pblock->uType = BLOCKTYPE_DELAYSLOT;+#endif s_pCode = (int *)PSM( pc ); assert(s_pCode);@@ -1541,14 +1520,14 @@ s_pCurBlock = PC_GETBLOCK(startpc); - if( s_pCurBlock->GetFnptr() ) {+ if( s_pCurBlock->GetFnptr() != (uptr)JITCompile ) { // clear if already taken- assert( s_pCurBlock->startpc < startpc );- recClearMem(s_pCurBlock); + assert( s_pCurBlock->GetStartPC() < startpc );+ recClearMem(startpc); } - if( s_pCurBlock->startpc == startpc ) {- s_pCurBlockEx = PC_GETBLOCKEX(s_pCurBlock);+ if( s_pCurBlock->GetStartPC() == startpc ) {+ s_pCurBlockEx = PC_GETBLOCKEX(startpc); assert( s_pCurBlockEx->startpc == startpc ); } else {@@ -1575,7 +1554,7 @@ x86Align(16); recPtr = x86Ptr[0]; s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] );- s_pCurBlock->startpc = startpc;+ s_pCurBlock->SetStartPC(startpc); branch = 0; @@ -1612,9 +1591,9 @@ while(1) { BASEBLOCK* pblock = PC_GETBLOCK(i);- if( pblock->GetFnptr() != 0 && pblock->startpc != s_pCurBlock->startpc ) {+ if( pblock->GetFnptr() != (uptr)JITCompile && pblock->GetStartPC() != s_pCurBlock->GetStartPC() ) { - if( i == pblock->startpc ) {+ if( i == pblock->GetStartPC() ) { // branch = 3 willbranch3 = 1; s_nEndBlock = i;@@ -1943,16 +1922,26 @@ assert( (pc-startpc)>>2 <= 0xffff ); s_pCurBlockEx->size = (pc-startpc)>>2; + for(i = 1; i <= (u32)s_pCurBlockEx->size-1; ++i) {+ if (!s_pCurBlock[i].GetStartPC())+ s_pCurBlock[i].SetStartPC( startpc );+ }+++// 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);@@ -2021,18 +2010,18 @@ u32 nEndBlock = s_nEndBlock; s_pCurBlock = PC_GETBLOCK(pc); assert( ptr != NULL );- - if( s_pCurBlock->startpc != pc ) ++ if( s_pCurBlock->GetStartPC() != pc ) recRecompile(pc); - if( pcurblock->startpc == startpc ) {- assert( pcurblock->GetFnptr() );- assert( s_pCurBlock->startpc == nEndBlock );+ if( pcurblock->GetStartPC() == startpc ) {+ assert( pcurblock->GetFnptr() != (uptr)JITCompile );+ assert( s_pCurBlock->GetStartPC() == nEndBlock ); *ptr = s_pCurBlock->GetFnptr() - ( (u32)ptr + 4 ); } else { recRecompile(startpc);- assert( pcurblock->GetFnptr() != 0 );+ assert( pcurblock->GetFnptr() != (uptr)JITCompile ); } } }