All pastes #1354301 Raw Edit

Mine

public diff v1 · immutable
#1354301 ·published 2009-03-06 10:16 UTC
rendered paste body
Index: pcsx2/x86/BaseblockEx.cpp===================================================================--- pcsx2/x86/BaseblockEx.cpp	(revision 698)+++ pcsx2/x86/BaseblockEx.cpp	(working copy)@@ -19,143 +19,53 @@ #include "PrecompiledHeader.h" #include "BaseblockEx.h" -#include <vector>--using namespace std;--struct BASEBLOCKS+BASEBLOCKEX* BaseBlocks::New(u32 startpc) {-	// 0 - ee, 1 - iop-	void Add(BASEBLOCKEX*);-	void Remove(BASEBLOCKEX*);-	int Get(u32 startpc);-	void Reset();+	if (blocks.size() == size)+		return 0; -	BASEBLOCKEX** GetAll(int* pnum);+	BASEBLOCKEX newblock;+	std::vector<BASEBLOCKEX>::iterator iter;+	memset(&newblock, 0, sizeof newblock);+	newblock.startpc = startpc; -	vector<BASEBLOCKEX*> blocks;-};+	int imin = 0, imax = blocks.size(), imid; -void BASEBLOCKS::Add(BASEBLOCKEX* pex)-{-	assert( pex != NULL );+	while (imin < imax) {+		imid = (imin+imax)>>1; -	switch(blocks.size()) {-		case 0:-			blocks.push_back(pex);-			return;-		case 1:-			assert( blocks.front()->startpc != pex->startpc );--			if( blocks.front()->startpc < pex->startpc ) {-				blocks.push_back(pex);-			}-			else blocks.insert(blocks.begin(), pex);--			return;--		default:-		{-			int imin = 0, imax = blocks.size(), imid;--			while(imin < imax) {-				imid = (imin+imax)>>1;--				if( blocks[imid]->startpc > pex->startpc ) imax = imid;-				else imin = imid+1;-			}--			assert( imin == blocks.size() || blocks[imin]->startpc > pex->startpc );-			blocks.insert(blocks.begin()+imin, pex);--			return;-		}+		if (blocks[imid].startpc > startpc)+			imax = imid;+		else+			imin = imid + 1; 	}++	assert(imin == blocks.size() || blocks[imin].startpc > startpc);+	iter = blocks.insert(blocks.begin() + imin, newblock);+	return &*iter; } -int BASEBLOCKS::Get(u32 startpc)+int BaseBlocks::Index(u32 startpc) const {-	switch(blocks.size()) {-		case 0:-			return -1;-		case 1:-			if (blocks.front()->startpc + blocks.front()->size*4 <= startpc)-				return -1;-			else-				return 0;-		/*case 2:-			return blocks.front()->startpc < startpc;*/+	if (0 == blocks.size())+		return -1; -		default:-		{-			int imin = 0, imax = blocks.size()-1, imid;+	int imin = 0, imax = blocks.size() - 1, imid; -			while(imin < imax) {-				imid = (imin+imax)>>1;+	while(imin != imax) {+		imid = (imin+imax+1)>>1; -				if( blocks[imid]->startpc > startpc ) imax = imid;-				else if( blocks[imid]->startpc == startpc ) return imid;-				else imin = imid+1;-			}--			//assert( blocks[imin]->startpc == startpc );-			if (startpc < blocks[imin]->startpc ||-				startpc >= blocks[imin]->startpc + blocks[imin]->size*4)-				return -1;-			else-				return imin;-		}+		if (blocks[imid].startpc > startpc)+			imax = imid - 1;+		else if (blocks[imid].startpc < startpc)+			imin = imid;+		else+			return imid; 	}-} -void BASEBLOCKS::Remove(BASEBLOCKEX* pex)-{-	assert( pex != NULL );-	int i = Get(pex->startpc);-	assert( blocks[i] == pex ); -	blocks.erase(blocks.begin()+i);-}--void BASEBLOCKS::Reset()-{-	blocks.resize(0);-	blocks.reserve(512);-}--BASEBLOCKEX** BASEBLOCKS::GetAll(int* pnum)-{-	assert( pnum != NULL );-	*pnum = blocks.size();-	return &blocks[0];-}--static BASEBLOCKS s_vecBaseBlocksEx[2];--void AddBaseBlockEx(BASEBLOCKEX* pex, int cpu)-{-	s_vecBaseBlocksEx[cpu].Add(pex);-}--BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu)-{-	int i = s_vecBaseBlocksEx[cpu].Get(startpc);-	if (i < 0)-		return 0;+	if (startpc < blocks[imin].startpc ||+		startpc >= blocks[imin].startpc + blocks[imin].size*4)+		return -1; 	else-		return s_vecBaseBlocksEx[cpu].blocks[i];-}--void RemoveBaseBlockEx(BASEBLOCKEX* pex, int cpu)-{-	s_vecBaseBlocksEx[cpu].Remove(pex);-}--void ResetBaseBlockEx(int cpu)-{-	s_vecBaseBlocksEx[cpu].Reset();-}--BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu)-{-	return s_vecBaseBlocksEx[cpu].GetAll(pnum);-}+		return imin;+}\ No newline at end of fileIndex: pcsx2/x86/BaseblockEx.h===================================================================--- pcsx2/x86/BaseblockEx.h	(revision 698)+++ pcsx2/x86/BaseblockEx.h	(working copy)@@ -16,9 +16,11 @@  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA  */ -#ifndef _BASEBLOCKEX_H_-#define _BASEBLOCKEX_H_+#pragma once +#include "PrecompiledHeader.h"+#include <vector>+ // used to keep block information #define BLOCKTYPE_DELAYSLOT	1		// if bit set, delay slot @@ -51,28 +53,58 @@  }; -// This is an asinine macro that bases indexing on sizeof(BASEBLOCK) for no reason. (air)+class BaseBlocks+{+private:+	std::vector<BASEBLOCKEX> blocks;+	unsigned long size;++public:+	BaseBlocks(unsigned long max) :+		size(max),+		blocks(0)+	{+		blocks.reserve(size);+	}++	BASEBLOCKEX* New(u32 startpc);+	int Index (u32 startpc) const;++	inline BASEBLOCKEX* operator[](int idx)+	{+		if (idx < 0 || idx >= (int)blocks.size())+			return 0;+		return &blocks[idx];+	}++	inline BASEBLOCKEX* Get(u32 startpc)+	{+		return (*this)[Index(startpc)];+	}++	inline void Remove(int idx)+	{+		blocks.erase(blocks.begin() + idx);+	}++	inline void Reset()+	{+		blocks.clear();+	}+};+ #define GET_BLOCKTYPE(b) ((b)->Type)-// 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))) -static void recLUT_SetPage( uptr reclut[0x10000], uint page, void* mapping )+static void recLUT_SetPage(uptr reclut[0x10000], uptr hwlut[0x10000],+						   BASEBLOCK *mapbase, uint pagebase, uint pageidx, uint mappage) {+	uint page = pagebase + pageidx;+ 	jASSUME( page < 0x10000 );-	reclut[page] = ((uptr)mapping) - ((page << 14) * sizeof(BASEBLOCK));+	reclut[page] = (uptr)&mapbase[(mappage - page) << 14];+	if (hwlut)+		hwlut[page] = 0u - (pagebase << 16); } -// This is needed because of the retarded GETBLOCK macro above.-C_ASSERT( sizeof(BASEBLOCK) == 8 );--// 0 - ee, 1 - iop-extern void AddBaseBlockEx(BASEBLOCKEX*, int cpu);-extern void RemoveBaseBlockEx(BASEBLOCKEX*, int cpu);-extern BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu);-extern void ResetBaseBlockEx(int cpu);--extern BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu);---#endif\ No newline at end of file+C_ASSERT( sizeof(BASEBLOCK) == 8 );\ No newline at end of fileIndex: pcsx2/x86/iR3000A.cpp===================================================================--- pcsx2/x86/iR3000A.cpp	(revision 698)+++ pcsx2/x86/iR3000A.cpp	(working copy)@@ -45,7 +45,10 @@ u32 s_psxrecblocks[] = {0};  uptr psxRecLUT[0x10000];+uptr psxhwLUT[0x10000]; +#define HWADDR(mem) (psxhwLUT[mem >> 16] + (mem))+ #define PSX_NUMBLOCKS (1<<12) #define MAPBASE			0x48000000 #define RECMEM_SIZE		(8*1024*1024)@@ -59,7 +62,7 @@ static BASEBLOCK *recRAM = NULL;	// and the ptr to the blocks here static BASEBLOCK *recROM = NULL;	// and here static BASEBLOCK *recROM1 = NULL;	// also here-static BASEBLOCKEX *recBlocks = NULL;+static BaseBlocks recBlocks(PSX_NUMBLOCKS); static u8 *recPtr = NULL; u32 psxpc;			// recompiler psxpc int psxbranch;		// set for branch@@ -71,10 +74,8 @@ static BASEBLOCK* s_pCurBlock = NULL; static BASEBLOCKEX* s_pCurBlockEx = NULL; -static u32 s_nEndBlock = 0; // what psxpc the current block ends	+static u32 s_nEndBlock = 0; // what psxpc the current block ends -static u32 s_nNextBlock = 0; // next free block in recBlocks- static u32 s_ConstGPRreg; static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; static EEINST* s_psaveInstInfo = NULL;@@ -88,7 +89,7 @@ extern void (*rpsxBSC[64])(); void rpsxpropBSC(EEINST* prev, EEINST* pinst); -static void iopInitRecLUT(BASEBLOCK* base, int count);+static void iopClearRecLUT(BASEBLOCK* base, int count);  #ifdef _DEBUG u32 psxdump = 0;@@ -98,22 +99,10 @@  #define PSX_GETBLOCK(x) PC_GETBLOCK_(x, psxRecLUT) -#define PSXREC_CLEARM(mem) { \-	if ((mem) < g_psxMaxRecMem && (psxRecLUT[(mem) >> 16] + mem)) { \-		psxRecClearMem(mem); \-	} \-} \+#define PSXREC_CLEARM(mem) \+	(((mem) < g_psxMaxRecMem && (psxRecLUT[(mem) >> 16] + (mem))) ? \+		psxRecClearMem(mem) : 4) -BASEBLOCKEX* PSX_GETBLOCKEX(BASEBLOCK* p)-{-//	BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1);-//	if( pex >= recBlocks && pex < recBlocks+PSX_NUMBLOCKS )-//		return pex;--	// otherwise, use the sorted list-	return GetBaseBlockEx(p->GetStartPC(), 1);-}- //////////////////////////////////////////////////// #ifdef _DEBUG using namespace R3000A;@@ -528,8 +517,7 @@ static u8* m_recBlockAlloc = NULL;  static const uint m_recBlockAllocSize = -		(((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK))-	+	(PSX_NUMBLOCKS*sizeof(BASEBLOCKEX));	// recBlocks+	(((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK));  static void recAlloc() {@@ -557,7 +545,6 @@ 	recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::IopRam / 4) * sizeof(BASEBLOCK); 	recROM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom / 4) * sizeof(BASEBLOCK); 	recROM1 = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom1 / 4) * sizeof(BASEBLOCK);-	recBlocks = (BASEBLOCKEX*)curpos;	// curpos += sizeof(BASEBLOCKEX)*EE_NUMBLOCKS;  	if( s_pInstCache == NULL ) 	{@@ -574,45 +561,45 @@ void recResetIOP() { 	// calling recResetIOP without first calling recInit is bad mojo.-	jASSUME( psxRecLUT != NULL ); 	jASSUME( recMem != NULL ); 	jASSUME( m_recBlockAlloc != NULL );  	DevCon::Status( "iR3000A Resetting recompiler memory and structures" ); -	memzero_ptr<sizeof(psxRecLUT)>( psxRecLUT ); 	memset_8<0xcd,RECMEM_SIZE>( recMem );-	memzero_ptr<PSX_NUMBLOCKS*sizeof(BASEBLOCKEX)>(recBlocks);-	iopInitRecLUT((BASEBLOCK*)m_recBlockAlloc,+	iopClearRecLUT((BASEBLOCK*)m_recBlockAlloc, 		(((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4))); +	for (int i = 0; i < 0x10000; i++)+		recLUT_SetPage(psxRecLUT, 0, 0, 0, i, 0);+ 	// We're only mapping 20 pages here in 4 places. 	// 0x80 comes from : (Ps2MemSize::IopRam / 0x10000) * 4 	for (int i=0; i<0x80; i++) 	{-		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]);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0x0000, i, i & 0x1f);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0x8000, i, i & 0x1f);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0xa000, i, i & 0x1f); 	} -	for (int i=0; i<(Ps2MemSize::Rom / 0x10000); i++)+	for (int i=0x1fc0; i<0x2000; i++) 	{-		recLUT_SetPage(psxRecLUT, i + 0x1fc0, &recROM[i << 14]);-		recLUT_SetPage(psxRecLUT, i + 0x9fc0, &recROM[i << 14]);-		recLUT_SetPage(psxRecLUT, i + 0xbfc0, &recROM[i << 14]);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recROM, 0x0000, i, i - 0x1fc0);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recROM, 0x8000, i, i - 0x1fc0);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recROM, 0xa000, i, i - 0x1fc0); 	} -	for (int i=0; i<(Ps2MemSize::Rom1 / 0x10000); i++)+	for (int i=0x1e00; i<0x1e04; i++) 	{-		recLUT_SetPage(psxRecLUT, i + 0x1e00, &recROM1[i << 14]);-		recLUT_SetPage(psxRecLUT, i + 0x9e00, &recROM1[i << 14]);-		recLUT_SetPage(psxRecLUT, i + 0xbe00, &recROM1[i << 14]);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recROM1, 0x0000, i, i - 0x1fc0);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recROM1, 0x8000, i, i - 0x1fc0);+		recLUT_SetPage(psxRecLUT, psxhwLUT, recROM1, 0xa000, i, i - 0x1fc0); 	}  	if( s_pInstCache ) 		memset( s_pInstCache, 0, sizeof(EEINST)*s_nInstCacheSize ); -	ResetBaseBlockEx(1);+	recBlocks.Reset(); 	g_psxMaxRecMem = 0;  	recPtr = recMem;@@ -782,7 +769,7 @@ } #endif // _MSC_VER -static void iopInitRecLUT(BASEBLOCK* base, int count)+static void iopClearRecLUT(BASEBLOCK* base, int count) { 	for (int i = 0; i < count; i++) { 		base[i].SetFnptr((uptr)iopJITCompile);@@ -845,59 +832,69 @@  static void recClear(u32 Addr, u32 Size) {-	u32 i;-	for(i = 0; i < Size; ++i, Addr+=4) {-		PSXREC_CLEARM(Addr);-	}+	u32 pc = Addr;+	while (pc < Addr + Size*4)+		pc += PSXREC_CLEARM(pc); } -#define IOP_MIN_BLOCK_BYTES 15-+// not used and not right for now+#if 0 void rpsxMemConstClear(u32 mem) { 	// NOTE! This assumes recLUT never changes its mapping 	if( !(psxRecLUT[mem>>16] + mem) ) 		return; -	CMP32ItoM((uptr)PSX_GETBLOCK(mem), 0);+	CMP32ItoM((uptr)PSX_GETBLOCK(mem), iopJITCompile); 	j8Ptr[6] = JE8(0);      _callFunctionArg1((uptr)psxRecClearMem, MEM_CONSTTAG, mem); 	x86SetJ8(j8Ptr[6]); }+#endif -void psxRecClearMem(u32 pc)+// Returns the offset to the next instruction after any cleared memory+u32 psxRecClearMem(u32 pc) { 	BASEBLOCKEX* pexblock;-	BASEBLOCK* pstart;-	BASEBLOCK* p;-	-	p= PSX_GETBLOCK(pc);-	pc = p->GetStartPC();-	if (!pc)-		return;-	pexblock = GetBaseBlockEx(pc, 1);-	if (!pexblock)-		return;-	pstart = PSX_GETBLOCK(pexblock->startpc);+	BASEBLOCK* pblock; -	for (int i = 0; i < pexblock->size; i++) {-		x86Ptr[0] = (u8*)pstart[i].GetFnptr();-		if (x86Ptr[0] == (u8*)iopJITCompile)-			continue;+	pblock = PSX_GETBLOCK(pc);+	// if ((u8*)iopJITCompile == pblock->GetFnptr())+	if (!pblock->GetStartPC())+		return 4; +	pc = HWADDR(pc);++	u32 lowerextent = (u32)-1, upperextent = pc + 4;+	int blockidx = recBlocks.Index(pc);++	while (pexblock = recBlocks[blockidx]) {+		u32 hwstart = HWADDR(pexblock->startpc);+		if (hwstart >= upperextent)+			break;+		pblock = PSX_GETBLOCK(pexblock->startpc);+		x86Ptr[_EmitterId_] = (u8*)pblock->GetFnptr();++		jASSUME((u8*)iopJITCompile != x86Ptr[_EmitterId_]);+		// jASSUME((u8*)iopJITCompileInside != x86Ptr[_EmitterId_]);+ 		// 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)iopDispatcherClear - ( (uptr)x86Ptr[0] + 5 ));+		MOV32ItoR(EDX, pexblock->startpc);+		assert((uptr)x86Ptr[_EmitterId_] <= 0xffffffff);+		PUSH32I((uptr)x86Ptr[_EmitterId_]); // will be replaced by JMP32+		JMP32((uptr)iopDispatcherClear - ((uptr)x86Ptr[_EmitterId_] + 5));++		lowerextent = min(lowerextent, hwstart);+		upperextent = max(upperextent, hwstart + pexblock->size * 4);+		recBlocks.Remove(blockidx); 	} -	iopInitRecLUT(pstart, pexblock->size);+	jASSUME(lowerextent != (u32)-1); -	RemoveBaseBlockEx(pexblock, 1);-	pexblock->size = 0;-	pexblock->startpc = 0;+	iopClearRecLUT(PSX_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4);++	return upperextent - pc; }  void psxSetBranchReg(u32 reg)@@ -1067,7 +1064,7 @@ 		if( !delayslot && psxpc == pblock->GetStartPC() ) 		{ 			// code already in place, so jump to it and exit recomp-			assert( PSX_GETBLOCKEX(pblock)->startpc == pblock->GetStartPC() );+			assert( HWADDR(recBlocks.Get(psxpc)->startpc) == HWADDR(psxpc) ); 			 			_psxFlushCall(FLUSH_EVERYTHING); 			MOV32ItoM((uptr)&psxRegs.pc, psxpc);@@ -1208,27 +1205,17 @@ 	}  	if( s_pCurBlock->GetStartPC() == startpc ) {-		s_pCurBlockEx = PSX_GETBLOCKEX(s_pCurBlock);-		assert( s_pCurBlockEx->startpc == startpc );+		s_pCurBlockEx = recBlocks.Get(HWADDR(startpc));+		assert( HWADDR(s_pCurBlockEx->startpc) == HWADDR(startpc) ); 	} 	else {-		s_pCurBlockEx = NULL;-		for(i = 0; i < PSX_NUMBLOCKS; ++i) {-			if( recBlocks[(i+s_nNextBlock)%PSX_NUMBLOCKS].size == 0 ) {-				s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%PSX_NUMBLOCKS;-				s_nNextBlock = (i+s_nNextBlock+1)%PSX_NUMBLOCKS;-				break;-			}-		}+		s_pCurBlockEx = recBlocks.New(HWADDR(startpc));  		if( s_pCurBlockEx == NULL ) { 			DevCon::WriteLn("IOP Recompiler data reset"); 			recResetIOP();-			s_nNextBlock = 0;-			s_pCurBlockEx = recBlocks;+			s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); 		}--		s_pCurBlockEx->startpc = startpc; 	} 	 	x86SetPtr( recPtr );@@ -1382,9 +1369,6 @@ 	} #endif -	// set the block ptr-	AddBaseBlockEx(s_pCurBlockEx, 1);- 	if( !(psxpc&0x10000000) ) 		g_psxMaxRecMem = std::max( (psxpc&~0xa0000000), g_psxMaxRecMem ); @@ -1423,7 +1407,6 @@ 		} 	} -	assert( x86Ptr[0] >= (u8*)s_pCurBlock->GetFnptr() + IOP_MIN_BLOCK_BYTES ); 	assert( x86Ptr[0] < recMem+RECMEM_SIZE );  	recPtr = x86Ptr[0];Index: pcsx2/x86/iR3000A.h===================================================================--- pcsx2/x86/iR3000A.h	(revision 698)+++ pcsx2/x86/iR3000A.h	(working copy)@@ -70,7 +70,7 @@ void psxSetBranchReg(u32 reg); void psxSetBranchImm( u32 imm ); void psxRecompileNextInstruction(int delayslot);-void psxRecClearMem(u32 p);+u32 psxRecClearMem(u32 p);  //////////////////////////////////////////////////////////////////// // IOP Constant Propagation Defines, Vars, and API - From here down!Index: pcsx2/x86/iR5900.h===================================================================--- pcsx2/x86/iR5900.h	(revision 698)+++ pcsx2/x86/iR5900.h	(working copy)@@ -92,8 +92,8 @@   // Used to clear recompiled code blocks during memory/dma write operations.-void recClearMem(u32 pc);-void REC_CLEARM( u32 mem );+u32 recClearMem(u32 pc);+u32 REC_CLEARM( u32 mem );  // used when processing branches void SaveBranchState();Index: pcsx2/x86/ix86-32/iR5900-32.cpp===================================================================--- pcsx2/x86/ix86-32/iR5900-32.cpp	(revision 698)+++ pcsx2/x86/ix86-32/iR5900-32.cpp	(working copy)@@ -53,7 +53,10 @@  u32 maxrecmem = 0; uptr recLUT[0x10000];+uptr hwLUT[0x10000]; +#define HWADDR(mem) (hwLUT[mem >> 16] + (mem))+ u32 s_nBlockCycles = 0; // cycles of current block recompiling //u8* dyna_block_discard_recmem=0; @@ -77,7 +80,7 @@ static BASEBLOCK *recRAM = NULL;		// and the ptr to the blocks here static BASEBLOCK *recROM = NULL;		// and here static BASEBLOCK *recROM1 = NULL;		// also here-static BASEBLOCKEX *recBlocks = NULL;+static BaseBlocks recBlocks(EE_NUMBLOCKS); static u8* recPtr = NULL, *recStackPtr = NULL; static EEINST* s_pInstCache = NULL; static u32 s_nInstCacheSize = 0;@@ -87,8 +90,6 @@ static u32 s_nEndBlock = 0; // what pc the current block ends	 static u32 s_nHasDelay = 0; -static u32 s_nNextBlock = 0; // next free block in recBlocks- // save states for branches static u16 s_savex86FpuState, s_saveiCWstate; static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0;@@ -111,18 +112,8 @@ #endif  static void iBranchTest(u32 newpc, bool noDispatch=false);-static void InitRecLUT(BASEBLOCK* base, int count);+static void ClearRecLUT(BASEBLOCK* base, int count); -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(pc, 0);-}- //////////////////////////////////////////////////// static void iDumpBlock( int startpc, u8 * ptr ) {@@ -464,7 +455,6 @@  static const uint m_recBlockAllocSize =  	(((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK))-+	(EE_NUMBLOCKS*sizeof(BASEBLOCKEX))		// recBlocks +	RECSTACK_SIZE;		// recStack  static void recAlloc() @@ -507,7 +497,6 @@ 	recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK); 	recROM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom / 4) * sizeof(BASEBLOCK); 	recROM1 = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom1 / 4) * sizeof(BASEBLOCK);-	recBlocks = (BASEBLOCKEX*)curpos; curpos += sizeof(BASEBLOCKEX)*EE_NUMBLOCKS; 	recStack = (u8*)curpos;  	if( s_pInstCache == NULL )@@ -531,19 +520,17 @@ { 	DbgCon::Status( "iR5900-32 > Resetting recompiler memory and structures." ); -	s_nNextBlock = 0; 	maxrecmem = 0;  	memset_8<0xcd, REC_CACHEMEM>(recMem); 	memzero_ptr<m_recBlockAllocSize>( m_recBlockAlloc );-	memzero_ptr<EE_NUMBLOCKS*sizeof(BASEBLOCKEX)>(recBlocks);-	InitRecLUT((BASEBLOCK*)m_recBlockAlloc,+	ClearRecLUT((BASEBLOCK*)m_recBlockAlloc, 		(((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4)));  	if( s_pInstCache ) 		memset( s_pInstCache, 0, sizeof(EEINST)*s_nInstCacheSize ); -	ResetBaseBlockEx(0);+	recBlocks.Reset(); 	mmap_ResetBlockTracking();  #ifdef _MSC_VER@@ -552,32 +539,35 @@     __asm__("emms"); #endif -	memzero_ptr<sizeof recLUT>( recLUT );+	#define GET_HWADDR(mem)  +	for (int i = 0; i < 0x10000; i++)+		recLUT_SetPage(recLUT, 0, 0, 0, i, 0);+ 	for ( int i = 0x0000; i < 0x0200; i++ ) 	{-		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 ]);+		recLUT_SetPage(recLUT, hwLUT, recRAM, 0x0000, i, i);+		recLUT_SetPage(recLUT, hwLUT, recRAM, 0x2000, i, i);+		recLUT_SetPage(recLUT, hwLUT, recRAM, 0x3000, i, i);+		recLUT_SetPage(recLUT, hwLUT, recRAM, 0x8000, i, i);+		recLUT_SetPage(recLUT, hwLUT, recRAM, 0xa000, i, i);+		recLUT_SetPage(recLUT, hwLUT, recRAM, 0xb000, i, i);+		recLUT_SetPage(recLUT, hwLUT, recRAM, 0xc000, i, i);+		recLUT_SetPage(recLUT, hwLUT, recRAM, 0xd000, i, i); 	} -	for ( int i = 0x0000; i < 0x0040; i++ )+	for ( int i = 0x1fc0; i < 0x2000; i++ ) 	{-		recLUT_SetPage(recLUT, i + 0x1fc0, &recROM[ i << 14 ]);-		recLUT_SetPage(recLUT, i + 0x9fc0, &recROM[ i << 14 ]);-		recLUT_SetPage(recLUT, i + 0xbfc0, &recROM[ i << 14 ]);+		recLUT_SetPage(recLUT, hwLUT, recROM, 0x0000, i, i - 0x1fc0);+		recLUT_SetPage(recLUT, hwLUT, recROM, 0x8000, i, i - 0x1fc0);+		recLUT_SetPage(recLUT, hwLUT, recROM, 0xa000, i, i - 0x1fc0); 	} -	for ( int i = 0x0000; i < 0x0004; i++ )+	for ( int i = 0x1e00; i < 0x1e04; i++ ) 	{-		recLUT_SetPage(recLUT, i + 0x1e00, &recROM1[ i << 14 ]);-		recLUT_SetPage(recLUT, i + 0x9e00, &recROM1[ i << 14 ]);-		recLUT_SetPage(recLUT, i + 0xbe00, &recROM1[ i << 14 ]);+		recLUT_SetPage(recLUT, hwLUT, recROM1, 0x0000, i, i - 0x1e00);+		recLUT_SetPage(recLUT, hwLUT, recROM1, 0x8000, i, i - 0x1e00);+		recLUT_SetPage(recLUT, hwLUT, recROM1, 0xa000, i, i - 0x1e00); 	}  	// drk||Raziel says this is useful but I'm not sure why.  Something to do with forward jumps.@@ -603,12 +593,11 @@ static void recShutdown( void ) { 	ProfilerTerminateSource( "EERec" );-	ResetBaseBlockEx(0);+	recBlocks.Reset();  	SafeSysMunmap( recMem, REC_CACHEMEM ); 	safe_aligned_free( m_recBlockAlloc ); 	recRAM = recROM = recROM1 = NULL;-	recBlocks = NULL; 	recStack = NULL;  	safe_free( s_pInstCache );@@ -880,21 +869,23 @@ } } }		// end namespace R5900::Dynarec::OpcodeImpl  ////////////////////////////////////////////////////-static void REC_CLEARM( u32 mem )+static u32 REC_CLEARM( u32 mem ) { 	if ((mem) < maxrecmem && (recLUT[(mem) >> 16] + mem))-		recClearMem(mem);+		return recClearMem(mem);+	else+		return 4; }  void recClear( u32 Addr, u32 Size ) {-	u32 i;-	for(i = 0; i < Size; ++i, Addr+=4)-		REC_CLEARM(Addr);+	u32 pc = Addr;+	while (pc < Addr + Size*4)+		pc += REC_CLEARM(pc); }  // Clears the recLUT table so that all blocks are mapped to the JIT recompiler by default.-static void InitRecLUT(BASEBLOCK* base, int count)+static void ClearRecLUT(BASEBLOCK* base, int count) { 	for (int i = 0; i < count; i++) 	{@@ -904,52 +895,49 @@ 	} } -void recClearMem(u32 pc)+// Returns the offset to the next instruction after any cleared memory+u32 recClearMem(u32 pc) { 	BASEBLOCKEX* pexblock;-	BASEBLOCK* pstart;-	BASEBLOCK* p;-	-	p= PC_GETBLOCK(pc);-	pc = p->GetStartPC();-	if (!pc)-		return;-	pexblock = PC_GETBLOCKEX(pc);-	if (!pexblock)-		return;-	pstart = PC_GETBLOCK(pexblock->startpc);+	BASEBLOCK* pblock; -	// necessary since recompiler doesn't call femms/emms-#ifdef __INTEL_COMPILER-		__asm__("emms");-#else-	#ifdef _MSC_VER-		if (cpucaps.has3DNOWInstructionExtensions) __asm femms;-		else __asm emms;-	#else-		if( cpucaps.has3DNOWInstructionExtensions )__asm__("femms");-		else -			__asm__("emms");-	#endif-#endif+	pblock = PC_GETBLOCK(pc);+	// if ((u8*)JITCompile == pblock->GetFnptr())+	if (!pblock->GetStartPC())+		return 4; -	for (int i = 0; i < pexblock->size; i++)-	{-		x86Ptr[0] = (u8*)pstart[i].GetFnptr();-		if (x86Ptr[0] == (u8*)JITCompile)-			continue;+	pc = HWADDR(pc); +	u32 lowerextent = (u32)-1, upperextent = pc + 4;+	int blockidx = recBlocks.Index(pc);++	while (pexblock = recBlocks[blockidx]) {+		u32 hwstart = HWADDR(pexblock->startpc);++		if (hwstart >= upperextent)+			break;+		pblock = PC_GETBLOCK(pexblock->startpc);+		x86Ptr[_EmitterId_] = (u8*)pblock->GetFnptr();++		jASSUME((u8*)JITCompile != x86Ptr[_EmitterId_]);+		// jASSUME((u8*)JITCompileInside != x86Ptr[_EmitterId_]);+ 		// 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 ));+		MOV32ItoR(EDX, pexblock->startpc);+		assert((uptr)x86Ptr[_EmitterId_] <= 0xffffffff);+		PUSH32I((uptr)x86Ptr[_EmitterId_]); // will be replaced by JMP32+		JMP32((uptr)DispatcherClear - ((uptr)x86Ptr[_EmitterId_] + 5));++		lowerextent = min(lowerextent, hwstart);+		upperextent = max(upperextent, hwstart + pexblock->size * 4);+		recBlocks.Remove(blockidx); 	} -	InitRecLUT(pstart, pexblock->size);+	jASSUME(lowerextent != (u32)-1); -	RemoveBaseBlockEx(pexblock, 0);-	pexblock->size = 0;-	pexblock->startpc = 0;+	ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4);++	return upperextent - pc; }  // check for end of bios@@ -1269,7 +1257,7 @@ 		if( !delayslot && pc == pblock->GetStartPC() ) 		{ 			// code already in place, so jump to it and exit recomp-			assert( PC_GETBLOCKEX(pc)->startpc == pblock->GetStartPC() );+			assert( HWADDR(recBlocks.Get(pc)->startpc) == HWADDR(pc) );  			iFlushCall(FLUSH_EVERYTHING); 			MOV32ItoM((uptr)&cpuRegs.pc, pc);			@@ -1501,27 +1489,17 @@ 	}  	if( s_pCurBlock->GetStartPC() == startpc ) {-		s_pCurBlockEx = PC_GETBLOCKEX(startpc);-		assert( s_pCurBlockEx->startpc == startpc );+		s_pCurBlockEx = recBlocks.Get(HWADDR(startpc));+		assert( HWADDR(s_pCurBlockEx->startpc) == HWADDR(startpc) ); 	} 	else {-		s_pCurBlockEx = NULL;-		for(i = 0; i < EE_NUMBLOCKS; ++i) {-			if( recBlocks[(i+s_nNextBlock)%EE_NUMBLOCKS].size == 0 ) {-				s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%EE_NUMBLOCKS;-				s_nNextBlock = (i+s_nNextBlock+1)%EE_NUMBLOCKS;-				break;-			}-		}+		s_pCurBlockEx = recBlocks.New(HWADDR(startpc));  		if( s_pCurBlockEx == NULL ) { 			//SysPrintf("ee reset (blocks)\n"); 			recResetEE();-			s_nNextBlock = 0;-			s_pCurBlockEx = recBlocks;+			s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); 		}--		s_pCurBlockEx->startpc = startpc; 	}  	x86SetPtr( recPtr );@@ -1896,9 +1874,9 @@ 	assert( (pc-startpc)>>2 <= 0xffff ); 	s_pCurBlockEx->size = (pc-startpc)>>2; -	for(i = 1; i < (u32)s_pCurBlockEx->size; ++i) {+	for(i = 1; i < (u32)s_pCurBlockEx->size; i++) { 		if (!s_pCurBlock[i].GetStartPC())-			s_pCurBlock[i].SetStartPC( startpc );+			s_pCurBlock[i].SetStartPC(startpc); 	}  @@ -1920,9 +1898,6 @@ 	} #endif -	// set the block ptr-	AddBaseBlockEx(s_pCurBlockEx, 0);- 	if( !(pc&0x10000000) ) 		maxrecmem = std::max( (pc&~0xa0000000), maxrecmem );