microVU: Minor changes/cleanups

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4412 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2011-03-12 05:41:33 +00:00
parent 7edaa221b8
commit ed35dcac17
4 changed files with 94 additions and 100 deletions

View File

@ -82,106 +82,114 @@ const __aligned(32) mVU_Globals mVUglob = {
static __fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) { static __fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) {
throw Exception::HardwareDeficiency() throw Exception::HardwareDeficiency()
.SetDiagMsg(pxsFmt(L"microVU%d recompiler init failed: %s is not available.", vuIndex, extFail)) .SetDiagMsg(pxsFmt(L"microVU%d recompiler init failed: %s is not available.", vuIndex, extFail))
.SetUserMsg(pxsFmt(_("%s Extensions not found. microVU requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail )); .SetUserMsg(pxsFmt(_("%s Extensions not found. microVU requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail));
} }
void microVU::reserveCache() void mVUreserveCache(microVU& mVU) {
{
cache_reserve = new RecompiledCodeReserve( pxsFmt("Micro VU%u Recompiler Cache", index) );
cache_reserve->SetProfilerName( pxsFmt("mVU%urec", index) );
cache = index ?
(u8*)cache_reserve->Reserve( cacheSize * _1mb, HostMemoryMap::mVU1rec ) :
(u8*)cache_reserve->Reserve( cacheSize * _1mb, HostMemoryMap::mVU0rec );
cache_reserve->ThrowIfNotOk(); mVU.cache_reserve = new RecompiledCodeReserve(pxsFmt("Micro VU%u Recompiler Cache", mVU.index));
mVU.cache_reserve->SetProfilerName(pxsFmt("mVU%urec", mVU.index));
mVU.cache = mVU.index ?
(u8*)mVU.cache_reserve->Reserve(mVU.cacheSize * _1mb, HostMemoryMap::mVU1rec):
(u8*)mVU.cache_reserve->Reserve(mVU.cacheSize * _1mb, HostMemoryMap::mVU0rec);
mVU.cache_reserve->ThrowIfNotOk();
} }
// Only run this once per VU! ;) // Only run this once per VU! ;)
void microVU::init(uint vuIndex) { void mVUinit(microVU& mVU, uint vuIndex) {
if(!x86caps.hasMultimediaExtensions) mVUthrowHardwareDeficiency( L"MMX", vuIndex ); if(!x86caps.hasMultimediaExtensions) mVUthrowHardwareDeficiency( L"MMX", vuIndex );
if(!x86caps.hasStreamingSIMDExtensions) mVUthrowHardwareDeficiency( L"SSE", vuIndex ); if(!x86caps.hasStreamingSIMDExtensions) mVUthrowHardwareDeficiency( L"SSE", vuIndex );
if(!x86caps.hasStreamingSIMD2Extensions) mVUthrowHardwareDeficiency( L"SSE2", vuIndex ); if(!x86caps.hasStreamingSIMD2Extensions) mVUthrowHardwareDeficiency( L"SSE2", vuIndex );
memzero(prog); memzero(mVU.prog);
index = vuIndex; mVU.index = vuIndex;
cop2 = 0; mVU.cop2 = 0;
vuMemSize = (index ? 0x4000 : 0x1000); mVU.vuMemSize = (mVU.index ? 0x4000 : 0x1000);
microMemSize = (index ? 0x4000 : 0x1000); mVU.microMemSize = (mVU.index ? 0x4000 : 0x1000);
progSize = (index ? 0x4000 : 0x1000) / 4; mVU.progSize = (mVU.index ? 0x4000 : 0x1000) / 4;
progMemMask = progSize-1; mVU.progMemMask = mVU.progSize-1;
mVU.cacheSize = vuIndex ? mVU1cacheReserve : mVU0cacheReserve;
mVU.cache = NULL;
mVU.dispCache = NULL;
mVU.startFunct = NULL;
mVU.exitFunct = NULL;
reserveCache(); mVUreserveCache(mVU);
dispCache = SysMmapEx(0, mVUdispCacheSize, 0, (index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher")); mVU.dispCache = SysMmapEx(0, mVUdispCacheSize, 0,(mVU.index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher"));
if (!dispCache) throw Exception::OutOfMemory( index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher" ); if (!mVU.dispCache) throw Exception::OutOfMemory (mVU.index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher");
memset(dispCache, 0xcc, mVUdispCacheSize); memset(mVU.dispCache, 0xcc, mVUdispCacheSize);
regAlloc = new microRegAlloc(index); mVU.regAlloc = new microRegAlloc(mVU.index);
} }
// Resets Rec Data // Resets Rec Data
void microVU::reset() { void mVUreset(microVU& mVU, bool resetReserve) {
x86SetPtr(dispCache); // Restore reserve to uncommitted state
mVUdispatcherA(this); if (resetReserve) mVU.cache_reserve->Reset();
mVUdispatcherB(this);
mVUdispatcherC(this); x86SetPtr(mVU.dispCache);
mVUdispatcherD(this); mVUdispatcherA(&mVU);
mVUdispatcherB(&mVU);
mVUdispatcherC(&mVU);
mVUdispatcherD(&mVU);
mVUemitSearch(); mVUemitSearch();
// Clear All Program Data // Clear All Program Data
//memset(&prog, 0, sizeof(prog)); //memset(&mVU.prog, 0, sizeof(mVU.prog));
memset(&prog.lpState, 0, sizeof(prog.lpState)); memset(&mVU.prog.lpState, 0, sizeof(mVU.prog.lpState));
// Program Variables // Program Variables
prog.cleared = 1; mVU.prog.cleared = 1;
prog.isSame = -1; mVU.prog.isSame = -1;
prog.cur = NULL; mVU.prog.cur = NULL;
prog.total = 0; mVU.prog.total = 0;
prog.curFrame = 0; mVU.prog.curFrame = 0;
// Setup Dynarec Cache Limits for Each Program // Setup Dynarec Cache Limits for Each Program
u8* z = cache; u8* z = mVU.cache;
prog.x86start = z; mVU.prog.x86start = z;
prog.x86ptr = z; mVU.prog.x86ptr = z;
prog.x86end = z + ((cacheSize - mVUcacheSafeZone) * _1mb); mVU.prog.x86end = z + ((mVU.cacheSize - mVUcacheSafeZone) * _1mb);
for (u32 i = 0; i < (progSize / 2); i++) { for(u32 i = 0; i < (mVU.progSize / 2); i++) {
if(!prog.prog[i]) { if(!mVU.prog.prog[i]) {
prog.prog[i] = new deque<microProgram*>(); mVU.prog.prog[i] = new deque<microProgram*>();
continue; continue;
} }
deque<microProgram*>::iterator it(prog.prog[i]->begin()); deque<microProgram*>::iterator it(mVU.prog.prog[i]->begin());
for ( ; it != prog.prog[i]->end(); ++it) { for ( ; it != mVU.prog.prog[i]->end(); ++it) {
if (index) mVUdeleteProg<1>(it[0]); if (mVU.index) mVUdeleteProg<1>(it[0]);
else mVUdeleteProg<0>(it[0]); else mVUdeleteProg<0>(it[0]);
} }
prog.prog[i]->clear(); mVU.prog.prog[i]->clear();
prog.quick[i].block = NULL; mVU.prog.quick[i].block = NULL;
prog.quick[i].prog = NULL; mVU.prog.quick[i].prog = NULL;
} }
} }
// Free Allocated Resources // Free Allocated Resources
void microVU::close() { void mVUclose(microVU& mVU) {
safe_delete(cache_reserve); safe_delete(mVU.cache_reserve);
SafeSysMunmap(dispCache, mVUdispCacheSize); SafeSysMunmap(mVU.dispCache, mVUdispCacheSize);
// Delete Programs and Block Managers // Delete Programs and Block Managers
for (u32 i = 0; i < (progSize / 2); i++) { for (u32 i = 0; i < (mVU.progSize / 2); i++) {
if (!prog.prog[i]) continue; if (!mVU.prog.prog[i]) continue;
deque<microProgram*>::iterator it(prog.prog[i]->begin()); deque<microProgram*>::iterator it(mVU.prog.prog[i]->begin());
for ( ; it != prog.prog[i]->end(); ++it) { for ( ; it != mVU.prog.prog[i]->end(); ++it) {
if (index) mVUdeleteProg<1>(it[0]); if (mVU.index) mVUdeleteProg<1>(it[0]);
else mVUdeleteProg<0>(it[0]); else mVUdeleteProg<0>(it[0]);
} }
safe_delete(prog.prog[i]); safe_delete(mVU.prog.prog[i]);
} }
} }
@ -347,29 +355,29 @@ void recMicroVU1::Vsync() throw() { mVUvsyncUpdate(&microVU1); }
void recMicroVU0::Reserve() { void recMicroVU0::Reserve() {
if (AtomicExchange(m_Reserved, 1) == 0) if (AtomicExchange(m_Reserved, 1) == 0)
microVU0.init(0); mVUinit(microVU0, 0);
} }
void recMicroVU1::Reserve() { void recMicroVU1::Reserve() {
if (AtomicExchange(m_Reserved, 1) == 0) if (AtomicExchange(m_Reserved, 1) == 0)
microVU1.init(1); mVUinit(microVU1, 1);
} }
void recMicroVU0::Shutdown() throw() { void recMicroVU0::Shutdown() throw() {
if (AtomicExchange(m_Reserved, 0) == 1) if (AtomicExchange(m_Reserved, 0) == 1)
microVU0.close(); mVUclose(microVU0);
} }
void recMicroVU1::Shutdown() throw() { void recMicroVU1::Shutdown() throw() {
if (AtomicExchange(m_Reserved, 0) == 1) if (AtomicExchange(m_Reserved, 0) == 1)
microVU1.close(); mVUclose(microVU1);
} }
void recMicroVU0::Reset() { void recMicroVU0::Reset() {
if(!pxAssertDev(m_Reserved, "MicroVU0 CPU Provider has not been reserved prior to reset!")) return; if(!pxAssertDev(m_Reserved, "MicroVU0 CPU Provider has not been reserved prior to reset!")) return;
microVU0.reset(); mVUreset(microVU0, true);
} }
void recMicroVU1::Reset() { void recMicroVU1::Reset() {
if(!pxAssertDev(m_Reserved, "MicroVU1 CPU Provider has not been reserved prior to reset!")) return; if(!pxAssertDev(m_Reserved, "MicroVU1 CPU Provider has not been reserved prior to reset!")) return;
microVU1.reset(); mVUreset(microVU1, true);
} }
void recMicroVU0::Execute(u32 cycles) { void recMicroVU0::Execute(u32 cycles) {
@ -405,13 +413,17 @@ uint recMicroVU1::GetCacheReserve() const {
return microVU1.cacheSize; return microVU1.cacheSize;
} }
void recMicroVU0::SetCacheReserve( uint reserveInMegs ) const { void recMicroVU0::SetCacheReserve(uint reserveInMegs) const {
DevCon.WriteLn("microVU0: Upping cache size [%dmb]", reserveInMegs); DevCon.WriteLn("microVU0: Changing cache size [%dmb]", reserveInMegs);
microVU0.cacheSize = min(reserveInMegs, mVUcacheMaxReserve); microVU0.cacheSize = min(reserveInMegs, mVU0cacheReserve);
safe_delete(microVU0.cache_reserve); // I assume this unmaps the memory
mVUreserveCache(microVU0); // Need rec-reset after this
} }
void recMicroVU1::SetCacheReserve( uint reserveInMegs ) const { void recMicroVU1::SetCacheReserve(uint reserveInMegs) const {
DevCon.WriteLn("microVU1: Upping cache size [%dmb]", reserveInMegs); DevCon.WriteLn("microVU1: Changing cache size [%dmb]", reserveInMegs);
microVU1.cacheSize = min(reserveInMegs, mVUcacheMaxReserve); microVU1.cacheSize = min(reserveInMegs, mVU1cacheReserve);
safe_delete(microVU1.cache_reserve); // I assume this unmaps the memory
mVUreserveCache(microVU1); // Need rec-reset after this
} }
void recMicroVU1::ResumeXGkick() { void recMicroVU1::ResumeXGkick() {

View File

@ -162,10 +162,10 @@ 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)
}; };
static const uint mVUdispCacheSize = __pagesize; // Dispatcher Cache Size (in bytes) static const uint mVUdispCacheSize = __pagesize; // Dispatcher Cache Size (in bytes)
static const uint mVUcacheSafeZone = 3; // Safe-Zone for program recompilation (in megabytes) static const uint mVUcacheSafeZone = 3; // Safe-Zone for program recompilation (in megabytes)
static const uint mVUcacheInitReserve = 64; // Initial Reserve Cache Size (in megabytes) static const uint mVU0cacheReserve = 64; // mVU0 Reserve Cache Size (in megabytes)
static const uint mVUcacheMaxReserve = 128; // Max Reserve Cache Size (in megabytes) static const uint mVU1cacheReserve = 64; // mVU1 Reserve Cache Size (in megabytes)
struct microVU { struct microVU {
@ -241,20 +241,6 @@ struct microVU {
pxAssumeDev((prog.IRinfo.curPC & 1) == 0, "microVU recompiler: Upper instructions cannot have valid branch addresses."); pxAssumeDev((prog.IRinfo.curPC & 1) == 0, "microVU recompiler: Upper instructions cannot have valid branch addresses.");
return (((prog.IRinfo.curPC + 4) + (Imm11() * 2)) & progMemMask) * 4; return (((prog.IRinfo.curPC + 4) + (Imm11() * 2)) & progMemMask) * 4;
} }
microVU()
{
cacheSize = mVUcacheInitReserve;
cache = NULL;
dispCache = NULL;
startFunct = NULL;
exitFunct = NULL;
}
void reserveCache();
void init(uint vuIndex);
void reset();
void close();
}; };
// microVU rec structs // microVU rec structs

