diff --git a/common/include/Pcsx2Config.h b/common/include/Pcsx2Config.h index c7fbdbea3b..05c1f32868 100644 --- a/common/include/Pcsx2Config.h +++ b/common/include/Pcsx2Config.h @@ -66,6 +66,7 @@ extern SessionOverrideFlags g_Session; //------------ SPECIAL GAME FIXES!!! --------------- #define CHECK_VUADDSUBHACK (Config.GameFixes & 0x1) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate. #define CHECK_FPUCOMPAREHACK (Config.GameFixes & 0x4) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu. +#define CHECK_VUCLIPFLAGHACK (Config.GameFixes & 0x2) // Special Fix for Persona games, maybe others. It's to do with the VU clip flag (again). #define CHECK_FPUMULHACK (Config.GameFixes & 0x8) // Special Fix for Tales of Destiny hangs. //------------ Advanced Options!!! --------------- #define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1) diff --git a/pcsx2/MMI.cpp b/pcsx2/MMI.cpp index d5a9784844..49b525d705 100644 --- a/pcsx2/MMI.cpp +++ b/pcsx2/MMI.cpp @@ -113,11 +113,22 @@ namespace OpcodeImpl { if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; } - void DIV1() { - if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + void DIV1() { + if (cpuRegs.GPR.r[_Rs_].UL[0] == 0x80000000 && cpuRegs.GPR.r[_Rt_].UL[0] == 0xffffffff) + { + cpuRegs.LO.SD[1] = (s32)0x80000000; + cpuRegs.HI.SD[1] = (s32)0x0; + } + else if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) + { cpuRegs.LO.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; } + else + { + cpuRegs.LO.SD[1] = (cpuRegs.GPR.r[_Rs_].SL[0] < 0) ? 1 : -1; + cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0]; + } } void DIVU1() @@ -129,6 +140,11 @@ namespace OpcodeImpl { cpuRegs.LO.SD[1] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]); cpuRegs.HI.SD[1] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]); } + else + { + cpuRegs.LO.SD[1] = -1; + cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0]; + } } namespace MMI { @@ -187,19 +203,19 @@ void PMFHL() { case 0x02: // SLW { - u64 TempU64 = ((u64)cpuRegs.HI.UL[0] << 32) | (u64)cpuRegs.LO.UL[0]; - if (TempU64 >= 0x000000007fffffffLL) { + s64 TempS64 = ((u64)cpuRegs.HI.UL[0] << 32) | (u64)cpuRegs.LO.UL[0]; + if (TempS64 >= 0x000000007fffffffLL) { cpuRegs.GPR.r[_Rd_].UD[0] = 0x000000007fffffffLL; - } else if (TempU64 <= 0xffffffff80000000LL) { + } else if (TempS64 <= 0xffffffff80000000LL) { cpuRegs.GPR.r[_Rd_].UD[0] = 0xffffffff80000000LL; } else { cpuRegs.GPR.r[_Rd_].UD[0] = (s64)cpuRegs.LO.SL[0]; } - TempU64 = ((u64)cpuRegs.HI.UL[2] << 32) | (u64)cpuRegs.LO.UL[2]; - if (TempU64 >= 0x000000007fffffffLL) { + TempS64 = ((u64)cpuRegs.HI.UL[2] << 32) | (u64)cpuRegs.LO.UL[2]; + if (TempS64 >= 0x000000007fffffffLL) { cpuRegs.GPR.r[_Rd_].UD[1] = 0x000000007fffffffLL; - } else if (TempU64 <= 0xffffffff80000000LL) { + } else if (TempS64 <= 0xffffffff80000000LL) { cpuRegs.GPR.r[_Rd_].UD[1] = 0xffffffff80000000LL; } else { cpuRegs.GPR.r[_Rd_].UD[1] = (s64)cpuRegs.LO.SL[2]; @@ -603,7 +619,7 @@ __forceinline void _PADDSB(int n) if (sTemp16 > 0x7F) cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; - else if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) + else if (sTemp16 < (s16)0xff80) cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; else cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; @@ -624,7 +640,7 @@ static __forceinline void _PSUBSB( u8 n ) if (sTemp16 >= 0x7F) cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; - else if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) + else if (sTemp16 <= (s16)0xff80) cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; else cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; @@ -727,7 +743,12 @@ void PPAC5() { __forceinline void _PABSW(int n) { - cpuRegs.GPR.r[_Rd_].UL[n] = abs(cpuRegs.GPR.r[_Rt_].SL[n]); + if (cpuRegs.GPR.r[_Rt_].UL[n] == 0x80000000) + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7fffffff; //clamp + else if (cpuRegs.GPR.r[_Rt_].SL[n] < 0) + cpuRegs.GPR.r[_Rd_].UL[n] = - cpuRegs.GPR.r[_Rt_].SL[n]; + else + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].SL[n]; } void PABSW() { @@ -773,7 +794,12 @@ void PADSBH() { __forceinline void _PABSH(int n) { - cpuRegs.GPR.r[_Rd_].US[n] = abs(cpuRegs.GPR.r[_Rt_].SS[n]); + if (cpuRegs.GPR.r[_Rt_].US[n] == 0x8000) + cpuRegs.GPR.r[_Rd_].US[n] = 0x7fff; //clamp + else if (cpuRegs.GPR.r[_Rt_].SS[n] < 0) + cpuRegs.GPR.r[_Rd_].US[n] = - cpuRegs.GPR.r[_Rt_].SS[n]; + else + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].SS[n]; } void PABSH() { @@ -994,38 +1020,39 @@ void QFSRV() { // JayteeMaster: changed a bit to avoid screw up GPR_reg Rd; if (!_Rd_) return; - if (cpuRegs.sa == 0) { + u32 sa_amt = cpuRegs.sa << 3; + if (sa_amt == 0) { cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; //saZero++; //if( saZero >= 388800 ) //Console::WriteLn( "SA Is Zero, Bitch: %d zeros and counting.", params saZero ); } else { - //Console::WriteLn( "SA Properly Valued at: %d (after %d zeros)", params cpuRegs.sa, saZero ); + //Console::WriteLn( "SA Properly Valued at: %d (after %d zeros)", params sa_amt, saZero ); //saZero = 0; - if (cpuRegs.sa < 64) { + if (sa_amt < 64) { /* - cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; - cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; - cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); - cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> sa_amt; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> sa_amt; + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - sa_amt); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - sa_amt); */ - Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; - Rd.UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; - Rd.UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); - Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> sa_amt; + Rd.UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> sa_amt; + Rd.UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - sa_amt); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - sa_amt); cpuRegs.GPR.r[_Rd_] = Rd; } else { /* - cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); - cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); - cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); - cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (sa_amt - 64); + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (sa_amt - 64); + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - sa_amt); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - sa_amt); */ - Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); - Rd.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); - Rd.UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); - Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (sa_amt - 64); + Rd.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (sa_amt - 64); + Rd.UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - sa_amt); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - sa_amt); cpuRegs.GPR.r[_Rd_] = Rd; } } @@ -1132,11 +1159,21 @@ void PMULTW() { __forceinline void _PDIVW(int dd, int ss) { - if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) + if (cpuRegs.GPR.r[_Rs_].UL[ss] == 0x80000000 && cpuRegs.GPR.r[_Rt_].UL[ss] == 0xffffffff) + { + cpuRegs.LO.SD[dd] = (s32)0x80000000; + cpuRegs.HI.SD[dd] = (s32)0; + } + else if (cpuRegs.GPR.r[_Rt_].SL[ss] != 0) { cpuRegs.LO.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] / cpuRegs.GPR.r[_Rt_].SL[ss]; cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] % cpuRegs.GPR.r[_Rt_].SL[ss]; } + else + { + cpuRegs.LO.SD[dd] = (cpuRegs.GPR.r[_Rs_].SL[ss] < 0) ? 1 : -1; + cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss]; + } } void PDIVW() { @@ -1196,18 +1233,20 @@ void PMADDH() { // JayteeMaster: changed a bit to avoid screw up // JayteeMaster: changed a bit to avoid screw up __forceinline void _PHMADH_LO(int dd, int n) { - s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] + \ - (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; + s32 firsttemp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1]; + s32 temp = firsttemp + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; cpuRegs.LO.UL[dd] = temp; + cpuRegs.LO.UL[dd+1] = firsttemp; } __forceinline void _PHMADH_HI(int dd, int n) { - s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] + \ - (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; + s32 firsttemp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1]; + s32 temp = firsttemp + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; cpuRegs.HI.UL[dd] = temp; + cpuRegs.HI.UL[dd+1] = firsttemp; } void PHMADH() { // JayteeMaster: changed a bit to avoid screw up. Also used 0,2,4,6 instead of 0,1,2,3 @@ -1279,17 +1318,19 @@ void PMSUBH() { // JayteeMaster: changed a bit to avoid screw up // JayteeMaster: changed a bit to avoid screw up __forceinline void _PHMSBH_LO(int dd, int n, int rdd) { - s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] - \ - (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; + s32 firsttemp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1]; + s32 temp = firsttemp - (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; cpuRegs.LO.UL[dd] = temp; + cpuRegs.LO.UL[dd+1] = ~firsttemp; } __forceinline void _PHMSBH_HI(int dd, int n, int rdd) { - s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] - \ - (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; + s32 firsttemp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1]; + s32 temp = firsttemp - (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; cpuRegs.HI.UL[dd] = temp; + cpuRegs.HI.UL[dd+1] = ~firsttemp; } void PHMSBH() { // JayteeMaster: changed a bit to avoid screw up @@ -1378,13 +1419,24 @@ void PMULTH() { // JayteeMaster: changed a bit to avoid screw up __forceinline void _PDIVBW(int n) { - cpuRegs.LO.UL[n] = (s32)(cpuRegs.GPR.r[_Rs_].SL[n] / cpuRegs.GPR.r[_Rt_].SS[0]); - cpuRegs.HI.UL[n] = (s16)(cpuRegs.GPR.r[_Rs_].SL[n] % cpuRegs.GPR.r[_Rt_].SS[0]); + if (cpuRegs.GPR.r[_Rs_].UL[n] == 0x80000000 && cpuRegs.GPR.r[_Rt_].US[0] == 0xffff) + { + cpuRegs.LO.SL[n] = (s32)0x80000000; + cpuRegs.HI.SL[n] = (s32)0x0; + } + else if (cpuRegs.GPR.r[_Rt_].US[0] != 0) + { + cpuRegs.LO.SL[n] = cpuRegs.GPR.r[_Rs_].SL[n] / cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.HI.SL[n] = cpuRegs.GPR.r[_Rs_].SL[n] % cpuRegs.GPR.r[_Rt_].SS[0]; + } + else + { + cpuRegs.LO.SL[n] = (cpuRegs.GPR.r[_Rs_].SL[n] < 0) ? 1 : -1; + cpuRegs.HI.SL[n] = cpuRegs.GPR.r[_Rs_].SL[n]; + } } void PDIVBW() { - if (cpuRegs.GPR.r[_Rt_].US[0] == 0) return; - _PDIVBW(0); _PDIVBW(1); _PDIVBW(2); _PDIVBW(3); } @@ -1489,6 +1541,11 @@ __forceinline void _PDIVUW(int dd, int ss) cpuRegs.LO.SD[dd] = (s32)(cpuRegs.GPR.r[_Rs_].UL[ss] / cpuRegs.GPR.r[_Rt_].UL[ss]); cpuRegs.HI.SD[dd] = (s32)(cpuRegs.GPR.r[_Rs_].UL[ss] % cpuRegs.GPR.r[_Rt_].UL[ss]); } + else + { + cpuRegs.LO.SD[dd] = -1; + cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss]; + } } void PDIVUW() { diff --git a/pcsx2/R5900OpcodeImpl.cpp b/pcsx2/R5900OpcodeImpl.cpp index d938fc6d62..15b7c792c0 100644 --- a/pcsx2/R5900OpcodeImpl.cpp +++ b/pcsx2/R5900OpcodeImpl.cpp @@ -247,14 +247,29 @@ void SLTU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rs * Format: OP rs, rt * *********************************************************/ +// Signed division "overflows" on (0x80000000 / -1), here (LO = 0x80000000, HI = 0) is returned by MIPS +// in division by zero on MIPS, it appears that: +// LO gets 1 if rs is negative (and the division is signed) and -1 otherwise. +// HI gets the value of rs. + // Result is stored in HI/LO [no arithmetic exceptions] void DIV() { - if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) + if (cpuRegs.GPR.r[_Rs_].UL[0] == 0x80000000 && cpuRegs.GPR.r[_Rt_].UL[0] == 0xffffffff) + { + cpuRegs.LO.SD[0] = (s32)0x80000000; + cpuRegs.HI.SD[0] = (s32)0x0; + } + else if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; } + else + { + cpuRegs.LO.SD[0] = (cpuRegs.GPR.r[_Rs_].SL[0] < 0) ? 1 : -1; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0]; + } } // Result is stored in HI/LO [no arithmetic exceptions] @@ -267,6 +282,11 @@ void DIVU() cpuRegs.LO.SD[0] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]); cpuRegs.HI.SD[0] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]); } + else + { + cpuRegs.LO.SD[0] = -1; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0]; + } } // Result is written to both HI/LO and to the _Rd_ (Lo only) @@ -858,7 +878,7 @@ void MFSA( void ) { } void MTSA( void ) { - cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0]; + cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0] & 0xf; } // SNY supports three basic modes, two which synchronize memory accesses (related @@ -907,11 +927,11 @@ void TLTIU() { if (cpuRegs.GPR.r[_Rs_].UD[0] < (u64)_Imm_) throw R5900Exception *********************************************************/ void MTSAB() { - cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3; + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)); } void MTSAH() { - cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4; + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 1; } } } } // end namespace R5900::Interpreter::OpcodeImpl diff --git a/pcsx2/windows/WinMain.cpp b/pcsx2/windows/WinMain.cpp index 0b8dbfd2ec..de6b3a953b 100644 --- a/pcsx2/windows/WinMain.cpp +++ b/pcsx2/windows/WinMain.cpp @@ -525,6 +525,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_INITDIALOG: if(Config.GameFixes & 0x1) CheckDlgButton(hDlg, IDC_GAMEFIX2, TRUE);//Tri-Ace fix if(Config.GameFixes & 0x4) CheckDlgButton(hDlg, IDC_GAMEFIX3, TRUE);//Digimon FPU compare fix + if(Config.GameFixes & 0x2) CheckDlgButton(hDlg, IDC_GAMEFIX4, TRUE);//Persona3/4 fix if(Config.GameFixes & 0x8) CheckDlgButton(hDlg, IDC_GAMEFIX5, TRUE);//Tales of Destiny fix return TRUE; @@ -534,6 +535,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) uint newfixes = 0; newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x1 : 0; newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX3) ? 0x4 : 0; + newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX4) ? 0x2 : 0; newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX5) ? 0x8 : 0; EndDialog(hDlg, TRUE); diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc index 523f912ea4..689657cc2f 100644 --- a/pcsx2/windows/pcsx2.rc +++ b/pcsx2/windows/pcsx2.rc @@ -74,21 +74,23 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN // Dialog // -IDD_GAMEFIXES DIALOGEX 0, 0, 279, 118 +IDD_GAMEFIXES DIALOGEX 0, 0, 279, 123 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Game Special Fixes" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "OK",IDOK,87,89,50,14 - PUSHBUTTON "Cancel",IDCANCEL,142,89,50,14 + DEFPUSHBUTTON "OK",IDOK,87,96,50,14 + PUSHBUTTON "Cancel",IDCANCEL,142,96,50,14 CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,265,17 - GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,28,265,83 + GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,22,265,94 CONTROL "FPU Compare Hack - Special fix for Digimon Rumble Arena 2.",IDC_GAMEFIX3, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,43,249,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,36,249,10 CONTROL "VU Add Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,72,252,10 + "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, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,57,249,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,50,249,10 END @@ -106,7 +108,7 @@ BEGIN RIGHTMARGIN, 272 VERTGUIDE, 14 TOPMARGIN, 7 - BOTTOMMARGIN, 111 + BOTTOMMARGIN, 116 HORZGUIDE, 103 END END diff --git a/pcsx2/x86/iMMI.cpp b/pcsx2/x86/iMMI.cpp index 2ffd8f789e..8c76caefbd 100644 --- a/pcsx2/x86/iMMI.cpp +++ b/pcsx2/x86/iMMI.cpp @@ -1617,23 +1617,29 @@ REC_FUNC_DEL( QFSRV, _Rd_); PCSX2_ALIGNED16(int s_MaskHighBitD[4]) = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; PCSX2_ALIGNED16(int s_MaskHighBitW[4]) = { 0x80008000, 0x80008000, 0x80008000, 0x80008000 }; -void recPABSW() +void recPABSW() //needs clamping { if( !_Rd_ ) return; CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM(t0reg, t0reg); + SSE2_PSLLD_I8_to_XMM(t0reg, 31); + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); //0xffffffff if equal to 0x80000000 if( cpucaps.hasSupplementalStreamingSIMD3Extensions ) { - SSSE3_PABSD_XMM_to_XMM(EEREC_D, EEREC_T); + SSSE3_PABSD_XMM_to_XMM(EEREC_D, EEREC_T); //0x80000000 -> 0x80000000 } else { - int t0reg = _allocTempXMMreg(XMMT_INT, -1); - SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSRAD_I8_to_XMM(t0reg, 31); - SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); - SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); - _freeXMMreg(t0reg); + SSE2_PSRAD_I8_to_XMM(t1reg, 31); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t1reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t1reg); //0x80000000 -> 0x80000000 + _freeXMMreg(t1reg); } + SSE2_PXOR_XMM_to_XMM(EEREC_D, t0reg); //0x80000000 -> 0x7fffffff + _freeXMMreg(t0reg); CPU_SSE_XMMCACHE_END _deleteEEreg(_Rt_, 1); @@ -1645,24 +1651,31 @@ CPU_SSE_XMMCACHE_END CALLFunc( (uptr)R5900::Interpreter::OpcodeImpl::MMI::PABSW ); } + //////////////////////////////////////////////////// -void recPABSH() +void recPABSH() { if( !_Rd_ ) return; CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQW_XMM_to_XMM(t0reg, t0reg); + SSE2_PSLLW_I8_to_XMM(t0reg, 15); + SSE2_PCMPEQW_XMM_to_XMM(t0reg, EEREC_T); //0xffff if equal to 0x8000 if( cpucaps.hasSupplementalStreamingSIMD3Extensions ) { - SSSE3_PABSW_XMM_to_XMM(EEREC_D, EEREC_T); + SSSE3_PABSW_XMM_to_XMM(EEREC_D, EEREC_T); //0x8000 -> 0x8000 } else { - int t0reg = _allocTempXMMreg(XMMT_INT, -1); - SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSRAW_I8_to_XMM(t0reg, 15); - SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); - SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); - _freeXMMreg(t0reg); + SSE2_PSRAW_I8_to_XMM(t1reg, 15); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t1reg); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t1reg); //0x8000 -> 0x8000 + _freeXMMreg(t1reg); } + SSE2_PXOR_XMM_to_XMM(EEREC_D, t0reg); //0x8000 -> 0x7fff + _freeXMMreg(t0reg); CPU_SSE_XMMCACHE_END _deleteEEreg(_Rt_, 1); @@ -1968,7 +1981,7 @@ void recQFSRV() SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); MOV32MtoR(EAX, (uptr)&cpuRegs.sa); - SHL32ItoR(EAX, 1); // Multiply SA bytes by 16 bytes (the amount of bytes in QFSRVhelper() macros) + SHL32ItoR(EAX, 4); // Multiply SA bytes by 16 bytes (the amount of bytes in QFSRVhelper() macros) AND32I8toR(EAX, 0xf0); // This can possibly be removed but keeping it incase theres garbage in SA (cottonvibes) ADD32ItoEAX((uptr)x86Ptr[0] + 7); // ADD32 = 5 bytes, JMPR = 2 bytes JMPR(EAX); // Jumps to a QFSRVhelper() case below (a total of 16 different cases) @@ -2402,8 +2415,8 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR // shamt is 5-bit SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); - SSE2_PSLLQ_I8_to_XMM(t0reg, 27); - SSE2_PSRLQ_I8_to_XMM(t0reg, 27); + SSE2_PSLLQ_I8_to_XMM(t0reg, 27+32); + SSE2_PSRLQ_I8_to_XMM(t0reg, 27+32); // EEREC_D[0] <- Rt[0], t1reg[0] <- Rt[2] SSE_MOVHLPS_XMM_to_XMM(t1reg, EEREC_T); @@ -2470,8 +2483,8 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR // shamt is 5-bit SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); - SSE2_PSLLQ_I8_to_XMM(t0reg, 27); - SSE2_PSRLQ_I8_to_XMM(t0reg, 27); + SSE2_PSLLQ_I8_to_XMM(t0reg, 27+32); + SSE2_PSRLQ_I8_to_XMM(t0reg, 27+32); // EEREC_D[0] <- Rt[0], t1reg[0] <- Rt[2] SSE_MOVHLPS_XMM_to_XMM(t1reg, EEREC_T); @@ -2619,9 +2632,18 @@ void recPDIVBW() //////////////////////////////////////////////////// PCSX2_ALIGNED16(int s_mask1[4]) = {~0, 0, ~0, 0}; +//upper word of each doubleword in LO and HI is undocumented/undefined +//contains the upper multiplication result (before the addition with the lower multiplication result) void recPHMADH() { CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSRLD_I8_to_XMM(t0reg, 16); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_PMADDWD_XMM_to_XMM(t0reg, EEREC_T); + if( _Rd_ ) { if( EEREC_D == EEREC_S ) { SSE2_PMADDWD_XMM_to_XMM(EEREC_D, EEREC_T); @@ -2641,14 +2663,22 @@ CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMI } SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); - SSE2_PSRLQ_I8_to_XMM(EEREC_HI, 32); + SSE_SHUFPS_XMM_to_XMM(EEREC_LO, t0reg, 0x88); + SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); + + SSE_SHUFPS_XMM_to_XMM(EEREC_HI, t0reg, 0xdd); + SSE_SHUFPS_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); + + _freeXMMreg(t0reg); CPU_SSE_XMMCACHE_END recCall( Interp::PHMADH, _Rd_ ); } //////////////////////////////////////////////////// +//upper word of each doubleword in LO and HI is undocumented/undefined +//contains the NOT of the upper multiplication result (before the substraction of the lower multiplication result) void recPMSUBH() { CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) @@ -2710,22 +2740,41 @@ CPU_SSE_XMMCACHE_END } //////////////////////////////////////////////////// + +// rs = ... a1 a0 +// rt = ... b1 b0 +// rd = ... a1*b1 - a0*b0 +// hi = ... +// lo = ... (undefined by doc)NOT(a1*b1), a1*b1 - a0*b0 void recPHMSBH() { CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM(EEREC_LO, EEREC_LO); - SSE2_PSRLD_XMM_to_XMM(EEREC_LO, 16); + SSE2_PSRLD_I8_to_XMM(EEREC_LO, 16); SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); SSE2_PAND_XMM_to_XMM(EEREC_HI, EEREC_LO); SSE2_PMADDWD_XMM_to_XMM(EEREC_HI, EEREC_T); - SSE2_PSLLD_XMM_to_XMM(EEREC_LO, 16); + SSE2_PSLLD_I8_to_XMM(EEREC_LO, 16); SSE2_PAND_XMM_to_XMM(EEREC_LO, EEREC_S); SSE2_PMADDWD_XMM_to_XMM(EEREC_LO, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); SSE2_PSUBD_XMM_to_XMM(EEREC_LO, EEREC_HI); if( _Rd_ ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PCMPEQD_XMM_to_XMM(EEREC_HI, EEREC_HI); + SSE2_PXOR_XMM_to_XMM(t0reg, EEREC_HI); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); - SSE2_PSRLQ_I8_to_XMM(EEREC_HI, 32); + + SSE_SHUFPS_XMM_to_XMM(EEREC_LO, t0reg, 0x88); + SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); + + SSE_SHUFPS_XMM_to_XMM(EEREC_HI, t0reg, 0xdd); + SSE_SHUFPS_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); + + _freeXMMreg(t0reg); CPU_SSE_XMMCACHE_END recCall( Interp::PHMSBH, _Rd_ ); @@ -3278,8 +3327,8 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR // shamt is 5-bit SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); - SSE2_PSLLQ_I8_to_XMM(t0reg, 27); - SSE2_PSRLQ_I8_to_XMM(t0reg, 27); + SSE2_PSLLQ_I8_to_XMM(t0reg, 27+32); + SSE2_PSRLQ_I8_to_XMM(t0reg, 27+32); // EEREC_D[0] <- Rt[0], t1reg[0] <- Rt[2] SSE_MOVHLPS_XMM_to_XMM(t1reg, EEREC_T); diff --git a/pcsx2/x86/iR5900Misc.cpp b/pcsx2/x86/iR5900Misc.cpp index 1580c54658..e496a1d311 100644 --- a/pcsx2/x86/iR5900Misc.cpp +++ b/pcsx2/x86/iR5900Misc.cpp @@ -94,10 +94,11 @@ void recMFSA( void ) } } +// SA is 4-bit and contains the amount of bytes to shift void recMTSA( void ) { if( GPR_IS_CONST1(_Rs_) ) { - MOV32ItoM((uptr)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM((uptr)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] & 0xf ); } else { int mmreg; @@ -113,19 +114,19 @@ void recMTSA( void ) MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); MOV32RtoM((uptr)&cpuRegs.sa, EAX); } + AND32ItoM((uptr)&cpuRegs.sa, 0xf); } } void recMTSAB( void ) { if( GPR_IS_CONST1(_Rs_) ) { - MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3); + MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) ); } else { _eeMoveGPRtoR(EAX, _Rs_); AND32ItoR(EAX, 0xF); XOR32ItoR(EAX, _Imm_&0xf); - SHL32ItoR(EAX, 3); MOV32RtoM((uptr)&cpuRegs.sa, EAX); } } @@ -133,13 +134,13 @@ void recMTSAB( void ) void recMTSAH( void ) { if( GPR_IS_CONST1(_Rs_) ) { - MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4); + MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 1); } else { _eeMoveGPRtoR(EAX, _Rs_); AND32ItoR(EAX, 0x7); XOR32ItoR(EAX, _Imm_&0x7); - SHL32ItoR(EAX, 4); + SHL32ItoR(EAX, 1); MOV32RtoM((uptr)&cpuRegs.sa, EAX); } } diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp index f4998b113e..e8e4b06efb 100644 --- a/pcsx2/x86/iVUzerorec.cpp +++ b/pcsx2/x86/iVUzerorec.cpp @@ -3000,7 +3000,7 @@ void VuInstruction::Recompile(list::iterator& itinst, u32 vuxyz) if( type & INST_CLIP_WRITE ) { if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) { - if( pparentinst != NULL ) { + if( !CHECK_VUCLIPFLAGHACK && pparentinst != NULL ) { if( nParentCheckForExecution >= 0 ) { if( pparentinst->pClipWrite == 0 ) diff --git a/pcsx2/x86/ix86-32/iR5900MultDiv.cpp b/pcsx2/x86/ix86-32/iR5900MultDiv.cpp index 2e261546ba..854837f898 100644 --- a/pcsx2/x86/ix86-32/iR5900MultDiv.cpp +++ b/pcsx2/x86/ix86-32/iR5900MultDiv.cpp @@ -595,14 +595,31 @@ void recMULTU1_constt(int info) EERECOMPILE_CODE0(MULTU1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); //// DIV + +void recDIVconst(int upper) +{ + s32 quot, rem; + if (g_cpuConstRegs[_Rs_].UL[0] == 0x80000000 && g_cpuConstRegs[_Rt_].SL[0] == -1) + { + quot = (s32)0x80000000; + rem = 0; + } + else if (g_cpuConstRegs[_Rt_].SL[0] != 0) + { + quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + } + else + { + quot = (g_cpuConstRegs[_Rs_].SL[0] < 0) ? 1 : -1; + rem = g_cpuConstRegs[_Rs_].SL[0]; + } + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, upper); +} + void recDIV_const() { - if (g_cpuConstRegs[_Rt_].SL[0] != 0) { - s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; - s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; - - recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); - } + recDIVconst(0); } void recDIVsuper(int info, int sign, int upper, int process) @@ -610,24 +627,46 @@ void recDIVsuper(int info, int sign, int upper, int process) EEINST_SETSIGNEXT(_Rs_); EEINST_SETSIGNEXT(_Rt_); - if( process & PROCESS_CONSTT ) { - if( !g_cpuConstRegs[_Rt_].UL[0] ) - return; + if( process & PROCESS_CONSTT ) MOV32ItoR( ECX, g_cpuConstRegs[_Rt_].UL[0] ); - } - else { + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); - OR32RtoR( ECX, ECX ); - j8Ptr[ 0 ] = JE8( 0 ); - } - if( process & PROCESS_CONSTS ) MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); - else { + else MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + u8 *end1; + if (sign) //test for overflow (x86 will just throw an exception) + { + CMP32ItoR( EAX, 0x80000000 ); + u8 *cont1 = JNE8(0); + CMP32ItoR( ECX, 0xffffffff ); + u8 *cont2 = JNE8(0); + //overflow case: + XOR32RtoR( EDX, EDX ); //EAX remains 0x80000000 + end1 = JMP8(0); + + x86SetJ8(cont1); + x86SetJ8(cont2); } + CMP32ItoR( ECX, 0 ); + u8 *cont3 = JNE8(0); + //divide by zero + MOV32RtoR( EDX, EAX ); + if (sign) //set EAX to (EAX < 0)?1:-1 + { + SAR32ItoR( EAX, 31 ); //(EAX < 0)?-1:0 + SHL32ItoR( EAX, 1 ); //(EAX < 0)?-2:0 + NOT32R( EAX ); //(EAX < 0)?1:-1 + } + else + MOV32ItoR( EAX, 0xffffffff ); + u8 *end2 = JMP8(0); + + x86SetJ8(cont3); if( sign ) { CDQ(); IDIV32R( ECX ); @@ -636,7 +675,9 @@ void recDIVsuper(int info, int sign, int upper, int process) XOR32RtoR( EDX, EDX ); DIV32R( ECX ); } - if( !(process & PROCESS_CONSTT) ) x86SetJ8( j8Ptr[ 0 ] ); + + if (sign) x86SetJ8( end1 ); + x86SetJ8( end2 ); // need to execute regardless of bad divide recWritebackHILO(info, 0, upper); @@ -660,14 +701,25 @@ void recDIV_constt(int info) EERECOMPILE_CODE0(DIV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); //// DIVU +void recDIVUconst(int upper) +{ + u32 quot, rem; + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + } + else + { + quot = 0xffffffff; + rem = g_cpuConstRegs[_Rs_].UL[0]; + } + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, upper); +} + void recDIVU_const() { - if (g_cpuConstRegs[_Rt_].UL[0] != 0) { - u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; - u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; - - recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); - } + recDIVUconst(0); } void recDIVU_(int info) @@ -689,12 +741,7 @@ EERECOMPILE_CODE0(DIVU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRIT void recDIV1_const() { - if (g_cpuConstRegs[_Rt_].SL[0] != 0) { - s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; - s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; - - recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); - } + recDIVconst(1); } void recDIV1_(int info) @@ -716,12 +763,7 @@ EERECOMPILE_CODE0(DIV1, XMMINFO_READS|XMMINFO_READT); void recDIVU1_const() { - if (g_cpuConstRegs[_Rt_].UL[0] != 0) { - u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; - u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; - - recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); - } + recDIVUconst(1); } void recDIVU1_(int info)