diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 6b6681f554..4caefaf716 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -7350,17 +7350,32 @@ public: { v128 data = get_const_vector(cv, m_pos, 5000); bool safe_int_compare = true; + bool safe_simple_compare = true; for (u32 i = 0; i < 4; i++) { const u32 exponent = data._u32[i] & 0x7f800000u; + const u32 sign_bit = data._u32[i] & 0x80000000u; + const u32 absolute_float_bits = data._u32[i] & 0x7fffffffu; if (data._u32[i] >= 0x7f7fffffu || !exponent) { // Postive or negative zero, Denormal (treated as zero), Negative constant, or Normalized number with exponent +127 // Cannot used signed integer compare safely + // Note: Technically this optimization is accurate for any positive value, but due to the fact that + // we don't produce "extended range" values the same way as real hardware, it's not safe to apply + // this optimization for values outside of the range of x86 floating point hardware. safe_int_compare = false; - break; + } + + if (absolute_float_bits < 0x7f7fffffu) + { + // Zero or a float in normalized range for x86 + continue; + } + else + { + safe_simple_compare = false; } } @@ -7369,6 +7384,12 @@ public: set_vr(op.rt, sext(bitcast(a) > bitcast(b))); return; } + + if (safe_simple_compare) + { + set_vr(op.rt, sext(fcmp_uno(a > b))); + return; + } } if (auto cv = llvm::dyn_cast(a.value))