diff options
author | 2020-02-12 11:23:51 -0500 | |
---|---|---|
committer | 2020-02-12 11:59:41 -0500 | |
commit | 9ce46c7cd54200d2896bdd7ad10ee31201b63985 (patch) | |
tree | 749c321594a4e733313a7ea581c080d88c28fa4b /src/devices/cpu/upd78k/upd78k3.cpp | |
parent | 2d3e38c384026fd053534c4c62bddbe7ee41661a (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]
Diffstat (limited to 'src/devices/cpu/upd78k/upd78k3.cpp')
-rw-r--r-- | src/devices/cpu/upd78k/upd78k3.cpp | 347 |
1 files changed, 347 insertions, 0 deletions
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; + } +} |