Jit_Integer: cmpXX
This commit is contained in:
parent
b256286690
commit
88e5d0d8b1
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue