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.
This commit is contained in:
parent
5ac05725c8
commit
2ca1ac3370
|
@ -501,18 +501,18 @@ void Interpreter::divwx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const s32 a = rGPR[inst.RA];
|
const s32 a = rGPR[inst.RA];
|
||||||
const s32 b = rGPR[inst.RB];
|
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 (overflow)
|
||||||
{
|
{
|
||||||
if (((u32)a & 0x80000000) && b == 0)
|
if (a < 0)
|
||||||
rGPR[inst.RD] = UINT32_MAX;
|
rGPR[inst.RD] = UINT32_MAX;
|
||||||
else
|
else
|
||||||
rGPR[inst.RD] = 0;
|
rGPR[inst.RD] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rGPR[inst.RD] = (u32)(a / b);
|
rGPR[inst.RD] = static_cast<u32>(a / b);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.OE)
|
if (inst.OE)
|
||||||
|
|
Loading…
Reference in New Issue