Handle DIV overflow in lightrec and the interpreter
authorEmber Cold <embercold@outlook.com>
Wed, 21 Jul 2021 12:04:23 +0000 (15:04 +0300)
committerEmber Cold <embercold@outlook.com>
Wed, 21 Jul 2021 12:04:23 +0000 (15:04 +0300)
deps/lightrec/interpreter.c
libpcsxcore/psxinterpreter.c

index f586685..ff609a4 100644 (file)
@@ -801,6 +801,9 @@ static u32 int_special_DIV(struct interpreter *inter)
        if (rt == 0) {
                hi = rs;
                lo = (rs < 0) * 2 - 1;
+       } else if ((rs == 0x80000000) && (rt == 0xFFFFFFFF)) {
+               lo = rs;
+               hi = 0;
        } else {
                lo = rs / rt;
                hi = rs % rt;
index d3e42e9..db8e73b 100644 (file)
@@ -507,14 +507,20 @@ void psxSLTU()    { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); }       // Rd
 * Format:  OP rs, rt                                     *
 *********************************************************/
 void psxDIV() {
-       if (_i32(_rRt_) != 0) {
-               _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
-               _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
-       }
-       else {
-               _i32(_rLo_) = _i32(_rRs_) >= 0 ? 0xffffffff : 1;
-               _i32(_rHi_) = _i32(_rRs_);
-       }
+    if (!_i32(_rRt_)) {
+        _i32(_rHi_) = _i32(_rRs_);
+        if (_i32(_rRs_) & 0x80000000) {
+            _i32(_rLo_) = 1;
+        } else {
+            _i32(_rLo_) = 0xFFFFFFFF;
+        }
+    } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
+        _i32(_rLo_) = 0x80000000;
+        _i32(_rHi_) = 0;
+    } else {
+        _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
+        _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
+    }
 }
 
 void psxDIVU() {