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:
cottonvibes 2010-06-28 05:23:59 +00:00
parent 87c80d6e2b
commit 8ae1e91f7f
4 changed files with 47 additions and 18 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -92,7 +92,7 @@ void mVUdispatcherB(mV) {
xRET();
mVUcacheCheck(x86Ptr, mVU->cache, 0x1000);
mVUcacheCheck(x86Ptr, mVU->dispCache, mVUdispCacheSize);
}
//------------------------------------------------------------------

View File

@ -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); \
} \
}