From 2caa457d0261dc00370cf91e0c261b441f66dcc3 Mon Sep 17 00:00:00 2001 From: zilmar Date: Fri, 22 Sep 2023 11:01:46 +0930 Subject: [PATCH] Core: reset pipeline stage after CompileLoadMemoryValue and CompileStoreMemoryValue Update counter before mfc0 x, count --- Source/Project64-core/N64System/N64System.cpp | 8 ++++ .../Recompiler/x86/x86RecompilerOps.cpp | 44 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/Source/Project64-core/N64System/N64System.cpp b/Source/Project64-core/N64System/N64System.cpp index ee4fae2f0..d0893e3a9 100644 --- a/Source/Project64-core/N64System/N64System.cpp +++ b/Source/Project64-core/N64System/N64System.cpp @@ -1297,6 +1297,10 @@ void CN64System::SyncCPU(CN64System * const SecondCPU) { ErrorFound = true; } + if (m_PipelineStage != SecondCPU->m_PipelineStage) + { + ErrorFound = true; + } for (int i = 0, n = sizeof(m_Reg.m_Mips_Interface) / sizeof(m_Reg.m_Mips_Interface[0]); i < n; i++) { @@ -1449,6 +1453,10 @@ void CN64System::DumpSyncErrors(CN64System * SecondCPU) { Error.LogF("Current Time: %X %X\r\n", (uint32_t)m_NextTimer, (uint32_t)SecondCPU->m_NextTimer); } + if (m_PipelineStage != SecondCPU->m_PipelineStage) + { + Error.LogF("Pipeline Stage: %X %X\r\n", (uint32_t)m_PipelineStage, (uint32_t)SecondCPU->m_PipelineStage); + } m_TLB.RecordDifference(Error, SecondCPU->m_TLB); m_SystemTimer.RecordDifference(Error, SecondCPU->m_SystemTimer); if (bFastSP() && m_Recomp) diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index 3da54e81c..4384027d7 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -7276,6 +7276,11 @@ void CX86RecompilerOps::SPECIAL_DSRA32() // COP0 functions void CX86RecompilerOps::COP0_MF() { + if (m_Opcode.rd == CRegisters::COP0Reg_Count) + { + UpdateCounters(m_RegWorkingSet, false, true); + } + m_RegWorkingSet.Map_GPR_32bit(m_Opcode.rt, true, -1); m_RegWorkingSet.BeforeCallDirect(); m_Assembler.push(m_Opcode.rd); @@ -7287,6 +7292,11 @@ void CX86RecompilerOps::COP0_MF() void CX86RecompilerOps::COP0_DMF() { + if (m_Opcode.rd == CRegisters::COP0Reg_Count) + { + UpdateCounters(m_RegWorkingSet, false, true); + } + m_RegWorkingSet.Map_GPR_64bit(m_Opcode.rt, -1); m_RegWorkingSet.BeforeCallDirect(); m_Assembler.push(m_Opcode.rd); @@ -9896,7 +9906,10 @@ void CX86RecompilerOps::CompileLoadMemoryValue(asmjit::x86::Gp AddressReg, asmji m_Assembler.SubConstFromVariable(OpsExecuted, g_NextTimer, "g_NextTimer"); } m_Assembler.MoveConstToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC); - m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); + if (m_PipelineStage != PIPELINE_STAGE_NORMAL) + { + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_JUMP); + } if (ValueSize == 32) { m_RegWorkingSet.BeforeCallDirect(); @@ -9943,6 +9956,10 @@ void CX86RecompilerOps::CompileLoadMemoryValue(asmjit::x86::Gp AddressReg, asmji { m_Assembler.AddConstToVariable(g_NextTimer, "g_NextTimer", OpsExecuted); } + if (m_PipelineStage != PIPELINE_STAGE_NORMAL) + { + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL); + } m_CodeBlock.Log(""); m_Assembler.bind(JumpFound); @@ -10057,7 +10074,10 @@ void CX86RecompilerOps::CompileStoreMemoryValue(asmjit::x86::Gp AddressReg, asmj m_Assembler.JneLabel(stdstr_f("MemoryWriteMap_%X_Found", m_CompilePC).c_str(), JumpFound); m_Assembler.MoveConstToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC); - m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", m_PipelineStage); + if (m_PipelineStage != PIPELINE_STAGE_NORMAL) + { + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", m_PipelineStage); + } uint32_t OpsExecuted = m_RegWorkingSet.GetBlockCycleCount(); if (OpsExecuted != 0) { @@ -10083,6 +10103,10 @@ void CX86RecompilerOps::CompileStoreMemoryValue(asmjit::x86::Gp AddressReg, asmj m_Assembler.test(asmjit::x86::al, asmjit::x86::al); m_RegWorkingSet.AfterCallDirect(); CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel); + if (m_PipelineStage != PIPELINE_STAGE_NORMAL) + { + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL); + } MemoryWriteDone = m_Assembler.newLabel(); m_Assembler.JmpLabel(stdstr_f("MemoryWrite_%X_Done:", m_CompilePC).c_str(), MemoryWriteDone); } @@ -10106,6 +10130,10 @@ void CX86RecompilerOps::CompileStoreMemoryValue(asmjit::x86::Gp AddressReg, asmj m_Assembler.test(asmjit::x86::al, asmjit::x86::al); m_RegWorkingSet.AfterCallDirect(); CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel); + if (m_PipelineStage != PIPELINE_STAGE_NORMAL) + { + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL); + } MemoryWriteDone = m_Assembler.newLabel(); m_Assembler.JmpLabel(stdstr_f("MemoryWrite_%X_Done:", m_CompilePC).c_str(), MemoryWriteDone); } @@ -10129,6 +10157,10 @@ void CX86RecompilerOps::CompileStoreMemoryValue(asmjit::x86::Gp AddressReg, asmj m_Assembler.test(asmjit::x86::al, asmjit::x86::al); m_RegWorkingSet.AfterCallDirect(); CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel); + if (m_PipelineStage != PIPELINE_STAGE_NORMAL) + { + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL); + } MemoryWriteDone = m_Assembler.newLabel(); m_Assembler.JmpLabel(stdstr_f("MemoryWrite_%X_Done:", m_CompilePC).c_str(), MemoryWriteDone); } @@ -10154,6 +10186,10 @@ void CX86RecompilerOps::CompileStoreMemoryValue(asmjit::x86::Gp AddressReg, asmj m_Assembler.test(asmjit::x86::al, asmjit::x86::al); m_RegWorkingSet.AfterCallDirect(); CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel); + if (m_PipelineStage != PIPELINE_STAGE_NORMAL) + { + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL); + } MemoryWriteDone = m_Assembler.newLabel(); m_Assembler.JmpLabel(stdstr_f("MemoryWrite_%X_Done:", m_CompilePC).c_str(), MemoryWriteDone); } @@ -10165,6 +10201,10 @@ void CX86RecompilerOps::CompileStoreMemoryValue(asmjit::x86::Gp AddressReg, asmj m_Assembler.MoveVariableDispToX86Reg(TempReg, g_MMU->m_TLB_WriteMap, "MMU->TLB_WriteMap", TempReg, CX86Ops::Multip_x4); CompileWriteTLBMiss(AddressReg, TempReg); m_Assembler.AddConstToX86Reg(TempReg, (uint32_t)m_MMU.Rdram()); + if (m_PipelineStage != PIPELINE_STAGE_NORMAL) + { + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL); + } } m_CodeBlock.Log(""); m_Assembler.bind(JumpFound);