summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/debug')
-rw-r--r--src/emu/debug/debugbuf.cpp1379
-rw-r--r--src/emu/debug/debugbuf.h93
-rw-r--r--src/emu/debug/debugcmd.cpp366
-rw-r--r--src/emu/debug/debugcon.cpp8
-rw-r--r--src/emu/debug/debugcon.h2
-rw-r--r--src/emu/debug/debugcpu.cpp145
-rw-r--r--src/emu/debug/debugcpu.h1
-rw-r--r--src/emu/debug/dvdisasm.cpp514
-rw-r--r--src/emu/debug/dvdisasm.h59
-rw-r--r--src/emu/debug/dvmemory.cpp7
10 files changed, 1965 insertions, 609 deletions
diff --git a/src/emu/debug/debugbuf.cpp b/src/emu/debug/debugbuf.cpp
new file mode 100644
index 00000000000..779b91f84ac
--- /dev/null
+++ b/src/emu/debug/debugbuf.cpp
@@ -0,0 +1,1379 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Buffering interface for the disassembly windows
+
+#include "emu.h"
+#include "debugbuf.h"
+
+debug_disasm_buffer::debug_data_buffer::debug_data_buffer(util::disasm_interface *intf) : m_intf(intf)
+{
+ m_space = nullptr;
+ m_back = nullptr;
+ m_opcode = true;
+ m_lstart = m_lend = 0;
+ m_wrapped = false;
+}
+
+bool debug_disasm_buffer::debug_data_buffer::active() const
+{
+ return m_space || m_back;
+}
+
+void debug_disasm_buffer::debug_data_buffer::set_source(address_space &space)
+{
+ m_space = &space;
+ setup_methods();
+}
+
+void debug_disasm_buffer::debug_data_buffer::set_source(debug_data_buffer &back, bool opcode)
+{
+ m_back = &back;
+ m_opcode = opcode;
+ setup_methods();
+}
+
+u8 debug_disasm_buffer::debug_data_buffer::r8 (offs_t pc) const
+{
+ return m_do_r8(pc & m_pc_mask);
+}
+
+u16 debug_disasm_buffer::debug_data_buffer::r16(offs_t pc) const
+{
+ return m_do_r16(pc & m_pc_mask);
+}
+
+u32 debug_disasm_buffer::debug_data_buffer::r32(offs_t pc) const
+{
+ return m_do_r32(pc & m_pc_mask);
+}
+
+u64 debug_disasm_buffer::debug_data_buffer::r64(offs_t pc) const
+{
+ return m_do_r64(pc & m_pc_mask);
+}
+
+address_space *debug_disasm_buffer::debug_data_buffer::get_underlying_space() const
+{
+ return m_space;
+}
+
+void debug_disasm_buffer::debug_data_buffer::fill(offs_t lstart, offs_t size) const
+{
+ offs_t lend = (lstart + size) & m_pc_mask;
+ if(m_page_mask) {
+ if((lstart ^ lend) & ~m_page_mask) {
+ lstart = lstart & ~m_page_mask;
+ lend = (((lend - 1) | m_page_mask) + 1) & m_pc_mask;
+ }
+ }
+
+ if(!m_buffer.empty()) {
+ if(m_lstart == m_lend)
+ return;
+ if(m_wrapped) {
+ if(lstart >= m_lstart && (lend > m_lstart || lend <= m_lend))
+ return;
+ if(lstart < m_lend && lend <= m_lend)
+ return;
+ } else {
+ if(lstart < lend && lstart >= m_lstart && lend <= m_lend)
+ return;
+ }
+ }
+
+ if(m_buffer.empty()) {
+ m_lstart = lstart;
+ m_lend = lend;
+ m_wrapped = lend < lstart;
+ offs_t size = m_pc_delta_to_bytes((lend - lstart) & m_pc_mask);
+ m_buffer.resize(size);
+ m_do_fill(lstart, lend);
+
+ } else {
+ offs_t n_lstart, n_lend;
+ if(lstart > lend) {
+ if(m_wrapped) {
+ // Old is wrapped, new is wrapped, just extend
+ n_lstart = std::min(m_lstart, lstart);
+ n_lend = std::max(m_lend, lend);
+ } else {
+ // Old is unwrapped, new is wrapped. Reduce the amount of "useless" data.
+ offs_t gap_post = m_lend >= lstart ? 0 : lstart - m_lend;
+ offs_t gap_pre = m_lstart <= lend ? 0 : m_lstart - lend;
+ if(gap_post < gap_pre) {
+ // extend the old one end until it reaches the new one
+ n_lstart = std::min(m_lstart, lstart);
+ n_lend = lend;
+ } else {
+ // extend the old one start until it reaches the new one
+ n_lstart = lstart;
+ n_lend = std::max(m_lend, lend);
+ }
+ m_wrapped = true;
+ }
+ } else if(m_wrapped) {
+ // Old is wrapped, new is unwrapped. Reduce the amount of "useless" data.
+ offs_t gap_post = m_lend >= lstart ? 0 : lstart - m_lend;
+ offs_t gap_pre = m_lstart <= lend ? 0 : m_lstart - lend;
+ if(gap_post < gap_pre) {
+ // extend the old one end until it reaches the new one
+ n_lstart = m_lstart;
+ n_lend = lend;
+ } else {
+ // extend the old one start until it reaches the new one
+ n_lstart = lstart;
+ n_lend = m_lend;
+ }
+ } else {
+ // Both are unwrapped, decide whether to wrap.
+ // If there's overlap, don't wrap, just extend
+ if(lend >= m_lstart && lstart < m_lend) {
+ n_lstart = std::min(m_lstart, lstart);
+ n_lend = std::max(m_lend, lend);
+ } else {
+ // If there's no overlap, compute the gap with wrapping or without
+ offs_t gap_unwrapped = lstart > m_lstart ? lstart - m_lend : m_lstart - lend;
+ offs_t gap_wrapped = lstart > m_lstart ? (m_lstart - lend) & m_pc_mask : (lstart - m_lend) & m_pc_mask;
+ if(gap_unwrapped < gap_wrapped) {
+ n_lstart = std::min(m_lstart, lstart);
+ n_lend = std::max(m_lend, lend);
+ } else {
+ n_lstart = std::max(m_lstart, lstart);
+ n_lend = std::min(m_lend, lend);
+ m_wrapped = true;
+ }
+ }
+ }
+
+ if(n_lstart != m_lstart) {
+ offs_t size = m_pc_delta_to_bytes((m_lstart - n_lstart) & m_pc_mask);
+ m_buffer.insert(m_buffer.begin(), size, 0);
+ offs_t old_lstart = m_lstart;
+ m_lstart = n_lstart;
+ m_do_fill(m_lstart, old_lstart);
+ }
+ if(n_lend != m_lend) {
+ offs_t size = m_pc_delta_to_bytes((n_lend - m_lstart) & m_pc_mask);
+ m_buffer.resize(size);
+ offs_t old_lend = m_lend;
+ m_lend = n_lend;
+ m_do_fill(old_lend, m_lend);
+ }
+ }
+}
+
+std::string debug_disasm_buffer::debug_data_buffer::data_to_string(offs_t pc, offs_t size) const
+{
+ return m_data_to_string(pc, size);
+}
+
+void debug_disasm_buffer::debug_data_buffer::data_get(offs_t pc, offs_t size, std::vector<u8> &data) const
+{
+ return m_data_get(pc, size, data);
+}
+
+void debug_disasm_buffer::debug_data_buffer::setup_methods()
+{
+ address_space *space = m_space ? m_space : m_back->get_underlying_space();
+ int shift = space->addrbus_shift();
+ int alignment = m_intf->opcode_alignment();
+ endianness_t endian = space->endianness();
+
+ m_pc_mask = space->logaddrmask();
+
+ if(m_intf->interface_flags() & util::disasm_interface::PAGED)
+ m_page_mask = (1 << m_intf->page_address_bits()) - 1;
+ else
+ m_page_mask = 0;
+
+ // Define the byte counter
+ switch(shift) {
+ case -3: m_pc_delta_to_bytes = [](offs_t delta) { return delta << 3; }; break;
+ case -2: m_pc_delta_to_bytes = [](offs_t delta) { return delta << 2; }; break;
+ case -1: m_pc_delta_to_bytes = [](offs_t delta) { return delta << 1; }; break;
+ case 0: m_pc_delta_to_bytes = [](offs_t delta) { return delta; }; break;
+ case 3: m_pc_delta_to_bytes = [](offs_t delta) { return delta >> 3; }; break;
+ default: throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer::setup_methods: Abnormal address buf shift\n");
+ }
+
+ // Define the filler
+ if(m_space) {
+ // get the data from given space
+ if(m_intf->interface_flags() & util::disasm_interface::NONLINEAR_PC) {
+ switch(shift) {
+ case -1:
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ auto dis = m_space->machine().disable_side_effect();
+ u16 *dest = get_ptr<u16>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) {
+ offs_t tpc = m_intf->pc_linear_to_real(lpc);
+ if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc))
+ *dest++ = m_space->read_word(tpc);
+ else
+ *dest++ = 0;
+ }
+ };
+ break;
+ case 0:
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ auto dis = m_space->machine().disable_side_effect();
+ u8 *dest = get_ptr<u8>(lstart);
+ u32 steps = 0;
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) {
+ offs_t tpc = m_intf->pc_linear_to_real(lpc);
+ if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc))
+ *dest++ = m_space->read_byte(tpc);
+ else
+ *dest++ = 0;
+ steps++;
+ }
+ };
+ break;
+ }
+
+ } else {
+ switch(shift) {
+ case -3: // bus granularity 64
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ auto dis = m_space->machine().disable_side_effect();
+ u64 *dest = get_ptr<u64>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) {
+ offs_t tpc = lpc;
+ if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc))
+ *dest++ = m_space->read_qword(tpc);
+ else
+ *dest++ = 0;
+ }
+ };
+ break;
+
+ case -2: // bus granularity 32
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ auto dis = m_space->machine().disable_side_effect();
+ u32 *dest = get_ptr<u32>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) {
+ offs_t tpc = lpc;
+ if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc))
+ *dest++ = m_space->read_dword(tpc);
+ else
+ *dest++ = 0;
+ }
+ };
+ break;
+
+ case -1: // bus granularity 16
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ auto dis = m_space->machine().disable_side_effect();
+ u16 *dest = get_ptr<u16>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) {
+ offs_t tpc = lpc;
+ if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc))
+ *dest++ = m_space->read_word(tpc);
+ else
+ *dest++ = 0;
+ }
+ };
+ break;
+
+ case 0: // bus granularity 8
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ auto dis = m_space->machine().disable_side_effect();
+ u8 *dest = get_ptr<u8>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) {
+ offs_t tpc = lpc;
+ if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc))
+ *dest++ = m_space->read_byte(tpc);
+ else
+ *dest++ = 0;
+ }
+ };
+ break;
+
+ case 3: // bus granularity 1, stored as u16
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ auto dis = m_space->machine().disable_side_effect();
+ u16 *dest = reinterpret_cast<u16 *>(&m_buffer[0]) + ((lstart - m_lstart) >> 4);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 0x10) & m_pc_mask) {
+ offs_t tpc = lpc;
+ if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc))
+ *dest++ = m_space->read_word(tpc);
+ else
+ *dest++ = 0;
+ }
+ };
+ break;
+ }
+ }
+ } else {
+ // get the data from a back buffer and decrypt it through the device
+ // size chosen is alignment * granularity
+ assert(!(m_intf->interface_flags() & util::disasm_interface::NONLINEAR_PC));
+
+ switch(shift) {
+ case -3: // bus granularity 64, endianness irrelevant
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u64 *dest = get_ptr<u64>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask)
+ *dest++ = m_intf->decrypt64(m_back->r64(lpc), lpc, m_opcode);
+ };
+ break;
+
+ case -2: // bus granularity 32
+ switch(alignment) {
+ case 1: // bus granularity 32, alignment 32, endianness irrelevant
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u32 *dest = get_ptr<u32>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask)
+ *dest++ = m_intf->decrypt32(m_back->r32(lpc), lpc, m_opcode);
+ };
+ break;
+
+ case 2: // bus granularity 32, alignment 64
+ switch(endian) {
+ case ENDIANNESS_LITTLE: // bus granularity 32, alignment 64, little endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u32 *dest = get_ptr<u32>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 2) & m_pc_mask) {
+ u64 val = m_intf->decrypt64(m_back->r64(lpc), lpc, m_opcode);
+ *dest++ = val;
+ *dest++ = val >> 32;
+ }
+ };
+ break;
+
+ case ENDIANNESS_BIG: // bus granularity 32, bus width 64, big endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u32 *dest = get_ptr<u32>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 2) & m_pc_mask) {
+ u64 val = m_intf->decrypt64(m_back->r64(lpc), lpc, m_opcode);
+ *dest++ = val >> 32;
+ *dest++ = val;
+ }
+ };
+ break;
+ }
+ break;
+ }
+ break;
+
+ case -1: // bus granularity 16
+ switch(alignment) {
+ case 1: // bus granularity 16, alignment 16, endianness irrelevant
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u16 *dest = get_ptr<u16>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask)
+ *dest++ = m_intf->decrypt16(m_back->r16(lpc), lpc, m_opcode);
+ };
+ break;
+
+ case 2: // bus granularity 16, alignment 32
+ switch(endian) {
+ case ENDIANNESS_LITTLE: // bus granularity 16, alignment 32, little endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u16 *dest = get_ptr<u16>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 2) & m_pc_mask) {
+ u32 val = m_intf->decrypt32(m_back->r32(lpc), lpc, m_opcode);
+ *dest++ = val;
+ *dest++ = val >> 16;
+ }
+ };
+ break;
+
+ case ENDIANNESS_BIG: // bus granularity 16, alignment 32, big endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u16 *dest = get_ptr<u16>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 2) & m_pc_mask) {
+ u32 val = m_intf->decrypt32(m_back->r32(lpc), lpc, m_opcode);
+ *dest++ = val >> 16;
+ *dest++ = val;
+ }
+ };
+ break;
+ }
+ break;
+
+ case 4: // bus granularity 16, alignment 64
+ switch(endian) {
+ case ENDIANNESS_LITTLE: // bus granularity 16, alignment 64, little endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u16 *dest = get_ptr<u16>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 4) & m_pc_mask) {
+ u64 val = m_intf->decrypt64(m_back->r64(lpc), lpc, m_opcode);
+ *dest++ = val;
+ *dest++ = val >> 16;
+ *dest++ = val >> 32;
+ *dest++ = val >> 48;
+ }
+ };
+ break;
+
+ case ENDIANNESS_BIG: // bus granularity 16, alignment 64, big endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u16 *dest = get_ptr<u16>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 4) & m_pc_mask) {
+ u64 val = m_intf->decrypt64(m_back->r64(lpc), lpc, m_opcode);
+ *dest++ = val >> 48;
+ *dest++ = val >> 32;
+ *dest++ = val >> 16;
+ *dest++ = val;
+ }
+ };
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0: // bus granularity 8
+ switch(alignment) {
+ case 1: // bus granularity 8, alignment 8, endianness irrelevant
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u8 *dest = get_ptr<u8>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask)
+ *dest++ = m_intf->decrypt8(m_back->r8(lpc), lpc, m_opcode);
+ };
+ break;
+
+ case 2: // bus granularity 8, alignment 16
+ switch(endian) {
+ case ENDIANNESS_LITTLE: // bus granularity 8, alignment 16, little endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u8 *dest = get_ptr<u8>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 2) & m_pc_mask) {
+ u16 val = m_intf->decrypt16(m_back->r16(lpc), lpc, m_opcode);
+ *dest++ = val;
+ *dest++ = val >> 8;
+ }
+ };
+ break;
+
+ case ENDIANNESS_BIG: // bus granularity 16, alignment 16, big endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u8 *dest = get_ptr<u8>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 2) & m_pc_mask) {
+ u16 val = m_intf->decrypt16(m_back->r16(lpc), lpc, m_opcode);
+ *dest++ = val >> 8;
+ *dest++ = val;
+ }
+ };
+ break;
+ }
+ break;
+
+ case 4: // bus granularity 8, alignment 32
+ switch(endian) {
+ case ENDIANNESS_LITTLE: // bus granularity 8, alignment 16, little endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u8 *dest = get_ptr<u8>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 4) & m_pc_mask) {
+ u32 val = m_intf->decrypt32(m_back->r32(lpc), lpc, m_opcode);
+ *dest++ = val;
+ *dest++ = val >> 8;
+ *dest++ = val >> 16;
+ *dest++ = val >> 24;
+ }
+ };
+ break;
+
+ case ENDIANNESS_BIG: // bus granularity 16, alignment 32, big endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u8 *dest = get_ptr<u8>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 4) & m_pc_mask) {
+ u32 val = m_intf->decrypt32(m_back->r32(lpc), lpc, m_opcode);
+ *dest++ = val >> 24;
+ *dest++ = val >> 16;
+ *dest++ = val >> 8;
+ *dest++ = val;
+ }
+ };
+ break;
+ }
+ break;
+
+
+ case 8: // bus granularity 8, alignment 64
+ switch(endian) {
+ case ENDIANNESS_LITTLE: // bus granularity 8, alignment 64, little endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u8 *dest = get_ptr<u8>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 8) & m_pc_mask) {
+ u64 val = m_intf->decrypt64(m_back->r64(lpc), lpc, m_opcode);
+ *dest++ = val;
+ *dest++ = val >> 8;
+ *dest++ = val >> 16;
+ *dest++ = val >> 24;
+ *dest++ = val >> 32;
+ *dest++ = val >> 40;
+ *dest++ = val >> 48;
+ *dest++ = val >> 56;
+ }
+ };
+ break;
+
+ case ENDIANNESS_BIG: // bus granularity 8, alignment 64, big endian
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u8 *dest = get_ptr<u8>(lstart);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 2) & m_pc_mask) {
+ u64 val = m_intf->decrypt64(m_back->r64(lpc), lpc, m_opcode);
+ *dest++ = val >> 56;
+ *dest++ = val >> 48;
+ *dest++ = val >> 40;
+ *dest++ = val >> 32;
+ *dest++ = val >> 24;
+ *dest++ = val >> 16;
+ *dest++ = val >> 8;
+ *dest++ = val;
+ }
+ };
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 3: // bus granularity 1, alignment 16, little endian (bit addressing, stored as u16, tms3401x)
+ assert(alignment == 16);
+ assert(endian == ENDIANNESS_LITTLE);
+ m_do_fill = [this](offs_t lstart, offs_t lend) {
+ u16 *dest = reinterpret_cast<u16 *>(&m_buffer[0]) + ((lstart - m_lstart) >> 4);
+ for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 0x10) & m_pc_mask)
+ *dest++ = m_intf->decrypt16(m_back->r16(lpc), lpc, m_opcode);
+ };
+ break;
+ }
+ }
+
+ // Define the accessors
+ if(m_intf->interface_flags() & util::disasm_interface::NONLINEAR_PC) {
+ switch(shift) {
+ case -1:
+ m_do_r8 = [](offs_t pc) -> u8 { throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer: r8 access on 16-bits granularity bus\n"); };
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 1);
+ const u16 *src = get_ptr<u16>(lpc);
+ return src[0];
+ };
+
+ switch(endian) {
+ case ENDIANNESS_LITTLE:
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 2);
+ u32 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u16>(lpc) << (j*16);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 4);
+ u64 r = 0;
+ for(int j=0; j != 4; j++) {
+ r |= u64(get<u16>(lpc)) << (j*16);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ break;
+
+ case ENDIANNESS_BIG:
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 2);
+ u32 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u16>(lpc) << ((1-j)*16);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 4);
+ u64 r = 0;
+ for(int j=0; j != 4; j++) {
+ r |= u64(get<u16>(lpc)) << ((3-j)*16);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ break;
+ }
+ break;
+
+ case 0:
+ m_do_r8 = [this](offs_t pc) -> u8 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 1);
+ const u8 *src = get_ptr<u8>(lpc);
+ return src[0];
+ };
+
+ switch(endian) {
+ case ENDIANNESS_LITTLE:
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 2);
+ u16 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u8>(lpc) << (j*8);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 4);
+ u32 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u8>(lpc) << (j*8);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 8);
+ u64 r = 0;
+ for(int j=0; j != 8; j++) {
+ r |= u64(get<u8>(lpc)) << (j*8);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ break;
+
+ case ENDIANNESS_BIG:
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 2);
+ u16 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u8>(lpc) << ((1-j)*8);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 4);
+ u32 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u8>(lpc) << ((3-j)*8);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ fill(lpc, 8);
+ u64 r = 0;
+ for(int j=0; j != 8; j++) {
+ r |= u64(get<u8>(lpc)) << ((7-j)*8);
+ lpc = (lpc & ~m_page_mask) | ((lpc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ break;
+ }
+ break;
+ }
+ } else {
+ switch(shift) {
+ case -3: // bus granularity 64
+ m_do_r8 = [](offs_t pc) -> u8 { throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer: r8 access on 64-bits granularity bus\n"); };
+ m_do_r16 = [](offs_t pc) -> u16 { throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer: r16 access on 64-bits granularity bus\n"); };
+ m_do_r32 = [](offs_t pc) -> u32 { throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer: r32 access on 64-bits granularity bus\n"); };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 1);
+ const u64 *src = get_ptr<u64>(pc);
+ return src[0];
+ };
+ break;
+
+ case -2: // bus granularity 32
+ m_do_r8 = [](offs_t pc) -> u8 { throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer: r8 access on 32-bits granularity bus\n"); };
+ m_do_r16 = [](offs_t pc) -> u16 { throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer: r16 access on 32-bits granularity bus\n"); };
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 1);
+ const u32 *src = get_ptr<u32>(pc);
+ return src[0];
+ };
+ switch(endian) {
+ case ENDIANNESS_LITTLE:
+ if(m_page_mask) {
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 2);
+ u64 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= u64(get<u32>(pc)) << (j*32);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ } else {
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 2);
+ const u32 *src = get_ptr<u32>(pc);
+ return src[0] | (u64(src[1]) << 32);
+ };
+ }
+ break;
+ case ENDIANNESS_BIG:
+ if(m_page_mask) {
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 2);
+ u64 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= u64(get<u32>(pc)) << ((1-j)*32);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ } else {
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 2);
+ const u32 *src = get_ptr<u32>(pc);
+ return (u64(src[0]) << 32) | u64(src[1]);
+ };
+ }
+ break;
+ }
+ break;
+
+ case -1: // bus granularity 16
+ m_do_r8 = [](offs_t pc) -> u8 { throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer: r8 access on 16-bits granularity bus\n"); };
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ fill(pc, 1);
+ const u16 *src = get_ptr<u16>(pc);
+ return src[0];
+ };
+ switch(endian) {
+ case ENDIANNESS_LITTLE:
+ if(m_page_mask) {
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 2);
+ u32 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u16>(pc) << (j*16);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 4);
+ u64 r = 0;
+ for(int j=0; j != 4; j++) {
+ r |= u64(get<u16>(pc)) << (j*16);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ } else {
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 2);
+ const u16 *src = get_ptr<u16>(pc);
+ return src[0] | (src[1] << 16);
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 4);
+ const u16 *src = get_ptr<u16>(pc);
+ return src[0] | (src[1] << 16) | (u64(src[2]) << 32) | (u64(src[3]) << 48);
+ };
+ }
+ break;
+ case ENDIANNESS_BIG:
+ if(m_page_mask) {
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 2);
+ u32 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u16>(pc) << ((1-j)*16);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 4);
+ u64 r = 0;
+ for(int j=0; j != 4; j++) {
+ r |= u64(get<u16>(pc)) << ((3-j)*16);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ } else {
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 2);
+ const u16 *src = get_ptr<u16>(pc);
+ return (src[0] << 16) | src[1];
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 4);
+ const u16 *src = get_ptr<u16>(pc);
+ return (u64(src[0]) << 48) | (u64(src[1]) << 32) | u32(src[2] << 16) | src[3];
+ };
+ }
+ break;
+ }
+ break;
+
+ case 0: // bus granularity 8
+ m_do_r8 = [this](offs_t pc) -> u8 {
+ fill(pc, 1);
+ const u8 *src = get_ptr<u8>(pc);
+ return src[0];
+ };
+ switch(endian) {
+ case ENDIANNESS_LITTLE:
+ if(m_page_mask) {
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ fill(pc, 2);
+ u16 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u8>(pc) << (j*8);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 4);
+ u32 r = 0;
+ for(int j=0; j != 4; j++) {
+ r |= get<u8>(pc) << (j*8);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 8);
+ u64 r = 0;
+ for(int j=0; j != 8; j++) {
+ r |= u64(get<u8>(pc)) << (j*8);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ } else {
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ fill(pc, 2);
+ const u8 *src = get_ptr<u8>(pc);
+ return src[0] | (src[1] << 8);
+ };
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 4);
+ const u8 *src = get_ptr<u8>(pc);
+ return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 8);
+ const u8 *src = get_ptr<u8>(pc);
+ return src[0] | (src[1] << 8) | (src[2] << 16) | u32(src[3] << 24) |
+ (u64(src[4]) << 32) | (u64(src[5]) << 40) | (u64(src[6]) << 48) | (u64(src[7]) << 56);
+ };
+ }
+ break;
+ case ENDIANNESS_BIG:
+ if(m_page_mask) {
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ fill(pc, 2);
+ u16 r = 0;
+ for(int j=0; j != 2; j++) {
+ r |= get<u8>(pc) << ((1-j)*8);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 4);
+ u32 r = 0;
+ for(int j=0; j != 4; j++) {
+ r |= get<u8>(pc) << ((3-j)*8);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 8);
+ u64 r = 0;
+ for(int j=0; j != 8; j++) {
+ r |= u64(get<u8>(pc)) << ((7-j)*8);
+ pc = (pc & ~m_page_mask) | ((pc + 1) & m_page_mask);
+ }
+ return r;
+ };
+ } else {
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ fill(pc, 2);
+ const u8 *src = get_ptr<u8>(pc);
+ return (src[0] << 8) | src[1];
+ };
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 4);
+ const u8 *src = get_ptr<u8>(pc);
+ return (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 8);
+ const u8 *src = get_ptr<u8>(pc);
+ return (u64(src[0]) << 56) | (u64(src[1]) << 32) | (u64(src[2]) << 40) | (u64(src[3]) << 32) |
+ (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
+ };
+ }
+ break;
+ }
+ break;
+
+ case 3: // bus granularity 1, u16 storage, no paging
+ assert(endian == ENDIANNESS_LITTLE);
+ assert(!m_page_mask);
+ m_do_r8 = [](offs_t pc) -> u8 { throw emu_fatalerror("debug_disasm_buffer::debug_data_buffer: r8 access on 1-bit/16 wide granularity bus\n"); };
+ m_do_r16 = [this](offs_t pc) -> u16 {
+ fill(pc, 16);
+ const u16 *src = reinterpret_cast<u16 *>(&m_buffer[0]) + ((pc - m_lstart) >> 4);
+ return src[0];
+ };
+ m_do_r32 = [this](offs_t pc) -> u32 {
+ fill(pc, 32);
+ const u16 *src = reinterpret_cast<u16 *>(&m_buffer[0]) + ((pc - m_lstart) >> 4);
+ return src[0] | (src[1] << 16);
+ };
+ m_do_r64 = [this](offs_t pc) -> u64 {
+ fill(pc, 64);
+ const u16 *src = reinterpret_cast<u16 *>(&m_buffer[0]) + ((pc - m_lstart) >> 4);
+ return src[0] | (src[1] << 16) | (u64(src[2]) << 32) | (u64(src[3]) << 48);
+ };
+ break;
+ }
+ }
+
+ // Define the data -> string conversion
+ switch(shift) {
+ case -3:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%016x", r64(pc));
+ pc = m_next_pc_wrap(pc, 1);
+ }
+ return out.str();
+ };
+ break;
+
+ case -2:
+ switch(alignment) {
+ case 1:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%08x", r32(pc));
+ pc = m_next_pc_wrap(pc, 1);
+ }
+ return out.str();
+ };
+ break;
+
+ case 2:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i += 2) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%016x", r64(pc));
+ pc = m_next_pc_wrap(pc, 2);
+ }
+ return out.str();
+ };
+ break;
+ }
+ break;
+
+ case -1:
+ switch(alignment) {
+ case 1:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%04x", r16(pc));
+ pc = m_next_pc_wrap(pc, 1);
+ }
+ return out.str();
+ };
+ break;
+
+ case 2:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i += 2) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%08x", r32(pc));
+ pc = m_next_pc_wrap(pc, 2);
+ }
+ return out.str();
+ };
+ break;
+
+ case 4:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i += 4) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%016x", r64(pc));
+ pc = m_next_pc_wrap(pc, 4);
+ }
+ return out.str();
+ };
+ break;
+ }
+ break;
+
+ case 0:
+ switch(alignment) {
+ case 1:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%02x", r8(pc));
+ pc = m_next_pc_wrap(pc, 1);
+ }
+ return out.str();
+ };
+ break;
+
+ case 2:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i += 2) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%04x", r16(pc));
+ pc = m_next_pc_wrap(pc, 2);
+ }
+ return out.str();
+ };
+ break;
+
+ case 4:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i += 4) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%08x", r32(pc));
+ pc = m_next_pc_wrap(pc, 4);
+ }
+ return out.str();
+ };
+ break;
+
+ case 8:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i += 8) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%016x", r64(pc));
+ pc = m_next_pc_wrap(pc, 8);
+ }
+ return out.str();
+ };
+ break;
+ }
+ break;
+
+ case 3:
+ m_data_to_string = [this](offs_t pc, offs_t size) {
+ std::ostringstream out;
+ for(offs_t i=0; i != size; i += 16) {
+ if(i)
+ out << ' ';
+ util::stream_format(out, "%04x", r16(pc));
+ pc = m_next_pc_wrap(pc, 16);
+ }
+ return out.str();
+ };
+ break;
+ }
+
+ // Define the data extraction
+ switch(shift) {
+ case -3:
+ m_data_get = [this](offs_t pc, offs_t size, std::vector<u8> &data) {
+ for(offs_t i=0; i != size; i++) {
+ u64 r = r64(pc);
+ for(int j=0; j != 8; j++)
+ data.push_back(r >> (8*j));
+ pc = m_next_pc_wrap(pc, 1);
+ }
+ };
+ break;
+
+ case -2:
+ m_data_get = [this](offs_t pc, offs_t size, std::vector<u8> &data) {
+ for(offs_t i=0; i != size; i++) {
+ u32 r = r32(pc);
+ for(int j=0; j != 4; j++)
+ data.push_back(r >> (8*j));
+ pc = m_next_pc_wrap(pc, 1);
+ }
+ };
+ break;
+
+ case -1:
+ m_data_get = [this](offs_t pc, offs_t size, std::vector<u8> &data) {
+ for(offs_t i=0; i != size; i++) {
+ u16 r = r16(pc);
+ for(int j=0; j != 2; j++)
+ data.push_back(r >> (8*j));
+ pc = m_next_pc_wrap(pc, 1);
+ }
+ };
+ break;
+
+ case 0:
+ m_data_get = [this](offs_t pc, offs_t size, std::vector<u8> &data) {
+ for(offs_t i=0; i != size; i++) {
+ data.push_back(r8(pc));
+ pc = m_next_pc_wrap(pc, 1);
+ }
+ };
+ break;
+
+ case 3:
+ m_data_get = [this](offs_t pc, offs_t size, std::vector<u8> &data) {
+ for(offs_t i=0; i != size >> 4; i++) {
+ u16 r = r16(pc);
+ for(int j=0; j != 2; j++)
+ data.push_back(r >> (8*j));
+ pc = m_next_pc_wrap(pc, 16);
+ }
+ };
+ break;
+ }
+
+ // Wrapped next pc computation
+ if(m_intf->interface_flags() & util::disasm_interface::NONLINEAR_PC) {
+ // lfsr pc is always paged
+ m_next_pc_wrap = [this](offs_t pc, offs_t size) {
+ offs_t lpc = m_intf->pc_real_to_linear(pc);
+ offs_t lpce = (lpc & ~m_page_mask) | ((lpc + size) & m_page_mask);
+ return m_intf->pc_linear_to_real(lpce);
+ };
+ } else if(m_intf->interface_flags() & util::disasm_interface::PAGED) {
+ m_next_pc_wrap = [this](offs_t pc, offs_t size) {
+ offs_t pce = (pc & ~m_page_mask) | ((pc + size) & m_page_mask);
+ return pce;
+ };
+ } else {
+ m_next_pc_wrap = [this](offs_t pc, offs_t size) {
+ return (pc + size) & m_pc_mask;
+ };
+ }
+}
+
+debug_disasm_buffer::debug_disasm_buffer(device_t &device) :
+ m_buf_raw(dynamic_cast<device_disasm_interface &>(device).get_disassembler()),
+ m_buf_opcodes(dynamic_cast<device_disasm_interface &>(device).get_disassembler()),
+ m_buf_params(dynamic_cast<device_disasm_interface &>(device).get_disassembler())
+{
+ m_dintf = dynamic_cast<device_disasm_interface *>(&device)->get_disassembler();
+ m_mintf = dynamic_cast<device_memory_interface *>(&device);
+
+ m_flags = m_dintf->interface_flags();
+
+ if(m_flags & util::disasm_interface::INTERNAL_DECRYPTION) {
+ m_buf_raw.set_source(m_mintf->space(AS_PROGRAM));
+ m_buf_opcodes.set_source(m_buf_raw, true);
+ if((m_flags & util::disasm_interface::SPLIT_DECRYPTION) == util::disasm_interface::SPLIT_DECRYPTION)
+ m_buf_params.set_source(m_buf_raw, false);
+ } else {
+ if(m_mintf->has_space(AS_OPCODES)) {
+ m_buf_opcodes.set_source(m_mintf->space(AS_OPCODES));
+ m_buf_params.set_source(m_mintf->space(AS_PROGRAM));
+ } else
+ m_buf_opcodes.set_source(m_mintf->space(AS_PROGRAM));
+ }
+
+ m_pc_mask = m_mintf->space(AS_PROGRAM).logaddrmask();
+
+ if(m_flags & util::disasm_interface::PAGED)
+ m_page_mask = (1 << m_dintf->page_address_bits()) - 1;
+ else
+ m_page_mask = 0;
+
+ // Next pc computation
+ if(m_flags & util::disasm_interface::NONLINEAR_PC) {
+ // lfsr pc is always paged
+ m_next_pc = [this](offs_t pc, offs_t size) {
+ offs_t lpc = m_dintf->pc_real_to_linear(pc);
+ offs_t lpce = lpc + size;
+ if((lpc ^ lpce) & ~m_page_mask)
+ lpce = (lpc | m_page_mask) + 1;
+ lpce &= m_pc_mask;
+ return m_dintf->pc_linear_to_real(lpce);
+ };
+ m_next_pc_wrap = [this](offs_t pc, offs_t size) {
+ offs_t lpc = m_dintf->pc_real_to_linear(pc);
+ offs_t lpce = (lpc & ~m_page_mask) | ((lpc + size) & m_page_mask);
+ return m_dintf->pc_linear_to_real(lpce);
+ };
+
+ } else if(m_flags & util::disasm_interface::PAGED) {
+ m_next_pc = [this](offs_t pc, offs_t size) {
+ offs_t pce = pc + size;
+ if((pc ^ pce) & ~m_page_mask)
+ pce = (pc | m_page_mask) + 1;
+ pce &= m_pc_mask;
+ return pce;
+ };
+ m_next_pc_wrap = [this](offs_t pc, offs_t size) {
+ offs_t pce = (pc & ~m_page_mask) | ((pc + size) & m_page_mask);
+ return pce;
+ };
+
+ } else {
+ m_next_pc = [this](offs_t pc, offs_t size) {
+ return (pc + size) & m_pc_mask;
+ };
+ m_next_pc_wrap = [this](offs_t pc, offs_t size) {
+ return (pc + size) & m_pc_mask;
+ };
+ }
+
+ // pc to string conversion
+ int aw = m_mintf->space(AS_PROGRAM).addr_width();
+ bool is_octal = m_mintf->space(AS_PROGRAM).is_octal();
+ if((m_flags & util::disasm_interface::PAGED2LEVEL) == util::disasm_interface::PAGED2LEVEL) {
+ int bits1 = m_dintf->page_address_bits();
+ int bits2 = m_dintf->page2_address_bits();
+ int bits3 = aw - bits1 - bits2;
+ offs_t sm1 = (1 << bits1) - 1;
+ int sh2 = bits1;
+ offs_t sm2 = (1 << bits2) - 1;
+ int sh3 = bits1+bits2;
+
+ if(is_octal) {
+ int nc1 = (bits1+2)/3;
+ int nc2 = (bits2+2)/3;
+ int nc3 = (bits3+2)/3;
+ m_pc_to_string = [nc1, nc2, nc3, sm1, sm2, sh2, sh3](offs_t pc) -> std::string {
+ return util::string_format("%0*o:%0*o:%0*o",
+ nc3, pc >> sh3,
+ nc2, (pc >> sh2) & sm2,
+ nc1, pc & sm1);
+ };
+ } else {
+ int nc1 = (bits1+3)/4;
+ int nc2 = (bits2+3)/4;
+ int nc3 = (bits3+3)/4;
+ m_pc_to_string = [nc1, nc2, nc3, sm1, sm2, sh2, sh3](offs_t pc) -> std::string {
+ return util::string_format("%0*x:%0*x:%0*x",
+ nc3, pc >> sh3,
+ nc2, (pc >> sh2) & sm2,
+ nc1, pc & sm1);
+ };
+ }
+
+ } else if(m_flags & util::disasm_interface::PAGED) {
+ int bits1 = m_dintf->page_address_bits();
+ int bits2 = aw - bits1;
+ offs_t sm1 = (1 << bits1) - 1;
+ int sh2 = bits1;
+
+ if(is_octal) {
+ int nc1 = (bits1+2)/3;
+ int nc2 = (bits2+2)/3;
+ m_pc_to_string = [nc1, nc2, sm1, sh2](offs_t pc) -> std::string {
+ return util::string_format("%0*o:%0*o",
+ nc2, pc >> sh2,
+ nc1, pc & sm1);
+ };
+ } else {
+ int nc1 = (bits1+3)/4;
+ int nc2 = (bits2+3)/4;
+ m_pc_to_string = [nc1, nc2, sm1, sh2](offs_t pc) -> std::string {
+ return util::string_format("%0*x:%0*x",
+ nc2, pc >> sh2,
+ nc1, pc & sm1);
+ };
+ }
+
+ } else {
+ int bits1 = aw;
+
+ if(is_octal) {
+ int nc1 = (bits1+2)/3;
+ m_pc_to_string = [nc1](offs_t pc) -> std::string {
+ return util::string_format("%0*o",
+ nc1, pc);
+ };
+ } else {
+ int nc1 = (bits1+3)/4;
+ m_pc_to_string = [nc1](offs_t pc) -> std::string {
+ return util::string_format("%0*x",
+ nc1, pc);
+ };
+ }
+ }
+}
+
+void debug_disasm_buffer::disassemble(offs_t pc, std::string &instruction, offs_t &next_pc, offs_t &size, u32 &info) const
+{
+ std::ostringstream out;
+ u32 result = m_dintf->disassemble(out, pc, m_buf_opcodes, m_buf_params.active() ? m_buf_params : m_buf_opcodes);
+ instruction = out.str();
+ size = result & util::disasm_interface::LENGTHMASK;
+ next_pc = m_next_pc(pc, size);
+ info = result;
+}
+
+
+u32 debug_disasm_buffer::disassemble_info(offs_t pc) const
+{
+ std::ostringstream out;
+ return m_dintf->disassemble(out, pc, m_buf_opcodes, m_buf_params.active() ? m_buf_params : m_buf_opcodes);
+}
+
+std::string debug_disasm_buffer::pc_to_string(offs_t pc) const
+{
+ return m_pc_to_string(pc);
+}
+
+std::string debug_disasm_buffer::data_to_string(offs_t pc, offs_t size, bool opcode) const
+{
+ if(!opcode && !m_buf_params.active())
+ return std::string();
+ return (opcode ? m_buf_opcodes : m_buf_params).data_to_string(pc, size);
+}
+
+void debug_disasm_buffer::data_get(offs_t pc, offs_t size, bool opcode, std::vector<u8> &data) const
+{
+ data.clear();
+ if(!opcode && !m_buf_params.active())
+ return;
+ (opcode ? m_buf_opcodes : m_buf_params).data_get(pc, size, data);
+}
+
+offs_t debug_disasm_buffer::next_pc(offs_t pc, offs_t step) const
+{
+ return m_next_pc(pc, step);
+}
+
+offs_t debug_disasm_buffer::next_pc_wrap(offs_t pc, offs_t step) const
+{
+ return m_next_pc_wrap(pc, step);
+}
diff --git a/src/emu/debug/debugbuf.h b/src/emu/debug/debugbuf.h
new file mode 100644
index 00000000000..46ec8286417
--- /dev/null
+++ b/src/emu/debug/debugbuf.h
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Buffering interface for the disassembly windows
+
+#ifndef MAME_EMU_DEBUG_DEBUGBUF_H
+#define MAME_EMU_DEBUG_DEBUGBUF_H
+
+#pragma once
+
+class debug_disasm_buffer
+{
+public:
+ debug_disasm_buffer(device_t &device);
+
+ void disassemble(offs_t pc, std::string &instruction, offs_t &next_pc, offs_t &size, u32 &info) const;
+ u32 disassemble_info(offs_t pc) const;
+ std::string pc_to_string(offs_t pc) const;
+ std::string data_to_string(offs_t pc, offs_t size, bool opcode) const;
+ void data_get(offs_t pc, offs_t size, bool opcode, std::vector<u8> &data) const;
+
+ offs_t next_pc(offs_t pc, offs_t step) const;
+ offs_t next_pc_wrap(offs_t pc, offs_t step) const;
+
+private:
+ class debug_data_buffer : public util::disasm_interface::data_buffer
+ {
+ public:
+ debug_data_buffer(util::disasm_interface *intf);
+ ~debug_data_buffer() = default;
+
+ virtual u8 r8 (offs_t pc) const override;
+ virtual u16 r16(offs_t pc) const override;
+ virtual u32 r32(offs_t pc) const override;
+ virtual u64 r64(offs_t pc) const override;
+
+ void set_source(address_space &space);
+ void set_source(debug_data_buffer &back, bool opcode);
+
+ bool active() const;
+
+ address_space *get_underlying_space() const;
+ std::string data_to_string(offs_t pc, offs_t size) const;
+ void data_get(offs_t pc, offs_t size, std::vector<u8> &data) const;
+
+ private:
+ util::disasm_interface *m_intf;
+
+ std::function<offs_t (offs_t)> m_pc_delta_to_bytes;
+ std::function<void (offs_t, offs_t)> m_do_fill;
+ std::function<u8 (offs_t)> m_do_r8;
+ std::function<u16 (offs_t)> m_do_r16;
+ std::function<u32 (offs_t)> m_do_r32;
+ std::function<u64 (offs_t)> m_do_r64;
+ std::function<std::string (offs_t, offs_t)> m_data_to_string;
+ std::function<void (offs_t, offs_t, std::vector<u8> &)> m_data_get;
+ std::function<offs_t (offs_t, offs_t)> m_next_pc_wrap;
+
+ address_space *m_space;
+ debug_data_buffer *m_back;
+ bool m_opcode;
+ offs_t m_page_mask, m_pc_mask;
+ mutable offs_t m_lstart, m_lend;
+ mutable bool m_wrapped;
+ mutable std::vector<u8> m_buffer;
+
+ template<typename T> T *get_ptr(offs_t lpc) {
+ return reinterpret_cast<T *>(&m_buffer[0]) + ((lpc - m_lstart) & m_pc_mask);
+ }
+
+ template<typename T> T get(offs_t lpc) const {
+ return reinterpret_cast<const T *>(&m_buffer[0])[(lpc - m_lstart) & m_pc_mask];
+ }
+
+ void setup_methods();
+ void fill(offs_t lstart, offs_t size) const;
+
+ };
+
+ util::disasm_interface *m_dintf;
+ device_memory_interface *m_mintf;
+
+ std::function<offs_t (offs_t, offs_t)> m_next_pc;
+ std::function<offs_t (offs_t, offs_t)> m_next_pc_wrap;
+ std::function<std::string (offs_t)> m_pc_to_string;
+
+ debug_data_buffer m_buf_raw, m_buf_opcodes, m_buf_params;
+ u32 m_flags;
+ offs_t m_page_mask, m_pc_mask;
+};
+
+#endif
+
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index c1e96054164..0c7715b523b 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -14,6 +14,7 @@
#include "debugcmd.h"
#include "debugcon.h"
#include "debugcpu.h"
+#include "debugbuf.h"
#include "express.h"
#include "debughlp.h"
#include "debugvw.h"
@@ -1644,7 +1645,6 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa
u64 offset, endoffset, length;
address_space *space;
FILE *f;
- u64 i;
/* validate parameters */
if (!validate_number_parameter(params[1], offset))
@@ -1655,8 +1655,9 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa
return;
/* determine the addresses to write */
- endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
- offset = space->address_to_byte(offset) & space->bytemask();
+ endoffset = (offset + length - 1) & space->addrmask();
+ offset = offset & space->addrmask();
+ endoffset ++;
/* open the file */
f = fopen(params[0].c_str(), "wb");
@@ -1667,10 +1668,46 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa
}
/* now write the data out */
- for (i = offset; i <= endoffset; i++)
+ auto dis = space->machine().disable_side_effect();
+ switch (space->addrbus_shift())
{
- u8 byte = m_cpu.read_byte(*space, i, true);
- fwrite(&byte, 1, 1, f);
+ case -3:
+ for (offs_t i = offset; i != endoffset; i++)
+ {
+ u64 data = space->read_qword(i);
+ fwrite(&data, 8, 1, f);
+ }
+ break;
+ case -2:
+ for (offs_t i = offset; i != endoffset; i++)
+ {
+ u32 data = space->read_dword(i);
+ fwrite(&data, 4, 1, f);
+ }
+ break;
+ case -1:
+ for (offs_t i = offset; i != endoffset; i++)
+ {
+ u16 byte = space->read_word(i);
+ fwrite(&byte, 2, 1, f);
+ }
+ break;
+ case 0:
+ for (offs_t i = offset; i != endoffset; i++)
+ {
+ u8 byte = space->read_byte(i);
+ fwrite(&byte, 1, 1, f);
+ }
+ break;
+ case 3:
+ offset &= ~15;
+ endoffset &= ~15;
+ for (offs_t i = offset; i != endoffset; i+=16)
+ {
+ u16 byte = space->read_word(i >> 4);
+ fwrite(&byte, 2, 1, f);
+ }
+ break;
}
/* close the file */
@@ -1687,7 +1724,6 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa
{
u64 offset, endoffset, length = 0;
address_space *space;
- u64 i;
// validate parameters
if (!validate_number_parameter(params[1], offset))
@@ -1712,19 +1748,66 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa
f.seekg(0, std::ios::end);
length = f.tellg();
f.seekg(0);
+ if (space->addrbus_shift() < 0)
+ length >>= -space->addrbus_shift();
+ else if (space->addrbus_shift() > 0)
+ length <<= space->addrbus_shift();
}
// determine the addresses to read
- endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
- offset = space->address_to_byte(offset) & space->bytemask();
-
+ endoffset = (offset + length - 1) & space->addrmask();
+ offset = offset & space->addrmask();
+ offs_t i = 0;
// now read the data in, ignore endoffset and load entire file if length has been set to zero (offset-1)
- for (i = offset; f.good() && (i <= endoffset || endoffset == offset - 1); i++)
+ switch (space->addrbus_shift())
{
- char byte;
- f.read(&byte, 1);
- if (f)
- m_cpu.write_byte(*space, i, byte, true);
+ case -3:
+ for (i = offset; f.good() && (i <= endoffset || endoffset == offset - 1); i++)
+ {
+ u64 data;
+ f.read((char *)&data, 8);
+ if (f)
+ space->write_qword(i, data);
+ }
+ break;
+ case -2:
+ for (i = offset; f.good() && (i <= endoffset || endoffset == offset - 1); i++)
+ {
+ u32 data;
+ f.read((char *)&data, 4);
+ if (f)
+ space->write_dword(i, data);
+ }
+ break;
+ case -1:
+ for (i = offset; f.good() && (i <= endoffset || endoffset == offset - 1); i++)
+ {
+ u16 data;
+ f.read((char *)&data, 2);
+ if (f)
+ space->write_word(i, data);
+ }
+ break;
+ case 0:
+ for (i = offset; f.good() && (i <= endoffset || endoffset == offset - 1); i++)
+ {
+ u8 data;
+ f.read((char *)&data, 1);
+ if (f)
+ space->write_byte(i, data);
+ }
+ break;
+ case 3:
+ offset &= ~15;
+ endoffset &= ~15;
+ for (i = offset; f.good() && (i <= endoffset || endoffset == offset - 16); i+=16)
+ {
+ u16 data;
+ f.read((char *)&data, 2);
+ if (f)
+ space->write_word(i >> 4, data);
+ }
+ break;
}
if (!f.good())
@@ -1767,6 +1850,9 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa
if (!validate_cpu_space_parameter((params.size() > 6) ? params[6].c_str() : nullptr, ref, space))
return;
+ int shift = space->addrbus_shift();
+ u64 granularity = shift > 0 ? 2 : 1 << -shift;
+
/* further validation */
if (width == 0)
width = space->data_width() / 8;
@@ -1777,14 +1863,19 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa
m_console.printf("Invalid width! (must be 1,2,4 or 8)\n");
return;
}
+ if (width < granularity)
+ {
+ m_console.printf("Invalid width! (must be at least %d)\n", granularity);
+ return;
+ }
if (rowsize == 0 || (rowsize % width) != 0)
{
m_console.printf("Invalid row size! (must be a positive multiple of %d)\n", width);
return;
}
- u64 endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
- offset = space->address_to_byte(offset) & space->bytemask();
+ u64 endoffset = (offset + length - 1) & space->addrmask();
+ offset = offset & space->addrmask();
/* open the file */
FILE* f = fopen(params[0].c_str(), "w");
@@ -1797,13 +1888,22 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa
/* now write the data out */
util::ovectorstream output;
output.reserve(200);
- for (u64 i = offset; i <= endoffset; i += rowsize)
+
+ if (shift > 0)
+ width <<= shift;
+ else if(shift < 0)
+ width >>= -shift;
+
+ auto dis = space->machine().disable_side_effect();
+ bool be = space->endianness() == ENDIANNESS_BIG;
+
+ for (offs_t i = offset; i <= endoffset; i += rowsize)
{
output.clear();
output.rdbuf()->clear();
/* print the address */
- util::stream_format(output, "%0*X: ", space->logaddrchars(), u32(space->byte_to_address(i)));
+ util::stream_format(output, "%0*X: ", space->logaddrchars(), i);
/* print the bytes */
for (u64 j = 0; j < rowsize; j += width)
@@ -1813,8 +1913,21 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa
offs_t curaddr = i + j;
if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr))
{
- u64 value = m_cpu.read_memory(*space, i + j, width, true);
- util::stream_format(output, " %0*X", width * 2, value);
+ switch (width)
+ {
+ case 8:
+ util::stream_format(output, " %016X", space->read_qword(i+j));
+ break;
+ case 4:
+ util::stream_format(output, " %08X", space->read_dword(i+j));
+ break;
+ case 2:
+ util::stream_format(output, " %04X", space->read_word(i+j));
+ break;
+ case 1:
+ util::stream_format(output, " %02X", space->read_byte(i+j));
+ break;
+ }
}
else
{
@@ -1834,8 +1947,26 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa
offs_t curaddr = i + j;
if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr))
{
- u8 byte = m_cpu.read_byte(*space, i + j, true);
- util::stream_format(output, "%c", (byte >= 32 && byte < 127) ? byte : '.');
+ u64 data = 0;
+ switch (width)
+ {
+ case 8:
+ data = space->read_qword(i+j);
+ break;
+ case 4:
+ data = space->read_dword(i+j);
+ break;
+ case 2:
+ data = space->read_word(i+j);
+ break;
+ case 1:
+ data = space->read_byte(i+j);
+ break;
+ }
+ for (unsigned int b = 0; b != width; b++) {
+ u8 byte = data >> (8 * (be ? (width-i-b) : b));
+ util::stream_format(output, "%c", (byte >= 32 && byte < 127) ? byte : '.');
+ }
}
else
{
@@ -1920,8 +2051,8 @@ void debugger_commands::execute_cheatinit(int ref, const std::vector<std::string
{
for (address_map_entry &entry : space->map()->m_entrylist)
{
- cheat_region[region_count].offset = space->address_to_byte(entry.m_addrstart) & space->bytemask();
- cheat_region[region_count].endoffset = space->address_to_byte(entry.m_addrend) & space->bytemask();
+ cheat_region[region_count].offset = entry.m_addrstart & space->addrmask();
+ cheat_region[region_count].endoffset = entry.m_addrend & space->addrmask();
cheat_region[region_count].share = entry.m_share;
cheat_region[region_count].disabled = (entry.m_write.m_type == AMH_RAM) ? false : true;
@@ -1944,8 +2075,8 @@ void debugger_commands::execute_cheatinit(int ref, const std::vector<std::string
return;
/* force region to the specified range */
- cheat_region[region_count].offset = space->address_to_byte(offset) & space->bytemask();
- cheat_region[region_count].endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
+ cheat_region[region_count].offset = offset & space->addrmask();
+ cheat_region[region_count].endoffset = (offset + length - 1) & space->addrmask();
cheat_region[region_count].share = nullptr;
cheat_region[region_count].disabled = false;
region_count++;
@@ -2320,9 +2451,9 @@ void debugger_commands::execute_find(int ref, const std::vector<std::string> &pa
return;
/* further validation */
- endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
- offset = space->address_to_byte(offset) & space->bytemask();
- cur_data_size = space->address_to_byte(1);
+ endoffset = (offset + length - 1) & space->addrmask();
+ offset = offset & space->addrmask();
+ cur_data_size = space->addrbus_shift() > 0 ? 2 : 1 << -space->addrbus_shift();
if (cur_data_size == 0)
cur_data_size = 1;
@@ -2403,10 +2534,7 @@ void debugger_commands::execute_find(int ref, const std::vector<std::string> &pa
void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &params)
{
u64 offset, length, bytes = 1;
- int minbytes, maxbytes, byteswidth;
- address_space *space, *decrypted_space;
- FILE *f;
- int j;
+ address_space *space;
/* validate parameters */
if (!validate_number_parameter(params[1], offset))
@@ -2417,10 +2545,6 @@ void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &pa
return;
if (!validate_cpu_space_parameter(params.size() > 4 ? params[4].c_str() : nullptr, AS_PROGRAM, space))
return;
- if (space->device().memory().has_space(AS_OPCODES))
- decrypted_space = &space->device().memory().space(AS_OPCODES);
- else
- decrypted_space = space;
/* determine the width of the bytes */
device_disasm_interface *dasmintf;
@@ -2429,104 +2553,72 @@ void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &pa
m_console.printf("No disassembler available for %s\n", space->device().name());
return;
}
- minbytes = dasmintf->min_opcode_bytes();
- maxbytes = dasmintf->max_opcode_bytes();
- byteswidth = 0;
- if (bytes)
- {
- byteswidth = (maxbytes + (minbytes - 1)) / minbytes;
- byteswidth *= (2 * minbytes) + 1;
- }
- /* open the file */
- f = fopen(params[0].c_str(), "w");
- if (!f)
- {
- m_console.printf("Error opening file '%s'\n", params[0].c_str());
- return;
- }
+ /* build the data, check the maximum size of the opcodes and disasm */
+ std::vector<offs_t> pcs;
+ std::vector<std::string> instructions;
+ std::vector<std::string> tpc;
+ std::vector<std::string> topcodes;
+ int max_opcodes_size = 0;
+ int max_disasm_size = 0;
+
+ debug_disasm_buffer buffer(space->device());
- /* now write the data out */
- util::ovectorstream output;
- util::ovectorstream disasm;
- output.reserve(512);
for (u64 i = 0; i < length; )
{
- int pcbyte = space->address_to_byte(offset + i) & space->bytemask();
- const char *comment;
- offs_t tempaddr;
- int numbytes = 0;
- output.clear();
- output.rdbuf()->clear();
- disasm.clear();
- disasm.seekp(0);
+ std::string instruction;
+ offs_t next_offset;
+ offs_t size;
+ u32 info;
+ buffer.disassemble(offset, instruction, next_offset, size, info);
+ pcs.push_back(offset);
+ instructions.emplace_back(instruction);
+ tpc.emplace_back(buffer.pc_to_string(offset));
+ topcodes.emplace_back(buffer.data_to_string(offset, size, true));
- /* print the address */
- stream_format(output, "%0*X: ", space->logaddrchars(), u32(space->byte_to_address(pcbyte)));
+ int osize = topcodes.back().size();
+ if(osize > max_opcodes_size)
+ max_opcodes_size = osize;
- /* make sure we can translate the address */
- tempaddr = pcbyte;
- if (space->device().memory().translate(space->spacenum(), TRANSLATE_FETCH_DEBUG, tempaddr))
- {
- {
- u8 opbuf[64], argbuf[64];
+ int dsize = instructions.back().size();
+ if(dsize > max_disasm_size)
+ max_disasm_size = dsize;
- /* fetch the bytes up to the maximum */
- for (numbytes = 0; numbytes < maxbytes; numbytes++)
- {
- opbuf[numbytes] = m_cpu.read_opcode(*decrypted_space, pcbyte + numbytes, 1);
- argbuf[numbytes] = m_cpu.read_opcode(*space, pcbyte + numbytes, 1);
- }
+ i += size;
+ offset = next_offset;
+ }
- /* disassemble the result */
- i += numbytes = dasmintf->disassemble(disasm, offset + i, opbuf, argbuf) & DASMFLAG_LENGTHMASK;
- }
+ /* write the data */
+ std::ofstream f(params[0]);
+ if (!f.good())
+ {
+ m_console.printf("Error opening file '%s'\n", params[0]);
+ return;
+ }
- /* print the bytes */
- if (bytes)
- {
- auto const startdex = output.tellp();
- numbytes = space->address_to_byte(numbytes);
- for (j = 0; j < numbytes; j += minbytes)
- stream_format(output, "%0*X ", minbytes * 2, m_cpu.read_opcode(*decrypted_space, pcbyte + j, minbytes));
- if ((output.tellp() - startdex) < byteswidth)
- stream_format(output, "%*s", byteswidth - (output.tellp() - startdex), "");
- stream_format(output, " ");
- }
- }
- else
+ if (bytes)
+ {
+ for(unsigned int i=0; i != pcs.size(); i++)
{
- disasm << "<unmapped>";
- i += minbytes;
+ const char *comment = space->device().debug()->comment_text(pcs[i]);
+ if (comment)
+ util::stream_format(f, "%s: %-*s %-*s // %s\n", tpc[i], max_opcodes_size, topcodes[i], max_disasm_size, instructions[i], comment);
+ else
+ util::stream_format(f, "%s: %-*s %s\n", tpc[i], max_opcodes_size, topcodes[i], instructions[i]);
}
-
- /* add the disassembly */
- disasm.put('\0');
- stream_format(output, "%s", &disasm.vec()[0]);
-
- /* attempt to add the comment */
- comment = space->device().debug()->comment_text(tempaddr);
- if (comment != nullptr)
+ }
+ else
+ {
+ for(unsigned int i=0; i != pcs.size(); i++)
{
- /* somewhat arbitrary guess as to how long most disassembly lines will be [column 60] */
- if (output.tellp() < 60)
- {
- /* pad the comment space out to 60 characters and null-terminate */
- while (output.tellp() < 60) output.put(' ');
-
- stream_format(output, "// %s", comment);
- }
+ const char *comment = space->device().debug()->comment_text(pcs[i]);
+ if (comment)
+ util::stream_format(f, "%s: %-*s // %s\n", tpc[i], max_disasm_size, instructions[i], comment);
else
- stream_format(output, "\t// %s", comment);
+ util::stream_format(f, "%s: %s\n", tpc[i], instructions[i]);
}
-
- /* output the result */
- auto const &text(output.vec());
- fprintf(f, "%.*s\n", int(unsigned(text.size())), &text[0]);
}
- /* close the file */
- fclose(f);
m_console.printf("Data dumped successfully\n");
}
@@ -2640,13 +2732,9 @@ void debugger_commands::execute_traceflush(int ref, const std::vector<std::strin
void debugger_commands::execute_history(int ref, const std::vector<std::string> &params)
{
/* validate parameters */
- address_space *space, *decrypted_space;
+ address_space *space;
if (!validate_cpu_space_parameter(!params.empty() ? params[0].c_str() : nullptr, AS_PROGRAM, space))
return;
- if (space->device().memory().has_space(AS_OPCODES))
- decrypted_space = &space->device().memory().space(AS_OPCODES);
- else
- decrypted_space = space;
u64 count = device_debug::HISTORY_SIZE;
if (params.size() > 1 && !validate_number_parameter(params[1], count))
@@ -2665,25 +2753,19 @@ void debugger_commands::execute_history(int ref, const std::vector<std::string>
m_console.printf("No disassembler available for %s\n", space->device().name());
return;
}
- int maxbytes = dasmintf->max_opcode_bytes();
+
+ debug_disasm_buffer buffer(space->device());
+
for (int index = 0; index < (int) count; index++)
{
offs_t pc = debug->history_pc(-index);
+ std::string instruction;
+ offs_t next_offset;
+ offs_t size;
+ u32 info;
+ buffer.disassemble(pc, instruction, next_offset, size, info);
- /* fetch the bytes up to the maximum */
- offs_t pcbyte = space->address_to_byte(pc) & space->bytemask();
- u8 opbuf[64], argbuf[64];
- for (int numbytes = 0; numbytes < maxbytes; numbytes++)
- {
- opbuf[numbytes] = m_cpu.read_opcode(*decrypted_space, pcbyte + numbytes, 1);
- argbuf[numbytes] = m_cpu.read_opcode(*space, pcbyte + numbytes, 1);
- }
-
- util::ovectorstream buffer;
- dasmintf->disassemble(buffer, pc, opbuf, argbuf);
- buffer.put('\0');
-
- m_console.printf("%0*X: %s\n", space->logaddrchars(), pc, &buffer.vec()[0]);
+ m_console.printf("%s: %s\n", buffer.pc_to_string(pc), instruction);
}
}
@@ -2882,7 +2964,7 @@ void debugger_commands::execute_map(int ref, const std::vector<std::string> &par
for (intention = TRANSLATE_READ_DEBUG; intention <= TRANSLATE_FETCH_DEBUG; intention++)
{
static const char *const intnames[] = { "Read", "Write", "Fetch" };
- taddress = space->address_to_byte(address) & space->bytemask();
+ taddress = address & space->addrmask();
if (space->device().memory().translate(space->spacenum(), intention, taddress))
{
const char *mapname = space->get_handler_string((intention == TRANSLATE_WRITE_DEBUG) ? read_or_write::WRITE : read_or_write::READ, taddress);
@@ -2890,7 +2972,7 @@ void debugger_commands::execute_map(int ref, const std::vector<std::string> &par
"%7s: %0*X logical == %0*X physical -> %s\n",
intnames[intention & 3],
space->logaddrchars(), address,
- space->addrchars(), space->byte_to_address(taddress),
+ space->addrchars(), taddress,
mapname);
}
else
diff --git a/src/emu/debug/debugcon.cpp b/src/emu/debug/debugcon.cpp
index 8b0cd786bff..3b0f2e98b6b 100644
--- a/src/emu/debug/debugcon.cpp
+++ b/src/emu/debug/debugcon.cpp
@@ -344,7 +344,7 @@ CMDERR debugger_console::execute_command(const std::string &command, bool echo)
if (!echo)
printf(">%s\n", command.c_str());
printf(" %*s^\n", CMDERR_ERROR_OFFSET(result), "");
- printf("%s\n", cmderr_to_string(result));
+ printf("%s\n", cmderr_to_string(result).c_str());
}
/* update all views */
@@ -404,8 +404,9 @@ void debugger_console::register_command(const char *command, u32 flags, int ref,
for a given command error
-------------------------------------------------*/
-const char *debugger_console::cmderr_to_string(CMDERR error)
+std::string debugger_console::cmderr_to_string(CMDERR error)
{
+ int offset = CMDERR_ERROR_OFFSET(error);
switch (CMDERR_ERROR_CLASS(error))
{
case CMDERR_UNKNOWN_COMMAND: return "unknown command";
@@ -414,7 +415,8 @@ const char *debugger_console::cmderr_to_string(CMDERR error)
case CMDERR_UNBALANCED_QUOTES: return "unbalanced quotes";
case CMDERR_NOT_ENOUGH_PARAMS: return "not enough parameters for command";
case CMDERR_TOO_MANY_PARAMS: return "too many parameters for command";
- case CMDERR_EXPRESSION_ERROR: return "error in assignment expression";
+ case CMDERR_EXPRESSION_ERROR: return string_format("error in assignment expression: %s",
+ expression_error(static_cast<expression_error::error_code>(offset)).code_string());
default: return "unknown error";
}
}
diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h
index 54bc3bf6772..7cc1231d4c9 100644
--- a/src/emu/debug/debugcon.h
+++ b/src/emu/debug/debugcon.h
@@ -104,7 +104,7 @@ public:
vprintf_wrap(wrapcol, util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
- static const char * cmderr_to_string(CMDERR error);
+ static std::string cmderr_to_string(CMDERR error);
private:
void exit();
diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp
index 46ad9e04683..c5f5a532599 100644
--- a/src/emu/debug/debugcpu.cpp
+++ b/src/emu/debug/debugcpu.cpp
@@ -10,6 +10,7 @@
#include "emu.h"
#include "debugcpu.h"
+#include "debugbuf.h"
#include "express.h"
#include "debugcon.h"
@@ -363,7 +364,7 @@ u8 debugger_cpu::read_byte(address_space &space, offs_t address, bool apply_tran
device_memory_interface &memory = space.device().memory();
/* mask against the logical byte mask */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
/* translate if necessary; if not mapped, return 0xff */
u8 result;
@@ -388,7 +389,7 @@ u8 debugger_cpu::read_byte(address_space &space, offs_t address, bool apply_tran
u16 debugger_cpu::read_word(address_space &space, offs_t address, bool apply_translation)
{
/* mask against the logical byte mask */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
u16 result;
if (!WORD_ALIGNED(address))
@@ -429,7 +430,7 @@ u16 debugger_cpu::read_word(address_space &space, offs_t address, bool apply_tra
u32 debugger_cpu::read_dword(address_space &space, offs_t address, bool apply_translation)
{
/* mask against the logical byte mask */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
u32 result;
if (!DWORD_ALIGNED(address))
@@ -469,7 +470,7 @@ u32 debugger_cpu::read_dword(address_space &space, offs_t address, bool apply_tr
u64 debugger_cpu::read_qword(address_space &space, offs_t address, bool apply_translation)
{
/* mask against the logical byte mask */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
u64 result;
if (!QWORD_ALIGNED(address))
@@ -531,7 +532,7 @@ void debugger_cpu::write_byte(address_space &space, offs_t address, u8 data, boo
device_memory_interface &memory = space.device().memory();
/* mask against the logical byte mask */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
/* translate if necessary; if not mapped, we're done */
if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address))
@@ -553,7 +554,7 @@ void debugger_cpu::write_byte(address_space &space, offs_t address, u8 data, boo
void debugger_cpu::write_word(address_space &space, offs_t address, u16 data, bool apply_translation)
{
/* mask against the logical byte mask */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
/* if this is a misaligned write, or if there are no word writers, just read two bytes */
if (!WORD_ALIGNED(address))
@@ -596,7 +597,7 @@ void debugger_cpu::write_word(address_space &space, offs_t address, u16 data, bo
void debugger_cpu::write_dword(address_space &space, offs_t address, u32 data, bool apply_translation)
{
/* mask against the logical byte mask */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
/* if this is a misaligned write, or if there are no dword writers, just read two words */
if (!DWORD_ALIGNED(address))
@@ -639,7 +640,7 @@ void debugger_cpu::write_dword(address_space &space, offs_t address, u32 data, b
void debugger_cpu::write_qword(address_space &space, offs_t address, u64 data, bool apply_translation)
{
/* mask against the logical byte mask */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
/* if this is a misaligned write, or if there are no qword writers, just read two dwords */
if (!QWORD_ALIGNED(address))
@@ -703,7 +704,7 @@ u64 debugger_cpu::read_opcode(address_space &space, offs_t address, int size)
u64 result = ~u64(0) & (~u64(0) >> (64 - 8*size));
/* keep in logical range */
- address &= space.logbytemask();
+ address &= space.logaddrmask();
/* if we're bigger than the address bus, break into smaller pieces */
if (size > space.data_width() / 8)
@@ -723,7 +724,7 @@ u64 debugger_cpu::read_opcode(address_space &space, offs_t address, int size)
return result;
/* keep in physical range */
- address &= space.bytemask();
+ address &= space.addrmask();
/* switch off the size and handle unaligned accesses */
switch (size)
@@ -1559,8 +1560,12 @@ device_debug::device_debug(device_t &device)
std::string tempstr;
for (const auto &entry : m_state->state_entries())
{
- strmakelower(tempstr.assign(entry->symbol()));
- m_symtable.add(tempstr.c_str(), (void *)(uintptr_t)entry->index(), get_state, set_state, entry->format_string());
+ // TODO: floating point registers
+ if (!entry->is_float())
+ {
+ strmakelower(tempstr.assign(entry->symbol()));
+ m_symtable.add(tempstr.c_str(), (void *)(uintptr_t)entry->index(), get_state, entry->writeable() ? set_state : nullptr, entry->format_string());
+ }
}
}
@@ -2483,33 +2488,15 @@ bool device_debug::comment_import(util::xml::data_node const &cpunode, bool is_i
u32 device_debug::compute_opcode_crc32(offs_t pc) const
{
- // Basically the same thing as dasm_wrapped, but with some tiny savings
- assert(m_memory != nullptr);
-
- // determine the adjusted PC
- address_space &decrypted_space = m_memory->has_space(AS_OPCODES) ? m_memory->space(AS_OPCODES) : m_memory->space(AS_PROGRAM);
- address_space &space = m_memory->space(AS_PROGRAM);
- offs_t pcbyte = space.address_to_byte(pc) & space.bytemask();
-
- // fetch the bytes up to the maximum
- u8 opbuf[64], argbuf[64];
- int maxbytes = (m_disasm != nullptr) ? m_disasm->max_opcode_bytes() : 1;
- for (int numbytes = 0; numbytes < maxbytes; numbytes++)
- {
- opbuf[numbytes] = m_device.machine().debugger().cpu().read_opcode(decrypted_space, pcbyte + numbytes, 1);
- argbuf[numbytes] = m_device.machine().debugger().cpu().read_opcode(space, pcbyte + numbytes, 1);
- }
+ std::vector<u8> opbuf;
+ debug_disasm_buffer buffer(device());
- u32 numbytes = maxbytes;
- if (m_disasm != nullptr)
- {
- // disassemble to our buffer
- std::ostringstream diasmbuf;
- numbytes = m_disasm->disassemble(diasmbuf, pc, opbuf, argbuf) & DASMFLAG_LENGTHMASK;
- }
+ // disassemble the current instruction and get the flags
+ u32 dasmresult = buffer.disassemble_info(pc);
+ buffer.data_get(pc, dasmresult & util::disasm_interface::LENGTHMASK, true, opbuf);
// return a CRC of the exact count of opcode bytes
- return core_crc32(0, opbuf, numbytes);
+ return core_crc32(0, &opbuf[0], opbuf.size());
}
@@ -2589,26 +2576,29 @@ void device_debug::compute_debug_flags()
void device_debug::prepare_for_step_overout(offs_t pc)
{
+ debug_disasm_buffer buffer(device());
+
// disassemble the current instruction and get the flags
- std::string dasmbuffer;
- offs_t dasmresult = dasm_wrapped(dasmbuffer, pc);
+ u32 dasmresult = buffer.disassemble_info(pc);
// if flags are supported and it's a call-style opcode, set a temp breakpoint after that instruction
- if ((dasmresult & DASMFLAG_SUPPORTED) != 0 && (dasmresult & DASMFLAG_STEP_OVER) != 0)
+ if ((dasmresult & util::disasm_interface::SUPPORTED) != 0 && (dasmresult & util::disasm_interface::STEP_OVER) != 0)
{
- int extraskip = (dasmresult & DASMFLAG_OVERINSTMASK) >> DASMFLAG_OVERINSTSHIFT;
- pc += dasmresult & DASMFLAG_LENGTHMASK;
+ int extraskip = (dasmresult & util::disasm_interface::OVERINSTMASK) >> util::disasm_interface::OVERINSTSHIFT;
+ pc = buffer.next_pc_wrap(pc, dasmresult & util::disasm_interface::LENGTHMASK);
// if we need to skip additional instructions, advance as requested
- while (extraskip-- > 0)
- pc += dasm_wrapped(dasmbuffer, pc) & DASMFLAG_LENGTHMASK;
+ while (extraskip-- > 0) {
+ u32 result = buffer.disassemble_info(pc);
+ pc += buffer.next_pc_wrap(pc, result & util::disasm_interface::LENGTHMASK);
+ }
m_stepaddr = pc;
}
// if we're stepping out and this isn't a step out instruction, reset the steps until stop to a high number
if ((m_flags & DEBUG_FLAG_STEPPING_OUT) != 0)
{
- if ((dasmresult & DASMFLAG_SUPPORTED) != 0 && (dasmresult & DASMFLAG_STEP_OUT) == 0)
+ if ((dasmresult & util::disasm_interface::SUPPORTED) != 0 && (dasmresult & util::disasm_interface::STEP_OUT) == 0)
m_stepsleft = 100;
else
m_stepsleft = 1;
@@ -2881,38 +2871,6 @@ void device_debug::hotspot_check(address_space &space, offs_t address)
//-------------------------------------------------
-// dasm_wrapped - wraps calls to the disassembler
-// by fetching the opcode bytes to a temporary
-// buffer and then disassembling them
-//-------------------------------------------------
-
-u32 device_debug::dasm_wrapped(std::string &buffer, offs_t pc)
-{
- assert(m_memory != nullptr && m_disasm != nullptr);
-
- // determine the adjusted PC
- address_space &decrypted_space = m_memory->has_space(AS_OPCODES) ? m_memory->space(AS_OPCODES) : m_memory->space(AS_PROGRAM);
- address_space &space = m_memory->space(AS_PROGRAM);
- offs_t pcbyte = space.address_to_byte(pc) & space.bytemask();
-
- // fetch the bytes up to the maximum
- u8 opbuf[64], argbuf[64];
- int maxbytes = m_disasm->max_opcode_bytes();
- for (int numbytes = 0; numbytes < maxbytes; numbytes++)
- {
- opbuf[numbytes] = m_device.machine().debugger().cpu().read_opcode(decrypted_space, pcbyte + numbytes, 1);
- argbuf[numbytes] = m_device.machine().debugger().cpu().read_opcode(space, pcbyte + numbytes, 1);
- }
-
- // disassemble to our buffer
- std::ostringstream stream;
- uint32_t result = m_disasm->disassemble(stream, pc, opbuf, argbuf);
- buffer = stream.str();
- return result;
-}
-
-
-//-------------------------------------------------
// get_current_pc - getter callback for a device's
// current instruction pointer
//-------------------------------------------------
@@ -3090,8 +3048,8 @@ device_debug::watchpoint::watchpoint(device_debug* debugInterface,
m_index(index),
m_enabled(true),
m_type(type),
- m_address(space.address_to_byte(address) & space.bytemask()),
- m_length(space.address_to_byte(length)),
+ m_address(address & space.addrmask()),
+ m_length(length),
m_condition(&symbols, (condition != nullptr) ? condition : "1"),
m_action((action != nullptr) ? action : "")
{
@@ -3253,35 +3211,24 @@ void device_debug::tracer::update(offs_t pc)
if (!m_action.empty())
m_debug.m_device.machine().debugger().console().execute_command(m_action, false);
- // print the address
- std::string buffer;
- int logaddrchars = m_debug.logaddrchars();
- if (m_debug.is_octal())
- {
- buffer = string_format("%0*o: ", logaddrchars*3/2, pc);
- }
- else
- {
- buffer = string_format("%0*X: ", logaddrchars, pc);
- }
-
- // print the disassembly
- std::string dasm;
- offs_t dasmresult = m_debug.dasm_wrapped(dasm, pc);
- buffer.append(dasm);
+ debug_disasm_buffer buffer(m_debug.device());
+ std::string instruction;
+ offs_t next_pc, size;
+ u32 dasmresult;
+ buffer.disassemble(pc, instruction, next_pc, size, dasmresult);
// output the result
- fprintf(&m_file, "%s\n", buffer.c_str());
+ fprintf(&m_file, "%s: %s\n", buffer.pc_to_string(pc).c_str(), instruction.c_str());
// do we need to step the trace over this instruction?
- if (m_trace_over && (dasmresult & DASMFLAG_SUPPORTED) != 0 && (dasmresult & DASMFLAG_STEP_OVER) != 0)
+ if (m_trace_over && (dasmresult & util::disasm_interface::SUPPORTED) != 0 && (dasmresult & util::disasm_interface::STEP_OVER) != 0)
{
- int extraskip = (dasmresult & DASMFLAG_OVERINSTMASK) >> DASMFLAG_OVERINSTSHIFT;
- offs_t trace_over_target = pc + (dasmresult & DASMFLAG_LENGTHMASK);
+ int extraskip = (dasmresult & util::disasm_interface::OVERINSTMASK) >> util::disasm_interface::OVERINSTSHIFT;
+ offs_t trace_over_target = buffer.next_pc_wrap(pc, dasmresult & util::disasm_interface::LENGTHMASK);
// if we need to skip additional instructions, advance as requested
while (extraskip-- > 0)
- trace_over_target += m_debug.dasm_wrapped(dasm, trace_over_target) & DASMFLAG_LENGTHMASK;
+ trace_over_target = buffer.next_pc_wrap(trace_over_target, buffer.disassemble_info(trace_over_target) & util::disasm_interface::LENGTHMASK);
m_trace_over_target = trace_over_target;
}
diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h
index 2ea78c3fe20..e00ac9576cc 100644
--- a/src/emu/debug/debugcpu.h
+++ b/src/emu/debug/debugcpu.h
@@ -278,7 +278,6 @@ private:
// internal helpers
void prepare_for_step_overout(offs_t pc);
- u32 dasm_wrapped(std::string &buffer, offs_t pc);
void errorlog_write_line(const char *line);
// breakpoint and watchpoint helpers
diff --git a/src/emu/debug/dvdisasm.cpp b/src/emu/debug/dvdisasm.cpp
index 1051365c561..9ad6cb968c2 100644
--- a/src/emu/debug/dvdisasm.cpp
+++ b/src/emu/debug/dvdisasm.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Olivier Galibert
/*********************************************************************
dvdisasm.c
@@ -14,7 +14,6 @@
#include "debugcpu.h"
#include "debugger.h"
-
//**************************************************************************
// DEBUG VIEW DISASM SOURCE
//**************************************************************************
@@ -25,7 +24,6 @@
debug_view_disasm_source::debug_view_disasm_source(const char *name, device_t &device)
: debug_view_source(name, &device),
- m_disasmintf(dynamic_cast<device_disasm_interface *>(&device)),
m_space(device.memory().space(AS_PROGRAM)),
m_decrypted_space(device.memory().has_space(AS_OPCODES) ? device.memory().space(AS_OPCODES) : device.memory().space(AS_PROGRAM))
{
@@ -49,23 +47,17 @@ debug_view_disasm::debug_view_disasm(running_machine &machine, debug_view_osd_up
m_right_column(DASM_RIGHTCOL_RAW),
m_backwards_steps(3),
m_dasm_width(DEFAULT_DASM_WIDTH),
- m_last_direct_raw(nullptr),
- m_last_direct_decrypted(nullptr),
- m_last_change_count(0),
- m_last_pcbyte(0),
- m_divider1(0),
- m_divider2(0),
- m_divider3(0),
+ m_previous_pc(1),
m_expression(machine)
{
// fail if no available sources
enumerate_sources();
- if (m_source_list.count() == 0)
+ if(m_source_list.count() == 0)
throw std::bad_alloc();
// count the number of comments
int total_comments = 0;
- for (const debug_view_source &source : m_source_list)
+ for(const debug_view_source &source : m_source_list)
{
const debug_view_disasm_source &dasmsource = downcast<const debug_view_disasm_source &>(source);
total_comments += dasmsource.device()->debug()->comment_count();
@@ -98,10 +90,10 @@ void debug_view_disasm::enumerate_sources()
// iterate over devices with disassembly interfaces
std::string name;
- for (device_disasm_interface &dasm : disasm_interface_iterator(machine().root_device()))
+ for(device_disasm_interface &dasm : disasm_interface_iterator(machine().root_device()))
{
name = string_format("%s '%s'", dasm.device().name(), dasm.device().tag());
- if (dasm.device().memory().space_config(AS_PROGRAM)!=nullptr)
+ if(dasm.device().memory().space_config(AS_PROGRAM)!=nullptr)
m_source_list.append(*global_alloc(debug_view_disasm_source(name.c_str(), dasm.device())));
}
@@ -117,10 +109,10 @@ void debug_view_disasm::enumerate_sources()
void debug_view_disasm::view_notify(debug_view_notification type)
{
- if (type == VIEW_NOTIFY_CURSOR_CHANGED)
+ if(type == VIEW_NOTIFY_CURSOR_CHANGED)
adjust_visible_y_for_cursor();
- else if (type == VIEW_NOTIFY_SOURCE_CHANGED)
+ else if(type == VIEW_NOTIFY_SOURCE_CHANGED)
m_expression.set_context(&downcast<const debug_view_disasm_source *>(m_source)->device()->debug()->symtable());
}
@@ -136,29 +128,29 @@ void debug_view_disasm::view_char(int chval)
u8 end_buffer = 3;
s32 temp;
- switch (chval)
+ switch(chval)
{
case DCH_UP:
- if (m_cursor.y > 0)
+ if(m_cursor.y > 0)
m_cursor.y--;
break;
case DCH_DOWN:
- if (m_cursor.y < m_total.y - 1)
+ if(m_cursor.y < m_total.y - 1)
m_cursor.y++;
break;
case DCH_PUP:
- temp = m_cursor.y - (m_visible.y - end_buffer);
- if (temp < 0)
+ temp = m_cursor.y -(m_visible.y - end_buffer);
+ if(temp < 0)
m_cursor.y = 0;
else
m_cursor.y = temp;
break;
case DCH_PDOWN:
- temp = m_cursor.y + (m_visible.y - end_buffer);
- if (temp > m_total.y - 1)
+ temp = m_cursor.y +(m_visible.y - end_buffer);
+ if(temp > m_total.y - 1)
m_cursor.y = m_total.y - 1;
else
m_cursor.y = temp;
@@ -167,11 +159,11 @@ void debug_view_disasm::view_char(int chval)
case DCH_HOME: // set the active column to the PC
{
const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
- offs_t pc = source.m_space.address_to_byte(source.device()->safe_pcbase()) & source.m_space.logbytemask();
+ offs_t pc = source.device()->safe_pcbase() & source.m_space.logaddrmask();
// figure out which row the pc is on
- for (unsigned int curline = 0; curline < m_dasm.size(); curline++)
- if (m_dasm[curline].m_byteaddress == pc)
+ for(unsigned int curline = 0; curline < m_dasm.size(); curline++)
+ if(m_dasm[curline].m_address == pc)
m_cursor.y = curline;
break;
}
@@ -186,7 +178,7 @@ void debug_view_disasm::view_char(int chval)
}
/* send a cursor changed notification */
- if (m_cursor.y != origcursor.y)
+ if(m_cursor.y != origcursor.y)
{
begin_update();
view_notify(VIEW_NOTIFY_CURSOR_CHANGED);
@@ -208,7 +200,7 @@ void debug_view_disasm::view_click(const int button, const debug_view_xy& pos)
/* cursor popup|toggle */
bool cursorVisible = true;
- if (m_cursor.y == origcursor.y)
+ if(m_cursor.y == origcursor.y)
{
cursorVisible = !m_cursor_visible;
}
@@ -221,218 +213,174 @@ void debug_view_disasm::view_click(const int button, const debug_view_xy& pos)
end_update();
}
+void debug_view_disasm::generate_from_address(debug_disasm_buffer &buffer, offs_t address)
+{
+ m_dasm.clear();
+ for(int i=0; i != m_total.y; i++) {
+ std::string dasm;
+ offs_t size;
+ offs_t next_address;
+ u32 info;
+ buffer.disassemble(address, dasm, next_address, size, info);
+ m_dasm.emplace_back(address, size, dasm);
+ address = next_address;
+ }
+}
-//-------------------------------------------------
-// find_pc_backwards - back up the specified
-// number of instructions from the given PC
-//-------------------------------------------------
-
-offs_t debug_view_disasm::find_pc_backwards(offs_t targetpc, int numinstrs)
+bool debug_view_disasm::generate_with_pc(debug_disasm_buffer &buffer, offs_t pc)
{
- auto dis = machine().disable_side_effect();
+ // Consider that instructions are 64 bytes max
const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
+ int shift = source.m_space.addrbus_shift();
- // compute the increment
- int minlen = source.m_space.byte_to_address(source.m_disasmintf->min_opcode_bytes());
- if (minlen == 0) minlen = 1;
- int maxlen = source.m_space.byte_to_address(source.m_disasmintf->max_opcode_bytes());
- if (maxlen == 0) maxlen = 1;
-
- // start off numinstrs back
- offs_t curpc = targetpc - minlen * numinstrs;
- if (curpc > targetpc)
- curpc = 0;
-
- /* loop until we find what we are looking for */
- offs_t targetpcbyte = source.m_space.address_to_byte(targetpc) & source.m_space.logbytemask();
- offs_t fillpcbyte = targetpcbyte;
- offs_t lastgoodpc = targetpc;
- while (1)
- {
- // fill the buffer up to the target
- offs_t curpcbyte = source.m_space.address_to_byte(curpc) & source.m_space.logbytemask();
- u8 opbuf[1024], argbuf[1024];
- while (curpcbyte < fillpcbyte)
- {
- fillpcbyte--;
- opbuf[1000 + fillpcbyte - targetpcbyte] = machine().debugger().cpu().read_opcode(source.m_decrypted_space, fillpcbyte, 1);
- argbuf[1000 + fillpcbyte - targetpcbyte] = machine().debugger().cpu().read_opcode(source.m_space, fillpcbyte, 1);
+ offs_t backwards_offset;
+ if(shift < 0)
+ backwards_offset = 64 >> -shift;
+ else if(shift == 0)
+ backwards_offset = 64;
+ else
+ backwards_offset = 64 << shift;
+
+ m_dasm.clear();
+ offs_t address = (pc - m_backwards_steps*backwards_offset) & source.m_space.logaddrmask();
+ // Handle wrap at 0
+ if(address > pc)
+ address = 0;
+
+ util::disasm_interface *intf = dynamic_cast<device_disasm_interface &>(*source.device()).get_disassembler();
+ if(intf->interface_flags() & util::disasm_interface::NONLINEAR_PC) {
+ offs_t lpc = intf->pc_real_to_linear(pc);
+ while(intf->pc_real_to_linear(address) < lpc) {
+ std::string dasm;
+ offs_t size;
+ offs_t next_address;
+ u32 info;
+ buffer.disassemble(address, dasm, next_address, size, info);
+ m_dasm.emplace_back(address, size, dasm);
+ if(intf->pc_real_to_linear(address) > intf->pc_real_to_linear(next_address))
+ return false;
+ address = next_address;
}
- // loop until we get past the target instruction
- int instcount = 0;
- int instlen;
- offs_t scanpc;
- for (scanpc = curpc; scanpc < targetpc; scanpc += instlen)
- {
- offs_t scanpcbyte = source.m_space.address_to_byte(scanpc) & source.m_space.logbytemask();
- offs_t physpcbyte = scanpcbyte;
-
- // get the disassembly, but only if mapped
- instlen = 1;
- if (source.m_space.device().memory().translate(source.m_space.spacenum(), TRANSLATE_FETCH, physpcbyte))
- {
- std::ostringstream dasmbuffer;
- instlen = source.m_disasmintf->disassemble(dasmbuffer, scanpc, &opbuf[1000 + scanpcbyte - targetpcbyte], &argbuf[1000 + scanpcbyte - targetpcbyte]) & DASMFLAG_LENGTHMASK;
- }
-
- // count this one
- instcount++;
+ } else {
+ while(address < pc) {
+ std::string dasm;
+ offs_t size;
+ offs_t next_address;
+ u32 info;
+ buffer.disassemble(address, dasm, next_address, size, info);
+ m_dasm.emplace_back(address, size, dasm);
+ if(address > next_address)
+ return false;
+ address = next_address;
}
+ }
- // if we ended up right on targetpc, this is a good candidate
- if (scanpc == targetpc && instcount <= numinstrs)
- lastgoodpc = curpc;
-
- // we're also done if we go back too far
- if (targetpc - curpc >= numinstrs * maxlen)
- break;
+ if(address != pc)
+ return false;
- // and if we hit 0, we're done
- if (curpc == 0)
- break;
+ if(m_dasm.size() > m_backwards_steps)
+ m_dasm.erase(m_dasm.begin(), m_dasm.begin() + (m_dasm.size() - m_backwards_steps));
- // back up one more and try again
- curpc -= minlen;
- if (curpc > targetpc)
- curpc = 0;
+ while(m_dasm.size() < m_total.y) {
+ std::string dasm;
+ offs_t size;
+ offs_t next_address;
+ u32 info;
+ buffer.disassemble(address, dasm, next_address, size, info);
+ m_dasm.emplace_back(address, size, dasm);
+ address = next_address;
}
-
- return lastgoodpc;
+ return true;
}
-
-//-------------------------------------------------
-// generate_bytes - generate the opcode byte
-// values
-//-------------------------------------------------
-
-std::string debug_view_disasm::generate_bytes(offs_t pcbyte, int numbytes, int granularity, bool encrypted)
+int debug_view_disasm::address_position(offs_t pc) const
{
- const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
- const int char_num = source.m_space.is_octal() ? 3 : 2;
- std::ostringstream ostr;
-
- for (int byte = 0; byte < numbytes; byte += granularity) {
- if (byte)
- ostr << ' ';
- util::stream_format(ostr, source.m_space.is_octal() ? "%0*o" : "%0*X", granularity * char_num, machine().debugger().cpu().read_opcode(encrypted ? source.m_space : source.m_decrypted_space, pcbyte + byte, granularity));
- }
-
- return ostr.str();
+ for(int i=0; i != int(m_dasm.size()); i++)
+ if(m_dasm[i].m_address == pc)
+ return i;
+ return -1;
}
-
-//-------------------------------------------------
-// recompute - recompute selected info for the
-// disassembly view
-//-------------------------------------------------
-
-bool debug_view_disasm::recompute(offs_t pc, int startline, int lines)
+void debug_view_disasm::generate_dasm(debug_disasm_buffer &buffer, offs_t pc)
{
- auto dis = machine().disable_side_effect();
-
- bool changed = false;
- const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
- const int char_num = source.m_space.is_octal() ? 3 : 2;
-
- // determine how many characters we need for an address and set the divider
- m_divider1 = 1 + (source.m_space.logaddrchars()/2*char_num) + 1;
+ bool pc_changed = pc != m_previous_pc;
+ m_previous_pc = pc;
+ if(strcmp(m_expression.string(), "curpc")) {
+ if(m_expression.dirty()) {
+ m_topleft.x = 0;
+ m_topleft.y = 0;
+ }
+ generate_from_address(buffer, m_expression.value());
+ return;
+ }
- // assume a fixed number of characters for the disassembly
- m_divider2 = m_divider1 + 1 + m_dasm_width + 1;
+ if(address_position(pc) != -1) {
+ generate_from_address(buffer, m_dasm[0].m_address);
+ int pos = address_position(pc);
+ if(pos != -1) {
+ if(!pc_changed)
+ return;
+ if(pos >= m_topleft.y && pos < m_topleft.y + m_visible.y)
+ return;
+ if(pos < m_total.y - m_visible.y) {
+ m_topleft.x = 0;
+ m_topleft.y = pos - m_backwards_steps;
+ return;
+ }
+ }
+ }
- // determine how many bytes we might need to display
- const int minbytes = source.m_disasmintf->min_opcode_bytes();
- const int maxbytes = source.m_disasmintf->max_opcode_bytes();
+ m_topleft.x = 0;
+ m_topleft.y = 0;
- // ensure that the PC is aligned to the minimum opcode size
- pc &= ~source.m_space.byte_to_address_end(minbytes - 1);
+ if(generate_with_pc(buffer, pc))
+ return;
- // set the width of the third column according to display mode
- if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED)
- {
- int const maxbytes_clamped = (std::min)(maxbytes, DASM_MAX_BYTES);
- m_total.x = m_divider2 + 1 + char_num * maxbytes_clamped + (maxbytes_clamped / minbytes - 1) + 1;
- }
- else if (m_right_column == DASM_RIGHTCOL_COMMENTS)
- m_total.x = m_divider2 + 1 + 50; // DEBUG_COMMENT_MAX_LINE_LENGTH
- else
- m_total.x = m_divider2 + 1;
+ generate_from_address(buffer, pc);
+}
- // allocate dasm array
- m_dasm.resize(m_total.y);
+void debug_view_disasm::complete_information(const debug_view_disasm_source &source, debug_disasm_buffer &buffer, offs_t pc)
+{
+ for(auto &dasm : m_dasm) {
+ offs_t adr = dasm.m_address;
- // comparison buffer to detect whether data changed when doing only one line
- dasm_line comparison_buffer;
+ dasm.m_tadr = buffer.pc_to_string(adr);
+ dasm.m_topcodes = buffer.data_to_string(adr, dasm.m_size, true);
+ dasm.m_tparams = buffer.data_to_string(adr, dasm.m_size, false);
- // iterate over lines
- for (int line = 0; line < lines; line++)
- {
- // convert PC to a byte offset
- const offs_t pcbyte = source.m_space.address_to_byte(pc) & source.m_space.logbytemask();
-
- // save a copy of the previous line as a backup if we're only doing one line
- const auto instr = startline + line;
- if (lines == 1)
- comparison_buffer = m_dasm[instr];
-
- // convert back and set the address of this instruction
- std::ostringstream oadr;
- m_dasm[instr].m_byteaddress = pcbyte;
- util::stream_format(oadr,
- source.m_space.is_octal() ? " %0*o " : " %0*X ",
- source.m_space.logaddrchars()/2*char_num, source.m_space.byte_to_address(pcbyte));
- m_dasm[instr].m_adr = oadr.str();
-
- // make sure we can translate the address, and then disassemble the result
- std::ostringstream dasm;
- int numbytes = 0;
- offs_t physpcbyte = pcbyte;
- if (source.m_space.device().memory().translate(source.m_space.spacenum(), TRANSLATE_FETCH_DEBUG, physpcbyte))
- {
- u8 opbuf[64], argbuf[64];
+ dasm.m_is_pc = adr == pc;
- // fetch the bytes up to the maximum
- for (numbytes = 0; numbytes < maxbytes; numbytes++)
- {
- opbuf[numbytes] = machine().debugger().cpu().read_opcode(source.m_decrypted_space, pcbyte + numbytes, 1);
- argbuf[numbytes] = machine().debugger().cpu().read_opcode(source.m_space, pcbyte + numbytes, 1);
+ dasm.m_is_bp = false;
+ for(device_debug::breakpoint *bp = source.device()->debug()->breakpoint_first(); bp != nullptr; bp = bp->next())
+ if(adr ==(bp->address() & source.m_space.logaddrmask())) {
+ dasm.m_is_bp = true;
+ break;
}
- // disassemble the result
- pc += numbytes = source.m_disasmintf->disassemble(dasm, pc & source.m_space.logaddrmask(), opbuf, argbuf) & DASMFLAG_LENGTHMASK;
- }
- else
- dasm << "<unmapped>";
-
- m_dasm[instr].m_dasm = dasm.str();
+ dasm.m_is_visited = source.device()->debug()->track_pc_visited(adr);
- // generate the byte views
- std::ostringstream bytes_raw;
- numbytes = source.m_space.address_to_byte(numbytes) & source.m_space.logbytemask();
- m_dasm[instr].m_rawdata = generate_bytes(pcbyte, numbytes, minbytes, false);
- m_dasm[instr].m_encdata = generate_bytes(pcbyte, numbytes, minbytes, true);
+ const char *comment = source.device()->debug()->comment_text(adr);
+ if(comment)
+ dasm.m_comment = comment;
+ }
+}
- // get and add the comment, if present
- const offs_t comment_address = source.m_space.byte_to_address(m_dasm[instr].m_byteaddress);
- const char *const text = source.device()->debug()->comment_text(comment_address);
- if (text != nullptr)
- m_dasm[instr].m_comment = text;
+//-------------------------------------------------
+// view_update - update the contents of the
+// disassembly view
+//-------------------------------------------------
- // see if the line changed at all
- if (lines == 1 && m_dasm[instr] != comparison_buffer)
- changed = true;
- }
+void debug_view_disasm::view_update()
+{
+ const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
+ debug_disasm_buffer buffer(*source.device());
+ offs_t pc = source.device()->safe_pcbase() & source.m_space.logaddrmask();
- // update opcode base information
- m_last_direct_decrypted = source.m_decrypted_space.direct().ptr();
- m_last_direct_raw = source.m_space.direct().ptr();
- m_last_change_count = source.device()->debug()->comment_change_count();
+ generate_dasm(buffer, pc);
- // no longer need to recompute
- m_recompute = false;
- return changed;
+ complete_information(source, buffer, pc);
+ redraw();
}
@@ -443,11 +391,11 @@ bool debug_view_disasm::recompute(offs_t pc, int startline, int lines)
void debug_view_disasm::print(int row, std::string text, int start, int end, u8 attrib)
{
int view_end = end - m_topleft.x;
- if (view_end < 0)
+ if(view_end < 0)
return;
int string_0 = start - m_topleft.x;
- if (string_0 >= m_visible.x)
+ if(string_0 >= m_visible.x)
return;
int view_start = string_0 > 0 ? string_0 : 0;
@@ -458,152 +406,63 @@ void debug_view_disasm::print(int row, std::string text, int start, int end, u8
for(int pos = view_start; pos < view_end; pos++) {
int spos = pos - string_0;
- if (spos >= int(text.size()))
+ if(spos >= int(text.size()))
*dest++ = { ' ', attrib };
else
*dest++ = { u8(text[spos]), attrib };
- }
+ }
}
+
//-------------------------------------------------
-// view_update - update the contents of the
-// disassembly view
+// redraw - update the view from the data
//-------------------------------------------------
-void debug_view_disasm::view_update()
+void debug_view_disasm::redraw()
{
- const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
-
- offs_t pc = source.device()->safe_pcbase();
- offs_t pcbyte = source.m_space.address_to_byte(pc) & source.m_space.logbytemask();
-
- // update our context; if the expression is dirty, recompute
- if (m_expression.dirty())
- m_recompute = true;
-
- // if we're tracking a value, make sure it is visible
- u64 previous = m_expression.last_value();
- u64 result = m_expression.value();
- if (result != previous)
- {
- offs_t resultbyte = source.m_space.address_to_byte(result) & source.m_space.logbytemask();
-
- // see if the new result is an address we already have
- u32 row;
- for (row = 0; row < m_dasm.size(); row++)
- if (m_dasm[row].m_byteaddress == resultbyte)
- break;
-
- // if we didn't find it, or if it's really close to the bottom, recompute
- if (row == m_dasm.size() || row >= m_total.y - m_visible.y)
- m_recompute = true;
-
- // otherwise, if it's not visible, adjust the view so it is
- else if (row < m_topleft.y || row >= m_topleft.y + m_visible.y - 2)
- m_topleft.y = (row > 3) ? row - 3 : 0;
- }
-
- // if the opcode base has changed, rework things
- if (source.m_decrypted_space.direct().ptr() != m_last_direct_decrypted || source.m_space.direct().ptr() != m_last_direct_raw)
- m_recompute = true;
-
- // if the comments have changed, redo it
- if (m_last_change_count != source.device()->debug()->comment_change_count())
- m_recompute = true;
-
- // if we need to recompute, do it
- bool recomputed_this_time = false;
-recompute:
- if (m_recompute)
- {
- // recompute the view
- if (!m_dasm.empty() && m_last_change_count != source.device()->debug()->comment_change_count())
- {
- // smoosh us against the left column, but not the top row
- m_topleft.x = 0;
-
- // recompute from where we last recomputed!
- recompute(source.m_space.byte_to_address(m_dasm[0].m_byteaddress), 0, m_total.y);
- }
- else
- {
- // determine the addresses of what we will display
- offs_t backpc = find_pc_backwards(u32(m_expression.value()), m_backwards_steps);
-
- // put ourselves back in the top left
- m_topleft.y = 0;
- m_topleft.x = 0;
-
- recompute(backpc, 0, m_total.y);
- }
- recomputed_this_time = true;
- }
+ // determine how many characters we need for an address and set the divider
+ int m_divider1 = 1 + m_dasm[0].m_tadr.size() + 1;
- // figure out the row where the PC is and recompute the disassembly
- if (pcbyte != m_last_pcbyte)
- {
- // find the row with the PC on it
- for (u32 row = 0; row < m_visible.y; row++)
- {
- u32 effrow = m_topleft.y + row;
- if (effrow >= m_dasm.size())
- break;
- if (pcbyte == m_dasm[effrow].m_byteaddress)
- {
- // see if we changed
- bool changed = recompute(pc, effrow, 1);
- if (changed && !recomputed_this_time)
- {
- m_recompute = true;
- goto recompute;
- }
+ // assume a fixed number of characters for the disassembly
+ int m_divider2 = m_divider1 + 1 + m_dasm_width + 1;
- // set the effective row and PC
- m_cursor.y = effrow;
- view_notify(VIEW_NOTIFY_CURSOR_CHANGED);
- }
- }
- m_last_pcbyte = pcbyte;
- }
+ // set the width of the third column to max comment length
+ m_total.x = m_divider2 + 1 + 50; // DEBUG_COMMENT_MAX_LINE_LENGTH
// loop over visible rows
- for (u32 row = 0; row < m_visible.y; row++)
+ for(u32 row = 0; row < m_visible.y; row++)
{
u32 effrow = m_topleft.y + row;
// if this visible row is valid, add it to the buffer
u8 attrib = DCA_NORMAL;
- if (effrow < m_dasm.size())
+ if(effrow < m_dasm.size())
{
- // if we're on the line with the PC, recompute and hilight it
- if (pcbyte == m_dasm[effrow].m_byteaddress)
+ // if we're on the line with the PC, hilight it
+ if(m_dasm[effrow].m_is_pc)
attrib = DCA_CURRENT;
// if we're on a line with a breakpoint, tag it changed
- else
- {
- for (device_debug::breakpoint *bp = source.device()->debug()->breakpoint_first(); bp != nullptr; bp = bp->next())
- if (m_dasm[effrow].m_byteaddress == (source.m_space.address_to_byte(bp->address()) & source.m_space.logbytemask()))
- attrib = DCA_CHANGED;
- }
+ else if(m_dasm[effrow].m_is_bp)
+ attrib = DCA_CHANGED;
// if we're on the active column and everything is couth, highlight it
- if (m_cursor_visible && effrow == m_cursor.y)
+ if(m_cursor_visible && effrow == m_cursor.y)
attrib |= DCA_SELECTED;
// if we've visited this pc, mark it as such
- if (source.device()->debug()->track_pc_visited(m_dasm[effrow].m_byteaddress))
+ if(m_dasm[effrow].m_is_visited)
attrib |= DCA_VISITED;
- print(row, m_dasm[effrow].m_adr, 0, m_divider1, attrib | DCA_ANCILLARY);
+ print(row, ' ' + m_dasm[effrow].m_tadr, 0, m_divider1, attrib | DCA_ANCILLARY);
print(row, ' ' + m_dasm[effrow].m_dasm, m_divider1, m_divider2, attrib);
- if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED) {
- std::string text = ' ' + (m_right_column == DASM_RIGHTCOL_RAW ? m_dasm[effrow].m_rawdata : m_dasm[effrow].m_encdata);
+ if(m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED) {
+ std::string text = ' ' +(m_right_column == DASM_RIGHTCOL_RAW ? m_dasm[effrow].m_topcodes : m_dasm[effrow].m_tparams);
print(row, text, m_divider2, m_visible.x, attrib | DCA_ANCILLARY);
if(int(text.size()) > m_visible.x - m_divider2) {
int base = m_total.x - 3;
- if (base < m_divider2)
+ if(base < m_divider2)
base = m_divider2;
print(row, "...", base, m_visible.x, attrib | DCA_ANCILLARY);
}
@@ -624,7 +483,7 @@ recompute:
offs_t debug_view_disasm::selected_address()
{
flush_updates();
- return downcast<const debug_view_disasm_source &>(*m_source).m_space.byte_to_address(m_dasm[m_cursor.y].m_byteaddress);
+ return m_dasm[m_cursor.y].m_address;
}
@@ -679,7 +538,7 @@ void debug_view_disasm::set_disasm_width(u32 width)
{
begin_update();
m_dasm_width = width;
- m_recompute = m_update_pending = true;
+ m_update_pending = true;
end_update();
}
@@ -692,10 +551,9 @@ void debug_view_disasm::set_disasm_width(u32 width)
void debug_view_disasm::set_selected_address(offs_t address)
{
const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
- offs_t byteaddress = source.m_space.address_to_byte(address) & source.m_space.logbytemask();
- for (int line = 0; line < m_total.y; line++)
- if (m_dasm[line].m_byteaddress == byteaddress)
- {
+ address = address & source.m_space.logaddrmask();
+ for(int line = 0; line < m_total.y; line++)
+ if(m_dasm[line].m_address == address) {
m_cursor.y = line;
set_cursor_position(m_cursor);
break;
diff --git a/src/emu/debug/dvdisasm.h b/src/emu/debug/dvdisasm.h
index 85ebd7cfef2..dcf756117b8 100644
--- a/src/emu/debug/dvdisasm.h
+++ b/src/emu/debug/dvdisasm.h
@@ -14,6 +14,7 @@
#pragma once
#include "debugvw.h"
+#include "debugbuf.h"
#include "vecstream.h"
@@ -51,7 +52,6 @@ public:
private:
// internal state
- device_disasm_interface *m_disasmintf; // disassembly interface
address_space & m_space; // address space to display
address_space & m_decrypted_space; // address space to display for decrypted opcodes
};
@@ -90,49 +90,42 @@ protected:
private:
// The information of one disassembly line. May become the actual
- // external interface at one point
+ // external interface at one point.
struct dasm_line {
- offs_t m_byteaddress; // address of the first byte of the instruction
- std::string m_adr; // instruction address as a string
+ offs_t m_address; // address of the instruction
+ offs_t m_size; // size of the instruction
+
+ std::string m_tadr; // instruction address as a string
std::string m_dasm; // disassembly
- std::string m_rawdata; // textual representation of the instruction values
- std::string m_encdata; // textual representation of encrypted instruction values
+ std::string m_topcodes; // textual representation of opcode/default values
+ std::string m_tparams; // textual representation of parameter values
std::string m_comment; // comment, when present
- bool operator == (const dasm_line &right) const {
- return
- m_byteaddress == right.m_byteaddress &&
- m_adr == right.m_adr &&
- m_dasm == right.m_dasm &&
- m_rawdata == right.m_rawdata &&
- m_encdata == right.m_encdata &&
- m_comment == right.m_comment;
- }
-
- bool operator != (const dasm_line &right) const {
- return !(*this == right);
- }
+ bool m_is_pc; // this line's address is PC
+ bool m_is_bp; // this line's address is a breakpoint
+ bool m_is_visited; // this line has been visited
+
+ dasm_line(offs_t address, offs_t size, std::string dasm) : m_address(address), m_size(size), m_dasm(dasm), m_is_pc(false), m_is_bp(false), m_is_visited(false) {}
};
// internal helpers
+ void generate_from_address(debug_disasm_buffer &buffer, offs_t address);
+ bool generate_with_pc(debug_disasm_buffer &buffer, offs_t pc);
+ int address_position(offs_t pc) const;
+ void generate_dasm(debug_disasm_buffer &buffer, offs_t pc);
+ void complete_information(const debug_view_disasm_source &source, debug_disasm_buffer &buffer, offs_t pc);
+
void enumerate_sources();
- offs_t find_pc_backwards(offs_t targetpc, int numinstrs);
- std::string generate_bytes(offs_t pcbyte, int numbytes, int granularity, bool encrypted);
- bool recompute(offs_t pc, int startline, int lines);
void print(int row, std::string text, int start, int end, u8 attrib);
+ void redraw();
// internal state
- disasm_right_column m_right_column; // right column contents
- u32 m_backwards_steps; // number of backwards steps
- u32 m_dasm_width; // width of the disassembly area
- u8 * m_last_direct_raw; // last direct raw value
- u8 * m_last_direct_decrypted;// last direct decrypted value
- u32 m_last_change_count; // last comment change count
- offs_t m_last_pcbyte; // last PC byte value
- int m_divider1, m_divider2; // left and right divider columns
- int m_divider3; // comment divider column
- debug_view_expression m_expression; // expression-related information
- std::vector<dasm_line> m_dasm; // disassembled instructions
+ disasm_right_column m_right_column; // right column contents
+ u32 m_backwards_steps; // number of backwards steps
+ u32 m_dasm_width; // width of the disassembly area
+ offs_t m_previous_pc; // previous pc, to detect whether it changed
+ debug_view_expression m_expression; // expression-related information
+ std::vector<dasm_line> m_dasm; // disassembled instructions
// constants
static constexpr int DEFAULT_DASM_LINES = 1000;
diff --git a/src/emu/debug/dvmemory.cpp b/src/emu/debug/dvmemory.cpp
index a5de89adb30..e32d576fa65 100644
--- a/src/emu/debug/dvmemory.cpp
+++ b/src/emu/debug/dvmemory.cpp
@@ -531,7 +531,7 @@ void debug_view_memory::recompute()
int addrchars;
if (source.m_space != nullptr)
{
- m_maxaddr = m_no_translation ? source.m_space->bytemask() : source.m_space->logbytemask();
+ m_maxaddr = m_no_translation ? source.m_space->addrmask() : source.m_space->logaddrmask();
addrchars = m_no_translation ? source.m_space->addrchars() : source.m_space->logaddrchars();
}
else
@@ -547,6 +547,8 @@ void debug_view_memory::recompute()
m_addrformat = string_format("%%0%dX%*s", addrchars, 8 - addrchars, "");
// if we are viewing a space with a minimum chunk size, clamp the bytes per chunk
+ // BAD
+#if 0
if (source.m_space != nullptr && source.m_space->byte_to_address(1) > 1)
{
u32 min_bytes_per_chunk = source.m_space->byte_to_address(1);
@@ -557,6 +559,7 @@ void debug_view_memory::recompute()
}
m_chunks_per_row = std::max(1U, m_chunks_per_row);
}
+#endif
// recompute the byte offset based on the most recent expression result
m_bytes_per_row = m_bytes_per_chunk * m_chunks_per_row;
@@ -617,7 +620,7 @@ bool debug_view_memory::needs_recompute()
const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
offs_t resultbyte;
if (source.m_space != nullptr)
- resultbyte = source.m_space->address_to_byte(m_expression.value()) & source.m_space->logbytemask();
+ resultbyte = m_expression.value() & source.m_space->logaddrmask();
else
resultbyte = m_expression.value();