diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 3593c37b60..52bddd7e3e 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -6166,6 +6166,12 @@ public: return (std::forward(a) << 16 >> 16) * (std::forward(b) << 16 >> 16); } + template + static auto fm(TA&& a, TB&& b) + { + return (std::forward(a)) * (std::forward(b)); + } + void SF(spu_opcode_t op) { set_vr(op.rt, get_vr(op.rb) - get_vr(op.ra)); @@ -7280,6 +7286,19 @@ public: set_vr(op.rt, -(a * b + c)); } + bool is_input_positive(value_t a) + { + if (auto [ok, v0, v1] = match_expr(a, fm(match(), match())); ok) + { + if (v0.value == v1.value) + { + return true; + } + } + + return false; + } + // clamping helpers value_t clamp_positive_smax(value_t v) { @@ -7288,6 +7307,11 @@ public: value_t clamp_negative_smax(value_t v) { + if (is_input_positive(v)) + { + return v; + } + return eval(bitcast(min(bitcast(v),splat(0xff7fffff)))); } @@ -7474,7 +7498,7 @@ public: if (op.ra == op.rb && !m_interp_magn) { - set_vr(op.rt, a * b); + set_vr(op.rt, fm(a, b)); return; } @@ -7482,7 +7506,7 @@ public: const auto mb = eval(sext(fcmp_uno(b != fsplat(0.)))); const auto ca = eval(bitcast(bitcast(a) & mb)); const auto cb = eval(bitcast(bitcast(b) & ma)); - set_vr(op.rt, ca * cb); + set_vr(op.rt, fm(ca, cb)); } else set_vr(op.rt, get_vr(op.ra) * get_vr(op.rb));