diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 63d70acf48..073285a49b 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -8663,15 +8663,26 @@ public: const auto a = get_vr(op.ra); const auto mask_ov = sext(bitcast(fabs(a)) > splat(0x7e7fffff)); const auto mask_de = eval(noncast(sext(fcmp_ord(a == fsplat(0.)))) >> 1); - set_vr(op.rt, (bitcast(fre(a)) & ~mask_ov) | noncast(mask_de)); + set_vr(op.rt, (bitcast(fsplat(1.0) / a) & ~mask_ov) | noncast(mask_de)); return; } - register_intrinsic("spu_frest", [&](llvm::CallInst* ci) + // To avoid divergence in online play don't use divergent intel/amd intrinsics when online + if (g_cfg.net.net_active == np_internet_status::enabled) { - const auto a = value(ci->getOperand(0)); - return fre(a); - }); + register_intrinsic("spu_frest", [&](llvm::CallInst* ci) + { + return fsplat(1.0) / value(ci->getOperand(0)); + }); + } + else + { + register_intrinsic("spu_frest", [&](llvm::CallInst* ci) + { + const auto a = value(ci->getOperand(0)); + return fre(a); + }); + } set_vr(op.rt, frest(get_vr(op.ra))); } @@ -8691,11 +8702,22 @@ public: return; } - register_intrinsic("spu_frsqest", [&](llvm::CallInst* ci) + // To avoid divergence in online play don't use divergent intel/amd intrinsics when online + if (g_cfg.net.net_active == np_internet_status::enabled) { - const auto a = value(ci->getOperand(0)); - return frsqe(fabs(a)); - }); + register_intrinsic("spu_frsqest", [&](llvm::CallInst* ci) + { + return fsplat(1.0) / fsqrt(fabs(value(ci->getOperand(0)))); + }); + } + else + { + register_intrinsic("spu_frsqest", [&](llvm::CallInst* ci) + { + const auto a = value(ci->getOperand(0)); + return frsqe(fabs(a)); + }); + } set_vr(op.rt, frsqest(get_vr(op.ra))); } @@ -9418,17 +9440,35 @@ public: return bitcast((b & 0xff800000u) | (bitcast(fpcast(bnew)) & ~0xff800000u)); // Inject old sign and exponent }); - register_intrinsic("spu_re", [&](llvm::CallInst* ci) + // To avoid divergence in online play don't use divergent intel/amd intrinsics when online + if (g_cfg.net.net_active == np_internet_status::enabled) { - const auto a = value(ci->getOperand(0)); - return fre(a); - }); + register_intrinsic("spu_re", [&](llvm::CallInst* ci) + { + const auto a = value(ci->getOperand(0)); + return fsplat(1.0) / a; + }); - register_intrinsic("spu_rsqrte", [&](llvm::CallInst* ci) + register_intrinsic("spu_rsqrte", [&](llvm::CallInst* ci) + { + const auto a = value(ci->getOperand(0)); + return fsplat(1.0) / fsqrt(fabs(a)); + }); + } + else { - const auto a = value(ci->getOperand(0)); - return frsqe(fabs(a)); - }); + register_intrinsic("spu_re", [&](llvm::CallInst* ci) + { + const auto a = value(ci->getOperand(0)); + return fre(a); + }); + + register_intrinsic("spu_rsqrte", [&](llvm::CallInst* ci) + { + const auto a = value(ci->getOperand(0)); + return frsqe(a); + }); + } const auto [a, b] = get_vrs(op.ra, op.rb);