summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2024-09-01 11:44:34 +0200
committerJosJuice <josjuice@gmail.com>2025-11-16 09:50:31 +0100
commit502317a4851141a53cc0d94cfecff4c578dafb79 (patch)
treed3be4b42896b34eeef52e3bb26842a9f09335103 /Source/Core
parentbac911aac472f5c1b8cd793769915754772447db (diff)
Jit: Move rlwimix to ConstantPropagation
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp191
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp106
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp18
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h1
4 files changed, 154 insertions, 162 deletions
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
index eb0a6086a0..03bf2fc786 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))
+ {
+ 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 bool left_shift = mask == 0U - (1U << inst.SH);
- const bool right_shift = mask == (1U << inst.SH) - 1;
- bool needs_test = false;
+ 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));
+ MOV(32, Ra, Rs);
+ SHR(32, Ra, Imm8(32 - inst.SH));
}
- else if (gpr.IsImm(a))
+ else
{
- 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);
+ RotateLeft(32, Ra, Rs, inst.SH);
+ AndWithMask(Ra, mask);
+ }
- 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 (maskA)
- OR(32, Ra, Imm32(maskA));
- else
- needs_test = true;
+ if (left_shift)
+ {
+ MOV(32, R(RSCRATCH), Rs);
+ SHL(32, R(RSCRATCH), Imm8(inst.SH));
}
- else if (inst.SH)
+ else if (right_shift)
{
- // 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);
- }
+ 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));
- }
+ if (mask == 0xFF || mask == 0xFFFF)
+ {
+ MOV(mask == 0xFF ? 8 : 16, Ra, R(RSCRATCH));
+ needs_test = true;
}
else
{
- RCX64Reg Rs = gpr.Bind(s, RCMode::Read);
- RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
- RegCache::Realize(Rs, Ra);
+ 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 (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);
}
+ 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 55eddf11c0..dd01d6dbdd 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)
- {
- // 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)
+ 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)
{
- // 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);
}
+ }
+ else
+ {
+ gpr.BindToRegister(a, true);
+ ARM64Reg RA = gpr.R(a);
+ auto WA = gpr.GetScopedReg();
+ const u32 inverted_mask = ~mask;
- if (inst.Rc)
- ComputeRC0(gpr.R(a));
+ 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 5efd3b55e1..b632cd3fc4 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 467944a658..ffbf543ed6 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;