summaryrefslogtreecommitdiffstats
path: root/src/emu/debug/debugcmd.cpp
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2020-05-25 11:15:39 -0400
committer AJR <ajrhacker@users.noreply.github.com>2020-05-25 11:15:39 -0400
commit0fa6e7eb86d3b247c46f840ef230c9331f3cc948 (patch)
treee01509e44adcff62a7d8e087c58572fce6b90e13 /src/emu/debug/debugcmd.cpp
parentad7a31ad57b09e1e0e9bb1adb03767f9dd386605 (diff)
Debugger expression and memory access overhaul
- Memory references in expressions no longer default to the console's visible CPU if no device name was specified, except when entered through the console itself. Expressions in view windows now use the context of the currently selected device instead. - The pcatmem debug command and similar qt mouseover function now produce an error message if the initial address translation fails. Related internal changes (nw) - The debugger_cpu class no longer interprets memory accesses. The existing routines have been moved into symbol_table (which used to invoke them as callbacks), and reimplemented in most other places. Thecode duplication is a bit messy, but could be potentially improved in the future with new utility classes. - The cheat engine no longer needs to hook into the debugger_cpu class or instantiate a dummy instance of it. - The inclusion of debug/express.h within emu.h has been undone. Some debugging structures now need unique_ptr to wrap the resulting incomplete classes; hopefully the performance impact of this is negligible. Another direct consequence is that the breakpoint, watchpoint and registerpoint classes are no longer inside device_debug and have their own source file. - The breakpoint list is now a std::multimap, using the addresses as keys to hopefully expedite lookup. - The visible CPU pointer has been removed from the debugger_cpu class, being now considered a property of the console instead. - Many minor bits of code have been simplified.
Diffstat (limited to 'src/emu/debug/debugcmd.cpp')
-rw-r--r--src/emu/debug/debugcmd.cpp165
1 files changed, 124 insertions, 41 deletions
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index 01d2f462d50..d8e1c985d27 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/*********************************************************************
- debugcmd.c
+ debugcmd.cpp
Debugger command interface engine.
@@ -18,6 +18,7 @@
#include "express.h"
#include "debughlp.h"
#include "debugvw.h"
+#include "points.h"
#include "natkeyboard.h"
#include "render.h"
#include <cctype>
@@ -58,9 +59,9 @@ u64 debugger_commands::cheat_sign_extend(const cheat_system *cheatsys, u64 value
{
switch (cheatsys->width)
{
- case 1: value = s8(value); break;
- case 2: value = s16(value); break;
- case 4: value = s32(value); break;
+ case 1: value = s8(value); break;
+ case 2: value = s16(value); break;
+ case 4: value = s32(value); break;
}
}
return value;
@@ -76,10 +77,9 @@ u64 debugger_commands::cheat_byte_swap(const cheat_system *cheatsys, u64 value)
{
switch (cheatsys->width)
{
- case 2: value = ((value >> 8) & 0x00ff) | ((value << 8) & 0xff00); break;
- case 4: value = ((value >> 24) & 0x000000ff) | ((value >> 8) & 0x0000ff00) | ((value << 8) & 0x00ff0000) | ((value << 24) & 0xff000000); break;
- case 8: value = ((value >> 56) & 0x00000000000000ffU) | ((value >> 40) & 0x000000000000ff00U) | ((value >> 24) & 0x0000000000ff0000U) | ((value >> 8) & 0x00000000ff000000U) |
- ((value << 8) & 0x000000ff00000000U) | ((value << 24) & 0x0000ff0000000000U) | ((value << 40) & 0x00ff000000000000U) | ((value << 56) & 0xff00000000000000U); break;
+ case 2: value = swapendian_int16(value); break;
+ case 4: value = swapendian_int32(value); break;
+ case 8: value = swapendian_int64(value); break;
}
}
return value;
@@ -93,7 +93,19 @@ u64 debugger_commands::cheat_byte_swap(const cheat_system *cheatsys, u64 value)
u64 debugger_commands::cheat_read_extended(const cheat_system *cheatsys, address_space &space, offs_t address)
{
- return cheat_sign_extend(cheatsys, cheat_byte_swap(cheatsys, m_cpu.read_memory(space, address, cheatsys->width, true)));
+ address &= space.logaddrmask();
+ u64 value = space.unmap();
+ if (space.device().memory().translate(space.spacenum(), TRANSLATE_READ_DEBUG, address))
+ {
+ switch (cheatsys->width)
+ {
+ case 1: value = space.read_byte(address); break;
+ case 2: value = space.read_word_unaligned(address); break;
+ case 4: value = space.read_dword_unaligned(address); break;
+ case 8: value = space.read_qword_unaligned(address); break;
+ }
+ }
+ return cheat_sign_extend(cheatsys, cheat_byte_swap(cheatsys, value));
}
debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu, debugger_console& console)
@@ -110,6 +122,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
symtable.add("min", 2, 2, std::bind(&debugger_commands::execute_min, this, _1, _2));
symtable.add("max", 2, 2, std::bind(&debugger_commands::execute_max, this, _1, _2));
symtable.add("if", 3, 3, std::bind(&debugger_commands::execute_if, this, _1, _2));
+ symtable.add("cpunum", std::bind(&debugger_commands::get_cpunum, this));
/* add all single-entry save state globals */
for (int itemnum = 0; itemnum < MAX_GLOBALS; itemnum++)
@@ -332,6 +345,17 @@ u64 debugger_commands::execute_if(int params, const u64 *param)
}
+//-------------------------------------------------
+// get_cpunum - getter callback for the
+// 'cpunum' symbol
+//-------------------------------------------------
+
+u64 debugger_commands::get_cpunum()
+{
+ execute_interface_iterator iter(m_machine.root_device());
+ return iter.indexof(m_console.get_visible_cpu()->execute());
+}
+
/***************************************************************************
GLOBAL ACCESSORS
@@ -385,7 +409,7 @@ bool debugger_commands::validate_number_parameter(const std::string &param, u64
/* evaluate the expression; success if no error */
try
{
- result = parsed_expression(m_cpu.visible_symtable(), param.c_str()).execute();
+ result = parsed_expression(m_console.visible_symtable(), param.c_str()).execute();
return true;
}
catch (expression_error &error)
@@ -436,7 +460,7 @@ bool debugger_commands::validate_cpu_parameter(const char *param, device_t *&res
/* if no parameter, use the visible CPU */
if (param == nullptr)
{
- result = m_cpu.get_visible_cpu();
+ result = m_console.get_visible_cpu();
if (!result)
{
m_console.printf("No valid CPU is currently selected\n");
@@ -454,7 +478,7 @@ bool debugger_commands::validate_cpu_parameter(const char *param, device_t *&res
u64 cpunum;
try
{
- cpunum = parsed_expression(m_cpu.visible_symtable(), param).execute();
+ cpunum = parsed_expression(m_console.visible_symtable(), param).execute();
}
catch (expression_error &)
{
@@ -743,7 +767,7 @@ void debugger_commands::execute_tracelog(int ref, const std::vector<std::string>
/* then do a printf */
char buffer[1024];
if (mini_printf(buffer, params[0].c_str(), params.size() - 1, &values[1]))
- m_cpu.get_visible_cpu()->debug()->trace_printf("%s", buffer);
+ m_console.get_visible_cpu()->debug()->trace_printf("%s", buffer);
}
@@ -759,7 +783,7 @@ void debugger_commands::execute_tracesym(int ref, const std::vector<std::string>
for (int i = 0; i < params.size(); i++)
{
// find this symbol
- symbol_entry *sym = m_cpu.visible_symtable().find(params[i].c_str());
+ symbol_entry *sym = m_console.visible_symtable().find(params[i].c_str());
if (!sym)
{
m_console.printf("Unknown symbol: %s\n", params[i].c_str());
@@ -779,7 +803,7 @@ void debugger_commands::execute_tracesym(int ref, const std::vector<std::string>
// then do a printf
char buffer[1024];
if (mini_printf(buffer, format.str().c_str(), params.size(), values))
- m_cpu.get_visible_cpu()->debug()->trace_printf("%s", buffer);
+ m_console.get_visible_cpu()->debug()->trace_printf("%s", buffer);
}
@@ -816,7 +840,7 @@ void debugger_commands::execute_step(int ref, const std::vector<std::string> &pa
if (params.size() > 0 && !validate_number_parameter(params[0], steps))
return;
- m_cpu.get_visible_cpu()->debug()->single_step(steps);
+ m_console.get_visible_cpu()->debug()->single_step(steps);
}
@@ -831,7 +855,7 @@ void debugger_commands::execute_over(int ref, const std::vector<std::string> &pa
if (params.size() > 0 && !validate_number_parameter(params[0], steps))
return;
- m_cpu.get_visible_cpu()->debug()->single_step_over(steps);
+ m_console.get_visible_cpu()->debug()->single_step_over(steps);
}
@@ -841,7 +865,7 @@ void debugger_commands::execute_over(int ref, const std::vector<std::string> &pa
void debugger_commands::execute_out(int ref, const std::vector<std::string> &params)
{
- m_cpu.get_visible_cpu()->debug()->single_step_out();
+ m_console.get_visible_cpu()->debug()->single_step_out();
}
@@ -857,7 +881,7 @@ void debugger_commands::execute_go(int ref, const std::vector<std::string> &para
if (params.size() > 0 && !validate_number_parameter(params[0], addr))
return;
- m_cpu.get_visible_cpu()->debug()->go(addr);
+ m_console.get_visible_cpu()->debug()->go(addr);
}
@@ -868,7 +892,7 @@ void debugger_commands::execute_go(int ref, const std::vector<std::string> &para
void debugger_commands::execute_go_vblank(int ref, const std::vector<std::string> &params)
{
- m_cpu.get_visible_cpu()->debug()->go_vblank();
+ m_console.get_visible_cpu()->debug()->go_vblank();
}
@@ -884,7 +908,7 @@ void debugger_commands::execute_go_interrupt(int ref, const std::vector<std::str
if (params.size() > 0 && !validate_number_parameter(params[0], irqline))
return;
- m_cpu.get_visible_cpu()->debug()->go_interrupt(irqline);
+ m_console.get_visible_cpu()->debug()->go_interrupt(irqline);
}
/*-------------------------------------------------
@@ -899,11 +923,11 @@ void debugger_commands::execute_go_exception(int ref, const std::vector<std::str
if (params.size() > 0 && !validate_number_parameter(params[0], exception))
return;
- parsed_expression condition(m_cpu.get_visible_cpu()->debug()->symtable());
+ parsed_expression condition(m_console.visible_symtable());
if (params.size() > 1 && !debug_command_parameter_expression(params[1], condition))
return;
- m_cpu.get_visible_cpu()->debug()->go_exception(exception, (condition.is_empty()) ? "1" : condition.original_string());
+ m_console.get_visible_cpu()->debug()->go_exception(exception, (condition.is_empty()) ? "1" : condition.original_string());
}
@@ -919,7 +943,7 @@ void debugger_commands::execute_go_time(int ref, const std::vector<std::string>
if (params.size() > 0 && !validate_number_parameter(params[0], milliseconds))
return;
- m_cpu.get_visible_cpu()->debug()->go_milliseconds(milliseconds);
+ m_console.get_visible_cpu()->debug()->go_milliseconds(milliseconds);
}
@@ -929,11 +953,11 @@ void debugger_commands::execute_go_time(int ref, const std::vector<std::string>
-------------------------------------------------*/
void debugger_commands::execute_go_privilege(int ref, const std::vector<std::string> &params)
{
- parsed_expression condition(m_cpu.get_visible_cpu()->debug()->symtable());
+ parsed_expression condition(m_console.visible_symtable());
if (params.size() > 0 && !debug_command_parameter_expression(params[0], condition))
return;
- m_cpu.get_visible_cpu()->debug()->go_privilege((condition.is_empty()) ? "1" : condition.original_string());
+ m_console.get_visible_cpu()->debug()->go_privilege((condition.is_empty()) ? "1" : condition.original_string());
}
/*-------------------------------------------------
@@ -942,7 +966,7 @@ void debugger_commands::execute_go_privilege(int ref, const std::vector<std::str
void debugger_commands::execute_next(int ref, const std::vector<std::string> &params)
{
- m_cpu.get_visible_cpu()->debug()->go_next_device();
+ m_console.get_visible_cpu()->debug()->go_next_device();
}
@@ -1194,7 +1218,7 @@ void debugger_commands::execute_cpulist(int ref, const std::vector<std::string>
{
device_state_interface *state;
if (exec.device().interface(state) && state->state_find_entry(STATE_GENPCBASE) != nullptr)
- m_console.printf("[%s%d] %s\n", &exec.device() == m_cpu.get_visible_cpu() ? "*" : "", index++, exec.device().tag());
+ m_console.printf("[%s%d] %s\n", &exec.device() == m_console.get_visible_cpu() ? "*" : "", index++, exec.device().tag());
}
}
@@ -1425,8 +1449,9 @@ void debugger_commands::execute_bplist(int ref, const std::vector<std::string> &
m_console.printf("Device '%s' breakpoints:\n", device.tag());
/* loop over the breakpoints */
- for (const device_debug::breakpoint &bp : device.debug()->breakpoint_list())
+ for (const auto &bpp : device.debug()->breakpoint_list())
{
+ debug_breakpoint &bp = *bpp.second;
buffer = string_format("%c%4X @ %0*X", bp.enabled() ? ' ' : 'D', bp.index(), device.debug()->logaddrchars(), bp.address());
if (std::string(bp.condition()).compare("1") != 0)
buffer.append(string_format(" if %s", bp.condition()));
@@ -1725,7 +1750,7 @@ void debugger_commands::execute_rplist(int ref, const std::vector<std::string> &
m_console.printf("Device '%s' registerpoints:\n", device.tag());
/* loop over the breakpoints */
- for (const device_debug::registerpoint &rp : device.debug()->registerpoint_list())
+ for (const debug_registerpoint &rp : device.debug()->registerpoint_list())
{
buffer = string_format("%c%4X if %s", rp.enabled() ? ' ' : 'D', rp.index(), rp.condition());
if (rp.action() != nullptr)
@@ -2655,7 +2680,6 @@ void debugger_commands::execute_find(int ref, const std::vector<std::string> &pa
int cur_data_size;
int data_count = 0;
int found = 0;
- int j;
/* validate parameters */
if (!validate_number_parameter(params[0], offset))
@@ -2681,7 +2705,7 @@ void debugger_commands::execute_find(int ref, const std::vector<std::string> &pa
/* check for a string */
if (pdata[0] == '"' && pdata[pdatalen] == '"')
{
- for (j = 1; j < pdatalen; j++)
+ for (int j = 1; j < pdatalen; j++)
{
data_to_find[data_count] = pdata[j];
data_size[data_count++] = 1;
@@ -2709,21 +2733,54 @@ void debugger_commands::execute_find(int ref, const std::vector<std::string> &pa
}
/* now search */
+ device_memory_interface &memory = space->device().memory();
+ auto dis = space->device().machine().disable_side_effects();
for (u64 i = offset; i <= endoffset; i += data_size[0])
{
int suboffset = 0;
bool match = true;
/* find the entire string */
- for (j = 0; j < data_count && match; j++)
+ for (int j = 0; j < data_count && match; j++)
{
+ offs_t address = space->byte_to_address(i + suboffset);
switch (data_size[j])
{
- case 1: match = (u8(m_cpu.read_byte(*space, space->byte_to_address(i + suboffset), true)) == u8(data_to_find[j])); break;
- case 2: match = (u16(m_cpu.read_word(*space, space->byte_to_address(i + suboffset), true)) == u16(data_to_find[j])); break;
- case 4: match = (u32(m_cpu.read_dword(*space, space->byte_to_address(i + suboffset), true)) == u32(data_to_find[j])); break;
- case 8: match = (u64(m_cpu.read_qword(*space, space->byte_to_address(i + suboffset), true)) == u64(data_to_find[j])); break;
- default: /* all other cases are wildcards */ break;
+ case 1:
+ address &= space->logaddrmask();
+ if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address))
+ match = space->read_byte(address) == u8(data_to_find[j]);
+ else
+ match = false;
+ break;
+
+ case 2:
+ address &= space->logaddrmask();
+ if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address))
+ match = space->read_word_unaligned(address) == u16(data_to_find[j]);
+ else
+ match = false;
+ break;
+
+ case 4:
+ address &= space->logaddrmask();
+ if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address))
+ match = space->read_dword_unaligned(address) == u32(data_to_find[j]);
+ else
+ match = false;
+ break;
+
+ case 8:
+ address &= space->logaddrmask();
+ if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address))
+ match = space->read_qword_unaligned(address) == u64(data_to_find[j]);
+ else
+ match = false;
+ break;
+
+ default:
+ /* all other cases are wildcards */
+ break;
}
suboffset += data_size[j] & 0x0f;
}
@@ -3010,7 +3067,7 @@ void debugger_commands::execute_trackpc(int ref, const std::vector<std::string>
if (turnOn)
{
// Insert current pc
- if (m_cpu.get_visible_cpu() == cpu)
+ if (m_console.get_visible_cpu() == cpu)
{
const offs_t pc = cpu->state().pcbase();
cpu->debug()->set_track_pc_visited(pc);
@@ -3083,9 +3140,35 @@ void debugger_commands::execute_pcatmem(int ref, const std::vector<std::string>
if (!validate_cpu_space_parameter((params.size() > 1) ? params[1].c_str() : nullptr, ref, space))
return;
+ // Translate the address
+ offs_t a = address & space->logaddrmask();
+ if (!space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, a))
+ {
+ m_console.printf("Bad address\n");
+ return;
+ }
+
// Get the value of memory at the address
- const int native_data_width = space->data_width() / 8;
- const u64 data = m_cpu.read_memory(*space, space->address_to_byte(address), native_data_width, true);
+ u64 data = space->unmap();
+ auto dis = space->device().machine().disable_side_effects();
+ switch (space->data_width())
+ {
+ case 8:
+ data = space->read_byte(a);
+ break;
+
+ case 16:
+ data = space->read_word_unaligned(a);
+ break;
+
+ case 32:
+ data = space->read_dword_unaligned(a);
+ break;
+
+ case 64:
+ data = space->read_qword_unaligned(a);
+ break;
+ }
// Recover the pc & print
const int space_num = (int)ref;