diff --git a/pcsx2/x86/microVU_Alloc.h b/pcsx2/x86/microVU_Alloc.h index 8de5d0737c..3bf038b7c3 100644 --- a/pcsx2/x86/microVU_Alloc.h +++ b/pcsx2/x86/microVU_Alloc.h @@ -54,6 +54,7 @@ struct microAllocInfo { microTempRegInfo regsTemp; // Temp Pipeline info (used so that new pipeline info isn't conflicting between upper and lower instructions in the same cycle) u8 branch; // 0 = No Branch, 1 = B. 2 = BAL, 3~8 = Conditional Branches, 9 = JALR, 10 = JR //u8 maxStall; // Helps in computing stalls (stores the max amount of cycles to stall for the current opcodes) + //u8 divFlag; u32 cycles; // Cycles for current block u32 count; // Number of VU 64bit instructions ran (starts at 0 for each block) u32 curPC; // Current PC diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index c591e88082..0fb6a1c155 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -665,13 +665,13 @@ microVUt(void) mVUallocFMAC26b(int& ACCw, int& ACCr) { // Flag Allocators //------------------------------------------------------------------ -#define getFlagReg(regX, fInst) { \ - switch (fInst) { \ +#define getFlagReg(regX, fInst) { \ + switch (fInst) { \ case 0: regX = gprF0; break; \ case 1: regX = gprF1; break; \ case 2: regX = gprF2; break; \ case 3: regX = gprF3; break; \ - } \ + } \ } microVUt(void) mVUallocSFLAGa(int reg, int fInstance) { diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 56228309ba..2c1846c2bc 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -49,6 +49,7 @@ #define calcCycles(reg, x) { reg = ((reg > x) ? (reg - x) : 0); } #define incP() { mVU->p = (mVU->p+1) & 1; } #define incQ() { mVU->q = (mVU->q+1) & 1; } +#define doUpperOp() { mVUopU(); mVUdivSet(); } //------------------------------------------------------------------ // Helper Functions @@ -59,7 +60,7 @@ microVUt(void) mVUstatusFlagOp() { microVU* mVU = mVUx; int curPC = iPC; int i = mVUcount; - if (doStatus) { mVUinfo |= _isSflag; } + if (doStatus) { mVUinfo |= _isSflag; } else { for (; i > 0; i--) { incPC2(-2); @@ -69,7 +70,7 @@ microVUt(void) mVUstatusFlagOp() { for (; i > 0; i--) { incPC2(-2); if (isSflag) break; - mVUinfo &= ~_doStatus; + mVUinfo &= ~(_doStatus|_doDivFlag); } iPC = curPC; } @@ -96,14 +97,14 @@ microVUt(void) mVUsetFlags(int* bStatus, int* bMac) { iPC = mVUstartPC; for (int i = 0; i < xCount; i++) { if ((xCount - i) > aCount) mVUstatusFlagOp(); // Don't Optimize out on the last ~4+ instructions - if (doStatus||isFSSET) { mVUinfo |= xStatus << 12; } // _fsInstance - if (doMac) { mVUinfo |= xMac << 10; } // _fmInstance + if (doStatus||isFSSET||doDivFlag) { mVUinfo |= xStatus << 12; } // _fsInstance + if (doMac) { mVUinfo |= xMac << 10; } // _fmInstance pStatus = (xStatus + ((mVUstall > 3) ? 3 : mVUstall)) & 3; pMac = (xMac + ((mVUstall > 3) ? 3 : mVUstall)) & 3; mVUinfo |= pStatus << 18; // _fvsInstance mVUinfo |= pMac << 16; // _fvmInstance - if (doStatus||isFSSET) { xStatus = (xStatus+1) & 3; } - if (doMac) { xMac = (xMac+1) & 3; } + if (doStatus||isFSSET||doDivFlag) { xStatus = (xStatus+1) & 3; } + if (doMac) { xMac = (xMac+1) & 3; } incPC2(2); } mVUcount = xCount; // Restore count @@ -111,7 +112,7 @@ microVUt(void) mVUsetFlags(int* bStatus, int* bMac) { // Setup Last 4 instances of Status/Mac flags (needed for accurate block linking) iPC = endPC; for (int i = 3, int j = 3, int ii = 1, int jj = 3; aCount > 0; ii++, aCount--) { - if (doStatus && (i >= 0)) { + if ((doStatus||isFSSET||doDivFlag) && (i >= 0)) { for (; (ii > 0 && i >= 0); ii--) { xStatus = (xStatus-1) & 3; bStatus[i] = xStatus; i--; } } if (doMac && (j >= 0)) { @@ -172,8 +173,9 @@ microVUt(void) mVUincCycles(int x) { calcCycles(mVUregs.VI[z], x); } if (mVUregs.q) { - calcCycles(mVUregs.q, x); - if (!mVUregs.q) { incQ(); } // Do Status Flag Merging Stuff? + if (mVUregs.q > 4) { calcCycles(mVUregs.q, x); if (mVUregs.q <= 4) { mVUinfo |= _doDivFlag; } } + else { calcCycles(mVUregs.q, x); } + if (!mVUregs.q) { incQ(); } } if (mVUregs.p) { calcCycles(mVUregs.p, x); @@ -202,6 +204,15 @@ microVUt(void) mVUsetCycles() { mVUregs.xgkick = mVUregsTemp.xgkick; } +microVUt(void) mVUdivSet() { + microVU* mVU = mVUx; + int flagReg1, flagReg2; + getFlagReg(flagReg1, fsInstance); + if (!doStatus) { getFlagReg(flagReg2, fpsInstance); MOV16RtoR(flagReg1, flagReg2); } + AND16ItoR(flagReg1, 0xfcf); + OR16MtoR (flagReg1, (uptr)&mVU->divFlag); +} + //------------------------------------------------------------------ // Recompiler //------------------------------------------------------------------ @@ -254,9 +265,9 @@ microVUx(void*) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState, if (isEOB) { x = 0; } //if (isBranch2) { mVUopU(); incPC(2); } - if (isNop) { mVUopU(); if (curI & _Ibit_) { incPC(1); mVU->iReg = curI; } else { incPC(1); } } - else if (!swapOps) { mVUopU(); incPC(1); mVUopL(); } - else { incPC(1); mVUopL(); incPC(-1); mVUopU(); incPC(1); } + if (isNop) { doUpperOp(); if (curI & _Ibit_) { incPC(1); mVU->iReg = curI; } else { incPC(1); } } + else if (!swapOps) { doUpperOp(); incPC(1); mVUopL(); } + else { incPC(1); mVUopL(); incPC(-1); doUpperOp(); incPC(1); } if (!isBdelay) { incPC(1); } else { diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 61f94a8b8c..21634de639 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -474,7 +474,7 @@ microVUf(void) mVU_FCSET() { microVUf(void) mVU_FMAND() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeMflag(_Fs_, _Ft_); } else { mVUallocMFLAGa(gprT1, fvmInstance); mVUallocVIa(gprT2, _Fs_); @@ -485,7 +485,7 @@ microVUf(void) mVU_FMAND() { microVUf(void) mVU_FMEQ() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeMflag(_Fs_, _Ft_); } else { mVUallocMFLAGa(gprT1, fvmInstance); mVUallocVIa(gprT2, _Fs_); @@ -498,7 +498,7 @@ microVUf(void) mVU_FMEQ() { microVUf(void) mVU_FMOR() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeMflag(_Fs_, _Ft_); } else { mVUallocMFLAGa(gprT1, fvmInstance); mVUallocVIa(gprT2, _Fs_); @@ -547,12 +547,11 @@ microVUf(void) mVU_FSSET() { microVU* mVU = mVUx; if (!recPass) { mVUanalyzeFSSET(); } else { - int flagReg = gprT1; - if (doStatus) { getFlagReg(flagReg, fsInstance); } // Get status result from upper instruction - else { mVUallocSFLAGa(flagReg, fpsInstance); } // Get status result from last status setting instruction - AND16ItoR(flagReg, 0x03f); // Remember not to modify upper 16 bits because of mac flag - OR16ItoR(flagReg, (_Imm12_ & 0xfc0)); - if (!doStatus) { mVUallocSFLAGb(flagReg, fsInstance); } + int flagReg1, flagReg2; + getFlagReg(flagReg1, fsInstance); + if (!(doStatus||doDivFlag)) { getFlagReg(flagReg2, fpsInstance); MOV16RtoR(flagReg1, flagReg2); } // Get status result from last status setting instruction + AND16ItoR(flagReg1, 0x03f); // Remember not to modify upper 16 bits because of mac flag + OR16ItoR (flagReg1, (_Imm12_ & 0xfc0)); } } diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index c5e6c046cc..0017e98438 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -185,7 +185,9 @@ declareAllVariables #define _writesVI (1<<25) // Current Instruction writes to VI #define _swapOps (1<<26) // Runs Lower Instruction Before Upper Instruction #define _isFSSSET (1<<27) // Cur Instruction is FSSET -//#define _isBranch2 (1<<28) // Cur Instruction is a Branch that writes VI regs (BAL/JALR) +#define _doDivFlag (1<<28) // Transfer Div flag to Status Flag + +//#define _isBranch2 (1<<31) // Cur Instruction is a Branch that writes VI regs (BAL/JALR) #define isNOP (mVUinfo & (1<<0)) #define isBranch (mVUinfo & (1<<1)) @@ -214,7 +216,8 @@ declareAllVariables #define writesVI (mVUinfo & (1<<25)) #define swapOps (mVUinfo & (1<<26)) #define isFSSET (mVUinfo & (1<<27)) -//#define isBranch2 (mVUinfo & (1<<28)) +#define doDivFlag (mVUinfo & (1<<28)) +//#define isBranch2 (mVUinfo & (1<<31)) #define isMMX(_VIreg_) (_VIreg_ >= 1 && _VIreg_ <=9) #define mmVI(_VIreg_) (_VIreg_ - 1)