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.
This commit is contained in:
AJR 2022-08-28 13:27:35 -04:00
parent f52b402f24
commit d8d588262d
18 changed files with 738 additions and 852 deletions

View File

@ -0,0 +1,134 @@
.. _debugger-exceptionpoint-list:
Exception Point Debugger Commands
=================================
:ref:`debugger-command-epset`
sets a new exception point
:ref:`debugger-command-epclear`
clears a specific exception point or all exception points
:ref:`debugger-command-epdisable`
disables a specific exception point or all exception points
:ref:`debugger-command-epenable`
enables a specific exception point or all exception points
:ref:`debugger-command-eplist`
lists exception points
Exception points halt execution and activate the debugger when
a CPU raises a particular exception number.
.. _debugger-command-epset:
epset
-----
**ep[set] <type>[,<condition>[,<action>]]**
Sets a new exception point for exceptions of type **<type>**. The
optional **<condition>** parameter lets you specify an expression that
will be evaluated each time the exception point is hit. If the result
of the expression is true (non-zero), the exception point will actually
halt execution at the start of the exception handler; otherwise,
execution will continue with no notification. The optional **<action>**
parameter provides a command that is executed whenever the exception
point is hit and the **<condition>** is true. Note that you may need to
embed the action within braces ``{ }`` in order to prevent commas and
semicolons from being interpreted as applying to the ``epset`` command
itself.
The numbering of exceptions depends upon the CPU type. Causes of
exceptions may include internally or externally vectored interrupts,
errors occurring within instructions and system calls.
Each exception point that is set is assigned an index which can be used
in other exception point commands to reference this exception point.
Examples:
``ep 2``
Set an exception that will halt execution whenever the visible CPU
raises exception number 2.
Back to :ref:`debugger-exceptionpoint-list`
.. _debugger-command-epclear:
epclear
-------
**epclear [<epnum>[,…]]**
The epclear command clears exception points. If **<epnum>** is
specified, only the requested exception points are cleared, otherwise
all exception points are cleared.
Examples:
``epclear 3``
Clear exception point index 3.
``epclear``
Clear all exception points.
Back to :ref:`debugger-exceptionpoint-list`
.. _debugger-command-epdisable:
epdisable
---------
**epdisable [<epnum>[,…]]**
The epdisable command disables exception points. If **<epnum>** is
specified, only the requested exception points are disabled, otherwise
all exception points are disabled. Note that disabling an exception
point does not delete it, it just temporarily marks the exception
point as inactive.
Examples:
``epdisable 3``
Disable exception point index 3.
``epdisable``
Disable all exception points.
Back to :ref:`debugger-exceptionpoint-list`
.. _debugger-command-epenable:
epenable
--------
**epenable [<epnum>[,…]]**
The epenable command enables exception points. If **<epnum>** is
specified, only the requested exception points are enabled, otherwise
all exception points are enabled.
Examples:
``epenable 3``
Enable exception point index 3.
``epenable``
Enable all exception points.
Back to :ref:`debugger-exceptionpoint-list`
.. _debugger-command-eplist:
eplist
------
**eplist**
The eplist command lists all the current exception points, along with
their index and any conditions or actions attached to them.
Back to :ref:`debugger-exceptionpoint-list`

View File

@ -50,6 +50,7 @@ name of a command, to see documentation directly in MAME.
breakpoint
watchpoint
registerpoints
exceptionpoint
annotation
cheats
image

View File

