From 482170c3ea8017983db5356d6c08f6741eea5b30 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 24 Sep 2013 19:01:03 +0000 Subject: [PATCH] [ARM] Implement subfic with optimizations stolen from JIT64. --- Source/Core/Core/Src/PowerPC/JitArm32/Jit.h | 1 + .../Src/PowerPC/JitArm32/JitArm_Integer.cpp | 73 +++++++++++++++++++ .../Src/PowerPC/JitArm32/JitArm_Tables.cpp | 2 +- 3 files changed, 75 insertions(+), 1 deletion(-) 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}},