summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug/debugcpu.cpp
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2018-06-29 10:58:19 +0200
committer Olivier Galibert <galibert@pobox.com>2018-06-29 20:04:28 +0200
commita704ed7b1b121c3bcff52d49bff8372360fe907c (patch)
tree53dd19f2dbe2bd0bf0f747dcccd989beabfafbf7 /src/emu/debug/debugcpu.cpp
parentf16d1298a44e71c18c337fc321faebe4fe691e06 (diff)
emumem: Backend modernization [O. Galibert]
Diffstat (limited to 'src/emu/debug/debugcpu.cpp')
-rw-r--r--src/emu/debug/debugcpu.cpp569
1 files changed, 342 insertions, 227 deletions
diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp
index bbf1170b762..cd130c5e3f0 100644
--- a/src/emu/debug/debugcpu.cpp
+++ b/src/emu/debug/debugcpu.cpp
@@ -1388,6 +1388,20 @@ device_debug::device_debug(device_t &device)
device.interface(m_state);
device.interface(m_disasm);
+ // set up notifiers and clear the passthrough handlers
+ if (m_memory) {
+ int count = m_memory->max_space_count();
+ m_phr.resize(count, nullptr);
+ m_phw.resize(count, nullptr);
+ for (int i=0; i != count; i++)
+ if (m_memory->has_space(i)) {
+ address_space &space = m_memory->space(i);
+ m_notifiers.push_back(space.add_change_notifier([this, &space](read_or_write mode) { reinstall(space, mode); }));
+ }
+ else
+ m_notifiers.push_back(-1);
+ }
+
// set up state-related stuff
if (m_state != nullptr)
{
@@ -1470,6 +1484,53 @@ device_debug::~device_debug()
registerpoint_clear_all();
}
+void device_debug::write_tracking(address_space &space, offs_t address, u64 data)
+{
+ dasm_memory_access const newAccess(space.spacenum(), address, data, history_pc(0));
+ std::pair<std::set<dasm_memory_access>::iterator, bool> trackedAccess = m_track_mem_set.insert(newAccess);
+ if (!trackedAccess.second)
+ trackedAccess.first->m_pc = newAccess.m_pc;
+}
+
+void device_debug::reinstall(address_space &space, read_or_write mode)
+{
+ int id = space.spacenum();
+ if (u32(mode) & u32(read_or_write::READ))
+ {
+ if (m_phr[id])
+ m_phr[id]->remove();
+ if (!m_hotspots.empty())
+ switch (space.data_width())
+ {
+ case 8: m_phr[id] = space.install_read_tap(0, space.addrmask(), "hotspot", [this, &space](offs_t address, u8 &, u8 ) { hotspot_check(space, address); }, m_phr[id]); break;
+ case 16: m_phr[id] = space.install_read_tap(0, space.addrmask(), "hotspot", [this, &space](offs_t address, u16 &, u16) { hotspot_check(space, address); }, m_phr[id]); break;
+ case 32: m_phr[id] = space.install_read_tap(0, space.addrmask(), "hotspot", [this, &space](offs_t address, u32 &, u32) { hotspot_check(space, address); }, m_phr[id]); break;
+ case 64: m_phr[id] = space.install_read_tap(0, space.addrmask(), "hotspot", [this, &space](offs_t address, u64 &, u64) { hotspot_check(space, address); }, m_phr[id]); break;
+ }
+ }
+ if (u32(mode) & u32(read_or_write::WRITE))
+ {
+ if (m_phw[id])
+ m_phw[id]->remove();
+ if (m_track_mem)
+ switch (space.data_width())
+ {
+ case 8: m_phw[id] = space.install_read_tap(0, space.addrmask(), "track_mem", [this, &space](offs_t address, u8 &data, u8 ) { write_tracking(space, address, data); }, m_phw[id]); break;
+ case 16: m_phw[id] = space.install_read_tap(0, space.addrmask(), "track_mem", [this, &space](offs_t address, u16 &data, u16) { write_tracking(space, address, data); }, m_phw[id]); break;
+ case 32: m_phw[id] = space.install_read_tap(0, space.addrmask(), "track_mem", [this, &space](offs_t address, u32 &data, u32) { write_tracking(space, address, data); }, m_phw[id]); break;
+ case 64: m_phw[id] = space.install_read_tap(0, space.addrmask(), "track_mem", [this, &space](offs_t address, u64 &data, u64) { write_tracking(space, address, data); }, m_phw[id]); break;
+ }
+ }
+}
+
+void device_debug::reinstall_all(read_or_write mode)
+{
+ int count = m_memory->max_space_count();
+ for (int i=0; i < count; i++)
+ if (m_memory->has_space(i))
+ reinstall(m_memory->space(i), mode);
+}
+
//-------------------------------------------------
// start_hook - the scheduler calls this hook
// before beginning execution for the given device
@@ -1679,42 +1740,6 @@ void device_debug::instruction_hook(offs_t curpc)
//-------------------------------------------------
-// memory_read_hook - the memory system calls
-// this hook when watchpoints are enabled and a
-// memory read happens
-//-------------------------------------------------
-
-void device_debug::memory_read_hook(address_space &space, offs_t address, u64 mem_mask)
-{
- // check watchpoints
- watchpoint_check(space, WATCHPOINT_READ, address, 0, mem_mask);
-
- // check hotspots
- if (!m_hotspots.empty())
- hotspot_check(space, address);
-}
-
-
-//-------------------------------------------------
-// memory_write_hook - the memory system calls
-// this hook when watchpoints are enabled and a
-// memory write happens
-//-------------------------------------------------
-
-void device_debug::memory_write_hook(address_space &space, offs_t address, u64 data, u64 mem_mask)
-{
- if (m_track_mem)
- {
- dasm_memory_access const newAccess(space.spacenum(), address, data, history_pc(0));
- std::pair<std::set<dasm_memory_access>::iterator, bool> trackedAccess = m_track_mem_set.insert(newAccess);
- if (!trackedAccess.second)
- trackedAccess.first->m_pc = newAccess.m_pc;
- }
- watchpoint_check(space, WATCHPOINT_WRITE, address, data, mem_mask);
-}
-
-
-//-------------------------------------------------
// set_instruction_hook - set a hook to be
// called on each instruction for a given device
//-------------------------------------------------
@@ -2015,22 +2040,16 @@ void device_debug::breakpoint_enable_all(bool enable)
// returning its index
//-------------------------------------------------
-int device_debug::watchpoint_set(address_space &space, int type, offs_t address, offs_t length, const char *condition, const char *action)
+int device_debug::watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition, const char *action)
{
if (space.spacenum() >= int(m_wplist.size()))
- m_wplist.resize(space.spacenum()+1, nullptr);
+ m_wplist.resize(space.spacenum()+1);
// allocate a new one
u32 id = m_device.machine().debugger().cpu().get_watchpoint_index();
- watchpoint *wp = auto_alloc(m_device.machine(), watchpoint(this, m_symtable, id, space, type, address, length, condition, action));
-
- // hook it into our list
- wp->m_next = m_wplist[space.spacenum()];
- m_wplist[space.spacenum()] = wp;
+ m_wplist[space.spacenum()].emplace_back(std::make_unique<watchpoint>(this, m_symtable, id, space, type, address, length, condition, action));
- // update the flags and return the index
- watchpoint_update_flags(wp->m_space);
- return wp->m_index;
+ return id;
}
@@ -2042,17 +2061,15 @@ int device_debug::watchpoint_set(address_space &space, int type, offs_t address,
bool device_debug::watchpoint_clear(int index)
{
// scan the list to see if we own this breakpoint
- for (int spacenum = 0; spacenum < int(m_wplist.size()); ++spacenum)
- for (watchpoint **wp = &m_wplist[spacenum]; *wp != nullptr; wp = &(*wp)->m_next)
- if ((*wp)->m_index == index)
+ for (auto &wpl : m_wplist)
+ {
+ for (auto wpi = wpl.begin(); wpi != wpl.end(); wpi++)
+ if ((*wpi)->index() == index)
{
- watchpoint *deleteme = *wp;
- address_space &space = deleteme->m_space;
- *wp = deleteme->m_next;
- auto_free(m_device.machine(), deleteme);
- watchpoint_update_flags(space);
+ wpl.erase(wpi);
return true;
}
+ }
// we don't own it, return false
return false;
@@ -2065,10 +2082,8 @@ bool device_debug::watchpoint_clear(int index)
void device_debug::watchpoint_clear_all()
{
- // clear the head until we run out
- for (int spacenum = 0; spacenum < int(m_wplist.size()); ++spacenum)
- while (m_wplist[spacenum] != nullptr)
- watchpoint_clear(m_wplist[spacenum]->index());
+ for (auto &wpl : m_wplist)
+ wpl.clear();
}
@@ -2080,12 +2095,11 @@ void device_debug::watchpoint_clear_all()
bool device_debug::watchpoint_enable(int index, bool enable)
{
// scan the list to see if we own this watchpoint
- for (int spacenum = 0; spacenum < int(m_wplist.size()); ++spacenum)
- for (watchpoint *wp = m_wplist[spacenum]; wp != nullptr; wp = wp->next())
- if (wp->m_index == index)
+ for (auto &wpl : m_wplist)
+ for (auto &wp : wpl)
+ if (wp->index() == index)
{
- wp->m_enabled = enable;
- watchpoint_update_flags(wp->m_space);
+ wp->setEnabled(enable);
return true;
}
@@ -2102,9 +2116,9 @@ bool device_debug::watchpoint_enable(int index, bool enable)
void device_debug::watchpoint_enable_all(bool enable)
{
// apply the enable to all watchpoints we own
- for (int spacenum = 0; spacenum < int(m_wplist.size()); ++spacenum)
- for (watchpoint *wp = m_wplist[spacenum]; wp != nullptr; wp = wp->next())
- watchpoint_enable(wp->index(), enable);
+ for (auto &wpl : m_wplist)
+ for (auto &wp : wpl)
+ wp->setEnabled(enable);
}
@@ -2218,10 +2232,7 @@ void device_debug::hotspot_track(int numspots, int threshhold)
// fill in the info
m_hotspot_threshhold = threshhold;
}
-
- // update the watchpoint flags to include us
- if (m_memory != nullptr && m_memory->has_space(AS_PROGRAM))
- watchpoint_update_flags(m_memory->space(AS_PROGRAM));
+ reinstall_all(read_or_write::READ);
}
@@ -2596,139 +2607,10 @@ void device_debug::breakpoint_check(offs_t pc)
//-------------------------------------------------
-// watchpoint_update_flags - update the device's
-// watchpoint flags
-//-------------------------------------------------
-
-void device_debug::watchpoint_update_flags(address_space &space)
-{
- // if hotspots are enabled, turn on all reads
- bool enableread = false;
- if (!m_hotspots.empty())
- enableread = true;
-
- // see if there are any enabled breakpoints
- bool enablewrite = false;
- if (space.spacenum() < int(m_wplist.size()))
- for (watchpoint *wp = m_wplist[space.spacenum()]; wp != nullptr; wp = wp->m_next)
- if (wp->m_enabled)
- {
- if (wp->m_type & WATCHPOINT_READ)
- enableread = true;
- if (wp->m_type & WATCHPOINT_WRITE)
- enablewrite = true;
- }
-
- // push the flags out globally
- space.enable_read_watchpoints(enableread);
- space.enable_write_watchpoints(enablewrite);
-}
-
-
-//-------------------------------------------------
// watchpoint_check - check the watchpoints
// for a given CPU and address space
//-------------------------------------------------
-void device_debug::watchpoint_check(address_space& space, int type, offs_t address, u64 value_to_write, u64 mem_mask)
-{
- m_device.machine().debugger().cpu().watchpoint_check(space, type, address, value_to_write, mem_mask, m_wplist);
-}
-
-void debugger_cpu::watchpoint_check(address_space& space, int type, offs_t address, u64 value_to_write, u64 mem_mask, std::vector<device_debug::watchpoint *> &wplist)
-{
- // if we're within debugger code, don't stop
- if (m_within_instruction_hook || m_machine.side_effects_disabled())
- return;
-
- m_within_instruction_hook = true;
-
- // adjust address, size & value_to_write based on mem_mask.
- offs_t size = 0;
- if (mem_mask != 0)
- {
- int bus_size = space.data_width() / 8;
- int address_offset = 0;
-
- while (address_offset < bus_size && (mem_mask & 0xff) == 0)
- {
- address_offset++;
- value_to_write >>= 8;
- mem_mask >>= 8;
- }
-
- while (mem_mask != 0)
- {
- size++;
- mem_mask >>= 8;
- }
-
- // (1<<(size*8))-1 won't work when size is 8; let's just use a lut
- static const u64 masks[] = {
- 0x0U,
- 0xffU,
- 0xffffU,
- 0xffffffU,
- 0xffffffffU,
- 0xffffffffffU,
- 0xffffffffffffU,
- 0xffffffffffffffU,
- 0xffffffffffffffffU};
- value_to_write &= masks[size];
-
- if (space.endianness() == ENDIANNESS_LITTLE)
- address += address_offset;
- else
- address += bus_size - size - address_offset;
- }
-
- // if we are a write watchpoint, stash the value that will be written
- m_wpaddr = address;
- if (type & WATCHPOINT_WRITE)
- m_wpdata = value_to_write;
-
- // see if we match
- if (space.spacenum() < int(wplist.size()))
- for (device_debug::watchpoint *wp = wplist[space.spacenum()]; wp != nullptr; wp = wp->next())
- if (wp->hit(type, address, size))
- {
- // halt in the debugger by default
- m_execution_state = exec_state::STOPPED;
-
- // if we hit, evaluate the action
- if (!wp->action().empty())
- m_machine.debugger().console().execute_command(wp->action(), false);
-
- // print a notification, unless the action made us go again
- if (m_execution_state == exec_state::STOPPED)
- {
- static const char *const sizes[] =
- {
- "0bytes", "byte", "word", "3bytes", "dword", "5bytes", "6bytes", "7bytes", "qword"
- };
- offs_t pc = space.device().state().pcbase();
- std::string buffer;
-
- if (type & WATCHPOINT_WRITE)
- {
- buffer = string_format("Stopped at watchpoint %X writing %s to %08X (PC=%X)", wp->index(), sizes[size], address, pc);
- if (value_to_write >> 32)
- buffer.append(string_format(" (data=%X%08X)", u32(value_to_write >> 32), u32(value_to_write)));
- else
- buffer.append(string_format(" (data=%X)", u32(value_to_write)));
- }
- else
- buffer = string_format("Stopped at watchpoint %X reading %s from %08X (PC=%X)", wp->index(), sizes[size], address, pc);
- m_machine.debugger().console().printf("%s\n", buffer.c_str());
- space.device().debug()->compute_debug_flags();
- }
- break;
- }
-
- m_within_instruction_hook = false;
-}
-
-
//-------------------------------------------------
// hotspot_check - check for hotspots on a
// memory read access
@@ -2773,7 +2655,6 @@ void device_debug::hotspot_check(address_space &space, offs_t address)
}
}
-
//-------------------------------------------------
// get_current_pc - getter callback for a device's
// current instruction pointer
@@ -2917,59 +2798,293 @@ device_debug::watchpoint::watchpoint(device_debug* debugInterface,
symbol_table &symbols,
int index,
address_space &space,
- int type,
+ read_or_write type,
offs_t address,
offs_t length,
const char *condition,
const char *action)
: m_debugInterface(debugInterface),
- m_next(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_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 : "")
+{
+ 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);
+
+ offs_t 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>((rend + subamask + 1 - end) * unit_size);
+ else
+ emask &= ~make_bitmask<u64>((end - rend) * 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
+ {
+ 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)
+ {
+ if (u32(mode) & u32(read_or_write::READ))
+ m_phr->remove();
+ if (u32(mode) & u32(read_or_write::WRITE))
+ m_phw->remove();
+ install(mode);
+ }
+ });
+}
+
+device_debug::watchpoint::~watchpoint()
{
+ m_space.remove_change_notifier(m_notifier);
+}
+
+void device_debug::watchpoint::setEnabled(bool value)
+{
+ if (m_enabled != value)
+ {
+ m_enabled = value;
+ if (m_enabled)
+ install(read_or_write::READWRITE);
+ else
+ {
+ m_phr->remove();
+ m_phw->remove();
+ }
+ }
}
+void device_debug::watchpoint::install(read_or_write mode)
+{
+ 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;
-//-------------------------------------------------
-// hit - detect a hit
-//-------------------------------------------------
+ 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;
+ }
+}
-bool device_debug::watchpoint::hit(int type, offs_t address, int size)
+void device_debug::watchpoint::triggered(read_or_write type, offs_t address, u64 data, u64 mem_mask)
{
- // don't hit if disabled
- if (!m_enabled)
- return false;
+ auto &machine = m_debugInterface->m_device.machine();
+ auto &debug = machine.debugger();
- // must match the type
- if ((m_type & type) == 0)
- return false;
+ // if we're within debugger code, don't trigger
+ if (debug.cpu().within_instruction_hook() || machine.side_effects_disabled())
+ return;
- // must match our address
- if (address + size <= m_address || address >= m_address + m_length)
- return false;
+ // adjust address, size & value_to_write based on mem_mask.
+ offs_t size = 0;
+ offs_t 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
{
- return (m_condition.execute() != 0);
+ if (!m_condition.execute() != 0)
+ {
+ debug.cpu().set_within_instruction(false);
+ return;
+ }
}
catch (expression_error &)
{
- return false;
+ debug.cpu().set_within_instruction(false);
+ return;
}
}
- return true;
-}
+ // halt in the debugger by default
+ 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())
+ {
+ offs_t pc = m_space.device().state().pcbase();
+ std::string buffer;
+
+ buffer = string_format(type == read_or_write::READ ?
+ "Stopped at watchpoint %X reading %0*X from %08X (PC=%X)" :
+ "Stopped at watchpoint %X writing %0*X to %08X (PC=%X)",
+ m_index,
+ size * unit_size / 4,
+ data,
+ address,
+ pc);
+ debug.console().printf("%s\n", buffer);
+ m_debugInterface->compute_debug_flags();
+ }
+
+ debug.cpu().set_within_instruction(false);
+}
//**************************************************************************
// DEBUG REGISTERPOINT