Permalink
Browse files

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 <anything> / 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.
  • Loading branch information...
lioncash committed May 22, 2018
1 parent 5ac0572 commit 2ca1ac337040a6dd9f0f1a18a7dbdc2aa027d21f
Showing with 3 additions and 3 deletions.
  1. +3 −3 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<u32>(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<u32>(a / b);
}
if (inst.OE)

0 comments on commit 2ca1ac3

Please sign in to comment.