rendered paste bodyIndex: pcsx2/x86/BaseblockEx.cpp===================================================================--- pcsx2/x86/BaseblockEx.cpp (revision 693)+++ 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 693)+++ 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 693)+++ 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 ); DbgCon::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);@@ -1221,27 +1218,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 );@@ -1395,9 +1382,6 @@ } #endif - // set the block ptr- AddBaseBlockEx(s_pCurBlockEx, 1);- if( !(psxpc&0x10000000) ) g_psxMaxRecMem = std::max( (psxpc&~0xa0000000), g_psxMaxRecMem ); @@ -1436,7 +1420,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 693)+++ 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 693)+++ 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 693)+++ 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-1; ++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 );