diff --git a/src/core/cpu_code_cache.cpp b/src/core/cpu_code_cache.cpp index cb2a23c19..c25d3d969 100644 --- a/src/core/cpu_code_cache.cpp +++ b/src/core/cpu_code_cache.cpp @@ -319,10 +319,14 @@ void ExecuteRecompiler() while (g_state.pending_ticks < g_state.downcount) { +#if 0 + LogCurrentState(); +#endif + const u32 pc = g_state.regs.pc; g_state.current_instruction_pc = pc; const u32 fast_map_index = GetFastMapIndex(pc); - s_single_block_asm_dispatcher[fast_map_index](); + s_single_block_asm_dispatcher(s_fast_map[fast_map_index]); } TimingEvents::RunEvents(); diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index 3ba83b682..b5450317f 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -684,6 +684,54 @@ Value CodeGenerator::OrValues(const Value& lhs, const Value& rhs) return res; } +void CodeGenerator::OrValueInPlace(Value& lhs, const Value& rhs) +{ + DebugAssert(lhs.size == rhs.size); + if (lhs.IsConstant() && rhs.IsConstant()) + { + // compile-time + u64 new_cv = lhs.constant_value | rhs.constant_value; + switch (lhs.size) + { + case RegSize_8: + lhs = Value::FromConstantU8(Truncate8(new_cv)); + break; + + case RegSize_16: + lhs = Value::FromConstantU16(Truncate16(new_cv)); + break; + + case RegSize_32: + lhs = Value::FromConstantU32(Truncate32(new_cv)); + break; + + case RegSize_64: + lhs = Value::FromConstantU64(new_cv); + break; + + default: + lhs = Value(); + break; + } + } + + // unlikely + if (rhs.HasConstantValue(0)) + return; + + if (lhs.IsInHostRegister()) + { + EmitOr(lhs.host_reg, lhs.host_reg, rhs); + } + else + { + Value new_lhs = m_register_cache.AllocateScratch(lhs.size); + EmitCopyValue(new_lhs.host_reg, lhs); + EmitOr(new_lhs.host_reg, new_lhs.host_reg, rhs); + lhs = std::move(new_lhs); + } +} + Value CodeGenerator::AndValues(const Value& lhs, const Value& rhs) { DebugAssert(lhs.size == rhs.size); @@ -2397,6 +2445,13 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi) { // need to adjust the mask Value masked_value = AndValues(value, Value::FromConstantU32(write_mask)); + { + Value old_value = m_register_cache.AllocateScratch(RegSize_32); + EmitLoadCPUStructField(old_value.GetHostRegister(), RegSize_32, offset); + EmitAnd(old_value.GetHostRegister(), old_value.GetHostRegister(), Value::FromConstantU32(~write_mask)); + OrValueInPlace(masked_value, old_value); + } + if (g_settings.UsingPGXPCPUMode()) { EmitFunctionCall(nullptr, &PGXP::CPU_MTC0, Value::FromConstantU32(cbi.instruction.bits), masked_value, diff --git a/src/core/cpu_recompiler_code_generator.h b/src/core/cpu_recompiler_code_generator.h index e6db0e7dd..e07470e79 100644 --- a/src/core/cpu_recompiler_code_generator.h +++ b/src/core/cpu_recompiler_code_generator.h @@ -163,6 +163,7 @@ public: Value ShrValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true); Value SarValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true); Value OrValues(const Value& lhs, const Value& rhs); + void OrValueInPlace(Value& lhs, const Value& rhs); Value AndValues(const Value& lhs, const Value& rhs); void AndValueInPlace(Value& lhs, const Value& rhs); Value XorValues(const Value& lhs, const Value& rhs);