diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 2a851e3339..9d44f967ef 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -99,6 +99,7 @@ public: void addcx(UGeckoInstruction inst); void slwx(UGeckoInstruction inst); void rlwimix(UGeckoInstruction inst); + void subfex(UGeckoInstruction inst); // System Registers void mtmsr(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 1ae60dc0b8..937bd07f3d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -724,6 +724,66 @@ void JitArm64::subfx(UGeckoInstruction inst) } } +void JitArm64::subfex(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + FALLBACK_IF(inst.OE); + + int a = inst.RA, b = inst.RB, d = inst.RD; + + if (gpr.IsImm(a) && gpr.IsImm(b)) + { + u32 i = gpr.GetImm(a), j = gpr.GetImm(b); + + gpr.BindToRegister(d, false); + MOVI2R(gpr.R(d), ~i + j); + ARM64Reg WA = gpr.GetReg(); + LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca)); + ADD(gpr.R(d), gpr.R(d), WA); + gpr.Unlock(WA); + + bool must_have_carry = Interpreter::Helper_Carry(~i, j); + bool might_have_carry = (~i + j) == 0xFFFFFFFF; + + if (must_have_carry) + { + ComputeCarry(true); + } + else if (might_have_carry) + { + // carry stay as it is + } + else + { + ComputeCarry(false); + } + } + else + { + ARM64Reg WA = gpr.GetReg(); + gpr.BindToRegister(d, d == a || d == b); + + // upload the carry state + LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca)); + CMP(WA, 1); + + // d = ~a + b + carry; + if (gpr.IsImm(a)) + MOVI2R(WA, ~gpr.GetImm(a)); + else + MVN(WA, gpr.R(a)); + ADCS(gpr.R(d), WA, gpr.R(b)); + + gpr.Unlock(WA); + + ComputeCarry(); + } + + if (inst.Rc) + ComputeRC(gpr.R(d), 0); +} + void JitArm64::addcx(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index a2c71acf91..7b3327706e 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -194,8 +194,8 @@ static GekkoOPTemplate table31[] = {552, &JitArm64::subfx}, // subfox {8, &JitArm64::FallBackToInterpreter}, // subfcx {520, &JitArm64::FallBackToInterpreter}, // subfcox - {136, &JitArm64::FallBackToInterpreter}, // subfex - {648, &JitArm64::FallBackToInterpreter}, // subfeox + {136, &JitArm64::subfex}, // subfex + {648, &JitArm64::subfex}, // subfeox {232, &JitArm64::FallBackToInterpreter}, // subfmex {744, &JitArm64::FallBackToInterpreter}, // subfmeox {200, &JitArm64::FallBackToInterpreter}, // subfzex