mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-12-16 04:09:39 +00:00
Jit: Move rlwimix to ConstantPropagation
This commit is contained in:
parent
bac911aac4
commit
502317a485
@ -1997,135 +1997,118 @@ void Jit64::rlwimix(UGeckoInstruction inst)
|
|||||||
int s = inst.RS;
|
int s = inst.RS;
|
||||||
|
|
||||||
const u32 mask = MakeRotationMask(inst.MB, inst.ME);
|
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));
|
needs_test = true;
|
||||||
if (inst.Rc)
|
|
||||||
ComputeRC(a);
|
|
||||||
}
|
}
|
||||||
else if (gpr.IsImm(s) && mask == 0xFFFFFFFF)
|
else if (mask == 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
gpr.SetImmediate32(a, std::rotl(gpr.Imm32(s), inst.SH));
|
RCOpArg Rs = gpr.Use(s, RCMode::Read);
|
||||||
|
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
|
||||||
if (inst.Rc)
|
RegCache::Realize(Rs, Ra);
|
||||||
ComputeRC(a);
|
RotateLeft(32, Ra, Rs, inst.SH);
|
||||||
|
needs_test = true;
|
||||||
}
|
}
|
||||||
else
|
else if (gpr.IsImm(s))
|
||||||
{
|
{
|
||||||
const bool left_shift = mask == 0U - (1U << inst.SH);
|
RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
|
||||||
const bool right_shift = mask == (1U << inst.SH) - 1;
|
RegCache::Realize(Ra);
|
||||||
bool needs_test = false;
|
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);
|
MOV(32, Ra, Rs);
|
||||||
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
|
SHL(32, Ra, Imm8(inst.SH));
|
||||||
RegCache::Realize(Rs, Ra);
|
|
||||||
RotateLeft(32, Ra, Rs, inst.SH);
|
|
||||||
needs_test = true;
|
|
||||||
}
|
}
|
||||||
else if (gpr.IsImm(s))
|
else if (right_shift)
|
||||||
{
|
{
|
||||||
RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
|
MOV(32, Ra, Rs);
|
||||||
RegCache::Realize(Ra);
|
SHR(32, Ra, Imm8(32 - inst.SH));
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RCX64Reg Rs = gpr.Bind(s, RCMode::Read);
|
RotateLeft(32, Ra, Rs, inst.SH);
|
||||||
RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
|
AndWithMask(Ra, mask);
|
||||||
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);
|
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)
|
void Jit64::rlwnmx(UGeckoInstruction inst)
|
||||||
|
|||||||
@ -1975,74 +1975,64 @@ void JitArm64::rlwimix(UGeckoInstruction inst)
|
|||||||
const u32 width = inst.ME - inst.MB + 1;
|
const u32 width = inst.ME - inst.MB + 1;
|
||||||
const u32 rot_dist = inst.SH ? 32 - inst.SH : 0;
|
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);
|
// Do Nothing
|
||||||
gpr.SetImmediate(a, res);
|
|
||||||
if (inst.Rc)
|
|
||||||
ComputeRC0(res);
|
|
||||||
}
|
}
|
||||||
else
|
else if (mask == 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
if (mask == 0 || (a == s && inst.SH == 0))
|
if (inst.SH || a != s)
|
||||||
{
|
gpr.BindToRegister(a, a == s);
|
||||||
// Do Nothing
|
|
||||||
}
|
|
||||||
else if (mask == 0xFFFFFFFF)
|
|
||||||
{
|
|
||||||
if (inst.SH || a != s)
|
|
||||||
gpr.BindToRegister(a, a == s);
|
|
||||||
|
|
||||||
if (inst.SH)
|
if (inst.SH)
|
||||||
ROR(gpr.R(a), gpr.R(s), rot_dist);
|
ROR(gpr.R(a), gpr.R(s), rot_dist);
|
||||||
else if (a != s)
|
else if (a != s)
|
||||||
MOV(gpr.R(a), gpr.R(s));
|
MOV(gpr.R(a), gpr.R(s));
|
||||||
}
|
}
|
||||||
else if (lsb == 0 && inst.MB <= inst.ME && rot_dist + width <= 32)
|
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
|
BFI(gpr.R(a), gpr.R(s), lsb, width);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gpr.BindToRegister(a, true);
|
|
||||||
ARM64Reg RA = gpr.R(a);
|
|
||||||
auto WA = gpr.GetScopedReg();
|
auto WA = gpr.GetScopedReg();
|
||||||
const u32 inverted_mask = ~mask;
|
ROR(WA, gpr.R(s), (rot_dist + lsb) % 32);
|
||||||
|
BFI(gpr.R(a), WA, lsb, width);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,8 @@ ConstantPropagationResult ConstantPropagation::EvaluateInstruction(UGeckoInstruc
|
|||||||
case 14: // addi
|
case 14: // addi
|
||||||
case 15: // addis
|
case 15: // addis
|
||||||
return EvaluateAddImm(inst);
|
return EvaluateAddImm(inst);
|
||||||
|
case 20: // rlwimix
|
||||||
|
return EvaluateRlwimix(inst);
|
||||||
case 21: // rlwinmx
|
case 21: // rlwinmx
|
||||||
return EvaluateRlwinmxRlwnmx(inst, inst.SH);
|
return EvaluateRlwinmxRlwnmx(inst, inst.SH);
|
||||||
case 23: // rlwnmx
|
case 23: // rlwnmx
|
||||||
@ -114,6 +116,22 @@ ConstantPropagationResult ConstantPropagation::EvaluateAddImmCarry(UGeckoInstruc
|
|||||||
return result;
|
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,
|
ConstantPropagationResult ConstantPropagation::EvaluateRlwinmxRlwnmx(UGeckoInstruction inst,
|
||||||
u32 shift) const
|
u32 shift) const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -81,6 +81,7 @@ private:
|
|||||||
ConstantPropagationResult EvaluateSubImmCarry(UGeckoInstruction inst) const;
|
ConstantPropagationResult EvaluateSubImmCarry(UGeckoInstruction inst) const;
|
||||||
ConstantPropagationResult EvaluateAddImm(UGeckoInstruction inst) const;
|
ConstantPropagationResult EvaluateAddImm(UGeckoInstruction inst) const;
|
||||||
ConstantPropagationResult EvaluateAddImmCarry(UGeckoInstruction inst) const;
|
ConstantPropagationResult EvaluateAddImmCarry(UGeckoInstruction inst) const;
|
||||||
|
ConstantPropagationResult EvaluateRlwimix(UGeckoInstruction inst) const;
|
||||||
ConstantPropagationResult EvaluateRlwinmxRlwnmx(UGeckoInstruction inst, u32 shift) const;
|
ConstantPropagationResult EvaluateRlwinmxRlwnmx(UGeckoInstruction inst, u32 shift) const;
|
||||||
ConstantPropagationResult EvaluateBitwiseImm(UGeckoInstruction inst,
|
ConstantPropagationResult EvaluateBitwiseImm(UGeckoInstruction inst,
|
||||||
u32 (*do_op)(u32, u32)) const;
|
u32 (*do_op)(u32, u32)) const;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user