From 502317a4851141a53cc0d94cfecff4c578dafb79 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 1 Sep 2024 11:44:34 +0200 Subject: [PATCH] Jit: Move rlwimix to ConstantPropagation --- .../Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 207 ++++++++---------- .../PowerPC/JitArm64/JitArm64_Integer.cpp | 108 +++++---- .../PowerPC/JitCommon/ConstantPropagation.cpp | 18 ++ .../PowerPC/JitCommon/ConstantPropagation.h | 1 + 4 files changed, 163 insertions(+), 171 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index eb0a6086a01..03bf2fc7867 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -1997,135 +1997,118 @@ void Jit64::rlwimix(UGeckoInstruction inst) int s = inst.RS; const u32 mask = MakeRotationMask(inst.MB, inst.ME); + const bool left_shift = mask == 0U - (1U << inst.SH); + const bool right_shift = mask == (1U << inst.SH) - 1; + bool needs_test = false; - if (gpr.IsImm(a, s)) + if (mask == 0 || (a == s && inst.SH == 0)) { - gpr.SetImmediate32(a, (gpr.Imm32(a) & ~mask) | (std::rotl(gpr.Imm32(s), inst.SH) & mask)); - if (inst.Rc) - ComputeRC(a); + needs_test = true; } - else if (gpr.IsImm(s) && mask == 0xFFFFFFFF) + else if (mask == 0xFFFFFFFF) { - gpr.SetImmediate32(a, std::rotl(gpr.Imm32(s), inst.SH)); - - if (inst.Rc) - ComputeRC(a); + RCOpArg Rs = gpr.Use(s, RCMode::Read); + RCX64Reg Ra = gpr.Bind(a, RCMode::Write); + RegCache::Realize(Rs, Ra); + RotateLeft(32, Ra, Rs, inst.SH); + needs_test = true; } - else + else if (gpr.IsImm(s)) { - const bool left_shift = mask == 0U - (1U << inst.SH); - const bool right_shift = mask == (1U << inst.SH) - 1; - bool needs_test = false; + RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite); + RegCache::Realize(Ra); + AndWithMask(Ra, ~mask); + OR(32, Ra, Imm32(std::rotl(gpr.Imm32(s), inst.SH) & mask)); + } + else if (gpr.IsImm(a)) + { + const u32 maskA = gpr.Imm32(a) & ~mask; - if (mask == 0 || (a == s && inst.SH == 0)) + RCOpArg Rs = gpr.Use(s, RCMode::Read); + RCX64Reg Ra = gpr.Bind(a, RCMode::Write); + RegCache::Realize(Rs, Ra); + + if (inst.SH == 0) { - needs_test = true; + MOV(32, Ra, Rs); + AndWithMask(Ra, mask); } - else if (mask == 0xFFFFFFFF) + else if (left_shift) { - RCOpArg Rs = gpr.Use(s, RCMode::Read); - RCX64Reg Ra = gpr.Bind(a, RCMode::Write); - RegCache::Realize(Rs, Ra); - RotateLeft(32, Ra, Rs, inst.SH); - needs_test = true; + MOV(32, Ra, Rs); + SHL(32, Ra, Imm8(inst.SH)); } - else if (gpr.IsImm(s)) + else if (right_shift) { - RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite); - RegCache::Realize(Ra); - AndWithMask(Ra, ~mask); - OR(32, Ra, Imm32(std::rotl(gpr.Imm32(s), inst.SH) & mask)); - } - else if (gpr.IsImm(a)) - { - const u32 maskA = gpr.Imm32(a) & ~mask; - - RCOpArg Rs = gpr.Use(s, RCMode::Read); - RCX64Reg Ra = gpr.Bind(a, RCMode::Write); - RegCache::Realize(Rs, Ra); - - if (inst.SH == 0) - { - MOV(32, Ra, Rs); - AndWithMask(Ra, mask); - } - else if (left_shift) - { - MOV(32, Ra, Rs); - SHL(32, Ra, Imm8(inst.SH)); - } - else if (right_shift) - { - MOV(32, Ra, Rs); - SHR(32, Ra, Imm8(32 - inst.SH)); - } - else - { - RotateLeft(32, Ra, Rs, inst.SH); - AndWithMask(Ra, mask); - } - - if (maskA) - OR(32, Ra, Imm32(maskA)); - else - needs_test = true; - } - else if (inst.SH) - { - // TODO: perhaps consider pinsrb or abuse of AH - RCOpArg Rs = gpr.Use(s, RCMode::Read); - RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite); - RegCache::Realize(Rs, Ra); - - if (left_shift) - { - MOV(32, R(RSCRATCH), Rs); - SHL(32, R(RSCRATCH), Imm8(inst.SH)); - } - else if (right_shift) - { - MOV(32, R(RSCRATCH), Rs); - SHR(32, R(RSCRATCH), Imm8(32 - inst.SH)); - } - else - { - RotateLeft(32, RSCRATCH, Rs, inst.SH); - } - - if (mask == 0xFF || mask == 0xFFFF) - { - MOV(mask == 0xFF ? 8 : 16, Ra, R(RSCRATCH)); - needs_test = true; - } - else - { - if (!left_shift && !right_shift) - AndWithMask(RSCRATCH, mask); - AndWithMask(Ra, ~mask); - OR(32, Ra, R(RSCRATCH)); - } + MOV(32, Ra, Rs); + SHR(32, Ra, Imm8(32 - inst.SH)); } else { - RCX64Reg Rs = gpr.Bind(s, RCMode::Read); - RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite); - RegCache::Realize(Rs, Ra); - - if (mask == 0xFF || mask == 0xFFFF) - { - MOV(mask == 0xFF ? 8 : 16, Ra, Rs); - needs_test = true; - } - else - { - XOR(32, Ra, Rs); - AndWithMask(Ra, ~mask); - XOR(32, Ra, Rs); - } + RotateLeft(32, Ra, Rs, inst.SH); + AndWithMask(Ra, mask); } - if (inst.Rc) - ComputeRC(a, needs_test); + + if (maskA) + OR(32, Ra, Imm32(maskA)); + else + needs_test = true; } + else if (inst.SH) + { + // TODO: perhaps consider pinsrb or abuse of AH + RCOpArg Rs = gpr.Use(s, RCMode::Read); + RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite); + RegCache::Realize(Rs, Ra); + + if (left_shift) + { + MOV(32, R(RSCRATCH), Rs); + SHL(32, R(RSCRATCH), Imm8(inst.SH)); + } + else if (right_shift) + { + MOV(32, R(RSCRATCH), Rs); + SHR(32, R(RSCRATCH), Imm8(32 - inst.SH)); + } + else + { + RotateLeft(32, RSCRATCH, Rs, inst.SH); + } + + if (mask == 0xFF || mask == 0xFFFF) + { + MOV(mask == 0xFF ? 8 : 16, Ra, R(RSCRATCH)); + needs_test = true; + } + else + { + if (!left_shift && !right_shift) + AndWithMask(RSCRATCH, mask); + AndWithMask(Ra, ~mask); + OR(32, Ra, R(RSCRATCH)); + } + } + else + { + RCX64Reg Rs = gpr.Bind(s, RCMode::Read); + RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite); + RegCache::Realize(Rs, Ra); + + if (mask == 0xFF || mask == 0xFFFF) + { + MOV(mask == 0xFF ? 8 : 16, Ra, Rs); + needs_test = true; + } + else + { + XOR(32, Ra, Rs); + AndWithMask(Ra, ~mask); + XOR(32, Ra, Rs); + } + } + if (inst.Rc) + ComputeRC(a, needs_test); } void Jit64::rlwnmx(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 55eddf11c03..dd01d6dbddb 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -1975,74 +1975,64 @@ void JitArm64::rlwimix(UGeckoInstruction inst) const u32 width = inst.ME - inst.MB + 1; const u32 rot_dist = inst.SH ? 32 - inst.SH : 0; - if (gpr.IsImm(a) && gpr.IsImm(s)) + if (mask == 0 || (a == s && inst.SH == 0)) { - u32 res = (gpr.GetImm(a) & ~mask) | (std::rotl(gpr.GetImm(s), inst.SH) & mask); - gpr.SetImmediate(a, res); - if (inst.Rc) - ComputeRC0(res); + // Do Nothing } - else + else if (mask == 0xFFFFFFFF) { - if (mask == 0 || (a == s && inst.SH == 0)) - { - // Do Nothing - } - else if (mask == 0xFFFFFFFF) - { - if (inst.SH || a != s) - gpr.BindToRegister(a, a == s); + if (inst.SH || a != s) + gpr.BindToRegister(a, a == s); - if (inst.SH) - ROR(gpr.R(a), gpr.R(s), rot_dist); - else if (a != s) - MOV(gpr.R(a), gpr.R(s)); - } - else if (lsb == 0 && inst.MB <= inst.ME && rot_dist + width <= 32) + if (inst.SH) + ROR(gpr.R(a), gpr.R(s), rot_dist); + else if (a != s) + MOV(gpr.R(a), gpr.R(s)); + } + else if (lsb == 0 && inst.MB <= inst.ME && rot_dist + width <= 32) + { + // Destination is in least significant position + // No mask inversion + // Source field pre-rotation is contiguous + gpr.BindToRegister(a, true); + BFXIL(gpr.R(a), gpr.R(s), rot_dist, width); + } + else if (inst.SH == 0 && inst.MB <= inst.ME) + { + // No rotation + // No mask inversion + gpr.BindToRegister(a, true); + auto WA = gpr.GetScopedReg(); + UBFX(WA, gpr.R(s), lsb, width); + BFI(gpr.R(a), WA, lsb, width); + } + else if (inst.SH && inst.MB <= inst.ME) + { + // No mask inversion + gpr.BindToRegister(a, true); + if ((rot_dist + lsb) % 32 == 0) { - // Destination is in least significant position - // No mask inversion - // Source field pre-rotation is contiguous - gpr.BindToRegister(a, true); - BFXIL(gpr.R(a), gpr.R(s), rot_dist, width); - } - else if (inst.SH == 0 && inst.MB <= inst.ME) - { - // No rotation - // No mask inversion - gpr.BindToRegister(a, true); - auto WA = gpr.GetScopedReg(); - UBFX(WA, gpr.R(s), lsb, width); - BFI(gpr.R(a), WA, lsb, width); - } - else if (inst.SH && inst.MB <= inst.ME) - { - // No mask inversion - gpr.BindToRegister(a, true); - if ((rot_dist + lsb) % 32 == 0) - { - BFI(gpr.R(a), gpr.R(s), lsb, width); - } - else - { - auto WA = gpr.GetScopedReg(); - ROR(WA, gpr.R(s), (rot_dist + lsb) % 32); - BFI(gpr.R(a), WA, lsb, width); - } + BFI(gpr.R(a), gpr.R(s), lsb, width); } else { - gpr.BindToRegister(a, true); - ARM64Reg RA = gpr.R(a); auto WA = gpr.GetScopedReg(); - const u32 inverted_mask = ~mask; - - AND(WA, gpr.R(s), LogicalImm(std::rotl(mask, rot_dist), GPRSize::B32)); - AND(RA, RA, LogicalImm(inverted_mask, GPRSize::B32)); - ORR(RA, RA, WA, ArithOption(WA, ShiftType::ROR, rot_dist)); + ROR(WA, gpr.R(s), (rot_dist + lsb) % 32); + BFI(gpr.R(a), WA, lsb, width); } - - if (inst.Rc) - ComputeRC0(gpr.R(a)); } + else + { + gpr.BindToRegister(a, true); + ARM64Reg RA = gpr.R(a); + auto WA = gpr.GetScopedReg(); + const u32 inverted_mask = ~mask; + + AND(WA, gpr.R(s), LogicalImm(std::rotl(mask, rot_dist), GPRSize::B32)); + AND(RA, RA, LogicalImm(inverted_mask, GPRSize::B32)); + ORR(RA, RA, WA, ArithOption(WA, ShiftType::ROR, rot_dist)); + } + + if (inst.Rc) + ComputeRC0(gpr.R(a)); } diff --git a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp index 5efd3b55e14..b632cd3fc4e 100644 --- a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp @@ -41,6 +41,8 @@ ConstantPropagationResult ConstantPropagation::EvaluateInstruction(UGeckoInstruc case 14: // addi case 15: // addis return EvaluateAddImm(inst); + case 20: // rlwimix + return EvaluateRlwimix(inst); case 21: // rlwinmx return EvaluateRlwinmxRlwnmx(inst, inst.SH); case 23: // rlwnmx @@ -114,6 +116,22 @@ ConstantPropagationResult ConstantPropagation::EvaluateAddImmCarry(UGeckoInstruc return result; } +ConstantPropagationResult ConstantPropagation::EvaluateRlwimix(UGeckoInstruction inst) const +{ + if (!HasGPR(inst.RS)) + return {}; + + const u32 mask = MakeRotationMask(inst.MB, inst.ME); + if (mask == 0xFFFFFFFF) + return ConstantPropagationResult(inst.RA, std::rotl(GetGPR(inst.RS), inst.SH), inst.Rc); + + if (!HasGPR(inst.RA)) + return {}; + + return ConstantPropagationResult( + inst.RA, (GetGPR(inst.RA) & ~mask) | (std::rotl(GetGPR(inst.RS), inst.SH) & mask), inst.Rc); +} + ConstantPropagationResult ConstantPropagation::EvaluateRlwinmxRlwnmx(UGeckoInstruction inst, u32 shift) const { diff --git a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h index 467944a658c..ffbf543ed6d 100644 --- a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h +++ b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h @@ -81,6 +81,7 @@ private: ConstantPropagationResult EvaluateSubImmCarry(UGeckoInstruction inst) const; ConstantPropagationResult EvaluateAddImm(UGeckoInstruction inst) const; ConstantPropagationResult EvaluateAddImmCarry(UGeckoInstruction inst) const; + ConstantPropagationResult EvaluateRlwimix(UGeckoInstruction inst) const; ConstantPropagationResult EvaluateRlwinmxRlwnmx(UGeckoInstruction inst, u32 shift) const; ConstantPropagationResult EvaluateBitwiseImm(UGeckoInstruction inst, u32 (*do_op)(u32, u32)) const;