summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@Gmail.com>2013-09-24 19:01:03 +0000
committerRyan Houdek <Sonicadvance1@Gmail.com>2013-09-24 19:01:03 +0000
commit482170c3ea8017983db5356d6c08f6741eea5b30 (patch)
tree2387ef3ec216442dd087c0699f74745a0439942c /Source/Core
parent405aa30cb81b6a48a3c4b666b2f2babd12b0e1a8 (diff)
[ARM] Implement subfic with optimizations stolen from JIT64.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/Jit.h1
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp73
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp2
3 files changed, 75 insertions, 1 deletions
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h
index 0d037bf921..ffbfe5a572 100644
--- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h
@@ -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);
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp
index 3aeea58e50..2b6bf54704 100644
--- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp
@@ -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;}
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp
index 706b09e4e2..b57cce06f9 100644
--- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp
@@ -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}},