All pastes #1353562 Raw Edit

Someone

public diff v1 · immutable
#1353562 ·published 2009-03-05 15:07 UTC
rendered paste body
Index: 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 ); 		} 	} }