@ -282,6 +282,13 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
m_console.register_command("rpenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpdisenable, this, true, _1));
m_console.register_command("rplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_rplist, this, _1));
m_console.register_command("epset", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_epset, this, _1));
m_console.register_command("ep", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_epset, this, _1));
m_console.register_command("epclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_epclear, this, _1));
m_console.register_command("epdisable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_epdisenable, this, false, _1));
m_console.register_command("epenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_epdisenable, this, true, _1));
m_console.register_command("eplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_eplist, this, _1));
m_console.register_command("statesave", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1));
m_console.register_command("ss", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1));
m_console.register_command("stateload", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_stateload, this, _1));
@ -471,8 +478,9 @@ bool debugger_commands::validate_boolean_parameter(std::string_view param, bool
return true;
// evaluate the expression; success if no error
bool const is_true = util::streqlower(param, "true");
bool const is_false = util::streqlower(param, "false");
using namespace std::literals;
bool const is_true = util::streqlower(param, "true"sv);
bool const is_false = util::streqlower(param, "false"sv);
if (is_true || is_false)
{
@ -1153,7 +1161,7 @@ void debugger_commands::execute_tracelog(const std::vector<std::string_view> &pa
/* then do a printf */
std::ostringstream buffer;
if (mini_printf(buffer, params[0], params.size() - 1, &values[1]))
m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str().c_str());
m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str());
}
@ -1189,7 +1197,7 @@ void debugger_commands::execute_tracesym(const std::vector<std::string_view> &pa
// then do a printf
std::ostringstream buffer;
if (mini_printf(buffer, format.str(), params.size(), values))
m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str().c_str());
m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str());
}
@ -1819,12 +1827,12 @@ void debugger_commands::execute_bpset(const std::vector<std::string_view> &param
return;
// param 3 is the action
std::string action;
std::string_view action;
if (params.size() > 2 && !debug_command_parameter_command(action = params[2]))
return;
// set the breakpoint
int const bpnum = debug->breakpoint_set(address, condition.is_empty() ? nullptr : condition.original_string(), action.c_str());
int const bpnum = debug->breakpoint_set(address, condition.is_empty() ? nullptr : condition.original_string(), action);
m_console.printf("Breakpoint %X set\n", bpnum);
}
@ -1966,16 +1974,20 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin
// param 3 is the type
read_or_write type;
if (util::streqlower(params[2], "r"))
type = read_or_write::READ;
else if (util::streqlower(params[2], "w"))
type = read_or_write::WRITE;
else if (util::streqlower(params[2], "rw") || util::streqlower(params[2], "wr"))
type = read_or_write::READWRITE;
else
{
m_console.printf("Invalid watchpoint type: expected r, w, or rw\n");
return;
using util::streqlower;
using namespace std::literals;
if (streqlower(params[2], "r"sv))
type = read_or_write::READ;
else if (streqlower(params[2], "w"sv))
type = read_or_write::WRITE;
else if (streqlower(params[2], "rw"sv) || streqlower(params[2], "wr"sv))
type = read_or_write::READWRITE;
else
{
m_console.printf("Invalid watchpoint type: expected r, w, or rw\n");
return;
}
}
// param 4 is the condition
@ -1984,12 +1996,12 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin
return;
// param 5 is the action
std::string action;
std::string_view action;
if (params.size() > 4 && !debug_command_parameter_command(action = params[4]))
return;
// set the watchpoint
int const wpnum = debug->watchpoint_set(*space, type, address, length, (condition.is_empty()) ? nullptr : condition.original_string(), action.c_str());
int const wpnum = debug->watchpoint_set(*space, type, address, length, (condition.is_empty()) ? nullptr : condition.original_string(), action);
m_console.printf("Watchpoint %X set\n", wpnum);
}
@ -2133,12 +2145,12 @@ void debugger_commands::execute_rpset(const std::vector<std::string_view> &param
return;
// param 2 is the action
std::string action;
std::string_view action;
if (params.size() > 1 && !debug_command_parameter_command(action = params[1]))
return;
// set the registerpoint
int const rpnum = cpu->debug()->registerpoint_set(condition.original_string(), action.c_str());
int const rpnum = cpu->debug()->registerpoint_set(condition.original_string(), action);
m_console.printf("Registerpoint %X set\n", rpnum);
}
@ -2201,6 +2213,148 @@ void debugger_commands::execute_rpdisenable(bool enable, const std::vector<std::
}
//-------------------------------------------------
// execute_epset - execute the exception point
// set command
//-------------------------------------------------
void debugger_commands::execute_epset(const std::vector<std::string_view> &params)
{
// CPU is implicit
device_t *cpu;
if (!validate_cpu_parameter(std::string_view(), cpu))
return;
// param 1 is the exception type
u64 type;
if (!validate_number_parameter(params[0], type))
return;
// param 2 is the condition
parsed_expression condition(cpu->debug()->symtable());
if (params.size() > 1 && !debug_command_parameter_expression(params[1], condition))
return;
// param 3 is the action
std::string_view action;
if (params.size() > 2 && !debug_command_parameter_command(action = params[2]))
return;
// set the exception point
int epnum = cpu->debug()->exceptionpoint_set(type, (condition.is_empty()) ? nullptr : condition.original_string(), action);
m_console.printf("Exception point %X set\n", epnum);
}
//-------------------------------------------------
// execute_epclear - execute the exception point
// clear command
//-------------------------------------------------
void debugger_commands::execute_epclear(const std::vector<std::string_view> &params)
{
if (params.empty()) // if no parameters, clear all
{
for (device_t &device : device_enumerator(m_machine.root_device()))
device.debug()->exceptionpoint_clear_all();
m_console.printf("Cleared all exception points\n");
}
else // otherwise, clear the specific ones
{
execute_index_command(
params,
[this] (device_t &device, u64 param) -> bool
{
if (!device.debug()->exceptionpoint_clear(param))
return false;
m_console.printf("Exception point %X cleared\n", param);
return true;
},
"Invalid exception point number %X\n");
}
}
//-------------------------------------------------
// execute_epdisenable - execute the exception
// point disable/enable commands
//-------------------------------------------------
void debugger_commands::execute_epdisenable(bool enable, const std::vector<std::string_view> &params)
{
if (params.empty()) // if no parameters, disable/enable all
{
for (device_t &device : device_enumerator(m_machine.root_device()))
device.debug()->exceptionpoint_enable_all(enable);
m_console.printf(enable ? "Enabled all exception points\n" : "Disabled all exception points\n");
}
else // otherwise, disable/enable the specific ones
{
execute_index_command(
params,
[this, enable] (device_t &device, u64 param) -> bool
{
if (!device.debug()->exceptionpoint_enable(param, enable))
return false;
m_console.printf(enable ? "Exception point %X enabled\n" : "Exception point %X disabled\n", param);
return true;
},
"Invalid exception point number %X\n");
}
}
//-------------------------------------------------
// execute_eplist - execute the exception point
// list command
//-------------------------------------------------
void debugger_commands::execute_eplist(const std::vector<std::string_view> &params)
{
int printed = 0;
std::string buffer;
auto const apply =
[this, &printed, &buffer] (device_t &device)
{
if (!device.debug()->exceptionpoint_list().empty())
{
m_console.printf("Device '%s' exception points:\n", device.tag());
// loop over the exception points
for (const auto &epp : device.debug()->exceptionpoint_list())
{
debug_exceptionpoint &ep = *epp.second;
buffer = string_format("%c%4X : %X", ep.enabled() ? ' ' : 'D', ep.index(), ep.type());
if (std::string(ep.condition()).compare("1") != 0)
buffer.append(string_format(" if %s", ep.condition()));
if (!ep.action().empty())
buffer.append(string_format(" do %s", ep.action()));
m_console.printf("%s\n", buffer);
printed++;
}
}
};
if (!params.empty())
{
device_t *cpu;
if (!validate_cpu_parameter(params[0], cpu))
return;
apply(*cpu);
if (!printed)
m_console.printf("No exception points currently installed for CPU %s\n", cpu->tag());
}
else
{
// loop over all CPUs
for (device_t &device : device_enumerator(m_machine.root_device()))
apply(device);
if (!printed)
m_console.printf("No exception points currently installed\n");
}
}
/*-------------------------------------------------
execute_rplist - execute the registerpoint list
command
@ -2221,7 +2375,7 @@ void debugger_commands::execute_rplist(const std::vector<std::string_view> &para
for (const auto &rp : device.debug()->registerpoint_list())
{
buffer = string_format("%c%4X if %s", rp.enabled() ? ' ' : 'D', rp.index(), rp.condition());
if (rp.action() && *rp.action())
if (!rp.action().empty())
buffer.append(string_format(" do %s", rp.action()));
m_console.printf("%s\n", buffer);
printed++;
@ -3129,30 +3283,34 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::s
// decode condition
u8 condition;
if (util::streqlower(params[0], "all"))
condition = CHEAT_ALL;
else if (util::streqlower(params[0], "equal") || util::streqlower(params[0], "eq"))
condition = (params.size() > 1) ? CHEAT_EQUALTO : CHEAT_EQUAL;
else if (util::streqlower(params[0], "notequal") || util::streqlower(params[0], "ne"))
condition = (params.size() > 1) ? CHEAT_NOTEQUALTO : CHEAT_NOTEQUAL;
else if (util::streqlower(params[0], "decrease") || util::streqlower(params[0], "de") || params[0] == "-")
condition = (params.size() > 1) ? CHEAT_DECREASEOF : CHEAT_DECREASE;
else if (util::streqlower(params[0], "increase") || util::streqlower(params[0], "in") || params[0] == "+")
condition = (params.size() > 1) ? CHEAT_INCREASEOF : CHEAT_INCREASE;
else if (util::streqlower(params[0], "decreaseorequal") || util::streqlower(params[0], "deeq"))
condition = CHEAT_DECREASE_OR_EQUAL;
else if (util::streqlower(params[0], "increaseorequal") || util::streqlower(params[0], "ineq"))
condition = CHEAT_INCREASE_OR_EQUAL;
else if (util::streqlower(params[0], "smallerof") || util::streqlower(params[0], "lt") || params[0] == "<")
condition = CHEAT_SMALLEROF;
else if (util::streqlower(params[0], "greaterof") || util::streqlower(params[0], "gt") || params[0] == ">")
condition = CHEAT_GREATEROF;
else if (util::streqlower(params[0], "changedby") || util::streqlower(params[0], "ch") || params[0] == "~")
condition = CHEAT_CHANGEDBY;
else
{
m_console.printf("Invalid condition type\n");
return;
using util::streqlower;
using namespace std::literals;
if (streqlower(params[0], "all"sv))
condition = CHEAT_ALL;
else if (streqlower(params[0], "equal"sv) || streqlower(params[0], "eq"sv))
condition = (params.size() > 1) ? CHEAT_EQUALTO : CHEAT_EQUAL;
else if (streqlower(params[0], "notequal"sv) || streqlower(params[0], "ne"sv))
condition = (params.size() > 1) ? CHEAT_NOTEQUALTO : CHEAT_NOTEQUAL;
else if (streqlower(params[0], "decrease"sv) || streqlower(params[0], "de"sv) || params[0] == "-"sv)
condition = (params.size() > 1) ? CHEAT_DECREASEOF : CHEAT_DECREASE;
else if (streqlower(params[0], "increase"sv) || streqlower(params[0], "in"sv) || params[0] == "+"sv)
condition = (params.size() > 1) ? CHEAT_INCREASEOF : CHEAT_INCREASE;
else if (streqlower(params[0], "decreaseorequal"sv) || streqlower(params[0], "deeq"sv))
condition = CHEAT_DECREASE_OR_EQUAL;
else if (streqlower(params[0], "increaseorequal"sv) || streqlower(params[0], "ineq"sv))
condition = CHEAT_INCREASE_OR_EQUAL;
else if (streqlower(params[0], "smallerof"sv) || streqlower(params[0], "lt"sv) || params[0] == "<"sv)
condition = CHEAT_SMALLEROF;
else if (streqlower(params[0], "greaterof"sv) || streqlower(params[0], "gt"sv) || params[0] == ">"sv)
condition = CHEAT_GREATEROF;
else if (streqlower(params[0], "changedby"sv) || streqlower(params[0], "ch"sv) || params[0] == "~"sv)
condition = CHEAT_CHANGEDBY;
else
{
m_console.printf("Invalid condition type\n");
return;
}
}
m_cheat.undo++;
@ -3754,17 +3912,16 @@ void debugger_commands::execute_dasm(const std::vector<std::string_view> &params
void debugger_commands::execute_trace(const std::vector<std::string_view> &params, bool trace_over)
{
std::string action;
std::string_view action;
bool detect_loops = true;
bool logerror = false;
device_t *cpu;
const char *mode;
std::string filename(params[0]);
// replace macros
strreplace(filename, "{game}", m_machine.basename());
// validate parameters
device_t *cpu;
if (!validate_cpu_parameter(params.size() > 1 ? params[1] : std::string_view(), cpu))
return;
if (params.size() > 2)
@ -3775,9 +3932,10 @@ void debugger_commands::execute_trace(const std::vector<std::string_view> &param
std::string flag;
while (std::getline(stream, flag, '|'))
{
if (util::streqlower(flag, "noloop"))
using namespace std::literals;
if (util::streqlower(flag, "noloop"sv))
detect_loops = false;
else if (util::streqlower(flag, "logerror"))
else if (util::streqlower(flag, "logerror"sv))
logerror = true;
else
{
@ -3790,19 +3948,22 @@ void debugger_commands::execute_trace(const std::vector<std::string_view> &param
return;
// open the file
FILE *f = nullptr;
if (!util::streqlower(filename, "off"))
std::unique_ptr<std::ofstream> f;
using namespace std::literals;
if (!util::streqlower(filename, "off"sv))
{
mode = "w";
std::ios_base::openmode mode = std::ios_base::out;
// opening for append?
if ((filename[0] == '>') && (filename[1] == '>'))
{
mode = "a";
mode |= std::ios_base::ate;
filename = filename.substr(2);
}
else
mode |= std::ios_base::trunc;
f = fopen(filename.c_str(), mode);
f = std::make_unique<std::ofstream>(filename.c_str(), mode);
if (!f)
{
m_console.printf("Error opening file '%s'\n", params[0]);
@ -3811,7 +3972,7 @@ void debugger_commands::execute_trace(const std::vector<std::string_view> &param
}
// do it
cpu->debug()->trace(f, trace_over, detect_loops, logerror, action.c_str());
cpu->debug()->trace(std::move(f), trace_over, detect_loops, logerror, action);
if (f)
m_console.printf("Tracing CPU '%s' to file %s\n", cpu->tag(), filename);
else

View File

@ -148,6 +148,10 @@ private:
void execute_rpclear(const std::vector<std::string_view> &params);
void execute_rpdisenable(bool enable, const std::vector<std::string_view> &params);
void execute_rplist(const std::vector<std::string_view> &params);
void execute_epset(const std::vector<std::string_view> &params);
void execute_epclear(const std::vector<std::string_view> &params);
void execute_epdisenable(bool enable, const std::vector<std::string_view> &params);
void execute_eplist(const std::vector<std::string_view> &params);
void execute_statesave(const std::vector<std::string_view> &params);
void execute_stateload(const std::vector<std::string_view> &params);
void execute_rewind(const std::vector<std::string_view> &params);

View File

@ -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)
{
@ -892,22 +919,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,11 +1410,96 @@ 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();
}

View File

@ -29,9 +29,6 @@ constexpr int COMMENT_VERSION = 1;
// TYPE DEFINITIONS
//**************************************************************************
typedef int (*debug_instruction_hook_func)(device_t &device, offs_t curpc);
// ======================> device_debug
// [TODO] This whole thing is terrible.
@ -59,9 +56,6 @@ public:
void privilege_hook();
void instruction_hook(offs_t curpc);
// hooks into our operations
void set_instruction_hook(debug_instruction_hook_func hook);
// debugger focus
void ignore(bool ignore = true);
bool observing() const { return ((m_flags & DEBUG_FLAG_OBSERVING) != 0); }
@ -94,7 +88,7 @@ public:
// breakpoints
const auto &breakpoint_list() const { return m_bplist; }
const debug_breakpoint *breakpoint_find(offs_t address) const;
int breakpoint_set(offs_t address, const char *condition = nullptr, const char *action = nullptr);
int breakpoint_set(offs_t address, const char *condition = nullptr, std::string_view action = {});
bool breakpoint_clear(int index);
void breakpoint_clear_all();
bool breakpoint_enable(int index, bool enable = true);
@ -104,7 +98,7 @@ public:
// watchpoints
int watchpoint_space_count() const { return m_wplist.size(); }
const std::vector<std::unique_ptr<debug_watchpoint>> &watchpoint_vector(int spacenum) const { return m_wplist[spacenum]; }
int watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition, const char *action);
int watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition = nullptr, std::string_view action = {});
bool watchpoint_clear(int wpnum);
void watchpoint_clear_all();
bool watchpoint_enable(int index, bool enable = true);
@ -113,12 +107,20 @@ public:
debug_watchpoint *triggered_watchpoint() { debug_watchpoint *ret = m_triggered_watchpoint; m_triggered_watchpoint = nullptr; return ret; }
// registerpoints
const std::forward_list<debug_registerpoint> &registerpoint_list() const { return *m_rplist; }
int registerpoint_set(const char *condition, const char *action = nullptr);
const std::forward_list<debug_registerpoint> &registerpoint_list() const { return m_rplist; }
int registerpoint_set(const char *condition, std::string_view action = {});
bool registerpoint_clear(int index);
void registerpoint_clear_all();
bool registerpoint_enable(int index, bool enable = true);
void registerpoint_enable_all(bool enable = true );
void registerpoint_enable_all(bool enable = true);
// exception points
const auto &exceptionpoint_list() const { return m_eplist; }
int exceptionpoint_set(int exception, const char *condition = nullptr, std::string_view action = {});
bool exceptionpoint_clear(int index);
void exceptionpoint_clear_all();
bool exceptionpoint_enable(int index, bool enable = true);
void exceptionpoint_enable_all(bool enable = true);
// comments
void comment_add(offs_t address, const char *comment, rgb_t color);
@ -147,8 +149,12 @@ public:
void track_mem_data_clear() { m_track_mem_set.clear(); }
// tracing
void trace(FILE *file, bool trace_over, bool detect_loops, bool logerror, const char *action);
void trace_printf(const char *fmt, ...) ATTR_PRINTF(2,3);
void trace(std::unique_ptr<std::ostream> &&file, bool trace_over, bool detect_loops, bool logerror, std::string_view action);
template <typename Format, typename... Params> void trace_printf(Format &&fmt, Params &&...args)
{
if (m_trace != nullptr)
m_trace->vprintf(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
void trace_flush() { if (m_trace != nullptr) m_trace->flush(); }
void reset_transient_flag() { m_flags &= ~DEBUG_FLAG_TRANSIENT; }
@ -182,7 +188,6 @@ private:
// global state
u32 m_flags; // debugging flags for this CPU
std::unique_ptr<symbol_table> m_symtable; // symbol table for expression evaluation
debug_instruction_hook_func m_instrhook; // per-instruction callback hook
// stepping information
offs_t m_stepaddr; // step target address for DEBUG_FLAG_STEPPING_OVER or DEBUG_FLAG_STEPPING_BRANCH
@ -208,7 +213,8 @@ private:
// breakpoints and watchpoints
std::multimap<offs_t, std::unique_ptr<debug_breakpoint>> m_bplist; // list of breakpoints
std::vector<std::vector<std::unique_ptr<debug_watchpoint>>> m_wplist; // watchpoint lists for each address space
std::unique_ptr<std::forward_list<debug_registerpoint>> m_rplist; // list of registerpoints
std::forward_list<debug_registerpoint> m_rplist; // list of registerpoints
std::multimap<offs_t, std::unique_ptr<debug_exceptionpoint>> m_eplist; // list of exception points
debug_breakpoint * m_triggered_breakpoint; // latest breakpoint that was triggered
debug_watchpoint * m_triggered_watchpoint; // latest watchpoint that was triggered
@ -217,11 +223,11 @@ private:
class tracer
{
public:
tracer(device_debug &debug, FILE &file, bool trace_over, bool detect_loops, bool logerror, const char *action);
tracer(device_debug &debug, std::unique_ptr<std::ostream> &&file, bool trace_over, bool detect_loops, bool logerror, std::string_view action);
~tracer();
void update(offs_t pc);
void vprintf(const char *format, va_list va);
void vprintf(util::format_argument_pack<std::ostream> const &args);
void flush();
bool logerror() const { return m_logerror; }
@ -229,7 +235,7 @@ private:
static const int TRACE_LOOPS = 64;
device_debug & m_debug; // reference to our owner
FILE & m_file; // tracing file for this CPU
std::unique_ptr<std::ostream> m_file; // tracing file for this CPU
std::string m_action; // action to perform during a trace
offs_t m_history[TRACE_LOOPS]; // history of recent PCs
bool m_detect_loops; // whether or not we should detect loops
@ -312,7 +318,6 @@ private:
static constexpr u32 DEBUG_FLAG_HISTORY = 0x00000002; // tracking this CPU's history
static constexpr u32 DEBUG_FLAG_TRACING = 0x00000004; // tracing this CPU
static constexpr u32 DEBUG_FLAG_TRACING_OVER = 0x00000008; // tracing this CPU with step over behavior
static constexpr u32 DEBUG_FLAG_HOOKED = 0x00000010; // per-instruction callback hook
static constexpr u32 DEBUG_FLAG_STEPPING = 0x00000020; // CPU is single stepping
static constexpr u32 DEBUG_FLAG_STEPPING_OVER = 0x00000040; // CPU is stepping over a function
static constexpr u32 DEBUG_FLAG_STEPPING_OUT = 0x00000080; // CPU is stepping out of a function
@ -384,6 +389,7 @@ public:
u32 get_breakpoint_index() { return m_bpindex++; }
u32 get_watchpoint_index() { return m_wpindex++; }
u32 get_registerpoint_index() { return m_rpindex++; }
u32 get_exceptionpoint_index() { return m_epindex++; }
// setters
void set_break_cpu(device_t * breakcpu) { m_breakcpu = breakcpu; }
@ -426,6 +432,7 @@ private:
u32 m_bpindex;
u32 m_wpindex;
u32 m_rpindex;
u32 m_epindex;
u64 m_wpdata;
u64 m_wpaddr;

View File

@ -46,6 +46,7 @@ const help_item f_static_help_list[] =
" Breakpoints\n"
" Watchpoints\n"
" Registerpoints\n"
" Exception Points\n"
" Expressions\n"
" Comments\n"
" Cheats\n"
@ -190,6 +191,18 @@ const help_item f_static_help_list[] =
" rpenable [<rpnum>[,...]] -- enables given registerpoints or all if no <rpnum> specified\n"
" rplist [<CPU>] -- lists all the registerpoints\n"
},
{
"exceptionpoints",
"\n"
"Exception Point Commands\n"
"Type help <command> for further details on each command\n"
"\n"
" ep[set] <type>[,<condition>[,<action>]] -- sets exception point on <type>\n"
" epclear [<epnum>] -- clears a given exception point or all if no <epnum> specified\n"
" epdisable [<epnum>] -- disabled a given exception point or all if no <epnum> specified\n"
" epenable [<epnum>] -- enables a given exception point or all if no <epnum> specified\n"
" eplist -- lists all the registerpoints\n"
},
{
"expressions",
"\n"
@ -1554,6 +1567,92 @@ const help_item f_static_help_list[] =
"The rplist command lists all the current registerpoints, along with their index and any "
"actions attached to them.\n"
},
{
"epset",
"\n"
" ep[set] <type>[,<condition>[,<action>]]\n"
"\n"
"Sets a new exception point for exceptions of type <type> on the currently visible CPU. "
"The optional <condition> parameter lets you specify an expression that will be evaluated "
"each time the exception point is hit. If the result of the expression is true (non-zero), "
"the exception point will actually halt execution at the start of the exception handler; "
"otherwise, execution will continue with no notification. The optional <action> parameter "
"provides a command that is executed whenever the exception point is hit and the "
"<condition> is true. Note that you may need to embed the action within braces { } in order "
"to prevent commas and semicolons from being interpreted as applying to the epset command "
"itself.\n"
"\n"
"The numbering of exceptions depends upon the CPU type. Causes of exceptions may include "
"internally or externally vectored interrupts, errors occurring within instructions and "
"system calls.\n"
"\n"
"Each exception point that is set is assigned an index which can be used in other "
"exception point commands to reference this exception point.\n"
"\n"
"Examples:\n"
"\n"
"ep 2\n"
" Set an exception that will halt execution whenever the visible CPU raises exception "
"number 2.\n"
},
{
"epclear",
"\n"
" epclear [<epnum>[,...]]\n"
"\n"
"The epclear command clears exception points. If <epnum> is specified, only the requested "
"exception points are cleared, otherwise all exception points are cleared.\n"
"\n"
"Examples:\n"
"\n"
"epclear 3\n"
" Clear exception point index 3.\n"
"\n"
"epclear\n"
" Clear all exception points.\n"
},
{
"epdisable",
"\n"
" epdisable [<epnum>[,...]]\n"
"\n"
"The epdisable command disables exception points. If <epnum> is specified, only the requested "
"exception points are disabled, otherwise all exception points are disabled. Note that "
"disabling an exception point does not delete it, it just temporarily marks the exception "
"point as inactive.\n"
"\n"
"Examples:\n"
"\n"
"epdisable 3\n"
" Disable exception point index 3.\n"
"\n"
"epdisable\n"
" Disable all exception points.\n"
},
{
"epenable",
"\n"
" epenable [<epnum>[,...]]\n"
"\n"
"The epenable command enables exception points. If <epnum> is specified, only the "
"requested exception points are enabled, otherwise all exception points are enabled.\n"
"\n"
"Examples:\n"
"\n"
"epenable 3\n"
" Enable exception point index 3.\n"
"\n"
"epenable\n"
" Enable all exception points.\n"
},
{
"eplist",
"\n"
" eplist\n"
"\n"
"The eplist command lists all the current exception points, along with their index and "
"any conditions or actions attached to them.\n"
},
{
"map",
"\n"

View File

@ -71,7 +71,7 @@ static bool cConditionDescending(const debug_breakpoint *a, const debug_breakpoi
static bool cActionAscending(const debug_breakpoint *a, const debug_breakpoint *b)
{
return strcmp(a->action(), b->action()) < 0;
return a->action() < b->action();
}
static bool cActionDescending(const debug_breakpoint *a, const debug_breakpoint *b)

View File

@ -62,7 +62,7 @@ bool cConditionDescending(std::pair<device_t *, debug_registerpoint const *> con
bool cActionAscending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return strcmp(a.second->action(), b.second->action()) < 0;
return a.second->action() < b.second->action();
}
bool cActionDescending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)

View File

@ -28,13 +28,13 @@ debug_breakpoint::debug_breakpoint(
int index,
offs_t address,
const char *condition,
const char *action) :
std::string_view action) :
m_debugInterface(debugInterface),
m_index(index),
m_enabled(true),
m_address(address),
m_condition(symbols, condition ? condition : "1"),
m_action(action ? action : "")
m_action(action)
{
}
@ -88,7 +88,7 @@ debug_watchpoint::debug_watchpoint(
offs_t address,
offs_t length,
const char *condition,
const char *action) :
std::string_view action) :
m_debugInterface(debugInterface),
m_phr(nullptr),
m_phw(nullptr),
@ -99,7 +99,7 @@ debug_watchpoint::debug_watchpoint(
m_address(address & space.addrmask()),
m_length(length),
m_condition(symbols, condition ? condition : "1"),
m_action(action ? action : ""),
m_action(action),
m_installing(false)
{
std::fill(std::begin(m_start_address), std::end(m_start_address), 0);
@ -431,11 +431,11 @@ void debug_watchpoint::triggered(read_or_write type, offs_t address, u64 data, u
// debug_registerpoint - constructor
//-------------------------------------------------
debug_registerpoint::debug_registerpoint(symbol_table &symbols, int index, const char *condition, const char *action)
debug_registerpoint::debug_registerpoint(symbol_table &symbols, int index, const char *condition, std::string_view action)
: m_index(index),
m_enabled(true),
m_condition(symbols, (condition != nullptr) ? condition : "1"),
m_action((action != nullptr) ? action : "")
m_action(action)
{
}
@ -465,3 +465,59 @@ bool debug_registerpoint::hit()
return true;
}
//**************************************************************************
// DEBUG EXCEPTION POINT
//**************************************************************************
//-------------------------------------------------
// debug_exceptionpoint - constructor
//-------------------------------------------------
debug_exceptionpoint::debug_exceptionpoint(
device_debug *debugInterface,
symbol_table &symbols,
int index,
int type,
const char *condition,
std::string_view action)
: m_debugInterface(debugInterface),
m_index(index),
m_enabled(true),
m_type(type),
m_condition(symbols, (condition != nullptr) ? condition : "1"),
m_action(action)
{
}
//-------------------------------------------------
// hit - detect a hit
//-------------------------------------------------
bool debug_exceptionpoint::hit(int exception)
{
// don't hit if disabled
if (!m_enabled)
return false;
// must match our type
if (m_type != exception)
return false;
// must satisfy the condition
if (!m_condition.is_empty())
{
try
{
return (m_condition.execute() != 0);
}
catch (expression_error &)
{
return false;
}
}
return true;
}

View File

@ -36,7 +36,7 @@ public:
int index,
offs_t address,
const char *condition = nullptr,
const char *action = nullptr);
std::string_view action = {});
// getters
const device_debug *debugInterface() const { return m_debugInterface; }
@ -44,7 +44,7 @@ public:
bool enabled() const { return m_enabled; }
offs_t address() const { return m_address; }
const char *condition() const { return m_condition.original_string(); }
const char *action() const { return m_action.c_str(); }
const std::string &action() const { return m_action; }
// setters
void setEnabled(bool value) { m_enabled = value; } // FIXME: need to update breakpoint flags but it's a private method
@ -77,7 +77,7 @@ public:
offs_t address,
offs_t length,
const char *condition = nullptr,
const char *action = nullptr);
std::string_view action = {});
~debug_watchpoint();
// getters
@ -128,13 +128,13 @@ class debug_registerpoint
public:
// construction/destruction
debug_registerpoint(symbol_table &symbols, int index, const char *condition, const char *action = nullptr);
debug_registerpoint(symbol_table &symbols, int index, const char *condition, std::string_view action = {});
// getters
int index() const { return m_index; }
bool enabled() const { return m_enabled; }
const char *condition() const { return m_condition.original_string(); }
const char *action() const { return m_action.c_str(); }
const std::string &action() const { return m_action; }
private:
// internals
@ -146,4 +146,42 @@ private:
std::string m_action; // action
};
// ======================> debug_exceptionpoint
class debug_exceptionpoint
{
friend class device_debug;
public:
// construction/destruction
debug_exceptionpoint(
device_debug* debugInterface,
symbol_table &symbols,
int index,
int type,
const char *condition = nullptr,
std::string_view action = {});
// getters
const device_debug *debugInterface() const { return m_debugInterface; }
int index() const { return m_index; }
bool enabled() const { return m_enabled; }
int type() const { return m_type; }
const char *condition() const { return m_condition.original_string(); }
const std::string &action() const { return m_action; }
// setters
void setEnabled(bool value) { m_enabled = value; }
private:
// internals
bool hit(int exception);
const device_debug * m_debugInterface; // the interface we were created from
int m_index; // user reported index
bool m_enabled; // enabled?
int m_type; // exception type
parsed_expression m_condition; // condition
std::string m_action; // action
};
#endif // MAME_EMU_DEBUG_POINTS_H

View File

@ -99,6 +99,7 @@ class symbol_table;
class debug_breakpoint;
class debug_watchpoint;
class debug_registerpoint;
class debug_exceptionpoint;
// declared in debugger.h
class debugger_manager;

View File

@ -87,13 +87,6 @@ public:
void nimbus(machine_config &config);
uint32_t m_debug_machine = 0;
uint32_t m_debug_trap = 0;
void decode_subbios(device_t *device, offs_t pc);
void decode_subbios_return(device_t *device, offs_t pc);
void decode_dos21(device_t *device, offs_t pc);
private:
required_device<i80186_cpu_device> m_maincpu;
required_device<i8031_device> m_iocpu;

View File

@ -63,10 +63,6 @@ chdman createhd -o ST125N.chd -chs 41921,1,1 -ss 512
#include <functional>
#include "rmnimbus.h"
#include "debugger.h"
#include "debug/debugcmd.h"
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
#include "imagedev/floppy.h"
@ -136,52 +132,6 @@ chdman createhd -o ST125N.chd -chs 41921,1,1 -ss 512
#define LOG_IOU 0
#define LOG_RAM 0
/* Debugging */
#define DEBUG_SET(flags) ((m_debug_machine & (flags))==(flags))
#define DEBUG_SET_STATE(flags) ((state->m_debug_machine & (flags))==(flags))
#define DEBUG_NONE 0x0000000
#define DECODE_BIOS 0x0000002
#define DECODE_BIOS_RAW 0x0000004
#define DECODE_DOS21 0x0000008
/* Nimbus sub-bios structures for debugging */
struct t_area_params
{
uint16_t ofs_brush;
uint16_t seg_brush;
uint16_t ofs_data;
uint16_t seg_data;
uint16_t count;
};
struct t_plot_string_params
{
uint16_t ofs_font;
uint16_t seg_font;
uint16_t ofs_data;
uint16_t seg_data;
uint16_t x;
uint16_t y;
uint16_t length;
};
struct t_nimbus_brush
{
uint16_t style;
uint16_t style_index;
uint16_t colour1;
uint16_t colour2;
uint16_t transparency;
uint16_t boundary_spec;
uint16_t boundary_colour;
uint16_t save_colour;
};
static int instruction_hook(device_t &device, offs_t curpc);
void rmnimbus_state::external_int(uint8_t vector, bool state)
{
@ -218,648 +168,11 @@ void rmnimbus_state::machine_start()
{
m_nimbus_mouse.m_mouse_timer = timer_alloc(FUNC(rmnimbus_state::do_mouse), this);
/* setup debug commands */
if (machine().debug_flags & DEBUG_FLAG_ENABLED)
{
using namespace std::placeholders;
machine().debugger().console().register_command("nimbus_debug", CMDFLAG_NONE, 0, 1, std::bind(&rmnimbus_state::debug_command, this, _1));
/* set up the instruction hook */
m_maincpu->debug()->set_instruction_hook(instruction_hook);
}
m_debug_machine=DEBUG_NONE;
m_debug_trap=0;
m_voice_enabled=false;
m_fdc->dden_w(0);
//m_fdc->overide_delays(64,m_fdc->get_cmd_delay());
}
void rmnimbus_state::debug_command(const std::vector<std::string_view> &params)
{
if (params.size() > 0)
{
uint64_t temp;
if (!machine().debugger().commands().validate_number_parameter(params[0], temp))
return;
m_debug_machine = temp;
}
else
{
machine().debugger().console().printf("Error usage : nimbus_debug <debuglevel>\n");
machine().debugger().console().printf("Current debuglevel=%02X\n", m_debug_machine);
}
}
/*-----------------------------------------------
instruction_hook - per-instruction hook
-----------------------------------------------*/
static int instruction_hook(device_t &device, offs_t curpc)
{
rmnimbus_state *state = device.machine().driver_data<rmnimbus_state>();
address_space &space = device.memory().space(AS_PROGRAM);
uint8_t *addr_ptr;
uint8_t first;
addr_ptr = (uint8_t*)space.get_read_ptr(curpc);
first = (curpc & 0x01) ? 1 : 0;
if(DEBUG_SET_STATE(DECODE_BIOS) && (curpc == state->m_debug_trap) && (0 != state->m_debug_trap))
{
state->decode_subbios_return(&device,curpc);
}
if ((addr_ptr !=nullptr) && (addr_ptr[first]==0xCD))
{
if(DEBUG_SET_STATE(DECODE_BIOS) && (addr_ptr[first+1]==0xF0))
state->decode_subbios(&device,curpc);
if(DEBUG_SET_STATE(DECODE_DOS21) && (addr_ptr[first+1]==0x21))
state->decode_dos21(&device,curpc);
}
return 0;
}
void rmnimbus_state::decode_subbios_return(device_t *device, offs_t pc)
{
uint16_t ax = m_maincpu->state_int(I8086_AX);
uint16_t ds = m_maincpu->state_int(I8086_DS);
uint16_t si = m_maincpu->state_int(I8086_SI);
if(!DEBUG_SET(DECODE_BIOS_RAW))
{
logerror("at %05X sub-bios return code : %04X\n",pc,ax);
decode_dssi_generic(ds,si);
logerror("=======================================================================\n");
}
else
logerror("%05X :: %04X\n",pc,ax);
m_debug_trap=0;
}
#define set_type(type_name) sprintf(type_str,type_name)
#define set_drv(drv_name) sprintf(drv_str,drv_name)
#define set_func(func_name) sprintf(func_str,func_name)
void rmnimbus_state::decode_subbios(device_t *device,offs_t pc)
{
char type_str[80];
char drv_str[80];
char func_str[80];
void (rmnimbus_state::*dump_dssi)(uint16_t, uint16_t) = &rmnimbus_state::decode_dssi_none;
uint16_t ax = m_maincpu->state_int(I8086_AX);
uint16_t bx = m_maincpu->state_int(I8086_BX);
uint16_t cx = m_maincpu->state_int(I8086_CX);
uint16_t ds = m_maincpu->state_int(I8086_DS);
uint16_t si = m_maincpu->state_int(I8086_SI);
// Set the address to trap after the sub-bios call.
m_debug_trap=pc+2;
// *** TEMP Don't show f_enquire_display_line calls !
if((cx==6) && (ax==43))
return;
// *** END TEMP
if(!DEBUG_SET(DECODE_BIOS_RAW))
{
logerror("=======================================================================\n");
logerror("Sub-bios call at %08X, AX=%04X, BX=%04X, CX=%04X, DS:SI=%04X:%04X\n",pc,ax,bx,cx,ds,si);
}
set_type("invalid");
set_drv("invalid");
set_func("invalid");
switch (cx)
{
case 0 :
{
set_type("t_mummu");
set_drv("d_mummu");
switch (ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_add_type_code"); break;
case 2 : set_func("f_del_typc_code"); break;
case 3 : set_func("f_get_TCB"); break;
case 4 : set_func("f_add_driver_code"); break;
case 5 : set_func("f_del_driver_code"); break;
case 6 : set_func("f_get_DCB"); break;
case 7 : set_func("f_get_copyright"); break;
}
}; break;
case 1 :
{
set_type("t_character");
set_drv("d_printer");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_get_output_status"); break;
case 2 : set_func("f_output_character"); break;
case 3 : set_func("f_get_input_status"); break;
case 4 : set_func("f_get_and_remove"); break;
case 5 : set_func("f_get_no_remove"); break;
case 6 : set_func("f_get_last_and_remove"); break;
case 7 : set_func("f_get_last_no_remove"); break;
case 8 : set_func("f_set_IO_parameters"); break;
}
}; break;
case 2 :
{
set_type("t_disk");
switch(bx)
{
case 0 : set_drv("d_floppy"); break;
case 1 : set_drv("d_winchester"); break;
case 2 : set_drv("d_tape"); break;
case 3 : set_drv("d_rompack"); break;
case 4 : set_drv("d_eeprom"); break;
}
dump_dssi = &rmnimbus_state::decode_dssi_generic;
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_initialise_unit"); break;
case 2 : set_func("f_pseudo_init_unit"); break;
case 3 : set_func("f_get_device_status"); break;
case 4 : set_func("f_read_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
case 5 : set_func("f_write_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
case 6 : set_func("f_verify_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
case 7 : set_func("f_media_check"); break;
case 8 : set_func("f_recalibrate"); break;
case 9 : set_func("f_motors_off"); break;
}
}; break;
case 3 :
{
set_type("t_piconet");
set_drv("d_piconet");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_get_slave_status"); break;
case 2 : set_func("f_get_slave_map"); break;
case 3 : set_func("f_change_slave_addr"); break;
case 4 : set_func("f_read_slave_control"); break;
case 5 : set_func("f_write_slave_control"); break;
case 6 : set_func("f_send_data_byte"); break;
case 7 : set_func("f_request_data_byte"); break;
case 8 : set_func("f_send_data_block"); break;
case 9 : set_func("f_request_data_block"); break;
case 10 : set_func("f_reset_slave"); break;
}
}; break;
case 4 :
{
set_type("t_tick");
set_drv("d_tick");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_ticks_per_second"); break;
case 2 : set_func("f_link_tick_routine"); break;
case 3 : set_func("f_unlink_tick_routine"); break;
}
}; break;
case 5 :
{
set_type("t_graphics_input");
switch(bx)
{
case 0 : set_drv("d_mouse"); break;
case 1 : set_drv("d_joystick_1"); break;
case 2 : set_drv("d_joystick_2"); break;
}
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_graphics_input_cold_start"); break;
case 2 : set_func("f_graphics_input_device_off"); break;
case 3 : set_func("f_return_button_status"); break;
case 4 : set_func("f_return_switch_and_button_stat"); break;
case 5 : set_func("f_start_tracking"); break;
case 6 : set_func("f_stop_tracking"); break;
case 7 : set_func("f_enquire_position"); break;
case 8 : set_func("f_set_position"); break;
case 10 : set_func("f_return_button_press_info"); break;
case 11 : set_func("f_return_button_release_info"); break;
case 12 : set_func("f_set_gain/f_set_squeaks_per_pixel_ratio"); break;
case 13 : set_func("f_enquire_graphics_in_misc_data"); break;
}
}; break;
case 6 :
{
set_type("t_graphics_output");
set_drv("d_ngc_screen");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_graphics_output_cold_start"); break;
case 2 : set_func("f_graphics_output_warm_start"); break;
case 3 : set_func("f_graphics_output_off"); break;
case 4 : set_func("f_reinit_graphics_output"); break;
case 5 : set_func("f_polymarker"); break;
case 6 : set_func("f_polyline"); dump_dssi = &rmnimbus_state::decode_dssi_f_fill_area; break;
case 7 : set_func("f_fill_area"); dump_dssi = &rmnimbus_state::decode_dssi_f_fill_area; break;
case 8 : set_func("f_flood_fill_area"); break;
case 9 : set_func("f_plot_character_string"); dump_dssi = &rmnimbus_state::decode_dssi_f_plot_character_string; break;
case 10 : set_func("f_define_graphics_clipping_area"); break;
case 11 : set_func("f_enquire_clipping_area_limits"); break;
case 12 : set_func("f_select_graphics_clipping_area"); break;
case 13 : set_func("f_enq_selctd_graphics_clip_area"); break;
case 14 : set_func("f_set_clt_element"); break;
case 15 : set_func("f_enquire_clt_element"); break;
case 16 : set_func("f_set_new_clt"); dump_dssi = &rmnimbus_state::decode_dssi_f_set_new_clt; break;
case 17 : set_func("f_enquire_clt_contents"); break;
case 18 : set_func("f_define_dithering_pattern"); break;
case 19 : set_func("f_enquire_dithering_pattern"); break;
case 20 : set_func("f_draw_sprite"); break;
case 21 : set_func("f_move_sprite"); break;
case 22 : set_func("f_erase_sprite"); break;
case 23 : set_func("f_read_pixel"); break;
case 24 : set_func("f_read_to_limit"); break;
case 25 : set_func("f_read_area_pixel"); break;
case 26 : set_func("f_write_area_pixel"); break;
case 27 : set_func("f_copy_area_pixel"); break;
case 29 : set_func("f_read_area_word"); break;
case 30 : set_func("f_write_area_word"); break;
case 31 : set_func("f_copy_area_word"); break;
case 32 : set_func("f_swap_area_word"); break;
case 33 : set_func("f_set_border_colour"); break;
case 34 : set_func("f_enquire_border_colour"); break;
case 35 : set_func("f_enquire_miscellaneous_data"); break;
case 36 : set_func("f_circle"); break;
case 38 : set_func("f_arc_of_ellipse"); break;
case 39 : set_func("f_isin"); break;
case 40 : set_func("f_icos"); break;
case 41 : set_func("f_define_hatching_pattern"); break;
case 42 : set_func("f_enquire_hatching_pattern"); break;
case 43 : set_func("f_enquire_display_line"); break;
case 44 : set_func("f_plonk_logo"); break;
}
}; break;
case 7 :
{
set_type("t_zend");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
}
}; break;
case 8 :
{
set_type("t_zep");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
}
}; break;
case 9 :
{
set_type("t_raw_console");
switch(bx)
{
case 0 :
{
set_drv("d_screen");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_plonk_char"); dump_dssi = &rmnimbus_state::decode_dssi_f_plonk_char; break;
case 2 : set_func("f_plonk_cursor"); break;
case 3 : set_func("f_kill_cursor"); break;
case 4 : set_func("f_scroll"); break;
case 5 : set_func("f_width"); dump_dssi = &rmnimbus_state::decode_dssi_generic; break;
case 6 : set_func("f_get_char_set"); break;
case 7 : set_func("f_set_char_set"); break;
case 8 : set_func("f_reset_char_set"); break;
case 9 : set_func("f_set_plonk_parameters"); break;
case 10 : set_func("f_set_cursor_flash_rate"); break;
}
}; break;
case 1 :
{
set_drv("d_keyboard");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_init_keyboard"); break;
case 2 : set_func("f_get_last_key_code"); break;
case 3 : set_func("f_get_bitmap"); break;
}
}; break;
}
}; break;
case 10 :
{
set_type("t_acoustics");
switch(bx)
{
case 0 :
{
set_drv("d_sound");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_sound_enable"); break;
case 2 : set_func("f_play_note"); break;
case 3 : set_func("f_get_queue_status"); break;
}
}; break;
case 1 :
{
set_drv("d_voice");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
case 1 : set_func("f_talk"); break;
case 2 : set_func("f_wait_and_talk"); break;
case 3 : set_func("f_test_talking"); break;
}
}
}
}; break;
case 11 :
{
set_type("t_hard_sums");
switch(ax)
{
case 0 : set_func("f_get_version_number"); break;
}
}; break;
}
if(DEBUG_SET(DECODE_BIOS_RAW))
{
(this->*dump_dssi)(ds, si);
}
else
{
logerror("Type=%s, Driver=%s, Function=%s\n",type_str,drv_str,func_str);
(this->*dump_dssi)(ds, si);
logerror("=======================================================================\n");
}
}
static inline void *get_regpair_ptr(address_space &space, uint16_t segment, uint16_t offset)
{
int addr;
addr=((segment<<4)+offset);
return space.get_read_ptr(addr);
}
void rmnimbus_state::decode_dssi_none(uint16_t ds, uint16_t si)
{
}
void rmnimbus_state::decode_dssi_generic(uint16_t ds, uint16_t si)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint16_t *params;
int count;
if(DEBUG_SET(DECODE_BIOS_RAW))
return;
params=(uint16_t *)get_regpair_ptr(space,ds,si);
for(count=0; count<10; count++)
logerror("%04X ",params[count]);
logerror("\n");
}
void rmnimbus_state::decode_dssi_f_fill_area(uint16_t ds, uint16_t si)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint16_t *addr_ptr;
t_area_params *area_params;
t_nimbus_brush *brush;
int cocount;
area_params = (t_area_params *)get_regpair_ptr(space,ds,si);
if (!DEBUG_SET(DECODE_BIOS_RAW))
OUTPUT_SEGOFS("SegBrush:OfsBrush",area_params->seg_brush,area_params->ofs_brush);
brush=(t_nimbus_brush *)space.get_read_ptr(LINEAR_ADDR(area_params->seg_brush,area_params->ofs_brush));
if(DEBUG_SET(DECODE_BIOS_RAW))
{
logerror("\tdw\t%04X, %04X, %04X, %04X, %04X, %04X, %04X, %04X, %04X, ",
brush->style,brush->style_index,brush->colour1,brush->colour2,
brush->transparency,brush->boundary_spec,brush->boundary_colour,brush->save_colour,
area_params->count);
}
else
{
logerror("Brush params\n");
logerror("Style=%04X, StyleIndex=%04X\n",brush->style,brush->style_index);
logerror("Colour1=%04X, Colour2=%04X\n",brush->colour1,brush->colour2);
logerror("transparency=%04X, boundary_spec=%04X\n",brush->transparency,brush->boundary_spec);
logerror("boundary colour=%04X, save colour=%04X\n",brush->boundary_colour,brush->save_colour);
OUTPUT_SEGOFS("SegData:OfsData",area_params->seg_data,area_params->ofs_data);
}
addr_ptr = (uint16_t *)space.get_read_ptr(LINEAR_ADDR(area_params->seg_data,area_params->ofs_data));
for(cocount=0; cocount < area_params->count; cocount++)
{
if(DEBUG_SET(DECODE_BIOS_RAW))
{
if(cocount!=(area_params->count-1))
logerror("%04X, %04X, ",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
else
logerror("%04X, %04X ",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
}
else
logerror("x=%d y=%d\n",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
}
if(DEBUG_SET(DECODE_BIOS_RAW))
logerror("\n");
}
void rmnimbus_state::decode_dssi_f_plot_character_string(uint16_t ds, uint16_t si)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint8_t *char_ptr;
t_plot_string_params *plot_string_params;
int charno;
if(DEBUG_SET(DECODE_BIOS_RAW))
return;
plot_string_params=(t_plot_string_params *)get_regpair_ptr(space,ds,si);
OUTPUT_SEGOFS("SegFont:OfsFont",plot_string_params->seg_font,plot_string_params->ofs_font);
OUTPUT_SEGOFS("SegData:OfsData",plot_string_params->seg_data,plot_string_params->ofs_data);
logerror("x=%d, y=%d, length=%d\n",plot_string_params->x,plot_string_params->y,plot_string_params->length);
char_ptr=(uint8_t*)space.get_read_ptr(LINEAR_ADDR(plot_string_params->seg_data,plot_string_params->ofs_data));
if (plot_string_params->length==0xFFFF)
logerror("%s",char_ptr);
else
for(charno=0;charno<plot_string_params->length;charno++)
logerror("%c",char_ptr[charno]);
logerror("\n");
}
void rmnimbus_state::decode_dssi_f_set_new_clt(uint16_t ds, uint16_t si)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint16_t *new_colours;
int colour;
new_colours=(uint16_t *)get_regpair_ptr(space,ds,si);
if(DEBUG_SET(DECODE_BIOS_RAW))
return;
OUTPUT_SEGOFS("SegColours:OfsColours",ds,si);
for(colour=0;colour<16;colour++)
logerror("colour #%02X=%04X\n",colour,new_colours[colour]);
}
void rmnimbus_state::decode_dssi_f_plonk_char(uint16_t ds, uint16_t si)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint16_t *params;
params=(uint16_t *)get_regpair_ptr(space,ds,si);
if(DEBUG_SET(DECODE_BIOS_RAW))
return;
OUTPUT_SEGOFS("SegParams:OfsParams",ds,si);
logerror("plonked_char=%c\n",params[0]);
}
void rmnimbus_state::decode_dssi_f_rw_sectors(uint16_t ds, uint16_t si)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint16_t *params;
int param_no;
if(DEBUG_SET(DECODE_BIOS_RAW))
return;
params=(uint16_t *)get_regpair_ptr(space,ds,si);
logerror("unitno=%04X, count=%02X, first_sector=%08X buffer=%04X:%04X (%05X)\n",
params[0],
params[1],
((params[3] * 65536)+params[2]),
params[5],params[4],
((params[5]*16)+params[4])
);
for(param_no=0;param_no<16;param_no++)
logerror("%04X ",params[param_no]);
logerror("\n");
}
void rmnimbus_state::decode_dos21(device_t *device,offs_t pc)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
//uint16_t *params;
char *path;
uint16_t ax = m_maincpu->state_int(I8086_AX);
uint16_t bx = m_maincpu->state_int(I8086_BX);
uint16_t cx = m_maincpu->state_int(I8086_CX);
uint16_t dx = m_maincpu->state_int(I8086_DX);
uint16_t cs = m_maincpu->state_int(I8086_CS);
uint16_t ds = m_maincpu->state_int(I8086_DS);
uint16_t es = m_maincpu->state_int(I8086_ES);
uint16_t ss = m_maincpu->state_int(I8086_SS);
uint16_t si = m_maincpu->state_int(I8086_SI);
uint16_t di = m_maincpu->state_int(I8086_DI);
uint16_t bp = m_maincpu->state_int(I8086_BP);
uint8_t dosfn = ax >> 8; // Dos function is AH, upper half of AX.
logerror("=======================================================================\n");
logerror("DOS Int 0x21 call at %05X\n",pc);
logerror("AX=%04X, BX=%04X, CX=%04X, DX=%04X\n",ax,bx,cx,dx);
logerror("CS=%04X, DS=%04X, ES=%04X, SS=%04X\n",cs,ds,es,ss);
logerror("SI=%04X, DI=%04X, BP=%04X\n",si,di,bp);
logerror("=======================================================================\n");
if (((dosfn >= 0x39) && (dosfn <= 0x3d))
|| (0x43 == dosfn)
|| (0x4e == dosfn)
|| (0x56 == dosfn)
|| ((dosfn >= 0x5a) && (dosfn <= 0x5b)) )
{
path=(char *)get_regpair_ptr(space,ds,dx);
logerror("Path at DS:DX=%s\n",path);
if (0x56 == dosfn)
{
path=(char *)get_regpair_ptr(space,es,di);
logerror("Path at ES:DI=%s\n",path);
}
logerror("=======================================================================\n");
}
}
#define CBUFLEN 32
offs_t rmnimbus_state::dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer &params)

