mirror of https://github.com/PCSX2/pcsx2.git
microVU: Minor changes/cleanups
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4412 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
7edaa221b8
commit
ed35dcac17
|
@ -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(µVU1); }
|
||||||
|
|
||||||
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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue