From 6aa4b0c5e11c4c70d7b0a7de82ea300db7bffaf5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 29 Jul 2023 19:13:12 -0700 Subject: [PATCH] irjit: Fix vmin/vmax nan handling. Should be relevant to NFS MW and possibly other game bugs. --- Core/MIPS/IR/IRInterpreter.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Core/MIPS/IR/IRInterpreter.cpp b/Core/MIPS/IR/IRInterpreter.cpp index 561adf6f25..cb752d35b1 100644 --- a/Core/MIPS/IR/IRInterpreter.cpp +++ b/Core/MIPS/IR/IRInterpreter.cpp @@ -768,12 +768,28 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { mips->f[inst->dest] = mips->f[inst->src1] / mips->f[inst->src2]; break; case IROp::FMin: - // TODO: This doesn't handle VFPU ordering right. - mips->f[inst->dest] = std::min(mips->f[inst->src1], mips->f[inst->src2]); + if (my_isnan(mips->f[inst->src1]) || my_isnan(mips->f[inst->src2])) { + // See interpreter for this logic: this is for vmin, we're comparing mantissa+exp. + if (mips->fi[inst->src1] < 0 && mips->fi[inst->src2] < 0) { + mips->fi[inst->dest] = std::max(mips->fi[inst->src1], mips->fi[inst->src2]); + } else { + mips->fi[inst->dest] = std::min(mips->fi[inst->src1], mips->fi[inst->src2]); + } + } else { + mips->f[inst->dest] = std::min(mips->f[inst->src1], mips->f[inst->src2]); + } break; case IROp::FMax: - // TODO: This doesn't handle VFPU ordering right. - mips->f[inst->dest] = std::max(mips->f[inst->src1], mips->f[inst->src2]); + if (my_isnan(mips->f[inst->src1]) || my_isnan(mips->f[inst->src2])) { + // See interpreter for this logic: this is for vmax, we're comparing mantissa+exp. + if (mips->fi[inst->src1] < 0 && mips->fi[inst->src2] < 0) { + mips->fi[inst->dest] = std::min(mips->fi[inst->src1], mips->fi[inst->src2]); + } else { + mips->fi[inst->dest] = std::max(mips->fi[inst->src1], mips->fi[inst->src2]); + } + } else { + mips->f[inst->dest] = std::max(mips->f[inst->src1], mips->f[inst->src2]); + } break; case IROp::FMov: