mirror of https://github.com/PCSX2/pcsx2.git
microVU: Now supports growable rec-cache.
So when a game has reached the cache-limit, mVU allocates more memory unless it has reached it's max limit (100mb for vu1, 50mb for vu0) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3332 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
87c80d6e2b
commit
8ae1e91f7f
|
@ -86,30 +86,27 @@ _f void mVUinit(VURegs* vuRegsPtr, int vuIndex) {
|
|||
mVU->vuMemSize = (vuIndex ? 0x4000 : 0x1000);
|
||||
mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000);
|
||||
mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4;
|
||||
mVU->dispCache = NULL;
|
||||
mVU->cache = NULL;
|
||||
mVU->cacheSize = mVUcacheSize;
|
||||
mVU->regAlloc = new microRegAlloc(mVU->regs);
|
||||
|
||||
// Give SysMmapEx a NULL and let the OS pick the memory for us: mVU can work with any
|
||||
// address the operating system gives us, and unlike the EE/IOP there's not much convenience
|
||||
// to debugging if the address is known anyway due to mVU's complex memory layouts (caching).
|
||||
|
||||
mVU->cache = SysMmapEx(NULL, mVU->cacheSize + 0x1000, 0, (vuIndex ? "Micro VU1" : "Micro VU0"));
|
||||
if (!mVU->cache) throw Exception::OutOfMemory( "microVU Error: Failed to allocate recompiler memory!" );
|
||||
|
||||
memset(mVU->cache, 0xcc, mVU->cacheSize + 0x1000);
|
||||
ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize);
|
||||
|
||||
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||
mVU->prog.prog[i].list = new deque<microProgram*>();
|
||||
}
|
||||
|
||||
mVU->dispCache = SysMmapEx(NULL, mVUdispCacheSize, 0, (mVU->index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher"));
|
||||
if (!mVU->dispCache) throw Exception::OutOfMemory("microVU Error: Failed to allocate dispatcher memory!");
|
||||
memset(mVU->dispCache, 0xcc, mVUdispCacheSize);
|
||||
|
||||
// Setup Entrance/Exit Points
|
||||
x86SetPtr(mVU->cache);
|
||||
x86SetPtr(mVU->dispCache);
|
||||
mVUdispatcherA(mVU);
|
||||
mVUdispatcherB(mVU);
|
||||
mVUemitSearch();
|
||||
mVUreset(mVU);
|
||||
|
||||
// Allocates rec-cache and calls mVUreset()
|
||||
mVUresizeCache(mVU, mVU->cacheSize + mVUcacheSafeZone);
|
||||
}
|
||||
|
||||
// Resets Rec Data
|
||||
|
@ -127,10 +124,10 @@ _f void mVUreset(mV) {
|
|||
mVU->prog.curFrame = 0;
|
||||
|
||||
// Setup Dynarec Cache Limits for Each Program
|
||||
u8* z = (mVU->cache + 0x1000); // Dispatcher Code is in first page of cache
|
||||
u8* z = mVU->cache;
|
||||
mVU->prog.x86start = z;
|
||||
mVU->prog.x86ptr = z;
|
||||
mVU->prog.x86end = (u8*)((uptr)z + (uptr)(mVU->cacheSize - (_1mb * 3))); // 3mb "Safe Zone"
|
||||
mVU->prog.x86end = (u8*)((uptr)z + (uptr)(mVU->cacheSize - mVUcacheSafeZone)); // "Safe Zone"
|
||||
|
||||
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||
deque<microProgram*>::iterator it = mVU->prog.prog[i].list->begin();
|
||||
|
@ -147,7 +144,8 @@ _f void mVUreset(mV) {
|
|||
// Free Allocated Resources
|
||||
_f void mVUclose(mV) {
|
||||
|
||||
if (mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); mVU->cache = NULL; }
|
||||
if (mVU->dispCache) { HostSys::Munmap(mVU->dispCache, mVUdispCacheSize); mVU->dispCache = NULL; }
|
||||
if (mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); mVU->cache = NULL; }
|
||||
|
||||
// Delete Programs and Block Managers
|
||||
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||
|
@ -162,6 +160,30 @@ _f void mVUclose(mV) {
|
|||
safe_delete(mVU->regAlloc);
|
||||
}
|
||||
|
||||
void mVUresizeCache(mV, u32 size) {
|
||||
|
||||
if (size > (u32)mVUcacheMaxSize) { if (mVU->cacheSize==mVUcacheMaxSize) return; size = mVUcacheMaxSize; }
|
||||
if (mVU->cache) Console.WriteLn(Color_Green, "microVU%d: Attempting to resize Cache [%dmb]", mVU->index, size/_1mb);
|
||||
|
||||
// Give SysMmapEx a NULL and let the OS pick the memory for us: mVU can work with any
|
||||
// address the operating system gives us, and unlike the EE/IOP there's not much convenience
|
||||
// to debugging if the address is known anyway due to mVU's complex memory layouts (caching).
|
||||
|
||||
u8* cache = SysMmapEx(NULL, size, 0, (mVU->index ? "Micro VU1" : "Micro VU0"));
|
||||
if(!cache && !mVU->cache) throw Exception::OutOfMemory("microVU Error: Failed to allocate recompiler memory!");
|
||||
if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); return; }
|
||||
if (mVU->cache) {
|
||||
HostSys::Munmap(mVU->cache, mVU->cacheSize);
|
||||
ProfilerTerminateSource(isVU1?"mVU1 Rec":"mVU0 Rec");
|
||||
}
|
||||
|
||||
mVU->cache = cache;
|
||||
mVU->cacheSize = size;
|
||||
memset(mVU->cache, 0xcc, mVU->cacheSize);
|
||||
ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize);
|
||||
mVUreset(mVU);
|
||||
}
|
||||
|
||||
// Clears Block Data in specified range
|
||||
_f void mVUclear(mV, u32 addr, u32 size) {
|
||||
if (!mVU->prog.cleared) {
|
||||
|
|
|
@ -156,7 +156,12 @@ struct microProgManager {
|
|||
microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution)
|
||||
};
|
||||
|
||||
#define mVUcacheSize ((mVU->index) ? (_1mb * 20) : (_1mb * 10))
|
||||
#define mVUdispCacheSize (0x1000) // Dispatcher Cache Size
|
||||
#define mVUcacheSize ((mVU->index) ? (_1mb * 17) : (_1mb * 7)) // Initial Size (Excluding Safe-Zone)
|
||||
#define mVUcacheMaxSize ((mVU->index) ? (_1mb * 100) : (_1mb * 50)) // Max Size allowed to grow to
|
||||
#define mVUcacheGrowBy ((mVU->index) ? (_1mb * 15) : (_1mb * 10)) // Grows by this amount
|
||||
#define mVUcacheSafeZone ((mVU->index) ? (_1mb * 3) : (_1mb * 3)) // Safe-Zone for last program
|
||||
|
||||
struct microVU {
|
||||
|
||||
__aligned16 u32 macFlag[4]; // 4 instances of mac flag (used in execution)
|
||||
|
@ -177,6 +182,7 @@ struct microVU {
|
|||
AsciiFile* logFile; // Log File Pointer
|
||||
VURegs* regs; // VU Regs Struct
|
||||
u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to)
|
||||
u8* dispCache; // Dispatchers Cache (where startFunct and exitFunct are written to)
|
||||
u8* startFunct; // Ptr Function to the Start code for recompiled programs
|
||||
u8* exitFunct; // Ptr Function to the Exit code for recompiled programs
|
||||
u32 code; // Contains the current Instruction
|
||||
|
@ -204,6 +210,7 @@ _f void mVUinit(VURegs*, int);
|
|||
_f void mVUreset(mV);
|
||||
_f void mVUclose(mV);
|
||||
_f void mVUclear(mV, u32, u32);
|
||||
void mVUresizeCache(mV, u32);
|
||||
_f void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
|
||||
_mVUt void* __fastcall mVUcompileJIT(u32 startPC, uptr pState);
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ void mVUdispatcherB(mV) {
|
|||
|
||||
xRET();
|
||||
|
||||
mVUcacheCheck(x86Ptr, mVU->cache, 0x1000);
|
||||
mVUcacheCheck(x86Ptr, mVU->dispCache, mVUdispCacheSize);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -289,7 +289,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
|
|||
uptr diff = ptr - start; \
|
||||
if (diff >= limit) { \
|
||||
Console.WriteLn("microVU%d: Program cache limit reached. Size = 0x%x", mVU->index, diff); \
|
||||
mVUreset(mVU); \
|
||||
mVUresizeCache(mVU, mVU->cacheSize + mVUcacheGrowBy); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue