From 2e276316c6adcbe879e1dd6d10845365b54e91d1 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" <sudonim1@gmail.com@96395faa-99c1-11dd-bbfe-3dabce05a288> Date: Tue, 11 Oct 2011 13:03:24 +0000 Subject: [PATCH] (Patch from firnis) R5900int: As per MIPS documentation, do not modify the destination register if an overflow exception occurs. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4932 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/R5900OpcodeImpl.cpp | 49 +++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/pcsx2/R5900OpcodeImpl.cpp b/pcsx2/R5900OpcodeImpl.cpp index 10b1180698..0b3f5c834a 100644 --- a/pcsx2/R5900OpcodeImpl.cpp +++ b/pcsx2/R5900OpcodeImpl.cpp @@ -24,7 +24,7 @@ #include "R5900Exceptions.h" -static __fi s64 _add64_Overflow( s64 x, s64 y ) +static __fi bool _add64_Overflow( s64 x, s64 y, s64 &ret ) { const s64 result = x + y; @@ -32,18 +32,21 @@ static __fi s64 _add64_Overflow( s64 x, s64 y ) // which apparently works, and generates compact/fast x86 code too (the // other method below is like 5-10 times slower). - if( ((~(x^y))&(x^result)) < 0 ) + if( ((~(x^y))&(x^result)) < 0 ) { cpuException(0x30, cpuRegs.branch); // fixme: is 0x30 right for overflow?? + return true; + } // the not-as-fast style! //if( ((x >= 0) && (y >= 0) && (result < 0)) || // ((x < 0) && (y < 0) && (result >= 0)) ) // cpuException(0x30, cpuRegs.branch); - return result; + ret = result; + return false; } -static __fi s64 _add32_Overflow( s32 x, s32 y ) +static __fi bool _add32_Overflow( s32 x, s32 y, s64 &ret ) { GPR_reg64 result; result.SD[0] = (s64)x + y; @@ -52,10 +55,14 @@ static __fi s64 _add32_Overflow( s32 x, s32 y ) // against bit 31 (leftmost of the lower word). // If bit32 != bit31 then we have an overflow. - if( (result.UL[0]>>31) != (result.UL[1] & 1) ) + if( (result.UL[0]>>31) != (result.UL[1] & 1) ) { cpuException(0x30, cpuRegs.branch); + return true; + } + + ret = result.SD[0]; - return result.SD[0]; + return false; } @@ -266,8 +273,9 @@ void COP1_Unknown() { Console.Warning("Unknown FPU/COP1 opcode called"); } // Rt = Rs + Im signed [exception on overflow] void ADDI() { - s64 result = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], _Imm_ ); - if (!_Rt_) return; + s64 result; + bool overflow = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], _Imm_, result ); + if (overflow || !_Rt_) return; cpuRegs.GPR.r[_Rt_].SD[0] = result; } @@ -285,8 +293,9 @@ void ADDIU() // of at 32 bits. void DADDI() { - s64 result = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], _Imm_ ); - if (!_Rt_) return; + s64 result; + bool overflow = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], _Imm_, result ); + if (overflow || !_Rt_) return; cpuRegs.GPR.r[_Rt_].SD[0] = result; } @@ -312,31 +321,35 @@ void SLTIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[ // Rd = Rs + Rt (Exception on Integer Overflow) void ADD() { - s64 result = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], cpuRegs.GPR.r[_Rt_].SD[0] ); - if (!_Rd_) return; + s64 result; + bool overflow = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], cpuRegs.GPR.r[_Rt_].SD[0], result ); + if (overflow || !_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = result; } void DADD() { - s64 result = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], cpuRegs.GPR.r[_Rt_].SD[0] ); - if (!_Rd_) return; + s64 result; + bool overflow = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], cpuRegs.GPR.r[_Rt_].SD[0], result ); + if (overflow || !_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = result; } // Rd = Rs - Rt (Exception on Integer Overflow) void SUB() { - s64 result = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], -cpuRegs.GPR.r[_Rt_].SD[0] ); - if (!_Rd_) return; + s64 result; + bool overflow = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], -cpuRegs.GPR.r[_Rt_].SD[0], result ); + if (overflow || !_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = result; } // Rd = Rs - Rt (Exception on Integer Overflow) void DSUB() { - s64 result = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], -cpuRegs.GPR.r[_Rt_].SD[0] ); - if (!_Rd_) return; + s64 result; + bool overflow = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], -cpuRegs.GPR.r[_Rt_].SD[0], result ); + if (overflow || !_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = result; }