Merge pull request #6491 from lioncash/sub-oe

Interpreter_Integer: Handle OE bit for subf, subfc, subfe, subfme, and subfze
This commit is contained in:
Markus Wick 2018-03-22 21:52:17 +01:00 committed by GitHub
commit a4511129e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 41 additions and 28 deletions

View File

@ -612,70 +612,83 @@ void Interpreter::negx(UGeckoInstruction inst)
void Interpreter::subfx(UGeckoInstruction inst) void Interpreter::subfx(UGeckoInstruction inst)
{ {
rGPR[inst.RD] = rGPR[inst.RB] - rGPR[inst.RA]; const u32 a = ~rGPR[inst.RA];
const u32 b = rGPR[inst.RB];
const u32 result = a + b + 1;
rGPR[inst.RD] = result;
if (inst.OE) if (inst.OE)
PanicAlert("OE: subfx"); SetXER_OV(HasAddOverflowed(a, b, result));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]); Helper_UpdateCR0(result);
} }
void Interpreter::subfcx(UGeckoInstruction inst) void Interpreter::subfcx(UGeckoInstruction inst)
{ {
u32 a = rGPR[inst.RA]; const u32 a = ~rGPR[inst.RA];
u32 b = rGPR[inst.RB]; const u32 b = rGPR[inst.RB];
rGPR[inst.RD] = b - a; const u32 result = a + b + 1;
SetCarry(a == 0 || Helper_Carry(b, 0 - a));
rGPR[inst.RD] = result;
SetCarry(a == 0xFFFFFFFF || Helper_Carry(b, a + 1));
if (inst.OE) if (inst.OE)
PanicAlert("OE: subfcx"); SetXER_OV(HasAddOverflowed(a, b, result));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]); Helper_UpdateCR0(result);
} }
void Interpreter::subfex(UGeckoInstruction inst) void Interpreter::subfex(UGeckoInstruction inst)
{ {
u32 a = rGPR[inst.RA]; const u32 a = ~rGPR[inst.RA];
u32 b = rGPR[inst.RB]; const u32 b = rGPR[inst.RB];
int carry = GetCarry(); const u32 carry = GetCarry();
rGPR[inst.RD] = (~a) + b + carry; const u32 result = a + b + carry;
SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry));
rGPR[inst.RD] = result;
SetCarry(Helper_Carry(a, b) || Helper_Carry(a + b, carry));
if (inst.OE) if (inst.OE)
PanicAlert("OE: subfex"); SetXER_OV(HasAddOverflowed(a, b, result));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]); Helper_UpdateCR0(result);
} }
// sub from minus one // sub from minus one
void Interpreter::subfmex(UGeckoInstruction inst) void Interpreter::subfmex(UGeckoInstruction inst)
{ {
u32 a = rGPR[inst.RA]; const u32 a = ~rGPR[inst.RA];
int carry = GetCarry(); const u32 b = 0xFFFFFFFF;
rGPR[inst.RD] = (~a) + carry - 1; const u32 carry = GetCarry();
SetCarry(Helper_Carry(~a, carry - 1)); const u32 result = a + b + carry;
rGPR[inst.RD] = result;
SetCarry(Helper_Carry(a, carry - 1));
if (inst.OE) if (inst.OE)
PanicAlert("OE: subfmex"); SetXER_OV(HasAddOverflowed(a, b, result));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]); Helper_UpdateCR0(result);
} }
// sub from zero // sub from zero
void Interpreter::subfzex(UGeckoInstruction inst) void Interpreter::subfzex(UGeckoInstruction inst)
{ {
u32 a = rGPR[inst.RA]; const u32 a = ~rGPR[inst.RA];
int carry = GetCarry(); const u32 carry = GetCarry();
rGPR[inst.RD] = (~a) + carry; const u32 result = a + carry;
SetCarry(Helper_Carry(~a, carry));
rGPR[inst.RD] = result;
SetCarry(Helper_Carry(a, carry));
if (inst.OE) if (inst.OE)
PanicAlert("OE: subfzex"); SetXER_OV(HasAddOverflowed(a, 0, result));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RD]); Helper_UpdateCR0(result);
} }