ARM64: Implement FP compares, misc

This commit is contained in:
Henrik Rydgard 2015-03-20 23:37:48 +01:00
parent ceb9f66502
commit 25ec85551f
4 changed files with 66 additions and 4 deletions

View File

@ -216,7 +216,7 @@ namespace MIPSComp
} else if (gpr.IsImm(rs) && !symmetric) {
Operand2 op2;
// For SUB, we can use RSB as a reverse operation.
if (TryMakeOperand2(gpr.GetImm(rs), op2) && eval == &EvalSub) {
if (eval == &EvalSub && TryMakeOperand2(gpr.GetImm(rs), op2)) {
gpr.MapDirtyIn(rd, rt);
RSB(gpr.R(rd), gpr.R(rt), op2);
return;

View File

@ -251,7 +251,18 @@ void Arm64Jit::Comp_RType3(MIPSOpcode op) {
CompType3(rd, rs, rt, &ARM64XEmitter::AND, &ARM64XEmitter::TryANDI2R, &EvalAnd, true);
break;
case 37: //R(rd) = R(rs) | R(rt); break; //or
CompType3(rd, rs, rt, &ARM64XEmitter::ORR, &ARM64XEmitter::TryORRI2R, &EvalOr, true);
if (rs == 0 && rd != rt) {
gpr.MapDirtyIn(rd, rt);
MOV(gpr.R(rd), gpr.R(rt));
} else if (rt == 0 && rd != rs) {
gpr.MapDirtyIn(rd, rs);
MOV(gpr.R(rd), gpr.R(rs));
} else if (rt == 0 && rs == 0) {
gpr.MapReg(rd, MAP_DIRTY | MAP_NOINIT);
MOVI2R(gpr.R(rd), 0);
} else {
CompType3(rd, rs, rt, &ARM64XEmitter::ORR, &ARM64XEmitter::TryORRI2R, &EvalOr, true);
}
break;
case 38: //R(rd) = R(rs) ^ R(rt); break; //xor/eor
CompType3(rd, rs, rt, &ARM64XEmitter::EOR, &ARM64XEmitter::TryEORI2R, &EvalEor, true);
@ -466,6 +477,7 @@ void Arm64Jit::Comp_Allegrex2(MIPSOpcode op) {
void Arm64Jit::Comp_MulDivType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
@ -508,7 +520,6 @@ void Arm64Jit::Comp_MulDivType(MIPSOpcode op) {
break;
// TODO: All of these could be more elegant if we cached HI and LO together in one 64-bit register!
case 24: //mult (the most popular one). lo,hi = signed mul (rs * rt)
if (gpr.IsImm(rs) && gpr.IsImm(rt)) {
s64 result = (s64)(s32)gpr.GetImm(rs) * (s64)(s32)gpr.GetImm(rt);

View File

@ -139,7 +139,49 @@ void Arm64Jit::Comp_FPULS(MIPSOpcode op)
}
void Arm64Jit::Comp_FPUComp(MIPSOpcode op) {
DISABLE;
CONDITIONAL_DISABLE;
int opc = op & 0xF;
if (opc >= 8) opc -= 8; // alias
if (opc == 0) { // f, sf (signalling false)
gpr.SetImm(MIPS_REG_FPCOND, 0);
return;
}
int fs = _FS;
int ft = _FT;
gpr.MapReg(MIPS_REG_FPCOND, MAP_DIRTY | MAP_NOINIT);
fpr.MapInIn(fs, ft);
fp.FCMP(fpr.R(fs), fpr.R(ft));
switch (opc) {
case 1: // un, ngle (unordered)
CSET(gpr.R(MIPS_REG_FPCOND), CC_VS);
break;
case 2: // eq, seq (equal, ordered)
CSET(gpr.R(MIPS_REG_FPCOND), CC_EQ);
break;
case 3: // ueq, ngl (equal, unordered)
CSET(gpr.R(MIPS_REG_FPCOND), CC_EQ);
CSET(SCRATCH1, CC_VS);
ORR(gpr.R(MIPS_REG_FPCOND), gpr.R(MIPS_REG_FPCOND), SCRATCH1);
return;
case 4: // olt, lt (less than, ordered)
CSET(gpr.R(MIPS_REG_FPCOND), CC_LO);
break;
case 5: // ult, nge (less than, unordered)
CSET(gpr.R(MIPS_REG_FPCOND), CC_LT);
break;
case 6: // ole, le (less equal, ordered)
CSET(gpr.R(MIPS_REG_FPCOND), CC_LS);
break;
case 7: // ule, ngt (less equal, unordered)
CSET(gpr.R(MIPS_REG_FPCOND), CC_LE);
break;
default:
Comp_Generic(op);
return;
}
}
void Arm64Jit::Comp_FPU2op(MIPSOpcode op) {

View File

@ -117,6 +117,15 @@ namespace MIPSComp
}
void Arm64Jit::Comp_VV2Op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix()) {
DISABLE;
}
// Pre-processing: Eliminate silly no-op VMOVs, common in Wipeout Pure
if (((op >> 16) & 0x1f) == 0 && _VS == _VD && js.HasNoPrefix()) {
return;
}
DISABLE;
}