From 4caf747729431fd9f93619761effac79c162c33a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 23 Nov 2019 19:31:42 +0300 Subject: [PATCH] SPU LLVM: detect mpy32 pattern --- rpcs3/Emu/Cell/SPURecompiler.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 377a2d420d..a0cca6ae01 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -6110,6 +6110,18 @@ public: // Check SPUInterpreter for notes. } + template + static auto mpyh(TA&& a, TB&& b) + { + return (std::forward(a) >> 16) * (std::forward(b) << 16); + } + + template + static auto mpyu(TA&& a, TB&& b) + { + return (std::forward(a) << 16 >> 16) * (std::forward(b) << 16 >> 16); + } + void SF(spu_opcode_t op) { set_vr(op.rt, get_vr(op.rb) - get_vr(op.ra)); @@ -6268,6 +6280,22 @@ public: void A(spu_opcode_t op) { + if (auto [a, b] = match_vrs(op.ra, op.rb); a && b) + { + static const auto MP = match(); + + if (auto [ok, a0, b0, b1, a1] = match_expr(a, mpyh(MP, MP) + mpyh(MP, MP)); ok) + { + if (auto [ok, a2, b2] = match_expr(b, mpyu(MP, MP)); ok && a2.eq(a0, a1) && b2.eq(b0, b1)) + { + // 32-bit multiplication + LOG_NOTICE(SPU, "mpy32 in %s at 0x%05x", m_hash, m_pos); + set_vr(op.rt, a0 * b0); + return; + } + } + } + set_vr(op.rt, get_vr(op.ra) + get_vr(op.rb)); } @@ -6729,7 +6757,7 @@ public: void MPYH(spu_opcode_t op) { - set_vr(op.rt, (get_vr(op.ra) >> 16) * (get_vr(op.rb) << 16)); + set_vr(op.rt, mpyh(get_vr(op.ra), get_vr(op.rb))); } void MPYHH(spu_opcode_t op) @@ -6749,7 +6777,7 @@ public: void MPYU(spu_opcode_t op) { - set_vr(op.rt, (get_vr(op.ra) << 16 >> 16) * (get_vr(op.rb) << 16 >> 16)); + set_vr(op.rt, mpyu(get_vr(op.ra), get_vr(op.rb))); } void CEQB(spu_opcode_t op)