mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-08 04:25:37 +00:00
CPU: Don't stall until GTE completion on write
Apparently this is what the real CPU does, and some very optimized code can run slower if we stall early. Obviously if you write to a register being read by the command, things are going to break.
This commit is contained in:
parent
7d80a74dc3
commit
8772c336ec
@ -1851,8 +1851,6 @@ restart_instruction:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StallUntilGTEComplete();
|
|
||||||
|
|
||||||
if (inst.cop.IsCommonInstruction())
|
if (inst.cop.IsCommonInstruction())
|
||||||
{
|
{
|
||||||
// TODO: Combine with cop0.
|
// TODO: Combine with cop0.
|
||||||
@ -1860,6 +1858,8 @@ restart_instruction:
|
|||||||
{
|
{
|
||||||
case CopCommonInstruction::cfcn:
|
case CopCommonInstruction::cfcn:
|
||||||
{
|
{
|
||||||
|
StallUntilGTEComplete();
|
||||||
|
|
||||||
const u32 value = GTE::ReadRegister(static_cast<u32>(inst.r.rd.GetValue()) + 32);
|
const u32 value = GTE::ReadRegister(static_cast<u32>(inst.r.rd.GetValue()) + 32);
|
||||||
WriteRegDelayed(inst.r.rt, value);
|
WriteRegDelayed(inst.r.rt, value);
|
||||||
|
|
||||||
@ -1880,6 +1880,8 @@ restart_instruction:
|
|||||||
|
|
||||||
case CopCommonInstruction::mfcn:
|
case CopCommonInstruction::mfcn:
|
||||||
{
|
{
|
||||||
|
StallUntilGTEComplete();
|
||||||
|
|
||||||
const u32 value = GTE::ReadRegister(static_cast<u32>(inst.r.rd.GetValue()));
|
const u32 value = GTE::ReadRegister(static_cast<u32>(inst.r.rd.GetValue()));
|
||||||
WriteRegDelayed(inst.r.rt, value);
|
WriteRegDelayed(inst.r.rt, value);
|
||||||
|
|
||||||
@ -1906,6 +1908,7 @@ restart_instruction:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
StallUntilGTEComplete();
|
||||||
GTE::ExecuteInstruction(inst.bits);
|
GTE::ExecuteInstruction(inst.bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1925,7 +1928,6 @@ restart_instruction:
|
|||||||
if (!ReadMemoryWord(addr, &value))
|
if (!ReadMemoryWord(addr, &value))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StallUntilGTEComplete();
|
|
||||||
GTE::WriteRegister(ZeroExtend32(static_cast<u8>(inst.i.rt.GetValue())), value);
|
GTE::WriteRegister(ZeroExtend32(static_cast<u8>(inst.i.rt.GetValue())), value);
|
||||||
|
|
||||||
if constexpr (pgxp_mode >= PGXPMode::Memory)
|
if constexpr (pgxp_mode >= PGXPMode::Memory)
|
||||||
|
@ -1301,8 +1301,8 @@ void CPU::Recompiler::Recompiler::CompileInstruction()
|
|||||||
{
|
{
|
||||||
case CopCommonInstruction::mfcn: if (inst->r.rt != Reg::zero) { CompileTemplate(nullptr, &Recompiler::Compile_mfc2, nullptr, TF_GTE_STALL); } break;
|
case CopCommonInstruction::mfcn: if (inst->r.rt != Reg::zero) { CompileTemplate(nullptr, &Recompiler::Compile_mfc2, nullptr, TF_GTE_STALL); } break;
|
||||||
case CopCommonInstruction::cfcn: if (inst->r.rt != Reg::zero) { CompileTemplate(nullptr, &Recompiler::Compile_mfc2, nullptr, TF_GTE_STALL); } break;
|
case CopCommonInstruction::cfcn: if (inst->r.rt != Reg::zero) { CompileTemplate(nullptr, &Recompiler::Compile_mfc2, nullptr, TF_GTE_STALL); } break;
|
||||||
case CopCommonInstruction::mtcn: CompileTemplate(nullptr, &Recompiler::Compile_mtc2, PGXPFN(CPU_MTC2), TF_GTE_STALL | TF_READS_T | TF_PGXP_WITHOUT_CPU); break;
|
case CopCommonInstruction::mtcn: CompileTemplate(nullptr, &Recompiler::Compile_mtc2, PGXPFN(CPU_MTC2), TF_READS_T | TF_PGXP_WITHOUT_CPU); break;
|
||||||
case CopCommonInstruction::ctcn: CompileTemplate(nullptr, &Recompiler::Compile_mtc2, PGXPFN(CPU_MTC2), TF_GTE_STALL | TF_READS_T | TF_PGXP_WITHOUT_CPU); break;
|
case CopCommonInstruction::ctcn: CompileTemplate(nullptr, &Recompiler::Compile_mtc2, PGXPFN(CPU_MTC2), TF_READS_T | TF_PGXP_WITHOUT_CPU); break;
|
||||||
default: Compile_Fallback(); break;
|
default: Compile_Fallback(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1314,7 +1314,7 @@ void CPU::Recompiler::Recompiler::CompileInstruction()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InstructionOp::lwc2: CompileLoadStoreTemplate(&Recompiler::Compile_lwc2, MemoryAccessSize::Word, false, false, TF_GTE_STALL | TF_READS_S | TF_LOAD_DELAY); break;
|
case InstructionOp::lwc2: CompileLoadStoreTemplate(&Recompiler::Compile_lwc2, MemoryAccessSize::Word, false, false, TF_READS_S | TF_LOAD_DELAY); break;
|
||||||
case InstructionOp::swc2: CompileLoadStoreTemplate(&Recompiler::Compile_swc2, MemoryAccessSize::Word, true, false, TF_GTE_STALL | TF_READS_S); SpecExec_swc2(); break;
|
case InstructionOp::swc2: CompileLoadStoreTemplate(&Recompiler::Compile_swc2, MemoryAccessSize::Word, true, false, TF_GTE_STALL | TF_READS_S); SpecExec_swc2(); break;
|
||||||
|
|
||||||
// swc0/lwc0/cop1/cop3 are essentially no-ops
|
// swc0/lwc0/cop1/cop3 are essentially no-ops
|
||||||
|
Loading…
x
Reference in New Issue
Block a user