From abc4c8f6017e516818eb301718bf3773f827a35e Mon Sep 17 00:00:00 2001 From: Sintendo Date: Sat, 24 Apr 2021 19:28:18 +0200 Subject: [PATCH] Jit64: divwx - Eliminate MOV for division by power of 2 Division by a power of two can be slightly improved when the destination and dividend registers are the same. Before: 8B C6 mov eax,esi 85 C0 test eax,eax 8D 70 03 lea esi,[rax+3] 0F 49 F0 cmovns esi,eax C1 FE 02 sar esi,2 After: 85 F6 test esi,esi 8D 46 03 lea eax,[rsi+3] 0F 48 F0 cmovs esi,eax C1 FE 02 sar esi,2 --- .../Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index b77914ef99..b31abb37e0 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -1493,15 +1493,39 @@ void Jit64::divwx(UGeckoInstruction inst) { u32 abs_val = std::abs(divisor); - X64Reg tmp = RSCRATCH; - if (Ra.IsSimpleReg() && Ra.GetSimpleReg() != Rd) - tmp = Ra.GetSimpleReg(); - else - MOV(32, R(tmp), Ra); + X64Reg dividend, sum, src; + CCFlags cond = CC_NS; - TEST(32, R(tmp), R(tmp)); - LEA(32, Rd, MDisp(tmp, abs_val - 1)); - CMOVcc(32, Rd, R(tmp), CC_NS); + if (!Ra.IsSimpleReg()) + { + dividend = RSCRATCH; + sum = Rd; + src = RSCRATCH; + + // Load dividend from memory + MOV(32, R(dividend), Ra); + } + else if (d == a) + { + // Rd holds the dividend, while RSCRATCH holds the sum + // This is opposite of the other cases + dividend = Rd; + sum = RSCRATCH; + src = RSCRATCH; + // Negate condition to compensate the swapped values + cond = CC_S; + } + else + { + // Use dividend from register directly + dividend = Ra.GetSimpleReg(); + sum = Rd; + src = dividend; + } + + TEST(32, R(dividend), R(dividend)); + LEA(32, sum, MDisp(dividend, abs_val - 1)); + CMOVcc(32, Rd, R(src), cond); SAR(32, Rd, Imm8(IntLog2(abs_val))); if (divisor < 0)