Jit_Integer: cmpXX

This commit is contained in:
MerryMage 2018-10-15 21:01:21 +01:00
parent b256286690
commit 88e5d0d8b1

View File

@ -524,42 +524,39 @@ void Jit64::cmpXX(UGeckoInstruction inst)
u32 crf = inst.CRFD; u32 crf = inst.CRFD;
bool merge_branch = CheckMergedBranch(crf); bool merge_branch = CheckMergedBranch(crf);
OpArg comparand;
bool signedCompare; bool signedCompare;
if (inst.OPCD == 31) RCOpArg comparand;
switch (inst.OPCD)
{ {
// cmp / cmpl // cmp / cmpl
gpr.Lock(a, b); case 31:
comparand = gpr.R(b);
signedCompare = (inst.SUBOP10 == 0); signedCompare = (inst.SUBOP10 == 0);
} comparand = signedCompare ? gpr.Use(b, RCMode::Read) : gpr.Bind(b, RCMode::Read);
else RegCache::Realize(comparand);
{ break;
gpr.Lock(a);
if (inst.OPCD == 10) // cmpli
{ case 10:
// cmpli signedCompare = false;
comparand = Imm32((u32)inst.UIMM); comparand = RCOpArg::Imm32((u32)inst.UIMM);
signedCompare = false; break;
}
else if (inst.OPCD == 11) // cmpi
{ case 11:
// cmpi signedCompare = true;
comparand = Imm32((u32)(s32)(s16)inst.UIMM); comparand = RCOpArg::Imm32((u32)(s32)(s16)inst.UIMM);
signedCompare = true; break;
}
else default:
{ signedCompare = false; // silence compiler warning
signedCompare = false; // silence compiler warning PanicAlert("cmpXX");
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 // Both registers contain immediate values, so we can pre-compile the compare result
s64 compareResult = signedCompare ? (s64)gpr.R(a).SImm32() - (s64)comparand.SImm32() : s64 compareResult = signedCompare ? (s64)gpr.SImm32(a) - (s64)comparand.SImm32() :
(u64)gpr.R(a).Imm32() - (u64)comparand.Imm32(); (u64)gpr.Imm32(a) - (u64)comparand.Imm32();
if (compareResult == (s32)compareResult) if (compareResult == (s32)compareResult)
{ {
MOV(64, PPCSTATE(cr_val[crf]), Imm32((u32)compareResult)); MOV(64, PPCSTATE(cr_val[crf]), Imm32((u32)compareResult));
@ -571,73 +568,83 @@ void Jit64::cmpXX(UGeckoInstruction inst)
} }
if (merge_branch) if (merge_branch)
{
RegCache::Unlock(comparand);
DoMergedBranchImmediate(compareResult); 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 else
{ {
X64Reg input = RSCRATCH; RCOpArg Ra = gpr.Use(a, RCMode::Read);
RegCache::Realize(Ra);
if (signedCompare) if (signedCompare)
{ MOVSX(64, 32, input, Ra);
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);
}
}
else else
{ MOVZX(64, 32, input, Ra);
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();
} }
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) void Jit64::boolX(UGeckoInstruction inst)