View File

@ -1211,15 +1211,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf)
return REPLY_OK;
case 2:
// write watchpoint
debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind, nullptr, nullptr);
debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind);
return REPLY_OK;
case 3:
// read watchpoint
debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind, nullptr, nullptr);
debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind);
return REPLY_OK;
case 4:
// access watchpoint
debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind, nullptr, nullptr);
debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind);
return REPLY_OK;
}

View File

@ -182,7 +182,7 @@
// if it doesn't exist, add a new one
if (bp == nullptr)
{
uint32_t const bpnum = device.debug()->breakpoint_set(address, nullptr, nullptr);
uint32_t const bpnum = device.debug()->breakpoint_set(address);
machine->debugger().console().printf("Breakpoint %X set\n", bpnum);
}
else

View File

@ -149,7 +149,7 @@ void DasmWindow::toggleBreakpointAtCursor(bool changedTo)
// If none exists, add a new one
if (!bp)
{
int32_t bpindex = cpuinfo->breakpoint_set(address, nullptr, nullptr);
int32_t bpindex = cpuinfo->breakpoint_set(address);
m_machine.debugger().console().printf("Breakpoint %X set\n", bpindex);
}
else

View File

@ -174,7 +174,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam)
{
if (bp == nullptr)
{
int32_t bpindex = debug->breakpoint_set(address, nullptr, nullptr);
int32_t bpindex = debug->breakpoint_set(address);
machine().debugger().console().printf("Breakpoint %X set\n", bpindex);
}
else