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->vuMemSize = (vuIndex ? 0x4000 : 0x1000);
|
||||||
mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000);
|
mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000);
|
||||||
mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4;
|
mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4;
|
||||||
|
mVU->dispCache = NULL;
|
||||||
mVU->cache = NULL;
|
mVU->cache = NULL;
|
||||||
mVU->cacheSize = mVUcacheSize;
|
mVU->cacheSize = mVUcacheSize;
|
||||||
mVU->regAlloc = new microRegAlloc(mVU->regs);
|
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++) {
|
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||||
mVU->prog.prog[i].list = new deque<microProgram*>();
|
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
|
// Setup Entrance/Exit Points
|
||||||
x86SetPtr(mVU->cache);
|
x86SetPtr(mVU->dispCache);
|
||||||
mVUdispatcherA(mVU);
|
mVUdispatcherA(mVU);
|
||||||
mVUdispatcherB(mVU);
|
mVUdispatcherB(mVU);
|
||||||
mVUemitSearch();
|
mVUemitSearch();
|
||||||
mVUreset(mVU);
|
|
||||||
|
// Allocates rec-cache and calls mVUreset()
|
||||||
|
mVUresizeCache(mVU, mVU->cacheSize + mVUcacheSafeZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets Rec Data
|
// Resets Rec Data
|
||||||
|
@ -127,10 +124,10 @@ _f void mVUreset(mV) {
|
||||||
mVU->prog.curFrame = 0;
|
mVU->prog.curFrame = 0;
|
||||||
|
|
||||||
// Setup Dynarec Cache Limits for Each Program
|
// 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.x86start = z;
|
||||||
mVU->prog.x86ptr = 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++) {
|
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||||
deque<microProgram*>::iterator it = mVU->prog.prog[i].list->begin();
|
deque<microProgram*>::iterator it = mVU->prog.prog[i].list->begin();
|
||||||
|
@ -147,7 +144,8 @@ _f void mVUreset(mV) {
|
||||||
// Free Allocated Resources
|
// Free Allocated Resources
|
||||||
_f void mVUclose(mV) {
|
_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
|
// Delete Programs and Block Managers
|
||||||
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||||
|
@ -162,6 +160,30 @@ _f void mVUclose(mV) {
|
||||||
safe_delete(mVU->regAlloc);
|
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
|
// Clears Block Data in specified range
|
||||||
_f void mVUclear(mV, u32 addr, u32 size) {
|
_f void mVUclear(mV, u32 addr, u32 size) {
|
||||||
if (!mVU->prog.cleared) {
|
if (!mVU->prog.cleared) {
|
||||||
|
|
|
@ -156,7 +156,12 @@ struct microProgManager {
|
||||||
microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution)
|
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 {
|
struct microVU {
|
||||||
|
|
||||||
__aligned16 u32 macFlag[4]; // 4 instances of mac flag (used in execution)
|
__aligned16 u32 macFlag[4]; // 4 instances of mac flag (used in execution)
|
||||||
|
@ -177,6 +182,7 @@ struct microVU {
|
||||||
AsciiFile* logFile; // Log File Pointer
|
AsciiFile* logFile; // Log File Pointer
|
||||||
VURegs* regs; // VU Regs Struct
|
VURegs* regs; // VU Regs Struct
|
||||||
u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to)
|
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* startFunct; // Ptr Function to the Start code for recompiled programs
|
||||||
u8* exitFunct; // Ptr Function to the Exit code for recompiled programs
|
u8* exitFunct; // Ptr Function to the Exit code for recompiled programs
|
||||||
u32 code; // Contains the current Instruction
|
u32 code; // Contains the current Instruction
|
||||||
|
@ -204,6 +210,7 @@ _f void mVUinit(VURegs*, int);
|
||||||
_f void mVUreset(mV);
|
_f void mVUreset(mV);
|
||||||
_f void mVUclose(mV);
|
_f void mVUclose(mV);
|
||||||
_f void mVUclear(mV, u32, u32);
|
_f void mVUclear(mV, u32, u32);
|
||||||
|
void mVUresizeCache(mV, u32);
|
||||||
_f void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
|
_f void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
|
||||||
_mVUt void* __fastcall mVUcompileJIT(u32 startPC, uptr pState);
|
_mVUt void* __fastcall mVUcompileJIT(u32 startPC, uptr pState);
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ void mVUdispatcherB(mV) {
|
||||||
|
|
||||||
xRET();
|
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; \
|
uptr diff = ptr - start; \
|
||||||
if (diff >= limit) { \
|
if (diff >= limit) { \
|
||||||
Console.WriteLn("microVU%d: Program cache limit reached. Size = 0x%x", mVU->index, diff); \
|
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