Merge pull request #10142 from aldelaro5/gdb-stub-rework
Rework the entire logic of the GDB stub
This commit is contained in:
commit
b997048cfe
|
@ -59,7 +59,6 @@ option(ENCODE_FRAMEDUMPS "Encode framedumps in AVI format" ON)
|
||||||
|
|
||||||
option(ENABLE_GPROF "Enable gprof profiling (must be using Debug build)" OFF)
|
option(ENABLE_GPROF "Enable gprof profiling (must be using Debug build)" OFF)
|
||||||
option(FASTLOG "Enable all logs" OFF)
|
option(FASTLOG "Enable all logs" OFF)
|
||||||
option(GDBSTUB "Enable gdb stub for remote debugging." ON)
|
|
||||||
option(OPROFILING "Enable profiling" OFF)
|
option(OPROFILING "Enable profiling" OFF)
|
||||||
|
|
||||||
# TODO: Add DSPSpy
|
# TODO: Add DSPSpy
|
||||||
|
@ -389,10 +388,6 @@ if(FASTLOG)
|
||||||
add_definitions(-DDEBUGFAST)
|
add_definitions(-DDEBUGFAST)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(GDBSTUB)
|
|
||||||
add_definitions(-DUSE_GDBSTUB)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ENABLE_VTUNE)
|
if(ENABLE_VTUNE)
|
||||||
set(VTUNE_DIR "/opt/intel/vtune_amplifier")
|
set(VTUNE_DIR "/opt/intel/vtune_amplifier")
|
||||||
add_definitions(-DUSE_VTUNE)
|
add_definitions(-DUSE_VTUNE)
|
||||||
|
|
|
@ -452,6 +452,8 @@ add_library(core
|
||||||
PowerPC/JitCommon/JitCache.h
|
PowerPC/JitCommon/JitCache.h
|
||||||
PowerPC/JitInterface.cpp
|
PowerPC/JitInterface.cpp
|
||||||
PowerPC/JitInterface.h
|
PowerPC/JitInterface.h
|
||||||
|
PowerPC/GDBStub.cpp
|
||||||
|
PowerPC/GDBStub.h
|
||||||
PowerPC/MMU.cpp
|
PowerPC/MMU.cpp
|
||||||
PowerPC/MMU.h
|
PowerPC/MMU.h
|
||||||
PowerPC/PowerPC.cpp
|
PowerPC/PowerPC.cpp
|
||||||
|
@ -698,13 +700,6 @@ if(TARGET Hidapi::Hidapi)
|
||||||
target_compile_definitions(core PRIVATE -DHAVE_HIDAPI=1)
|
target_compile_definitions(core PRIVATE -DHAVE_HIDAPI=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(GDBSTUB)
|
|
||||||
target_sources(core PRIVATE
|
|
||||||
PowerPC/GDBStub.cpp
|
|
||||||
PowerPC/GDBStub.h
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
target_sources(core PRIVATE
|
target_sources(core PRIVATE
|
||||||
MemoryWatcher.cpp
|
MemoryWatcher.cpp
|
||||||
|
|
|
@ -131,12 +131,10 @@ void SConfig::SaveGeneralSettings(IniFile& ini)
|
||||||
|
|
||||||
general->Set("WirelessMac", m_WirelessMac);
|
general->Set("WirelessMac", m_WirelessMac);
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
general->Set("GDBSocket", gdb_socket);
|
general->Set("GDBSocket", gdb_socket);
|
||||||
#endif
|
#endif
|
||||||
general->Set("GDBPort", iGDBPort);
|
general->Set("GDBPort", iGDBPort);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SConfig::SaveInterfaceSettings(IniFile& ini)
|
void SConfig::SaveInterfaceSettings(IniFile& ini)
|
||||||
|
@ -349,12 +347,10 @@ void SConfig::LoadGeneralSettings(IniFile& ini)
|
||||||
|
|
||||||
general->Get("ShowLag", &m_ShowLag, false);
|
general->Get("ShowLag", &m_ShowLag, false);
|
||||||
general->Get("ShowFrameCount", &m_ShowFrameCount, false);
|
general->Get("ShowFrameCount", &m_ShowFrameCount, false);
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
general->Get("GDBSocket", &gdb_socket, "");
|
general->Get("GDBSocket", &gdb_socket, "");
|
||||||
#endif
|
#endif
|
||||||
general->Get("GDBPort", &(iGDBPort), -1);
|
general->Get("GDBPort", &(iGDBPort), -1);
|
||||||
#endif
|
|
||||||
|
|
||||||
m_ISOFolder.clear();
|
m_ISOFolder.clear();
|
||||||
int numISOPaths;
|
int numISOPaths;
|
||||||
|
@ -689,11 +685,9 @@ void SConfig::LoadDefaults()
|
||||||
bAutomaticStart = false;
|
bAutomaticStart = false;
|
||||||
bBootToPause = false;
|
bBootToPause = false;
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
iGDBPort = -1;
|
iGDBPort = -1;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
gdb_socket = "";
|
gdb_socket = "";
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cpu_core = PowerPC::DefaultCPUCore();
|
cpu_core = PowerPC::DefaultCPUCore();
|
||||||
|
|
|
@ -70,11 +70,9 @@ struct SConfig
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
bool bEnableDebugging = false;
|
bool bEnableDebugging = false;
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
int iGDBPort;
|
int iGDBPort;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
std::string gdb_socket;
|
std::string gdb_socket;
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
bool bAutomaticStart = false;
|
bool bAutomaticStart = false;
|
||||||
bool bBootToPause = false;
|
bool bBootToPause = false;
|
||||||
|
|
|
@ -63,15 +63,12 @@
|
||||||
#include "Core/NetPlayClient.h"
|
#include "Core/NetPlayClient.h"
|
||||||
#include "Core/NetPlayProto.h"
|
#include "Core/NetPlayProto.h"
|
||||||
#include "Core/PatchEngine.h"
|
#include "Core/PatchEngine.h"
|
||||||
|
#include "Core/PowerPC/GDBStub.h"
|
||||||
#include "Core/PowerPC/JitInterface.h"
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "Core/State.h"
|
#include "Core/State.h"
|
||||||
#include "Core/WiiRoot.h"
|
#include "Core/WiiRoot.h"
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
#include "Core/PowerPC/GDBStub.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_MEMORYWATCHER
|
#ifdef USE_MEMORYWATCHER
|
||||||
#include "Core/MemoryWatcher.h"
|
#include "Core/MemoryWatcher.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -316,12 +313,13 @@ void UndeclareAsCPUThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the CPU Thread only.
|
// For the CPU Thread only.
|
||||||
static void CPUSetInitialExecutionState()
|
static void CPUSetInitialExecutionState(bool force_paused = false)
|
||||||
{
|
{
|
||||||
// The CPU starts in stepping state, and will wait until a new state is set before executing.
|
// The CPU starts in stepping state, and will wait until a new state is set before executing.
|
||||||
// SetState must be called on the host thread, so we defer it for later.
|
// SetState must be called on the host thread, so we defer it for later.
|
||||||
QueueHostJob([]() {
|
QueueHostJob([force_paused]() {
|
||||||
SetState(SConfig::GetInstance().bBootToPause ? State::Paused : State::Running);
|
bool paused = SConfig::GetInstance().bBootToPause || force_paused;
|
||||||
|
SetState(paused ? State::Paused : State::Running);
|
||||||
Host_UpdateDisasmDialog();
|
Host_UpdateDisasmDialog();
|
||||||
Host_UpdateMainFrame();
|
Host_UpdateMainFrame();
|
||||||
Host_Message(HostMessageID::WMUserCreate);
|
Host_Message(HostMessageID::WMUserCreate);
|
||||||
|
@ -363,24 +361,23 @@ static void CpuThread(const std::optional<std::string>& savestate_path, bool del
|
||||||
}
|
}
|
||||||
|
|
||||||
s_is_started = true;
|
s_is_started = true;
|
||||||
CPUSetInitialExecutionState();
|
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if (!_CoreParameter.gdb_socket.empty())
|
if (!_CoreParameter.gdb_socket.empty())
|
||||||
{
|
{
|
||||||
gdb_init_local(_CoreParameter.gdb_socket.data());
|
GDBStub::InitLocal(_CoreParameter.gdb_socket.data());
|
||||||
gdb_break();
|
CPUSetInitialExecutionState(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (_CoreParameter.iGDBPort > 0)
|
if (_CoreParameter.iGDBPort > 0)
|
||||||
{
|
{
|
||||||
gdb_init(_CoreParameter.iGDBPort);
|
GDBStub::Init(_CoreParameter.iGDBPort);
|
||||||
// break at next instruction (the first instruction)
|
CPUSetInitialExecutionState(true);
|
||||||
gdb_break();
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPUSetInitialExecutionState();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Enter CPU run loop. When we leave it - we are done.
|
// Enter CPU run loop. When we leave it - we are done.
|
||||||
CPU::Run();
|
CPU::Run();
|
||||||
|
@ -393,6 +390,13 @@ static void CpuThread(const std::optional<std::string>& savestate_path, bool del
|
||||||
|
|
||||||
if (_CoreParameter.bFastmem)
|
if (_CoreParameter.bFastmem)
|
||||||
EMM::UninstallExceptionHandler();
|
EMM::UninstallExceptionHandler();
|
||||||
|
|
||||||
|
if (GDBStub::IsActive())
|
||||||
|
{
|
||||||
|
GDBStub::Deinit();
|
||||||
|
INFO_LOG_FMT(GDB_STUB, "Killed by CPU shutdown");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
|
static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
|
||||||
|
@ -653,11 +657,9 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
||||||
cpuThreadFunc(savestate_path, delete_savestate);
|
cpuThreadFunc(savestate_path, delete_savestate);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
INFO_LOG_FMT(CONSOLE, "{}", StopMessage(true, "Stopping GDB ..."));
|
INFO_LOG_FMT(CONSOLE, "{}", StopMessage(true, "Stopping GDB ..."));
|
||||||
gdb_deinit();
|
GDBStub::Deinit();
|
||||||
INFO_LOG_FMT(CONSOLE, "{}", StopMessage(true, "GDB stopped."));
|
INFO_LOG_FMT(CONSOLE, "{}", StopMessage(true, "GDB stopped."));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set or get the running state
|
// Set or get the running state
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Common/Event.h"
|
#include "Common/Event.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
|
#include "Core/PowerPC/GDBStub.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "VideoCommon/Fifo.h"
|
#include "VideoCommon/Fifo.h"
|
||||||
|
|
||||||
|
@ -96,6 +97,7 @@ void Run()
|
||||||
s_state_cpu_cvar.wait(state_lock, [] { return !s_state_paused_and_locked; });
|
s_state_cpu_cvar.wait(state_lock, [] { return !s_state_paused_and_locked; });
|
||||||
ExecutePendingJobs(state_lock);
|
ExecutePendingJobs(state_lock);
|
||||||
|
|
||||||
|
Common::Event gdb_step_sync_event;
|
||||||
switch (s_state)
|
switch (s_state)
|
||||||
{
|
{
|
||||||
case State::Running:
|
case State::Running:
|
||||||
|
@ -129,8 +131,26 @@ void Run()
|
||||||
|
|
||||||
case State::Stepping:
|
case State::Stepping:
|
||||||
// Wait for step command.
|
// Wait for step command.
|
||||||
s_state_cpu_cvar.wait(state_lock, [&state_lock] {
|
s_state_cpu_cvar.wait(state_lock, [&state_lock, &gdb_step_sync_event] {
|
||||||
ExecutePendingJobs(state_lock);
|
ExecutePendingJobs(state_lock);
|
||||||
|
state_lock.unlock();
|
||||||
|
if (GDBStub::IsActive() && GDBStub::HasControl())
|
||||||
|
{
|
||||||
|
GDBStub::SendSignal(GDBStub::Signal::Sigtrap);
|
||||||
|
GDBStub::ProcessCommands(true);
|
||||||
|
// If we are still going to step, emulate the fact we just sent a step command
|
||||||
|
if (GDBStub::HasControl())
|
||||||
|
{
|
||||||
|
// Make sure the previous step by gdb was serviced
|
||||||
|
if (s_state_cpu_step_instruction_sync &&
|
||||||
|
s_state_cpu_step_instruction_sync != &gdb_step_sync_event)
|
||||||
|
s_state_cpu_step_instruction_sync->Set();
|
||||||
|
|
||||||
|
s_state_cpu_step_instruction = true;
|
||||||
|
s_state_cpu_step_instruction_sync = &gdb_step_sync_event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state_lock.lock();
|
||||||
return s_state_cpu_step_instruction || !IsStepping();
|
return s_state_cpu_step_instruction || !IsStepping();
|
||||||
});
|
});
|
||||||
if (!IsStepping())
|
if (!IsStepping())
|
||||||
|
@ -282,6 +302,12 @@ void Break()
|
||||||
RunAdjacentSystems(false);
|
RunAdjacentSystems(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continue()
|
||||||
|
{
|
||||||
|
CPU::EnableStepping(false);
|
||||||
|
Core::CallOnStateChangedCallbacks(Core::State::Running);
|
||||||
|
}
|
||||||
|
|
||||||
bool PauseAndLock(bool do_lock, bool unpause_on_unlock, bool control_adjacent)
|
bool PauseAndLock(bool do_lock, bool unpause_on_unlock, bool control_adjacent)
|
||||||
{
|
{
|
||||||
// NOTE: This is protected by s_stepping_lock.
|
// NOTE: This is protected by s_stepping_lock.
|
||||||
|
|
|
@ -53,6 +53,9 @@ void EnableStepping(bool stepping);
|
||||||
// should not be used by the Host.
|
// should not be used by the Host.
|
||||||
void Break();
|
void Break();
|
||||||
|
|
||||||
|
// This should only be called from the CPU thread
|
||||||
|
void Continue();
|
||||||
|
|
||||||
// Shorthand for GetState() == State::Stepping.
|
// Shorthand for GetState() == State::Stepping.
|
||||||
// WARNING: State::PowerDown will return false, not just State::Running.
|
// WARNING: State::PowerDown will return false, not just State::Running.
|
||||||
bool IsStepping();
|
bool IsStepping();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,38 +6,23 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Core/CoreTiming.h"
|
||||||
|
|
||||||
#ifndef MSG_WAITALL
|
namespace GDBStub
|
||||||
#define MSG_WAITALL (8)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
{
|
||||||
GDB_SIGTRAP = 5,
|
enum class Signal
|
||||||
GDB_SIGTERM = 15,
|
|
||||||
} gdb_signals;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
{
|
||||||
GDB_BP_TYPE_NONE = 0,
|
Sigtrap = 5,
|
||||||
GDB_BP_TYPE_X,
|
Sigterm = 15,
|
||||||
GDB_BP_TYPE_R,
|
};
|
||||||
GDB_BP_TYPE_W,
|
|
||||||
GDB_BP_TYPE_A
|
|
||||||
} gdb_bp_type;
|
|
||||||
|
|
||||||
void gdb_init(u32 port);
|
void Init(u32 port);
|
||||||
void gdb_init_local(const char* socket);
|
void InitLocal(const char* socket);
|
||||||
void gdb_deinit();
|
void Deinit();
|
||||||
bool gdb_active();
|
bool IsActive();
|
||||||
void gdb_break();
|
bool HasControl();
|
||||||
|
void TakeControl();
|
||||||
|
|
||||||
void gdb_handle_exception();
|
void ProcessCommands(bool loop_until_continue);
|
||||||
int gdb_signal(u32 signal);
|
void SendSignal(Signal signal);
|
||||||
|
} // namespace GDBStub
|
||||||
int gdb_bp_x(u32 addr);
|
|
||||||
int gdb_bp_r(u32 addr);
|
|
||||||
int gdb_bp_w(u32 addr);
|
|
||||||
int gdb_bp_a(u32 addr);
|
|
||||||
|
|
||||||
bool gdb_add_bp(u32 type, u32 addr, u32 len);
|
|
||||||
|
|
|
@ -20,15 +20,12 @@
|
||||||
#include "Core/HLE/HLE.h"
|
#include "Core/HLE/HLE.h"
|
||||||
#include "Core/HW/CPU.h"
|
#include "Core/HW/CPU.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
|
#include "Core/PowerPC/GDBStub.h"
|
||||||
#include "Core/PowerPC/Interpreter/ExceptionUtils.h"
|
#include "Core/PowerPC/Interpreter/ExceptionUtils.h"
|
||||||
#include "Core/PowerPC/MMU.h"
|
#include "Core/PowerPC/MMU.h"
|
||||||
#include "Core/PowerPC/PPCTables.h"
|
#include "Core/PowerPC/PPCTables.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
#include "Core/PowerPC/GDBStub.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
u32 last_pc;
|
u32 last_pc;
|
||||||
|
@ -152,16 +149,6 @@ int Interpreter::SingleStepInner()
|
||||||
return PPCTables::GetOpInfo(m_prev_inst)->numCycles;
|
return PPCTables::GetOpInfo(m_prev_inst)->numCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
if (gdb_active() && gdb_bp_x(PC))
|
|
||||||
{
|
|
||||||
Host_UpdateDisasmDialog();
|
|
||||||
|
|
||||||
gdb_signal(GDB_SIGTRAP);
|
|
||||||
gdb_handle_exception();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NPC = PC + sizeof(UGeckoInstruction);
|
NPC = PC + sizeof(UGeckoInstruction);
|
||||||
m_prev_inst.hex = PowerPC::Read_Opcode(PC);
|
m_prev_inst.hex = PowerPC::Read_Opcode(PC);
|
||||||
|
|
||||||
|
@ -306,6 +293,8 @@ void Interpreter::Run()
|
||||||
#endif
|
#endif
|
||||||
INFO_LOG_FMT(POWERPC, "Hit Breakpoint - {:08x}", PC);
|
INFO_LOG_FMT(POWERPC, "Hit Breakpoint - {:08x}", PC);
|
||||||
CPU::Break();
|
CPU::Break();
|
||||||
|
if (GDBStub::IsActive())
|
||||||
|
GDBStub::TakeControl();
|
||||||
if (PowerPC::breakpoints.IsTempBreakPoint(PC))
|
if (PowerPC::breakpoints.IsTempBreakPoint(PC))
|
||||||
PowerPC::breakpoints.Remove(PC);
|
PowerPC::breakpoints.Remove(PC);
|
||||||
|
|
||||||
|
|
|
@ -18,15 +18,12 @@
|
||||||
#include "Core/HW/MMIO.h"
|
#include "Core/HW/MMIO.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
#include "Core/HW/ProcessorInterface.h"
|
#include "Core/HW/ProcessorInterface.h"
|
||||||
|
#include "Core/PowerPC/GDBStub.h"
|
||||||
#include "Core/PowerPC/JitInterface.h"
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
#include "VideoCommon/VideoBackendBase.h"
|
#include "VideoCommon/VideoBackendBase.h"
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
#include "Core/PowerPC/GDBStub.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace PowerPC
|
namespace PowerPC
|
||||||
{
|
{
|
||||||
// EFB RE
|
// EFB RE
|
||||||
|
@ -522,6 +519,9 @@ static void Memcheck(u32 address, u64 var, bool write, size_t size)
|
||||||
|
|
||||||
CPU::Break();
|
CPU::Break();
|
||||||
|
|
||||||
|
if (GDBStub::IsActive())
|
||||||
|
GDBStub::TakeControl();
|
||||||
|
|
||||||
// Fake a DSI so that all the code that tests for it in order to skip
|
// Fake a DSI so that all the code that tests for it in order to skip
|
||||||
// the rest of the instruction will apply. (This means that
|
// the rest of the instruction will apply. (This means that
|
||||||
// watchpoints will stop the emulator before the offending load/store,
|
// watchpoints will stop the emulator before the offending load/store,
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
#include "Core/PowerPC/CPUCoreBase.h"
|
#include "Core/PowerPC/CPUCoreBase.h"
|
||||||
|
#include "Core/PowerPC/GDBStub.h"
|
||||||
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
||||||
#include "Core/PowerPC/JitInterface.h"
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
#include "Core/PowerPC/MMU.h"
|
#include "Core/PowerPC/MMU.h"
|
||||||
|
@ -611,7 +612,11 @@ void CheckBreakPoints()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PowerPC::breakpoints.IsBreakPointBreakOnHit(PC))
|
if (PowerPC::breakpoints.IsBreakPointBreakOnHit(PC))
|
||||||
|
{
|
||||||
CPU::Break();
|
CPU::Break();
|
||||||
|
if (GDBStub::IsActive())
|
||||||
|
GDBStub::TakeControl();
|
||||||
|
}
|
||||||
if (PowerPC::breakpoints.IsBreakPointLogOnHit(PC))
|
if (PowerPC::breakpoints.IsBreakPointLogOnHit(PC))
|
||||||
{
|
{
|
||||||
NOTICE_LOG_FMT(MEMMAP,
|
NOTICE_LOG_FMT(MEMMAP,
|
||||||
|
|
Loading…
Reference in New Issue