From 796d67e1ec6788a0649d0604de7493f5cc09148c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 22 Mar 2018 10:49:04 -0400 Subject: [PATCH] Interpreter_Integer: Handle OE bit for subf, subfc, subfe, subfme, and subfze With this, overflow flag support is now fully implemented for all instructions that support it. --- .../Interpreter/Interpreter_Integer.cpp | 69 +++++++++++-------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp index 09db4c35da..93dea85c85 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -612,70 +612,83 @@ void Interpreter::negx(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) - PanicAlert("OE: subfx"); + SetXER_OV(HasAddOverflowed(a, b, result)); if (inst.Rc) - Helper_UpdateCR0(rGPR[inst.RD]); + Helper_UpdateCR0(result); } void Interpreter::subfcx(UGeckoInstruction inst) { - u32 a = rGPR[inst.RA]; - u32 b = rGPR[inst.RB]; - rGPR[inst.RD] = b - a; - SetCarry(a == 0 || Helper_Carry(b, 0 - a)); + const u32 a = ~rGPR[inst.RA]; + const u32 b = rGPR[inst.RB]; + const u32 result = a + b + 1; + + rGPR[inst.RD] = result; + SetCarry(a == 0xFFFFFFFF || Helper_Carry(b, a + 1)); if (inst.OE) - PanicAlert("OE: subfcx"); + SetXER_OV(HasAddOverflowed(a, b, result)); if (inst.Rc) - Helper_UpdateCR0(rGPR[inst.RD]); + Helper_UpdateCR0(result); } void Interpreter::subfex(UGeckoInstruction inst) { - u32 a = rGPR[inst.RA]; - u32 b = rGPR[inst.RB]; - int carry = GetCarry(); - rGPR[inst.RD] = (~a) + b + carry; - SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry)); + const u32 a = ~rGPR[inst.RA]; + const u32 b = rGPR[inst.RB]; + const u32 carry = GetCarry(); + const u32 result = a + b + carry; + + rGPR[inst.RD] = result; + SetCarry(Helper_Carry(a, b) || Helper_Carry(a + b, carry)); if (inst.OE) - PanicAlert("OE: subfex"); + SetXER_OV(HasAddOverflowed(a, b, result)); if (inst.Rc) - Helper_UpdateCR0(rGPR[inst.RD]); + Helper_UpdateCR0(result); } // sub from minus one void Interpreter::subfmex(UGeckoInstruction inst) { - u32 a = rGPR[inst.RA]; - int carry = GetCarry(); - rGPR[inst.RD] = (~a) + carry - 1; - SetCarry(Helper_Carry(~a, carry - 1)); + const u32 a = ~rGPR[inst.RA]; + const u32 b = 0xFFFFFFFF; + const u32 carry = GetCarry(); + const u32 result = a + b + carry; + + rGPR[inst.RD] = result; + SetCarry(Helper_Carry(a, carry - 1)); if (inst.OE) - PanicAlert("OE: subfmex"); + SetXER_OV(HasAddOverflowed(a, b, result)); if (inst.Rc) - Helper_UpdateCR0(rGPR[inst.RD]); + Helper_UpdateCR0(result); } // sub from zero void Interpreter::subfzex(UGeckoInstruction inst) { - u32 a = rGPR[inst.RA]; - int carry = GetCarry(); - rGPR[inst.RD] = (~a) + carry; - SetCarry(Helper_Carry(~a, carry)); + const u32 a = ~rGPR[inst.RA]; + const u32 carry = GetCarry(); + const u32 result = a + carry; + + rGPR[inst.RD] = result; + SetCarry(Helper_Carry(a, carry)); if (inst.OE) - PanicAlert("OE: subfzex"); + SetXER_OV(HasAddOverflowed(a, 0, result)); if (inst.Rc) - Helper_UpdateCR0(rGPR[inst.RD]); + Helper_UpdateCR0(result); }