From 06a09d38216c4a64f1dd33a3137ed8ef4df92fdc Mon Sep 17 00:00:00 2001 From: GavinAndrews Date: Mon, 2 Apr 2018 17:23:38 +0100 Subject: Added suspend and resume debugger commands (#3411) --- src/emu/debug/debugcmd.cpp | 105 +++++++++++++++++++++++++++++++++++++++++++++ src/emu/debug/debugcmd.h | 2 + src/emu/debug/debugcpu.cpp | 23 ++++++++++ src/emu/debug/debugcpu.h | 5 +++ src/emu/debug/debughlp.cpp | 2 + 5 files changed, 137 insertions(+) diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index 6b393e21552..55632bd4e85 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -163,6 +163,8 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu m_console.register_command("focus", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_focus, this, _1, _2)); m_console.register_command("ignore", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_ignore, this, _1, _2)); m_console.register_command("observe", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_observe, this, _1, _2)); + m_console.register_command("suspend", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_suspend, this, _1, _2)); + m_console.register_command("resume", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_resume, this, _1, _2)); m_console.register_command("comadd", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_comment_add, this, _1, _2)); m_console.register_command("//", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_comment_add, this, _1, _2)); @@ -1023,6 +1025,109 @@ void debugger_commands::execute_observe(int ref, const std::vector } } +/*------------------------------------------------- + execute_suspend - suspend execution on cpu +-------------------------------------------------*/ + +void debugger_commands::execute_suspend(int ref, const std::vector ¶ms) +{ + /* if there are no parameters, dump the ignore list */ + if (params.empty()) + { + std::string buffer; + + /* loop over all executable devices */ + for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) + + /* build up a comma-separated list */ + if (exec.device().debug()->suspended()) + { + if (buffer.empty()) + buffer = string_format("Currently suspended device '%s'", exec.device().tag()); + else + buffer.append(string_format(", '%s'", exec.device().tag())); + } + + /* special message for none */ + if (buffer.empty()) + buffer = string_format("No currently suspended devices"); + m_console.printf("%s\n", buffer.c_str()); + } + else + { + device_t *devicelist[MAX_COMMAND_PARAMS]; + + /* validate parameters */ + for (int paramnum = 0; paramnum < params.size(); paramnum++) + if (!validate_cpu_parameter(params[paramnum].c_str(), devicelist[paramnum])) + return; + + for (int paramnum = 0; paramnum < params.size(); paramnum++) + { + /* make sure this isn't the last live CPU */ + bool gotone = false; + for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) + if (&exec.device() != devicelist[paramnum] && !exec.device().debug()->suspended()) + { + gotone = true; + break; + } + if (!gotone) + { + m_console.printf("Can't suspend all devices!\n"); + return; + } + + devicelist[paramnum]->debug()->suspend(true); + m_console.printf("Suspended device '%s'\n", devicelist[paramnum]->tag()); + } + } +} + +/*------------------------------------------------- + execute_resume - Resume execution on CPU +-------------------------------------------------*/ + +void debugger_commands::execute_resume(int ref, const std::vector ¶ms) +{ + /* if there are no parameters, dump the ignore list */ + if (params.empty()) + { + std::string buffer; + + /* loop over all executable devices */ + for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) + + /* build up a comma-separated list */ + if (exec.device().debug()->suspended()) + { + if (buffer.empty()) + buffer = string_format("Currently suspended device '%s'", exec.device().tag()); + else + buffer.append(string_format(", '%s'", exec.device().tag())); + } + + /* special message for none */ + if (buffer.empty()) + buffer = string_format("No currently suspended devices"); + m_console.printf("%s\n", buffer.c_str()); + } + else + { + device_t *devicelist[MAX_COMMAND_PARAMS]; + + /* validate parameters */ + for (int paramnum = 0; paramnum < params.size(); paramnum++) + if (!validate_cpu_parameter(params[paramnum].c_str(), devicelist[paramnum])) + return; + + for (int paramnum = 0; paramnum < params.size(); paramnum++) + { + devicelist[paramnum]->debug()->suspend(false); + m_console.printf("Resumed device '%s'\n", devicelist[paramnum]->tag()); + } + } +} /*------------------------------------------------- execute_comment - add a comment to a line diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index 41405ec0a71..71f27cb4ac5 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -110,6 +110,8 @@ private: void execute_focus(int ref, const std::vector ¶ms); void execute_ignore(int ref, const std::vector ¶ms); void execute_observe(int ref, const std::vector ¶ms); + void execute_suspend(int ref, const std::vector ¶ms); + void execute_resume(int ref, const std::vector ¶ms); void execute_next(int ref, const std::vector ¶ms); void execute_comment_add(int ref, const std::vector ¶ms); void execute_comment_del(int ref, const std::vector ¶ms); diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index 37840b2a62c..016d214cfa4 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -1820,6 +1820,29 @@ void device_debug::ignore(bool ignore) } } +//------------------------------------------------- +// suspend +//------------------------------------------------- + +void device_debug::suspend(bool suspend) +{ + assert(m_exec != nullptr); + + if (suspend) { + m_flags |= DEBUG_FLAG_SUSPENDED; + m_exec->suspend(SUSPEND_REASON_HALT, 1); + } + else { + m_flags &= ~DEBUG_FLAG_SUSPENDED; + m_exec->resume(SUSPEND_REASON_HALT); + } + + if (&m_device == m_device.machine().debugger().cpu().live_cpu() && suspend) + { + assert(m_exec != nullptr); + go_next_device(); + } +} //------------------------------------------------- // single_step - single step the device past the diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index 43384566da8..6d54456b913 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -189,6 +189,10 @@ public: void ignore(bool ignore = true); bool observing() const { return ((m_flags & DEBUG_FLAG_OBSERVING) != 0); } + // debugger suspend/unsuspend + void suspend(bool suspend = true); + bool suspended() const { return ((m_flags & DEBUG_FLAG_SUSPENDED) != 0); } + // single stepping void single_step(int numsteps = 1); void single_step_over(int numsteps = 1); @@ -447,6 +451,7 @@ private: static constexpr u32 DEBUG_FLAG_STOP_EXCEPTION = 0x00000800; // there is a pending stop on the next exception static constexpr u32 DEBUG_FLAG_STOP_VBLANK = 0x00001000; // there is a pending stop on the next VBLANK static constexpr u32 DEBUG_FLAG_STOP_TIME = 0x00002000; // there is a pending stop at cpu->stoptime + static constexpr u32 DEBUG_FLAG_SUSPENDED = 0x00004000; // CPU currently suspended static constexpr u32 DEBUG_FLAG_LIVE_BP = 0x00010000; // there are live breakpoints for this CPU static constexpr u32 DEBUG_FLAG_STEPPING_ANY = DEBUG_FLAG_STEPPING | DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT; diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index 9f5d8ad133e..f131df0d017 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -142,6 +142,8 @@ static const help_item static_help_list[] = " focus -- focuses debugger only on \n" " ignore [[,[,...]]] -- stops debugging on \n" " observe [[,[,...]]] -- resumes debugging on \n" + " suspend [[,[,...]]] -- suspends execution on \n" + " resume [[,[,...]]] -- resumes execution on \n" " trace {|OFF}[,[,[,]]] -- trace the given CPU to a file (defaults to active CPU)\n" " traceover {|OFF}[,[,[,]]] -- trace the given CPU to a file, but skip subroutines (defaults to active CPU)\n" " traceflush -- flushes all open trace files\n" -- cgit v1.2.3