summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug/debugbuf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/debug/debugbuf.cpp')
-rw-r--r--src/emu/debug/debugbuf.cpp1381
1 files changed, 1381 insertions, 0 deletions
diff --git a/src/emu/debug/debugbuf.cpp b/src/emu/debug/debugbuf.cpp
new file mode 100644
index 00000000000..96392f60bf5
--- /dev/null
+++ b/src/emu/debug/debugbuf.cpp
@@ -0,0 +1,1381 @@
+// 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);
+}
+
+u16 debug_disasm_buffer::debug_data_buffer::r16(offs_t pc) const
+{
+ return m_do_r16(pc);
+}
+
+u32 debug_disasm_buffer::debug_data_buffer::r32(offs_t pc) const
+{
+ return m_do_r32(pc);
+}
+
+u64 debug_disasm_buffer::debug_data_buffer::r64(offs_t pc) const
+{
+ return m_do_r64(pc);
+}
+
+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_wrapped) {
+ if(lstart >= m_lstart && (lend > m_lstart || lend <= m_lend))
+ return;
+ if(lstart < m_lend && lend <= m_lend)
+ return;
+ } else {
+ if(m_lend && lstart >= m_lstart && lend <= m_lend)
+ return;
+ if(!m_lend && lstart >= m_lstart)
+ return;
+ if(m_lstart == 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 << 1);
+ 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 << 3);
+ 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 << 2);
+ 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 << 1);
+ 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 >> 3);
+ 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) | (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) | (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);
+}