Merge pull request #3212 from mickdermack/pr-recalc-flags

JIT x64: Recalculate flags after add/sub
This commit is contained in:
Ryan Houdek 2016-01-22 12:45:52 -05:00
commit ae4c7661d6

View File

@ -134,6 +134,8 @@ void Jit64::FinalizeCarryOverflow(bool oe, bool inv)
// to be recalculated and haven't been clobbered. Keep in mind not all instructions set // to be recalculated and haven't been clobbered. Keep in mind not all instructions set
// sufficient flags -- for example, the flags from SHL/SHR are *not* sufficient for LT/GT // sufficient flags -- for example, the flags from SHL/SHR are *not* sufficient for LT/GT
// branches, only EQ. // branches, only EQ.
// The flags from any instruction that may set OF (such as ADD/SUB) can not be used for
// LT/GT either.
void Jit64::ComputeRC(const OpArg& arg, bool needs_test, bool needs_sext) void Jit64::ComputeRC(const OpArg& arg, bool needs_test, bool needs_sext)
{ {
_assert_msg_(DYNA_REC, arg.IsSimpleReg() || arg.IsImm(), "Invalid ComputeRC operand"); _assert_msg_(DYNA_REC, arg.IsSimpleReg() || arg.IsImm(), "Invalid ComputeRC operand");
@ -223,7 +225,7 @@ static u32 Xor(u32 a, u32 b)
void Jit64::regimmop(int d, int a, bool binary, u32 value, Operation doop, void (XEmitter::*op)(int, const OpArg&, const OpArg&), bool Rc, bool carry) void Jit64::regimmop(int d, int a, bool binary, u32 value, Operation doop, void (XEmitter::*op)(int, const OpArg&, const OpArg&), bool Rc, bool carry)
{ {
bool needs_test = false; bool needs_test = doop == Add;
gpr.Lock(d, a); gpr.Lock(d, a);
// Be careful; addic treats r0 as r0, but addi treats r0 as zero. // Be careful; addic treats r0 as r0, but addi treats r0 as zero.
if (a || binary || carry) if (a || binary || carry)
@ -243,7 +245,6 @@ void Jit64::regimmop(int d, int a, bool binary, u32 value, Operation doop, void
gpr.BindToRegister(d, false); gpr.BindToRegister(d, false);
if (doop == Add && gpr.R(a).IsSimpleReg() && !carry) if (doop == Add && gpr.R(a).IsSimpleReg() && !carry)
{ {
needs_test = true;
LEA(32, gpr.RX(d), MDisp(gpr.RX(a), value)); LEA(32, gpr.RX(d), MDisp(gpr.RX(a), value));
} }
else else
@ -905,7 +906,7 @@ void Jit64::subfx(UGeckoInstruction inst)
GenerateOverflow(); GenerateOverflow();
} }
if (inst.Rc) if (inst.Rc)
ComputeRC(gpr.R(d), false); ComputeRC(gpr.R(d));
gpr.UnlockAll(); gpr.UnlockAll();
} }
@ -1267,7 +1268,6 @@ void Jit64::addx(UGeckoInstruction inst)
INSTRUCTION_START INSTRUCTION_START
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
int a = inst.RA, b = inst.RB, d = inst.RD; int a = inst.RA, b = inst.RB, d = inst.RD;
bool needs_test = false;
if (gpr.R(a).IsImm() && gpr.R(b).IsImm()) if (gpr.R(a).IsImm() && gpr.R(b).IsImm())
{ {
@ -1290,7 +1290,6 @@ void Jit64::addx(UGeckoInstruction inst)
gpr.Lock(a, b, d); gpr.Lock(a, b, d);
gpr.BindToRegister(d, false); gpr.BindToRegister(d, false);
LEA(32, gpr.RX(d), MRegSum(gpr.RX(a), gpr.RX(b))); LEA(32, gpr.RX(d), MRegSum(gpr.RX(a), gpr.RX(b)));
needs_test = true;
} }
else else
{ {
@ -1302,7 +1301,7 @@ void Jit64::addx(UGeckoInstruction inst)
GenerateOverflow(); GenerateOverflow();
} }
if (inst.Rc) if (inst.Rc)
ComputeRC(gpr.R(d), needs_test); ComputeRC(gpr.R(d));
gpr.UnlockAll(); gpr.UnlockAll();
} }
@ -1367,7 +1366,7 @@ void Jit64::arithXex(UGeckoInstruction inst)
} }
FinalizeCarryOverflow(inst.OE, invertedCarry); FinalizeCarryOverflow(inst.OE, invertedCarry);
if (inst.Rc) if (inst.Rc)
ComputeRC(gpr.R(d), false); ComputeRC(gpr.R(d));
gpr.UnlockAll(); gpr.UnlockAll();
} }
@ -1406,7 +1405,7 @@ void Jit64::arithcx(UGeckoInstruction inst)
FinalizeCarryOverflow(inst.OE, !add); FinalizeCarryOverflow(inst.OE, !add);
if (inst.Rc) if (inst.Rc)
ComputeRC(gpr.R(d), false); ComputeRC(gpr.R(d));
gpr.UnlockAll(); gpr.UnlockAll();
} }