diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index bc2bfb096c..d4564b78c9 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -30,6 +30,7 @@ PCSX2_ALIGNED16(microVU microVU0); PCSX2_ALIGNED16(microVU microVU1); declareAllVariables // Declares All Global Variables :D + //------------------------------------------------------------------ // Micro VU - Main Functions //------------------------------------------------------------------ @@ -117,7 +118,6 @@ microVUt(void) mVUclose() { // Clears Block Data in specified range microVUt(void) mVUclear(u32 addr, u32 size) { - microVU* mVU = mVUx; if (!mVU->prog.cleared) { memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState)); @@ -139,7 +139,7 @@ microVUt(void) mVUclearProg(int progIndex) { mVU->prog.prog[progIndex].range[1] = -1; mVU->prog.prog[progIndex].x86ptr = mVU->prog.prog[progIndex].x86start; for (u32 i = 0; i < (mVU->progSize / 2); i++) { - if( mVU->prog.prog[progIndex].block[i] ) + if (mVU->prog.prog[progIndex].block[i]) mVU->prog.prog[progIndex].block[i]->reset(); } } @@ -170,11 +170,9 @@ microVUt(int) mVUfindLeastUsedProg() { int smallidx = startidx; u32 smallval = mVU->prog.prog[startidx].used; - for (int i = startidx; i != endidx; i = (i+1)&mVU->prog.max) - { + for (int i = startidx; i != endidx; i = (i+1)&mVU->prog.max) { u32 used = mVU->prog.prog[i].used; - if (smallval > used) - { + if (smallval > used) { smallval = used; smallidx = i; } @@ -195,7 +193,6 @@ microVUt(int) mVUfindLeastUsedProg() { // frame-based decrementing system in combination with a program-execution-based incrementing // system. In english: if last_used >= 2 it means the program has been used for the current // or prev frame. if it's 0, the program hasn't been used for a while. -// microVUt(void) __mVUvsyncUpdate() { microVU* mVU = mVUx; @@ -246,11 +243,7 @@ microVUt(int) mVUsearchProg() { for (int i = 0; i <= mVU->prog.total; i++) { if (mVUcmpProg(i, !mVU->prog.prog[i].used, 0, 0)) return 1; // Check Older Programs - } - /*for (int i = 0; i <= mVU->prog.total; i++) { - if (mVUcmpProg(i, 1, 1, 0)) - return 1; // Check Partial Program - }*/ + } mVU->prog.cur = mVUfindLeastUsedProg(); // If cleared and program not found, make a new program instance mVU->prog.cleared = 0; mVU->prog.isSame = 1; @@ -260,27 +253,7 @@ microVUt(int) mVUsearchProg() { mVU->prog.prog[mVU->prog.cur].last_used = 3; return 1; // If !cleared, then we're still on the same program as last-time ;) } -/* -// Block Invalidation -__forceinline void mVUinvalidateBlock(microVU* mVU, u32 addr, u32 size) { - int i = addr/8; - int end = i+((size+(8-(size&7)))/8); // ToDo: Can be simplified to addr+size if Size is always a multiple of 8 - - if (!mVU->prog.cleared) { - for ( ; i < end; i++) { - if ( mVU->prog.prog[mVU->prog.cur].block[i]->clear() ) { - mVU->prog.cleared = 1; - i++; - break; - } - } - } - for ( ; i < end; i++) { - mVU->prog.prog[mVU->prog.cur].block[i]->clearFast(); - } -} -*/ //------------------------------------------------------------------ // Wrapper Functions - Called by other parts of the Emu //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index b6d4106c3c..827102865d 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -17,8 +17,8 @@ */ #pragma once -//#define mVUdebug // Prints Extra Info to Console -//#define mVUlogProg // Dumps MicroPrograms into microVU0.txt/microVU1.txt +//#define mVUdebug // Prints Extra Info to Console +//#define mVUlogProg // Dumps MicroPrograms to \logs\*.html #include "Common.h" #include "VU.h" @@ -27,24 +27,26 @@ #include "microVU_Alloc.h" #include "microVU_Misc.h" -#define mMaxBlocks 32 // Max Blocks With Different Pipeline States +#define mMaxBlocks 32 // Max Blocks With Different Pipeline States (For n = 1, 2, 4, 8, 16, etc...) class microBlockManager { private: static const int MaxBlocks = mMaxBlocks - 1; int listSize; // Total Items - 1 + int listI; // Index to Add new block microBlock blockList[mMaxBlocks]; public: microBlockManager() { reset(); } ~microBlockManager() {} - void reset() { listSize = -1; }; + void reset() { listSize = -1; listI = -1; }; microBlock* add(microBlock* pBlock) { microBlock* thisBlock = search(&pBlock->pState); if (!thisBlock) { - listSize++; - if (listSize > MaxBlocks) { Console::Error("microVU Warning: Block List Overflow"); listSize = 0; } - memcpy_fast(&blockList[listSize], pBlock, sizeof(microBlock)); - thisBlock = &blockList[listSize]; + listI++; + if (listSize < MaxBlocks) { listSize++; } + if (listI > MaxBlocks) { Console::Error("microVU Warning: Block List Overflow"); listI = 0; } + memcpy_fast(&blockList[listI], pBlock, sizeof(microBlock)); + thisBlock = &blockList[listI]; } return thisBlock; } diff --git a/pcsx2/x86/microVU_Analyze.inl b/pcsx2/x86/microVU_Analyze.inl index e10803938d..c61872be38 100644 --- a/pcsx2/x86/microVU_Analyze.inl +++ b/pcsx2/x86/microVU_Analyze.inl @@ -49,6 +49,19 @@ } \ } +#define analyzeReg1b(reg) { \ + if (reg) { \ + analyzeReg1(reg); \ + if (mVUregsTemp.VFreg[0] == reg) { \ + if ((mVUregsTemp.VF[0].x && _X) \ + || (mVUregsTemp.VF[0].y && _Y) \ + || (mVUregsTemp.VF[0].z && _Z) \ + || (mVUregsTemp.VF[0].w && _W)) \ + { mVUinfo |= _swapOps; } \ + } \ + } \ +} + microVUt(void) mVUanalyzeFMAC1(int Fd, int Fs, int Ft) { microVU* mVU = mVUx; mVUinfo |= _doStatus; @@ -136,6 +149,13 @@ microVUt(void) mVUanalyzeIALU2(int Is, int It) { if (_Y) { mVUstall = aMax(mVUstall, aReg(reg).z); } \ if (_Z) { mVUstall = aMax(mVUstall, aReg(reg).w); } \ if (_W) { mVUstall = aMax(mVUstall, aReg(reg).x); } \ + if (mVUregsTemp.VFreg[0] == reg) { \ + if ((mVUregsTemp.VF[0].y && _X) \ + || (mVUregsTemp.VF[0].z && _Y) \ + || (mVUregsTemp.VF[0].w && _Z) \ + || (mVUregsTemp.VF[0].x && _W)) \ + { mVUinfo |= _swapOps; } \ + } \ } \ } @@ -158,6 +178,13 @@ microVUt(void) mVUanalyzeMR32(int Fs, int Ft) { case 2: mVUstall = aMax(mVUstall, aReg(reg).z); break; \ case 3: mVUstall = aMax(mVUstall, aReg(reg).w); break; \ } \ + if (mVUregsTemp.VFreg[0] == reg) { \ + if ((mVUregsTemp.VF[0].x && (fxf == 0)) \ + || (mVUregsTemp.VF[0].y && (fxf == 1)) \ + || (mVUregsTemp.VF[0].z && (fxf == 2)) \ + || (mVUregsTemp.VF[0].w && (fxf == 3))) \ + { mVUinfo |= _swapOps; } \ + } \ } \ } @@ -186,7 +213,7 @@ microVUt(void) mVUanalyzeEFU1(int Fs, int Fsf, u8 xCycles) { microVUt(void) mVUanalyzeEFU2(int Fs, u8 xCycles) { microVU* mVU = mVUx; mVUprint("microVU: EFU Opcode"); - analyzeReg1(Fs); + analyzeReg1b(Fs); analyzePreg(xCycles); } @@ -207,8 +234,7 @@ microVUt(void) mVUanalyzeMFP(int Ft) { microVUt(void) mVUanalyzeMOVE(int Fs, int Ft) { microVU* mVU = mVUx; if (!Ft || (Ft == Fs)) { mVUinfo |= _isNOP; } - if (mVUregsTemp.VFreg[0] == Fs) { mVUinfo |= _swapOps; } - analyzeReg1(Fs); + analyzeReg1b(Fs); analyzeReg2(Ft, 1); } @@ -231,10 +257,9 @@ microVUt(void) mVUanalyzeLQ(int Ft, int Is, bool writeIs) { microVUt(void) mVUanalyzeSQ(int Fs, int It, bool writeIt) { microVU* mVU = mVUx; - analyzeReg1(Fs); + analyzeReg1b(Fs); analyzeVIreg1(It); if (writeIt) { analyzeVIreg2(It, 1); } - if (mVUregsTemp.VFreg[0] == Fs) { mVUinfo |= _swapOps; } } //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 5e21be02e4..3af44862f8 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -45,6 +45,36 @@ // Helper Functions //------------------------------------------------------------------ +// Used by mVUsetupRange +microVUt(void) mVUcheckIsSame() { + microVU* mVU = mVUx; + + if (mVU->prog.isSame == -1) { + mVU->prog.isSame = !!memcmp_mmx(mVU->prog.prog[mVU->prog.cur].data, mVU->regs->Micro, mVU->microSize); + } + if (mVU->prog.isSame == 0) { + mVUcacheProg(mVU->prog.cur); + } +} + +// Sets up microProgram PC ranges based on whats been recompiled +microVUt(void) mVUsetupRange(u32 pc) { + microVU* mVU = mVUx; + + if (mVUcurProg.range[0] == -1) { + mVUcurProg.range[0] = (s32)pc; + mVUcurProg.range[1] = (s32)pc; + } + else if (mVUcurProg.range[0] > (s32)pc) { + mVUcurProg.range[0] = (s32)pc; + mVUcheckIsSame(); + } + else if (mVUcurProg.range[1] < (s32)pc) { + mVUcurProg.range[1] = (s32)pc; + mVUcheckIsSame(); + } +} + // Recompiles Code for Proper Flags and Q/P regs on Block Linkings microVUt(void) mVUsetupBranch(int* xStatus, int* xMac, int* xClip, int xCycles) { microVU* mVU = mVUx; @@ -150,34 +180,6 @@ microVUt(void) mVUtestCycles() { SUB32ItoM((uptr)&mVU->cycles, mVUcycles); } -microVUt(void) mVUcheckIsSame() { - microVU* mVU = mVUx; - - if (mVU->prog.isSame == -1) { - mVU->prog.isSame = !!memcmp_mmx(mVU->prog.prog[mVU->prog.cur].data, mVU->regs->Micro, mVU->microSize); - } - if (mVU->prog.isSame == 0) { - mVUcacheProg(mVU->prog.cur); - } -} - -microVUt(void) mVUsetupRange(u32 pc) { - microVU* mVU = mVUx; - - if (mVUcurProg.range[0] == -1) { - mVUcurProg.range[0] = (s32)pc; - mVUcurProg.range[1] = (s32)pc; - } - else if (mVUcurProg.range[0] > (s32)pc) { - mVUcurProg.range[0] = (s32)pc; - mVUcheckIsSame(); - } - else if (mVUcurProg.range[1] < (s32)pc) { - mVUcurProg.range[1] = (s32)pc; - mVUcheckIsSame(); - } -} - //------------------------------------------------------------------ // Recompiler //------------------------------------------------------------------ @@ -276,7 +278,7 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) { incPC(-3); // Go back to branch opcode (to get branch imm addr) mVUsetupBranch(xStatus, xMac, xClip, xCycles); - if( mVUblocks[branchAddr/8] == NULL ) + if (mVUblocks[branchAddr/8] == NULL) mVUblocks[branchAddr/8] = new microBlockManager(); // Check if branch-block has already been compiled @@ -293,7 +295,6 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) { mVUbackupRegs(); MOV32MtoR(gprT2, (uptr)&mVU->branch); // Get startPC (ECX first argument for __fastcall) - //AND32ItoR(gprT2, (vuIndex)?0x3ff8:0xff8); // Ensure valid jump address MOV32ItoR(gprR, (u32)&pBlock->pStateEnd); // Get pState (EDX second argument for __fastcall) if (!vuIndex) CALLFunc((uptr)mVUcompileVU0); //(u32 startPC, uptr pState) diff --git a/pcsx2/x86/microVU_Flags.inl b/pcsx2/x86/microVU_Flags.inl index 7091fc711a..4dc2c8b226 100644 --- a/pcsx2/x86/microVU_Flags.inl +++ b/pcsx2/x86/microVU_Flags.inl @@ -26,7 +26,7 @@ microVUt(void) mVUdivSet() { if (doDivFlag) { getFlagReg(flagReg1, fsInstance); if (!doStatus) { getFlagReg(flagReg2, fpsInstance); MOV32RtoR(flagReg1, flagReg2); } - AND16ItoR(flagReg1, 0x0fcf); + AND32ItoR(flagReg1, 0x0fcf); OR32MtoR (flagReg1, (uptr)&mVU->divFlag); } } @@ -223,8 +223,7 @@ microVUt(void) mVUsetFlagInfo() { mVUflagInfo = 0; incPC(4); // Branch Not Taken mVUpass4(xPC); - incPC(-3); - //if (mVUflagInfo != backupFlagInfo) { mVUflagInfo |= __NeedExact; } + incPC(-3); mVUflagInfo |= backupFlagInfo; } } diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index e8c34d0886..9e1ad49a4d 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -293,7 +293,10 @@ declareAllVariables #define CHECK_VU_MINMAXHACK 0 // Min/Max Speed Hack // Cache Limit Check -#define mVUcacheCheck(ptr, start, limit) { \ - uptr diff = ptr - start; \ - if (diff >= limit) { Console::Error("microVU Error: Program went over its cache limit. Size = 0x%x", params diff); } \ +#define mVUcacheCheck(ptr, start, limit) { \ + uptr diff = ptr - start; \ + if (diff >= limit) { \ + Console::Error("microVU Error: Program went over its cache limit. Size = 0x%x", params diff); \ + mVUreset(); \ + } \ } diff --git a/pcsx2/x86/microVU_Misc.inl b/pcsx2/x86/microVU_Misc.inl index 9810b00336..1d4f16ffba 100644 --- a/pcsx2/x86/microVU_Misc.inl +++ b/pcsx2/x86/microVU_Misc.inl @@ -302,12 +302,9 @@ microVUt(void) mVUrestoreRegs() { // Reads entire microProgram and finds out if Status Flag is Used microVUt(void) mVUcheckSflag(int progIndex) { if (CHECK_VU_FLAGHACK) { - microVU* mVU = mVUx; mVUsFlagHack = 1; for (u32 i = 0; i < mVU->progSize; i+=2) { - mVU->code = mVU->prog.prog[progIndex].data[i+1]; - mVUopU(); mVU->code = mVU->prog.prog[progIndex].data[i]; mVUopL(); }