summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug/debugcpu.cpp
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2022-08-28 13:27:35 -0400
committer AJR <ajrhacker@users.noreply.github.com>2022-08-28 13:31:50 -0400
commitd8d588262de1f11a529b208e470cff9b89a4cba6 (patch)
treefbeff8d28cb8538d527b8e3cc6c3df572d495189 /src/emu/debug/debugcpu.cpp
parentf52b402f2416ddfd646afe2d132c16d78c6fe9c3 (diff)
Debugger changes
- Added exception points as a new class of "points" triggering on specific exception numbers, with a similar set of commands to breakpoints and registerpoints. - Removed the per-instruction callback hook from device_debug. Only one driver was using this (rmnimbus.cpp), and what it was doing with it could be done more cleanly with exception points. - Change the type of the action string parameter for "points"-creating methods and make some parameters optional for those. - Change trace file logging to use a std::ostream instead of FILE * to take better advantage of strformat.
Diffstat (limited to 'src/emu/debug/debugcpu.cpp')
-rw-r--r--src/emu/debug/debugcpu.cpp211
1 files changed, 145 insertions, 66 deletions
diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp
index 820d9e72688..aba79d74036 100644
--- a/src/emu/debug/debugcpu.cpp
+++ b/src/emu/debug/debugcpu.cpp
@@ -47,6 +47,7 @@ debugger_cpu::debugger_cpu(running_machine &machine)
, m_bpindex(1)
, m_wpindex(1)
, m_rpindex(1)
+ , m_epindex(1)
, m_wpdata(0)
, m_wpaddr(0)
, m_wpsize(0)
@@ -424,7 +425,6 @@ device_debug::device_debug(device_t &device)
, m_disasm(nullptr)
, m_flags(0)
, m_symtable(std::make_unique<symbol_table>(device.machine(), &device.machine().debugger().cpu().global_symtable(), &device))
- , m_instrhook(nullptr)
, m_stepaddr(0)
, m_stepsleft(0)
, m_delay_steps(0)
@@ -438,7 +438,8 @@ device_debug::device_debug(device_t &device)
, m_pc_history_index(0)
, m_pc_history_valid(0)
, m_bplist()
- , m_rplist(std::make_unique<std::forward_list<debug_registerpoint>>())
+ , m_rplist()
+ , m_eplist()
, m_triggered_breakpoint(nullptr)
, m_triggered_watchpoint(nullptr)
, m_trace(nullptr)
@@ -549,6 +550,7 @@ device_debug::~device_debug()
breakpoint_clear_all();
watchpoint_clear_all();
registerpoint_clear_all();
+ exceptionpoint_clear_all();
}
void device_debug::write_tracking(address_space &space, offs_t address, u64 data)
@@ -672,10 +674,39 @@ void device_debug::exception_hook(int exception)
if (matched)
{
m_device.machine().debugger().cpu().set_execution_stopped();
- m_device.machine().debugger().console().printf("Stopped on exception (CPU '%s', exception %d, PC=%X)\n", m_device.tag(), exception, m_state->pcbase());
+ m_device.machine().debugger().console().printf("Stopped on exception (CPU '%s', exception %X, PC=%X)\n", m_device.tag(), exception, m_state->pcbase());
compute_debug_flags();
}
}
+
+ // see if any exception points match
+ if (!m_eplist.empty())
+ {
+ auto epitp = m_eplist.equal_range(exception);
+ for (auto epit = epitp.first; epit != epitp.second; ++epit)
+ {
+ debug_exceptionpoint &ep = *epit->second;
+ if (ep.hit(exception))
+ {
+ // halt in the debugger by default
+ debugger_cpu &debugcpu = m_device.machine().debugger().cpu();
+ debugcpu.set_execution_stopped();
+
+ // if we hit, evaluate the action
+ if (!ep.m_action.empty())
+ m_device.machine().debugger().console().execute_command(ep.m_action, false);
+
+ // print a notification, unless the action made us go again
+ if (debugcpu.is_stopped())
+ {
+ debugcpu.set_execution_stopped();
+ m_device.machine().debugger().console().printf("Stopped at exception point %X (CPU '%s', PC=%X)\n", ep.m_index, m_device.tag(), exception, m_state->pcbase());
+ compute_debug_flags();
+ }
+ break;
+ }
+ }
+ }
}
@@ -744,10 +775,6 @@ void device_debug::instruction_hook(offs_t curpc)
if (m_trace != nullptr)
m_trace->update(curpc);
- // per-instruction hook?
- if (!debugcpu.is_stopped() && (m_flags & DEBUG_FLAG_HOOKED) != 0 && (*m_instrhook)(m_device, curpc))
- debugcpu.set_execution_stopped();
-
// handle single stepping
if (!debugcpu.is_stopped() && (m_flags & DEBUG_FLAG_STEPPING_ANY) != 0)
{
@@ -893,22 +920,6 @@ void device_debug::instruction_hook(offs_t curpc)
//-------------------------------------------------
-// set_instruction_hook - set a hook to be
-// called on each instruction for a given device
-//-------------------------------------------------
-
-void device_debug::set_instruction_hook(debug_instruction_hook_func hook)
-{
- // set the hook and also the CPU's flag for fast knowledge of the hook
- m_instrhook = hook;
- if (hook != nullptr)
- m_flags |= DEBUG_FLAG_HOOKED;
- else
- m_flags &= ~DEBUG_FLAG_HOOKED;
-}
-
-
-//-------------------------------------------------
// ignore - ignore/observe a given device
//-------------------------------------------------
@@ -1151,7 +1162,7 @@ const debug_breakpoint *device_debug::breakpoint_find(offs_t address) const
// returning its index
//-------------------------------------------------
-int device_debug::breakpoint_set(offs_t address, const char *condition, const char *action)
+int device_debug::breakpoint_set(offs_t address, const char *condition, std::string_view action)
{
// allocate a new one and hook it into our list
u32 id = m_device.machine().debugger().cpu().get_breakpoint_index();
@@ -1238,7 +1249,7 @@ void device_debug::breakpoint_enable_all(bool enable)
// returning its index
//-------------------------------------------------
-int device_debug::watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition, const char *action)
+int device_debug::watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition, std::string_view action)
{
if (space.spacenum() >= int(m_wplist.size()))
m_wplist.resize(space.spacenum()+1);
@@ -1325,15 +1336,15 @@ void device_debug::watchpoint_enable_all(bool enable)
// returning its index
//-------------------------------------------------
-int device_debug::registerpoint_set(const char *condition, const char *action)
+int device_debug::registerpoint_set(const char *condition, std::string_view action)
{
// allocate a new one
u32 id = m_device.machine().debugger().cpu().get_registerpoint_index();
- m_rplist->emplace_front(*m_symtable, id, condition, action);
+ m_rplist.emplace_front(*m_symtable, id, condition, action);
// update the flags and return the index
breakpoint_update_flags();
- return m_rplist->front().m_index;
+ return m_rplist.front().m_index;
}
@@ -1345,10 +1356,10 @@ int device_debug::registerpoint_set(const char *condition, const char *action)
bool device_debug::registerpoint_clear(int index)
{
// scan the list to see if we own this registerpoint
- for (auto brp = m_rplist->before_begin(); std::next(brp) != m_rplist->end(); ++brp)
+ for (auto brp = m_rplist.before_begin(); std::next(brp) != m_rplist.end(); ++brp)
if (std::next(brp)->m_index == index)
{
- m_rplist->erase_after(brp);
+ m_rplist.erase_after(brp);
breakpoint_update_flags();
return true;
}
@@ -1365,7 +1376,7 @@ bool device_debug::registerpoint_clear(int index)
void device_debug::registerpoint_clear_all()
{
// clear the list
- m_rplist->clear();
+ m_rplist.clear();
breakpoint_update_flags();
}
@@ -1378,7 +1389,7 @@ void device_debug::registerpoint_clear_all()
bool device_debug::registerpoint_enable(int index, bool enable)
{
// scan the list to see if we own this conditionpoint
- for (debug_registerpoint &rp : *m_rplist)
+ for (debug_registerpoint &rp : m_rplist)
if (rp.m_index == index)
{
rp.m_enabled = enable;
@@ -1399,12 +1410,97 @@ bool device_debug::registerpoint_enable(int index, bool enable)
void device_debug::registerpoint_enable_all(bool enable)
{
// apply the enable to all registerpoints we own
- for (debug_registerpoint &rp : *m_rplist)
+ for (debug_registerpoint &rp : m_rplist)
registerpoint_enable(rp.index(), enable);
}
//-------------------------------------------------
+// exceptionpoint_set - set a new exception
+// point, returning its index
+//-------------------------------------------------
+
+int device_debug::exceptionpoint_set(int exception, const char *condition, std::string_view action)
+{
+ // allocate a new one and hook it into our list
+ u32 id = m_device.machine().debugger().cpu().get_exceptionpoint_index();
+ m_eplist.emplace(exception, std::make_unique<debug_exceptionpoint>(this, *m_symtable, id, exception, condition, action));
+
+ // return the index
+ return id;
+}
+
+
+//-------------------------------------------------
+// exceptionpoint_clear - clear an exception
+// point by index, returning true if we found it
+//-------------------------------------------------
+
+bool device_debug::exceptionpoint_clear(int index)
+{
+ // scan the list to see if we own this breakpoint
+ for (auto epit = m_eplist.begin(); epit != m_eplist.end(); ++epit)
+ if (epit->second->m_index == index)
+ {
+ m_eplist.erase(epit);
+ return true;
+ }
+
+ // we don't own it, return false
+ return false;
+}
+
+
+//-------------------------------------------------
+// exceptionpoint_clear_all - clear all exception
+// points
+//-------------------------------------------------
+
+void device_debug::exceptionpoint_clear_all()
+{
+ // clear the list
+ m_eplist.clear();
+}
+
+
+//-------------------------------------------------
+// exceptionpoint_enable - enable/disable an
+// exception point by index, returning true if we
+// found it
+//-------------------------------------------------
+
+bool device_debug::exceptionpoint_enable(int index, bool enable)
+{
+ // scan the list to see if we own this exception point
+ for (auto &epp : m_eplist)
+ {
+ debug_exceptionpoint &ep = *epp.second;
+ if (ep.m_index == index)
+ {
+ ep.m_enabled = enable;
+ return true;
+ }
+ }
+
+ // we don't own it, return false
+ return false;
+}
+
+
+//-------------------------------------------------
+// exceptionpoint_enable_all - enable/disable all
+// exception points
+//-------------------------------------------------
+
+void device_debug::exceptionpoint_enable_all(bool enable)
+{
+ // apply the enable to all exception points we own
+ for (auto &epp : m_eplist)
+ exceptionpoint_enable(epp.second->index(), enable);
+}
+
+
+//-------------------------------------------------
// history_pc - return an entry from the PC
// history
//-------------------------------------------------
@@ -1600,31 +1696,14 @@ u32 device_debug::compute_opcode_crc32(offs_t pc) const
// trace - trace execution of a given device
//-------------------------------------------------
-void device_debug::trace(FILE *file, bool trace_over, bool detect_loops, bool logerror, const char *action)
+void device_debug::trace(std::unique_ptr<std::ostream> &&file, bool trace_over, bool detect_loops, bool logerror, std::string_view action)
{
// delete any existing tracers
m_trace = nullptr;
// if we have a new file, make a new tracer
if (file != nullptr)
- m_trace = std::make_unique<tracer>(*this, *file, trace_over, detect_loops, logerror, action);
-}
-
-
-//-------------------------------------------------
-// trace_printf - output data into the given
-// device's tracefile, if tracing
-//-------------------------------------------------
-
-void device_debug::trace_printf(const char *fmt, ...)
-{
- if (m_trace != nullptr)
- {
- va_list va;
- va_start(va, fmt);
- m_trace->vprintf(fmt, va);
- va_end(va);
- }
+ m_trace = std::make_unique<tracer>(*this, std::move(file), trace_over, detect_loops, logerror, action);
}
@@ -1652,7 +1731,7 @@ void device_debug::compute_debug_flags()
// if we're tracking history, or we're hooked, or stepping, or stopping at a breakpoint
// make sure we call the hook
- if ((m_flags & (DEBUG_FLAG_HISTORY | DEBUG_FLAG_HOOKED | DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP)) != 0)
+ if ((m_flags & (DEBUG_FLAG_HISTORY | DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP)) != 0)
machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
// also call if we are tracing
@@ -1753,7 +1832,7 @@ void device_debug::breakpoint_update_flags()
if (!(m_flags & DEBUG_FLAG_LIVE_BP))
{
// see if there are any enabled registerpoints
- for (debug_registerpoint &rp : *m_rplist)
+ for (debug_registerpoint &rp : m_rplist)
{
if (rp.m_enabled)
{
@@ -1803,7 +1882,7 @@ void device_debug::breakpoint_check(offs_t pc)
}
// see if we have any matching registerpoints
- for (debug_registerpoint &rp : *m_rplist)
+ for (debug_registerpoint &rp : m_rplist)
{
if (rp.hit())
{
@@ -1836,10 +1915,10 @@ void device_debug::breakpoint_check(offs_t pc)
// tracer - constructor
//-------------------------------------------------
-device_debug::tracer::tracer(device_debug &debug, FILE &file, bool trace_over, bool detect_loops, bool logerror, const char *action)
+device_debug::tracer::tracer(device_debug &debug, std::unique_ptr<std::ostream> &&file, bool trace_over, bool detect_loops, bool logerror, std::string_view action)
: m_debug(debug)
- , m_file(file)
- , m_action((action != nullptr) ? action : "")
+ , m_file(std::move(file))
+ , m_action(action)
, m_detect_loops(detect_loops)
, m_logerror(logerror)
, m_loops(0)
@@ -1858,7 +1937,7 @@ device_debug::tracer::tracer(device_debug &debug, FILE &file, bool trace_over, b
device_debug::tracer::~tracer()
{
// make sure we close the file if we can
- fclose(&m_file);
+ m_file.reset();
}
@@ -1894,7 +1973,7 @@ void device_debug::tracer::update(offs_t pc)
// if we just finished looping, indicate as much
if (m_loops != 0)
- fprintf(&m_file, "\n (loops for %d instructions)\n\n", m_loops);
+ util::stream_format(*m_file, "\n (loops for %d instructions)\n\n", m_loops);
m_loops = 0;
}
@@ -1909,7 +1988,7 @@ void device_debug::tracer::update(offs_t pc)
buffer.disassemble(pc, instruction, next_pc, size, dasmresult);
// output the result
- fprintf(&m_file, "%s: %s\n", buffer.pc_to_string(pc).c_str(), instruction.c_str());
+ util::stream_format(*m_file, "%s: %s\n", buffer.pc_to_string(pc), instruction);
// do we need to step the trace over this instruction?
if (m_trace_over && (dasmresult & util::disasm_interface::SUPPORTED) != 0 && (dasmresult & util::disasm_interface::STEP_OVER) != 0)
@@ -1927,7 +2006,7 @@ void device_debug::tracer::update(offs_t pc)
// log this PC
m_nextdex = (m_nextdex + 1) % TRACE_LOOPS;
m_history[m_nextdex] = pc;
- fflush(&m_file);
+ m_file->flush();
}
@@ -1935,11 +2014,11 @@ void device_debug::tracer::update(offs_t pc)
// vprintf - generic print to the trace file
//-------------------------------------------------
-void device_debug::tracer::vprintf(const char *format, va_list va)
+void device_debug::tracer::vprintf(util::format_argument_pack<std::ostream> const &args)
{
// pass through to the file
- vfprintf(&m_file, format, va);
- fflush(&m_file);
+ util::stream_format(*m_file, args);
+ m_file->flush();
}
@@ -1950,7 +2029,7 @@ void device_debug::tracer::vprintf(const char *format, va_list va)
void device_debug::tracer::flush()
{
- fflush(&m_file);
+ m_file->flush();
}