diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index ce807524cd..116af6b02c 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -5620,24 +5620,32 @@ public: const auto [a, b] = get_vrs(op.ra, op.rb); - // Resistance 2 doesn't like this - if (g_cfg.core.spu_xfloat_accuracy == xfloat_accuracy::relaxed) + auto full_fm_accurate = [&](const auto& a, const auto& div) { - // FM(a, re_accurate(div)) - if (const auto [ok_re_acc, div, one] = match_expr(b, re_accurate(match(), match())); ok_re_acc) - { - erase_stores(one, b); - set_vr(op.rt, a / div); - return; - } + const auto div_result = a / div; + const auto result_and = bitcast(div_result) & 0x7fffffffu; + const auto result_cmp_inf = sext(result_and == splat(0x7F800000u)); + const auto result_cmp_nan = sext(result_and <= splat(0x7F800000u)); - // FM(re_accurate(div), b) - if (const auto [ok_re_acc, div, one] = match_expr(a, re_accurate(match(), match())); ok_re_acc) - { - erase_stores(one, a); - set_vr(op.rt, b / div); - return; - } + const auto and_mask = bitcast(result_cmp_nan) & splat(0xFFFFFFFFu); + const auto or_mask = bitcast(result_cmp_inf) & splat(0xFFFFFFFu); + set_vr(op.rt, bitcast((bitcast(div_result) & and_mask) | or_mask)); + }; + + // FM(a, re_accurate(div)) + if (const auto [ok_re_acc, div, one] = match_expr(b, re_accurate(match(), match())); ok_re_acc) + { + full_fm_accurate(a, div); + erase_stores(one, b); + return; + } + + // FM(re_accurate(div), b) + if (const auto [ok_re_acc, div, one] = match_expr(a, re_accurate(match(), match())); ok_re_acc) + { + full_fm_accurate(b, div); + erase_stores(one, a); + return; } set_vr(op.rt, fm(a, b)); @@ -6007,10 +6015,10 @@ public: const auto result_and = bitcast(div_result) & 0x7fffffffu; const auto result_cmp_inf = sext(result_and == splat(0x7F800000u)); const auto result_cmp_nan = sext(result_and <= splat(0x7F800000u)); - + const auto and_mask = bitcast(result_cmp_nan) & splat(0xFFFFFFFFu); const auto or_mask = bitcast(result_cmp_inf) & splat(0xFFFFFFFu); - + return bitcast((bitcast(div_result) & and_mask) | or_mask); });