Jit_Integer: cmpXX

This commit is contained in:
MerryMage 2018-10-15 21:01:21 +01:00
parent b256286690
commit 88e5d0d8b1
1 changed files with 95 additions and 88 deletions

View File

@ -524,42 +524,39 @@ void Jit64::cmpXX(UGeckoInstruction inst)
u32 crf = inst.CRFD;
bool merge_branch = CheckMergedBranch(crf);
OpArg comparand;
bool signedCompare;
if (inst.OPCD == 31)
RCOpArg comparand;
switch (inst.OPCD)
{
// cmp / cmpl
gpr.Lock(a, b);
comparand = gpr.R(b);
// cmp / cmpl
case 31:
signedCompare = (inst.SUBOP10 == 0);
}
else
{
gpr.Lock(a);
if (inst.OPCD == 10)
{
// cmpli
comparand = Imm32((u32)inst.UIMM);
signedCompare = false;
}
else if (inst.OPCD == 11)
{
// cmpi
comparand = Imm32((u32)(s32)(s16)inst.UIMM);
signedCompare = true;
}
else
{
signedCompare = false; // silence compiler warning
PanicAlert("cmpXX");
}
comparand = signedCompare ? gpr.Use(b, RCMode::Read) : gpr.Bind(b, RCMode::Read);
RegCache::Realize(comparand);
break;
// cmpli
case 10:
signedCompare = false;
comparand = RCOpArg::Imm32((u32)inst.UIMM);
break;
// cmpi
case 11:
signedCompare = true;
comparand = RCOpArg::Imm32((u32)(s32)(s16)inst.UIMM);
break;
default:
signedCompare = false; // silence compiler warning
PanicAlert("cmpXX");
}
if (gpr.R(a).IsImm() && comparand.IsImm())
if (gpr.IsImm(a) && comparand.IsImm())
{
// Both registers contain immediate values, so we can pre-compile the compare result
s64 compareResult = signedCompare ? (s64)gpr.R(a).SImm32() - (s64)comparand.SImm32() :
(u64)gpr.R(a).Imm32() - (u64)comparand.Imm32();
s64 compareResult = signedCompare ? (s64)gpr.SImm32(a) - (s64)comparand.SImm32() :
(u64)gpr.Imm32(a) - (u64)comparand.Imm32();
if (compareResult == (s32)compareResult)
{
MOV(64, PPCSTATE(cr_val[crf]), Imm32((u32)compareResult));
@ -571,73 +568,83 @@ void Jit64::cmpXX(UGeckoInstruction inst)
}
if (merge_branch)
{
RegCache::Unlock(comparand);
DoMergedBranchImmediate(compareResult);
}
return;
}
if (!gpr.IsImm(a) && !signedCompare && comparand.IsImm() && comparand.Imm32() == 0)
{
RCX64Reg Ra = gpr.Bind(a, RCMode::Read);
RegCache::Realize(Ra);
MOV(64, PPCSTATE(cr_val[crf]), Ra);
if (merge_branch)
{
TEST(64, Ra, Ra);
RegCache::Unlock(comparand, Ra);
DoMergedBranchCondition();
}
return;
}
const X64Reg input = RSCRATCH;
if (gpr.IsImm(a))
{
if (signedCompare)
MOV(64, R(input), Imm32(gpr.SImm32(a)));
else
MOV(32, R(input), Imm32(gpr.Imm32(a)));
}
else
{
X64Reg input = RSCRATCH;
RCOpArg Ra = gpr.Use(a, RCMode::Read);
RegCache::Realize(Ra);
if (signedCompare)
{
if (gpr.R(a).IsImm())
MOV(64, R(input), Imm32(gpr.R(a).SImm32()));
else
MOVSX(64, 32, input, gpr.R(a));
if (!comparand.IsImm())
{
MOVSX(64, 32, RSCRATCH2, comparand);
comparand = R(RSCRATCH2);
}
}
MOVSX(64, 32, input, Ra);
else
{
if (gpr.R(a).IsImm())
{
MOV(32, R(input), Imm32(gpr.R(a).Imm32()));
}
else if (comparand.IsImm() && !comparand.Imm32())
{
gpr.BindToRegister(a, true, false);
input = gpr.RX(a);
}
else
{
MOVZX(64, 32, input, gpr.R(a));
}
if (comparand.IsImm())
{
// sign extension will ruin this, so store it in a register
if (comparand.Imm32() & 0x80000000U)
{
MOV(32, R(RSCRATCH2), comparand);
comparand = R(RSCRATCH2);
}
}
else
{
gpr.BindToRegister(b, true, false);
comparand = gpr.R(b);
}
}
if (comparand.IsImm() && !comparand.Imm32())
{
MOV(64, PPCSTATE(cr_val[crf]), R(input));
// Place the comparison next to the branch for macro-op fusion
if (merge_branch)
TEST(64, R(input), R(input));
}
else
{
SUB(64, R(input), comparand);
MOV(64, PPCSTATE(cr_val[crf]), R(input));
}
if (merge_branch)
DoMergedBranchCondition();
MOVZX(64, 32, input, Ra);
}
gpr.UnlockAll();
if (comparand.IsImm())
{
// sign extension will ruin this, so store it in a register
if (!signedCompare && (comparand.Imm32() & 0x80000000U) != 0)
{
MOV(32, R(RSCRATCH2), comparand);
comparand = RCOpArg::R(RSCRATCH2);
}
}
else
{
if (signedCompare)
{
MOVSX(64, 32, RSCRATCH2, comparand);
comparand = RCOpArg::R(RSCRATCH2);
}
}
if (comparand.IsImm() && comparand.Imm32() == 0)
{
MOV(64, PPCSTATE(cr_val[crf]), R(input));
// Place the comparison next to the branch for macro-op fusion
if (merge_branch)
TEST(64, R(input), R(input));
}
else
{
SUB(64, R(input), comparand);
MOV(64, PPCSTATE(cr_val[crf]), R(input));
}
if (merge_branch)
{
RegCache::Unlock(comparand);
DoMergedBranchCondition();
}
}
void Jit64::boolX(UGeckoInstruction inst)