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;
|
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
|
// cmpli
|
||||||
comparand = Imm32((u32)inst.UIMM);
|
case 10:
|
||||||
signedCompare = false;
|
signedCompare = false;
|
||||||
}
|
comparand = RCOpArg::Imm32((u32)inst.UIMM);
|
||||||
else if (inst.OPCD == 11)
|
break;
|
||||||
{
|
|
||||||
// cmpi
|
// cmpi
|
||||||
comparand = Imm32((u32)(s32)(s16)inst.UIMM);
|
case 11:
|
||||||
signedCompare = true;
|
signedCompare = true;
|
||||||
}
|
comparand = RCOpArg::Imm32((u32)(s32)(s16)inst.UIMM);
|
||||||
else
|
break;
|
||||||
{
|
|
||||||
|
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,56 +568,66 @@ void Jit64::cmpXX(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (merge_branch)
|
if (merge_branch)
|
||||||
|
{
|
||||||
|
RegCache::Unlock(comparand);
|
||||||
DoMergedBranchImmediate(compareResult);
|
DoMergedBranchImmediate(compareResult);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
X64Reg input = RSCRATCH;
|
|
||||||
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())
|
return;
|
||||||
{
|
|
||||||
MOVSX(64, 32, RSCRATCH2, comparand);
|
|
||||||
comparand = R(RSCRATCH2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
{
|
{
|
||||||
if (gpr.R(a).IsImm())
|
RCOpArg Ra = gpr.Use(a, RCMode::Read);
|
||||||
{
|
RegCache::Realize(Ra);
|
||||||
MOV(32, R(input), Imm32(gpr.R(a).Imm32()));
|
if (signedCompare)
|
||||||
}
|
MOVSX(64, 32, input, Ra);
|
||||||
else if (comparand.IsImm() && !comparand.Imm32())
|
|
||||||
{
|
|
||||||
gpr.BindToRegister(a, true, false);
|
|
||||||
input = gpr.RX(a);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
MOVZX(64, 32, input, Ra);
|
||||||
MOVZX(64, 32, input, gpr.R(a));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comparand.IsImm())
|
if (comparand.IsImm())
|
||||||
{
|
{
|
||||||
// sign extension will ruin this, so store it in a register
|
// sign extension will ruin this, so store it in a register
|
||||||
if (comparand.Imm32() & 0x80000000U)
|
if (!signedCompare && (comparand.Imm32() & 0x80000000U) != 0)
|
||||||
{
|
{
|
||||||
MOV(32, R(RSCRATCH2), comparand);
|
MOV(32, R(RSCRATCH2), comparand);
|
||||||
comparand = R(RSCRATCH2);
|
comparand = RCOpArg::R(RSCRATCH2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gpr.BindToRegister(b, true, false);
|
if (signedCompare)
|
||||||
comparand = gpr.R(b);
|
{
|
||||||
|
MOVSX(64, 32, RSCRATCH2, comparand);
|
||||||
|
comparand = RCOpArg::R(RSCRATCH2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (comparand.IsImm() && !comparand.Imm32())
|
|
||||||
|
if (comparand.IsImm() && comparand.Imm32() == 0)
|
||||||
{
|
{
|
||||||
MOV(64, PPCSTATE(cr_val[crf]), R(input));
|
MOV(64, PPCSTATE(cr_val[crf]), R(input));
|
||||||
// Place the comparison next to the branch for macro-op fusion
|
// Place the comparison next to the branch for macro-op fusion
|
||||||
|
@ -634,10 +641,10 @@ void Jit64::cmpXX(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (merge_branch)
|
if (merge_branch)
|
||||||
|
{
|
||||||
|
RegCache::Unlock(comparand);
|
||||||
DoMergedBranchCondition();
|
DoMergedBranchCondition();
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr.UnlockAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::boolX(UGeckoInstruction inst)
|
void Jit64::boolX(UGeckoInstruction inst)
|
||||||
|
|
Loading…
Reference in New Issue