diff --git a/rpcs3/Emu/CPU/CPUTranslator.h b/rpcs3/Emu/CPU/CPUTranslator.h index 4a9632484f..0288c81f1f 100644 --- a/rpcs3/Emu/CPU/CPUTranslator.h +++ b/rpcs3/Emu/CPU/CPUTranslator.h @@ -361,6 +361,24 @@ struct is_llvm_expr_of::type, typena template using llvm_common_t = std::enable_if_t<(is_llvm_expr_of::ok && ...), typename is_llvm_expr::type>; +template >> +struct llvm_match_t +{ + using type = T; + + llvm::Value* value = nullptr; + + explicit operator bool() const + { + return value != nullptr; + } + + llvm::Value* eval(llvm::IRBuilder<>* ir) const + { + return value; + } +}; + template struct llvm_const_int { diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 1983327f42..b7d2cd5e59 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -2686,6 +2686,31 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator return {get_vr(args)...}; } + template + llvm_match_t match_vr(const bf_t& index) + { + llvm_match_t r; + + if (m_block) + { + auto v = m_block->reg.at(index); + + if (v && v->getType() == get_type()) + { + r.value = v; + return r; + } + } + + return r; + } + + template + std::tuple>...> match_vrs(const Args&... args) + { + return {match_vr(args)...}; + } + void set_reg_fixed(u32 index, llvm::Value* value, bool fixup = true) { llvm::StoreInst* dummy{}; @@ -4962,6 +4987,18 @@ public: void AND(spu_opcode_t op) { + if (const auto [a, b] = match_vrs(op.ra, op.rb); a && b) + { + set_vr(op.rt, a & b); + return; + } + + if (const auto [a, b] = match_vrs(op.ra, op.rb); a && b) + { + set_vr(op.rt, a & b); + return; + } + set_vr(op.rt, get_vr(op.ra) & get_vr(op.rb)); }