Interpreter_Integer: Handle overflow flag when OE bit is set in add, addc, adde, addme, and addze

This commit is contained in:
Lioncash 2018-03-21 21:26:10 -04:00
parent 23bc50704a
commit 9d21425449
1 changed files with 44 additions and 24 deletions

View File

@ -422,72 +422,92 @@ void Interpreter::xorx(UGeckoInstruction inst)
Helper_UpdateCR0(rGPR[inst.RA]);
}
static bool HasAddOverflowed(u32 x, u32 y, u32 result)
{
// If x and y have the same sign, but the result is different
// then an overflow has occurred.
return (((x ^ result) & (y ^ result)) >> 31) != 0;
}
void Interpreter::addx(UGeckoInstruction inst)
{
rGPR[inst.RD] = rGPR[inst.RA] + rGPR[inst.RB];
const u32 a = rGPR[inst.RA];
const u32 b = rGPR[inst.RB];
const u32 result = a + b;
rGPR[inst.RD] = result;
if (inst.OE)
PanicAlert("OE: addx");
SetXER_OV(HasAddOverflowed(a, b, result));
if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]);
Helper_UpdateCR0(result);
}
void Interpreter::addcx(UGeckoInstruction inst)
{
u32 a = rGPR[inst.RA];
u32 b = rGPR[inst.RB];
rGPR[inst.RD] = a + b;
const u32 a = rGPR[inst.RA];
const u32 b = rGPR[inst.RB];
const u32 result = a + b;
rGPR[inst.RD] = result;
SetCarry(Helper_Carry(a, b));
if (inst.OE)
PanicAlert("OE: addcx");
SetXER_OV(HasAddOverflowed(a, b, result));
if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]);
Helper_UpdateCR0(result);
}
void Interpreter::addex(UGeckoInstruction inst)
{
int carry = GetCarry();
int a = rGPR[inst.RA];
int b = rGPR[inst.RB];
rGPR[inst.RD] = a + b + carry;
const u32 carry = GetCarry();
const u32 a = rGPR[inst.RA];
const u32 b = rGPR[inst.RB];
const u32 result = a + b + carry;
rGPR[inst.RD] = result;
SetCarry(Helper_Carry(a, b) || (carry != 0 && Helper_Carry(a + b, carry)));
if (inst.OE)
PanicAlert("OE: addex");
SetXER_OV(HasAddOverflowed(a, b, result));
if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]);
Helper_UpdateCR0(result);
}
void Interpreter::addmex(UGeckoInstruction inst)
{
int carry = GetCarry();
int a = rGPR[inst.RA];
rGPR[inst.RD] = a + carry - 1;
const u32 carry = GetCarry();
const u32 a = rGPR[inst.RA];
const u32 b = 0xFFFFFFFF;
const u32 result = a + b + carry;
rGPR[inst.RD] = result;
SetCarry(Helper_Carry(a, carry - 1));
if (inst.OE)
PanicAlert("OE: addmex");
SetXER_OV(HasAddOverflowed(a, b, result));
if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]);
Helper_UpdateCR0(result);
}
void Interpreter::addzex(UGeckoInstruction inst)
{
int carry = GetCarry();
int a = rGPR[inst.RA];
rGPR[inst.RD] = a + carry;
const u32 carry = GetCarry();
const u32 a = rGPR[inst.RA];
const u32 result = a + carry;
rGPR[inst.RD] = result;
SetCarry(Helper_Carry(a, carry));
if (inst.OE)
PanicAlert("OE: addzex");
SetXER_OV(HasAddOverflowed(a, 0, result));
if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]);
Helper_UpdateCR0(result);
}
void Interpreter::divwx(UGeckoInstruction inst)