diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua index 0a5207d5365..89c7d3ccd20 100644 --- a/scripts/src/emu.lua +++ b/scripts/src/emu.lua @@ -244,6 +244,8 @@ files { MAME_DIR .. "src/emu/debug/dvtext.h", MAME_DIR .. "src/emu/debug/express.cpp", MAME_DIR .. "src/emu/debug/express.h", + MAME_DIR .. "src/emu/debug/points.cpp", + MAME_DIR .. "src/emu/debug/points.h", MAME_DIR .. "src/emu/debug/textbuf.cpp", MAME_DIR .. "src/emu/debug/textbuf.h", MAME_DIR .. "src/emu/drivers/empty.cpp", 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 @@ -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 ¶m, 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 /* 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 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 // 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 &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 &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 &pa void debugger_commands::execute_out(int ref, const std::vector ¶ms) { - 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 ¶ 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 ¶ void debugger_commands::execute_go_vblank(int ref, const std::vector ¶ms) { - 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 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 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 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 -------------------------------------------------*/ void debugger_commands::execute_go_privilege(int ref, const std::vector ¶ms) { - 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 ¶ms) { - 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 { 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 & 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 & 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 &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 &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 &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 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 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; diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index 62e8008c322..a47378765ff 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -84,6 +84,7 @@ private: u64 execute_min(int params, const u64 *param); u64 execute_max(int params, const u64 *param); u64 execute_if(int params, const u64 *param); + u64 get_cpunum(); u64 global_get(global_entry *global); void global_set(global_entry *global, u64 value); diff --git a/src/emu/debug/debugcon.cpp b/src/emu/debug/debugcon.cpp index 2c5989a8faa..e9c08268338 100644 --- a/src/emu/debug/debugcon.cpp +++ b/src/emu/debug/debugcon.cpp @@ -35,6 +35,7 @@ debugger_console::debugger_console(running_machine &machine) : m_machine(machine) + , m_visiblecpu(nullptr) , m_console_textbuf(nullptr) , m_errorlog_textbuf(nullptr) { @@ -60,6 +61,17 @@ debugger_console::debugger_console(running_machine &machine) /* register our own custom-command help */ register_command("helpcustom", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_console::execute_help_custom, this, _1, _2)); + + /* first CPU is visible by default */ + for (device_t &device : device_iterator(m_machine.root_device())) + { + auto *cpu = dynamic_cast(&device); + if (cpu != nullptr) + { + m_visiblecpu = cpu; + break; + } + } } @@ -121,6 +133,18 @@ void debugger_console::execute_help_custom(int ref, const std::vectordebug()->symtable(); +} + + + /*------------------------------------------------- trim_parameter - executes a command @@ -334,7 +358,7 @@ CMDERR debugger_console::internal_parse_command(const std::string &original_comm { try { - parsed_expression(m_machine.debugger().cpu().visible_symtable(), command_start).execute(); + parsed_expression(visible_symtable(), command_start).execute(); } catch (expression_error &err) { diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h index e57b06a7378..cabff196d9f 100644 --- a/src/emu/debug/debugcon.h +++ b/src/emu/debug/debugcon.h @@ -107,6 +107,10 @@ public: vprintf_wrap(wrapcol, util::make_format_argument_pack(std::forward(fmt), std::forward(args)...)); } + device_t *get_visible_cpu() { return m_visiblecpu; } + void set_visible_cpu(device_t *visiblecpu) { m_visiblecpu = visiblecpu; } + symbol_table &visible_symtable(); + static std::string cmderr_to_string(CMDERR error); private: @@ -134,6 +138,9 @@ private: running_machine &m_machine; + // visible CPU device (the one that commands should apply to) + device_t *m_visiblecpu; + text_buffer *m_console_textbuf; text_buffer *m_errorlog_textbuf; diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index fb5db3ffb89..afdef1362d1 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -13,6 +13,7 @@ #include "debugbuf.h" #include "express.h" +#include "points.h" #include "debugcon.h" #include "debugvw.h" @@ -36,7 +37,6 @@ const size_t debugger_cpu::NUM_TEMP_VARIABLES = 10; debugger_cpu::debugger_cpu(running_machine &machine) : m_machine(machine) , m_livecpu(nullptr) - , m_visiblecpu(nullptr) , m_breakcpu(nullptr) , m_symtable(nullptr) , m_vblank_occurred(false) @@ -53,17 +53,13 @@ debugger_cpu::debugger_cpu(running_machine &machine) m_tempvar = make_unique_clear(NUM_TEMP_VARIABLES); /* create a global symbol table */ - m_symtable = std::make_unique(); + m_symtable = std::make_unique(machine); + m_symtable->set_memory_modified_func([this]() { set_memory_modified(true); }); - // configure our base memory accessors - configure_memory(*m_symtable); - - /* add "wpaddr", "wpdata", "cycles", "cpunum", "logunmap" to the global symbol table */ + /* add "wpaddr", "wpdata" to the global symbol table */ m_symtable->add("wpaddr", symbol_table::READ_ONLY, &m_wpaddr); m_symtable->add("wpdata", symbol_table::READ_ONLY, &m_wpdata); - m_symtable->add("cpunum", std::bind(&debugger_cpu::get_cpunum, this)); - screen_device_iterator screen_iterator = screen_device_iterator(m_machine.root_device()); screen_device_iterator::auto_iterator iter = screen_iterator.begin(); const uint32_t count = (uint32_t)screen_iterator.count(); @@ -74,7 +70,7 @@ debugger_cpu::debugger_cpu(running_machine &machine) m_symtable->add("beamx", [&screen]() { return screen.hpos(); }); m_symtable->add("beamy", [&screen]() { return screen.vpos(); }); m_symtable->add("frame", [&screen]() { return screen.frame_number(); }); - iter.current()->register_vblank_callback(vblank_state_delegate(&debugger_cpu::on_vblank, this)); + screen.register_vblank_callback(vblank_state_delegate(&debugger_cpu::on_vblank, this)); } else if (count > 1) { @@ -84,7 +80,7 @@ debugger_cpu::debugger_cpu(running_machine &machine) m_symtable->add(string_format("beamx%d", i).c_str(), [&screen]() { return screen.hpos(); }); m_symtable->add(string_format("beamy%d", i).c_str(), [&screen]() { return screen.vpos(); }); m_symtable->add(string_format("frame%d", i).c_str(), [&screen]() { return screen.frame_number(); }); - iter.current()->register_vblank_callback(vblank_state_delegate(&debugger_cpu::on_vblank, this)); + screen.register_vblank_callback(vblank_state_delegate(&debugger_cpu::on_vblank, this)); } } @@ -95,27 +91,8 @@ debugger_cpu::debugger_cpu(running_machine &machine) sprintf(symname, "temp%d", regnum); m_symtable->add(symname, symbol_table::READ_WRITE, &m_tempvar[regnum]); } - - /* first CPU is visible by default */ - for (device_t &device : device_iterator(m_machine.root_device())) - { - auto *cpu = dynamic_cast(&device); - if (cpu != nullptr) - { - m_visiblecpu = cpu; - break; - } - } } -void debugger_cpu::configure_memory(symbol_table &table) -{ - using namespace std::placeholders; - table.configure_memory( - std::bind(&debugger_cpu::expression_validate, this, _1, _2), - std::bind(&debugger_cpu::expression_read_memory, this, _1, _2, _3, _4, _5), - std::bind(&debugger_cpu::expression_write_memory, this, _1, _2, _3, _4, _5, _6)); -} /*------------------------------------------------- flush_traces - flushes all traces; this is @@ -134,22 +111,6 @@ void debugger_cpu::flush_traces() -//************************************************************************** -// SYMBOL TABLE INTERFACES -//************************************************************************** - -//------------------------------------------------- -// visible_symtable - return the locally-visible -// symbol table -//------------------------------------------------- - -symbol_table &debugger_cpu::visible_symtable() -{ - return m_visiblecpu->debug()->symtable(); -} - - - //************************************************************************** // MEMORY AND DISASSEMBLY HELPERS //************************************************************************** @@ -287,294 +248,6 @@ bool debugger_cpu::comment_load(bool is_inline) -/*************************************************************************** - DEBUGGER MEMORY ACCESSORS -***************************************************************************/ - -/*------------------------------------------------- - read_byte - return a byte from the specified - memory space --------------------------------------------------*/ - -u8 debugger_cpu::read_byte(address_space &space, offs_t address, bool apply_translation) -{ - device_memory_interface &memory = space.device().memory(); - - if (apply_translation) - { - /* mask against the logical byte mask */ - address &= space.logaddrmask(); - - /* translate if necessary; if not mapped, return 0xff */ - if (!memory.translate(space.spacenum(), TRANSLATE_READ_DEBUG, address)) - return 0xff; - } - - /* otherwise, call the byte reading function for the translated address */ - return space.read_byte(address); -} - - -/*------------------------------------------------- - read_word - return a word from the specified - memory space --------------------------------------------------*/ - -u16 debugger_cpu::read_word(address_space &space, offs_t address, bool apply_translation) -{ - device_memory_interface &memory = space.device().memory(); - - if (apply_translation) - { - /* mask against the logical byte mask */ - address &= space.logaddrmask(); - - /* translate if necessary; if not mapped, return 0xffff */ - if (!memory.translate(space.spacenum(), TRANSLATE_READ_DEBUG, address)) - return 0xffff; - } - - /* otherwise, call the byte reading function for the translated address */ - return space.read_word_unaligned(address); -} - - -/*------------------------------------------------- - read_dword - return a dword from the specified - memory space --------------------------------------------------*/ - -u32 debugger_cpu::read_dword(address_space &space, offs_t address, bool apply_translation) -{ - device_memory_interface &memory = space.device().memory(); - - if (apply_translation) - { - /* mask against the logical byte mask */ - address &= space.logaddrmask(); - - /* translate if necessary; if not mapped, return 0xffffffff */ - if (!memory.translate(space.spacenum(), TRANSLATE_READ_DEBUG, address)) - return 0xffffffff; - } - - /* otherwise, call the byte reading function for the translated address */ - return space.read_dword_unaligned(address); -} - - -/*------------------------------------------------- - read_qword - return a qword from the specified - memory space --------------------------------------------------*/ - -u64 debugger_cpu::read_qword(address_space &space, offs_t address, bool apply_translation) -{ - device_memory_interface &memory = space.device().memory(); - - /* translate if necessary; if not mapped, return 0xffffffffffffffff */ - if (apply_translation) - { - /* mask against the logical byte mask */ - address &= space.logaddrmask(); - - /* translate if necessary; if not mapped, return 0xffffffff */ - if (!memory.translate(space.spacenum(), TRANSLATE_READ_DEBUG, address)) - return ~u64(0); - } - - /* otherwise, call the byte reading function for the translated address */ - return space.read_qword_unaligned(address); -} - - -/*------------------------------------------------- - read_memory - return 1,2,4 or 8 bytes - from the specified memory space --------------------------------------------------*/ - -u64 debugger_cpu::read_memory(address_space &space, offs_t address, int size, bool apply_translation) -{ - u64 result = ~u64(0) >> (64 - 8*size); - switch (size) - { - case 1: result = read_byte(space, address, apply_translation); break; - case 2: result = read_word(space, address, apply_translation); break; - case 4: result = read_dword(space, address, apply_translation); break; - case 8: result = read_qword(space, address, apply_translation); break; - } - return result; -} - - -/*------------------------------------------------- - write_byte - write a byte to the specified - memory space --------------------------------------------------*/ - -void debugger_cpu::write_byte(address_space &space, offs_t address, u8 data, bool apply_translation) -{ - device_memory_interface &memory = space.device().memory(); - - if (apply_translation) - { - /* mask against the logical byte mask */ - address &= space.logaddrmask(); - - /* translate if necessary; if not mapped, we're done */ - if (!memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address)) - return; - } - - /* otherwise, call the byte reading function for the translated address */ - space.write_byte(address, data); - - m_memory_modified = true; -} - - -/*------------------------------------------------- - write_word - write a word to the specified - memory space --------------------------------------------------*/ - -void debugger_cpu::write_word(address_space &space, offs_t address, u16 data, bool apply_translation) -{ - device_memory_interface &memory = space.device().memory(); - - if (apply_translation) - { - /* mask against the logical byte mask */ - address &= space.logaddrmask(); - - /* translate if necessary; if not mapped, we're done */ - if (!memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address)) - return; - } - - /* otherwise, call the byte reading function for the translated address */ - space.write_word_unaligned(address, data); - - m_memory_modified = true; -} - - -/*------------------------------------------------- - write_dword - write a dword to the specified - memory space --------------------------------------------------*/ - -void debugger_cpu::write_dword(address_space &space, offs_t address, u32 data, bool apply_translation) -{ - device_memory_interface &memory = space.device().memory(); - - if (apply_translation) - { - /* mask against the logical byte mask */ - address &= space.logaddrmask(); - - /* translate if necessary; if not mapped, we're done */ - if (!memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address)) - return; - } - - /* otherwise, call the byte reading function for the translated address */ - space.write_dword_unaligned(address, data); - - m_memory_modified = true; -} - - -/*------------------------------------------------- - write_qword - write a qword to the specified - memory space --------------------------------------------------*/ - -void debugger_cpu::write_qword(address_space &space, offs_t address, u64 data, bool apply_translation) -{ - device_memory_interface &memory = space.device().memory(); - - if (apply_translation) - { - /* mask against the logical byte mask */ - address &= space.logaddrmask(); - - /* translate if necessary; if not mapped, we're done */ - if (!memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address)) - return; - } - - /* otherwise, call the byte reading function for the translated address */ - space.write_qword_unaligned(address, data); - - m_memory_modified = true; -} - - -/*------------------------------------------------- - write_memory - write 1,2,4 or 8 bytes to the - specified memory space --------------------------------------------------*/ - -void debugger_cpu::write_memory(address_space &space, offs_t address, u64 data, int size, bool apply_translation) -{ - switch (size) - { - case 1: write_byte(space, address, data, apply_translation); break; - case 2: write_word(space, address, data, apply_translation); break; - case 4: write_dword(space, address, data, apply_translation); break; - case 8: write_qword(space, address, data, apply_translation); break; - } -} - - -/*------------------------------------------------- - read_opcode - read 1,2,4 or 8 bytes at the - given offset from opcode space --------------------------------------------------*/ - -u64 debugger_cpu::read_opcode(address_space &space, offs_t address, int size) -{ - device_memory_interface &memory = space.device().memory(); - - u64 result = ~u64(0) & (~u64(0) >> (64 - 8*size)); - - /* keep in logical range */ - address &= space.logaddrmask(); - - /* translate to physical first */ - if (!memory.translate(space.spacenum(), TRANSLATE_FETCH_DEBUG, address)) - return result; - - /* keep in physical range */ - address &= space.addrmask(); - - /* switch off the size and handle unaligned accesses */ - switch (size) - { - case 1: - result = space.read_byte(address); - break; - - case 2: - result = space.read_word_unaligned(address); - break; - - case 4: - result = space.read_dword_unaligned(address); - break; - - case 6: - case 8: - result = space.read_qword_unaligned(address); - break; - } - - return result; -} - - - /*************************************************************************** INTERNAL HELPERS ***************************************************************************/ @@ -605,537 +278,6 @@ void debugger_cpu::reset_transient_flags() } - -/*************************************************************************** - EXPRESSION HANDLERS -***************************************************************************/ - -/*------------------------------------------------- - expression_get_device - return a device - based on a case insensitive tag search --------------------------------------------------*/ - -device_t* debugger_cpu::expression_get_device(const char *tag) -{ - // convert to lowercase then lookup the name (tags are enforced to be all lower case) - std::string fullname(tag); - strmakelower(fullname); - return m_machine.root_device().subdevice(fullname.c_str()); -} - - -/*------------------------------------------------- - expression_read_memory - read 1,2,4 or 8 bytes - at the given offset in the given address - space --------------------------------------------------*/ - -u64 debugger_cpu::expression_read_memory(const char *name, expression_space spacenum, u32 address, int size, bool disable_se) -{ - switch (spacenum) - { - case EXPSPACE_PROGRAM_LOGICAL: - case EXPSPACE_DATA_LOGICAL: - case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - { - device_t *device = nullptr; - device_memory_interface *memory; - - if (name != nullptr) - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - { - device = get_visible_cpu(); - memory = &device->memory(); - } - if (memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - return read_memory(space, address, size, true); - } - break; - } - - case EXPSPACE_PROGRAM_PHYSICAL: - case EXPSPACE_DATA_PHYSICAL: - case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - { - device_t *device = nullptr; - device_memory_interface *memory; - - if (name != nullptr) - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - { - device = get_visible_cpu(); - memory = &device->memory(); - } - if (memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - return read_memory(space, address, size, false); - } - break; - } - - case EXPSPACE_RAMWRITE: - { - device_t *device = nullptr; - device_memory_interface *memory; - - if (name != nullptr) - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - { - device = get_visible_cpu(); - memory = &device->memory(); - } - auto dis = m_machine.disable_side_effects(disable_se); - return expression_read_program_direct(memory->space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size); - break; - } - - case EXPSPACE_OPCODE: - { - device_t *device = nullptr; - device_memory_interface *memory; - - if (name != nullptr) - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - { - device = get_visible_cpu(); - memory = &device->memory(); - } - auto dis = m_machine.disable_side_effects(disable_se); - return expression_read_program_direct(memory->space(AS_OPCODES), (spacenum == EXPSPACE_OPCODE), address, size); - break; - } - - case EXPSPACE_REGION: - if (name == nullptr) - break; - return expression_read_memory_region(name, address, size); - break; - - default: - break; - } - - return 0; -} - - -/*------------------------------------------------- - expression_read_program_direct - read memory - directly from an opcode or RAM pointer --------------------------------------------------*/ - -u64 debugger_cpu::expression_read_program_direct(address_space &space, int opcode, offs_t address, int size) -{ - u8 *base; - - /* adjust the address into a byte address, but not if being called recursively */ - if ((opcode & 2) == 0) - address = space.address_to_byte(address); - - /* call ourself recursively until we are byte-sized */ - if (size > 1) - { - int halfsize = size / 2; - - /* read each half, from lower address to upper address */ - u64 r0 = expression_read_program_direct(space, opcode | 2, address + 0, halfsize); - u64 r1 = expression_read_program_direct(space, opcode | 2, address + halfsize, halfsize); - - /* assemble based on the target endianness */ - if (space.endianness() == ENDIANNESS_LITTLE) - return r0 | (r1 << (8 * halfsize)); - else - return r1 | (r0 << (8 * halfsize)); - } - - /* handle the byte-sized final requests */ - else - { - /* lowmask specified which address bits are within the databus width */ - offs_t lowmask = space.data_width() / 8 - 1; - - /* get the base of memory, aligned to the address minus the lowbits */ - base = (u8 *)space.get_read_ptr(address & ~lowmask); - - /* if we have a valid base, return the appropriate byte */ - if (base != nullptr) - { - if (space.endianness() == ENDIANNESS_LITTLE) - return base[BYTE8_XOR_LE(address) & lowmask]; - else - return base[BYTE8_XOR_BE(address) & lowmask]; - } - } - - return 0; -} - - -/*------------------------------------------------- - expression_read_memory_region - read memory - from a memory region --------------------------------------------------*/ - -u64 debugger_cpu::expression_read_memory_region(const char *rgntag, offs_t address, int size) -{ - memory_region *region = m_machine.root_device().memregion(rgntag); - u64 result = ~u64(0) >> (64 - 8*size); - - /* make sure we get a valid base before proceeding */ - if (region != nullptr) - { - /* call ourself recursively until we are byte-sized */ - if (size > 1) - { - int halfsize = size / 2; - u64 r0, r1; - - /* read each half, from lower address to upper address */ - r0 = expression_read_memory_region(rgntag, address + 0, halfsize); - r1 = expression_read_memory_region(rgntag, address + halfsize, halfsize); - - /* assemble based on the target endianness */ - if (region->endianness() == ENDIANNESS_LITTLE) - result = r0 | (r1 << (8 * halfsize)); - else - result = r1 | (r0 << (8 * halfsize)); - } - - /* only process if we're within range */ - else if (address < region->bytes()) - { - /* lowmask specified which address bits are within the databus width */ - u32 lowmask = region->bytewidth() - 1; - u8 *base = region->base() + (address & ~lowmask); - - /* if we have a valid base, return the appropriate byte */ - if (region->endianness() == ENDIANNESS_LITTLE) - result = base[BYTE8_XOR_LE(address) & lowmask]; - else - result = base[BYTE8_XOR_BE(address) & lowmask]; - } - } - return result; -} - - -/*------------------------------------------------- - expression_write_memory - write 1,2,4 or 8 - bytes at the given offset in the given address - space --------------------------------------------------*/ - -void debugger_cpu::expression_write_memory(const char *name, expression_space spacenum, u32 address, int size, u64 data, bool disable_se) -{ - device_t *device = nullptr; - device_memory_interface *memory; - - switch (spacenum) - { - case EXPSPACE_PROGRAM_LOGICAL: - case EXPSPACE_DATA_LOGICAL: - case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - if (name != nullptr) - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - { - device = get_visible_cpu(); - memory = &device->memory(); - } - if (memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - write_memory(space, address, data, size, true); - } - break; - - case EXPSPACE_PROGRAM_PHYSICAL: - case EXPSPACE_DATA_PHYSICAL: - case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - if (name != nullptr) - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - { - device = get_visible_cpu(); - memory = &device->memory(); - } - if (memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - write_memory(space, address, data, size, false); - } - break; - - case EXPSPACE_RAMWRITE: { - if (name != nullptr) - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - { - device = get_visible_cpu(); - memory = &device->memory(); - } - auto dis = m_machine.disable_side_effects(disable_se); - expression_write_program_direct(memory->space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size, data); - break; - } - - case EXPSPACE_OPCODE: { - if (name != nullptr) - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - { - device = get_visible_cpu(); - memory = &device->memory(); - } - auto dis = m_machine.disable_side_effects(disable_se); - expression_write_program_direct(memory->space(AS_OPCODES), (spacenum == EXPSPACE_OPCODE), address, size, data); - break; - } - - case EXPSPACE_REGION: - if (name == nullptr) - break; - expression_write_memory_region(name, address, size, data); - break; - - default: - break; - } -} - - -/*------------------------------------------------- - expression_write_program_direct - write memory - directly to an opcode or RAM pointer --------------------------------------------------*/ - -void debugger_cpu::expression_write_program_direct(address_space &space, int opcode, offs_t address, int size, u64 data) -{ - /* adjust the address into a byte address, but not if being called recursively */ - if ((opcode & 2) == 0) - address = space.address_to_byte(address); - - /* call ourself recursively until we are byte-sized */ - if (size > 1) - { - int halfsize = size / 2; - - /* break apart based on the target endianness */ - u64 halfmask = ~u64(0) >> (64 - 8 * halfsize); - u64 r0, r1; - if (space.endianness() == ENDIANNESS_LITTLE) - { - r0 = data & halfmask; - r1 = (data >> (8 * halfsize)) & halfmask; - } - else - { - r0 = (data >> (8 * halfsize)) & halfmask; - r1 = data & halfmask; - } - - /* write each half, from lower address to upper address */ - expression_write_program_direct(space, opcode | 2, address + 0, halfsize, r0); - expression_write_program_direct(space, opcode | 2, address + halfsize, halfsize, r1); - } - - /* handle the byte-sized final case */ - else - { - /* lowmask specified which address bits are within the databus width */ - offs_t lowmask = space.data_width() / 8 - 1; - - /* get the base of memory, aligned to the address minus the lowbits */ - u8 *base = (u8 *)space.get_read_ptr(address & ~lowmask); - - /* if we have a valid base, write the appropriate byte */ - if (base != nullptr) - { - if (space.endianness() == ENDIANNESS_LITTLE) - base[BYTE8_XOR_LE(address) & lowmask] = data; - else - base[BYTE8_XOR_BE(address) & lowmask] = data; - m_memory_modified = true; - } - } -} - - -/*------------------------------------------------- - expression_write_memory_region - write memory - from a memory region --------------------------------------------------*/ - -void debugger_cpu::expression_write_memory_region(const char *rgntag, offs_t address, int size, u64 data) -{ - memory_region *region = m_machine.root_device().memregion(rgntag); - - /* make sure we get a valid base before proceeding */ - if (region != nullptr) - { - /* call ourself recursively until we are byte-sized */ - if (size > 1) - { - int halfsize = size / 2; - - /* break apart based on the target endianness */ - u64 halfmask = ~u64(0) >> (64 - 8 * halfsize); - u64 r0, r1; - if (region->endianness() == ENDIANNESS_LITTLE) - { - r0 = data & halfmask; - r1 = (data >> (8 * halfsize)) & halfmask; - } - else - { - r0 = (data >> (8 * halfsize)) & halfmask; - r1 = data & halfmask; - } - - /* write each half, from lower address to upper address */ - expression_write_memory_region(rgntag, address + 0, halfsize, r0); - expression_write_memory_region(rgntag, address + halfsize, halfsize, r1); - } - - /* only process if we're within range */ - else if (address < region->bytes()) - { - /* lowmask specified which address bits are within the databus width */ - u32 lowmask = region->bytewidth() - 1; - u8 *base = region->base() + (address & ~lowmask); - - /* if we have a valid base, set the appropriate byte */ - if (region->endianness() == ENDIANNESS_LITTLE) - { - base[BYTE8_XOR_LE(address) & lowmask] = data; - } - else - { - base[BYTE8_XOR_BE(address) & lowmask] = data; - } - m_memory_modified = true; - } - } -} - - -/*------------------------------------------------- - expression_validate - validate that the - provided expression references an - appropriate name --------------------------------------------------*/ - -expression_error::error_code debugger_cpu::expression_validate(const char *name, expression_space space) -{ - device_t *device = nullptr; - device_memory_interface *memory; - - switch (space) - { - case EXPSPACE_PROGRAM_LOGICAL: - case EXPSPACE_DATA_LOGICAL: - case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - if (name) - { - device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - } - if (!device) - device = get_visible_cpu(); - if (!device->interface(memory) || !memory->has_space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_LOGICAL))) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; - - case EXPSPACE_PROGRAM_PHYSICAL: - case EXPSPACE_DATA_PHYSICAL: - case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - if (name) - { - device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - } - if (!device) - device = get_visible_cpu(); - if (!device->interface(memory) || !memory->has_space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_PHYSICAL))) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; - - case EXPSPACE_RAMWRITE: - if (name) - { - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - return expression_error::INVALID_MEMORY_NAME; - } - if (!device) - device = get_visible_cpu(); - if (!device->interface(memory) || !memory->has_space(AS_PROGRAM)) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; - - case EXPSPACE_OPCODE: - if (name) - { - device = expression_get_device(name); - if (device == nullptr || !device->interface(memory)) - return expression_error::INVALID_MEMORY_NAME; - } - if (!device) - device = get_visible_cpu(); - if (!device->interface(memory) || !memory->has_space(AS_OPCODES)) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; - - case EXPSPACE_REGION: - if (!name) - return expression_error::MISSING_MEMORY_NAME; - if (!m_machine.root_device().memregion(name) || !m_machine.root_device().memregion(name)->base()) - return expression_error::INVALID_MEMORY_NAME; - break; - - default: - return expression_error::NO_SUCH_MEMORY_SPACE; - } - return expression_error::NONE; -} - - - -//************************************************************************** -// VARIABLE GETTERS/SETTERS -//************************************************************************** - -//------------------------------------------------- -// get_cpunum - getter callback for the -// 'cpunum' symbol -//------------------------------------------------- - -u64 debugger_cpu::get_cpunum() -{ - execute_interface_iterator iter(m_machine.root_device()); - return iter.indexof(m_visiblecpu->execute()); -} - - //************************************************************************** // EXECUTION HOOKS //************************************************************************** @@ -1164,7 +306,8 @@ void debugger_cpu::start_hook(device_t *device, bool stop_on_vblank) // if we're running, do some periodic updating if (m_execution_state != exec_state::STOPPED) { - if (device == m_visiblecpu && osd_ticks() > m_last_periodic_update_time + osd_ticks_per_second() / 4) + device_t *visiblecpu = m_machine.debugger().console().get_visible_cpu(); + if (device == visiblecpu && osd_ticks() > m_last_periodic_update_time + osd_ticks_per_second() / 4) { // check for periodic updates m_machine.debug_view().update_all(); m_machine.debug_view().flush_osd_updates(); @@ -1191,8 +334,8 @@ void debugger_cpu::start_hook(device_t *device, bool stop_on_vblank) // check for debug keypresses if (m_machine.ui_input().pressed(IPT_UI_DEBUG_BREAK)) { - m_visiblecpu->debug()->ignore(false); - m_visiblecpu->debug()->halt_on_next_instruction("User-initiated break\n"); + visiblecpu->debug()->ignore(false); + visiblecpu->debug()->halt_on_next_instruction("User-initiated break\n"); } } } @@ -1276,7 +419,7 @@ device_debug::device_debug(device_t &device) , m_state(nullptr) , m_disasm(nullptr) , m_flags(0) - , m_symtable(&device.machine().debugger().cpu().global_symtable()) + , m_symtable(std::make_unique(device.machine(), &device.machine().debugger().cpu().global_symtable(), &device)) , m_instrhook(nullptr) , m_stepaddr(0) , m_stepsleft(0) @@ -1289,7 +432,7 @@ device_debug::device_debug(device_t &device) , m_last_total_cycles(0) , m_pc_history_index(0) , m_bplist() - , m_rplist() + , m_rplist(std::make_unique>()) , m_triggered_breakpoint(nullptr) , m_triggered_watchpoint(nullptr) , m_trace(nullptr) @@ -1329,31 +472,31 @@ device_debug::device_debug(device_t &device) // add global symbol for cycles and totalcycles if (m_exec != nullptr) { - m_symtable.add("cycles", [this]() { return m_exec->cycles_remaining(); }); - m_symtable.add("totalcycles", symbol_table::READ_ONLY, &m_total_cycles); - m_symtable.add("lastinstructioncycles", [this]() { return m_total_cycles - m_last_total_cycles; }); + m_symtable->add("cycles", [this]() { return m_exec->cycles_remaining(); }); + m_symtable->add("totalcycles", symbol_table::READ_ONLY, &m_total_cycles); + m_symtable->add("lastinstructioncycles", [this]() { return m_total_cycles - m_last_total_cycles; }); } // add entries to enable/disable unmap reporting for each space if (m_memory != nullptr) { if (m_memory->has_space(AS_PROGRAM)) - m_symtable.add( + m_symtable->add( "logunmap", [&space = m_memory->space(AS_PROGRAM)] () { return space.log_unmap(); }, [&space = m_memory->space(AS_PROGRAM)] (u64 value) { return space.set_log_unmap(bool(value)); }); if (m_memory->has_space(AS_DATA)) - m_symtable.add( + m_symtable->add( "logunmap", [&space = m_memory->space(AS_DATA)] () { return space.log_unmap(); }, [&space = m_memory->space(AS_DATA)] (u64 value) { return space.set_log_unmap(bool(value)); }); if (m_memory->has_space(AS_IO)) - m_symtable.add( + m_symtable->add( "logunmap", [&space = m_memory->space(AS_IO)] () { return space.log_unmap(); }, [&space = m_memory->space(AS_IO)] (u64 value) { return space.set_log_unmap(bool(value)); }); if (m_memory->has_space(AS_OPCODES)) - m_symtable.add( + m_symtable->add( "logunmap", [&space = m_memory->space(AS_OPCODES)] () { return space.log_unmap(); }, [&space = m_memory->space(AS_OPCODES)] (u64 value) { return space.set_log_unmap(bool(value)); }); @@ -1368,7 +511,7 @@ device_debug::device_debug(device_t &device) { using namespace std::placeholders; strmakelower(tempstr.assign(entry->symbol())); - m_symtable.add( + m_symtable->add( tempstr.c_str(), std::bind(&device_state_interface::state_int, m_state, entry->index()), entry->writeable() ? std::bind(&device_state_interface::set_state_int, m_state, entry->index(), _1) : symbol_table::setter_func(nullptr), @@ -1383,8 +526,8 @@ device_debug::device_debug(device_t &device) m_flags = DEBUG_FLAG_OBSERVING | DEBUG_FLAG_HISTORY; // if no curpc, add one - if (m_state && !m_symtable.find("curpc")) - m_symtable.add("curpc", std::bind(&device_state_interface::pcbase, m_state)); + if (m_state && !m_symtable->find("curpc")) + m_symtable->add("curpc", std::bind(&device_state_interface::pcbase, m_state)); } // set up trace @@ -1657,7 +800,7 @@ void device_debug::instruction_hook(offs_t curpc) debugcpu.set_break_cpu(nullptr); // remember the last visible CPU in the debugger - debugcpu.set_visible_cpu(&m_device); + machine.debugger().console().set_visible_cpu(&m_device); // update all views machine.debug_view().update_all(); @@ -1692,10 +835,10 @@ void device_debug::instruction_hook(offs_t curpc) if (machine.scheduled_event_pending()) debugcpu.set_execution_running(); } - m_device.machine().sound().debugger_mute(false); + machine.sound().debugger_mute(false); // remember the last visible CPU in the debugger - debugcpu.set_visible_cpu(&m_device); + machine.debugger().console().set_visible_cpu(&m_device); } // handle step out/over on the instruction we are about to execute @@ -1879,7 +1022,7 @@ void device_debug::go_exception(int exception, const char *condition) m_device.machine().rewind_invalidate(); m_stopexception = exception; - m_exception_condition = std::make_unique(m_symtable, condition); + m_exception_condition = std::make_unique(*m_symtable, condition); m_flags |= DEBUG_FLAG_STOP_EXCEPTION; m_device.machine().debugger().cpu().set_execution_running(); } @@ -1910,7 +1053,7 @@ void device_debug::go_privilege(const char *condition) { assert(m_exec != nullptr); m_device.machine().rewind_invalidate(); - m_privilege_condition = std::make_unique(m_symtable, condition); + m_privilege_condition = std::make_unique(*m_symtable, condition); m_flags |= DEBUG_FLAG_STOP_PRIVILEGE; m_device.machine().debugger().cpu().set_execution_running(); } @@ -1934,11 +1077,11 @@ void device_debug::halt_on_next_instruction_impl(util::format_argument_packsecond.get(); return nullptr; } @@ -1952,11 +1095,11 @@ int device_debug::breakpoint_set(offs_t address, const char *condition, const ch { // allocate a new one and hook it into our list u32 id = m_device.machine().debugger().cpu().get_breakpoint_index(); - m_bplist.emplace_front(this, m_symtable, id, address, condition, action); + m_bplist.emplace(address, std::make_unique(this, *m_symtable, id, address, condition, action)); // update the flags and return the index breakpoint_update_flags(); - return m_bplist.front().m_index; + return id; } @@ -1968,10 +1111,10 @@ int device_debug::breakpoint_set(offs_t address, const char *condition, const ch bool device_debug::breakpoint_clear(int index) { // scan the list to see if we own this breakpoint - for (auto bbp = m_bplist.before_begin(); std::next(bbp) != m_bplist.end(); ++bbp) - if (std::next(bbp)->m_index == index) + for (auto bpit = m_bplist.begin(); bpit != m_bplist.end(); ++bpit) + if (bpit->second->m_index == index) { - m_bplist.erase_after(bbp); + m_bplist.erase(bpit); breakpoint_update_flags(); return true; } @@ -2001,13 +1144,16 @@ void device_debug::breakpoint_clear_all() bool device_debug::breakpoint_enable(int index, bool enable) { // scan the list to see if we own this breakpoint - for (breakpoint &bp : m_bplist) + for (auto &bpp : m_bplist) + { + debug_breakpoint &bp = *bpp.second; if (bp.m_index == index) { bp.m_enabled = enable; breakpoint_update_flags(); return true; } + } // we don't own it, return false return false; @@ -2022,8 +1168,8 @@ bool device_debug::breakpoint_enable(int index, bool enable) void device_debug::breakpoint_enable_all(bool enable) { // apply the enable to all breakpoints we own - for (breakpoint &bp : m_bplist) - breakpoint_enable(bp.index(), enable); + for (auto &bpp : m_bplist) + breakpoint_enable(bpp.second->index(), enable); } @@ -2039,7 +1185,7 @@ int device_debug::watchpoint_set(address_space &space, read_or_write type, offs_ // allocate a new one u32 id = m_device.machine().debugger().cpu().get_watchpoint_index(); - m_wplist[space.spacenum()].emplace_back(std::make_unique(this, m_symtable, id, space, type, address, length, condition, action)); + m_wplist[space.spacenum()].emplace_back(std::make_unique(this, *m_symtable, id, space, type, address, length, condition, action)); return id; } @@ -2123,11 +1269,11 @@ int device_debug::registerpoint_set(const char *condition, const char *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; } @@ -2139,10 +1285,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; } @@ -2159,7 +1305,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(); } @@ -2172,7 +1318,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 (registerpoint &rp : m_rplist) + for (debug_registerpoint &rp : *m_rplist) if (rp.m_index == index) { rp.m_enabled = enable; @@ -2193,7 +1339,7 @@ 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 (registerpoint &rp : m_rplist) + for (debug_registerpoint &rp : *m_rplist) registerpoint_enable(rp.index(), enable); } @@ -2516,8 +1662,8 @@ void device_debug::breakpoint_update_flags() { // see if there are any enabled breakpoints m_flags &= ~DEBUG_FLAG_LIVE_BP; - for (breakpoint &bp : m_bplist) - if (bp.m_enabled) + for (auto &bpp : m_bplist) + if (bpp.second->m_enabled) { m_flags |= DEBUG_FLAG_LIVE_BP; break; @@ -2526,7 +1672,7 @@ void device_debug::breakpoint_update_flags() if ( ! ( m_flags & DEBUG_FLAG_LIVE_BP ) ) { // see if there are any enabled registerpoints - for (registerpoint &rp : m_rplist) + for (debug_registerpoint &rp : *m_rplist) { if (rp.m_enabled) { @@ -2551,7 +1697,10 @@ void device_debug::breakpoint_check(offs_t pc) debugger_cpu& debugcpu = m_device.machine().debugger().cpu(); // see if we match - for (breakpoint &bp : m_bplist) + auto bpitp = m_bplist.equal_range(pc); + for (auto bpit = bpitp.first; bpit != bpitp.second; ++bpit) + { + debug_breakpoint &bp = *bpit->second; if (bp.hit(pc)) { // halt in the debugger by default @@ -2569,9 +1718,10 @@ void device_debug::breakpoint_check(offs_t pc) } break; } + } // see if we have any matching registerpoints - for (registerpoint &rp : m_rplist) + for (debug_registerpoint &rp : *m_rplist) { if (rp.hit()) { @@ -2645,433 +1795,6 @@ void device_debug::hotspot_check(address_space &space, offs_t address) } -//************************************************************************** -// DEBUG BREAKPOINT -//************************************************************************** - -//------------------------------------------------- -// breakpoint - constructor -//------------------------------------------------- - -device_debug::breakpoint::breakpoint(device_debug* debugInterface, - symbol_table &symbols, - int index, - offs_t address, - const char *condition, - const char *action) - : m_debugInterface(debugInterface), - m_index(index), - m_enabled(true), - m_address(address), - m_condition(symbols, (condition != nullptr) ? condition : "1"), - m_action((action != nullptr) ? action : "") -{ -} - - -//------------------------------------------------- -// hit - detect a hit -//------------------------------------------------- - -bool device_debug::breakpoint::hit(offs_t pc) -{ - // don't hit if disabled - if (!m_enabled) - return false; - - // must match our address - if (m_address != pc) - return false; - - // must satisfy the condition - if (!m_condition.is_empty()) - { - try - { - return (m_condition.execute() != 0); - } - catch (expression_error &) - { - return false; - } - } - - return true; -} - - - -//************************************************************************** -// DEBUG WATCHPOINT -//************************************************************************** - -//------------------------------------------------- -// watchpoint - constructor -//------------------------------------------------- - -device_debug::watchpoint::watchpoint(device_debug* debugInterface, - symbol_table &symbols, - int index, - address_space &space, - read_or_write type, - offs_t address, - offs_t length, - const char *condition, - const char *action) - : m_debugInterface(debugInterface), - m_phr(nullptr), - m_phw(nullptr), - m_space(space), - m_index(index), - m_enabled(true), - m_type(type), - m_address(address & space.addrmask()), - m_length(length), - m_condition(symbols, (condition != nullptr) ? condition : "1"), - m_action((action != nullptr) ? action : ""), - m_installing(false) -{ - std::fill(std::begin(m_start_address), std::end(m_start_address), 0); - std::fill(std::begin(m_end_address), std::end(m_end_address), 0); - std::fill(std::begin(m_masks), std::end(m_masks), 0); - - int ashift = m_space.addr_shift(); - endianness_t endian = m_space.endianness(); - offs_t subamask = m_space.alignment() - 1; - offs_t unit_size = ashift <= 0 ? 8 << -ashift : 8 >> ashift; - offs_t start = m_address; - offs_t end = (m_address + m_length - 1) & space.addrmask(); - if (end < start) - end = space.addrmask(); - offs_t rstart = start & ~subamask; - offs_t rend = end | subamask; - u64 smask, mmask, emask; - smask = mmask = emask = make_bitmask(m_space.data_width()); - if (start != rstart) - { - if (endian == ENDIANNESS_LITTLE) - smask &= ~make_bitmask((start - rstart) * unit_size); - else - smask &= make_bitmask((rstart + subamask + 1 - start) * unit_size); - } - if (end != rend) - { - if (endian == ENDIANNESS_LITTLE) - emask &= make_bitmask((subamask + 1 + end - rend) * unit_size); - else - emask &= ~make_bitmask((rend - end) * unit_size); - } - - if (rend == (rstart | subamask) || smask == emask) - { - m_start_address[0] = rstart; - m_end_address[0] = rend; - m_masks[0] = smask & emask; - } - else - { - int idx = 0; - if (smask != mmask) - { - m_start_address[idx] = rstart; - m_end_address[idx] = rstart | subamask; - m_masks[idx] = smask; - idx++; - rstart += subamask + 1; - } - if (mmask == emask) - { - m_start_address[idx] = rstart; - m_end_address[idx] = rend; - m_masks[idx] = emask; - } - else - { - if (rstart < rend - subamask) - { - m_start_address[idx] = rstart; - m_end_address[idx] = rend - subamask - 1; - m_masks[idx] = mmask; - idx++; - } - m_start_address[idx] = rend - subamask; - m_end_address[idx] = rend; - m_masks[idx] = emask; - } - } - - install(read_or_write::READWRITE); - m_notifier = m_space.add_change_notifier([this](read_or_write mode) { - if (m_enabled) - { - install(mode); - } - }); -} - -device_debug::watchpoint::~watchpoint() -{ - m_space.remove_change_notifier(m_notifier); - if (m_phr) - m_phr->remove(); - if (m_phw) - m_phw->remove(); -} - -void device_debug::watchpoint::setEnabled(bool value) -{ - if (m_enabled != value) - { - m_enabled = value; - if (m_enabled) - install(read_or_write::READWRITE); - else - { - m_installing = true; - if(m_phr) - m_phr->remove(); - if(m_phw) - m_phw->remove(); - m_installing = false; - } - } -} - -void device_debug::watchpoint::install(read_or_write mode) -{ - if (m_installing) - return; - m_installing = true; - if ((u32(mode) & u32(read_or_write::READ)) && m_phr) - m_phr->remove(); - if ((u32(mode) & u32(read_or_write::WRITE)) && m_phw) - m_phw->remove(); - std::string name = util::string_format("wp@%x", m_address); - switch (m_space.data_width()) - { - case 8: - if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) - m_phr = m_space.install_read_tap(m_start_address[0], m_end_address[0], name, - [this](offs_t offset, u8 &data, u8 mem_mask) { - triggered(read_or_write::READ, offset, data, mem_mask); - }, m_phr); - if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) - m_phw = m_space.install_write_tap(m_start_address[0], m_end_address[0], name, - [this](offs_t offset, u8 &data, u8 mem_mask) { - triggered(read_or_write::WRITE, offset, data, mem_mask); - }, m_phw); - break; - - case 16: - for (int i=0; i != 3; i++) - if (m_masks[i]) - { - u16 mask = m_masks[i]; - if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) - m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u16 &data, u16 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::READ, offset, data, mem_mask); - }, m_phr); - if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) - m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u16 &data, u16 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::WRITE, offset, data, mem_mask); - }, m_phw); - } - break; - - case 32: - for (int i=0; i != 3; i++) - if (m_masks[i]) - { - u32 mask = m_masks[i]; - if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) - m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u32 &data, u32 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::READ, offset, data, mem_mask); - }, m_phr); - if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) - m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u32 &data, u32 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::WRITE, offset, data, mem_mask); - }, m_phw); - } - break; - - case 64: - for (int i=0; i != 3; i++) - if (m_masks[i]) - { - u64 mask = m_masks[i]; - if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) - m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u64 &data, u64 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::READ, offset, data, mem_mask); - }, m_phr); - if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) - m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u64 &data, u64 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::WRITE, offset, data, mem_mask); - }, m_phw); - } - break; - } - m_installing = false; -} - -void device_debug::watchpoint::triggered(read_or_write type, offs_t address, u64 data, u64 mem_mask) -{ - auto &machine = m_debugInterface->m_device.machine(); - auto &debug = machine.debugger(); - - // if we're within debugger code, don't trigger - if (debug.cpu().within_instruction_hook() || machine.side_effects_disabled()) - return; - - // adjust address, size & value_to_write based on mem_mask. - offs_t size = 0; - int ashift = m_space.addr_shift(); - offs_t unit_size = ashift <= 0 ? 8 << -ashift : 8 >> ashift; - u64 unit_mask = make_bitmask(unit_size); - - offs_t address_offset = 0; - - if(!mem_mask) - mem_mask = 0xff; - - while (!(mem_mask & unit_mask)) - { - address_offset++; - data >>= unit_size; - mem_mask >>= unit_size; - } - - while (mem_mask) - { - size++; - mem_mask >>= unit_size; - } - - data &= make_bitmask(size * unit_size); - - if (m_space.endianness() == ENDIANNESS_LITTLE) - address += address_offset; - else - address += m_space.alignment() - size - address_offset; - - // stash the value that will be written or has just been read - debug.cpu().set_wpinfo(address, data); - - // protect against recursion - debug.cpu().set_within_instruction(true); - - // must satisfy the condition - if (!m_condition.is_empty()) - { - try - { - if (!m_condition.execute()) - { - debug.cpu().set_within_instruction(false); - return; - } - } - catch (expression_error &) - { - debug.cpu().set_within_instruction(false); - return; - } - } - - // halt in the debugger by default - bool was_stopped = debug.cpu().is_stopped(); - debug.cpu().set_execution_stopped(); - - // evaluate the action - if (!m_action.empty()) - debug.console().execute_command(m_action, false); - - // print a notification, unless the action made us go again - if (debug.cpu().is_stopped()) - { - std::string buffer; - - buffer = string_format(type == read_or_write::READ ? - "Stopped at watchpoint %X reading %0*X from %08X" : - "Stopped at watchpoint %X writing %0*X to %08X", - m_index, - size * unit_size / 4, - data, - address); - - if (debug.cpu().live_cpu() == &m_space.device()) - { - offs_t pc = m_space.device().state().pcbase(); - debug.console().printf("%s (PC=%X)\n", buffer, pc); - m_debugInterface->compute_debug_flags(); - } - else if (!was_stopped) - { - debug.console().printf("%s\n", buffer); - debug.cpu().set_execution_running(); - debug.cpu().set_break_cpu(&m_space.device()); - } - m_debugInterface->set_triggered_watchpoint(this); - } - - debug.cpu().set_within_instruction(false); -} - -//************************************************************************** -// DEBUG REGISTERPOINT -//************************************************************************** - -//------------------------------------------------- -// registerpoint - constructor -//------------------------------------------------- - -device_debug::registerpoint::registerpoint(symbol_table &symbols, int index, const char *condition, const char *action) - : m_index(index), - m_enabled(true), - m_condition(symbols, (condition != nullptr) ? condition : "1"), - m_action((action != nullptr) ? action : "") -{ -} - - -//------------------------------------------------- -// hit - detect a hit -//------------------------------------------------- - -bool device_debug::registerpoint::hit() -{ - // don't hit if disabled - if (!m_enabled) - return false; - - // must satisfy the condition - if (!m_condition.is_empty()) - { - try - { - return (m_condition.execute() != 0); - } - catch (expression_error &) - { - return false; - } - } - - return true; -} - - //************************************************************************** // TRACER diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index 36b718c6a16..b21bd72b122 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -13,8 +13,6 @@ #pragma once -#include "express.h" - #include @@ -39,134 +37,13 @@ typedef int (*debug_instruction_hook_func)(device_t &device, offs_t curpc); class device_debug { -public: - // breakpoint class - class breakpoint - { - friend class device_debug; - - public: - // construction/destruction - breakpoint( - device_debug* debugInterface, - symbol_table &symbols, - int index, - offs_t address, - const char *condition = nullptr, - const char *action = nullptr); - - // getters - const device_debug *debugInterface() const { return m_debugInterface; } - int index() const { return m_index; } - 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(); } - - // setters - void setEnabled(bool value) { m_enabled = value; } - - private: - // internals - bool hit(offs_t pc); - const device_debug * m_debugInterface; // the interface we were created from - int m_index; // user reported index - bool m_enabled; // enabled? - offs_t m_address; // execution address - parsed_expression m_condition; // condition - std::string m_action; // action - }; - - // watchpoint class - class watchpoint - { - friend class device_debug; - - public: - // construction/destruction - watchpoint( - device_debug* debugInterface, - symbol_table &symbols, - int index, - address_space &space, - read_or_write type, - offs_t address, - offs_t length, - const char *condition = nullptr, - const char *action = nullptr); - ~watchpoint(); - - // getters - const device_debug *debugInterface() const { return m_debugInterface; } - address_space &space() const { return m_space; } - int index() const { return m_index; } - read_or_write type() const { return m_type; } - bool enabled() const { return m_enabled; } - offs_t address() const { return m_address; } - offs_t length() const { return m_length; } - const char *condition() const { return m_condition.original_string(); } - const std::string &action() const { return m_action; } - - // setters - void setEnabled(bool value); - - // internals - bool hit(int type, offs_t address, int size); - - private: - device_debug * m_debugInterface; // the interface we were created from - memory_passthrough_handler *m_phr; // passthrough handler reference, read access - memory_passthrough_handler *m_phw; // passthrough handler reference, write access - address_space & m_space; // address space - int m_index; // user reported index - bool m_enabled; // enabled? - read_or_write m_type; // type (read/write) - offs_t m_address; // start address - offs_t m_length; // length of watch area - parsed_expression m_condition; // condition - std::string m_action; // action - int m_notifier; // address map change notifier id - - offs_t m_start_address[3]; // the start addresses of the checks to install - offs_t m_end_address[3]; // the end addresses - u64 m_masks[3]; // the access masks - bool m_installing; // prevent recursive multiple installs - void install(read_or_write mode); - void triggered(read_or_write type, offs_t address, u64 data, u64 mem_mask); - }; - - // registerpoint class - class registerpoint - { - friend class device_debug; - - public: - // construction/destruction - registerpoint(symbol_table &symbols, int index, const char *condition, const char *action = nullptr); - - // 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(); } - - private: - // internals - bool hit(); - - int m_index; // user reported index - bool m_enabled; // enabled? - parsed_expression m_condition; // condition - std::string m_action; // action - }; - public: // construction/destruction device_debug(device_t &device); ~device_debug(); // getters - symbol_table &symtable() { return m_symtable; } + symbol_table &symtable() { return *m_symtable; } // commonly-used pass-throughs int logaddrchars() const { return (m_memory != nullptr && m_memory->has_space(AS_PROGRAM)) ? m_memory->space(AS_PROGRAM).logaddrchars() : 8; } @@ -213,28 +90,28 @@ public: } // breakpoints - const std::forward_list &breakpoint_list() const { return m_bplist; } - const breakpoint *breakpoint_find(offs_t address) const; + 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); bool breakpoint_clear(int index); void breakpoint_clear_all(); bool breakpoint_enable(int index, bool enable = true); void breakpoint_enable_all(bool enable = true); - breakpoint *triggered_breakpoint(void) { breakpoint *ret = m_triggered_breakpoint; m_triggered_breakpoint = nullptr; return ret; } + debug_breakpoint *triggered_breakpoint() { debug_breakpoint *ret = m_triggered_breakpoint; m_triggered_breakpoint = nullptr; return ret; } // watchpoints int watchpoint_space_count() const { return m_wplist.size(); } - const std::vector> &watchpoint_vector(int spacenum) const { return m_wplist[spacenum]; } + const std::vector> &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); bool watchpoint_clear(int wpnum); void watchpoint_clear_all(); bool watchpoint_enable(int index, bool enable = true); void watchpoint_enable_all(bool enable = true); - void set_triggered_watchpoint(watchpoint *wp) { m_triggered_watchpoint = wp; } - watchpoint *triggered_watchpoint(void) { watchpoint *ret = m_triggered_watchpoint; m_triggered_watchpoint = nullptr; return ret; } + void set_triggered_watchpoint(debug_watchpoint *wp) { m_triggered_watchpoint = wp; } + debug_watchpoint *triggered_watchpoint() { debug_watchpoint *ret = m_triggered_watchpoint; m_triggered_watchpoint = nullptr; return ret; } // registerpoints - const std::forward_list ®isterpoint_list() const { return m_rplist; } + const std::forward_list ®isterpoint_list() const { return *m_rplist; } int registerpoint_set(const char *condition, const char *action = nullptr); bool registerpoint_clear(int index); void registerpoint_clear_all(); @@ -307,7 +184,7 @@ private: // global state u32 m_flags; // debugging flags for this CPU - symbol_table m_symtable; // symbol table for expression evaluation + std::unique_ptr m_symtable; // symbol table for expression evaluation debug_instruction_hook_func m_instrhook; // per-instruction callback hook // stepping information @@ -330,12 +207,12 @@ private: u32 m_pc_history_index; // current history index // breakpoints and watchpoints - std::forward_list m_bplist; // list of breakpoints - std::vector>> m_wplist; // watchpoint lists for each address space - std::forward_list m_rplist; // list of registerpoints + std::multimap> m_bplist; // list of breakpoints + std::vector>> m_wplist; // watchpoint lists for each address space + std::unique_ptr> m_rplist; // list of registerpoints - breakpoint * m_triggered_breakpoint; // latest breakpoint that was triggered - watchpoint * m_triggered_watchpoint; // latest watchpoint that was triggered + debug_breakpoint * m_triggered_breakpoint; // latest breakpoint that was triggered + debug_watchpoint * m_triggered_watchpoint; // latest watchpoint that was triggered // tracing class tracer @@ -484,14 +361,9 @@ public: /* flushes all traces; this is useful if a trace is going on when we fatalerror */ void flush_traces(); - void configure_memory(symbol_table &table); - /* ----- debugging status & information ----- */ - /* return the visible CPU device (the one that commands should apply to) */ - device_t *get_visible_cpu() { return m_visiblecpu; } - /* return true if the current execution state is stopped */ bool is_stopped() const { return m_execution_state == exec_state::STOPPED; } bool is_running() const { return m_execution_state == exec_state::RUNNING; } @@ -502,9 +374,6 @@ public: /* return the global symbol table */ symbol_table &global_symtable() { return *m_symtable; } - /* return the locally-visible symbol table */ - symbol_table &visible_symtable(); - /* ----- debugger comment helpers ----- */ @@ -515,41 +384,6 @@ public: bool comment_load(bool is_inline); - /* ----- debugger memory accessors ----- */ - - /* return a byte from the specified memory space */ - u8 read_byte(address_space &space, offs_t address, bool apply_translation); - - /* return a word from the specified memory space */ - u16 read_word(address_space &space, offs_t address, bool apply_translation); - - /* return a dword from the specified memory space */ - u32 read_dword(address_space &space, offs_t address, bool apply_translation); - - /* return a qword from the specified memory space */ - u64 read_qword(address_space &space, offs_t address, bool apply_translation); - - /* return 1,2,4 or 8 bytes from the specified memory space */ - u64 read_memory(address_space &space, offs_t address, int size, bool apply_translation); - - /* write a byte to the specified memory space */ - void write_byte(address_space &space, offs_t address, u8 data, bool apply_translation); - - /* write a word to the specified memory space */ - void write_word(address_space &space, offs_t address, u16 data, bool apply_translation); - - /* write a dword to the specified memory space */ - void write_dword(address_space &space, offs_t address, u32 data, bool apply_translation); - - /* write a qword to the specified memory space */ - void write_qword(address_space &space, offs_t address, u64 data, bool apply_translation); - - /* write 1,2,4 or 8 bytes to the specified memory space */ - void write_memory(address_space &space, offs_t address, u64 data, int size, bool apply_translation); - - /* read 1,2,4 or 8 bytes at the given offset from opcode space */ - u64 read_opcode(address_space &space, offs_t offset, int size); - // getters bool within_instruction_hook() const { return m_within_instruction_hook; } bool memory_modified() const { return m_memory_modified; } @@ -560,7 +394,6 @@ public: u32 get_registerpoint_index() { return m_rpindex++; } // setters - void set_visible_cpu(device_t * visiblecpu) { m_visiblecpu = visiblecpu; } void set_break_cpu(device_t * breakcpu) { m_breakcpu = breakcpu; } void set_within_instruction(bool within_instruction) { m_within_instruction_hook = within_instruction; } void set_memory_modified(bool memory_modified) { m_memory_modified = memory_modified; } @@ -581,26 +414,12 @@ public: private: static const size_t NUM_TEMP_VARIABLES; - /* expression handlers */ - u64 expression_read_memory(const char *name, expression_space space, u32 address, int size, bool disable_se); - u64 expression_read_program_direct(address_space &space, int opcode, offs_t address, int size); - u64 expression_read_memory_region(const char *rgntag, offs_t address, int size); - void expression_write_memory(const char *name, expression_space space, u32 address, int size, u64 data, bool disable_se); - void expression_write_program_direct(address_space &space, int opcode, offs_t address, int size, u64 data); - void expression_write_memory_region(const char *rgntag, offs_t address, int size, u64 data); - expression_error::error_code expression_validate(const char *name, expression_space space); - device_t* expression_get_device(const char *tag); - - // variable getters/setters - u64 get_cpunum(); - // internal helpers void on_vblank(screen_device &device, bool vblank_state); running_machine& m_machine; device_t * m_livecpu; - device_t * m_visiblecpu; device_t * m_breakcpu; std::unique_ptr m_symtable; // global symbol table diff --git a/src/emu/debug/dvbpoints.cpp b/src/emu/debug/dvbpoints.cpp index 2ab47b906f2..b4b03f75681 100644 --- a/src/emu/debug/dvbpoints.cpp +++ b/src/emu/debug/dvbpoints.cpp @@ -11,6 +11,7 @@ #include "emu.h" #include "debugger.h" #include "dvbpoints.h" +#include "points.h" #include #include @@ -18,62 +19,62 @@ // Sorting functors for the qsort function -static bool cIndexAscending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cIndexAscending(const debug_breakpoint *a, const debug_breakpoint *b) { return a->index() < b->index(); } -static bool cIndexDescending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cIndexDescending(const debug_breakpoint *a, const debug_breakpoint *b) { return cIndexAscending(b, a); } -static bool cEnabledAscending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cEnabledAscending(const debug_breakpoint *a, const debug_breakpoint *b) { return !a->enabled() && b->enabled(); } -static bool cEnabledDescending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cEnabledDescending(const debug_breakpoint *a, const debug_breakpoint *b) { return cEnabledAscending(b, a); } -static bool cCpuAscending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cCpuAscending(const debug_breakpoint *a, const debug_breakpoint *b) { return strcmp(a->debugInterface()->device().tag(), b->debugInterface()->device().tag()) < 0; } -static bool cCpuDescending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cCpuDescending(const debug_breakpoint *a, const debug_breakpoint *b) { return cCpuAscending(b, a); } -static bool cAddressAscending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cAddressAscending(const debug_breakpoint *a, const debug_breakpoint *b) { return a->address() < b->address(); } -static bool cAddressDescending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cAddressDescending(const debug_breakpoint *a, const debug_breakpoint *b) { return cAddressAscending(b, a); } -static bool cConditionAscending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cConditionAscending(const debug_breakpoint *a, const debug_breakpoint *b) { return strcmp(a->condition(), b->condition()) < 0; } -static bool cConditionDescending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cConditionDescending(const debug_breakpoint *a, const debug_breakpoint *b) { return cConditionAscending(b, a); } -static bool cActionAscending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cActionAscending(const debug_breakpoint *a, const debug_breakpoint *b) { return strcmp(a->action(), b->action()) < 0; } -static bool cActionDescending(const device_debug::breakpoint *a, const device_debug::breakpoint *b) +static bool cActionDescending(const debug_breakpoint *a, const debug_breakpoint *b) { return cActionAscending(b, a); } @@ -169,7 +170,7 @@ void debug_view_breakpoints::view_click(const int button, const debug_view_xy& p return; // Enable / disable - const_cast(*m_buffer[bpIndex]).setEnabled(!m_buffer[bpIndex]->enabled()); + const_cast(*m_buffer[bpIndex]).setEnabled(!m_buffer[bpIndex]->enabled()); machine().debug_view().update_all(DVT_DISASSEMBLY); } @@ -195,8 +196,8 @@ void debug_view_breakpoints::gather_breakpoints() { // Collect device_debug &debugInterface = *source->device()->debug(); - for (const device_debug::breakpoint &bp : debugInterface.breakpoint_list()) - m_buffer.push_back(&bp); + for (const auto &bpp : debugInterface.breakpoint_list()) + m_buffer.push_back(bpp.second.get()); } // And now for the sort @@ -270,7 +271,7 @@ void debug_view_breakpoints::view_update() int bpi = row + m_topleft.y - 1; if ((bpi < m_buffer.size()) && (bpi >= 0)) { - const device_debug::breakpoint *const bp = m_buffer[bpi]; + const debug_breakpoint *const bp = m_buffer[bpi]; linebuf.clear(); linebuf.rdbuf()->clear(); diff --git a/src/emu/debug/dvbpoints.h b/src/emu/debug/dvbpoints.h index 2cba6cd3081..18419434c03 100644 --- a/src/emu/debug/dvbpoints.h +++ b/src/emu/debug/dvbpoints.h @@ -48,8 +48,8 @@ private: // internal state - bool (*m_sortType)(const device_debug::breakpoint *, const device_debug::breakpoint *); - std::vector m_buffer; + bool (*m_sortType)(const debug_breakpoint *, const debug_breakpoint *); + std::vector m_buffer; }; #endif // MAME_EMU_DEBUG_DVBPOINTS_H diff --git a/src/emu/debug/dvdisasm.cpp b/src/emu/debug/dvdisasm.cpp index 95d72e5cda8..385a0c98a65 100644 --- a/src/emu/debug/dvdisasm.cpp +++ b/src/emu/debug/dvdisasm.cpp @@ -360,13 +360,7 @@ void debug_view_disasm::complete_information(const debug_view_disasm_source &sou dasm.m_is_pc = adr == pc; - dasm.m_is_bp = false; - for(const device_debug::breakpoint &bp : source.device()->debug()->breakpoint_list()) - if(adr == (bp.address() & source.m_space.logaddrmask())) { - dasm.m_is_bp = true; - break; - } - + dasm.m_is_bp = source.device()->debug()->breakpoint_find(adr) != nullptr; dasm.m_is_visited = source.device()->debug()->track_pc_visited(adr); const char *comment = source.device()->debug()->comment_text(adr); diff --git a/src/emu/debug/dvmemory.cpp b/src/emu/debug/dvmemory.cpp index e4daaff1a80..eaffcac33b8 100644 --- a/src/emu/debug/dvmemory.cpp +++ b/src/emu/debug/dvmemory.cpp @@ -256,6 +256,118 @@ static inline float u64_to_double(u64 value) return v.f; } +//------------------------------------------------- +// generate_row - read one row of data and make a +// text representation of the chunks +//------------------------------------------------- + +void debug_view_memory::generate_row(debug_view_char *destmin, debug_view_char *destmax, debug_view_char *destrow, offs_t address) +{ + // get positional data + const memory_view_pos &posdata = s_memory_pos_table[m_data_format]; + int spacing = posdata.m_spacing; + + // generate the address + char addrtext[20]; + sprintf(addrtext, m_addrformat.c_str(), address); + debug_view_char *dest = destrow + m_section[0].m_pos + 1; + for (int ch = 0; addrtext[ch] != 0 && ch < m_section[0].m_width - 1; ch++, dest++) + if (dest >= destmin && dest < destmax) + dest->byte = addrtext[ch]; + + // generate the data and the ascii string + std::string chunkascii; + if (m_data_format <= 8) + { + for (int chunknum = 0; chunknum < m_chunks_per_row; chunknum++) + { + u64 chunkdata; + bool ismapped = read_chunk(address, chunknum, chunkdata); + + int chunkindex = m_reverse_view ? (m_chunks_per_row - 1 - chunknum) : chunknum; + dest = destrow + m_section[1].m_pos + 1 + chunkindex * spacing; + for (int ch = 0; ch < spacing; ch++, dest++) + if (dest >= destmin && dest < destmax) + { + u8 shift = posdata.m_shift[ch]; + if (shift < 64) + dest->byte = ismapped ? "0123456789ABCDEF"[(chunkdata >> shift) & 0x0f] : '*'; + } + + for (int i = 0; i < m_bytes_per_chunk; i++) + { + u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1)); + chunkascii += char((ismapped && isprint(chval)) ? chval : '.'); + } + } + } + else + { + for (int chunknum = 0; chunknum < m_chunks_per_row; chunknum++) + { + char valuetext[64]; + u64 chunkdata = 0; + extFloat80_t chunkdata80 = { 0, 0 }; + bool ismapped; + + if (m_data_format != 11) + ismapped = read(m_bytes_per_chunk, address + chunknum * m_steps_per_chunk, chunkdata); + else + ismapped = read(m_bytes_per_chunk, address + chunknum * m_steps_per_chunk, chunkdata80); + + if (ismapped) + switch (m_data_format) + { + case 9: + sprintf(valuetext, "%.8g", u32_to_float(u32(chunkdata))); + break; + case 10: + sprintf(valuetext, "%.24g", u64_to_double(chunkdata)); + break; + case 11: + float64_t f64 = extF80M_to_f64(&chunkdata80); + sprintf(valuetext, "%.24g", u64_to_double(f64.v)); + break; + } + else + { + valuetext[0] = '*'; + valuetext[1] = 0; + } + + int ch; + int chunkindex = m_reverse_view ? (m_chunks_per_row - 1 - chunknum) : chunknum; + dest = destrow + m_section[1].m_pos + 1 + chunkindex * spacing; + // first copy the text + for (ch = 0; (ch < spacing) && (valuetext[ch] != 0); ch++, dest++) + if (dest >= destmin && dest < destmax) + dest->byte = valuetext[ch]; + // then fill with spaces + for (; ch < spacing; ch++, dest++) + if (dest >= destmin && dest < destmax) + dest->byte = ' '; + + for (int i = 0; i < m_bytes_per_chunk; i++) + { + u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1)); + chunkascii += char((ismapped && isprint(chval)) ? chval : '.'); + } + } + } + + // generate the ASCII data, but follow the chunks + if (m_section[2].m_width > 0) + { + dest = destrow + m_section[2].m_pos + 1; + for (size_t i = 0; i != chunkascii.size(); i++) + { + if (dest >= destmin && dest < destmax) + dest->byte = chunkascii[i]; + dest++; + } + } +} + //------------------------------------------------- // view_update - update the contents of the // memory view @@ -269,9 +381,6 @@ void debug_view_memory::view_update() if (needs_recompute()) recompute(); - // get positional data - const memory_view_pos &posdata = s_memory_pos_table[m_data_format]; - // loop over visible rows for (u32 row = 0; row < m_visible.y; row++) { @@ -281,10 +390,9 @@ void debug_view_memory::view_update() u32 effrow = m_topleft.y + row; // reset the line of data; section 1 is normal, others are ancillary, cursor is selected - debug_view_char *dest = destmin; - for (int ch = 0; ch < m_visible.x; ch++, dest++) + u32 effcol = m_topleft.x; + for (debug_view_char *dest = destmin; dest != destmax; dest++, effcol++) { - u32 effcol = m_topleft.x + ch; dest->byte = ' '; dest->attrib = DCA_ANCILLARY; if (m_section[1].contains(effcol)) @@ -300,96 +408,7 @@ void debug_view_memory::view_update() { offs_t addrbyte = m_byte_offset + effrow * m_bytes_per_row; offs_t address = (source.m_space != nullptr) ? source.m_space->byte_to_address(addrbyte) : addrbyte; - char addrtext[20]; - - // generate the address - sprintf(addrtext, m_addrformat.c_str(), address); - dest = destrow + m_section[0].m_pos + 1; - for (int ch = 0; addrtext[ch] != 0 && ch < m_section[0].m_width - 1; ch++, dest++) - if (dest >= destmin && dest < destmax) - dest->byte = addrtext[ch]; - - // generate the data and the ascii string - std::string chunkascii; - for (int chunknum = 0; chunknum < m_chunks_per_row; chunknum++) - { - int chunkindex = m_reverse_view ? (m_chunks_per_row - 1 - chunknum) : chunknum; - int spacing = posdata.m_spacing; - - if (m_data_format <= 8) { - u64 chunkdata; - bool ismapped = read_chunk(address, chunknum, chunkdata); - dest = destrow + m_section[1].m_pos + 1 + chunkindex * spacing; - for (int ch = 0; ch < posdata.m_spacing; ch++, dest++) - if (dest >= destmin && dest < destmax) - { - u8 shift = posdata.m_shift[ch]; - if (shift < 64) - dest->byte = ismapped ? "0123456789ABCDEF"[(chunkdata >> shift) & 0x0f] : '*'; - } - for (int i=0; i < m_bytes_per_chunk; i++) { - u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1)); - chunkascii += char((ismapped && isprint(chval)) ? chval : '.'); - } - } - else { - int ch; - char valuetext[64]; - u64 chunkdata = 0; - extFloat80_t chunkdata80 = { 0, 0 }; - bool ismapped; - - if (m_data_format != 11) - ismapped = read(m_bytes_per_chunk, address + chunknum * m_steps_per_chunk, chunkdata); - else - ismapped = read(m_bytes_per_chunk, address + chunknum * m_steps_per_chunk, chunkdata80); - - if (ismapped) - switch (m_data_format) - { - case 9: - sprintf(valuetext, "%.8g", u32_to_float(u32(chunkdata))); - break; - case 10: - sprintf(valuetext, "%.24g", u64_to_double(chunkdata)); - break; - case 11: - float64_t f64 = extF80M_to_f64(&chunkdata80); - sprintf(valuetext, "%.24g", u64_to_double(f64.v)); - break; - } - else { - valuetext[0] = '*'; - valuetext[1] = 0; - } - - dest = destrow + m_section[1].m_pos + 1 + chunkindex * spacing; - // first copy the text - for (ch = 0; (ch < spacing) && (valuetext[ch] != 0); ch++, dest++) - if (dest >= destmin && dest < destmax) - dest->byte = valuetext[ch]; - // then fill with spaces - for (; ch < spacing; ch++, dest++) - if (dest >= destmin && dest < destmax) - dest->byte = ' '; - - for (int i=0; i < m_bytes_per_chunk; i++) { - u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1)); - chunkascii += char((ismapped && isprint(chval)) ? chval : '.'); - } - } - } - - // generate the ASCII data, but follow the chunks - if (m_section[2].m_width > 0) - { - dest = destrow + m_section[2].m_pos + 1; - for (size_t i = 0; i != chunkascii.size(); i++) { - if (dest >= destmin && dest < destmax) - dest->byte = chunkascii[i]; - dest++; - } - } + generate_row(destmin, destmax, destrow, address); } } } @@ -784,15 +803,7 @@ bool debug_view_memory::read(u8 size, offs_t offs, u64 &data) } data = ~u64(0); if (ismapped) - { - switch (size) - { - case 1: data = machine().debugger().cpu().read_byte(*source.m_space, offs, !m_no_translation); break; - case 2: data = machine().debugger().cpu().read_word(*source.m_space, offs, !m_no_translation); break; - case 4: data = machine().debugger().cpu().read_dword(*source.m_space, offs, !m_no_translation); break; - case 8: data = machine().debugger().cpu().read_qword(*source.m_space, offs, !m_no_translation); break; - } - } + data = m_expression.context().read_memory(*source.m_space, offs, size, !m_no_translation); return ismapped; } @@ -883,14 +894,7 @@ void debug_view_memory::write(u8 size, offs_t offs, u64 data) if (source.m_space) { auto dis = machine().disable_side_effects(); - - switch (size) - { - case 1: machine().debugger().cpu().write_byte(*source.m_space, offs, data, !m_no_translation); break; - case 2: machine().debugger().cpu().write_word(*source.m_space, offs, data, !m_no_translation); break; - case 4: machine().debugger().cpu().write_dword(*source.m_space, offs, data, !m_no_translation); break; - case 8: machine().debugger().cpu().write_qword(*source.m_space, offs, data, !m_no_translation); break; - } + m_expression.context().write_memory(*source.m_space, offs, data, size, !m_no_translation); return; } diff --git a/src/emu/debug/dvmemory.h b/src/emu/debug/dvmemory.h index 05138c2ba0c..8aa5df7cbeb 100644 --- a/src/emu/debug/dvmemory.h +++ b/src/emu/debug/dvmemory.h @@ -104,6 +104,7 @@ private: void write(u8 size, offs_t offs, u64 data); bool read(u8 size, offs_t offs, extFloat80_t &data); bool read_chunk(offs_t address, int chunknum, u64 &chunkdata); + void generate_row(debug_view_char *destmin, debug_view_char *destmax, debug_view_char *destrow, offs_t address); // internal state debug_view_expression m_expression; // expression describing the start address diff --git a/src/emu/debug/dvwpoints.cpp b/src/emu/debug/dvwpoints.cpp index fb713ac58e7..28f2740a2f5 100644 --- a/src/emu/debug/dvwpoints.cpp +++ b/src/emu/debug/dvwpoints.cpp @@ -10,88 +10,89 @@ #include "emu.h" #include "dvwpoints.h" +#include "points.h" #include #include -static bool cIndexAscending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cIndexAscending(const debug_watchpoint *a, const debug_watchpoint *b) { return a->index() < b->index(); } -static bool cIndexDescending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cIndexDescending(const debug_watchpoint *a, const debug_watchpoint *b) { return cIndexAscending(b, a); } -static bool cEnabledAscending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cEnabledAscending(const debug_watchpoint *a, const debug_watchpoint *b) { return !a->enabled() && b->enabled(); } -static bool cEnabledDescending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cEnabledDescending(const debug_watchpoint *a, const debug_watchpoint *b) { return cEnabledAscending(b, a); } -static bool cCpuAscending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cCpuAscending(const debug_watchpoint *a, const debug_watchpoint *b) { return strcmp(a->debugInterface()->device().tag(), b->debugInterface()->device().tag()) < 0; } -static bool cCpuDescending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cCpuDescending(const debug_watchpoint *a, const debug_watchpoint *b) { return cCpuAscending(b, a); } -static bool cSpaceAscending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cSpaceAscending(const debug_watchpoint *a, const debug_watchpoint *b) { return strcmp(a->space().name(), b->space().name()) < 0; } -static bool cSpaceDescending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cSpaceDescending(const debug_watchpoint *a, const debug_watchpoint *b) { return cSpaceAscending(b, a); } -static bool cAddressAscending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cAddressAscending(const debug_watchpoint *a, const debug_watchpoint *b) { return a->address() < b->address(); } -static bool cAddressDescending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cAddressDescending(const debug_watchpoint *a, const debug_watchpoint *b) { return cAddressAscending(b, a); } -static bool cTypeAscending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cTypeAscending(const debug_watchpoint *a, const debug_watchpoint *b) { return int(a->type()) < int(b->type()); } -static bool cTypeDescending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cTypeDescending(const debug_watchpoint *a, const debug_watchpoint *b) { return cTypeAscending(b, a); } -static bool cConditionAscending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cConditionAscending(const debug_watchpoint *a, const debug_watchpoint *b) { return strcmp(a->condition(), b->condition()) < 0; } -static bool cConditionDescending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cConditionDescending(const debug_watchpoint *a, const debug_watchpoint *b) { return cConditionAscending(b, a); } -static bool cActionAscending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cActionAscending(const debug_watchpoint *a, const debug_watchpoint *b) { return a->action() < b->action(); } -static bool cActionDescending(const device_debug::watchpoint *a, const device_debug::watchpoint *b) +static bool cActionDescending(const debug_watchpoint *a, const debug_watchpoint *b) { return cActionAscending(b, a); } @@ -301,7 +302,7 @@ void debug_view_watchpoints::view_update() if ((wpi < m_buffer.size()) && wpi >= 0) { static char const *const types[] = { "unkn ", "read ", "write", "r/w " }; - device_debug::watchpoint *const wp = m_buffer[wpi]; + debug_watchpoint *const wp = m_buffer[wpi]; linebuf.clear(); linebuf.rdbuf()->clear(); diff --git a/src/emu/debug/dvwpoints.h b/src/emu/debug/dvwpoints.h index 26b7c676e0e..753cbe62356 100644 --- a/src/emu/debug/dvwpoints.h +++ b/src/emu/debug/dvwpoints.h @@ -43,8 +43,8 @@ private: // internal state - bool (*m_sortType)(const device_debug::watchpoint *, const device_debug::watchpoint *); - std::vector m_buffer; + bool (*m_sortType)(const debug_watchpoint *, const debug_watchpoint *); + std::vector m_buffer; }; #endif // MAME_EMU_DEBUG_DVWPOINTS_H diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp index bb1f17e05f3..2f5da8d0dea 100644 --- a/src/emu/debug/express.cpp +++ b/src/emu/debug/express.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles /*************************************************************************** - express.c + express.cpp Generic expressions engine. @@ -358,24 +358,23 @@ u64 function_symbol_entry::execute(int numparams, const u64 *paramlist) // symbol_table - constructor //------------------------------------------------- -symbol_table::symbol_table(symbol_table *parent) - : m_parent(parent), - m_memory_valid(nullptr), - m_memory_read(nullptr), - m_memory_write(nullptr) +symbol_table::symbol_table(running_machine &machine, symbol_table *parent, device_t *device) + : m_machine(machine) + , m_parent(parent) + , m_memintf(dynamic_cast(device)) + , m_memory_modified(nullptr) { } //------------------------------------------------- -// add - add a new u64 pointer symbol +// set_memory_modified_func - install notifier +// for when memory is modified in debugger //------------------------------------------------- -void symbol_table::configure_memory(valid_func valid, read_func read, write_func write) +void symbol_table::set_memory_modified_func(memory_modified_func modified) { - m_memory_valid = std::move(valid); - m_memory_read = std::move(read); - m_memory_write = std::move(write); + m_memory_modified = std::move(modified); } @@ -464,6 +463,492 @@ void symbol_table::set_value(const char *symbol, u64 value) } + +//************************************************************************** +// EXPRESSION MEMORY HANDLERS +//************************************************************************** + +//------------------------------------------------- +// read_memory - return 1,2,4 or 8 bytes +// from the specified memory space +//------------------------------------------------- + +u64 symbol_table::read_memory(address_space &space, offs_t address, int size, bool apply_translation) +{ + u64 result = ~u64(0) >> (64 - 8*size); + + if (apply_translation) + { + // mask against the logical byte mask + address &= space.logaddrmask(); + + // translate if necessary; if not mapped, return 0xffffffffffffffff + if (!space.device().memory().translate(space.spacenum(), TRANSLATE_READ_DEBUG, address)) + return result; + } + + // otherwise, call the reading function for the translated address + switch (size) + { + case 1: result = space.read_byte(address); break; + case 2: result = space.read_word_unaligned(address); break; + case 4: result = space.read_dword_unaligned(address); break; + case 8: result = space.read_qword_unaligned(address); break; + } + return result; +} + + +//------------------------------------------------- +// write_memory - write 1,2,4 or 8 bytes to the +// specified memory space +//------------------------------------------------- + +void symbol_table::write_memory(address_space &space, offs_t address, u64 data, int size, bool apply_translation) +{ + if (apply_translation) + { + // mask against the logical byte mask + address &= space.logaddrmask(); + + // translate if necessary; if not mapped, we're done + if (!space.device().memory().translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address)) + return; + } + + // otherwise, call the writing function for the translated address + switch (size) + { + case 1: space.write_byte(address, data); break; + case 2: space.write_word_unaligned(address, data); break; + case 4: space.write_dword_unaligned(address, data); break; + case 8: space.write_qword_unaligned(address, data); break; + } + + notify_memory_modified(); +} + + +//------------------------------------------------- +// expression_get_device - return a device +// based on a case insensitive tag search +//------------------------------------------------- + +device_t *symbol_table::expression_get_device(const char *tag) +{ + // convert to lowercase then lookup the name (tags are enforced to be all lower case) + std::string fullname(tag); + strmakelower(fullname); + return m_machine.root_device().subdevice(fullname.c_str()); +} + + +//------------------------------------------------- +// notify_memory_modified - notify that memory +// has been changed +//------------------------------------------------- + +void symbol_table::notify_memory_modified() +{ + // walk up the table hierarchy to find the owner + for (symbol_table *symtable = this; symtable != nullptr; symtable = symtable->m_parent) + if (symtable->m_memory_modified != nullptr) + m_memory_modified(); +} + + +//------------------------------------------------- +// memory_value - read 1,2,4 or 8 bytes at the +// given offset in the given address space +//------------------------------------------------- + +u64 symbol_table::memory_value(const char *name, expression_space spacenum, u32 address, int size, bool disable_se) +{ + device_memory_interface *memory = m_memintf; + + switch (spacenum) + { + case EXPSPACE_PROGRAM_LOGICAL: + case EXPSPACE_DATA_LOGICAL: + case EXPSPACE_IO_LOGICAL: + case EXPSPACE_SPACE3_LOGICAL: + if (name != nullptr) + { + device_t *device = expression_get_device(name); + if (device != nullptr) + device->interface(memory); + } + if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL))) + { + address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); + auto dis = m_machine.disable_side_effects(disable_se); + return read_memory(space, address, size, true); + } + break; + + case EXPSPACE_PROGRAM_PHYSICAL: + case EXPSPACE_DATA_PHYSICAL: + case EXPSPACE_IO_PHYSICAL: + case EXPSPACE_SPACE3_PHYSICAL: + if (name != nullptr) + { + device_t *device = expression_get_device(name); + if (device != nullptr) + device->interface(memory); + } + if (memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL))) + { + address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); + auto dis = m_machine.disable_side_effects(disable_se); + return read_memory(space, address, size, false); + } + break; + + case EXPSPACE_RAMWRITE: + if (name != nullptr) + { + device_t *device = expression_get_device(name); + if (device != nullptr) + device->interface(memory); + } + if (memory != nullptr && memory->has_space(AS_PROGRAM)) + { + auto dis = m_machine.disable_side_effects(disable_se); + return read_program_direct(memory->space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size); + } + break; + + case EXPSPACE_OPCODE: + if (name != nullptr) + { + device_t *device = expression_get_device(name); + if (device != nullptr) + device->interface(memory); + } + if (memory != nullptr && memory->has_space(AS_OPCODES)) + { + auto dis = m_machine.disable_side_effects(disable_se); + return read_program_direct(memory->space(AS_OPCODES), (spacenum == EXPSPACE_OPCODE), address, size); + } + break; + + case EXPSPACE_REGION: + if (name == nullptr) + break; + return read_memory_region(name, address, size); + + default: + break; + } + + return 0; +} + + +//------------------------------------------------- +// read_program_direct - read memory directly +// from an opcode or RAM pointer +//------------------------------------------------- + +u64 symbol_table::read_program_direct(address_space &space, int opcode, offs_t address, int size) +{ + u8 *base; + + // adjust the address into a byte address, but not if being called recursively + if ((opcode & 2) == 0) + address = space.address_to_byte(address); + + // call ourself recursively until we are byte-sized + if (size > 1) + { + int halfsize = size / 2; + + // read each half, from lower address to upper address + u64 r0 = read_program_direct(space, opcode | 2, address + 0, halfsize); + u64 r1 = read_program_direct(space, opcode | 2, address + halfsize, halfsize); + + // assemble based on the target endianness + if (space.endianness() == ENDIANNESS_LITTLE) + return r0 | (r1 << (8 * halfsize)); + else + return r1 | (r0 << (8 * halfsize)); + } + + // handle the byte-sized final requests + else + { + // lowmask specified which address bits are within the databus width + offs_t lowmask = space.data_width() / 8 - 1; + + // get the base of memory, aligned to the address minus the lowbits + base = (u8 *)space.get_read_ptr(address & ~lowmask); + + // if we have a valid base, return the appropriate byte + if (base != nullptr) + { + if (space.endianness() == ENDIANNESS_LITTLE) + return base[BYTE8_XOR_LE(address) & lowmask]; + else + return base[BYTE8_XOR_BE(address) & lowmask]; + } + } + + return 0; +} + + +//------------------------------------------------- +// read_memory_region - read memory from a +// memory region +//------------------------------------------------- + +u64 symbol_table::read_memory_region(const char *rgntag, offs_t address, int size) +{ + memory_region *region = m_machine.root_device().memregion(rgntag); + u64 result = ~u64(0) >> (64 - 8*size); + + // make sure we get a valid base before proceeding + if (region != nullptr) + { + // call ourself recursively until we are byte-sized + if (size > 1) + { + int halfsize = size / 2; + u64 r0, r1; + + // read each half, from lower address to upper address + r0 = read_memory_region(rgntag, address + 0, halfsize); + r1 = read_memory_region(rgntag, address + halfsize, halfsize); + + // assemble based on the target endianness + if (region->endianness() == ENDIANNESS_LITTLE) + result = r0 | (r1 << (8 * halfsize)); + else + result = r1 | (r0 << (8 * halfsize)); + } + + // only process if we're within range + else if (address < region->bytes()) + { + // lowmask specified which address bits are within the databus width + u32 lowmask = region->bytewidth() - 1; + u8 *base = region->base() + (address & ~lowmask); + + // if we have a valid base, return the appropriate byte + if (region->endianness() == ENDIANNESS_LITTLE) + result = base[BYTE8_XOR_LE(address) & lowmask]; + else + result = base[BYTE8_XOR_BE(address) & lowmask]; + } + } + return result; +} + + +//------------------------------------------------- +// set_memory_value - write 1,2,4 or 8 bytes at +// the given offset in the given address space +//------------------------------------------------- + +void symbol_table::set_memory_value(const char *name, expression_space spacenum, u32 address, int size, u64 data, bool disable_se) +{ + device_memory_interface *memory = m_memintf; + + switch (spacenum) + { + case EXPSPACE_PROGRAM_LOGICAL: + case EXPSPACE_DATA_LOGICAL: + case EXPSPACE_IO_LOGICAL: + case EXPSPACE_SPACE3_LOGICAL: + if (name != nullptr) + { + device_t *device = expression_get_device(name); + if (device != nullptr) + device->interface(memory); + } + if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL))) + { + address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); + auto dis = m_machine.disable_side_effects(disable_se); + write_memory(space, address, data, size, true); + } + break; + + case EXPSPACE_PROGRAM_PHYSICAL: + case EXPSPACE_DATA_PHYSICAL: + case EXPSPACE_IO_PHYSICAL: + case EXPSPACE_SPACE3_PHYSICAL: + if (name != nullptr) + { + device_t *device = expression_get_device(name); + if (device != nullptr) + device->interface(memory); + } + if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL))) + { + address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); + auto dis = m_machine.disable_side_effects(disable_se); + write_memory(space, address, data, size, false); + } + break; + + case EXPSPACE_RAMWRITE: { + if (name != nullptr) + { + device_t *device = expression_get_device(name); + if (device != nullptr) + device->interface(memory); + } + if (memory != nullptr && memory->has_space(AS_PROGRAM)) + { + auto dis = m_machine.disable_side_effects(disable_se); + write_program_direct(memory->space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size, data); + } + break; + } + + case EXPSPACE_OPCODE: { + if (name != nullptr) + { + device_t *device = expression_get_device(name); + if (device != nullptr) + device->interface(memory); + } + if (memory != nullptr && memory->has_space(AS_OPCODES)) + { + auto dis = m_machine.disable_side_effects(disable_se); + write_program_direct(memory->space(AS_OPCODES), (spacenum == EXPSPACE_OPCODE), address, size, data); + } + break; + } + + case EXPSPACE_REGION: + if (name == nullptr) + break; + write_memory_region(name, address, size, data); + break; + + default: + break; + } +} + + +//------------------------------------------------- +// write_program_direct - write memory directly +// to an opcode or RAM pointer +//------------------------------------------------- + +void symbol_table::write_program_direct(address_space &space, int opcode, offs_t address, int size, u64 data) +{ + // adjust the address into a byte address, but not if being called recursively + if ((opcode & 2) == 0) + address = space.address_to_byte(address); + + // call ourself recursively until we are byte-sized + if (size > 1) + { + int halfsize = size / 2; + + // break apart based on the target endianness + u64 halfmask = ~u64(0) >> (64 - 8 * halfsize); + u64 r0, r1; + if (space.endianness() == ENDIANNESS_LITTLE) + { + r0 = data & halfmask; + r1 = (data >> (8 * halfsize)) & halfmask; + } + else + { + r0 = (data >> (8 * halfsize)) & halfmask; + r1 = data & halfmask; + } + + // write each half, from lower address to upper address + write_program_direct(space, opcode | 2, address + 0, halfsize, r0); + write_program_direct(space, opcode | 2, address + halfsize, halfsize, r1); + } + + // handle the byte-sized final case + else + { + // lowmask specified which address bits are within the databus width + offs_t lowmask = space.data_width() / 8 - 1; + + // get the base of memory, aligned to the address minus the lowbits + u8 *base = (u8 *)space.get_read_ptr(address & ~lowmask); + + // if we have a valid base, write the appropriate byte + if (base != nullptr) + { + if (space.endianness() == ENDIANNESS_LITTLE) + base[BYTE8_XOR_LE(address) & lowmask] = data; + else + base[BYTE8_XOR_BE(address) & lowmask] = data; + notify_memory_modified(); + } + } +} + + +//------------------------------------------------- +// write_memory_region - write memory to a +// memory region +//------------------------------------------------- + +void symbol_table::write_memory_region(const char *rgntag, offs_t address, int size, u64 data) +{ + memory_region *region = m_machine.root_device().memregion(rgntag); + + // make sure we get a valid base before proceeding + if (region != nullptr) + { + // call ourself recursively until we are byte-sized + if (size > 1) + { + int halfsize = size / 2; + + // break apart based on the target endianness + u64 halfmask = ~u64(0) >> (64 - 8 * halfsize); + u64 r0, r1; + if (region->endianness() == ENDIANNESS_LITTLE) + { + r0 = data & halfmask; + r1 = (data >> (8 * halfsize)) & halfmask; + } + else + { + r0 = (data >> (8 * halfsize)) & halfmask; + r1 = data & halfmask; + } + + // write each half, from lower address to upper address + write_memory_region(rgntag, address + 0, halfsize, r0); + write_memory_region(rgntag, address + halfsize, halfsize, r1); + } + + // only process if we're within range + else if (address < region->bytes()) + { + // lowmask specified which address bits are within the databus width + u32 lowmask = region->bytewidth() - 1; + u8 *base = region->base() + (address & ~lowmask); + + // if we have a valid base, set the appropriate byte + if (region->endianness() == ENDIANNESS_LITTLE) + { + base[BYTE8_XOR_LE(address) & lowmask] = data; + } + else + { + base[BYTE8_XOR_BE(address) & lowmask] = data; + } + notify_memory_modified(); + } + } +} + + //------------------------------------------------- // memory_valid - return true if the given // memory name/space/offset combination is valid @@ -471,52 +956,87 @@ void symbol_table::set_value(const char *symbol, u64 value) expression_error::error_code symbol_table::memory_valid(const char *name, expression_space space) { - // walk up the table hierarchy to find the owner - for (symbol_table *symtable = this; symtable != nullptr; symtable = symtable->m_parent) - if (symtable->m_memory_valid != nullptr) + device_memory_interface *memory = m_memintf; + + switch (space) + { + case EXPSPACE_PROGRAM_LOGICAL: + case EXPSPACE_DATA_LOGICAL: + case EXPSPACE_IO_LOGICAL: + case EXPSPACE_SPACE3_LOGICAL: + if (name != nullptr) { - expression_error::error_code err = symtable->m_memory_valid(name, space); - if (err != expression_error::NO_SUCH_MEMORY_SPACE) - return err; + device_t *device = expression_get_device(name); + if (device == nullptr) + return expression_error::INVALID_MEMORY_NAME; + if (!device->interface(memory)) + return expression_error::NO_SUCH_MEMORY_SPACE; } - return expression_error::NO_SUCH_MEMORY_SPACE; -} + else if (memory == nullptr) + return expression_error::MISSING_MEMORY_NAME; + if (!memory->has_space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_LOGICAL))) + return expression_error::NO_SUCH_MEMORY_SPACE; + break; - -//------------------------------------------------- -// memory_value - return a value read from memory -//------------------------------------------------- - -u64 symbol_table::memory_value(const char *name, expression_space space, u32 offset, int size, bool disable_se) -{ - // walk up the table hierarchy to find the owner - for (symbol_table *symtable = this; symtable != nullptr; symtable = symtable->m_parent) - if (symtable->m_memory_valid != nullptr) + case EXPSPACE_PROGRAM_PHYSICAL: + case EXPSPACE_DATA_PHYSICAL: + case EXPSPACE_IO_PHYSICAL: + case EXPSPACE_SPACE3_PHYSICAL: + if (name) { - expression_error::error_code err = symtable->m_memory_valid(name, space); - if (err != expression_error::NO_SUCH_MEMORY_SPACE && symtable->m_memory_read != nullptr) - return symtable->m_memory_read(name, space, offset, size, disable_se); - return 0; + device_t *device = expression_get_device(name); + if (device == nullptr) + return expression_error::INVALID_MEMORY_NAME; + if (!device->interface(memory)) + return expression_error::NO_SUCH_MEMORY_SPACE; } - return 0; -} + else if (memory == nullptr) + return expression_error::MISSING_MEMORY_NAME; + if (!memory->has_space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_PHYSICAL))) + return expression_error::NO_SUCH_MEMORY_SPACE; + break; - -//------------------------------------------------- -// set_memory_value - write a value to memory -//------------------------------------------------- - -void symbol_table::set_memory_value(const char *name, expression_space space, u32 offset, int size, u64 value, bool disable_se) -{ - // walk up the table hierarchy to find the owner - for (symbol_table *symtable = this; symtable != nullptr; symtable = symtable->m_parent) - if (symtable->m_memory_valid != nullptr) + case EXPSPACE_RAMWRITE: + if (name) { - expression_error::error_code err = symtable->m_memory_valid(name, space); - if (err != expression_error::NO_SUCH_MEMORY_SPACE && symtable->m_memory_write != nullptr) - symtable->m_memory_write(name, space, offset, size, value, disable_se); - return; + device_t *device = expression_get_device(name); + if (device == nullptr) + return expression_error::INVALID_MEMORY_NAME; + if (!device->interface(memory)) + return expression_error::NO_SUCH_MEMORY_SPACE; } + else if (memory == nullptr) + return expression_error::MISSING_MEMORY_NAME; + if (!memory->has_space(AS_PROGRAM)) + return expression_error::NO_SUCH_MEMORY_SPACE; + break; + + case EXPSPACE_OPCODE: + if (name) + { + device_t *device = expression_get_device(name); + if (device == nullptr) + return expression_error::INVALID_MEMORY_NAME; + if (!device->interface(memory)) + return expression_error::NO_SUCH_MEMORY_SPACE; + } + else if (memory == nullptr) + return expression_error::MISSING_MEMORY_NAME; + if (!memory->has_space(AS_OPCODES)) + return expression_error::NO_SUCH_MEMORY_SPACE; + break; + + case EXPSPACE_REGION: + if (!name) + return expression_error::MISSING_MEMORY_NAME; + if (!m_machine.root_device().memregion(name) || !m_machine.root_device().memregion(name)->base()) + return expression_error::INVALID_MEMORY_NAME; + break; + + default: + return expression_error::NO_SUCH_MEMORY_SPACE; + } + return expression_error::NONE; } diff --git a/src/emu/debug/express.h b/src/emu/debug/express.h index 6b3ac6afa84..1caee590d5a 100644 --- a/src/emu/debug/express.h +++ b/src/emu/debug/express.h @@ -49,6 +49,8 @@ enum expression_space // TYPE DEFINITIONS //************************************************************************** +using offs_t = u32; + // ======================> expression_error // an expression_error holds an error code and a string offset @@ -154,9 +156,7 @@ public: typedef std::function execute_func; // callback functions for memory reads/writes - typedef std::function valid_func; - typedef std::function read_func; - typedef std::function write_func; + typedef std::function memory_modified_func; enum read_write { @@ -165,14 +165,14 @@ public: }; // construction/destruction - symbol_table(symbol_table *parent = nullptr); + symbol_table(running_machine &machine, symbol_table *parent = nullptr, device_t *device = nullptr); // getters const std::unordered_map> &entries() const { return m_symlist; } symbol_table *parent() const { return m_parent; } // setters - void configure_memory(valid_func valid, read_func read, write_func write); + void set_memory_modified_func(memory_modified_func modified); // symbol access void add(const char *name, read_write rw, u64 *ptr = nullptr); @@ -190,14 +190,24 @@ public: expression_error::error_code memory_valid(const char *name, expression_space space); u64 memory_value(const char *name, expression_space space, u32 offset, int size, bool disable_se); void set_memory_value(const char *name, expression_space space, u32 offset, int size, u64 value, bool disable_se); + u64 read_memory(address_space &space, offs_t address, int size, bool apply_translation); + void write_memory(address_space &space, offs_t address, u64 data, int size, bool apply_translation); private: + // memory helpers + u64 read_program_direct(address_space &space, int opcode, offs_t address, int size); + u64 read_memory_region(const char *rgntag, offs_t address, int size); + void write_program_direct(address_space &space, int opcode, offs_t address, int size, u64 data); + void write_memory_region(const char *rgntag, offs_t address, int size, u64 data); + device_t *expression_get_device(const char *tag); + void notify_memory_modified(); + // internal state + running_machine & m_machine; // reference to the machine symbol_table * m_parent; // pointer to the parent symbol table std::unordered_map> m_symlist; // list of symbols - valid_func m_memory_valid; // validation callback - read_func m_memory_read; // read callback - write_func m_memory_write; // write callback + device_memory_interface *const m_memintf; // pointer to the local memory interface (if any) + memory_modified_func m_memory_modified; // memory modified callback }; diff --git a/src/emu/debug/points.cpp b/src/emu/debug/points.cpp new file mode 100644 index 00000000000..1cde2bbf486 --- /dev/null +++ b/src/emu/debug/points.cpp @@ -0,0 +1,441 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +/*************************************************************************** + + points.cpp + + Debugger breakpoints, watchpoints, etc. + +***************************************************************************/ + +#include "emu.h" +#include "points.h" +#include "debugger.h" +#include "debugcon.h" + + +//************************************************************************** +// DEBUG BREAKPOINT +//************************************************************************** + +//------------------------------------------------- +// debug_breakpoint - constructor +//------------------------------------------------- + +debug_breakpoint::debug_breakpoint(device_debug* debugInterface, + symbol_table &symbols, + int index, + offs_t address, + const char *condition, + const char *action) + : m_debugInterface(debugInterface), + m_index(index), + m_enabled(true), + m_address(address), + m_condition(symbols, (condition != nullptr) ? condition : "1"), + m_action((action != nullptr) ? action : "") +{ +} + + +//------------------------------------------------- +// hit - detect a hit +//------------------------------------------------- + +bool debug_breakpoint::hit(offs_t pc) +{ + // don't hit if disabled + if (!m_enabled) + return false; + + // must match our address + if (m_address != pc) + return false; + + // must satisfy the condition + if (!m_condition.is_empty()) + { + try + { + return (m_condition.execute() != 0); + } + catch (expression_error &) + { + return false; + } + } + + return true; +} + + + +//************************************************************************** +// DEBUG WATCHPOINT +//************************************************************************** + +//------------------------------------------------- +// debug_watchpoint - constructor +//------------------------------------------------- + +debug_watchpoint::debug_watchpoint(device_debug* debugInterface, + symbol_table &symbols, + int index, + address_space &space, + read_or_write type, + offs_t address, + offs_t length, + const char *condition, + const char *action) + : m_debugInterface(debugInterface), + m_phr(nullptr), + m_phw(nullptr), + m_space(space), + m_index(index), + m_enabled(true), + m_type(type), + m_address(address & space.addrmask()), + m_length(length), + m_condition(symbols, (condition != nullptr) ? condition : "1"), + m_action((action != nullptr) ? action : ""), + m_installing(false) +{ + std::fill(std::begin(m_start_address), std::end(m_start_address), 0); + std::fill(std::begin(m_end_address), std::end(m_end_address), 0); + std::fill(std::begin(m_masks), std::end(m_masks), 0); + + int ashift = m_space.addr_shift(); + endianness_t endian = m_space.endianness(); + offs_t subamask = m_space.alignment() - 1; + offs_t unit_size = ashift <= 0 ? 8 << -ashift : 8 >> ashift; + offs_t start = m_address; + offs_t end = (m_address + m_length - 1) & space.addrmask(); + if (end < start) + end = space.addrmask(); + offs_t rstart = start & ~subamask; + offs_t rend = end | subamask; + u64 smask, mmask, emask; + smask = mmask = emask = make_bitmask(m_space.data_width()); + if (start != rstart) + { + if (endian == ENDIANNESS_LITTLE) + smask &= ~make_bitmask((start - rstart) * unit_size); + else + smask &= make_bitmask((rstart + subamask + 1 - start) * unit_size); + } + if (end != rend) + { + if (endian == ENDIANNESS_LITTLE) + emask &= make_bitmask((subamask + 1 + end - rend) * unit_size); + else + emask &= ~make_bitmask((rend - end) * unit_size); + } + + if (rend == (rstart | subamask) || smask == emask) + { + m_start_address[0] = rstart; + m_end_address[0] = rend; + m_masks[0] = smask & emask; + } + else + { + int idx = 0; + if (smask != mmask) + { + m_start_address[idx] = rstart; + m_end_address[idx] = rstart | subamask; + m_masks[idx] = smask; + idx++; + rstart += subamask + 1; + } + if (mmask == emask) + { + m_start_address[idx] = rstart; + m_end_address[idx] = rend; + m_masks[idx] = emask; + } + else + { + if (rstart < rend - subamask) + { + m_start_address[idx] = rstart; + m_end_address[idx] = rend - subamask - 1; + m_masks[idx] = mmask; + idx++; + } + m_start_address[idx] = rend - subamask; + m_end_address[idx] = rend; + m_masks[idx] = emask; + } + } + + install(read_or_write::READWRITE); + m_notifier = m_space.add_change_notifier([this](read_or_write mode) { + if (m_enabled) + { + install(mode); + } + }); +} + +debug_watchpoint::~debug_watchpoint() +{ + m_space.remove_change_notifier(m_notifier); + if (m_phr) + m_phr->remove(); + if (m_phw) + m_phw->remove(); +} + +void debug_watchpoint::setEnabled(bool value) +{ + if (m_enabled != value) + { + m_enabled = value; + if (m_enabled) + install(read_or_write::READWRITE); + else + { + m_installing = true; + if(m_phr) + m_phr->remove(); + if(m_phw) + m_phw->remove(); + m_installing = false; + } + } +} + +void debug_watchpoint::install(read_or_write mode) +{ + if (m_installing) + return; + m_installing = true; + if ((u32(mode) & u32(read_or_write::READ)) && m_phr) + m_phr->remove(); + if ((u32(mode) & u32(read_or_write::WRITE)) && m_phw) + m_phw->remove(); + std::string name = util::string_format("wp@%x", m_address); + switch (m_space.data_width()) + { + case 8: + if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) + m_phr = m_space.install_read_tap(m_start_address[0], m_end_address[0], name, + [this](offs_t offset, u8 &data, u8 mem_mask) { + triggered(read_or_write::READ, offset, data, mem_mask); + }, m_phr); + if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) + m_phw = m_space.install_write_tap(m_start_address[0], m_end_address[0], name, + [this](offs_t offset, u8 &data, u8 mem_mask) { + triggered(read_or_write::WRITE, offset, data, mem_mask); + }, m_phw); + break; + + case 16: + for (int i=0; i != 3; i++) + if (m_masks[i]) + { + u16 mask = m_masks[i]; + if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) + m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u16 &data, u16 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::READ, offset, data, mem_mask); + }, m_phr); + if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) + m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u16 &data, u16 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::WRITE, offset, data, mem_mask); + }, m_phw); + } + break; + + case 32: + for (int i=0; i != 3; i++) + if (m_masks[i]) + { + u32 mask = m_masks[i]; + if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) + m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u32 &data, u32 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::READ, offset, data, mem_mask); + }, m_phr); + if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) + m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u32 &data, u32 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::WRITE, offset, data, mem_mask); + }, m_phw); + } + break; + + case 64: + for (int i=0; i != 3; i++) + if (m_masks[i]) + { + u64 mask = m_masks[i]; + if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) + m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u64 &data, u64 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::READ, offset, data, mem_mask); + }, m_phr); + if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) + m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u64 &data, u64 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::WRITE, offset, data, mem_mask); + }, m_phw); + } + break; + } + m_installing = false; +} + +void debug_watchpoint::triggered(read_or_write type, offs_t address, u64 data, u64 mem_mask) +{ + running_machine &machine = m_debugInterface->device().machine(); + debugger_manager &debug = machine.debugger(); + + // if we're within debugger code, don't trigger + if (debug.cpu().within_instruction_hook() || machine.side_effects_disabled()) + return; + + // adjust address, size & value_to_write based on mem_mask. + offs_t size = 0; + int ashift = m_space.addr_shift(); + offs_t unit_size = ashift <= 0 ? 8 << -ashift : 8 >> ashift; + u64 unit_mask = make_bitmask(unit_size); + + offs_t address_offset = 0; + + if(!mem_mask) + mem_mask = 0xff; + + while (!(mem_mask & unit_mask)) + { + address_offset++; + data >>= unit_size; + mem_mask >>= unit_size; + } + + while (mem_mask) + { + size++; + mem_mask >>= unit_size; + } + + data &= make_bitmask(size * unit_size); + + if (m_space.endianness() == ENDIANNESS_LITTLE) + address += address_offset; + else + address += m_space.alignment() - size - address_offset; + + // stash the value that will be written or has just been read + debug.cpu().set_wpinfo(address, data); + + // protect against recursion + debug.cpu().set_within_instruction(true); + + // must satisfy the condition + if (!m_condition.is_empty()) + { + try + { + if (!m_condition.execute()) + { + debug.cpu().set_within_instruction(false); + return; + } + } + catch (expression_error &) + { + debug.cpu().set_within_instruction(false); + return; + } + } + + // halt in the debugger by default + bool was_stopped = debug.cpu().is_stopped(); + debug.cpu().set_execution_stopped(); + + // evaluate the action + if (!m_action.empty()) + debug.console().execute_command(m_action, false); + + // print a notification, unless the action made us go again + if (debug.cpu().is_stopped()) + { + std::string buffer; + + buffer = string_format(type == read_or_write::READ ? + "Stopped at watchpoint %X reading %0*X from %08X" : + "Stopped at watchpoint %X writing %0*X to %08X", + m_index, + size * unit_size / 4, + data, + address); + + if (debug.cpu().live_cpu() == &m_space.device()) + { + offs_t pc = m_space.device().state().pcbase(); + debug.console().printf("%s (PC=%X)\n", buffer, pc); + m_debugInterface->compute_debug_flags(); + } + else if (!was_stopped) + { + debug.console().printf("%s\n", buffer); + debug.cpu().set_execution_running(); + debug.cpu().set_break_cpu(&m_space.device()); + } + m_debugInterface->set_triggered_watchpoint(this); + } + + debug.cpu().set_within_instruction(false); +} + +//************************************************************************** +// DEBUG REGISTERPOINT +//************************************************************************** + +//------------------------------------------------- +// debug_registerpoint - constructor +//------------------------------------------------- + +debug_registerpoint::debug_registerpoint(symbol_table &symbols, int index, const char *condition, const char *action) + : m_index(index), + m_enabled(true), + m_condition(symbols, (condition != nullptr) ? condition : "1"), + m_action((action != nullptr) ? action : "") +{ +} + + +//------------------------------------------------- +// hit - detect a hit +//------------------------------------------------- + +bool debug_registerpoint::hit() +{ + // don't hit if disabled + if (!m_enabled) + return false; + + // must satisfy the condition + if (!m_condition.is_empty()) + { + try + { + return (m_condition.execute() != 0); + } + catch (expression_error &) + { + return false; + } + } + + return true; +} diff --git a/src/emu/debug/points.h b/src/emu/debug/points.h new file mode 100644 index 00000000000..220b75728ce --- /dev/null +++ b/src/emu/debug/points.h @@ -0,0 +1,149 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +/*************************************************************************** + + points.h + + Debugger breakpoints, watchpoints, etc. + +***************************************************************************/ + +#ifndef MAME_EMU_DEBUG_POINTS_H +#define MAME_EMU_DEBUG_POINTS_H + +#pragma once + +#include "debugcpu.h" +#include "express.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +// ======================> debug_breakpoint + +class debug_breakpoint +{ + friend class device_debug; + +public: + // construction/destruction + debug_breakpoint( + device_debug* debugInterface, + symbol_table &symbols, + int index, + offs_t address, + const char *condition = nullptr, + const char *action = nullptr); + + // getters + const device_debug *debugInterface() const { return m_debugInterface; } + int index() const { return m_index; } + 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(); } + + // setters + void setEnabled(bool value) { m_enabled = value; } + +private: + // internals + bool hit(offs_t pc); + const device_debug * m_debugInterface; // the interface we were created from + int m_index; // user reported index + bool m_enabled; // enabled? + offs_t m_address; // execution address + parsed_expression m_condition; // condition + std::string m_action; // action +}; + +// ======================> debug_watchpoint + +class debug_watchpoint +{ + friend class device_debug; + +public: + // construction/destruction + debug_watchpoint( + device_debug* debugInterface, + symbol_table &symbols, + int index, + address_space &space, + read_or_write type, + offs_t address, + offs_t length, + const char *condition = nullptr, + const char *action = nullptr); + ~debug_watchpoint(); + + // getters + const device_debug *debugInterface() const { return m_debugInterface; } + address_space &space() const { return m_space; } + int index() const { return m_index; } + read_or_write type() const { return m_type; } + bool enabled() const { return m_enabled; } + offs_t address() const { return m_address; } + offs_t length() const { return m_length; } + const char *condition() const { return m_condition.original_string(); } + const std::string &action() const { return m_action; } + + // setters + void setEnabled(bool value); + + // internals + bool hit(int type, offs_t address, int size); + +private: + void install(read_or_write mode); + void triggered(read_or_write type, offs_t address, u64 data, u64 mem_mask); + + device_debug * m_debugInterface; // the interface we were created from + memory_passthrough_handler *m_phr; // passthrough handler reference, read access + memory_passthrough_handler *m_phw; // passthrough handler reference, write access + address_space & m_space; // address space + int m_index; // user reported index + bool m_enabled; // enabled? + read_or_write m_type; // type (read/write) + offs_t m_address; // start address + offs_t m_length; // length of watch area + parsed_expression m_condition; // condition + std::string m_action; // action + int m_notifier; // address map change notifier id + + offs_t m_start_address[3]; // the start addresses of the checks to install + offs_t m_end_address[3]; // the end addresses + u64 m_masks[3]; // the access masks + bool m_installing; // prevent recursive multiple installs +}; + +// ======================> debug_registerpoint + +class debug_registerpoint +{ + friend class device_debug; + +public: + // construction/destruction + debug_registerpoint(symbol_table &symbols, int index, const char *condition, const char *action = nullptr); + + // 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(); } + +private: + // internals + bool hit(); + + int m_index; // user reported index + bool m_enabled; // enabled? + parsed_expression m_condition; // condition + std::string m_action; // action +}; + +#endif // MAME_EMU_DEBUG_POINTS_H diff --git a/src/emu/debugger.cpp b/src/emu/debugger.cpp index f3a35a2a0bb..5e866057d61 100644 --- a/src/emu/debugger.cpp +++ b/src/emu/debugger.cpp @@ -31,7 +31,7 @@ static bool g_atexit_registered = false; void debugger_manager::debug_break() { - m_cpu->get_visible_cpu()->debug()->halt_on_next_instruction("Internal breakpoint\n"); + m_console->get_visible_cpu()->debug()->halt_on_next_instruction("Internal breakpoint\n"); } diff --git a/src/emu/emufwd.h b/src/emu/emufwd.h index 275d1fecedd..bd7d2235a15 100644 --- a/src/emu/emufwd.h +++ b/src/emu/emufwd.h @@ -96,6 +96,11 @@ class debug_view_manager; class parsed_expression; class symbol_table; +// declared in debug/points.h +class debug_breakpoint; +class debug_watchpoint; +class debug_registerpoint; + // declared in debugger.h class debugger_manager; diff --git a/src/frontend/mame/cheat.cpp b/src/frontend/mame/cheat.cpp index 00f8c9d67fd..daf6461b0f4 100644 --- a/src/frontend/mame/cheat.cpp +++ b/src/frontend/mame/cheat.cpp @@ -79,9 +79,7 @@ #include "ui/ui.h" #include "ui/menu.h" -#include "debugger.h" #include "emuopts.h" -#include "debug/debugcpu.h" #include #include @@ -679,7 +677,7 @@ void cheat_script::script_entry::output_argument::save(emu_file &cheatfile) cons cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, std::string const &filename, util::xml::data_node const &cheatnode) : m_manager(manager) - , m_symbols(&globaltable) + , m_symbols(manager.machine(), &globaltable) , m_state(SCRIPT_STATE_OFF) , m_numtemp(DEFAULT_TEMP_VARIABLES) , m_argindex(0) @@ -1058,7 +1056,7 @@ constexpr int cheat_manager::CHEAT_VERSION; cheat_manager::cheat_manager(running_machine &machine) : m_machine(machine) , m_disabled(true) - , m_symtable() + , m_symtable(machine) { // if the cheat engine is disabled, we're done if (!machine.options().cheat()) @@ -1081,19 +1079,6 @@ cheat_manager::cheat_manager(running_machine &machine) m_symtable.add("frombcd", 1, 1, execute_frombcd); m_symtable.add("tobcd", 1, 1, execute_tobcd); - // we rely on the debugger expression callbacks; if the debugger isn't - // enabled, we must jumpstart them manually - if ((machine.debug_flags & DEBUG_FLAG_ENABLED) == 0) - { - m_cpu = std::make_unique(machine); - m_cpu->configure_memory(m_symtable); - } - else - { - // configure for memory access (shared with debugger) - machine.debugger().cpu().configure_memory(m_symtable); - } - // load the cheats reload(); } diff --git a/src/frontend/mame/cheat.h b/src/frontend/mame/cheat.h index b81225faf15..b8f3e89a4e5 100644 --- a/src/frontend/mame/cheat.h +++ b/src/frontend/mame/cheat.h @@ -14,7 +14,6 @@ #pragma once #include "debug/express.h" -#include "debug/debugcpu.h" #include "ui/text.h" #include "xmlfile.h" @@ -345,7 +344,6 @@ private: int8_t m_lastline; // last line used for output bool m_disabled; // true if the cheat engine is disabled symbol_table m_symtable; // global symbol table - std::unique_ptr m_cpu; // debugger interface for cpus/memory // constants static constexpr int CHEAT_VERSION = 1; diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 8d3bd043ce0..993a3eeb428 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -14,6 +14,7 @@ #include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" #include "debug/textbuf.h" #include "drivenum.h" #include "emuopts.h" @@ -1577,8 +1578,8 @@ void lua_engine::initialize() debugger_type.set("consolelog", sol::property([](debugger_manager &debug) { return wrap_textbuf(debug.console().get_console_textbuf()); })); debugger_type.set("errorlog", sol::property([](debugger_manager &debug) { return wrap_textbuf(debug.console().get_errorlog_textbuf()); })); debugger_type.set("visible_cpu", sol::property( - [](debugger_manager &debug) { debug.cpu().get_visible_cpu(); }, - [](debugger_manager &debug, device_t &dev) { debug.cpu().set_visible_cpu(&dev); })); + [](debugger_manager &debug) { debug.console().get_visible_cpu(); }, + [](debugger_manager &debug, device_t &dev) { debug.console().set_visible_cpu(&dev); })); debugger_type.set("execution_state", sol::property( [](debugger_manager &debug) { return debug.cpu().is_stopped() ? "stop" : "run"; @@ -1616,7 +1617,7 @@ void lua_engine::initialize() * debug:bpset(addr, [opt] cond, [opt] act) - set breakpoint on addr, cond and act are debugger * expressions. returns breakpoint index * debug:bpclr(idx) - clear break - * debug:bplist()[] - table of breakpoints (k=index, v=device_debug::breakpoint) + * debug:bplist()[] - table of breakpoints (k=index, v=debug_breakpoint) * debug:wpset(space, type, addr, len, [opt] cond, [opt] act) - set watchpoint, cond and act * are debugger expressions. * returns watchpoint index @@ -1636,8 +1637,9 @@ void lua_engine::initialize() device_debug_type.set("bpclr", &device_debug::breakpoint_clear); device_debug_type.set("bplist", [this](device_debug &dev) { sol::table table = sol().create_table(); - for(const device_debug::breakpoint &bpt : dev.breakpoint_list()) + for(const auto &bpp : dev.breakpoint_list()) { + const debug_breakpoint &bpt = *bpp.second; sol::table bp = sol().create_table(); bp["enabled"] = bpt.enabled(); bp["address"] = bpt.address(); diff --git a/src/mame/drivers/chihiro.cpp b/src/mame/drivers/chihiro.cpp index 8bbdd7f4ed0..a30570a2de3 100644 --- a/src/mame/drivers/chihiro.cpp +++ b/src/mame/drivers/chihiro.cpp @@ -682,7 +682,6 @@ St. Instr. Comment /* jamtable disassembler */ void chihiro_state::jamtable_disasm(address_space &space, uint32_t address, uint32_t size) // 0xff000080 == fff00080 { - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); offs_t addr = (offs_t)address; if (!space.device().memory().translate(space.spacenum(), TRANSLATE_READ_DEBUG, addr)) @@ -694,11 +693,11 @@ void chihiro_state::jamtable_disasm(address_space &space, uint32_t address, uint { offs_t base = addr; - uint32_t opcode = cpu.read_byte(space, addr, true); + uint32_t opcode = space.read_byte(addr); addr++; - uint32_t op1 = cpu.read_dword(space, addr, true); + uint32_t op1 = space.read_dword_unaligned(addr); addr += 4; - uint32_t op2 = cpu.read_dword(space, addr, true); + uint32_t op2 = space.read_dword_unaligned(addr); addr += 4; char sop1[16]; diff --git a/src/mame/drivers/konamim2.cpp b/src/mame/drivers/konamim2.cpp index 13728e0ea0d..28f2ac63b19 100644 --- a/src/mame/drivers/konamim2.cpp +++ b/src/mame/drivers/konamim2.cpp @@ -1581,7 +1581,6 @@ void konamim2_state::dump_task_command(int ref, const std::vector & m2ptr pt_UserData; /* user-private data */ }; - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); address_space &space = m_ppc1->space(); uint64_t addr; @@ -1603,14 +1602,14 @@ void konamim2_state::dump_task_command(int ref, const std::vector & Task task; - task.t.pn_Next = cpu.read_dword(space, address + offsetof(ItemNode, pn_Next), true); - task.t.pn_Prev = cpu.read_dword(space, address + offsetof(ItemNode, pn_Prev), true); - task.t.n_SubsysType = cpu.read_byte(space, address + offsetof(ItemNode, n_SubsysType), true); - task.t.n_Type = cpu.read_byte(space, address + offsetof(ItemNode, n_Type), true); - task.t.n_Priority = cpu.read_byte(space, address + offsetof(ItemNode, n_Priority), true); - task.t.n_Flags = cpu.read_byte(space, address + offsetof(ItemNode, n_Flags), true); - task.t.n_Size = cpu.read_dword(space, address + offsetof(ItemNode, n_Size), true); - task.t.pn_Name = cpu.read_dword(space, address + offsetof(ItemNode, pn_Name), true); + task.t.pn_Next = space.read_dword(address + offsetof(ItemNode, pn_Next)); + task.t.pn_Prev = space.read_dword(address + offsetof(ItemNode, pn_Prev)); + task.t.n_SubsysType = space.read_byte(address + offsetof(ItemNode, n_SubsysType)); + task.t.n_Type = space.read_byte(address + offsetof(ItemNode, n_Type)); + task.t.n_Priority = space.read_byte(address + offsetof(ItemNode, n_Priority)); + task.t.n_Flags = space.read_byte(address + offsetof(ItemNode, n_Flags)); + task.t.n_Size = space.read_dword(address + offsetof(ItemNode, n_Size)); + task.t.pn_Name = space.read_dword(address + offsetof(ItemNode, pn_Name)); char name[128]; char *ptr = name; @@ -1618,31 +1617,31 @@ void konamim2_state::dump_task_command(int ref, const std::vector & do { - *ptr = cpu.read_byte(space, nameptr++, true); + *ptr = space.read_byte(nameptr++); } while (*ptr++ != 0); - task.t.n_Version = cpu.read_byte(space, address + offsetof(ItemNode, n_Version), true); - task.t.n_Revision = cpu.read_byte(space, address + offsetof(ItemNode, n_Revision), true); - task.t.n_Reserved0 = cpu.read_byte(space, address + offsetof(ItemNode, n_Reserved0), true); - task.t.n_ItemFlags = cpu.read_byte(space, address + offsetof(ItemNode, n_ItemFlags), true); - task.t.n_Item = cpu.read_dword(space, address + offsetof(ItemNode, n_Item), true); - task.t.n_Owner = cpu.read_dword(space, address + offsetof(ItemNode, n_Owner), true); - task.t.pn_Reserved1 = cpu.read_dword(space, address + offsetof(ItemNode, pn_Reserved1), true); + task.t.n_Version = space.read_byte(address + offsetof(ItemNode, n_Version)); + task.t.n_Revision = space.read_byte(address + offsetof(ItemNode, n_Revision)); + task.t.n_Reserved0 = space.read_byte(address + offsetof(ItemNode, n_Reserved0)); + task.t.n_ItemFlags = space.read_byte(address + offsetof(ItemNode, n_ItemFlags)); + task.t.n_Item = space.read_dword(address + offsetof(ItemNode, n_Item)); + task.t.n_Owner = space.read_dword(address + offsetof(ItemNode, n_Owner)); + task.t.pn_Reserved1 = space.read_dword(address + offsetof(ItemNode, pn_Reserved1)); - task.pt_ThreadTask = cpu.read_dword(space, address + offsetof(Task, pt_ThreadTask), true); - task.t_WaitBits = cpu.read_dword(space, address + offsetof(Task, t_WaitBits), true); - task.t_SigBits = cpu.read_dword(space, address + offsetof(Task, t_SigBits), true); - task.t_AllocatedSigs = cpu.read_dword(space, address + offsetof(Task, t_AllocatedSigs), true); - task.pt_StackBase = cpu.read_dword(space, address + offsetof(Task, pt_StackBase), true); - task.t_StackSize = cpu.read_dword(space, address + offsetof(Task, t_StackSize), true); - task.t_MaxUSecs = cpu.read_dword(space, address + offsetof(Task, t_MaxUSecs), true); - task.t_ElapsedTime.tt_Hi = cpu.read_dword(space, address + offsetof(Task, t_ElapsedTime)+0, true); - task.t_ElapsedTime.tt_Lo = cpu.read_dword(space, address + offsetof(Task, t_ElapsedTime)+4, true); - task.t_NumTaskLaunch = cpu.read_dword(space, address + offsetof(Task, t_NumTaskLaunch), true); - task.t_Flags = cpu.read_dword(space, address + offsetof(Task, t_Flags), true); - task.t_Module = cpu.read_dword(space, address + offsetof(Task, t_Module), true); - task.t_DefaultMsgPort = cpu.read_dword(space, address + offsetof(Task, t_DefaultMsgPort), true); - task.pt_UserData = cpu.read_dword(space, address + offsetof(Task, pt_UserData), true); + task.pt_ThreadTask = space.read_dword(address + offsetof(Task, pt_ThreadTask)); + task.t_WaitBits = space.read_dword(address + offsetof(Task, t_WaitBits)); + task.t_SigBits = space.read_dword(address + offsetof(Task, t_SigBits)); + task.t_AllocatedSigs = space.read_dword(address + offsetof(Task, t_AllocatedSigs)); + task.pt_StackBase = space.read_dword(address + offsetof(Task, pt_StackBase)); + task.t_StackSize = space.read_dword(address + offsetof(Task, t_StackSize)); + task.t_MaxUSecs = space.read_dword(address + offsetof(Task, t_MaxUSecs)); + task.t_ElapsedTime.tt_Hi = space.read_dword(address + offsetof(Task, t_ElapsedTime)+0); + task.t_ElapsedTime.tt_Lo = space.read_dword(address + offsetof(Task, t_ElapsedTime)+4); + task.t_NumTaskLaunch = space.read_dword(address + offsetof(Task, t_NumTaskLaunch)); + task.t_Flags = space.read_dword(address + offsetof(Task, t_Flags)); + task.t_Module = space.read_dword(address + offsetof(Task, t_Module)); + task.t_DefaultMsgPort = space.read_dword(address + offsetof(Task, t_DefaultMsgPort)); + task.pt_UserData = space.read_dword(address + offsetof(Task, pt_UserData)); // m2ptr pt_ThreadTask; /* I am a thread of what task? */ // uint32_t t_WaitBits; /* signals being waited for */ diff --git a/src/mame/machine/fddebug.cpp b/src/mame/machine/fddebug.cpp index a62cb823d9a..1e186468e12 100644 --- a/src/mame/machine/fddebug.cpp +++ b/src/mame/machine/fddebug.cpp @@ -883,7 +883,7 @@ static void execute_fdeliminate(running_machine &machine, int ref, int params, c static void execute_fdunlock(running_machine &machine, int ref, int params, const char **param) { - device_t *cpu = machine.debugger().cpu().get_visible_cpu(); + device_t *cpu = machine.debugger().console().get_visible_cpu(); /* support 0 or 1 parameters */ uint64_t offset; @@ -920,7 +920,7 @@ static void execute_fdunlock(running_machine &machine, int ref, int params, cons static void execute_fdignore(running_machine &machine, int ref, int params, const char **param) { - device_t *cpu = machine.debugger().cpu().get_visible_cpu(); + device_t *cpu = machine.debugger().console().get_visible_cpu(); /* support 0 or 1 parameters */ if (params == 1 && strcmp(param[0], "all") == 0) @@ -944,7 +944,7 @@ static void execute_fdignore(running_machine &machine, int ref, int params, cons /* if no parameter given, implicitly run as well */ if (params == 0) - machine.debugger().cpu().get_visible_cpu()->debug()->go(); + machine.debugger().console().get_visible_cpu()->debug()->go(); } @@ -1026,7 +1026,7 @@ static void execute_fdstate(running_machine &machine, int ref, int params, const static void execute_fdpc(running_machine &machine, int ref, int params, const char **param) { - device_t *cpu = machine.debugger().cpu().get_visible_cpu(); + device_t *cpu = machine.debugger().console().get_visible_cpu(); /* support 0 or 1 parameters */ uint64_t newpc = 0; @@ -1048,7 +1048,7 @@ static void execute_fdpc(running_machine &machine, int ref, int params, const ch static void execute_fdsearch(running_machine &machine, int ref, int params, const char **param) { - address_space &space = machine->debugger().cpu().get_visible_cpu()->memory().space(AS_PROGRAM); + address_space &space = machine->debugger().console().get_visible_cpu()->memory().space(AS_PROGRAM); int pc = space.device().state().pc(); int length, first = true; uint8_t instrdata[2]; @@ -1174,7 +1174,7 @@ static void execute_fdsearch(running_machine &machine, int ref, int params, cons static void execute_fddasm(running_machine &machine, int ref, int params, const char **param) { - address_space &space = machine->debugger().cpu().get_visible_cpu()->memory().space(AS_PROGRAM); + address_space &space = machine->debugger().console().get_visible_cpu()->memory().space(AS_PROGRAM); int origstate = fd1094_set_state(keyregion, -1); const char *filename; int skipped = false; diff --git a/src/mame/machine/xbox.cpp b/src/mame/machine/xbox.cpp index 95d14f42167..2e84803167e 100644 --- a/src/mame/machine/xbox.cpp +++ b/src/mame/machine/xbox.cpp @@ -83,7 +83,6 @@ void xbox_base_state::find_debug_params() void xbox_base_state::dump_string_command(int ref, const std::vector ¶ms) { - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); address_space &space = m_maincpu->space(); uint64_t addr; @@ -101,11 +100,10 @@ void xbox_base_state::dump_string_command(int ref, const std::vector 256) length = 256; - for (int a = 0; a < length; a++) + if (m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, buffer)) { - uint8_t c = cpu.read_byte(space, buffer + a, true); - con.printf("%c", c); + for (int a = 0; a < length; a++) + { + uint8_t c = space.read_byte(buffer + a); + con.printf("%c", c); + } } con.printf("\n"); } void xbox_base_state::dump_process_command(int ref, const std::vector ¶ms) { - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); address_space &space = m_maincpu->space(); uint64_t addr; @@ -142,21 +142,19 @@ void xbox_base_state::dump_process_command(int ref, const std::vector ¶ms) { - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); address_space &space = m_maincpu->space(); uint64_t addr; @@ -184,7 +182,6 @@ void xbox_base_state::dump_list_command(int ref, const std::vector con.printf("Address is unmapped.\n"); return; } - address = (offs_t)addr; if (params.size() >= 3) con.printf("Entry Object\n"); else @@ -198,7 +195,7 @@ void xbox_base_state::dump_list_command(int ref, const std::vector else con.printf("%08X\n", (uint32_t)addr); old = addr; - addr = cpu.read_dword(space, address, true); + addr = space.read_dword_unaligned(address); if (addr == start) break; if (addr == old) @@ -206,13 +203,11 @@ void xbox_base_state::dump_list_command(int ref, const std::vector address = (offs_t)addr; if (!m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, address)) break; - address = (offs_t)addr; } } void xbox_base_state::dump_dpc_command(int ref, const std::vector ¶ms) { - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); address_space &space = m_maincpu->space(); uint64_t addr; @@ -230,20 +225,18 @@ void xbox_base_state::dump_dpc_command(int ref, const std::vector & con.printf("Address is unmapped.\n"); return; } - address = (offs_t)addr; - con.printf("Type %d word\n", cpu.read_word(space, address, true)); - con.printf("Inserted %d byte\n", cpu.read_byte(space, address + 2, true)); - con.printf("Padding %d byte\n", cpu.read_byte(space, address + 3, true)); - con.printf("DpcListEntry {%08X,%08X} _LIST_ENTRY\n", cpu.read_dword(space, address + 4, true), cpu.read_dword(space, address + 8, true)); - con.printf("DeferredRoutine %08X dword\n", cpu.read_dword(space, address + 12, true)); - con.printf("DeferredContext %08X dword\n", cpu.read_dword(space, address + 16, true)); - con.printf("SystemArgument1 %08X dword\n", cpu.read_dword(space, address + 20, true)); - con.printf("SystemArgument2 %08X dword\n", cpu.read_dword(space, address + 24, true)); + con.printf("Type %d word\n", space.read_word_unaligned(address)); + con.printf("Inserted %d byte\n", space.read_byte(address + 2)); + con.printf("Padding %d byte\n", space.read_byte(address + 3)); + con.printf("DpcListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 4), space.read_dword_unaligned(address + 8, true)); + con.printf("DeferredRoutine %08X dword\n", space.read_dword_unaligned(address + 12)); + con.printf("DeferredContext %08X dword\n", space.read_dword_unaligned(address + 16)); + con.printf("SystemArgument1 %08X dword\n", space.read_dword_unaligned(address + 20)); + con.printf("SystemArgument2 %08X dword\n", space.read_dword_unaligned(address + 24)); } void xbox_base_state::dump_timer_command(int ref, const std::vector ¶ms) { - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); address_space &space = m_maincpu->space(); uint64_t addr; @@ -261,22 +254,20 @@ void xbox_base_state::dump_timer_command(int ref, const std::vector con.printf("Address is unmapped.\n"); return; } - address = (offs_t)addr; - con.printf("Header.Type %d byte\n", cpu.read_byte(space, address, true)); - con.printf("Header.Absolute %d byte\n", cpu.read_byte(space, address + 1, true)); - con.printf("Header.Size %d byte\n", cpu.read_byte(space, address + 2, true)); - con.printf("Header.Inserted %d byte\n", cpu.read_byte(space, address + 3, true)); - con.printf("Header.SignalState %08X dword\n", cpu.read_dword(space, address + 4, true)); - con.printf("Header.WaitListEntry {%08X,%08X} _LIST_ENTRY\n", cpu.read_dword(space, address + 8, true), cpu.read_dword(space, address + 12, true)); - con.printf("%s", string_format("DueTime %x qword\n", (int64_t)cpu.read_qword(space, address + 16, true)).c_str()); - con.printf("TimerListEntry {%08X,%08X} _LIST_ENTRY\n", cpu.read_dword(space, address + 24, true), cpu.read_dword(space, address + 28, true)); - con.printf("Dpc %08X dword\n", cpu.read_dword(space, address + 32, true)); - con.printf("Period %d dword\n", cpu.read_dword(space, address + 36, true)); + con.printf("Header.Type %d byte\n", space.read_byte(address)); + con.printf("Header.Absolute %d byte\n", space.read_byte(address + 1)); + con.printf("Header.Size %d byte\n", space.read_byte(address + 2)); + con.printf("Header.Inserted %d byte\n", space.read_byte(address + 3)); + con.printf("Header.SignalState %08X dword\n", space.read_dword_unaligned(address + 4)); + con.printf("Header.WaitListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 8), space.read_dword_unaligned(address + 12)); + con.printf("%s", string_format("DueTime %x qword\n", (int64_t)space.read_qword_unaligned(address + 16)).c_str()); + con.printf("TimerListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 24), space.read_dword_unaligned(address + 28)); + con.printf("Dpc %08X dword\n", space.read_dword_unaligned(address + 32)); + con.printf("Period %d dword\n", space.read_dword_unaligned(address + 36)); } void xbox_base_state::curthread_command(int ref, const std::vector ¶ms) { - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); address_space &space = m_maincpu->space(); offs_t address; @@ -288,26 +279,29 @@ void xbox_base_state::curthread_command(int ref, const std::vector con.printf("Address is unmapped.\n"); return; } - address = (offs_t)fsbase + (offs_t)debugc_bios->parameter[7-1]; - uint32_t kthrd = cpu.read_dword(space, address, true); + uint32_t kthrd = space.read_dword_unaligned(address); con.printf("Current thread is %08X\n", kthrd); address = (offs_t)(kthrd + debugc_bios->parameter[8-1]); - uint32_t topstack = cpu.read_dword(space, address, true); + if (!m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, address)) + return; + uint32_t topstack = space.read_dword_unaligned(address); con.printf("Current thread stack top is %08X\n", topstack); address = (offs_t)(kthrd + debugc_bios->parameter[4-1]); - uint32_t tlsdata = cpu.read_dword(space, address, true); + if (!m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, address)) + return; + uint32_t tlsdata = space.read_dword_unaligned(address); if (tlsdata == 0) address = (offs_t)(topstack - debugc_bios->parameter[5-1] - debugc_bios->parameter[6-1]); else address = (offs_t)(tlsdata - debugc_bios->parameter[6-1]); - con.printf("Current thread function is %08X\n", cpu.read_dword(space, address, true)); + if (m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, address)) + con.printf("Current thread function is %08X\n", space.read_dword_unaligned(address)); } void xbox_base_state::threadlist_command(int ref, const std::vector ¶ms) { address_space &space = m_maincpu->space(); - debugger_cpu &cpu = machine().debugger().cpu(); debugger_console &con = machine().debugger().console(); con.printf("Pri. _KTHREAD Stack Function\n"); @@ -315,20 +309,31 @@ void xbox_base_state::threadlist_command(int ref, const std::vector for (int pri = 0; pri < 16; pri++) { uint32_t curr = debugc_bios->parameter[1 - 1] + pri * 8; - uint32_t next = cpu.read_dword(space, curr, true); + uint32_t addr = curr; + if (!m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, addr)) + continue; + uint32_t next = space.read_dword_unaligned(addr); while ((next != curr) && (next != 0)) { uint32_t kthrd = next - debugc_bios->parameter[2 - 1]; - uint32_t topstack = cpu.read_dword(space, kthrd + debugc_bios->parameter[3 - 1], true); - uint32_t tlsdata = cpu.read_dword(space, kthrd + debugc_bios->parameter[4 - 1], true); - uint32_t function; + if (!m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, kthrd)) + break; + uint32_t topstack = space.read_dword_unaligned(kthrd + debugc_bios->parameter[3 - 1]); + uint32_t tlsdata = space.read_dword_unaligned(kthrd + debugc_bios->parameter[4 - 1]); + uint32_t function = 0; if (tlsdata == 0) - function = cpu.read_dword(space, topstack - debugc_bios->parameter[5 - 1] - debugc_bios->parameter[6 - 1], true); + addr = topstack - debugc_bios->parameter[5 - 1] - debugc_bios->parameter[6 - 1]; else - function = cpu.read_dword(space, tlsdata - debugc_bios->parameter[6 - 1], true); + addr = tlsdata - debugc_bios->parameter[6 - 1]; + if (m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, addr)) + function = space.read_dword_unaligned(addr); con.printf(" %02d %08x %08x %08x\n", pri, kthrd, topstack, function); - next = cpu.read_dword(space, next, true); + addr = next; + if (m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, addr)) + next = space.read_dword_unaligned(addr); + else + break; } } } diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp index 63dbd420184..b8c0bbe7b80 100644 --- a/src/osd/modules/debugger/debuggdbstub.cpp +++ b/src/osd/modules/debugger/debuggdbstub.cpp @@ -9,6 +9,7 @@ #include "emu.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" #include "debug/textbuf.h" #include "debug_module.h" #include "debugger.h" @@ -426,8 +427,8 @@ private: std::map m_address_map; - device_debug::breakpoint *m_triggered_breakpoint; - device_debug::watchpoint *m_triggered_watchpoint; + debug_breakpoint *m_triggered_breakpoint; + debug_watchpoint *m_triggered_watchpoint; std::string m_target_xml; @@ -596,7 +597,7 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop) } else { - device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug(); + device_debug *debug = m_debugger_console->get_visible_cpu()->debug(); m_triggered_watchpoint = debug->triggered_watchpoint(); m_triggered_breakpoint = debug->triggered_breakpoint(); if ( m_send_stop_packet ) @@ -683,7 +684,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_c(const char *buf) if ( *buf != '\0' ) return REPLY_UNSUPPORTED; - m_debugger_cpu->get_visible_cpu()->debug()->go(); + m_debugger_console->get_visible_cpu()->debug()->go(); m_send_stop_packet = true; return REPLY_NONE; } @@ -696,7 +697,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_D(const char *buf) if ( *buf != '\0' ) return REPLY_UNSUPPORTED; - m_debugger_cpu->get_visible_cpu()->debug()->go(); + m_debugger_console->get_visible_cpu()->debug()->go(); m_dettached = true; return REPLY_OK; @@ -752,7 +753,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_H(const char *buf) debug_gdbstub::cmd_reply debug_gdbstub::handle_k(const char *buf) { m_machine->schedule_exit(); - m_debugger_cpu->get_visible_cpu()->debug()->go(); + m_debugger_console->get_visible_cpu()->debug()->go(); m_dettached = true; m_socket.close(); return REPLY_NONE; @@ -969,7 +970,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_s(const char *buf) if ( *buf != '\0' ) return REPLY_UNSUPPORTED; - m_debugger_cpu->get_visible_cpu()->debug()->single_step(); + m_debugger_console->get_visible_cpu()->debug()->single_step(); m_send_stop_packet = true; return REPLY_NONE; } @@ -977,7 +978,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_s(const char *buf) //------------------------------------------------------------------------- static bool remove_breakpoint(device_debug *debug, uint64_t address, int /*kind*/) { - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); if (bp != nullptr) return debug->breakpoint_clear(bp->index()); return false; @@ -1021,7 +1022,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_z(const char *buf) m_address_map.erase(offset); } - device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug(); + device_debug *debug = m_debugger_console->get_visible_cpu()->debug(); switch ( type ) { // Note: software and hardware breakpoints are treated both the @@ -1062,7 +1063,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf) m_address_map[offset] = address; } - device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug(); + device_debug *debug = m_debugger_console->get_visible_cpu()->debug(); switch ( type ) { // Note: software and hardware breakpoints are treated both the diff --git a/src/osd/modules/debugger/debugimgui.cpp b/src/osd/modules/debugger/debugimgui.cpp index c1e3a4de21d..296b148c5db 100644 --- a/src/osd/modules/debugger/debugimgui.cpp +++ b/src/osd/modules/debugger/debugimgui.cpp @@ -375,36 +375,36 @@ void debug_imgui::handle_keys() else { m_machine->schedule_soft_reset(); - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); } } if(ImGui::IsKeyPressed(ITEM_ID_F5,false)) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); m_running = true; } if(ImGui::IsKeyPressed(ITEM_ID_F6,false)) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_next_device(); m_running = true; } if(ImGui::IsKeyPressed(ITEM_ID_F7,false)) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_interrupt(); m_running = true; } if(ImGui::IsKeyPressed(ITEM_ID_F8,false)) - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_vblank(); if(ImGui::IsKeyPressed(ITEM_ID_F9,false)) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_out(); if(ImGui::IsKeyPressed(ITEM_ID_F10,false)) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_over(); if(ImGui::IsKeyPressed(ITEM_ID_F11,false)) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); if(ImGui::IsKeyPressed(ITEM_ID_F12,false)) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); m_hide = true; } @@ -484,7 +484,7 @@ void debug_imgui::handle_console(running_machine* machine) // if console input is empty, then do a single step if(strlen(view_main_console->console_input) == 0) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); view_main_console->exec_cmd = false; history_pos = view_main_console->console_history.size(); return; @@ -1248,33 +1248,33 @@ void debug_imgui::draw_console() ImGui::Separator(); if(ImGui::MenuItem("Run", "F5")) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); m_running = true; } if(ImGui::MenuItem("Go to next CPU", "F6")) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_next_device(); m_running = true; } if(ImGui::MenuItem("Run until next interrupt", "F7")) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_interrupt(); m_running = true; } if(ImGui::MenuItem("Run until VBLANK", "F8")) - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_vblank(); if(ImGui::MenuItem("Run and hide debugger", "F12")) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); m_hide = true; } ImGui::Separator(); if(ImGui::MenuItem("Single step", "F11")) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); if(ImGui::MenuItem("Step over", "F10")) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_over(); if(ImGui::MenuItem("Step out", "F9")) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_out(); ImGui::EndMenu(); } diff --git a/src/osd/modules/debugger/debugwin.cpp b/src/osd/modules/debugger/debugwin.cpp index 975e7ba6bc6..18bbc07dd70 100644 --- a/src/osd/modules/debugger/debugwin.cpp +++ b/src/osd/modules/debugger/debugwin.cpp @@ -161,7 +161,7 @@ void debugger_windows::debugger_update() { HWND const focuswnd = GetFocus(); - m_machine->debugger().cpu().get_visible_cpu()->debug()->halt_on_next_instruction("User-initiated break\n"); + m_machine->debugger().debug_break(); // if we were focused on some window's edit box, reset it to default for (auto &info : m_window_list) diff --git a/src/osd/modules/debugger/none.cpp b/src/osd/modules/debugger/none.cpp index 3ce8d6572bc..ef23fe04089 100644 --- a/src/osd/modules/debugger/none.cpp +++ b/src/osd/modules/debugger/none.cpp @@ -10,6 +10,7 @@ #include "debug_module.h" #include "modules/osdmodule.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" #include "debugger.h" @@ -42,7 +43,7 @@ void debug_none::init_debugger(running_machine &machine) void debug_none::wait_for_debugger(device_t &device, bool firststop) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); } void debug_none::debugger_update() diff --git a/src/osd/modules/debugger/osx/debugconsole.mm b/src/osd/modules/debugger/osx/debugconsole.mm index 1bd285e8c3b..c1689a8b855 100644 --- a/src/osd/modules/debugger/osx/debugconsole.mm +++ b/src/osd/modules/debugger/osx/debugconsole.mm @@ -24,6 +24,7 @@ #include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" #include "util/xmlfile.h" @@ -181,7 +182,7 @@ [dasmSplit setFrame:rhsFrame]; // select the current processor - [self setCPU:machine->debugger().cpu().get_visible_cpu()]; + [self setCPU:machine->debugger().console().get_visible_cpu()]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(auxiliaryWindowWillClose:) @@ -219,7 +220,7 @@ NSString *command = [sender stringValue]; if ([command length] == 0) { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine->debugger().console().get_visible_cpu()->debug()->single_step(); [history reset]; } else @@ -234,10 +235,10 @@ - (IBAction)debugToggleBreakpoint:(id)sender { device_t &device = *[dasmView source]->device(); - if ([dasmView cursorVisible] && (machine->debugger().cpu().get_visible_cpu() == &device)) + if ([dasmView cursorVisible] && (machine->debugger().console().get_visible_cpu() == &device)) { offs_t const address = [dasmView selectedAddress]; - const device_debug::breakpoint *bp = [dasmView source]->device()->debug()->breakpoint_find(address); + const debug_breakpoint *bp = [dasmView source]->device()->debug()->breakpoint_find(address); // if it doesn't exist, add a new one NSString *command; @@ -252,9 +253,9 @@ - (IBAction)debugToggleBreakpointEnable:(id)sender { device_t &device = *[dasmView source]->device(); - if ([dasmView cursorVisible] && (machine->debugger().cpu().get_visible_cpu() == &device)) + if ([dasmView cursorVisible] && (machine->debugger().console().get_visible_cpu() == &device)) { - const device_debug::breakpoint *bp = [dasmView source]->device()->debug()->breakpoint_find([dasmView selectedAddress]); + const debug_breakpoint *bp = [dasmView source]->device()->debug()->breakpoint_find([dasmView selectedAddress]); if (bp != nullptr) { NSString *command; @@ -270,7 +271,7 @@ - (IBAction)debugRunToCursor:(id)sender { device_t &device = *[dasmView source]->device(); - if ([dasmView cursorVisible] && (machine->debugger().cpu().get_visible_cpu() == &device)) + if ([dasmView cursorVisible] && (machine->debugger().console().get_visible_cpu() == &device)) { NSString *command = [NSString stringWithFormat:@"go 0x%lX", (unsigned long)[dasmView selectedAddress]]; machine->debugger().console().execute_command([command UTF8String], 1); @@ -499,7 +500,7 @@ [[NSNotificationCenter defaultCenter] postNotificationName:MAMEHideDebuggerNotification object:self userInfo:info]; - machine->debugger().cpu().get_visible_cpu()->debug()->go(); + machine->debugger().console().get_visible_cpu()->debug()->go(); } } @@ -562,9 +563,9 @@ SEL const action = [item action]; BOOL const inContextMenu = ([item menu] == [dasmView menu]); BOOL const haveCursor = [dasmView cursorVisible]; - BOOL const isCurrent = (machine->debugger().cpu().get_visible_cpu() == [dasmView source]->device()); + BOOL const isCurrent = (machine->debugger().console().get_visible_cpu() == [dasmView source]->device()); - const device_debug::breakpoint *breakpoint = nullptr; + const debug_breakpoint *breakpoint = nullptr; if (haveCursor) { breakpoint = [dasmView source]->device()->debug()->breakpoint_find([dasmView selectedAddress]); diff --git a/src/osd/modules/debugger/osx/debugview.mm b/src/osd/modules/debugger/osx/debugview.mm index a414e4ad8a4..df7c4dbcc01 100644 --- a/src/osd/modules/debugger/osx/debugview.mm +++ b/src/osd/modules/debugger/osx/debugview.mm @@ -10,6 +10,7 @@ #include "emu.h" #include "debugger.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" #include "modules/lib/osdobj_common.h" @@ -871,7 +872,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) - (void)insertNewline:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine->debugger().console().get_visible_cpu()->debug()->single_step(); } diff --git a/src/osd/modules/debugger/osx/debugwindowhandler.mm b/src/osd/modules/debugger/osx/debugwindowhandler.mm index c1aa8e383a2..fd1eb44f6d3 100644 --- a/src/osd/modules/debugger/osx/debugwindowhandler.mm +++ b/src/osd/modules/debugger/osx/debugwindowhandler.mm @@ -14,6 +14,7 @@ #import "debugview.h" #include "debugger.h" +#include "debug/debugcon.h" #include "util/xmlfile.h" @@ -189,12 +190,12 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo - (IBAction)debugBreak:(id)sender { if (machine->debug_flags & DEBUG_FLAG_ENABLED) - machine->debugger().cpu().get_visible_cpu()->debug()->halt_on_next_instruction("User-initiated break\n"); + machine->debugger().console().get_visible_cpu()->debug()->halt_on_next_instruction("User-initiated break\n"); } - (IBAction)debugRun:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->go(); + machine->debugger().console().get_visible_cpu()->debug()->go(); } @@ -203,43 +204,43 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo object:self userInfo:[NSDictionary dictionaryWithObject:[NSValue valueWithPointer:machine] forKey:@"MAMEDebugMachine"]]; - machine->debugger().cpu().get_visible_cpu()->debug()->go(); + machine->debugger().console().get_visible_cpu()->debug()->go(); } - (IBAction)debugRunToNextCPU:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + machine->debugger().console().get_visible_cpu()->debug()->go_next_device(); } - (IBAction)debugRunToNextInterrupt:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + machine->debugger().console().get_visible_cpu()->debug()->go_interrupt(); } - (IBAction)debugRunToNextVBLANK:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + machine->debugger().console().get_visible_cpu()->debug()->go_vblank(); } - (IBAction)debugStepInto:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine->debugger().console().get_visible_cpu()->debug()->single_step(); } - (IBAction)debugStepOver:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + machine->debugger().console().get_visible_cpu()->debug()->single_step_over(); } - (IBAction)debugStepOut:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + machine->debugger().console().get_visible_cpu()->debug()->single_step_out(); } - (IBAction)debugSoftReset:(id)sender { machine->schedule_soft_reset(); - machine->debugger().cpu().get_visible_cpu()->debug()->go(); + machine->debugger().console().get_visible_cpu()->debug()->go(); } diff --git a/src/osd/modules/debugger/osx/disassemblyviewer.mm b/src/osd/modules/debugger/osx/disassemblyviewer.mm index eb039f4ca17..1f286a6bfc4 100644 --- a/src/osd/modules/debugger/osx/disassemblyviewer.mm +++ b/src/osd/modules/debugger/osx/disassemblyviewer.mm @@ -16,6 +16,7 @@ #include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" #include "util/xmlfile.h" @@ -109,7 +110,7 @@ [actionButton release]; // set default state - [dasmView selectSubviewForDevice:machine->debugger().cpu().get_visible_cpu()]; + [dasmView selectSubviewForDevice:machine->debugger().console().get_visible_cpu()]; [dasmView setExpression:@"curpc"]; [expressionField setStringValue:@"curpc"]; [expressionField selectText:self]; @@ -176,7 +177,7 @@ { device_t &device = *[dasmView source]->device(); offs_t const address = [dasmView selectedAddress]; - const device_debug::breakpoint *bp = device.debug()->breakpoint_find(address); + const debug_breakpoint *bp = device.debug()->breakpoint_find(address); // if it doesn't exist, add a new one if (bp == nullptr) @@ -203,7 +204,7 @@ { device_t &device = *[dasmView source]->device(); offs_t const address = [dasmView selectedAddress]; - const device_debug::breakpoint *bp = device.debug()->breakpoint_find(address); + const debug_breakpoint *bp = device.debug()->breakpoint_find(address); if (bp != nullptr) { device.debug()->breakpoint_enable(bp->index(), !bp->enabled()); @@ -252,7 +253,7 @@ BOOL const inContextMenu = ([item menu] == [dasmView menu]); BOOL const haveCursor = [dasmView cursorVisible]; - const device_debug::breakpoint *breakpoint = nullptr; + const debug_breakpoint *breakpoint = nullptr; if (haveCursor) { breakpoint = [dasmView source]->device()->debug()->breakpoint_find([dasmView selectedAddress]); diff --git a/src/osd/modules/debugger/osx/memoryview.mm b/src/osd/modules/debugger/osx/memoryview.mm index 78af307e993..0db48236b79 100644 --- a/src/osd/modules/debugger/osx/memoryview.mm +++ b/src/osd/modules/debugger/osx/memoryview.mm @@ -9,7 +9,6 @@ #include "emu.h" #import "memoryview.h" -#include "debug/debugcpu.h" #include "debug/debugvw.h" #include "util/xmlfile.h" diff --git a/src/osd/modules/debugger/osx/memoryviewer.mm b/src/osd/modules/debugger/osx/memoryviewer.mm index 80d5434a826..b1064aee69f 100644 --- a/src/osd/modules/debugger/osx/memoryviewer.mm +++ b/src/osd/modules/debugger/osx/memoryviewer.mm @@ -14,7 +14,7 @@ #import "memoryview.h" #include "debugger.h" -#include "debug/debugcpu.h" +#include "debug/debugcon.h" #include "debug/dvmemory.h" #include "util/xmlfile.h" @@ -108,7 +108,7 @@ [actionButton release]; // set default state - [memoryView selectSubviewForDevice:machine->debugger().cpu().get_visible_cpu()]; + [memoryView selectSubviewForDevice:machine->debugger().console().get_visible_cpu()]; [memoryView setExpression:@"0"]; [expressionField setStringValue:@"0"]; [expressionField selectText:self]; diff --git a/src/osd/modules/debugger/osx/registersview.mm b/src/osd/modules/debugger/osx/registersview.mm index ae202fa488e..c710179c5bd 100644 --- a/src/osd/modules/debugger/osx/registersview.mm +++ b/src/osd/modules/debugger/osx/registersview.mm @@ -10,7 +10,7 @@ #include "emu.h" #include "debugger.h" -#include "debug/debugcpu.h" +#include "debug/debugcon.h" #include "debug/debugvw.h" @@ -30,7 +30,7 @@ - (NSSize)maximumFrameSize { debug_view_xy max; - device_t *curcpu = machine->debugger().cpu().get_visible_cpu(); + device_t *curcpu = machine->debugger().console().get_visible_cpu(); const debug_view_source *source = view->source_for_device(curcpu); max.x = max.y = 0; diff --git a/src/osd/modules/debugger/qt/dasmwindow.cpp b/src/osd/modules/debugger/qt/dasmwindow.cpp index 04cbd523cdd..52b33b50da8 100644 --- a/src/osd/modules/debugger/qt/dasmwindow.cpp +++ b/src/osd/modules/debugger/qt/dasmwindow.cpp @@ -12,6 +12,7 @@ #include "debug/debugcon.h" #include "debug/debugcpu.h" #include "debug/dvdisasm.h" +#include "debug/points.h" DasmWindow::DasmWindow(running_machine* machine, QWidget* parent) : @@ -141,7 +142,7 @@ void DasmWindow::toggleBreakpointAtCursor(bool changedTo) device_debug *const cpuinfo = device->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); // If none exists, add a new one if (bp == nullptr) @@ -172,7 +173,7 @@ void DasmWindow::enableBreakpointAtCursor(bool changedTo) device_debug *const cpuinfo = device->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); if (bp != nullptr) { @@ -228,7 +229,7 @@ void DasmWindow::dasmViewUpdated() device_debug *const cpuinfo = device->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); if (bp != nullptr) { @@ -260,7 +261,7 @@ void DasmWindow::populateComboBox() void DasmWindow::setToCurrentCpu() { - device_t* curCpu = m_machine->debugger().cpu().get_visible_cpu(); + device_t* curCpu = m_machine->debugger().console().get_visible_cpu(); if (curCpu) { const debug_view_source *source = m_dasmView->view()->source_for_device(curCpu); diff --git a/src/osd/modules/debugger/qt/mainwindow.cpp b/src/osd/modules/debugger/qt/mainwindow.cpp index 6a79ebf955d..f2026db67e9 100644 --- a/src/osd/modules/debugger/qt/mainwindow.cpp +++ b/src/osd/modules/debugger/qt/mainwindow.cpp @@ -14,6 +14,7 @@ #include "debug/debugcon.h" #include "debug/debugcpu.h" #include "debug/dvdisasm.h" +#include "debug/points.h" MainWindow::MainWindow(running_machine* machine, QWidget* parent) : @@ -214,13 +215,13 @@ bool MainWindow::eventFilter(QObject* obj, QEvent* event) void MainWindow::toggleBreakpointAtCursor(bool changedTo) { debug_view_disasm *const dasmView = downcast(m_dasmFrame->view()->view()); - if (dasmView->cursor_visible() && (m_machine->debugger().cpu().get_visible_cpu() == dasmView->source()->device())) + if (dasmView->cursor_visible() && (m_machine->debugger().console().get_visible_cpu() == dasmView->source()->device())) { offs_t const address = downcast(dasmView)->selected_address(); device_debug *const cpuinfo = dasmView->source()->device()->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); // If none exists, add a new one std::string command; @@ -242,13 +243,13 @@ void MainWindow::toggleBreakpointAtCursor(bool changedTo) void MainWindow::enableBreakpointAtCursor(bool changedTo) { debug_view_disasm *const dasmView = downcast(m_dasmFrame->view()->view()); - if (dasmView->cursor_visible() && (m_machine->debugger().cpu().get_visible_cpu() == dasmView->source()->device())) + if (dasmView->cursor_visible() && (m_machine->debugger().console().get_visible_cpu() == dasmView->source()->device())) { offs_t const address = dasmView->selected_address(); device_debug *const cpuinfo = dasmView->source()->device()->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); if (bp != nullptr) { @@ -265,7 +266,7 @@ void MainWindow::enableBreakpointAtCursor(bool changedTo) void MainWindow::runToCursor(bool changedTo) { debug_view_disasm* dasmView = downcast(m_dasmFrame->view()->view()); - if (dasmView->cursor_visible() && (m_machine->debugger().cpu().get_visible_cpu() == dasmView->source()->device())) + if (dasmView->cursor_visible() && (m_machine->debugger().console().get_visible_cpu() == dasmView->source()->device())) { offs_t address = downcast(dasmView)->selected_address(); std::string command = string_format("go 0x%X", address); @@ -304,7 +305,7 @@ void MainWindow::executeCommand(bool withClear) // A blank command is a "silent step" if (command == "") { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); return; } @@ -396,7 +397,7 @@ void MainWindow::unmountImage(bool changedTo) void MainWindow::dasmViewUpdated() { debug_view_disasm *const dasmView = downcast(m_dasmFrame->view()->view()); - bool const haveCursor = dasmView->cursor_visible() && (m_machine->debugger().cpu().get_visible_cpu() == dasmView->source()->device()); + bool const haveCursor = dasmView->cursor_visible() && (m_machine->debugger().console().get_visible_cpu() == dasmView->source()->device()); bool haveBreakpoint = false; bool breakpointEnabled = false; if (haveCursor) @@ -406,7 +407,7 @@ void MainWindow::dasmViewUpdated() device_debug *const cpuinfo = device->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); if (bp != nullptr) { diff --git a/src/osd/modules/debugger/qt/memorywindow.cpp b/src/osd/modules/debugger/qt/memorywindow.cpp index 2124effcbbd..bead6af0cef 100644 --- a/src/osd/modules/debugger/qt/memorywindow.cpp +++ b/src/osd/modules/debugger/qt/memorywindow.cpp @@ -295,7 +295,7 @@ void MemoryWindow::populateComboBox() void MemoryWindow::setToCurrentCpu() { - device_t* curCpu = m_machine->debugger().cpu().get_visible_cpu(); + device_t* curCpu = m_machine->debugger().console().get_visible_cpu(); if (curCpu) { const debug_view_source *source = m_memTable->view()->source_for_device(curCpu); @@ -355,27 +355,51 @@ void DebuggerMemView::mousePressEvent(QMouseEvent* event) const offs_t address = memView->addressAtCursorPosition(clickViewPosition); const debug_view_memory_source* source = downcast(memView->source()); address_space* addressSpace = source->space(); - const int nativeDataWidth = addressSpace->data_width() / 8; - const uint64_t memValue = source->device()->machine().debugger().cpu().read_memory(*addressSpace, - addressSpace->address_to_byte(address), - nativeDataWidth, - true); - const offs_t pc = source->device()->debug()->track_mem_pc_from_space_address_data(addressSpace->spacenum(), - address, - memValue); - if (pc != (offs_t)(-1)) + offs_t a = address & space->logaddrmask(); + if (!addressSpace->device().memory().translate(addressSpace->spacenum(), TRANSLATE_READ_DEBUG, a)) { - // TODO: You can specify a box that the tooltip stays alive within - might be good? - const QString addressAndPc = QString("Address %1 written at PC=%2").arg(address, 2, 16).arg(pc, 2, 16); - QToolTip::showText(QCursor::pos(), addressAndPc, nullptr); - - // Copy the PC into the clipboard as well - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(QString("%1").arg(pc, 2, 16)); + QToolTip::showText(QCursor::pos(), "Bad address", nullptr); } else { - QToolTip::showText(QCursor::pos(), "UNKNOWN PC", nullptr); + uint64_t memValue = addressSpace->unmap(); + auto dis = addressSpace->device().machine().disable_side_effects(); + switch (addressSpace->data_width()) + { + case 8: + memValue = space->read_byte(a); + break; + + case 16: + memValue = space->read_word_unaligned(a); + break; + + case 32: + memValue = space->read_dword_unaligned(a); + break; + + case 64: + memValue = space->read_qword_unaligned(a); + break; + } + + const offs_t pc = source->device()->debug()->track_mem_pc_from_space_address_data(addressSpace->spacenum(), + address, + memValue); + if (pc != (offs_t)(-1)) + { + // TODO: You can specify a box that the tooltip stays alive within - might be good? + const QString addressAndPc = QString("Address %1 written at PC=%2").arg(address, 2, 16).arg(pc, 2, 16); + QToolTip::showText(QCursor::pos(), addressAndPc, nullptr); + + // Copy the PC into the clipboard as well + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(QString("%1").arg(pc, 2, 16)); + } + else + { + QToolTip::showText(QCursor::pos(), "UNKNOWN PC", nullptr); + } } } diff --git a/src/osd/modules/debugger/qt/windowqt.cpp b/src/osd/modules/debugger/qt/windowqt.cpp index dda9ee64dc7..aa32ffb5220 100644 --- a/src/osd/modules/debugger/qt/windowqt.cpp +++ b/src/osd/modules/debugger/qt/windowqt.cpp @@ -179,49 +179,49 @@ void WindowQt::debugActOpenDevices() void WindowQt::debugActRun() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); } void WindowQt::debugActRunAndHide() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); hideAll(); } void WindowQt::debugActRunToNextCpu() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_next_device(); } void WindowQt::debugActRunNextInt() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_interrupt(); } void WindowQt::debugActRunNextVBlank() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_vblank(); } void WindowQt::debugActStepInto() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); } void WindowQt::debugActStepOver() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_over(); } void WindowQt::debugActStepOut() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_out(); } void WindowQt::debugActSoftReset() { m_machine->schedule_soft_reset(); - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); } void WindowQt::debugActHardReset() diff --git a/src/osd/modules/debugger/win/consolewininfo.cpp b/src/osd/modules/debugger/win/consolewininfo.cpp index 27a6228d2f5..e6ad4c0986f 100644 --- a/src/osd/modules/debugger/win/consolewininfo.cpp +++ b/src/osd/modules/debugger/win/consolewininfo.cpp @@ -78,7 +78,7 @@ consolewin_info::consolewin_info(debugger_windows_interface &debugger) : } // recompute the children - set_cpu(*machine().debugger().cpu().get_visible_cpu()); + set_cpu(*machine().debugger().console().get_visible_cpu()); // mark the edit box as the default focus and set it editwin_info::set_default_focus(); @@ -481,7 +481,7 @@ bool consolewin_info::handle_command(WPARAM wparam, LPARAM lparam) void consolewin_info::process_string(std::string const &string) { if (string.empty()) // an empty string is a single step - machine().debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine().debugger().console().get_visible_cpu()->debug()->single_step(); else // otherwise, just process the command machine().debugger().console().execute_command(string, true); diff --git a/src/osd/modules/debugger/win/debugviewinfo.cpp b/src/osd/modules/debugger/win/debugviewinfo.cpp index ff46d13c7fe..1b824a04b8c 100644 --- a/src/osd/modules/debugger/win/debugviewinfo.cpp +++ b/src/osd/modules/debugger/win/debugviewinfo.cpp @@ -12,6 +12,7 @@ #include "debugwininfo.h" #include "uimetrics.h" #include "debugger.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" #include "strconv.h" @@ -207,7 +208,7 @@ bool debugview_info::source_is_visible_cpu() const if (m_view != nullptr) { const debug_view_source *const source = m_view->source(); - return (source != nullptr) && (machine().debugger().cpu().get_visible_cpu() == source->device()); + return (source != nullptr) && (machine().debugger().console().get_visible_cpu() == source->device()); } return false; } @@ -245,7 +246,7 @@ bool debugview_info::set_source_for_device(device_t &device) bool debugview_info::set_source_for_visible_cpu() { - device_t *const curcpu = machine().debugger().cpu().get_visible_cpu(); + device_t *const curcpu = machine().debugger().console().get_visible_cpu(); if (curcpu != nullptr) return set_source_for_device(*curcpu); else diff --git a/src/osd/modules/debugger/win/debugwininfo.cpp b/src/osd/modules/debugger/win/debugwininfo.cpp index 1645582038c..e684e1f32fa 100644 --- a/src/osd/modules/debugger/win/debugwininfo.cpp +++ b/src/osd/modules/debugger/win/debugwininfo.cpp @@ -12,6 +12,7 @@ #include "debugviewinfo.h" #include "debugger.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" #include "window.h" #include "winutf8.h" @@ -300,31 +301,31 @@ bool debugwin_info::handle_command(WPARAM wparam, LPARAM lparam) case ID_RUN_AND_HIDE: debugger().hide_all(); case ID_RUN: - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); return true; case ID_NEXT_CPU: - machine().debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + machine().debugger().console().get_visible_cpu()->debug()->go_next_device(); return true; case ID_RUN_VBLANK: - machine().debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + machine().debugger().console().get_visible_cpu()->debug()->go_vblank(); return true; case ID_RUN_IRQ: - machine().debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + machine().debugger().console().get_visible_cpu()->debug()->go_interrupt(); return true; case ID_STEP: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine().debugger().console().get_visible_cpu()->debug()->single_step(); return true; case ID_STEP_OVER: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + machine().debugger().console().get_visible_cpu()->debug()->single_step_over(); return true; case ID_STEP_OUT: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + machine().debugger().console().get_visible_cpu()->debug()->single_step_out(); return true; case ID_REWIND_STEP: @@ -348,7 +349,7 @@ bool debugwin_info::handle_command(WPARAM wparam, LPARAM lparam) case ID_SOFT_RESET: machine().schedule_soft_reset(); - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); return true; case ID_EXIT: @@ -507,7 +508,7 @@ LRESULT debugwin_info::window_proc(UINT message, WPARAM wparam, LPARAM lparam) if (m_is_main_console) { debugger().hide_all(); - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); } else { diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.cpp b/src/osd/modules/debugger/win/disasmbasewininfo.cpp index 0d22b7b8d39..800443b47c1 100644 --- a/src/osd/modules/debugger/win/disasmbasewininfo.cpp +++ b/src/osd/modules/debugger/win/disasmbasewininfo.cpp @@ -15,6 +15,7 @@ #include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" //#include "winutf8.h" @@ -115,7 +116,7 @@ void disasmbasewin_info::update_menu() device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); if (bp == nullptr) { @@ -166,7 +167,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); // if it doesn't exist, add a new one if (!is_main_console()) @@ -204,7 +205,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); // if it doesn't exist, add a new one if (bp != nullptr)