JitArm64: Implement derefered carry usage.

This commit is contained in:
degasus 2016-10-27 21:11:56 +02:00
parent 4d88f5410e
commit f449541e65
1 changed files with 53 additions and 24 deletions

View File

@ -752,11 +752,14 @@ void JitArm64::addzex(UGeckoInstruction inst)
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
FALLBACK_IF(inst.OE); FALLBACK_IF(inst.OE);
FlushCarry();
int a = inst.RA, d = inst.RD; int a = inst.RA, d = inst.RD;
if (d == a) if (js.carryFlagSet)
{
gpr.BindToRegister(d, d == a);
ADCS(gpr.R(d), gpr.R(a), WZR);
}
else if (d == a)
{ {
gpr.BindToRegister(d, true); gpr.BindToRegister(d, true);
ARM64Reg WA = gpr.GetReg(); ARM64Reg WA = gpr.GetReg();
@ -806,8 +809,6 @@ void JitArm64::subfex(UGeckoInstruction inst)
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
FALLBACK_IF(inst.OE); FALLBACK_IF(inst.OE);
FlushCarry();
int a = inst.RA, b = inst.RB, d = inst.RD; int a = inst.RA, b = inst.RB, d = inst.RD;
if (gpr.IsImm(a) && gpr.IsImm(b)) if (gpr.IsImm(a) && gpr.IsImm(b))
@ -816,8 +817,16 @@ void JitArm64::subfex(UGeckoInstruction inst)
gpr.BindToRegister(d, false); gpr.BindToRegister(d, false);
ARM64Reg WA = gpr.GetReg(); ARM64Reg WA = gpr.GetReg();
if (js.carryFlagSet)
{
MOVI2R(WA, ~i + j, gpr.R(d));
ADC(gpr.R(d), WA, WZR);
}
else
{
LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d)); ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d));
}
gpr.Unlock(WA); gpr.Unlock(WA);
bool must_have_carry = Interpreter::Helper_Carry(~i, j); bool must_have_carry = Interpreter::Helper_Carry(~i, j);
@ -842,8 +851,11 @@ void JitArm64::subfex(UGeckoInstruction inst)
gpr.BindToRegister(d, d == a || d == b); gpr.BindToRegister(d, d == a || d == b);
// upload the carry state // upload the carry state
if (!js.carryFlagSet)
{
LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CMP(WA, 1); CMP(WA, 1);
}
// d = ~a + b + carry; // d = ~a + b + carry;
if (gpr.IsImm(a)) if (gpr.IsImm(a))
@ -899,17 +911,23 @@ void JitArm64::subfzex(UGeckoInstruction inst)
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
FALLBACK_IF(inst.OE); FALLBACK_IF(inst.OE);
FlushCarry();
int a = inst.RA, d = inst.RD; int a = inst.RA, d = inst.RD;
gpr.BindToRegister(d, d == a); gpr.BindToRegister(d, d == a);
if (js.carryFlagSet)
{
MVN(gpr.R(d), gpr.R(a));
ADCS(gpr.R(d), gpr.R(d), WZR);
}
else
{
ARM64Reg WA = gpr.GetReg(); ARM64Reg WA = gpr.GetReg();
LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
MVN(gpr.R(d), gpr.R(a)); MVN(gpr.R(d), gpr.R(a));
ADDS(gpr.R(d), gpr.R(d), WA); ADDS(gpr.R(d), gpr.R(d), WA);
gpr.Unlock(WA); gpr.Unlock(WA);
}
ComputeCarry(); ComputeCarry();
@ -952,8 +970,6 @@ void JitArm64::addex(UGeckoInstruction inst)
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
FALLBACK_IF(inst.OE); FALLBACK_IF(inst.OE);
FlushCarry();
int a = inst.RA, b = inst.RB, d = inst.RD; int a = inst.RA, b = inst.RB, d = inst.RD;
if (gpr.IsImm(a) && gpr.IsImm(b)) if (gpr.IsImm(a) && gpr.IsImm(b))
@ -962,8 +978,16 @@ void JitArm64::addex(UGeckoInstruction inst)
gpr.BindToRegister(d, false); gpr.BindToRegister(d, false);
ARM64Reg WA = gpr.GetReg(); ARM64Reg WA = gpr.GetReg();
if (js.carryFlagSet)
{
MOVI2R(WA, i + j);
ADC(gpr.R(d), WA, WZR);
}
else
{
LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(gpr.R(d), WA, i + j, gpr.R(d)); ADDI2R(gpr.R(d), WA, i + j, gpr.R(d));
}
gpr.Unlock(WA); gpr.Unlock(WA);
bool must_have_carry = Interpreter::Helper_Carry(i, j); bool must_have_carry = Interpreter::Helper_Carry(i, j);
@ -987,10 +1011,13 @@ void JitArm64::addex(UGeckoInstruction inst)
gpr.BindToRegister(d, d == a || d == b); gpr.BindToRegister(d, d == a || d == b);
// upload the carry state // upload the carry state
if (!js.carryFlagSet)
{
ARM64Reg WA = gpr.GetReg(); ARM64Reg WA = gpr.GetReg();
LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CMP(WA, 1); CMP(WA, 1);
gpr.Unlock(WA); gpr.Unlock(WA);
}
// d = a + b + carry; // d = a + b + carry;
ADCS(gpr.R(d), gpr.R(a), gpr.R(b)); ADCS(gpr.R(d), gpr.R(a), gpr.R(b));
@ -1104,6 +1131,8 @@ void JitArm64::divwx(UGeckoInstruction inst)
} }
else else
{ {
FlushCarry();
gpr.BindToRegister(d, d == a || d == b); gpr.BindToRegister(d, d == a || d == b);
ARM64Reg WA = gpr.GetReg(); ARM64Reg WA = gpr.GetReg();