diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index 4e8c044113..d5791c30dd 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -6731,6 +6731,13 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s break; } + if (reg_index != i && ::at32(reg->regs, reg_index)) + { + // Unimplemented + break_reduced_loop_pattern(30, reduced_loop->discard()); + break; + } + u32 cond_val_incr = static_cast(reg_org->IMM); if (reg_org->mod1_type == spu_itype::AI || reg_org->mod1_type == spu_itype::AHI) diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index b13c27e376..9880c167e8 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -2542,9 +2542,24 @@ public: break; } } - } - //condition = m_ir->getInt1(0); + // TODO: Optimze so constant evalatuated cases will not be checked + const bool is_cond_need_runtime_verify = compare == ICmpInst::ICMP_NE && (!m_reduced_loop_info->cond_val_is_immediate || m_reduced_loop_info->cond_val_incr % 2 == 0); + + if (is_cond_need_runtime_verify) + { + // Verify that it is actually possible to finish the loop and it is not an infinite loop + + // First: create a mask of the bits that definitely do not change between iterations (0 results in umax which is accurate here) + const auto no_change_bits = m_ir->CreateAnd(m_ir->CreateNot(cond_val_incr), m_ir->CreateSub(cond_val_incr, m_ir->getIntN(type_bits, 1))); + + // Compare that when the mask applied to both the result and the original value is the same + const auto cond_verify = m_ir->CreateICmpEQ(m_ir->CreateAnd(loop_dictator_after_adjustment, no_change_bits), m_ir->CreateAnd(loop_argument, no_change_bits)); + + // Amend condition + condition = m_ir->CreateAnd(cond_verify, condition); + } + } m_ir->CreateCondBr(condition, optimization_block, block_optimization_next); };