mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
CPU/Recompiler: Don't zero read-only bits in mtc0
Fixes memory card error in Digimon Digital Card Battle.
This commit is contained in:
parent
77d861e7df
commit
520b64e711
|
@ -319,10 +319,14 @@ void ExecuteRecompiler()
|
||||||
|
|
||||||
while (g_state.pending_ticks < g_state.downcount)
|
while (g_state.pending_ticks < g_state.downcount)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
LogCurrentState();
|
||||||
|
#endif
|
||||||
|
|
||||||
const u32 pc = g_state.regs.pc;
|
const u32 pc = g_state.regs.pc;
|
||||||
g_state.current_instruction_pc = pc;
|
g_state.current_instruction_pc = pc;
|
||||||
const u32 fast_map_index = GetFastMapIndex(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();
|
TimingEvents::RunEvents();
|
||||||
|
|
|
@ -684,6 +684,54 @@ Value CodeGenerator::OrValues(const Value& lhs, const Value& rhs)
|
||||||
return res;
|
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)
|
Value CodeGenerator::AndValues(const Value& lhs, const Value& rhs)
|
||||||
{
|
{
|
||||||
DebugAssert(lhs.size == rhs.size);
|
DebugAssert(lhs.size == rhs.size);
|
||||||
|
@ -2397,6 +2445,13 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
||||||
{
|
{
|
||||||
// need to adjust the mask
|
// need to adjust the mask
|
||||||
Value masked_value = AndValues(value, Value::FromConstantU32(write_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())
|
if (g_settings.UsingPGXPCPUMode())
|
||||||
{
|
{
|
||||||
EmitFunctionCall(nullptr, &PGXP::CPU_MTC0, Value::FromConstantU32(cbi.instruction.bits), masked_value,
|
EmitFunctionCall(nullptr, &PGXP::CPU_MTC0, Value::FromConstantU32(cbi.instruction.bits), masked_value,
|
||||||
|
|
|
@ -163,6 +163,7 @@ public:
|
||||||
Value ShrValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true);
|
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 SarValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true);
|
||||||
Value OrValues(const Value& lhs, const Value& rhs);
|
Value OrValues(const Value& lhs, const Value& rhs);
|
||||||
|
void OrValueInPlace(Value& lhs, const Value& rhs);
|
||||||
Value AndValues(const Value& lhs, const Value& rhs);
|
Value AndValues(const Value& lhs, const Value& rhs);
|
||||||
void AndValueInPlace(Value& lhs, const Value& rhs);
|
void AndValueInPlace(Value& lhs, const Value& rhs);
|
||||||
Value XorValues(const Value& lhs, const Value& rhs);
|
Value XorValues(const Value& lhs, const Value& rhs);
|
||||||
|
|
Loading…
Reference in a new issue