summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/pps41/mm78.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/pps41/mm78.cpp')
-rw-r--r--src/devices/cpu/pps41/mm78.cpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/devices/cpu/pps41/mm78.cpp b/src/devices/cpu/pps41/mm78.cpp
new file mode 100644
index 00000000000..dd875551fc8
--- /dev/null
+++ b/src/devices/cpu/pps41/mm78.cpp
@@ -0,0 +1,217 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*
+
+ Rockwell MM77/MM78 MCU
+
+*/
+
+#include "emu.h"
+#include "mm78.h"
+
+#include "pps41d.h"
+
+
+DEFINE_DEVICE_TYPE(MM78, mm78_device, "mm78", "Rockwell MM78 A7800") // 2KB ROM, 128 nibbles RAM
+DEFINE_DEVICE_TYPE(MM78L, mm78l_device, "mm78l", "Rockwell MM78L B7800") // low-power
+DEFINE_DEVICE_TYPE(MM77, mm77_device, "mm77", "Rockwell MM77 A7700") // 1.3KB ROM, 96 nibbles RAM
+DEFINE_DEVICE_TYPE(MM77L, mm77l_device, "mm77l", "Rockwell MM77L B7700") // 1.5KB ROM, low-power
+
+
+// constructor
+mm78_device::mm78_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ mm78_device(mconfig, MM78, tag, owner, clock, 11, address_map_constructor(FUNC(mm78_device::program_2k), this), 7, address_map_constructor(FUNC(mm78_device::data_128x4), this))
+{ }
+
+mm78_device::mm78_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) :
+ mm76_device(mconfig, type, tag, owner, clock, prgwidth, program, datawidth, data)
+{ }
+
+mm78l_device::mm78l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ mm78_device(mconfig, MM78L, tag, owner, clock, 11, address_map_constructor(FUNC(mm78l_device::program_2k), this), 7, address_map_constructor(FUNC(mm78l_device::data_128x4), this))
+{ }
+
+mm77_device::mm77_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ mm77_device(mconfig, MM77, tag, owner, clock, 11, address_map_constructor(FUNC(mm77_device::program_1_3k), this), 7, address_map_constructor(FUNC(mm77_device::data_96x4), this))
+{ }
+
+mm77_device::mm77_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) :
+ mm78_device(mconfig, type, tag, owner, clock, prgwidth, program, datawidth, data)
+{ }
+
+mm77l_device::mm77l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ mm77_device(mconfig, MM77L, tag, owner, clock, 11, address_map_constructor(FUNC(mm77l_device::program_1_5k), this), 7, address_map_constructor(FUNC(mm77l_device::data_96x4), this))
+{ }
+
+
+// internal memory maps
+void mm78_device::program_2k(address_map &map)
+{
+ map(0x000, 0x7ff).rom();
+}
+
+void mm78_device::program_1_3k(address_map &map)
+{
+ map(0x040, 0x1ff).rom();
+ map(0x240, 0x3ff).rom();
+ map(0x640, 0x7ff).rom();
+}
+
+void mm78_device::program_1_5k(address_map &map)
+{
+ map(0x000, 0x3ff).rom();
+ map(0x400, 0x5ff).mirror(0x200).rom();
+}
+
+void mm78_device::data_128x4(address_map &map)
+{
+ map(0x00, 0x7f).ram();
+}
+
+void mm78_device::data_96x4(address_map &map)
+{
+ map(0x00, 0x3f).ram();
+ map(0x40, 0x47).mirror(0x18).ram(); // not to 0x50
+ map(0x50, 0x57).ram();
+ map(0x60, 0x67).mirror(0x18).ram(); // not to 0x70
+ map(0x70, 0x77).ram();
+}
+
+
+// disasm
+std::unique_ptr<util::disasm_interface> mm78_device::create_disassembler()
+{
+ return std::make_unique<mm78_disassembler>();
+}
+
+
+// initialize
+void mm78_device::device_start()
+{
+ mm76_device::device_start();
+ m_stack_levels = 2;
+
+ state_add(++m_state_count, "X", m_x).formatstr("%01X"); // 6
+}
+
+void mm78_device::device_reset()
+{
+ mm76_device::device_reset();
+}
+
+
+//-------------------------------------------------
+// execute
+//-------------------------------------------------
+
+void mm78_device::execute_one()
+{
+ if (op_is_tr(m_prev_op) && op_is_tr(m_prev2_op))
+ {
+ // 3-byte opcodes
+ switch (m_op & 0xf0)
+ {
+ case 0x80: case 0x90: case 0xa0: case 0xb0: op_tmlb(); break;
+ case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_tlb(); break;
+
+ default: op_illegal(); break;
+ }
+ }
+ else if (op_is_tr(m_prev_op))
+ {
+ // 2-byte opcodes
+ switch (m_op & 0xf0)
+ {
+ case 0x30: op_tr(); break;
+ case 0x40: op_skbei(); break;
+ case 0x60:
+ if (m_op != 0x60)
+ op_skaei();
+ else
+ op_illegal();
+ break;
+
+ case 0x80: case 0x90: case 0xa0: case 0xb0: op_tml(); break;
+ case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_tl(); break;
+
+ default: op_illegal(); break;
+ }
+ }
+ else
+ {
+ // standard opcodes
+ switch (m_op & 0xf0)
+ {
+ case 0x10: op_lb(); break;
+ case 0x30: op_tr(); break;
+ case 0x40: op_lai(); break;
+ case 0x60:
+ if (m_op != 0x60)
+ op_aisk();
+ else
+ op_i1sk();
+ break;
+
+ case 0x80: case 0x90: case 0xa0: case 0xb0: op_tm(); break;
+ case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_t(); break;
+
+ default:
+ switch (m_op & 0xfc)
+ {
+ case 0x08: case 0x0c: op_eob(); break;
+ case 0x20: op_sb(); break;
+ case 0x24: op_rb(); break;
+ case 0x28: op_skbf(); break;
+ case 0x50: op_l(); break;
+ case 0x54: op_xnsk(); break;
+ case 0x58: op_xdsk(); break;
+ case 0x5c: op_x(); break;
+
+ default:
+ switch (m_op)
+ {
+ case 0x00: op_nop(); break;
+ case 0x01: op_skisl(); break;
+ case 0x02: op_sknc(); break;
+ case 0x03: op_int0h(); break;
+ case 0x04: op_int1l(); break;
+ case 0x05: op_rc(); break;
+ case 0x06: op_sc(); break;
+ case 0x07: op_sag(); break;
+
+ case 0x2c: break; // TAB
+ case 0x2d: op_ios(); break;
+ case 0x2e: op_rtsk(); break;
+ case 0x2f: op_rt(); break;
+
+ case 0x70: op_sos(); break;
+ case 0x71: op_ros(); break;
+ case 0x72: op_ix(); break;
+ case 0x73: op_ox(); break;
+ case 0x74: op_xas(); break;
+ case 0x75: op_lxa(); break;
+ case 0x76: op_lba(); break;
+ case 0x77: op_com(); break;
+ case 0x78: op_i2c(); break;
+ case 0x79: op_xax(); break;
+ case 0x7a: op_xab(); break;
+ case 0x7b: op_ioa(); break;
+ case 0x7c: op_ac(); break;
+ case 0x7d: op_acsk(); break;
+ case 0x7e: op_a(); break;
+ case 0x7f: op_skmea(); break;
+
+ default: op_illegal(); break; // won't happen
+ }
+ break; // 0xff
+
+ }
+ break; // 0xfc
+
+ } // 0xf0
+ }
+
+ // TAB is delayed by 1 opcode (including a single TR)
+ if (m_prev_op == 0x2c)
+ op_tab();
+}