summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2021-12-20 14:20:26 -0500
committerGitHub <noreply@github.com>2021-12-20 14:20:26 -0500
commit9ed368ead7b513d8d2fdca356eee878f5795a8cc (patch)
treee038c9f8c81123ca1b23585101218e3e52d90b7f /Source
parent2d1c7352e4520918419ee9f88ea3a44011c40f20 (diff)
parentcdcca72b61d39811d65eeb9a5f5f3af90a547483 (diff)
Merge pull request #9376 from merryhime/rlwimix2
Jit_Integer: Optimize rlwimix
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp141
1 files changed, 83 insertions, 58 deletions
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
index ac16144d09..7c1b073148 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
@@ -1966,18 +1966,28 @@ void Jit64::rlwimix(UGeckoInstruction inst)
int a = inst.RA;
int s = inst.RS;
+ const u32 mask = MakeRotationMask(inst.MB, inst.ME);
+
if (gpr.IsImm(a, s))
{
- const u32 mask = MakeRotationMask(inst.MB, inst.ME);
gpr.SetImmediate32(a,
(gpr.Imm32(a) & ~mask) | (Common::RotateLeft(gpr.Imm32(s), inst.SH) & mask));
if (inst.Rc)
ComputeRC(a);
}
+ else if (gpr.IsImm(s) && mask == 0xFFFFFFFF)
+ {
+ gpr.SetImmediate32(a, Common::RotateLeft(gpr.Imm32(s), inst.SH));
+
+ if (inst.Rc)
+ ComputeRC(a);
+ }
else
{
- 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 (mask == 0 || (a == s && inst.SH == 0))
{
needs_test = true;
@@ -1997,63 +2007,73 @@ void Jit64::rlwimix(UGeckoInstruction inst)
AndWithMask(Ra, ~mask);
OR(32, Ra, Imm32(Common::RotateLeft(gpr.Imm32(s), inst.SH) & mask));
}
- else if (inst.SH)
+ else if (gpr.IsImm(a))
{
- bool isLeftShift = mask == 0U - (1U << inst.SH);
- bool isRightShift = mask == (1U << inst.SH) - 1;
- if (gpr.IsImm(a))
- {
- u32 maskA = gpr.Imm32(a) & ~mask;
+ 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);
+ RCOpArg Rs = gpr.Use(s, RCMode::Read);
+ RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
+ RegCache::Realize(Rs, Ra);
- if (isLeftShift)
- {
- MOV(32, Ra, Rs);
- SHL(32, Ra, Imm8(inst.SH));
- }
- else if (isRightShift)
- {
- MOV(32, Ra, Rs);
- SHR(32, Ra, Imm8(32 - inst.SH));
- }
- else
- {
- 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 (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
{
- // TODO: common cases of this might be faster with pinsrb or abuse of AH
- RCOpArg Rs = gpr.Use(s, RCMode::Read);
- RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
- RegCache::Realize(Rs, Ra);
+ RotateLeft(32, RSCRATCH, Rs, inst.SH);
+ }
- if (isLeftShift)
- {
- MOV(32, R(RSCRATCH), Rs);
- SHL(32, R(RSCRATCH), Imm8(inst.SH));
- AndWithMask(Ra, ~mask);
- OR(32, Ra, R(RSCRATCH));
- }
- else if (isRightShift)
- {
- MOV(32, R(RSCRATCH), Rs);
- SHR(32, R(RSCRATCH), Imm8(32 - inst.SH));
- AndWithMask(Ra, ~mask);
- OR(32, Ra, R(RSCRATCH));
- }
- else
- {
- RotateLeft(32, RSCRATCH, Rs, inst.SH);
- XOR(32, R(RSCRATCH), Ra);
+ 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);
- XOR(32, Ra, R(RSCRATCH));
- }
+ AndWithMask(Ra, ~mask);
+ OR(32, Ra, R(RSCRATCH));
}
}
else
@@ -2061,9 +2081,18 @@ void Jit64::rlwimix(UGeckoInstruction inst)
RCX64Reg Rs = gpr.Bind(s, RCMode::Read);
RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
RegCache::Realize(Rs, Ra);
- 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);
@@ -2088,11 +2117,7 @@ void Jit64::rlwnmx(UGeckoInstruction inst)
RCOpArg Rs = gpr.Use(s, RCMode::Read);
RegCache::Realize(Ra, Rs);
- if (a != s)
- MOV(32, Ra, Rs);
-
- if (amount)
- ROL(32, Ra, Imm8(amount));
+ RotateLeft(32, Ra, Rs, amount);
// we need flags if we're merging the branch
if (inst.Rc && CheckMergedBranch(0))