diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp index bfec4633f..7feada20b 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp @@ -5393,6 +5393,11 @@ void CArmRecompilerOps::CompileExecuteBP(void) g_Notify->BreakPoint(__FILE__, __LINE__); } +void CArmRecompilerOps::CompileExecuteDelaySlotBP(void) +{ + g_Notify->BreakPoint(__FILE__, __LINE__); +} + CRegInfo & CArmRecompilerOps::GetRegWorkingSet(void) { return m_RegWorkingSet; diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.h b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.h index b5bfe3115..ab1aeb4c6 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.h @@ -225,6 +225,7 @@ private: void CompileReadTLBMiss(ArmReg AddressReg, ArmReg LookUpReg); void CompileWriteTLBMiss(ArmReg AddressReg, ArmReg LookUpReg); void CompileExecuteBP(void); + void CompileExecuteDelaySlotBP(void); /********* Helper Functions *********/ typedef CRegInfo::REG_STATE REG_STATE; diff --git a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp index a42c5f1ea..b47186f34 100644 --- a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp +++ b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp @@ -26,6 +26,50 @@ void InPermLoop(); bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2); +static bool OpHasDelaySlot(const OPCODE & Opcode) +{ + if (Opcode.op == R4300i_J || + Opcode.op == R4300i_JAL || + Opcode.op == R4300i_BEQ || + Opcode.op == R4300i_BNE || + Opcode.op == R4300i_BLEZ || + Opcode.op == R4300i_BGTZ || + Opcode.op == R4300i_BEQL || + Opcode.op == R4300i_BNEL || + Opcode.op == R4300i_BLEZL || + Opcode.op == R4300i_BGTZL) + { + return true; + } + else if (Opcode.op == R4300i_SPECIAL) + { + if (Opcode.funct == R4300i_SPECIAL_JR || + Opcode.funct == R4300i_SPECIAL_JALR) + { + return true; + } + } + else if (Opcode.op == R4300i_REGIMM) + { + if (Opcode.rt == R4300i_REGIMM_BLTZ || + Opcode.rt == R4300i_REGIMM_BGEZ || + Opcode.rt == R4300i_REGIMM_BLTZL || + Opcode.rt == R4300i_REGIMM_BGEZL || + Opcode.rt == R4300i_REGIMM_BLTZAL || + Opcode.rt == R4300i_REGIMM_BGEZAL || + Opcode.rt == R4300i_REGIMM_BLTZALL || + Opcode.rt == R4300i_REGIMM_BGEZALL) + { + return true; + } + } + else if (Opcode.op == R4300i_CP1 && Opcode.fmt == R4300i_COP1_BC) + { + return true; + } + return false; +} + static bool DelaySlotEffectsJump(uint32_t JumpPC) { OPCODE Command; @@ -476,6 +520,12 @@ bool CCodeSection::GenerateNativeCode(uint32_t Test) m_BlockInfo->SetVAddrLast(m_RecompilerOps->GetCurrentPC()); } + if (isDebugging() && HaveExecutionBP() && OpHasDelaySlot(Opcode) && g_Debugger->ExecutionBP(m_RecompilerOps->GetCurrentPC() + 4)) + { + m_RecompilerOps->CompileExecuteDelaySlotBP(); + break; + } + if (isDebugging() && HaveExecutionBP() && g_Debugger->ExecutionBP(m_RecompilerOps->GetCurrentPC())) { m_RecompilerOps->CompileExecuteBP(); diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h index 6b305bf3d..392a74858 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h @@ -223,4 +223,5 @@ public: virtual void PostCompileOpcode(void) = 0; virtual void UpdateCounters(CRegInfo & RegSet, bool CheckTimer, bool ClearValues = false) = 0; virtual void CompileExecuteBP(void) = 0; + virtual void CompileExecuteDelaySlotBP(void) = 0; }; diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index 764f9d012..391158252 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -87,6 +87,29 @@ static void x86_compiler_Break_Point() } } +static void x86_Break_Point_DelaySlot() +{ + CInterpreterCPU::ExecuteOps(g_System->CountPerOp()); + if (g_SyncSystem) + { + g_System->UpdateSyncCPU(g_SyncSystem, g_System->CountPerOp()); + g_System->SyncCPU(g_SyncSystem); + } + if (g_Debugger->ExecutionBP(g_Reg->m_PROGRAM_COUNTER)) + { + x86_compiler_Break_Point(); + } + if (R4300iOp::m_NextInstruction != NORMAL) + { + CInterpreterCPU::ExecuteOps(g_System->CountPerOp()); + if (g_SyncSystem) + { + g_System->UpdateSyncCPU(g_SyncSystem, g_System->CountPerOp()); + g_System->SyncCPU(g_SyncSystem); + } + } +} + static uint32_t memory_access_address; static uint32_t memory_write_in_delayslot; static uint32_t memory_breakpoint_found = 0; @@ -10060,6 +10083,32 @@ void CX86RecompilerOps::CompileExecuteBP(void) m_NextInstruction = END_BLOCK; } +void CX86RecompilerOps::CompileExecuteDelaySlotBP(void) +{ + bool bDelay = m_NextInstruction == JUMP || m_NextInstruction == DELAY_SLOT; + if (bDelay) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + m_RegWorkingSet.WriteBackRegisters(); + + UpdateCounters(m_RegWorkingSet, true, true); + if (g_SyncSystem) + { +#ifdef _WIN32 + MoveConstToX86reg((uint32_t)g_BaseSystem, x86_ECX); + Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem"); +#else + PushImm32((uint32_t)g_BaseSystem); + Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem"); + AddConstToX86Reg(x86_ESP, 4); +#endif + } + Call_Direct((void *)x86_Break_Point_DelaySlot, "x86_Break_Point_DelaySlot"); + ExitCodeBlock(); + m_NextInstruction = END_BLOCK; +} + void CX86RecompilerOps::OverflowDelaySlot(bool TestTimer) { m_RegWorkingSet.WriteBackRegisters(); diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h index 384115db5..8111de5f9 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h @@ -242,6 +242,7 @@ public: void UpdateCounters(CRegInfo & RegSet, bool CheckTimer, bool ClearValues = false); void CompileSystemCheck(uint32_t TargetPC, const CRegInfo & RegSet); void CompileExecuteBP(void); + void CompileExecuteDelaySlotBP(void); static void ChangeDefaultRoundingModel(); void OverflowDelaySlot(bool TestTimer);