View File

@ -191,7 +191,7 @@ _mVUt void mVUcleanUp() {
if ((xGetPtr() < mVU->prog.x86start) || (xGetPtr() >= mVU->prog.x86end)) { if ((xGetPtr() < mVU->prog.x86start) || (xGetPtr() >= mVU->prog.x86end)) {
Console.WriteLn(vuIndex ? Color_Orange : Color_Magenta, "microVU%d: Program cache limit reached.", mVU->index); Console.WriteLn(vuIndex ? Color_Orange : Color_Magenta, "microVU%d: Program cache limit reached.", mVU->index);
mVU->reset(); mVUreset(*mVU, false);
} }
mVU->cycles = mVU->totalCycles - mVU->cycles; mVU->cycles = mVU->totalCycles - mVU->cycles;

View File

@ -36,20 +36,16 @@ static void mVUupdateFlags(mV, const xmm& reg, const xmm& regT1in = xEmptyReg, c
const xmm& regT1 = regT1b ? mVU->regAlloc->allocReg() : regT1in; const xmm& regT1 = regT1b ? mVU->regAlloc->allocReg() : regT1in;
xmm regT2 = reg; xmm regT2 = reg;
if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) {
{
regT2 = regT2in; regT2 = regT2in;
if (regT2.IsEmpty()) if (regT2.IsEmpty()) {
{
regT2 = mVU->regAlloc->allocReg(); regT2 = mVU->regAlloc->allocReg();
regT2b = true; regT2b = true;
} }
xPSHUF.D(regT2, reg, 0x1B); // Flip wzyx to xyzw xPSHUF.D(regT2, reg, 0x1B); // Flip wzyx to xyzw
} }
else regT2 = reg; else regT2 = reg;
if (sFLAG.doFlag) { if (sFLAG.doFlag) {
mVUallocSFLAGa(sReg, sFLAG.lastWrite); // Get Prev Status Flag mVUallocSFLAGa(sReg, sFLAG.lastWrite); // Get Prev Status Flag
if (sFLAG.doNonSticky) xAND(sReg, 0xfffc00ff); // Clear O,U,S,Z flags if (sFLAG.doNonSticky) xAND(sReg, 0xfffc00ff); // Clear O,U,S,Z flags