Jit_Integer: rlwimix

This commit is contained in:
MerryMage 2018-10-15 21:01:24 +01:00
parent b866b5bdd9
commit 0d3393b306
1 changed files with 45 additions and 35 deletions

View File

@ -1594,17 +1594,16 @@ void Jit64::rlwimix(UGeckoInstruction inst)
int a = inst.RA; int a = inst.RA;
int s = inst.RS; int s = inst.RS;
if (gpr.R(a).IsImm() && gpr.R(s).IsImm()) if (gpr.IsImm(a, s))
{ {
const u32 mask = MakeRotationMask(inst.MB, inst.ME); const u32 mask = MakeRotationMask(inst.MB, inst.ME);
gpr.SetImmediate32(a, (gpr.R(a).Imm32() & ~mask) | gpr.SetImmediate32(a,
(Common::RotateLeft(gpr.R(s).Imm32(), inst.SH) & mask)); (gpr.Imm32(a) & ~mask) | (Common::RotateLeft(gpr.Imm32(s), inst.SH) & mask));
if (inst.Rc) if (inst.Rc)
ComputeRC(gpr.R(a)); ComputeRC(a);
} }
else else
{ {
gpr.Lock(a, s);
const u32 mask = MakeRotationMask(inst.MB, inst.ME); const u32 mask = MakeRotationMask(inst.MB, inst.ME);
bool needs_test = false; bool needs_test = false;
if (mask == 0 || (a == s && inst.SH == 0)) if (mask == 0 || (a == s && inst.SH == 0))
@ -1613,79 +1612,90 @@ void Jit64::rlwimix(UGeckoInstruction inst)
} }
else if (mask == 0xFFFFFFFF) else if (mask == 0xFFFFFFFF)
{ {
gpr.BindToRegister(a, a == s, true); RCOpArg Rs = gpr.Use(s, RCMode::Read);
RCX64Reg Ra = gpr.Bind(a, RCMode::Read);
RegCache::Realize(Rs, Ra);
if (a != s) if (a != s)
MOV(32, gpr.R(a), gpr.R(s)); MOV(32, Ra, Rs);
if (inst.SH) if (inst.SH)
ROL(32, gpr.R(a), Imm8(inst.SH)); ROL(32, Ra, Imm8(inst.SH));
needs_test = true; needs_test = true;
} }
else if (gpr.R(s).IsImm()) else if (gpr.IsImm(s))
{ {
gpr.BindToRegister(a, true, true); RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
AndWithMask(gpr.RX(a), ~mask); RegCache::Realize(Ra);
OR(32, gpr.R(a), Imm32(Common::RotateLeft(gpr.R(s).Imm32(), inst.SH) & mask)); AndWithMask(Ra, ~mask);
OR(32, Ra, Imm32(Common::RotateLeft(gpr.Imm32(s), inst.SH) & mask));
} }
else if (inst.SH) else if (inst.SH)
{ {
bool isLeftShift = mask == 0U - (1U << inst.SH); bool isLeftShift = mask == 0U - (1U << inst.SH);
bool isRightShift = mask == (1U << inst.SH) - 1; bool isRightShift = mask == (1U << inst.SH) - 1;
if (gpr.R(a).IsImm()) if (gpr.IsImm(a))
{ {
u32 maskA = gpr.R(a).Imm32() & ~mask; u32 maskA = gpr.Imm32(a) & ~mask;
gpr.BindToRegister(a, false, true);
MOV(32, gpr.R(a), gpr.R(s)); RCOpArg Rs = gpr.Use(s, RCMode::Read);
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
RegCache::Realize(Rs, Ra);
MOV(32, Ra, Rs);
if (isLeftShift) if (isLeftShift)
{ {
SHL(32, gpr.R(a), Imm8(inst.SH)); SHL(32, Ra, Imm8(inst.SH));
} }
else if (isRightShift) else if (isRightShift)
{ {
SHR(32, gpr.R(a), Imm8(32 - inst.SH)); SHR(32, Ra, Imm8(32 - inst.SH));
} }
else else
{ {
ROL(32, gpr.R(a), Imm8(inst.SH)); ROL(32, Ra, Imm8(inst.SH));
AND(32, gpr.R(a), Imm32(mask)); AND(32, Ra, Imm32(mask));
} }
OR(32, gpr.R(a), Imm32(maskA)); OR(32, Ra, Imm32(maskA));
} }
else else
{ {
// TODO: common cases of this might be faster with pinsrb or abuse of AH // TODO: common cases of this might be faster with pinsrb or abuse of AH
gpr.BindToRegister(a, true, true); RCOpArg Rs = gpr.Use(s, RCMode::Read);
MOV(32, R(RSCRATCH), gpr.R(s)); RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
RegCache::Realize(Rs, Ra);
MOV(32, R(RSCRATCH), Rs);
if (isLeftShift) if (isLeftShift)
{ {
SHL(32, R(RSCRATCH), Imm8(inst.SH)); SHL(32, R(RSCRATCH), Imm8(inst.SH));
AndWithMask(gpr.RX(a), ~mask); AndWithMask(Ra, ~mask);
OR(32, gpr.R(a), R(RSCRATCH)); OR(32, Ra, R(RSCRATCH));
} }
else if (isRightShift) else if (isRightShift)
{ {
SHR(32, R(RSCRATCH), Imm8(32 - inst.SH)); SHR(32, R(RSCRATCH), Imm8(32 - inst.SH));
AndWithMask(gpr.RX(a), ~mask); AndWithMask(Ra, ~mask);
OR(32, gpr.R(a), R(RSCRATCH)); OR(32, Ra, R(RSCRATCH));
} }
else else
{ {
ROL(32, R(RSCRATCH), Imm8(inst.SH)); ROL(32, R(RSCRATCH), Imm8(inst.SH));
XOR(32, R(RSCRATCH), gpr.R(a)); XOR(32, R(RSCRATCH), Ra);
AndWithMask(RSCRATCH, mask); AndWithMask(RSCRATCH, mask);
XOR(32, gpr.R(a), R(RSCRATCH)); XOR(32, Ra, R(RSCRATCH));
} }
} }
} }
else else
{ {
gpr.BindToRegister(a, true, true); RCX64Reg Rs = gpr.Bind(s, RCMode::Read);
XOR(32, gpr.R(a), gpr.R(s)); RCX64Reg Ra = gpr.Bind(a, RCMode::ReadWrite);
AndWithMask(gpr.RX(a), ~mask); RegCache::Realize(Rs, Ra);
XOR(32, gpr.R(a), gpr.R(s)); XOR(32, Ra, Rs);
AndWithMask(Ra, ~mask);
XOR(32, Ra, Rs);
} }
if (inst.Rc) if (inst.Rc)
ComputeRC(gpr.R(a), needs_test); ComputeRC(a, needs_test);
gpr.UnlockAll();
} }
} }