diff --git a/Core/MIPS/RiscV/RiscVCompFPU.cpp b/Core/MIPS/RiscV/RiscVCompFPU.cpp index a99cff0b86..27ab1a943f 100644 --- a/Core/MIPS/RiscV/RiscVCompFPU.cpp +++ b/Core/MIPS/RiscV/RiscVCompFPU.cpp @@ -51,7 +51,35 @@ void RiscVJit::CompIR_FArith(IRInst inst) { case IROp::FMul: fpr.MapDirtyInIn(inst.dest, inst.src1, inst.src2); if (inst.src1 != inst.src2) { - CompIR_Generic(inst); + // These will output 0x80/0x01 if infinity, 0x10/0x80 if zero. + // We need to check if one is infinity and the other zero. + + // First, try inf * zero. + FCLASS(32, SCRATCH1, fpr.R(inst.src1)); + FCLASS(32, SCRATCH2, fpr.R(inst.src2)); + ANDI(R_RA, SCRATCH1, 0x81); + FixupBranch lhsNotInf = BEQ(R_RA, R_ZERO); + ANDI(R_RA, SCRATCH2, 0x18); + FixupBranch infZero = BNE(R_RA, R_ZERO); + + // Okay, what about the other order? + SetJumpTarget(lhsNotInf); + ANDI(R_RA, SCRATCH1, 0x18); + FixupBranch lhsNotZero = BEQ(R_RA, R_ZERO); + ANDI(R_RA, SCRATCH2, 0x81); + FixupBranch zeroInf = BNE(R_RA, R_ZERO); + + // Nope, all good. + SetJumpTarget(lhsNotZero); + FMUL(32, fpr.R(inst.dest), fpr.R(inst.src1), fpr.R(inst.src2)); + FixupBranch skip = J(); + + SetJumpTarget(infZero); + SetJumpTarget(zeroInf); + LI(SCRATCH1, 0x7FC00000); + FMV(FMv::W, FMv::X, fpr.R(inst.dest), SCRATCH1); + + SetJumpTarget(skip); } else { FMUL(32, fpr.R(inst.dest), fpr.R(inst.src1), fpr.R(inst.src2)); }