From 2ca1ac337040a6dd9f0f1a18a7dbdc2aa027d21f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 22 May 2018 10:25:45 -0400 Subject: [PATCH] Interpreter_Integer: Correct negative overflow handling for divw Previously, given cases such as 0x80000000 / 0xFFFFFFFF we'd incorrectly set the destination register value to zero. If the dividend is negative, then the destination should be set to -1 (0xFFFFFFFF), however if the dividend is positive, then the destination should be set to 0. Note that the 750CL documents state that: "If an attempt is made to perform either of the divisions -- 0x80000000 / -1 or / 0, then the contents of rD are undefined, as are the contents of the LT, GT, and EQ bits of the CR0 field (if Rc = 1). In this case, if OE = 1 then OV is set." So this is a particular behavior of the hardware itself. --- .../Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp index 5801b527c1..5b5d4450a6 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -501,18 +501,18 @@ void Interpreter::divwx(UGeckoInstruction inst) { const s32 a = rGPR[inst.RA]; const s32 b = rGPR[inst.RB]; - const bool overflow = b == 0 || ((u32)a == 0x80000000 && b == -1); + const bool overflow = b == 0 || (static_cast(a) == 0x80000000 && b == -1); if (overflow) { - if (((u32)a & 0x80000000) && b == 0) + if (a < 0) rGPR[inst.RD] = UINT32_MAX; else rGPR[inst.RD] = 0; } else { - rGPR[inst.RD] = (u32)(a / b); + rGPR[inst.RD] = static_cast(a / b); } if (inst.OE)