summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2020-02-12 11:23:51 -0500
committer AJR <ajrhacker@users.noreply.github.com>2020-02-12 11:59:41 -0500
commit9ce46c7cd54200d2896bdd7ad10ee31201b63985 (patch)
tree749c321594a4e733313a7ea581c080d88c28fa4b
parent2d3e38c384026fd053534c4c62bddbe7ee41661a (diff)
New machines marked as NOT_WORKING
---------------------------------- Roland D-50 (Ver. 2.xx) [DBWBP, depblue] New NOT_WORKING clones ---------------------- Roland D-50 (Ver. 1.xx) [DBWBP] Roland D-550 [DBWBP] Add disassembler for NEC 78K/III architecture [AJR]
-rw-r--r--scripts/src/cpu.lua4
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/cpu/upd78k/upd78k3.cpp347
-rw-r--r--src/devices/cpu/upd78k/upd78k3.h114
-rw-r--r--src/devices/cpu/upd78k/upd78k3d.cpp1648
-rw-r--r--src/devices/cpu/upd78k/upd78k3d.h164
-rw-r--r--src/devices/cpu/upd78k/upd78kd.cpp12
-rw-r--r--src/devices/cpu/upd78k/upd78kd.h1
-rw-r--r--src/mame/drivers/roland_d50.cpp110
-rw-r--r--src/mame/mame.lst5
-rw-r--r--src/mame/mess.flt1
-rw-r--r--src/tools/unidasm.cpp9
12 files changed, 2416 insertions, 0 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 0913af02d75..c11149c85fb 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -3145,6 +3145,8 @@ if (CPUS["UPD78K"]~=null) then
MAME_DIR .. "src/devices/cpu/upd78k/upd78k0.h",
MAME_DIR .. "src/devices/cpu/upd78k/upd78k2.cpp",
MAME_DIR .. "src/devices/cpu/upd78k/upd78k2.h",
+ MAME_DIR .. "src/devices/cpu/upd78k/upd78k3.cpp",
+ MAME_DIR .. "src/devices/cpu/upd78k/upd78k3.h",
}
end
@@ -3157,4 +3159,6 @@ if (CPUS["UPD78K"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/upd78k/upd78k1d.h")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/upd78k/upd78k2d.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/upd78k/upd78k2d.h")
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/upd78k/upd78k3d.cpp")
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/upd78k/upd78k3d.h")
end
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 81a2fe0f993..3ec53d58e92 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -3211,6 +3211,7 @@ files {
createMESSProjects(_target, _subtarget, "roland")
files {
MAME_DIR .. "src/mame/drivers/roland_cm32p.cpp",
+ MAME_DIR .. "src/mame/drivers/roland_d50.cpp",
MAME_DIR .. "src/mame/drivers/roland_d110.cpp",
MAME_DIR .. "src/mame/drivers/roland_mt32.cpp",
MAME_DIR .. "src/mame/drivers/roland_sc55.cpp",
diff --git a/src/devices/cpu/upd78k/upd78k3.cpp b/src/devices/cpu/upd78k/upd78k3.cpp
new file mode 100644
index 00000000000..473d8a9fb9c
--- /dev/null
+++ b/src/devices/cpu/upd78k/upd78k3.cpp
@@ -0,0 +1,347 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/****************************************************************************
+
+ NEC 78K/III series 16/8-bit single-chip microcontrollers
+
+ Currently these devices are just stubs with no actual execution core.
+
+****************************************************************************/
+
+#include "emu.h"
+#include "upd78k3.h"
+#include "upd78k3d.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(UPD78312, upd78312_device, "upd78312", "NEC uPD78312")
+
+//**************************************************************************
+// 78K/III CORE
+//**************************************************************************
+
+//-------------------------------------------------
+// upd78k3_device - constructor
+//-------------------------------------------------
+
+upd78k3_device::upd78k3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor mem_map, address_map_constructor sfr_map)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, mem_map)
+ , m_iram_config("IRAM", ENDIANNESS_LITTLE, 16, 8, 0, address_map_constructor(FUNC(upd78k3_device::iram_map), this))
+ , m_sfr_config("SFR", ENDIANNESS_LITTLE, 16, 8, 0, sfr_map)
+ , m_program_space(nullptr)
+ , m_program_cache(nullptr)
+ , m_iram_cache(nullptr)
+ , m_sfr_space(nullptr)
+ , m_pc(0)
+ , m_ppc(0)
+ , m_psw(0)
+ , m_sp(0)
+ , m_icount(0)
+{
+}
+
+
+//-------------------------------------------------
+// iram_map - type-universal IRAM map
+//-------------------------------------------------
+
+void upd78k3_device::iram_map(address_map &map)
+{
+ map(0x00, 0xff).ram().share("iram");
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a vector of
+// address space configurations for this device
+//-------------------------------------------------
+
+device_memory_interface::space_config_vector upd78k3_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config),
+ std::make_pair(AS_DATA, &m_iram_config),
+ std::make_pair(AS_IO, &m_sfr_config)
+ };
+}
+
+
+//-------------------------------------------------
+// register_base - determine current base of
+// register file in IRAM
+//-------------------------------------------------
+
+inline u8 upd78k3_device::register_base() const noexcept
+{
+ return 0x80 | (~m_psw & 0x7000) >> 8;
+}
+
+
+//-------------------------------------------------
+// state_add_psw - overridable method for PSW
+// state registration
+//-------------------------------------------------
+
+void upd78k3_device::state_add_psw()
+{
+ state_add(UPD78K3_PSW, "PSW", m_psw).mask(0xf0fd);
+ state_add(STATE_GENFLAGS, "FLAGS", m_psw).mask(0xf0fd).formatstr("%12s").noshow();
+ state_add<u8>(UPD78K3_PSWL, "PSWL",
+ [this]() { return m_psw & 0x00ff; },
+ [this](u8 data) { m_psw = (m_psw & 0xff00) | data; }
+ ).mask(0xfd).noshow();
+ state_add<u8>(UPD78K3_PSWH, "PSWH",
+ [this]() { return (m_psw & 0xff00) >> 8; },
+ [this](u8 data) { m_psw = (m_psw & 0x00ff) | u16(data) << 8; }
+ ).mask(0xf0).noshow();
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void upd78k3_device::device_start()
+{
+ // get address spaces and access caches
+ m_program_space = &space(AS_PROGRAM);
+ m_program_cache = m_program_space->cache<0, 0, ENDIANNESS_LITTLE>();
+ m_iram_cache = space(AS_DATA).cache<1, 0, ENDIANNESS_LITTLE>();
+ m_sfr_space = &space(AS_IO);
+
+ set_icountptr(m_icount);
+
+ // debug state
+ state_add(UPD78K3_PC, "PC", m_pc);
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow();
+ state_add_psw();
+ state_add<u8>(UPD78K3_RBS, "RBS",
+ [this]() { return (m_psw & 7000) >> 12; },
+ [this](u8 data) { m_psw = (m_psw & 0x8fff) | u16(data) << 12; }
+ ).mask(7).noshow();
+ state_add(UPD78K3_SP, "SP", m_sp);
+ void *iram = memshare("iram")->ptr();
+ for (int n = 0; n < 4; n++)
+ state_add<u16>(UPD78K3_RP0 + n, string_format("RP%d", n).c_str(),
+ [this, iram, n]() { return static_cast<u16 *>(iram)[register_base() >> 1 | n]; },
+ [this, iram, n](u16 data) { static_cast<u16 *>(iram)[register_base() >> 1 | n] = data; }
+ ).formatstr("%9s");
+ for (int n = 0; n < 2; n++)
+ state_add<u16>(UPD78K3_AX + n, std::array<const char *, 2>{{"AX", "BC"}}[n],
+ [this, iram, n]() { return static_cast<u16 *>(iram)[register_base() >> 1 | (m_psw & 0x0020) >> 4 | n]; },
+ [this, iram, n](u16 data) { static_cast<u16 *>(iram)[register_base() >> 1 | (m_psw & 0x0020) >> 4 | n] = data; }
+ ).noshow();
+ for (int n = 0; n < 4; n++)
+ {
+ state_add<u16>(UPD78K3_VP + n, std::array<const char *, 4>{{"VP", "UP", "DE", "HL"}}[n],
+ [this, iram, n]() { return static_cast<u16 *>(iram)[register_base() >> 1 | 0x04 | n]; },
+ [this, iram, n](u16 data) { static_cast<u16 *>(iram)[register_base() >> 1 | 0x04 | n] = data; }
+ );
+ state_add<u16>(UPD78K3_RP4 + n, string_format("RP%d", 4 + n).c_str(),
+ [this, iram, n]() { return static_cast<u16 *>(iram)[register_base() >> 1 | 0x04 | n]; },
+ [this, iram, n](u16 data) { static_cast<u16 *>(iram)[register_base() >> 1 | 0x04 | n] = data; }
+ ).noshow();
+ }
+ for (int n = 0; n < 16; n++)
+ state_add<u8>(UPD78K3_R0 + n, string_format("R%d", n).c_str(),
+ [this, iram, n]() { return static_cast<u8 *>(iram)[BYTE_XOR_LE(register_base() | n)]; },
+ [this, iram, n](u8 data) { static_cast<u8 *>(iram)[BYTE_XOR_LE(register_base() | n)] = data; }
+ ).noshow();
+ for (int n = 0; n < 4; n++)
+ state_add<u8>(UPD78K3_X + n, std::array<const char *, 4>{{"X", "A", "C", "B"}}[n],
+ [this, iram, n]() { return static_cast<u8 *>(iram)[BYTE_XOR_LE(register_base() | (m_psw & 0x0020) >> 3 | n)]; },
+ [this, iram, n](u8 data) { static_cast<u8 *>(iram)[BYTE_XOR_LE(register_base() | (m_psw & 0x0020) >> 3 | n)] = data; }
+ ).noshow();
+ for (int n = 0; n < 8; n++)
+ state_add<u8>(UPD78K3_VPL + n, std::array<const char *, 8>{{"VPL", "VPH", "UPL", "UPH", "E", "D", "L", "H"}}[n],
+ [this, iram, n]() { return static_cast<u8 *>(iram)[BYTE_XOR_LE(register_base() | 0x08 | n)]; },
+ [this, iram, n](u8 data) { static_cast<u8 *>(iram)[BYTE_XOR_LE(register_base() | 0x08 | n)] = data; }
+ ).noshow();
+
+ // save state
+ save_item(NAME(m_pc));
+ save_item(NAME(m_ppc));
+ save_item(NAME(m_sp));
+ save_item(NAME(m_psw));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void upd78k3_device::device_reset()
+{
+ // PC will be initialized from vector following reset
+ m_psw = 0x0000;
+}
+
+
+//-------------------------------------------------
+// execute_run -
+//-------------------------------------------------
+
+void upd78k3_device::execute_run()
+{
+ m_pc = m_program_cache->read_word(0);
+ m_ppc = m_pc;
+ debugger_instruction_hook(m_pc);
+
+ // TODO
+ m_icount = 0;
+}
+
+
+//-------------------------------------------------
+// state_string_export -
+//-------------------------------------------------
+
+void upd78k3_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("RB%d:%c%c%c%c%c%c%c%c",
+ (m_psw & 0x7000) >> 12,
+ BIT(m_psw, 15) ? 'U' : '.',
+ BIT(m_psw, 7) ? 'S' : '.',
+ BIT(m_psw, 6) ? 'Z' : '.',
+ BIT(m_psw, 5) ? 'R' : '.',
+ BIT(m_psw, 4) ? 'A' : '.',
+ BIT(m_psw, 3) ? 'I' : '.',
+ BIT(m_psw, 2) ? 'V' : '.',
+ BIT(m_psw, 0) ? 'C' : '.');
+ break;
+
+#if 0 // doesn't compile because value() is protected
+ case UPD78K3_RP0:
+ str = string_format("%04X %s", entry.value(), BIT(m_psw, 5) ? " " : "(AX)");
+ break;
+
+ case UPD78K3_RP1:
+ str = string_format("%04X %s", entry.value(), BIT(m_psw, 5) ? " " : "(BC)");
+ break;
+
+ case UPD78K3_RP2:
+ str = string_format("%04X %s", entry.value(), BIT(m_psw, 5) ? "(AX)" : " ");
+ break;
+
+ case UPD78K3_RP3:
+ str = string_format("%04X %s", entry.value(), BIT(m_psw, 5) ? "(BC)" : " ");
+ break;
+#else // nasty and inefficient workaround
+ case UPD78K3_RP0:
+ str = string_format("%04X %s", const_cast<upd78k3_device &>(*this).state_int(UPD78K3_RP0), BIT(m_psw, 5) ? " " : "(AX)");
+ break;
+
+ case UPD78K3_RP1:
+ str = string_format("%04X %s", const_cast<upd78k3_device &>(*this).state_int(UPD78K3_RP1), BIT(m_psw, 5) ? " " : "(BC)");
+ break;
+
+ case UPD78K3_RP2:
+ str = string_format("%04X %s", const_cast<upd78k3_device &>(*this).state_int(UPD78K3_RP2), BIT(m_psw, 5) ? "(AX)" : " ");
+ break;
+
+ case UPD78K3_RP3:
+ str = string_format("%04X %s", const_cast<upd78k3_device &>(*this).state_int(UPD78K3_RP3), BIT(m_psw, 5) ? "(BC)" : " ");
+ break;
+#endif
+ }
+}
+
+
+//**************************************************************************
+// 78K/III SUBSERIES DEVICES
+//**************************************************************************
+
+//-------------------------------------------------
+// upd78312_device - constructor
+//-------------------------------------------------
+
+upd78312_device::upd78312_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : upd78k3_device(mconfig, UPD78312, tag, owner, clock,
+ address_map_constructor(FUNC(upd78312_device::mem_map), this),
+ address_map_constructor(FUNC(upd78312_device::sfr_map), this))
+{
+}
+
+
+//-------------------------------------------------
+// create_disassembler -
+//-------------------------------------------------
+
+std::unique_ptr<util::disasm_interface> upd78312_device::create_disassembler()
+{
+ return std::make_unique<upd78312_disassembler>();
+}
+
+
+//-------------------------------------------------
+// mem_map - type-specific internal memory map
+// (excluding IRAM and SFRs)
+//-------------------------------------------------
+
+void upd78312_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x1fff).rom().region(DEVICE_SELF, 0); // 8K mask ROM
+}
+
+
+//-------------------------------------------------
+// sfr_map - type-specific SFR map
+//-------------------------------------------------
+
+void upd78312_device::sfr_map(address_map &map)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// state_add_psw - overridable method for PSW
+// state registration
+//-------------------------------------------------
+
+void upd78312_device::state_add_psw()
+{
+ state_add(UPD78K3_PSW, "PSW", m_psw).mask(0x72ff);
+ state_add(STATE_GENFLAGS, "FLAGS", m_psw).mask(0x72ff).formatstr("%13s").noshow();
+ state_add<u8>(UPD78K3_PSWL, "PSWL",
+ [this]() { return m_psw & 0x00ff; },
+ [this](u8 data) { m_psw = (m_psw & 0xff00) | data; }
+ ).noshow();
+ state_add<u8>(UPD78K3_PSWH, "PSWH",
+ [this]() { return (m_psw & 0xff00) >> 8; },
+ [this](u8 data) { m_psw = (m_psw & 0x00ff) | u16(data) << 8; }
+ ).mask(0x72).noshow();
+}
+
+
+//-------------------------------------------------
+// state_string_export -
+//-------------------------------------------------
+
+void upd78312_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("RB%d:%c%c%c%c%c%c%c%c%c",
+ (m_psw & 0x7000) >> 12,
+ BIT(m_psw, 9) ? 'I' : '.',
+ BIT(m_psw, 7) ? 'S' : '.',
+ BIT(m_psw, 6) ? 'Z' : '.',
+ BIT(m_psw, 5) ? 'R' : '.',
+ BIT(m_psw, 4) ? 'A' : '.',
+ BIT(m_psw, 3) ? 'I' : '.',
+ BIT(m_psw, 2) ? 'V' : '.',
+ BIT(m_psw, 1) ? '-' : '+',
+ BIT(m_psw, 0) ? 'C' : '.');
+ break;
+
+ default:
+ upd78k3_device::state_string_export(entry, str);
+ break;
+ }
+}
diff --git a/src/devices/cpu/upd78k/upd78k3.h b/src/devices/cpu/upd78k/upd78k3.h
new file mode 100644
index 00000000000..6625bb50474
--- /dev/null
+++ b/src/devices/cpu/upd78k/upd78k3.h
@@ -0,0 +1,114 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ NEC 78K/III series 16/8-bit single-chip microcontrollers
+
+**********************************************************************/
+
+#ifndef MAME_CPU_UPD78K_UPD78K3_H
+#define MAME_CPU_UPD78K_UPD78K3_H
+
+#pragma once
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> upd78k3_device
+
+class upd78k3_device : public cpu_device
+{
+public:
+ enum {
+ UPD78K3_PC,
+ UPD78K3_PSW, UPD78K3_PSWL, UPD78K3_PSWH, UPD78K3_RBS, UPD78K3_SP,
+ UPD78K3_RP0, UPD78K3_RP1, UPD78K3_RP2, UPD78K3_RP3,
+ UPD78K3_RP4, UPD78K3_RP5, UPD78K3_RP6, UPD78K3_RP7,
+ UPD78K3_AX, UPD78K3_BC,
+ UPD78K3_VP, UPD78K3_UP, UPD78K3_DE, UPD78K3_HL,
+ UPD78K3_R0, UPD78K3_R1, UPD78K3_R2, UPD78K3_R3,
+ UPD78K3_R4, UPD78K3_R5, UPD78K3_R6, UPD78K3_R7,
+ UPD78K3_R8, UPD78K3_R9, UPD78K3_R10, UPD78K3_R11,
+ UPD78K3_R12, UPD78K3_R13, UPD78K3_R14, UPD78K3_R15,
+ UPD78K3_X, UPD78K3_A, UPD78K3_C, UPD78K3_B,
+ UPD78K3_VPL, UPD78K3_VPH, UPD78K3_UPL, UPD78K3_UPH,
+ UPD78K3_E, UPD78K3_D, UPD78K3_L, UPD78K3_H
+ };
+
+ // TODO: callbacks and configuration thereof
+
+protected:
+ upd78k3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor mem_map, address_map_constructor sfr_map);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual void execute_run() override;
+ virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 2 - 1) / 2; }
+ virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 2); }
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ virtual void state_add_psw();
+
+private:
+ // internal memory map
+ void iram_map(address_map &map);
+
+ // internal helpers
+ inline u8 register_base() const noexcept;
+
+ // address spaces, caches & configuration
+ address_space_config m_program_config;
+ address_space_config m_iram_config;
+ address_space_config m_sfr_config;
+ address_space *m_program_space;
+ memory_access_cache<0, 0, ENDIANNESS_LITTLE> *m_program_cache;
+ memory_access_cache<1, 0, ENDIANNESS_LITTLE> *m_iram_cache;
+ address_space *m_sfr_space;
+
+ // core registers and execution state
+ u16 m_pc;
+ u16 m_ppc;
+protected:
+ u16 m_psw;
+private:
+ u16 m_sp;
+ s32 m_icount;
+};
+
+// ======================> upd78312_device
+
+class upd78312_device : public upd78k3_device
+{
+public:
+ // device type constructor
+ upd78312_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // upd78k3_device overrides
+ virtual void state_add_psw() override;
+
+private:
+ // type-specific internal memory maps
+ void mem_map(address_map &map);
+ void sfr_map(address_map &map);
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(UPD78312, upd78312_device)
+
+#endif // MAME_CPU_UPD78K_UPD7832_H
diff --git a/src/devices/cpu/upd78k/upd78k3d.cpp b/src/devices/cpu/upd78k/upd78k3d.cpp
new file mode 100644
index 00000000000..819724dece7
--- /dev/null
+++ b/src/devices/cpu/upd78k/upd78k3d.cpp
@@ -0,0 +1,1648 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#include "emu.h"
+#include "upd78k3d.h"
+
+upd78k3_disassembler::upd78k3_disassembler(const char *const sfr_names[], const char *const sfrp_names[], const char *const psw_bits[], bool has_macw, bool has_macsw)
+ : upd78k_family_disassembler(sfr_names, sfrp_names)
+ , m_ix_bases(s_ix_bases)
+ , m_psw_bits(psw_bits)
+ , m_has_macw(has_macw)
+ , m_has_macsw(has_macsw)
+{
+}
+
+upd78k3_disassembler::upd78k3_disassembler(const char *const sfr_names[], const char *const sfrp_names[], const char *const ix_bases[])
+ : upd78k_family_disassembler(sfr_names, sfrp_names)
+ , m_ix_bases(ix_bases)
+ , m_psw_bits(s_psw_bits)
+ , m_has_macw(true)
+ , m_has_macsw(true)
+{
+}
+
+const char *const upd78k3_disassembler::s_r_names[16] =
+{
+ "R0", // X when RSS = 0
+ "R1", // A when RSS = 0
+ "R2", // C when RSS = 0
+ "R3", // B when RSS = 0
+ "R4", // X when RSS = 1
+ "R5", // A when RSS = 1
+ "R6", // C when RSS = 1
+ "R7", // B when RSS = 1
+ "VPL",
+ "VPH",
+ "UPL",
+ "UPH",
+ "E",
+ "D",
+ "L",
+ "H"
+};
+
+const char *const upd78k3_disassembler::s_rp_names[8] =
+{
+ "RP0", // AX when RSS = 0
+ "RP1", // BC when RSS = 0
+ "RP2", // AX when RSS = 1
+ "RP3", // BC when RSS = 1
+ "VP",
+ "UP",
+ "DE",
+ "HL"
+};
+
+const char *const upd78k3_disassembler::s_ix_bases[5] =
+{
+ "DE",
+ "SP",
+ "HL",
+ "UP",
+ "VP"
+};
+
+const char *const upd78k3_disassembler::s_psw_bits[16] =
+{
+ "CY",
+ "PSWL.1",
+ "P/V",
+ "IE",
+ "AC",
+ "RSS",
+ "Z",
+ "S",
+ "PSWH.0",
+ "PSWH.1",
+ "PSWH.2",
+ "PSWH.3",
+ "RBS0",
+ "RBS1",
+ "RBS2",
+ "UF"
+};
+
+const char *const upd78k3_disassembler::s_alu_ops[8] =
+{
+ "ADD",
+ "ADDC",
+ "SUB",
+ "SUBC",
+ "AND",
+ "XOR",
+ "OR",
+ "CMP"
+};
+
+const char *const upd78k3_disassembler::s_16bit_ops[4] =
+{
+ "MOVW",
+ "ADDW",
+ "SUBW",
+ "CMPW"
+};
+
+const char *const upd78k3_disassembler::s_bool_ops[4] =
+{
+ "MOV1",
+ "AND1",
+ "OR1",
+ "XOR1"
+};
+
+const char *const upd78k3_disassembler::s_shift_ops[2][4] =
+{
+ { "RORC", "ROR", "SHR", "SHRW" },
+ { "ROLC", "ROL", "SHL", "SHLW" }
+};
+
+const char *const upd78k3_disassembler::s_bcond[8] =
+{
+ "BNZ",
+ "BZ",
+ "BNC",
+ "BC",
+ "BNV",
+ "BV",
+ "BN",
+ "BP"
+};
+
+const char *const upd78k3_disassembler::s_bcond_07f8[6] =
+{
+ "BLT",
+ "BGE",
+ "BLE",
+ "BGT",
+ "BNH",
+ "BH"
+};
+
+const char *const upd78k3_disassembler::s_cmpscond[4] =
+{
+ "E",
+ "NE",
+ "NC",
+ "C"
+};
+
+offs_t upd78k3_disassembler::dasm_01xx(std::ostream &stream, u8 op2, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ if (op2 >= 0x0d && op2 < 0x10)
+ {
+ util::stream_format(stream, "%-8s", s_16bit_ops[op2 & 0x03]);
+ format_sfrp(stream, opcodes.r8(pc + 2));
+ stream << ",";
+ format_imm16(stream, opcodes.r8(pc + 3));
+ return 5 | SUPPORTED;
+ }
+ else if (op2 == 0x1b)
+ {
+ util::stream_format(stream, "%-8sAX,", "XCHW");
+ format_sfrp(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else if (op2 >= 0x1d && op2 < 0x20)
+ {
+ util::stream_format(stream, "%-8sAX,", s_16bit_ops[op2 & 0x03]);
+ format_sfrp(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else if (op2 == 0x21)
+ {
+ util::stream_format(stream, "%-8sA,", "XCH");
+ format_sfr(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else if ((op2 & 0xf8) == 0x68)
+ {
+ util::stream_format(stream, "%-8sA,", s_alu_ops[op2 & 0x07]);
+ format_sfr(stream, opcodes.r8(pc + 2));
+ stream << ",";
+ format_imm8(stream, opcodes.r8(pc + 3));
+ return 4 | SUPPORTED;
+ }
+ else if ((op2 & 0xf8) == 0x98)
+ {
+ util::stream_format(stream, "%-8sA,", s_alu_ops[op2 & 0x07]);
+ format_sfr(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x01, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_02xx(std::ostream &stream, u8 op1, u8 op2, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ if ((op2 & 0xf0) == 0x10)
+ {
+ util::stream_format(stream, "%-8s", "MOV1");
+ if (BIT(op1, 0))
+ util::stream_format(stream, "%c.%d,CY", BIT(op2, 3) ? 'A' : 'X', op2 & 0x07);
+ else
+ util::stream_format(stream, "%s,CY", m_psw_bits[op2 & 0x0f]);
+ return 2 | SUPPORTED;
+ }
+ else if (op2 < 0x70)
+ {
+ util::stream_format(stream, "%-8sCY,", s_bool_ops[(op2 & 0x60) >> 5]);
+ if (BIT(op2, 4))
+ stream << "/";
+ if (BIT(op1, 0))
+ util::stream_format(stream, "%c.%d", BIT(op2, 3) ? 'A' : 'X', op2 & 0x07);
+ else
+ util::stream_format(stream, "%s", m_psw_bits[op2 & 0x0f]);
+ return 2 | SUPPORTED;
+ }
+ else if (op2 < 0xa0)
+ {
+ util::stream_format(stream, "%-8s", op2 < 0x80 ? "NOT1" : BIT(op2, 4) ? "CLR1" : "SET1");
+ if (BIT(op1, 0))
+ util::stream_format(stream, "%c.%d", BIT(op2, 3) ? 'A' : 'X', op2 & 0x07);
+ else
+ util::stream_format(stream, "%s", m_psw_bits[op2 & 0x0f]);
+ return 2 | SUPPORTED;
+ }
+ else if (op2 < 0xe0)
+ {
+ if (BIT(op2, 6))
+ util::stream_format(stream, "%-8s", BIT(op2, 4) ? "BTCLR" : "BFSET");
+ else
+ util::stream_format(stream, "%-8s", BIT(op2, 4) ? "BT" : "BF");
+ if (BIT(op1, 0))
+ util::stream_format(stream, "%c.%d,", BIT(op2, 3) ? 'A' : 'X', op2 & 0x07);
+ else
+ util::stream_format(stream, "%s,", m_psw_bits[op2 & 0x0f]);
+ format_jdisp8(stream, pc + 4, opcodes.r8(pc + 3));
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, op1, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_04(std::ostream &stream)
+{
+ stream << "CVTBW";
+ return 1 | SUPPORTED;
+}
+
+offs_t upd78k3_disassembler::dasm_05xx(std::ostream &stream, u8 op2)
+{
+ if ((op2 & 0x88) == 0x08)
+ {
+ if (BIT(op2, 6))
+ {
+ util::stream_format(stream, "%-8s", BIT(op2, 4) ? "CALL" : "BR");
+ if (BIT(op2, 5))
+ util::stream_format(stream, "[%s]", s_rp_names[(op2 & 0x06) >> 1 | (op2 & 0x01) << 2]);
+ else
+ stream << s_rp_names[(op2 & 0x06) >> 1 | (op2 & 0x01) << 2];
+ return 2 | (BIT(op2, 4) ? STEP_OVER : 0) | SUPPORTED;
+ }
+ else
+ {
+ if (BIT(op2, 5))
+ util::stream_format(stream, "%-8s%s", BIT(op2, 4) ? "MULSW" : "MULUW", s_rp_names[(op2 & 0x06) >> 1 | (op2 & 0x01) << 2]);
+ else
+ util::stream_format(stream, "%-8s%s", BIT(op2, 4) ? "DIVUW" : "MULU", s_r_names[op2 & 0x07]);
+ return 2 | SUPPORTED;
+ }
+ }
+ else if ((op2 & 0xc8) == 0x88)
+ {
+ if (BIT(op2, 5))
+ util::stream_format(stream, "%-8sRB%d%s", "SEL", op2 & 0x07, BIT(op2, 4) ? ",ALT" : "");
+ else
+ util::stream_format(stream, "%-8s[%s]", BIT(op2, 4) ? "ROL4" : "ROR4", s_rp_names[(op2 & 0x06) >> 1 | (op2 & 0x01) << 2]);
+ return 2 | SUPPORTED;
+ }
+ else if ((op2 & 0xfe) == 0xc8)
+ {
+ util::stream_format(stream, "%-8sSP", BIT(op2, 4) ? "DECW" : "INCW");
+ return 2 | SUPPORTED;
+ }
+ else if ((op2 & 0xf8) == 0xd8)
+ {
+ util::stream_format(stream, "%-8sRB%d", "BRKCS", op2 & 0x07);
+ return 2 | STEP_OVER | SUPPORTED;
+ }
+ else if ((op2 & 0xf8) == 0xe8)
+ {
+ util::stream_format(stream, "%-8s%s", "DIVUX", s_rp_names[(op2 & 0x06) >> 1 | (op2 & 0x01) << 2]);
+ return 2 | SUPPORTED;
+ }
+ else if (op2 >= 0xfe)
+ {
+ util::stream_format(stream, "ADJB%c", BIT(op2, 0) ? 'S' : 'A');
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x05, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_06xx(std::ostream &stream, u8 op2, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ if ((op2 & 0x70) < 0x50 && (BIT(op2, 3) || (op2 & (BIT(op2, 7) ? 0x06 : 0x02)) == 0x00))
+ {
+ if (BIT(op2, 3))
+ util::stream_format(stream, "%-8s", s_alu_ops[op2 & 0x07]);
+ else if (BIT(op2, 0))
+ util::stream_format(stream, "%-8s", BIT(op2, 2) ? "XCHW" : "MOVW");
+ else
+ util::stream_format(stream, "%-8s", BIT(op2, 2) ? "XCH" : "MOV");
+ if ((op2 & 0x8b) == 0x01)
+ stream << "AX,";
+ else if (!BIT(op2, 7))
+ stream << "A,";
+ format_ix_disp8(stream, m_ix_bases[(op2 & 0x70) >> 4], opcodes.r8(pc + 2));
+ if ((op2 & 0x8b) == 0x81)
+ stream << ",AX";
+ else if (BIT(op2, 7))
+ stream << ",A";
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x06, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_07xx(std::ostream &stream, u8 op2, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ if (op2 >= 0xf8 && op2 <= 0xfd)
+ {
+ util::stream_format(stream, "%-8s", s_bcond_07f8[op2 & 0x07]);
+ format_jdisp8(stream, pc + 3, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else if ((op2 & 0xce) == 0xc8)
+ {
+ if (BIT(op2, 5))
+ {
+ util::stream_format(stream, "%-8s", BIT(op2, 0) ? "DECW" : "INCW");
+ format_saddrp(stream, opcodes.r8(pc + 2));
+ }
+ else if (BIT(op2, 4))
+ {
+ util::stream_format(stream, "%-8s", BIT(op2, 0) ? "PUSH" : "POP");
+ format_sfrp(stream, opcodes.r8(pc + 2));
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op2, 0) ? "CHKLA" : "CHKL");
+ format_sfr(stream, opcodes.r8(pc + 2));
+ }
+ return 3 | SUPPORTED;
+ }
+ else if (m_has_macw && (op2 | (m_has_macsw ? 0x80 : 0x00)) == 0x85)
+ {
+ util::stream_format(stream, "%-8s", BIT(op2, 7) ? "MACW" : "MACSW");
+ format_count(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x07, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_08xx(std::ostream &stream, u8 op2, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ if ((op2 & 0xf0) == 0x10)
+ {
+ util::stream_format(stream, "%-8s", "MOV1");
+ if (BIT(op2, 3))
+ format_sfr(stream, opcodes.r8(pc + 2));
+ else
+ format_saddr(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, ".%d,CY", op2 & 0x07);
+ return 3 | SUPPORTED;
+ }
+ else if (op2 < 0x70)
+ {
+ util::stream_format(stream, "%-8sCY,", s_bool_ops[(op2 & 0x60) >> 5]);
+ if (BIT(op2, 4))
+ stream << "/";
+ if (BIT(op2, 3))
+ format_sfr(stream, opcodes.r8(pc + 2));
+ else
+ format_saddr(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, ".%d", op2 & 0x07);
+ return 3 | SUPPORTED;
+ }
+ else if (op2 < (BIT(op2, 3) ? 0xa0 : 0x80))
+ {
+ util::stream_format(stream, "%-8s", op2 < 0x80 ? "NOT1" : BIT(op2, 4) ? "CLR1" : "SET1");
+ if (BIT(op2, 3))
+ format_sfr(stream, opcodes.r8(pc + 2));
+ else
+ format_saddr(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, ".%d", op2 & 0x07);
+ return 3 | SUPPORTED;
+ }
+ else if (op2 < 0xe0)
+ {
+ if (BIT(op2, 6))
+ util::stream_format(stream, "%-8s", BIT(op2, 4) ? "BTCLR" : "BFSET");
+ else
+ util::stream_format(stream, "%-8s", BIT(op2, 4) ? "BT" : "BF");
+ if (BIT(op2, 3))
+ format_sfr(stream, opcodes.r8(pc + 2));
+ else
+ format_saddr(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, ".%d,", op2 & 0x07);
+ format_jdisp8(stream, pc + 4, opcodes.r8(pc + 3));
+ return 4 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x08, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_09xx_sfrmov(std::ostream &stream, u8 sfr, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ util::stream_format(stream, "%-8s", "MOV");
+ format_sfr(stream, sfr);
+ stream << ",";
+ u8 nbyte = opcodes.r8(pc + 2);
+ u8 pbyte = opcodes.r8(pc + 3);
+ if ((nbyte ^ 0xff) == pbyte)
+ format_imm8(stream, pbyte);
+ else
+ stream << "invalid";
+ return 4 | SUPPORTED;
+}
+
+offs_t upd78k3_disassembler::dasm_09xx(std::ostream &stream, u8 op2, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ if ((op2 & 0xe8) == 0x80)
+ {
+ util::stream_format(stream, "%-8s", "MOVW");
+ if (BIT(op2, 4))
+ {
+ format_abs16(stream, opcodes.r16(pc + 2));
+ util::stream_format(stream, ",%s", (op2 & 0x06) >> 1 | (op2 & 0x01) << 2);
+ }
+ else
+ {
+ util::stream_format(stream, "%s,", (op2 & 0x06) >> 1 | (op2 & 0x01) << 2);
+ format_abs16(stream, opcodes.r16(pc + 2));
+ }
+ return 4 | SUPPORTED;
+ }
+ else if (op2 == 0xa0 && m_has_macw)
+ {
+ util::stream_format(stream, "%-8s", "MOVTBLW");
+ format_abs16(stream, 0xfe00 | opcodes.r8(pc + 2));
+ stream << ",";
+ format_count(stream, opcodes.r8(pc + 3));
+ return 4 | SUPPORTED;
+ }
+ else if (op2 == 0xb0 && m_has_macsw)
+ {
+ util::stream_format(stream, "%-8s", "SACW");
+ u8 post1 = opcodes.r8(pc + 2);
+ u8 post2 = opcodes.r8(pc + 3);
+ if (post1 == 0x41 && post2 == 0x46)
+ util::stream_format(stream, "[%s+],[%s+]", m_ix_bases[0], m_ix_bases[2]);
+ else
+ stream << "invalid";
+ return 4 | SUPPORTED;
+ }
+ else if (op2 == 0xc0 || op2 == 0xc2)
+ return dasm_09xx_sfrmov(stream, op2, pc, opcodes);
+ else if (op2 == 0xe0)
+ {
+ util::stream_format(stream, "%-8s", "RETCSB");
+ format_abs16(stream, opcodes.r16(pc + 2));
+ return 4 | SUPPORTED;
+ }
+ else if ((op2 & 0xfe) == 0xf0)
+ {
+ util::stream_format(stream, "%-8s", "MOV");
+ if (!BIT(op2, 4))
+ stream << "A,";
+ format_abs16(stream, opcodes.r16(pc + 2));
+ if (BIT(op2, 4))
+ stream << ",A";
+ return 4 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x09, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_0axx(std::ostream &stream, u8 op2, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ if (!BIT(op2, 6) && (BIT(op2, 3) || (op2 & (BIT(op2, 7) ? 0x06 : 0x02)) == 0x00))
+ {
+ if (BIT(op2, 3))
+ util::stream_format(stream, "%-8s", s_alu_ops[op2 & 0x07]);
+ else if (BIT(op2, 0))
+ util::stream_format(stream, "%-8s", BIT(op2, 2) ? "XCHW" : "MOVW");
+ else
+ util::stream_format(stream, "%-8s", BIT(op2, 2) ? "XCH" : "MOV");
+ if ((op2 & 0x8b) == 0x01)
+ stream << "AX,";
+ else if (!BIT(op2, 7))
+ stream << "A,";
+
+ if (BIT(op2, 5))
+ format_ix_disp16(stream, BIT(op2, 4) ? "B" : "A", opcodes.r16(pc + 2));
+ else
+ format_ix_disp16(stream, m_ix_bases[(op2 & 0x10) >> 3], opcodes.r16(pc + 2));
+
+ if ((op2 & 0x8b) == 0x81)
+ stream << ",AX";
+ else if (BIT(op2, 7))
+ stream << ",A";
+ return 4 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x0a, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_15xx(std::ostream &stream, u8 op2)
+{
+ if ((op2 & 0xc8) == 0x00 && (op2 & 0x06) != 0x02)
+ {
+ if (BIT(op2, 2))
+ util::stream_format(stream, "%-8s", util::string_format("CMP%s%s", BIT(op2, 5) ? "BK" : "M", s_cmpscond[op2 & 0x03]));
+ else
+ util::stream_format(stream, "%-8s", util::string_format("%s%s", BIT(op2, 0) ? "XCH" : "MOV", BIT(op2, 5) ? "BK" : "M"));
+ util::stream_format(stream, "[%s%c],", m_ix_bases[0], BIT(op2, 4) ? '-' : '+');
+ if (BIT(op2, 5))
+ util::stream_format(stream, "[%s%c]", m_ix_bases[2], BIT(op2, 4) ? '-' : '+');
+ else
+ stream << "A";
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x15, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_16xx(std::ostream &stream, u8 op1, u8 op2)
+{
+ if ((!BIT(op1, 0) || (op2 & 0x60) != 0x60) && (BIT(op2, 3) || (op2 & (BIT(op2, 7) ? 0x06 : 0x02)) == 0x00))
+ {
+ if (BIT(op2, 3))
+ util::stream_format(stream, "%-8s", s_alu_ops[op2 & 0x07]);
+ else if (BIT(op2, 0))
+ util::stream_format(stream, "%-8s", BIT(op2, 2) ? "XCHW" : "MOVW");
+ else
+ util::stream_format(stream, "%-8s", BIT(op2, 2) ? "XCH" : "MOV");
+ if ((op2 & 0x8b) == 0x01)
+ stream << "AX,";
+ else if (!BIT(op2, 7))
+ stream << "A,";
+
+ stream << "[";
+ if (BIT(op1, 0) && BIT(op2, 6))
+ util::stream_format(stream, "%s+", m_ix_bases[4]);
+ if ((op2 & 0x60) == 0x60)
+ stream << m_ix_bases[BIT(op2, 4) ? 3 : 4];
+ else
+ {
+ stream << m_ix_bases[(op2 & 0x10) >> 3];
+ if (!BIT(op2, 6))
+ {
+ if (BIT(op1, 0))
+ util::stream_format(stream, "+%c", BIT(op2, 5) ? 'B' : 'A');
+ else
+ stream << (BIT(op2, 5) ? "-" : "+");
+ }
+ }
+ stream << "]";
+
+ if ((op2 & 0x8b) == 0x81)
+ stream << ",AX";
+ else if (BIT(op2, 7))
+ stream << ",A";
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, 0x16, op2);
+}
+
+offs_t upd78k3_disassembler::dasm_24xx(std::ostream &stream, u8 op, u8 rr)
+{
+ if (!BIT(rr, 3))
+ {
+ util::stream_format(stream, "%-8s%s,%s", BIT(op, 0) ? "XCH" : "MOV", s_r_names[(rr & 0xf0) >> 4], s_r_names[rr & 0x07]);
+ return 2 | SUPPORTED;
+ }
+ else if (!BIT(rr, 4))
+ {
+ util::stream_format(stream, "%-8s%s,%s", BIT(op, 0) ? "XCHW" : "MOVW", s_rp_names[(rr & 0xe0) >> 5], s_rp_names[(rr & 0x06) >> 1 | (rr & 0x01) << 2]);
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, op, rr);
+}
+
+offs_t upd78k3_disassembler::dasm_2a(std::ostream &stream, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ util::stream_format(stream, "%-8s", "XCHW");
+ format_saddrp(stream, opcodes.r8(pc + 1));
+ stream << ",";
+ format_saddrp(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+}
+
+offs_t upd78k3_disassembler::dasm_38(std::ostream &stream, u8 op, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "XCH" : "MOV");
+ format_saddr(stream, opcodes.r8(pc + 1));
+ stream << ",";
+ format_saddr(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+}
+
+offs_t upd78k3_disassembler::dasm_3c(std::ostream &stream, u8 op, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ util::stream_format(stream, "%-8s", s_16bit_ops[op & 0x03]);
+ format_saddrp(stream, opcodes.r8(pc + 1));
+ stream << ",";
+ format_saddrp(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+}
+
+offs_t upd78k3_disassembler::dasm_43(std::ostream &stream, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ stream << "SWRS";
+ return 1 | SUPPORTED;
+}
+
+offs_t upd78k3_disassembler::dasm_50(std::ostream &stream, u8 op)
+{
+ if ((op & 0x06) == 0x06)
+ {
+ if (op == 0x5e)
+ {
+ stream << "BRK";
+ return 1 | STEP_OVER | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "RET%s", BIT(op, 3) ? "B" : BIT(op, 0) ? "I" : "");
+ return 1 | STEP_OUT | SUPPORTED;
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", "MOV");
+ if (BIT(op, 3))
+ stream << "A,";
+ util::stream_format(stream, "[%s%s]", m_ix_bases[(op & 0x01) << 1], BIT(op, 2) ? "" : BIT(op, 1) ? "-" : "+");
+ if (!BIT(op, 3))
+ stream << ",A";
+ return 1 | SUPPORTED;
+ }
+}
+
+offs_t upd78k3_disassembler::dasm_78(std::ostream &stream, u8 op, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes)
+{
+ util::stream_format(stream, "%-8s", s_alu_ops[op & 0x07]);
+ format_saddr(stream, opcodes.r8(pc + 1));
+ stream << ",";
+ format_saddr(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+}
+
+offs_t upd78k3_disassembler::dasm_88xx(std::ostream &stream, u8 op, u8 rr)
+{
+ if (!BIT(rr, 3))
+ {
+ util::stream_format(stream, "%-8s%s,%s", s_alu_ops[op & 0x07], s_r_names[(rr & 0xf0) >> 4], s_r_names[rr & 0x07]);
+ return 2 | SUPPORTED;
+ }
+ else if (!BIT(rr, 4) && (op == 0x88 || op == 0x8a || op == 0x8f))
+ {
+ util::stream_format(stream, "%-8s%s,%s", std::string(s_alu_ops[op & 0x07]) + "W", s_rp_names[(rr & 0xe0) >> 5], s_rp_names[(rr & 0x06) >> 1 | (rr & 0x01) << 2]);
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_illegal2(stream, op, rr);
+}
+
+offs_t upd78k3_disassembler::disassemble(std::ostream &stream, offs_t pc, const upd78k3_disassembler::data_buffer &opcodes, const upd78k3_disassembler::data_buffer &params)
+{
+ u8 op = opcodes.r8(pc);
+ switch (op & 0xf8)
+ {
+ case 0x00:
+ switch (op)
+ {
+ case 0x00:
+ stream << "NOP";
+ return 1 | SUPPORTED;
+
+ case 0x01:
+ return dasm_01xx(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x02: case 0x03:
+ return dasm_02xx(stream, op, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x04:
+ return dasm_04(stream);
+
+ case 0x05:
+ return dasm_05xx(stream, opcodes.r8(pc + 1));
+
+ case 0x06:
+ return dasm_06xx(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x07:
+ return dasm_07xx(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ default: // can't happen here, though compilers believe it could
+ return dasm_illegal(stream, op);
+ }
+
+ case 0x08:
+ switch (op)
+ {
+ case 0x08:
+ return dasm_08xx(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x09:
+ return dasm_09xx(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x0a:
+ return dasm_0axx(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ default:
+ if (BIT(op, 2))
+ {
+ util::stream_format(stream, "%-8s", s_16bit_ops[op & 0x03]);
+ format_saddrp(stream, opcodes.r8(pc + 1));
+ }
+ else
+ {
+ u8 sfrp = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8s", "MOVW");
+ if (sfrp == 0xfc)
+ stream << "SP";
+ else
+ format_sfrp(stream, sfrp);
+ }
+ stream << ",";
+ format_imm16(stream, opcodes.r16(pc + 2));
+ return 4 | SUPPORTED;
+ }
+
+ case 0x10:
+ if (!BIT(op, 2))
+ {
+ if (BIT(op, 0))
+ {
+ util::stream_format(stream, "%-8s", "MOVW");
+ if (!BIT(op, 1))
+ stream << "AX,";
+ u8 sfrp = opcodes.r8(pc + 1);
+ if (sfrp == 0xfc)
+ stream << "SP";
+ else
+ format_sfrp(stream, sfrp);
+ if (BIT(op, 1))
+ stream << ",AX";
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", "MOV");
+ if (!BIT(op, 1))
+ stream << "A,";
+ u8 sfrp = opcodes.r8(pc + 1);
+ if (sfrp >= 0xfe)
+ util::stream_format(stream, "PSW%c", BIT(sfrp, 0) ? 'H' : 'L');
+ else
+ format_sfrp(stream, sfrp);
+ if (BIT(op, 1))
+ stream << ",A";
+ }
+ return 2 | SUPPORTED;
+ }
+ else if (BIT(op, 1))
+ return dasm_16xx(stream, op, opcodes.r8(pc + 1));
+ else if (BIT(op, 0))
+ return dasm_15xx(stream, opcodes.r8(pc + 1));
+ else
+ {
+ util::stream_format(stream, "%-8s", "BR");
+ format_jdisp8(stream, pc + 2, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+ }
+
+ case 0x18:
+ if (BIT(op, 2))
+ {
+ util::stream_format(stream, "%-8sAX,", s_16bit_ops[op & 0x03]);
+ format_saddrp(stream, opcodes.r8(pc + 1));
+ }
+ else if (BIT(op, 1))
+ {
+ if (BIT(op, 0))
+ util::stream_format(stream, "%-8sAX,", "XCHW");
+ else
+ util::stream_format(stream, "%-8s", "MOVW");
+ format_saddrp(stream, opcodes.r8(pc + 1));
+ if (!BIT(op, 0))
+ stream << ",AX";
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", "MOV");
+ if (!BIT(op, 0))
+ stream << "A,";
+ stream << "[";
+ format_saddrp(stream, opcodes.r8(pc + 1));
+ stream << "]";
+ if (BIT(op, 0))
+ stream << ",A";
+ }
+ return 2 | SUPPORTED;
+
+ case 0x20:
+ if (BIT(op, 2))
+ {
+ if (BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "DEC" : "INC");
+ format_saddr(stream, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_24xx(stream, op, opcodes.r8(pc + 1));
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "XCH" : "MOV");
+ if (op != 0x22)
+ stream << "A,";
+ if (op == 0x23)
+ {
+ stream << "[";
+ format_saddrp(stream, opcodes.r8(pc + 1));
+ stream << "]";
+ }
+ else
+ {
+ format_saddr(stream, opcodes.r8(pc + 1));
+ if (op == 0x22)
+ stream << ",A";
+ }
+ return 2 | SUPPORTED;
+ }
+
+ case 0x28:
+ switch (op)
+ {
+ case 0x28:
+ util::stream_format(stream, "%-8s", "CALL");
+ format_abs16(stream, opcodes.r16(pc + 1));
+ return 3 | STEP_OVER | SUPPORTED;
+
+ case 0x29:
+ util::stream_format(stream, "%-8s", "RETCS");
+ format_abs16(stream, opcodes.r16(pc + 1));
+ return 3 | STEP_OUT | SUPPORTED;
+
+ case 0x2a:
+ return dasm_2a(stream, pc, opcodes);
+
+ case 0x2b:
+ {
+ util::stream_format(stream, "%-8s", "MOV");
+ u8 sfr = opcodes.r8(pc + 1);
+ if (sfr >= 0xfe)
+ util::stream_format(stream, "PSW%c", BIT(sfr, 0) ? 'H' : 'L');
+ else
+ format_sfr(stream, sfr);
+ stream << ",";
+ format_imm8(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+
+ case 0x2c:
+ util::stream_format(stream, "%-8s", "BR");
+ format_abs16(stream, opcodes.r16(pc + 1));
+ return 3 | SUPPORTED;
+
+ default:
+ util::stream_format(stream, "%-8sAX,", s_16bit_ops[op & 0x03]);
+ format_imm16(stream, opcodes.r16(pc + 1));
+ return 3 | SUPPORTED;
+ }
+
+ case 0x30:
+ if (BIT(op, 2))
+ {
+ u8 post = opcodes.r8(pc + 1);
+ if (BIT(op, 0))
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 1) ? "PUSHU" : "PUSH");
+ if (post == 0)
+ stream << "none";
+ else for (int n = 7; n >= 0; n--)
+ {
+ if (BIT(post, n))
+ {
+ stream << s_rp_names[n];
+ post &= ~(1 << n);
+ if (post != 0)
+ stream << ",";
+ }
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 1) ? "POPU" : "POP");
+ if (post == 0)
+ stream << "none";
+ else for (int n = 0; n < 8; n++)
+ {
+ if (BIT(post, n))
+ {
+ stream << s_rp_names[n];
+ post &= ~(1 << n);
+ if (post != 0)
+ stream << ",";
+ }
+ }
+ }
+ return 2 | SUPPORTED;
+ }
+ else if (BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s%s,", "DBNZ", s_r_names[op & 0x07]);
+ format_jdisp8(stream, pc + 2, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+ }
+ else
+ {
+ u8 n = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8s", s_shift_ops[op & 0x01][(n & 0xc0) >> 6]);
+ if (n >= 0xc0)
+ stream << s_rp_names[(n & 0x06) >> 1 | (n & 0x01) << 2];
+ else
+ stream << s_r_names[n & 0x07];
+ util::stream_format(stream, ",%d", (n & 0x38) >> 3);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x38:
+ if (BIT(op, 2))
+ return dasm_3c(stream, op, pc, opcodes);
+ else if (BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "DBNZ" : "MOV");
+ format_saddr(stream, opcodes.r8(pc + 1));
+ stream << ",";
+ if (BIT(op, 0))
+ format_jdisp8(stream, pc + 3, opcodes.r8(pc + 2));
+ else
+ format_imm8(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_38(stream, op, pc, opcodes);
+
+ case 0x40:
+ if (BIT(op, 2))
+ {
+ util::stream_format(stream, "%-8s%s", "INCW", s_rp_names[op & 0x07]);
+ return 1 | SUPPORTED;
+ }
+ else if (BIT(op, 1))
+ {
+ if (BIT(op, 0))
+ return dasm_43(stream, pc, opcodes);
+ else
+ {
+ util::stream_format(stream, "%-8sCY", "NOT1");
+ return 1 | SUPPORTED;
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "%-8sCY", BIT(op, 0) ? "SET1" : "CLR1");
+ return 1 | SUPPORTED;
+ }
+
+ case 0x48:
+ if (BIT(op, 2))
+ util::stream_format(stream, "%-8s%s", "DECW", s_rp_names[op & 0x07]);
+ else if (BIT(op, 1))
+ util::stream_format(stream, "%cI", BIT(op, 0) ? 'E' : 'D');
+ else
+ util::stream_format(stream, "%-8sPSW", BIT(op, 0) ? "PUSH" : "POP");
+ return 1 | SUPPORTED;
+
+ case 0x50: case 0x58:
+ return dasm_50(stream, op);
+
+ case 0x60:
+ util::stream_format(stream, "%-8s%s,", "MOVW", s_rp_names[(op & 0x06) >> 1 | (op & 0x01) << 2]);
+ format_imm16(stream, opcodes.r16(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 0x68:
+ util::stream_format(stream, "%-8s", s_alu_ops[op & 0x07]);
+ format_saddr(stream, opcodes.r8(pc + 1));
+ stream << ",";
+ format_imm8(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+
+ case 0x70:
+ util::stream_format(stream, "%-8s", "BT");
+ format_saddr(stream, opcodes.r8(pc + 1));
+ util::stream_format(stream, ".%d,", op & 0x07);
+ format_jdisp8(stream, pc + 3, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+
+ case 0x78:
+ return dasm_78(stream, op, pc, opcodes);
+
+ case 0x80:
+ util::stream_format(stream, "%-8s", s_bcond[op & 0x07]);
+ format_jdisp8(stream, pc + 2, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+
+ case 0x88:
+ return dasm_88xx(stream, op, opcodes.r8(pc + 1));
+
+ case 0x90:
+ util::stream_format(stream, "%-8s", "CALLF");
+ format_abs16(stream, 0x0800 | u16(op & 0x07) << 8 | opcodes.r8(pc + 1));
+ return 2 | STEP_OVER | SUPPORTED;
+
+ case 0x98:
+ util::stream_format(stream, "%-8sA,", s_alu_ops[op & 0x07]);
+ format_saddr(stream, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+
+ case 0xa0: case 0xb0:
+ util::stream_format(stream, "%-8s", BIT(op, 4) ? "SET1" : "CLR1");
+ format_saddr(stream, opcodes.r8(pc + 1));
+ util::stream_format(stream, ".%d", op & 0x07);
+ return 2 | SUPPORTED;
+
+ case 0xa8:
+ util::stream_format(stream, "%-8sA,", s_alu_ops[op & 0x07]);
+ format_imm8(stream, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+
+ case 0xb8:
+ util::stream_format(stream, "%-8s%s,", "MOV", s_r_names[op & 0x07]);
+ format_imm8(stream, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+
+ case 0xc0: case 0xc8:
+ util::stream_format(stream, "%-8s%s", BIT(op, 3) ? "DEC" : "INC", s_r_names[op & 0x07]);
+ return 1 | SUPPORTED;
+
+ case 0xd0: case 0xd8:
+ util::stream_format(stream, "%-8sA,%s", BIT(op, 3) ? "XCH" : "MOV", s_r_names[op & 0x07]);
+ return 1 | SUPPORTED;
+
+ case 0xe0: case 0xe8: case 0xf0: case 0xf8:
+ // vectors may be at 00XXH or 80XXH depending on the state of TPF (CCW.1)
+ util::stream_format(stream, "%-8s[%02XH]", "CALLT", (op & 0x3f) << 1);
+ return 1 | STEP_OVER | SUPPORTED;
+
+ default: // can't happen here, though compilers believe it could
+ return dasm_illegal(stream, op);
+ }
+}
+
+upd78312_disassembler::upd78312_disassembler()
+ : upd78k3_disassembler(s_sfr_names, s_sfrp_names, s_psw_bits, false, false)
+{
+}
+
+const char *const upd78312_disassembler::s_sfr_names[256] =
+{
+ "P0", "P1", "P2", "P3", "P4", "P5", nullptr, nullptr,
+ "CR00L", "CR00H", "CR01L", "CR01H", "CR10L", "CR10H", "CR11L", "CR11H",
+ "CPT0L", "CPT0H", "CPT1L", "CPT1H", "PWM0L", "PWM0H", "PWM1L", "PWM1H",
+ nullptr, nullptr, nullptr, nullptr, "UDC0L", "UDC0H", "UDC1L", "UDC1H",
+ "PM0", "PM1", "PM2", "PM3", nullptr, "PM5", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, "PMC2", "PMC3", nullptr, nullptr, nullptr, nullptr,
+ "RTPC", nullptr, "P0L", "P0H", nullptr, nullptr, nullptr, nullptr,
+ "MM", "RFM", "WDM", nullptr, "STBC", nullptr, "TBM", nullptr,
+ "INTM", nullptr, "ISPR", nullptr, nullptr, nullptr, "CCW", nullptr,
+ "SCM", nullptr, "SCC", "BRG", nullptr, nullptr, "RXB", "TXB",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "FRCC", nullptr, nullptr, nullptr, "CPTM", nullptr, "PWMM", nullptr,
+ "ADM", nullptr, "ADCR", nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CUIM", nullptr, "UDCC0", nullptr, "CRC", nullptr, nullptr, nullptr,
+ nullptr, nullptr, "UDCC1", nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TMC0", nullptr, "TMC1", nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TM0L", "TM0H", "MD0L", "MD0H", "TM1L", "TM1H", "MD1L", "MD1H",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ "CRIC00", "CRMS00", "CRIC01", nullptr, "CRIC10", "CRMS10", "CRIC11", nullptr,
+ "EXIC0", "EXMS0", "EXIC1", "EXMS1", "EXIC2", "EXMS2", "TMIC0", "TMMS0",
+ "TMIC1", "TMMS1", "TMIC2", "TMMS2", nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, "SEIC", nullptr, "SRIC", "SRMS", "STIC", "STMS",
+ "ADIC", "ADMS", "TBIC", nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78312_disassembler::s_sfrp_names[128] =
+{
+ nullptr, nullptr, nullptr, nullptr, "CR00", "CR01", "CR10", "CR11",
+ "CPT0", "CPT1", "PWM0", "PWM1", nullptr, nullptr, "UDC0", "UDC1",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, "TM0", "MD0", "TM1", "MD1",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78312_disassembler::s_psw_bits[16] =
+{
+ "CY",
+ "SUB",
+ "P/V",
+ "UF",
+ "AC",
+ "RSS",
+ "Z",
+ "S",
+ "PSWH.0",
+ "IE",
+ "PSWH.2",
+ "PSWH.3",
+ "RBS0",
+ "RBS1",
+ "RBS2",
+ "PSWH.7"
+};
+
+offs_t upd78312_disassembler::dasm_04(std::ostream &stream)
+{
+ stream << "ADJ4";
+ return 1 | SUPPORTED;
+}
+
+offs_t upd78312_disassembler::dasm_05xx(std::ostream &stream, u8 op2)
+{
+ // no MULW or ADJBA/ADJBS (which replaced ADJ4)
+ if (op2 < 0xfe && (op2 & 0xf0) != 0x30)
+ return upd78k3_disassembler::dasm_05xx(stream, op2);
+ else
+ return dasm_illegal2(stream, 0x05, op2);
+}
+
+offs_t upd78312_disassembler::dasm_06xx(std::ostream &stream, u8 op2, offs_t pc, const upd78312_disassembler::data_buffer &opcodes)
+{
+ // no MOVW/XCHW variants
+ if ((op2 & 0x0b) != 0x01)
+ return upd78k3_disassembler::dasm_06xx(stream, op2, pc, opcodes);
+ else
+ return dasm_illegal2(stream, 0x06, op2);
+}
+
+offs_t upd78312_disassembler::dasm_07xx(std::ostream &stream, u8 op2, offs_t pc, const upd78312_disassembler::data_buffer &opcodes)
+{
+ // no CHKL(A) or PUSH/POP sfrp
+ if ((op2 & 0xee) != 0xc8)
+ return upd78k3_disassembler::dasm_07xx(stream, op2, pc, opcodes);
+ else
+ return dasm_illegal2(stream, 0x07, op2);
+}
+
+offs_t upd78312_disassembler::dasm_09xx(std::ostream &stream, u8 op2, offs_t pc, const upd78312_disassembler::data_buffer &opcodes)
+{
+ // STBC and WDM are moved; no RETCSB
+ if (op2 == 0x42 || op2 == 0x44)
+ return dasm_09xx_sfrmov(stream, op2, pc, opcodes);
+ else if ((op2 & 0xd0) != 0xc0)
+ return upd78k3_disassembler::dasm_09xx(stream, op2, pc, opcodes);
+ else
+ return dasm_illegal2(stream, 0x09, op2);
+}
+
+offs_t upd78312_disassembler::dasm_0axx(std::ostream &stream, u8 op2, offs_t pc, const upd78312_disassembler::data_buffer &opcodes)
+{
+ // no MOVW/XCHW variants
+ if ((op2 & 0x0b) != 0x01)
+ return upd78k3_disassembler::dasm_0axx(stream, op2, pc, opcodes);
+ else
+ return dasm_illegal2(stream, 0x0a, op2);
+}
+
+offs_t upd78312_disassembler::dasm_16xx(std::ostream &stream, u8 op1, u8 op2)
+{
+ // no MOVW/XCHW variants
+ if ((op2 & 0x0b) != 0x01)
+ return upd78k3_disassembler::dasm_16xx(stream, op1, op2);
+ else
+ return dasm_illegal2(stream, op1, op2);
+}
+
+offs_t upd78312_disassembler::dasm_50(std::ostream &stream, u8 op)
+{
+ // no RETB
+ if (op != 0x5f)
+ return upd78k3_disassembler::dasm_50(stream, op);
+ else
+ return dasm_illegal(stream, op);
+}
+
+upd78322_disassembler::upd78322_disassembler()
+ : upd78k3_disassembler(s_sfr_names, s_sfrp_names, s_psw_bits, false, false)
+{
+}
+
+const char *const upd78322_disassembler::s_sfr_names[256] =
+{
+ "P0", nullptr, "P2", "P3", "P4", "P5", nullptr, "P7",
+ "P8", "P9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PM0", nullptr, nullptr, "PM3", nullptr, "PM5", nullptr, nullptr,
+ "PM8", "PM9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PMC0", "RTPS", nullptr, "PMC3", nullptr, nullptr, nullptr, nullptr,
+ "PMC8", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "RTP", "RTPR", "PRDC", nullptr, nullptr, nullptr, nullptr, nullptr,
+ "ADM", nullptr, nullptr, "ADCRH", nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CSIM", nullptr, "SBIC", nullptr, nullptr, nullptr, "SIO", nullptr,
+ "ASIM", nullptr, "ASIS", nullptr, "RXB", nullptr, "TXS", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TMC", "BRGM", "PRM", nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TOC0", "TOC1", nullptr, nullptr, nullptr, nullptr, nullptr, "RPM",
+ "STBC", "CCW", "WDM", nullptr, "MM", nullptr, "PWC", nullptr,
+ nullptr, "FCC", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ "IF0L", "IF0H", "IF1L", nullptr, "MK0L", "MK0H", "MK1L", nullptr,
+ "PB0L", "PB0H", "PB1L", nullptr, "ISM0L", "ISM0H", "ISM1L", nullptr,
+ "CSE0L", "CSE0H", "CSE1L", nullptr, "INTM0", "INTM1", nullptr, nullptr,
+ "ISPR", "PRSL", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78322_disassembler::s_sfrp_names[128] =
+{
+ nullptr, nullptr, nullptr, nullptr, nullptr, "TM0LW", nullptr, nullptr,
+ "CTX0LW", "CT01LW", "CT02LW", "CT03LW", "CCX0LW", "CC01LW", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, "TM0UW", "TM1", nullptr,
+ "CTX0UW", "CT01UW", "CT02UW", "CT03UW", "CCX0UW", "CC01UW", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "BRG", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, "ADCR", nullptr, nullptr,
+ "CM00", "CM01", "CM02", "CM03", nullptr, nullptr, "CM10", "CM11",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "IF0", "IF1", "MK0", "MK1", "PB0", "PB1", "ISM0", "ISM1",
+ "CSE0", "CSE1", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+upd78328_disassembler::upd78328_disassembler()
+ : upd78k3_disassembler(s_sfr_names, s_sfrp_names, s_psw_bits, false, false)
+{
+}
+
+const char *const upd78328_disassembler::s_sfr_names[256] =
+{
+ "P0", nullptr, "P2", "P3", "P4", "P5", nullptr, "P7",
+ "P8", "P9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PM0", nullptr, nullptr, "PM3", nullptr, "PM5", nullptr, nullptr,
+ "PM8", "PM9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, "PMC3", nullptr, nullptr, nullptr, nullptr,
+ "PMC8", nullptr, nullptr, nullptr, "BRG", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "P0L", "P0H", "PRDC", "RTPC", "PWMC", nullptr, "PWMB", nullptr,
+ "ADM", nullptr, nullptr, "ADCRH", nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CSIM", nullptr, "SBIC", nullptr, nullptr, nullptr, "SIO", nullptr,
+ "ASIM", nullptr, "ASIS", nullptr, "RXB", nullptr, "TXS", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TMC0", "BRGM", "TMC1", nullptr, "TUM", nullptr, nullptr, nullptr,
+ nullptr, nullptr, "TOUT", nullptr, nullptr, nullptr, nullptr, nullptr,
+ "STBC", "CCW", "WDM", nullptr, "MM", nullptr, "PWC", nullptr,
+ nullptr, "FCC", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ "IF0L", "IF0H", "IF1L", nullptr, "MK0L", "MK0H", "MK1L", nullptr,
+ "PB0L", "PB0H", "PB1L", nullptr, "ISM0L", "ISM0H", "ISM1L", nullptr,
+ "CSE0L", "CSE0H", "CSE1L", nullptr, "INTM0", "INTM1", nullptr, nullptr,
+ "ISPR", "PRSL", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78328_disassembler::s_sfrp_names[128] =
+{
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "TM2", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "CC10", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, "TM0", "TM1", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, "ADCR", nullptr, nullptr,
+ "CM00S", "CM01S", "CM02S", "CM03S", "CM04S", "CM05S", "CM06", "CM20",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CM00R", "CM01R", "CM02R", "CM03R", "CM04R", "CM05R", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "IF0", "IF1", "MK0", "MK1", "PB0", "PB1", "ISM0", "ISM1",
+ "CSE0", "CSE1", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+upd78334_disassembler::upd78334_disassembler()
+ : upd78k3_disassembler(s_sfr_names, s_sfrp_names, s_psw_bits, false, false)
+{
+}
+
+const char *const upd78334_disassembler::s_sfr_names[256] =
+{
+ "P0", "P1", "P2", "P3", "P4", "P5", nullptr, "P7",
+ "P8", "P9", "TLA", nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PM0", "PM1", nullptr, "PM3", nullptr, "PM5", nullptr, nullptr,
+ nullptr, "PM9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PMC0", "PMC1", nullptr, "PMC3", nullptr, nullptr, nullptr, nullptr,
+ "PMC8", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "RTP", "RTPR", "PRDC", "RTPS", "PWMC", nullptr, "PWM0", nullptr,
+ "ADM", nullptr, nullptr, nullptr, nullptr, nullptr, "PWM1", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CSIM", nullptr, "SBIC", nullptr, nullptr, nullptr, "SIO", nullptr,
+ "ASIM", nullptr, "ASIS", nullptr, "RXB", nullptr, "TXS", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, "ADCR0H", nullptr, "ADCR1H", nullptr, "ADCR2H", nullptr, "ADCR3H",
+ nullptr, "ADCR4H", nullptr, "ADCR5H", nullptr, "ADCR6H", nullptr, "ADCR7H",
+ "TMC0", "BRGM", "TMC1", nullptr, "TUM0", "TUM1", nullptr, nullptr,
+ "TOC0", "TOC1", nullptr, nullptr, "PPOS", nullptr, nullptr, nullptr,
+ "STBC", "CCW", "WDM", nullptr, "MM", nullptr, "PWC", nullptr,
+ nullptr, "FCC", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ "IF0L", "IF0H", "IF1L", nullptr, "MK0L", "MK0H", "MK1L", nullptr,
+ "PB0L", "PB0H", "PB1L", nullptr, "ISM0L", "ISM0H", "ISM1L", nullptr,
+ "CSE0L", "CSE0H", "CSE1L", nullptr, "INTM0", "INTM1", nullptr, nullptr,
+ "ISPR", "PRSL", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78334_disassembler::s_sfrp_names[128] =
+{
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "TM2", nullptr,
+ "CT00", "CT01", "CT02", nullptr, nullptr, nullptr, "CT10", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, "TM0", "TM1", "TM3",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "BRG", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CM11", "CM12", "CM20", "CM21", "CM30", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CMX0", "CM01R", "CM02R", "CM03R", "CM04R", "CC00R", "CC01R", nullptr,
+ "ADCR0", "ADCR1", "ADCR2", "ADCR3", "ADCR4", "ADCR5", "ADCR6", "ADCR7",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "IF0", "IF1", "MK0", "MK1", "PB0", "PB1", "ISM0", "ISM1",
+ "CSE0", "CSE1", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+upd78352_disassembler::upd78352_disassembler()
+ : upd78k3_disassembler(s_sfr_names, s_sfrp_names, s_psw_bits, true, false)
+{
+}
+
+const char *const upd78352_disassembler::s_sfr_names[256] =
+{
+ "P0", "P1", "P2", "P3", "P4", "P5", nullptr, nullptr,
+ nullptr, "P9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PM0", "PM1", nullptr, "PM3", nullptr, "PM5", nullptr, nullptr,
+ nullptr, "PM9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TMC0", "TMC1", nullptr, nullptr, "INTM0", "INTM1", nullptr, nullptr,
+ nullptr, nullptr, nullptr, "PMC3", nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, "PRDC", nullptr, "PWMC", nullptr, "PWM0", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "PWM1", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "ISPR", nullptr, "IMC", nullptr, "MKL", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "STBC", "CCW", "WDM", nullptr, "MM", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ "OVIC", "PIC0", "PIC1", "CMIC10", "CMIC20", "PIC2", "PIC3", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78352_disassembler::s_sfrp_names[128] =
+{
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CT00", "CT01", "CM10", nullptr, nullptr, nullptr, nullptr, "CM20",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TM0", "TM1", "TM2", nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "MK",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, "PWC", nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+upd78356_disassembler::upd78356_disassembler()
+ : upd78k3_disassembler(s_sfr_names, s_sfrp_names, s_psw_bits, true, true)
+{
+}
+
+const char *const upd78356_disassembler::s_sfr_names[256] =
+{
+ "P0", "P1", "P2", "P3", "P4", "P5", "P6", "P7",
+ "P8", "P9", "P10", nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PM0", "PM1", "PM2", "PM3", nullptr, "PM5", nullptr, nullptr,
+ "PM8", "PM9", "PM10", nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, "INTM0", "INTM1", nullptr, nullptr,
+ "PMC0", nullptr, "PMC2", "PMC3", "PUOL", "PUOH", nullptr, nullptr,
+ "PMC8", nullptr, "PMC10", nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "RTPL", "RTPH", "PRDC", "RTPM", nullptr, nullptr, nullptr, nullptr,
+ "ADM0", "ADM1", "DACS0", "DACS1", nullptr, nullptr, nullptr, nullptr,
+ "TUM0", "TUM1", "TUM2", "TUM3", "TMC0", "TMC1", "TMC2", "UDCC",
+ "TOC0", "TOC1", "TOC2", "TOVS", "NPC", nullptr, nullptr, nullptr,
+ "CSIM0", nullptr, "SBIC", nullptr, nullptr, nullptr, "SIO0", nullptr,
+ "ASIM", nullptr, "ASIS", nullptr, "RXB", nullptr, "TXS", nullptr,
+ "CSIM1", nullptr, nullptr, nullptr, nullptr, nullptr, "SIO1", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PWMC", nullptr, "PWM0L", nullptr, "PWM1L", nullptr, nullptr, nullptr,
+ "ISPR", nullptr, "IMC", nullptr, "MK0L", "MK0H", "MK1L", nullptr,
+ nullptr, "ADCR0H", nullptr, "ADCR1H", nullptr, "ADCR2H", nullptr, "ADCR3H",
+ nullptr, "ADCR4H", nullptr, "ADCR5H", nullptr, "ADCR6H", nullptr, "ADCR7H",
+ "STBC", "CCW", "WDM", nullptr, "MM", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ "OVIC0", "OVIC3", "PIC0", "PIC1", "PIC2", "PIC3", "PIC4", "CMIC00",
+ "CMIC01", "CMIC02", "CMIC03", "CMIC10", "CMIC11", "CMIC20", "CMIC21", "CMIC40",
+ "CMICUD0", "CMICUD1", "SERIC", "SRIC", "STIC", "CSIIC0", "CSIIC1", "ADIC",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78356_disassembler::s_sfrp_names[128] =
+{
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CC00", "CC01", "CC02", "CC30", "CC31", "CM00", "CM01", "CM02",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TM0", "TM1", "TM2", "TM3", "TM4", "UDC", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CM03", "CM10", "CM11", "CM20", "CM21", "CM40", "CMUD0", "CMUD1",
+ nullptr, nullptr, nullptr, nullptr, nullptr, "DACS", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, "PWM0", "PWM1", nullptr, nullptr, nullptr, "MK0", "MK1",
+ "ADCR0", "ADCR1", "ADCR2", "ADCR3", "ADCR4", "ADCR5", "ADCR6", "ADCR7",
+ nullptr, nullptr, nullptr, "PWC", nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+upd78366a_disassembler::upd78366a_disassembler()
+ : upd78k3_disassembler(s_sfr_names, s_sfrp_names, s_psw_bits, true, true)
+{
+}
+
+const char *const upd78366a_disassembler::s_sfr_names[256] =
+{
+ "P0", "P1", "P2", "P3", "P4", "P5", nullptr, "P7",
+ "P8", "P9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PM0", "PM1", nullptr, "PM3", nullptr, "PM5", nullptr, nullptr,
+ "PM8", "PM9", nullptr, nullptr, nullptr, nullptr, "TUM0", "TUM1",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, "INTM0", "INTM1", nullptr, nullptr,
+ "PMC0", nullptr, nullptr, "PMC3", "PUOL", "PUOH", nullptr, nullptr,
+ "PMC8", nullptr, nullptr, nullptr, nullptr, nullptr, "SMPC0", "SMPC1",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "TMC4", "TOUT",
+ "RTP", "RTPM", "PRDC", nullptr, nullptr, nullptr, nullptr, nullptr,
+ "ADM", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "SBUF0", "SBUF1", "SBUF2", "SBUF3", "SBUF4", "SBUF5", "MBUF0", "MBUF1",
+ "MBUF2", "MBUF3", "MBUF4", "MBUF5", "TMC0", "TMC1", "TMC2", "TMC3",
+ "CSIM", nullptr, "SBIC", nullptr, "BRGC", "BRG", "SIO", nullptr,
+ "ASIM", nullptr, "ASIS", nullptr, "RXB", nullptr, "TXS", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PWMC0", "PWMC1", "PWM0L", nullptr, "PWM1L", nullptr, nullptr, nullptr,
+ "ISPR", nullptr, "IMC", nullptr, "MK0L", "MK0H", nullptr, nullptr,
+ nullptr, "ADCR0H", nullptr, "ADCR1H", nullptr, "ADCR2H", nullptr, "ADCR3H",
+ nullptr, "ADCR4H", nullptr, "ADCR5H", nullptr, "ADCR6H", nullptr, "ADCR7H",
+ "STBC", "CCW", "WDM", nullptr, "MM", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ "OVIC3", "PIC0", "PIC1", "PIC2", "PIC3", "PIC4", "TMIC0", "CMIC03",
+ "CMIC10", "CMIC40", "CMIC41", "SERIC", "SRIC", "STIC", "CSIIC", "ADIC",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78366a_disassembler::s_sfrp_names[128] =
+{
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CM00", "CM01", "CM02", "CM03", "BFCM00", "BFCM01", "BFCM02", "TM0",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "DTIME", nullptr,
+ "CM10", "TM1", "CC20", "CT20", "TM2", "BFCM03", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "CC30", "CT30", "CT31", "TM3", "CM40", "CM41", "TM4", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, "DACS", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, "PWM0", "PWM1", nullptr, nullptr, nullptr, "MK0", nullptr,
+ "ADCR0", "ADCR1", "ADCR2", "ADCR3", "ADCR4", "ADCR5", "ADCR6", "ADCR7",
+ nullptr, nullptr, nullptr, "PWC", nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+upd78372_disassembler::upd78372_disassembler()
+ : upd78k3_disassembler(s_sfr_names, s_sfrp_names, s_psw_bits, true, true)
+{
+}
+
+const char *const upd78372_disassembler::s_sfr_names[256] =
+{
+ "P0", "P1", "P2", "P3", "P4", "P5", nullptr, "P7",
+ "P8", "P9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TLA", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PM0", "PM1", "PM2", "PM3", nullptr, "PM5", nullptr, nullptr,
+ nullptr, "PM9", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TUM0", "TUM1", "TUM2", "TOC0", "TOC1", "TOC2", "PRM", "NPC",
+ nullptr, nullptr, nullptr, nullptr, "INTM0", "INTM1", nullptr, nullptr,
+ "PMC0", nullptr, "PMC2", "PMC3", "PUOL", "PUOH", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, "PRDC", nullptr, nullptr, nullptr, nullptr, nullptr,
+ "ADM", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, "ADCR0H", nullptr, "ADCR1H", nullptr, "ADCR2H", nullptr, "ADCR3H",
+ nullptr, "ADCR4H", nullptr, "ADCR5H", nullptr, "ADCR6H", nullptr, "ADCR7H",
+ "CSIM", nullptr, nullptr, nullptr, nullptr, nullptr, "SIO", nullptr,
+ "ASIM", nullptr, "ASIS", nullptr, "RXB", nullptr, "TXS", nullptr,
+ "BRGM", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "PWMC", nullptr, "PWM0L", nullptr, "PWM1L", nullptr, nullptr, nullptr,
+ "ISPR", nullptr, "IMC", nullptr, "MK0L", "MK0H", "MK1L", nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "STBC", "CCW", "WDM", nullptr, "MM", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // external access
+ "OVIC0", "OVIC3", "PLIC0", "PHIC0", "PLIC1", "PHIC1", "PLIC2", "PHIC2",
+ "PLIC3", "PHIC3", "PIC4", "PIC5", "CMIC10", "CMIC11", "CMIC12", "CMIC13",
+ "SERIC", "SRIC", "STIC", "CSIIC", "ADIC", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+const char *const upd78372_disassembler::s_sfrp_names[128] =
+{
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, "TM0", "CC00", "CC01", "CC02", "CC03", "CC04", "CC05",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "TM1", "CM10", "CM11", "CM12", "CM13", nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ "ADCR0", "ADCR1", "ADCR2", "ADCR3", "ADCR4", "ADCR5", "ADCR6", "ADCR7",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, "BRG", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "MK0", "MK1",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, "PWC", nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
+};
diff --git a/src/devices/cpu/upd78k/upd78k3d.h b/src/devices/cpu/upd78k/upd78k3d.h
new file mode 100644
index 00000000000..09853502e80
--- /dev/null
+++ b/src/devices/cpu/upd78k/upd78k3d.h
@@ -0,0 +1,164 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_UPD78K_UPD78K3D_H
+#define MAME_CPU_UPD78K_UPD78K3D_H
+
+#pragma once
+
+#include "upd78kd.h"
+
+class upd78k3_disassembler : public upd78k_family_disassembler
+{
+protected:
+ upd78k3_disassembler(const char *const sfr_names[], const char *const sfrp_names[], const char *const psw_bits[], bool has_macw, bool has_macsw);
+ upd78k3_disassembler(const char *const sfr_names[], const char *const sfrp_names[], const char *const ix_bases[]);
+
+ // register and mnemonic tables
+ static const char *const s_r_names[16];
+ static const char *const s_rp_names[8];
+ static const char *const s_ix_bases[5];
+ static const char *const s_psw_bits[16];
+ static const char *const s_alu_ops[8];
+ static const char *const s_16bit_ops[4];
+ static const char *const s_bool_ops[4];
+ static const char *const s_shift_ops[2][4];
+ static const char *const s_bcond[8];
+ static const char *const s_bcond_07f8[6];
+ static const char *const s_cmpscond[4];
+
+ // disasm_interface overrides
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+ // disassembly helpers
+ offs_t dasm_01xx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes);
+ offs_t dasm_02xx(std::ostream &stream, u8 op1, u8 op2, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_04(std::ostream &stream);
+ virtual offs_t dasm_05xx(std::ostream &stream, u8 op2);
+ virtual offs_t dasm_06xx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_07xx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes);
+ offs_t dasm_08xx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_09xx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes);
+ offs_t dasm_09xx_sfrmov(std::ostream &stream, u8 sfr, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_0axx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes);
+ offs_t dasm_15xx(std::ostream &stream, u8 op2);
+ virtual offs_t dasm_16xx(std::ostream &stream, u8 op1, u8 op2);
+ virtual offs_t dasm_24xx(std::ostream &stream, u8 op, u8 rr);
+ virtual offs_t dasm_2a(std::ostream &stream, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_38(std::ostream &stream, u8 op, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_3c(std::ostream &stream, u8 op, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_43(std::ostream &stream, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_50(std::ostream &stream, u8 op);
+ virtual offs_t dasm_78(std::ostream &stream, u8 op, offs_t pc, const data_buffer &opcodes);
+ virtual offs_t dasm_88xx(std::ostream &stream, u8 op, u8 rr);
+
+ // parameters
+ const char *const *const m_ix_bases;
+ const char *const *const m_psw_bits;
+ const bool m_has_macw;
+ const bool m_has_macsw;
+};
+
+class upd78312_disassembler : public upd78k3_disassembler
+{
+public:
+ upd78312_disassembler();
+
+protected:
+ // upd78k3_disassembler overrides
+ virtual offs_t dasm_04(std::ostream &stream) override;
+ virtual offs_t dasm_05xx(std::ostream &stream, u8 op2) override;
+ virtual offs_t dasm_06xx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes) override;
+ virtual offs_t dasm_07xx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes) override;
+ virtual offs_t dasm_09xx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes) override;
+ virtual offs_t dasm_0axx(std::ostream &stream, u8 op2, offs_t pc, const data_buffer &opcodes) override;
+ virtual offs_t dasm_16xx(std::ostream &stream, u8 op1, u8 op2) override;
+ virtual offs_t dasm_50(std::ostream &stream, u8 op) override;
+
+private:
+ // SFR tables
+ static const char *const s_sfr_names[256];
+ static const char *const s_sfrp_names[128];
+
+ // PSW table
+ static const char *const s_psw_bits[16];
+};
+
+class upd78322_disassembler : public upd78k3_disassembler
+{
+public:
+ upd78322_disassembler();
+
+private:
+ // SFR tables
+ static const char *const s_sfr_names[256];
+ static const char *const s_sfrp_names[128];
+};
+
+class upd78328_disassembler : public upd78k3_disassembler
+{
+public:
+ upd78328_disassembler();
+
+private:
+ // SFR tables
+ static const char *const s_sfr_names[256];
+ static const char *const s_sfrp_names[128];
+};
+
+class upd78334_disassembler : public upd78k3_disassembler
+{
+public:
+ upd78334_disassembler();
+
+private:
+ // SFR tables
+ static const char *const s_sfr_names[256];
+ static const char *const s_sfrp_names[128];
+};
+
+class upd78352_disassembler : public upd78k3_disassembler
+{
+public:
+ upd78352_disassembler();
+
+private:
+ // SFR tables
+ static const char *const s_sfr_names[256];
+ static const char *const s_sfrp_names[128];
+};
+
+class upd78356_disassembler : public upd78k3_disassembler
+{
+public:
+ upd78356_disassembler();
+
+private:
+ // SFR tables
+ static const char *const s_sfr_names[256];
+ static const char *const s_sfrp_names[128];
+};
+
+class upd78366a_disassembler : public upd78k3_disassembler
+{
+public:
+ upd78366a_disassembler();
+
+private:
+ // SFR tables
+ static const char *const s_sfr_names[256];
+ static const char *const s_sfrp_names[128];
+};
+
+class upd78372_disassembler : public upd78k3_disassembler
+{
+public:
+ upd78372_disassembler();
+
+private:
+ // SFR tables
+ static const char *const s_sfr_names[256];
+ static const char *const s_sfrp_names[128];
+};
+
+#endif // MAME_CPU_UPD78K_UPD78K3D_H
diff --git a/src/devices/cpu/upd78k/upd78kd.cpp b/src/devices/cpu/upd78k/upd78kd.cpp
index 71c3eb9715c..2193948169b 100644
--- a/src/devices/cpu/upd78k/upd78kd.cpp
+++ b/src/devices/cpu/upd78k/upd78kd.cpp
@@ -105,6 +105,18 @@ void upd78k_family_disassembler::format_sfrp(std::ostream &stream, u8 addr)
util::stream_format(stream, "0%04XH", 0xff00 + addr);
}
+void upd78k_family_disassembler::format_count(std::ostream &stream, u8 n)
+{
+ if (n < 0x0a)
+ util::stream_format(stream, "%d", n);
+ else
+ {
+ if (n >= 0x0a)
+ stream << "0";
+ util::stream_format(stream, "%02XH", n);
+ }
+}
+
void upd78k_family_disassembler::format_saddrp(std::ostream &stream, u8 addr)
{
if (addr < 0x20)
diff --git a/src/devices/cpu/upd78k/upd78kd.h b/src/devices/cpu/upd78k/upd78kd.h
index 2356a3cbbb8..5ebebdd17d7 100644
--- a/src/devices/cpu/upd78k/upd78kd.h
+++ b/src/devices/cpu/upd78k/upd78kd.h
@@ -25,6 +25,7 @@ protected:
void format_saddr(std::ostream &stream, u8 addr);
void format_sfrp(std::ostream &stream, u8 addr);
void format_saddrp(std::ostream &stream, u8 addr);
+ void format_count(std::ostream &stream, u8 n);
// generic illegal instruction dissasembly
offs_t dasm_illegal(std::ostream &stream, u8 op);
diff --git a/src/mame/drivers/roland_d50.cpp b/src/mame/drivers/roland_d50.cpp
new file mode 100644
index 00000000000..365bf6274ba
--- /dev/null
+++ b/src/mame/drivers/roland_d50.cpp
@@ -0,0 +1,110 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/****************************************************************************
+
+ Skeleton driver for Roland D-50/D-550.
+
+****************************************************************************/
+
+#include "emu.h"
+#include "cpu/upd78k/upd78k3.h"
+
+class roland_d50_state : public driver_device
+{
+public:
+ roland_d50_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
+ {
+ }
+
+ void d50(machine_config &config);
+
+private:
+ void mem_map(address_map &map);
+
+ required_device<upd78312_device> m_maincpu;
+};
+
+
+void roland_d50_state::mem_map(address_map &map)
+{
+ // Internal ROM is enabled at 0000–1FFF (+5V pullup on EA pin)
+ map(0x2000, 0xfdff).rom().region("progrom", 0x2000); // TODO: banking
+}
+
+
+static INPUT_PORTS_START(d50)
+INPUT_PORTS_END
+
+
+void roland_d50_state::d50(machine_config &config)
+{
+ UPD78312(config, m_maincpu, 12_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &roland_d50_state::mem_map);
+
+ // LCD unit is LM402802 (D-50) or LM402551 (D-550)
+
+ //MB87136(config, "synthe", 32.768_MHz_XTAL);
+}
+
+
+ROM_START(d50)
+ ROM_REGION(0x10000, "progrom", 0)
+ ROM_SYSTEM_BIOS(0, "v2.22", "ROM Version 2.22")
+ ROMX_LOAD("d-50_222.bin", 0x00000, 0x10000, CRC(e92c69f9) SHA1(fd783abc7fbd4abe2dedfe89d59e396b5e687a27), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v2.20", "ROM Version 2.20 (CFW, patched)")
+ ROMX_LOAD("roland_d50_220rw_cfw_patched.bin", 0x00000, 0x10000, CRC(8901640e) SHA1(abbc0026c64c55a6cbaca5e3e5dcb1a7536e91b3), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "v2.10", "ROM Version 2.10")
+ ROMX_LOAD("d50 - v.2.10 - ic22 - 27c512.bin", 0x00000, 0x10000, CRC(d1387c54) SHA1(904cf9daf296a66d3c4969266541983081e19471), ROM_BIOS(2))
+
+ ROM_REGION(0x2000, "maincpu", 0)
+ ROM_LOAD("d78312g-022_15179266.ic25", 0x0000, 0x2000, NO_DUMP) // 8-digit Roland part number not printed on IC
+ ROM_COPY("progrom", 0x0000, 0x0000, 0x2000)
+
+ ROM_REGION(0x40000, "pcma", 0)
+ ROM_LOAD("tc532000p-7469.ic30", 0x00000, 0x40000, NO_DUMP)
+
+ ROM_REGION(0x40000, "pcmb", 0)
+ ROM_LOAD("tc532000p-7470.ic29", 0x00000, 0x40000, NO_DUMP)
+ROM_END
+
+ROM_START(d50a)
+ ROM_REGION(0x10000, "progrom", 0)
+ ROM_SYSTEM_BIOS(0, "v1.06", "ROM Version 1.06")
+ ROMX_LOAD("d50-v1.06.bin", 0x00000, 0x10000, CRC(ccba4e46) SHA1(ce56321226dbbf7dbfac2ad344da447ad6448ee8), ROM_BIOS(0))
+
+ ROM_REGION(0x2000, "maincpu", 0)
+ ROM_LOAD("d78312g-017_15179261.ic25", 0x0000, 0x2000, NO_DUMP) // not compatible with newer firmware
+ ROM_COPY("progrom", 0x0000, 0x0000, 0x2000)
+
+ ROM_REGION(0x40000, "pcma", 0)
+ ROM_LOAD("tc532000p-7469.ic30", 0x00000, 0x40000, NO_DUMP)
+
+ ROM_REGION(0x40000, "pcmb", 0)
+ ROM_LOAD("tc532000p-7470.ic29", 0x00000, 0x40000, NO_DUMP)
+ROM_END
+
+ROM_START(d550)
+ ROM_REGION(0x10000, "progrom", 0)
+ ROM_SYSTEM_BIOS(0, "v1.02", "ROM Version 1.02")
+ ROMX_LOAD("roland d-550 v1.02 eprom firmware.bin", 0x00000, 0x10000, CRC(11b54d24) SHA1(d11bdb50c49edababec73a936346a6f918dd0949), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v1.01", "ROM Version 1.01")
+ ROMX_LOAD("roland_d-550_ver_1.01.bin", 0x00000, 0x10000, CRC(c267019f) SHA1(314616d14b91e8c8733aee5dd64736fda8ff6904), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "v1.0.0", "ROM Version 1.0.0")
+ ROMX_LOAD("d-550__1.0.0.mbm27c512.ic22.bin", 0x00000, 0x10000, CRC(f8ec84c3) SHA1(00b2b74009bdc0747e11bf57d4dc6c39424c7669), ROM_BIOS(2))
+
+ ROM_REGION(0x2000, "maincpu", 0)
+ ROM_LOAD("d78312g-022_15179266.ic25", 0x0000, 0x2000, NO_DUMP)
+ ROM_COPY("progrom", 0x0000, 0x0000, 0x2000)
+
+ ROM_REGION(0x40000, "pcma", 0)
+ ROM_LOAD("tc532000p-7469.ic30", 0x00000, 0x40000, NO_DUMP)
+
+ ROM_REGION(0x40000, "pcmb", 0)
+ ROM_LOAD("tc532000p-7470.ic29", 0x00000, 0x40000, NO_DUMP)
+ROM_END
+
+SYST(1987, d50, 0, 0, d50, d50, roland_d50_state, empty_init, "Roland", "D-50 (Ver. 2.xx)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
+SYST(1987, d50a, d50, 0, d50, d50, roland_d50_state, empty_init, "Roland", "D-50 (Ver. 1.xx)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
+SYST(1987, d550, d50, 0, d50, d50, roland_d50_state, empty_init, "Roland", "D-550", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index e9b22b5c3ef..0ebe4bc75aa 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -34460,6 +34460,11 @@ hangzo
@source:roland_cm32p.cpp
cm32p //
+@source:roland_d50.cpp
+d50 //
+d50a //
+d550 //
+
@source:roland_d110.cpp
d110 //
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 1770bfb5909..009cca7168d 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -739,6 +739,7 @@ riscpc.cpp
rm380z.cpp
rmnimbus.cpp
roland_cm32p.cpp
+roland_d50.cpp
roland_d110.cpp
roland_mt32.cpp
roland_sc55.cpp
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 5b0f345dc15..47e46adf004 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -163,6 +163,7 @@ using util::BIT;
#include "cpu/upd78k/upd78k0d.h"
#include "cpu/upd78k/upd78k1d.h"
#include "cpu/upd78k/upd78k2d.h"
+#include "cpu/upd78k/upd78k3d.h"
#include "cpu/v60/v60d.h"
#include "cpu/v810/v810dasm.h"
#include "cpu/vt50/vt50dasm.h"
@@ -551,6 +552,14 @@ static const dasm_table_entry dasm_table[] =
{ "upd78234", le, 0, []() -> util::disasm_interface * { return new upd78234_disassembler; } },
{ "upd78244", le, 0, []() -> util::disasm_interface * { return new upd78244_disassembler; } },
{ "upd780024a", le, 0, []() -> util::disasm_interface * { return new upd780024a_disassembler; } },
+ { "upd78312", le, 0, []() -> util::disasm_interface * { return new upd78312_disassembler; } },
+ { "upd78322", le, 0, []() -> util::disasm_interface * { return new upd78322_disassembler; } },
+ { "upd78328", le, 0, []() -> util::disasm_interface * { return new upd78328_disassembler; } },
+ { "upd78334", le, 0, []() -> util::disasm_interface * { return new upd78334_disassembler; } },
+ { "upd78352", le, 0, []() -> util::disasm_interface * { return new upd78352_disassembler; } },
+ { "upd78356", le, 0, []() -> util::disasm_interface * { return new upd78356_disassembler; } },
+ { "upd78366a", le, 0, []() -> util::disasm_interface * { return new upd78366a_disassembler; } },
+ { "upd78372", le, 0, []() -> util::disasm_interface * { return new upd78372_disassembler; } },
{ "upd780065", le, 0, []() -> util::disasm_interface * { return new upd780065_disassembler; } },
{ "upd780988", le, 0, []() -> util::disasm_interface * { return new upd78083_disassembler; } },
{ "upd78k0kx1", le, 0, []() -> util::disasm_interface * { return new upd78k0kx1_disassembler; } },