Skip to content

Commit

Permalink
Merge pull request #6486 from lioncash/add-oe
Browse files Browse the repository at this point in the history
Interpreter_Integer: Handle overflow flag when OE bit is set in add, addc, adde, addme, and addze
  • Loading branch information
degasus committed Mar 22, 2018
2 parents 2e92d95 + 9d21425 commit 59c5bc9
Showing 1 changed file with 44 additions and 24 deletions.
68 changes: 44 additions & 24 deletions Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp
Expand Up @@ -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)
Expand Down

0 comments on commit 59c5bc9

Please sign in to comment.