[ARM] Implement subfic with optimizations stolen from JIT64.

This commit is contained in:
Ryan Houdek 2013-09-24 19:01:03 +00:00
parent 405aa30cb8
commit 482170c3ea
3 changed files with 75 additions and 1 deletions

View file

@ -159,6 +159,7 @@ public:
void arith(UGeckoInstruction _inst);
void addex(UGeckoInstruction _inst);
void subfic(UGeckoInstruction _inst);
void cntlzwx(UGeckoInstruction _inst);
void cmp (UGeckoInstruction _inst);
void cmpi(UGeckoInstruction _inst);

View file

@ -117,6 +117,79 @@ void JitArm::FinalizeCarry(ARMReg reg)
STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
gpr.Unlock(tmp);
}
void JitArm::subfic(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITIntegerOff)
int a = inst.RA, d = inst.RD;
int imm = inst.SIMM_16;
if (d == a)
{
if (imm == 0)
{
ARMReg tmp = gpr.GetReg();
Operand2 mask = Operand2(2, 2); // XER_CA_MASK
LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
BIC(tmp, tmp, mask);
// Flags act exactly like subtracting from 0
RSBS(gpr.R(d), gpr.R(d), 0);
// Output carry is inverted
SetCC(CC_CC);
ORR(tmp, tmp, mask);
SetCC();
STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
gpr.Unlock(tmp);
}
else if (imm == -1)
{
// CA is always set in this case
ARMReg tmp = gpr.GetReg();
Operand2 mask = Operand2(2, 2); // XER_CA_MASK
LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
ORR(tmp, tmp, mask);
STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
gpr.Unlock(tmp);
MVN(gpr.R(d), gpr.R(d));
}
else
{
ARMReg tmp = gpr.GetReg();
ARMReg rA = gpr.GetReg();
Operand2 mask = Operand2(2, 2); // XER_CA_MASK
MOVI2R(rA, imm + 1);
LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
BIC(tmp, tmp, mask);
// Flags act exactly like subtracting from 0
MVN(gpr.R(d), gpr.R(d));
ADDS(gpr.R(d), gpr.R(d), rA);
// Output carry is inverted
SetCC(CC_CS);
ORR(tmp, tmp, mask);
SetCC();
STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
gpr.Unlock(tmp, rA);
}
}
else
{
ARMReg tmp = gpr.GetReg();
Operand2 mask = Operand2(2, 2); // XER_CA_MASK
MOVI2R(gpr.R(d), imm);
LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
BIC(tmp, tmp, mask);
// Flags act exactly like subtracting from 0
SUBS(gpr.R(d), gpr.R(d), gpr.R(a));
// Output carry is inverted
SetCC(CC_CC);
ORR(tmp, tmp, mask);
SetCC();
STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
gpr.Unlock(tmp);
}
// This instruction has no RC flag
}
u32 Add(u32 a, u32 b) {return a + b;}
u32 Sub(u32 a, u32 b) {return a - b;}

View file

@ -59,7 +59,7 @@ static GekkoOPTemplate primarytable[] =
{17, &JitArm::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
{7, &JitArm::arith}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}},
{8, &JitArm::Default}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{8, &JitArm::subfic}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{10, &JitArm::cmpli}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{11, &JitArm::cmpi}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{12, &JitArm::arith}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},