diff --git a/Source/Core/Common/Arm64Emitter.h b/Source/Core/Common/Arm64Emitter.h index 9093642417..5ea860a77a 100644 --- a/Source/Core/Common/Arm64Emitter.h +++ b/Source/Core/Common/Arm64Emitter.h @@ -896,7 +896,15 @@ public: CSINV(Rd, zr, zr, (CCFlags)((u32)cond ^ 1)); } void NEG(ARM64Reg Rd, ARM64Reg Rs) { SUB(Rd, Is64Bit(Rd) ? ARM64Reg::ZR : ARM64Reg::WZR, Rs); } + void NEG(ARM64Reg Rd, ARM64Reg Rs, ArithOption Option) + { + SUB(Rd, Is64Bit(Rd) ? ARM64Reg::ZR : ARM64Reg::WZR, Rs, Option); + } void NEGS(ARM64Reg Rd, ARM64Reg Rs) { SUBS(Rd, Is64Bit(Rd) ? ARM64Reg::ZR : ARM64Reg::WZR, Rs); } + void NEGS(ARM64Reg Rd, ARM64Reg Rs, ArithOption Option) + { + SUBS(Rd, Is64Bit(Rd) ? ARM64Reg::ZR : ARM64Reg::WZR, Rs, Option); + } // Data-Processing 1 source void RBIT(ARM64Reg Rd, ARM64Reg Rn); void REV16(ARM64Reg Rd, ARM64Reg Rn); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 0b29127976..a6b88a8cb1 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -1366,7 +1366,7 @@ void JitArm64::divwx(UGeckoInstruction inst) if (inst.Rc) ComputeRC0(RD); } - else if (gpr.IsImm(b) && gpr.GetImm(b) != UINT32_C(0x80000000)) + else if (gpr.IsImm(b)) { const s32 divisor = s32(gpr.GetImm(b)); @@ -1394,6 +1394,28 @@ void JitArm64::divwx(UGeckoInstruction inst) gpr.Unlock(WA); } + else if (MathUtil::IsPow2(divisor) || MathUtil::IsPow2(-static_cast(divisor))) + { + const u32 abs_val = static_cast(std::abs(static_cast(divisor))); + + ARM64Reg RA = gpr.R(a); + ARM64Reg RD = gpr.R(d); + + const bool allocate_reg = a == d; + ARM64Reg WA = allocate_reg ? gpr.GetReg() : RD; + + TST(RA, RA); + ADDI2R(WA, RA, abs_val - 1, WA); + CSEL(WA, RA, WA, CCFlags::CC_PL); + + if (divisor < 0) + NEG(RD, WA, ArithOption(WA, ShiftType::ASR, IntLog2(abs_val))); + else + ASR(RD, WA, IntLog2(abs_val)); + + if (allocate_reg) + gpr.Unlock(WA); + } else { // Optimize signed 32-bit integer division by a constant