From 9ce46c7cd54200d2896bdd7ad10ee31201b63985 Mon Sep 17 00:00:00 2001 From: AJR Date: Wed, 12 Feb 2020 11:23:51 -0500 Subject: [PATCH] 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] --- scripts/src/cpu.lua | 4 + scripts/target/mame/mess.lua | 1 + src/devices/cpu/upd78k/upd78k3.cpp | 347 ++++++ src/devices/cpu/upd78k/upd78k3.h | 114 ++ src/devices/cpu/upd78k/upd78k3d.cpp | 1648 +++++++++++++++++++++++++++ src/devices/cpu/upd78k/upd78k3d.h | 164 +++ src/devices/cpu/upd78k/upd78kd.cpp | 12 + src/devices/cpu/upd78k/upd78kd.h | 1 + src/mame/drivers/roland_d50.cpp | 110 ++ src/mame/mame.lst | 5 + src/mame/mess.flt | 1 + src/tools/unidasm.cpp | 9 + 12 files changed, 2416 insertions(+) create mode 100644 src/devices/cpu/upd78k/upd78k3.cpp create mode 100644 src/devices/cpu/upd78k/upd78k3.h create mode 100644 src/devices/cpu/upd78k/upd78k3d.cpp create mode 100644 src/devices/cpu/upd78k/upd78k3d.h create mode 100644 src/mame/drivers/roland_d50.cpp 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(UPD78K3_PSWL, "PSWL", + [this]() { return m_psw & 0x00ff; }, + [this](u8 data) { m_psw = (m_psw & 0xff00) | data; } + ).mask(0xfd).noshow(); + state_add(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(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(UPD78K3_RP0 + n, string_format("RP%d", n).c_str(), + [this, iram, n]() { return static_cast(iram)[register_base() >> 1 | n]; }, + [this, iram, n](u16 data) { static_cast(iram)[register_base() >> 1 | n] = data; } + ).formatstr("%9s"); + for (int n = 0; n < 2; n++) + state_add(UPD78K3_AX + n, std::array{{"AX", "BC"}}[n], + [this, iram, n]() { return static_cast(iram)[register_base() >> 1 | (m_psw & 0x0020) >> 4 | n]; }, + [this, iram, n](u16 data) { static_cast(iram)[register_base() >> 1 | (m_psw & 0x0020) >> 4 | n] = data; } + ).noshow(); + for (int n = 0; n < 4; n++) + { + state_add(UPD78K3_VP + n, std::array{{"VP", "UP", "DE", "HL"}}[n], + [this, iram, n]() { return static_cast(iram)[register_base() >> 1 | 0x04 | n]; }, + [this, iram, n](u16 data) { static_cast(iram)[register_base() >> 1 | 0x04 | n] = data; } + ); + state_add(UPD78K3_RP4 + n, string_format("RP%d", 4 + n).c_str(), + [this, iram, n]() { return static_cast(iram)[register_base() >> 1 | 0x04 | n]; }, + [this, iram, n](u16 data) { static_cast(iram)[register_base() >> 1 | 0x04 | n] = data; } + ).noshow(); + } + for (int n = 0; n < 16; n++) + state_add(UPD78K3_R0 + n, string_format("R%d", n).c_str(), + [this, iram, n]() { return static_cast(iram)[BYTE_XOR_LE(register_base() | n)]; }, + [this, iram, n](u8 data) { static_cast(iram)[BYTE_XOR_LE(register_base() | n)] = data; } + ).noshow(); + for (int n = 0; n < 4; n++) + state_add(UPD78K3_X + n, std::array{{"X", "A", "C", "B"}}[n], + [this, iram, n]() { return static_cast(iram)[BYTE_XOR_LE(register_base() | (m_psw & 0x0020) >> 3 | n)]; }, + [this, iram, n](u8 data) { static_cast(iram)[BYTE_XOR_LE(register_base() | (m_psw & 0x0020) >> 3 | n)] = data; } + ).noshow(); + for (int n = 0; n < 8; n++) + state_add(UPD78K3_VPL + n, std::array{{"VPL", "VPH", "UPL", "UPH", "E", "D", "L", "H"}}[n], + [this, iram, n]() { return static_cast(iram)[BYTE_XOR_LE(register_base() | 0x08 | n)]; }, + [this, iram, n](u8 data) { static_cast(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(*this).state_int(UPD78K3_RP0), BIT(m_psw, 5) ? " " : "(AX)"); + break; + + case UPD78K3_RP1: + str = string_format("%04X %s", const_cast(*this).state_int(UPD78K3_RP1), BIT(m_psw, 5) ? " " : "(BC)"); + break; + + case UPD78K3_RP2: + str = string_format("%04X %s", const_cast(*this).state_int(UPD78K3_RP2), BIT(m_psw, 5) ? "(AX)" : " "); + break; + + case UPD78K3_RP3: + str = string_format("%04X %s", const_cast(*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 upd78312_device::create_disassembler() +{ + return std::make_unique(); +} + + +//------------------------------------------------- +// 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(UPD78K3_PSWL, "PSWL", + [this]() { return m_psw & 0x00ff; }, + [this](u8 data) { m_psw = (m_psw & 0xff00) | data; } + ).noshow(); + state_add(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 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 ¶ms) +{ + 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 ¶ms) 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 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; } },