diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc index 689657cc2f..63316593a2 100644 --- a/pcsx2/windows/pcsx2.rc +++ b/pcsx2/windows/pcsx2.rc @@ -89,7 +89,7 @@ BEGIN "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,65,252,10 CONTROL "VU Clip Hack - Fixes missing ground geometry in Persona.",IDC_GAMEFIX4, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,79,238,10 - CONTROL "FPU Mul Hack - Special fix for Tales of Destiny (possibly other games).",IDC_GAMEFIX5, + CONTROL "FPU Mul Hack - Special fix for Tales of Destiny.",IDC_GAMEFIX5, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,50,249,10 END diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 2c4911bfd1..4613a13acb 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -266,13 +266,13 @@ __declspec(naked) void __fastcall endVU0(u32 startPC, u32 cycles) { } } #else -extern "C" -{ -extern void __fastcall startVU0(u32 startPC, u32 cycles); -extern void __fastcall startVU1(u32 startPC, u32 cycles); -extern void __fastcall endVU0(u32 startPC, u32 cycles); +extern "C" { + extern void __fastcall startVU0(u32 startPC, u32 cycles); + extern void __fastcall startVU1(u32 startPC, u32 cycles); + extern void __fastcall endVU0(u32 startPC, u32 cycles); } #endif + //------------------------------------------------------------------ // Wrapper Functions - Called by other parts of the Emu //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 6ed5809f53..c37a084043 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -125,7 +125,7 @@ struct microVU { u32 code; // Contains the current Instruction u32 iReg; // iReg (only used in recompilation, not execution) u32 clipFlag[4]; // 4 instances of clip flag (used in execution) - u32 divFlag[2]; // 2 Instances of I/D flags + u32 divFlag; // 1 instance of I/D flags /* uptr x86eax; // Accumulator register. Used in arithmetic operations. diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index d2691245ae..ca6cee9e09 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -508,10 +508,6 @@ microVUt(void) mVUallocFMAC17a(int& Fs, int& Ft) { getReg9(Ft, _Ft_); } -microVUt(void) mVUallocFMAC17b(int& ACC, int& Fs) { - //mVUallocFMAC4b(ACC, Fs); -} - //------------------------------------------------------------------ // FMAC18 - OPMULA FMAC Opcode //------------------------------------------------------------------ @@ -678,20 +674,10 @@ microVUt(void) mVUallocFMAC26b(int& ACCw, int& ACCr) { } \ } -microVUt(void) mVUallocSFLAGa(int reg, int fInstance, bool mergeDivFlag) { +microVUt(void) mVUallocSFLAGa(int reg, int fInstance) { microVU* mVU = mVUx; getFlagReg(fInstance, fInstance); MOVZX32R16toR(reg, fInstance); - if (mergeDivFlag) { - if (mVUdivFlag && !mVUdivFlagT) { - AND32ItoR(reg, 0xc00); - if (mVUdivFlag > 1) { OR32ItoR(reg, (u32)((mVUdivFlag << 9) & 0xc00)); } - } - else { - AND32ItoR(reg, 0x30); - OR32MtoR(reg, (uptr)&mVU->divFlag[readQ]); - } - } } microVUt(void) mVUallocSFLAGb(int reg, int fInstance) { @@ -722,19 +708,19 @@ microVUt(void) mVUallocCFLAGb(int reg, int fInstance) { microVU* mVU = mVUx; MOV32RtoM(mVU->clipFlag[fInstance], reg); } - +/* microVUt(void) mVUallocDFLAGa(int reg) { microVU* mVU = mVUx; - if (!mVUdivFlag) { MOV32MtoR(reg, (uptr)&mVU->divFlag[readQ]); AND32ItoR(reg, 0xc00); } - else if (mVUdivFlag & 1) { XOR32RtoR(reg, reg); } - else { MOV32ItoR(reg, (u32)((mVUdivFlag << 9) & 0xc00)); } + //if (!mVUdivFlag) { MOV32MtoR(reg, (uptr)&mVU->divFlag[readQ]); AND32ItoR(reg, 0xc00); } + //else if (mVUdivFlag & 1) { XOR32RtoR(reg, reg); } + //else { MOV32ItoR(reg, (u32)((mVUdivFlag << 9) & 0xc00)); } } microVUt(void) mVUallocDFLAGb(int reg) { microVU* mVU = mVUx; - MOV32RtoM((uptr)&mVU->divFlag[writeQ], reg); + //MOV32RtoM((uptr)&mVU->divFlag[writeQ], reg); } - +*/ //------------------------------------------------------------------ // VI Reg Allocators //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 5acfae6eef..e07dff38e8 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -57,6 +57,7 @@ microVUt(void) mVUsetCycles() { microVUx(void) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState, u8* x86ptrStart) { microVU* mVU = mVUx; microBlock block; + int branch; iPC = startPC / 4; // Searches for Existing Compiled Block (if found, then returns; else, compile) @@ -65,30 +66,32 @@ microVUx(void) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState, // First Pass setCode(); + branch = 0; + mVUbranch = 0; mVUcycles = 1; // Skips "M" phase, and starts counting cycles at "T" stage for (;;) { startLoop(); mVUopU(); - if (curI & _Ebit_) { mVUbranch = 5; } - if (curI & _MDTbit_) { mVUbranch = 4; } - if (curI & _Ibit_) { incPC(1); mVUinfo |= _isNOP; } - else { incPC(1); mVUopL(); } + if (curI & _Ebit_) { branch = 1; } + if (curI & _MDTbit_) { branch = 2; } + if (curI & _Ibit_) { incPC(1); mVUinfo |= _isNOP; } + else { incPC(1); mVUopL(); } mVUsetCycles(); - if (mVUbranch == 4) { mVUbranch = 0; mVUinfo |= _isEOB; break; } - else if (mVUbranch == 5) { mVUbranch = 4; } - else if (mVUbranch) { mVUbranch = 4; mVUinfo |= _isBranch; } + if (branch >= 2) { mVUinfo |= _isEOB | ((branch == 3) ? _isBdelay : 0); if (mVUbranch) { Console::Error("microVU Warning: Branch in E-bit/Branch delay slot!"); mVUinfo |= _isNOP; } break; } + else if (branch == 1) { branch = 2; } + if (mVUbranch) { branch = 3; mVUbranch = 0; mVUinfo |= _isBranch; } incPC(1); } // Second Pass iPC = startPC; setCode(); - for (bool x = 1; x==1; ) { + for (bool x = 1; x; ) { if (isEOB) { x = 0; } else if (isBranch) { mVUopU(); incPC(2); } mVUopU(); - if (isNop) { incPC(1); } + if (isNop) { if (curI & _Ibit_) { incPC(1); mVU->iReg = curI; } else { incPC(1); } } else { incPC(1); mVUopL(); } if (!isBdelay) { incPC(1); } else { diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index af97294e09..0a234dfc8e 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -32,7 +32,6 @@ microVUf(void) mVU_DIV() { getReg5(xmmFs, _Fs_, _Fsf_); getReg5(xmmFt, _Ft_, _Ftf_); - mVUallocDFLAGa(gprT2); // Get DS/IS flags // FT can be zero here! so we need to check if its zero and set the correct flag. SSE_XORPS_XMM_to_XMM(xmmT1, xmmT1); // Clear xmmT1 @@ -47,10 +46,10 @@ microVUf(void) mVU_DIV() { AND32ItoR(gprT1, 1); // Grab "Is Zero" bits from the previous calculation pjmp = JZ8(0); - OR32ItoR(gprT2, 0x410); // Set invalid flag (0/0) + MOV32ItoM((uptr)&mVU->divFlag, 0x410); // Set invalid flag (0/0) pjmp1 = JMP8(0); x86SetJ8(pjmp); - OR32ItoR(gprT2, 0x820); // Zero divide (only when not 0/0) + MOV32ItoM((uptr)&mVU->divFlag, 0x820); // Zero divide (only when not 0/0) x86SetJ8(pjmp1); SSE_XORPS_XMM_to_XMM(xmmFs, xmmFt); @@ -60,6 +59,7 @@ microVUf(void) mVU_DIV() { bjmp32 = JMP32(0); x86SetJ32(ajmp32); + MOV32ItoM((uptr)&mVU->divFlag, 0); // Clear I/D flags SSE_DIVSS_XMM_to_XMM(xmmFs, xmmFt); mVUclamp1(xmmFs, xmmFt, 8); @@ -67,7 +67,6 @@ microVUf(void) mVU_DIV() { mVUunpack_xyzw(xmmFs, xmmFs, 0); mVUmergeRegs(xmmPQ, xmmFs, writeQ ? 4 : 8); - mVUallocDFLAGb(gprT2); } } microVUf(void) mVU_SQRT() { @@ -478,7 +477,7 @@ microVUf(void) mVU_FSAND() { microVU* mVU = mVUx; if (!recPass) {} else { - mVUallocSFLAGa(gprT1, fvsInstance, !!(_Imm12_ & 0xc30)); + mVUallocSFLAGa(gprT1, fvsInstance); AND16ItoR(gprT1, _Imm12_); mVUallocVIb(gprT1, _Ft_); } @@ -487,7 +486,7 @@ microVUf(void) mVU_FSEQ() { microVU* mVU = mVUx; if (!recPass) {} else { - mVUallocSFLAGa(gprT1, fvsInstance, 1); + mVUallocSFLAGa(gprT1, fvsInstance); XOR16ItoR(gprT1, _Imm12_); SUB16ItoR(gprT1, 1); SHR16ItoR(gprT1, 15); @@ -498,21 +497,21 @@ microVUf(void) mVU_FSOR() { microVU* mVU = mVUx; if (!recPass) {} else { - mVUallocSFLAGa(gprT1, fvsInstance, !!((_Imm12_ & 0xc30) == 0xc30)); + mVUallocSFLAGa(gprT1, fvsInstance); OR16ItoR(gprT1, _Imm12_); mVUallocVIb(gprT1, _Ft_); } } microVUf(void) mVU_FSSET() { microVU* mVU = mVUx; - if (!recPass) { mVUdivFlagT = 4; } + if (!recPass) {} else { int flagReg; getFlagReg(flagReg, fsInstance); MOV16ItoR(gprT1, (_Imm12_ & 0xfc0)); - if (_Imm12_ & 0xc00) { mVUdivFlag = _Imm12_ >> 9; } - else { mVUdivFlag = 1; } - mVUdivFlagT = 4; + //if (_Imm12_ & 0xc00) { mVUdivFlag = _Imm12_ >> 9; } + //else { mVUdivFlag = 1; } + //mVUdivFlagT = 4; } } diff --git a/pcsx2/x86/microVU_Upper.inl b/pcsx2/x86/microVU_Upper.inl index 22496011b8..1b02f1f37e 100644 --- a/pcsx2/x86/microVU_Upper.inl +++ b/pcsx2/x86/microVU_Upper.inl @@ -22,7 +22,9 @@ // mVUupdateFlags() - Updates status/mac flags //------------------------------------------------------------------ -#define AND_XYZW ((_XYZW_SS && modXYZW) ? (1) : (doMac ? (_X_Y_Z_W) : (flipMask[_X_Y_Z_W]))) +#define AND_XYZW ((_XYZW_SS && modXYZW) ? (1) : (doMac ? (_X_Y_Z_W) : (flipMask[_X_Y_Z_W]))) +#define ADD_XYZW ((_XYZW_SS && modXYZW) ? (_X ? 3 : (_Y ? 2 : (_Z ? 1 : 0))) : 0) +#define SHIFT_XYZW(gprReg) { if (_XYZW_SS && modXYZW && !_W) { SHL16ItoR(gprReg, ADD_XYZW); } } // Note: If modXYZW is true, then it adjusts XYZW for Single Scalar operations microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modXYZW) { @@ -31,14 +33,12 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX static u8 *pjmp, *pjmp2; static const int flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}; - //SysPrintf ("mVUupdateFlags\n"); - if( !(doFlags) ) return; - + if (!doFlags) return; if (!doMac) { regT1 = reg; } - else SSE2_PSHUFD_XMM_to_XMM(regT1, reg, 0x1B); // Flip wzyx to xyzw + else { SSE2_PSHUFD_XMM_to_XMM(regT1, reg, 0x1B); } // Flip wzyx to xyzw if (doStatus) { getFlagReg(sReg, fsInstance); // Set sReg to valid GPR by Cur Flag Instance - mVUallocSFLAGa(sReg, fpsInstance, 0); // Get Prev Status Flag + mVUallocSFLAGa(sReg, fpsInstance); // Get Prev Status Flag AND16ItoR(sReg, 0xff0); // Keep Sticky and D/I flags } @@ -54,7 +54,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX AND16ItoR(mReg, AND_XYZW ); // Grab "Is Signed" bits from the previous calculation pjmp = JZ8(0); // Skip if none are - if (doMac) SHL16ItoR(mReg, 4); + if (doMac) SHL16ItoR(mReg, 4 + ADD_XYZW); if (doStatus) OR16ItoR(sReg, 0x82); // SS, S flags if (_XYZW_SS) pjmp2 = JMP8(0); // If negative and not Zero, we can skip the Zero Flag checking x86SetJ8(pjmp); @@ -63,11 +63,11 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX AND16ItoR(gprT2, AND_XYZW ); // Grab "Is Zero" bits from the previous calculation pjmp = JZ8(0); // Skip if none are - if (doMac) OR32RtoR(mReg, gprT2); - if (doStatus) OR16ItoR(sReg, 0x41); // ZS, Z flags + if (doMac) { SHIFT_XYZW(gprT2); OR32RtoR(mReg, gprT2); } + if (doStatus) { OR16ItoR(sReg, 0x41); } // ZS, Z flags x86SetJ8(pjmp); - //-------------------------Finally: Send the Flags to the Mac Flag Address------------------------------ + //-------------------------Write back flags------------------------------ if (_XYZW_SS) x86SetJ8(pjmp2); // If we skipped the Zero Flag Checking, return here