summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug/debugcpu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/debug/debugcpu.cpp')
-rw-r--r--src/emu/debug/debugcpu.cpp1395
1 files changed, 59 insertions, 1336 deletions
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<u64[]>(NUM_TEMP_VARIABLES);
/* create a global symbol table */
- m_symtable = std::make_unique<symbol_table>();
+ m_symtable = std::make_unique<symbol_table>(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<cpu_device *>(&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
@@ -135,22 +112,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
//**************************************************************************
@@ -288,294 +249,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<symbol_table>(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<std::forward_list<debug_registerpoint>>())
, 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<parsed_expression>(m_symtable, condition);
+ m_exception_condition = std::make_unique<parsed_expression>(*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<parsed_expression>(m_symtable, condition);
+ m_privilege_condition = std::make_unique<parsed_expression>(*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_pack<std:
// given address, or nullptr if none exists there
//-------------------------------------------------
-const device_debug::breakpoint *device_debug::breakpoint_find(offs_t address) const
+const debug_breakpoint *device_debug::breakpoint_find(offs_t address) const
{
- for (const breakpoint &bp : m_bplist)
- if (bp.address() == address)
- return &bp;
+ auto bpitp = m_bplist.equal_range(address);
+ if (bpitp.first != bpitp.second)
+ return bpitp.first->second.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<debug_breakpoint>(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<watchpoint>(this, m_symtable, id, space, type, address, length, condition, action));
+ m_wplist[space.spacenum()].emplace_back(std::make_unique<debug_watchpoint>(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<u64>(m_space.data_width());
- if (start != rstart)
- {
- if (endian == ENDIANNESS_LITTLE)
- smask &= ~make_bitmask<u64>((start - rstart) * unit_size);
- else
- smask &= make_bitmask<u64>((rstart + subamask + 1 - start) * unit_size);
- }
- if (end != rend)
- {
- if (endian == ENDIANNESS_LITTLE)
- emask &= make_bitmask<u64>((subamask + 1 + end - rend) * unit_size);
- else
- emask &= ~make_bitmask<u64>((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<u64>(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<u64>(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