diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 66f9b07337..297bda67d9 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -85,6 +85,7 @@ public: void addcx(UGeckoInstruction inst); void slwx(UGeckoInstruction inst); void srwx(UGeckoInstruction inst); + void srawx(UGeckoInstruction inst); void rlwimix(UGeckoInstruction inst); void subfex(UGeckoInstruction inst); void subfcx(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index aba0efff0e..3099f31017 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -1104,6 +1104,92 @@ void JitArm64::srwx(UGeckoInstruction inst) } } +void JitArm64::srawx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + + int a = inst.RA, b = inst.RB, s = inst.RS; + + if (gpr.IsImm(b) && gpr.IsImm(s)) + { + s32 i = gpr.GetImm(s), amount = gpr.GetImm(b); + if (amount & 0x20) + { + gpr.SetImmediate(a, i & 0x80000000 ? 0xFFFFFFFF : 0); + ComputeCarry(i & 0x80000000 ? true : false); + } + else + { + amount &= 0x1F; + gpr.SetImmediate(a, i >> amount); + ComputeCarry(amount != 0 && i < 0 && (i << (32 - amount))); + } + + if (inst.Rc) + ComputeRC(gpr.GetImm(a), 0); + return; + } + else if (gpr.IsImm(b) && (gpr.GetImm(b) & 0x20) == 0 && !js.op->wantsCA) + { + gpr.BindToRegister(a, a == s); + ASR(gpr.R(a), gpr.R(a), gpr.GetImm(b) & 0x1F); + } + else if (!js.op->wantsCA) + { + gpr.BindToRegister(a, a == b || a == s); + + ARM64Reg WA = gpr.GetReg(); + + LSL(EncodeRegTo64(WA), EncodeRegTo64(gpr.R(s)), 32); + ASRV(EncodeRegTo64(WA), EncodeRegTo64(WA), EncodeRegTo64(gpr.R(b))); + LSR(EncodeRegTo64(gpr.R(a)), EncodeRegTo64(WA), 32); + + gpr.Unlock(WA); + } + else + { + gpr.BindToRegister(a, a == b || a == s); + ARM64Reg WA = gpr.GetReg(); + ARM64Reg WB = gpr.GetReg(); + ARM64Reg WC = gpr.GetReg(); + + ANDI2R(WA, gpr.R(b), 32); + FixupBranch bit_is_not_zero = TBNZ(gpr.R(b), 5); + + ANDSI2R(WC, gpr.R(b), 31); + MOV(WB, gpr.R(s)); + FixupBranch is_zero = B(CC_EQ); + + ASRV(WB, gpr.R(s), WC); + FixupBranch bit_is_zero = TBZ(gpr.R(s), 31); + + MOVI2R(WA, 32); + SUB(WC, WA, WC); + LSL(WC, gpr.R(s), WC); + CMP(WC, 0); + CSET(WA, CC_NEQ); + FixupBranch end = B(); + + SetJumpTarget(bit_is_not_zero); + CMP(gpr.R(s), 0); + CSET(WA, CC_LT); + CSINV(WB, WZR, WZR, CC_GE); + + SetJumpTarget(is_zero); + SetJumpTarget(bit_is_zero); + SetJumpTarget(end); + + MOV(gpr.R(a), WB); + STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + + gpr.Unlock(WA, WB, WC); + } + + if (inst.Rc) + ComputeRC(gpr.R(a), 0); +} + void JitArm64::rlwimix(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 723cf91aa6..340342665b 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -209,23 +209,23 @@ static GekkoOPTemplate table31[] = { {200, &JitArm64::FallBackToInterpreter}, // subfzex {712, &JitArm64::FallBackToInterpreter}, // subfzeox - {28, &JitArm64::boolX}, // andx - {60, &JitArm64::boolX}, // andcx - {444, &JitArm64::boolX}, // orx - {124, &JitArm64::boolX}, // norx - {316, &JitArm64::boolX}, // xorx - {412, &JitArm64::boolX}, // orcx - {476, &JitArm64::boolX}, // nandx - {284, &JitArm64::boolX}, // eqvx - {0, &JitArm64::cmp}, // cmp - {32, &JitArm64::cmpl}, // cmpl - {26, &JitArm64::cntlzwx}, // cntlzwx - {922, &JitArm64::extsXx}, // extshx - {954, &JitArm64::extsXx}, // extsbx - {536, &JitArm64::srwx}, // srwx - {792, &JitArm64::FallBackToInterpreter}, // srawx - {824, &JitArm64::srawix}, // srawix - {24, &JitArm64::slwx}, // slwx + {28, &JitArm64::boolX}, // andx + {60, &JitArm64::boolX}, // andcx + {444, &JitArm64::boolX}, // orx + {124, &JitArm64::boolX}, // norx + {316, &JitArm64::boolX}, // xorx + {412, &JitArm64::boolX}, // orcx + {476, &JitArm64::boolX}, // nandx + {284, &JitArm64::boolX}, // eqvx + {0, &JitArm64::cmp}, // cmp + {32, &JitArm64::cmpl}, // cmpl + {26, &JitArm64::cntlzwx}, // cntlzwx + {922, &JitArm64::extsXx}, // extshx + {954, &JitArm64::extsXx}, // extsbx + {536, &JitArm64::srwx}, // srwx + {792, &JitArm64::srawx}, // srawx + {824, &JitArm64::srawix}, // srawix + {24, &JitArm64::slwx}, // slwx {54, &JitArm64::dcbx}, // dcbst {86, &JitArm64::dcbx}, // dcbf