summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2020-06-28 20:03:13 -0400
committer AJR <ajrhacker@users.noreply.github.com>2020-06-28 20:03:13 -0400
commit040c88bf1d206cbbc47129e3e99d34ffbe4436da (patch)
tree45f94f8cddfaed8e3c78764fedd995b60024ce5f /src/devices
parent606ef88f02c7218f1ea8c99ed83316dc7dad9c7c (diff)
New machines marked as NOT_WORKING
---------------------------------- Korg WaveStation EX [DBWBP] Korg WaveStation A/D [DBWBP] Korg WaveStation SR [DBWBP] -Add H16 disassembler and skeleton HD641016 CPU device [AJR]
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/cpu/h16/h16dasm.cpp1052
-rw-r--r--src/devices/cpu/h16/h16dasm.h55
-rw-r--r--src/devices/cpu/h16/hd641016.cpp235
-rw-r--r--src/devices/cpu/h16/hd641016.h142
4 files changed, 1484 insertions, 0 deletions
diff --git a/src/devices/cpu/h16/h16dasm.cpp b/src/devices/cpu/h16/h16dasm.cpp
new file mode 100644
index 00000000000..ac502508e89
--- /dev/null
+++ b/src/devices/cpu/h16/h16dasm.cpp
@@ -0,0 +1,1052 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Hitachi H16 (HD641016) disassembler
+
+***************************************************************************/
+
+#include "emu.h"
+#include "h16dasm.h"
+
+h16_disassembler::h16_disassembler()
+ : util::disasm_interface()
+{
+}
+
+u32 h16_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+const char *const h16_disassembler::s_conditions[16] = {
+ "T", "F",
+ "HI", "LS",
+ "CC", "CS",
+ "NE", "EQ",
+ "VC", "VS",
+ "PL", "MI",
+ "GE", "LT",
+ "GT", "LE"
+};
+
+const char *const h16_disassembler::s_term_conditions[16] = {
+ "T", "F",
+ "HI", "LS",
+ "HS", "LO",
+ "NE", "EQ",
+ "VC", "VS",
+ "PL", "MI",
+ "GE", "LT",
+ "GT", "LE"
+};
+
+const char *const h16_disassembler::s_basic_ops[4] = {
+ "ADD", "SUB", "CMP", "MOV"
+};
+
+const char *const h16_disassembler::s_logical_ops[3] = {
+ "AND", "XOR", "OR"
+};
+
+const char *const h16_disassembler::s_sft_ops[8] = {
+ "SHAR", "SHLR", "ROTR", "ROTXR",
+ "SHAL", "SHLL", "ROTL", "ROTXL"
+};
+
+const char *const h16_disassembler::s_bit_ops[4] = {
+ "BSET", "BNOT", "BCLR", "BTST"
+};
+
+const char *const h16_disassembler::s_bf_ops[3] = {
+ "BFEXT", "BFINS", "BFSCH"
+};
+
+const char *const h16_disassembler::s_cr_ops[5] = {
+ "ANDC", "ORC", "XORC", "LDC", "STC"
+};
+
+void h16_disassembler::format_register(std::ostream &stream, char bank, u8 n) const
+{
+ if (bank != 0)
+ util::stream_format(stream, "%cR%d", bank, n);
+ else if (n == 15)
+ stream << "SP";
+ else
+ util::stream_format(stream, "R%d", n);
+}
+
+void h16_disassembler::format_register_to_register(std::ostream &stream, u8 rr) const
+{
+ format_register(stream, 0, rr >> 4);
+ stream << ", ";
+ format_register(stream, 0, rr & 0x0f);
+}
+
+void h16_disassembler::format_register_list(std::ostream &stream, u16 rl) const
+{
+ stream << "[";
+ bool first = false;
+ for (int n = 0; n < 16; n++)
+ {
+ if (BIT(rl, n))
+ {
+ if (first)
+ stream << ",";
+ else
+ first = true;
+ int m = n + 1;
+ while (m < 16 && BIT(rl, m))
+ m++;
+ m--;
+ if (m > n)
+ {
+ util::stream_format(stream, "R%d-R%d", n, m);
+ n = m;
+ }
+ else
+ util::stream_format(stream, "R%d", n);
+ }
+ }
+ stream << "]";
+}
+
+u8 h16_disassembler::get_cr_size(u8 cr) const
+{
+ switch (cr)
+ {
+ case 0x01: case 0x80: case 0x81:
+ return 0;
+
+ case 0x20: case 0xa0:
+ return 1;
+
+ default:
+ return 2;
+ }
+}
+
+void h16_disassembler::format_cr(std::ostream &stream, u8 cr) const
+{
+ switch (cr)
+ {
+ case 0x01:
+ stream << "VBNR";
+ break;
+
+ case 0x20:
+ stream << "CCR";
+ break;
+
+ case 0x40:
+ stream << "CBNR";
+ break;
+
+ case 0x41:
+ stream << "BSP";
+ break;
+
+ case 0x80:
+ stream << "BMR";
+ break;
+
+ case 0x81:
+ stream << "GBNR";
+ break;
+
+ case 0xa0:
+ stream << "SR";
+ break;
+
+ case 0xc0:
+ stream << "EBR";
+ break;
+
+ case 0xc1:
+ stream << "RBR";
+ break;
+
+ case 0xc2:
+ stream << "USP";
+ break;
+
+ case 0xc3:
+ stream << "IBR";
+ break;
+
+ default:
+ stream << "<unknown CR>";
+ break;
+ }
+}
+
+void h16_disassembler::format_s8(std::ostream &stream, u8 data) const
+{
+ if (s8(data) < 0)
+ {
+ stream << "-";
+ data = 0x100 - data;
+ }
+ if (data >= 0x0a)
+ stream << "H'";
+ util::stream_format(stream, "%X", data);
+}
+
+void h16_disassembler::format_s16(std::ostream &stream, u16 data) const
+{
+ if (s16(data) < 0)
+ {
+ stream << "-";
+ data = 0x10000 - data;
+ }
+ if (data >= 0x000a)
+ stream << "H'";
+ util::stream_format(stream, "%X", data);
+}
+
+void h16_disassembler::format_s32(std::ostream &stream, u32 data) const
+{
+ if (s32(data) < 0)
+ {
+ stream << "-";
+ data = u32(-data);
+ }
+ if (data >= 0x0000000a)
+ stream << "H'";
+ util::stream_format(stream, "%X", data);
+}
+
+void h16_disassembler::dasm_displacement(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, u8 sd) const
+{
+ switch (sd)
+ {
+ case 0:
+ // No displacement
+ break;
+
+ case 1:
+ {
+ // 8-bit displacement
+ format_s8(stream, opcodes.r8(pc++));
+ stream << ", ";
+ break;
+ }
+
+ case 2:
+ {
+ // 16-bit displacement
+ u16 disp = opcodes.r16(pc);
+ pc += 2;
+ format_s16(stream, disp);
+ if (disp < 0x0080 || disp >= 0xff80)
+ stream << ":16";
+ stream << ", ";
+ break;
+ }
+
+ case 3:
+ {
+ // 32-bit displacement
+ u32 disp = opcodes.r32(pc);
+ pc += 4;
+ format_s32(stream, disp);
+ if (disp < 0x00008000 || disp >= 0xffff8000U)
+ stream << ":32";
+ stream << ", ";
+ break;
+ }
+ }
+}
+
+void h16_disassembler::dasm_ea(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, u8 ea, char bank, h16_disassembler::ea_mode mode, u8 sz) const
+{
+ if (ea < 0x10)
+ {
+ // Register indirect
+ stream << "@";
+ format_register(stream, bank, ea);
+ }
+ else if (ea < 0x40)
+ {
+ // Register indirect (with displacement)
+ stream << "@(";
+ dasm_displacement(stream, pc, opcodes, ea >> 4);
+ format_register(stream, bank, ea & 0x0f);
+ stream << ")";
+ }
+ else if (ea < 0x50)
+ {
+ // Register direct
+ if (mode != ea_mode::ADDRESS && mode != ea_mode::MEMORY && mode != ea_mode::PLAIN_MEMORY)
+ format_register(stream, bank, ea & 0x0f);
+ else
+ stream << "<RIE>";
+ }
+ else if (ea < 0x70 && mode != ea_mode::PLAIN_MEMORY && mode != ea_mode::BITFIELD)
+ {
+ // Register indirect auto-increment/auto-decrement
+ stream << "@";
+ if (BIT(ea, 5))
+ stream << "-";
+ format_register(stream, bank, ea & 0x0f);
+ if (BIT(ea, 4))
+ stream << "+";
+ }
+ else switch (ea)
+ {
+ case 0x70:
+ // Current bank
+ ea = opcodes.r8(pc++);
+ dasm_ea(stream, pc, opcodes, ea & 0x7f, 'C', mode, sz);
+ break;
+
+ case 0x71:
+ // Immediate (Imm8)
+ switch (mode)
+ {
+ case ea_mode::SIGNED:
+ stream << "#";
+ format_s8(stream, opcodes.r8(pc++));
+ if (sz != 0)
+ stream << ".B";
+ break;
+
+ case ea_mode::UNSIGNED:
+ stream << "#";
+ if (sz == 0)
+ util::stream_format(stream, "H'%02X", opcodes.r8(pc++));
+ else
+ {
+ u8 imm = opcodes.r8(pc++);
+ if (imm >= 0x0a)
+ stream << "H'";
+ util::stream_format(stream, "%X.B", imm);
+ }
+ break;
+
+ default:
+ stream << "<RIE>";
+ break;
+ }
+ break;
+
+ case 0x72:
+ // Immediate (Imm16)
+ switch (mode)
+ {
+ case ea_mode::SIGNED:
+ stream << "#";
+ format_s16(stream, opcodes.r16(pc));
+ pc += 2;
+ if (sz != 1)
+ stream << ".W";
+ break;
+
+ case ea_mode::UNSIGNED:
+ stream << "#";
+ if (sz == 1)
+ util::stream_format(stream, "H'%04X", opcodes.r16(pc));
+ else
+ {
+ u16 imm = opcodes.r16(pc);
+ if (imm >= 0x000a)
+ stream << "H'";
+ util::stream_format(stream, "%X.W", imm);
+ }
+ pc += 2;
+ break;
+
+ default:
+ stream << "<RIE>";
+ break;
+ }
+ break;
+
+ case 0x73:
+ // Immediate (Imm32)
+ switch (mode)
+ {
+ case ea_mode::SIGNED:
+ stream << "#";
+ format_s32(stream, opcodes.r32(pc));
+ pc += 4;
+ if (sz != 2)
+ stream << ".L";
+ break;
+
+ case ea_mode::UNSIGNED:
+ stream << "#";
+ if (sz == 2)
+ util::stream_format(stream, "H'%08X", opcodes.r32(pc));
+ else
+ {
+ u32 imm = opcodes.r32(pc);
+ if (imm >= 0x0000000a)
+ stream << "H'";
+ util::stream_format(stream, "%X.L", imm);
+ }
+ pc += 4;
+ break;
+
+ default:
+ stream << "<RIE>";
+ break;
+ }
+ break;
+
+ case 0x74:
+ // Previous bank
+ ea = opcodes.r8(pc++);
+ dasm_ea(stream, pc, opcodes, ea & 0x7f, 'P', mode, sz);
+ break;
+
+ case 0x75:
+ {
+ // Absolute address (Abs8)
+ u8 aa = opcodes.r8(pc++);
+ if (aa < 0x80)
+ util::stream_format(stream, "@H'%02X", aa);
+ else
+ util::stream_format(stream, "@H'%X", aa + (mode != ea_mode::ADDRESS ? 0xffff00U : 0xffffff00U));
+ break;
+ }
+
+ case 0x76:
+ {
+ // Absolute address (Abs16)
+ u16 aa = opcodes.r16(pc);
+ pc += 2;
+ if (aa < 0x80)
+ util::stream_format(stream, "@H'%X.W", aa);
+ else if (aa < 0x8000)
+ util::stream_format(stream, "@H'%04X", aa);
+ else
+ {
+ util::stream_format(stream, "@H'%X", aa + (mode != ea_mode::ADDRESS ? 0xff0000U : 0xffff0000U));
+ if (aa >= 0xff80)
+ stream << ".W";
+ }
+ break;
+ }
+
+ case 0x77:
+ {
+ // Absolute address (Abs32)
+ u32 aa = opcodes.r32(pc);
+ pc += 4;
+ if (aa < 0x8000)
+ util::stream_format(stream, "@H'%X.L", aa);
+ else if (mode != ea_mode::ADDRESS)
+ {
+ aa &= 0xffffff;
+ util::stream_format(stream, "@H'%06X", aa);
+ if (aa >= 0xff8000)
+ stream << ".L";
+ }
+ else
+ {
+ util::stream_format(stream, "@H'%08X", aa);
+ if (aa >= 0xffff8000U)
+ stream << ".L";
+ }
+ break;
+ }
+
+ case 0x78:
+ {
+ // Register indirect with scale
+ u8 xb = opcodes.r8(pc++);
+ stream << "@";
+ format_register(stream, bank, xb & 0x0f);
+ util::stream_format(stream, "*%d", 1 << BIT(xb, 4, 2));
+ break;
+ }
+
+ case 0x79: case 0x7a: case 0x7b:
+ {
+ // Register indirect with scale (and displacement)
+ u8 xb = opcodes.r8(pc++);
+ stream << "@(";
+ dasm_displacement(stream, pc, opcodes, ea & 0x03);
+ format_register(stream, bank, xb & 0x0f);
+ util::stream_format(stream, "*%d)", 1 << BIT(xb, 4, 2));
+ break;
+ }
+
+ case 0x7c:
+ {
+ u8 xb1 = opcodes.r8(pc++);
+ if (xb1 < 0x80)
+ {
+ // Register indirect with index
+ u8 xb2 = opcodes.r8(pc++);
+ stream << "@(";
+ dasm_displacement(stream, pc, opcodes, BIT(xb1, 4, 2));
+ format_register(stream, 0, xb2 & 0x0f);
+ util::stream_format(stream, ".%c", BIT(xb1, 6) ? 'L' : 'W');
+ if ((xb2 & 0x30) != 0)
+ util::stream_format(stream, "*%d", 1 << BIT(xb2, 4, 2));
+ stream << ", ";
+ format_register(stream, bank, xb1 & 0x0f);
+ stream << ")";
+ }
+ else
+ stream << "<RIE>";
+ break;
+ }
+
+ case 0x7d:
+ {
+ u8 xb1 = opcodes.r8(pc++);
+ if (xb1 < 0x80)
+ {
+ // Program counter relative with index
+ u8 xb2 = opcodes.r8(pc++);
+ stream << "@(";
+ dasm_displacement(stream, pc, opcodes, BIT(xb1, 4, 2));
+ format_register(stream, bank, xb2 & 0x0f);
+ util::stream_format(stream, ".%c", BIT(xb1, 6) ? 'L' : 'W');
+ if ((xb2 & 0x30) != 0)
+ util::stream_format(stream, "*%d", 1 << BIT(xb2, 4, 2));
+ stream << ", PC)";
+ }
+ else if (xb1 < 0x90)
+ stream << "@PC";
+ else if (xb1 < 0xc0)
+ {
+ // Program counter relative
+ stream << "@(";
+ dasm_displacement(stream, pc, opcodes, BIT(xb1, 4, 2));
+ stream << "PC)";
+ }
+ else
+ stream << "<RIE>";
+ break;
+ }
+
+ case 0x7e:
+ {
+ // Register double indirect (only 8-bit and 32-bit displacements allowed)
+ u8 xb = opcodes.r8(pc++);
+ if ((xb & 0x50) == 0x50)
+ {
+ stream << "@";
+ u32 ds1 = BIT(xb, 5) ? opcodes.r32(std::exchange(pc, pc + 4)) : s32(s8(opcodes.r8(pc++)));
+ u32 ds2 = BIT(xb, 7) ? opcodes.r32(std::exchange(pc, pc + 4)) : s32(s8(opcodes.r8(pc++)));
+ if (ds2 != 0)
+ {
+ stream << "(";
+ format_s32(stream, ds2);
+ if (BIT(xb, 7) && (ds2 < 0x00000080 || ds2 >= 0xffffff80U))
+ stream << ":32";
+ stream << ", ";
+ }
+ stream << "@";
+ if (ds1 != 0)
+ {
+ stream << "(";
+ format_s32(stream, ds1);
+ if (BIT(xb, 5) && (ds1 < 0x00000080 || ds1 >= 0xffffff80U))
+ stream << ":32";
+ stream << ", ";
+ }
+ format_register(stream, bank, xb & 0x0f);
+ if (ds1 != 0)
+ stream << ")";
+ if (ds2 != 0)
+ stream << ")";
+ }
+ else
+ stream << "<RIE>";
+ break;
+ }
+
+ default:
+ // Not used
+ stream << "<RIE>";
+ break;
+ }
+}
+
+void h16_disassembler::dasm_eas_ead(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, h16_disassembler::ea_mode smode, h16_disassembler::ea_mode dmode, u8 sz) const
+{
+ dasm_eas_ead(stream, pc, opcodes, smode, dmode, sz, sz);
+}
+
+void h16_disassembler::dasm_eas_ead(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, h16_disassembler::ea_mode smode, h16_disassembler::ea_mode dmode, u8 szs, u8 szd) const
+{
+ const offs_t pcs = pc;
+ u8 eas = opcodes.r8(pc++);
+ dasm_ea(stream, pc, opcodes, eas & 0x7f, 0, smode, szs);
+ stream << ", ";
+ u8 ead = BIT(eas, 7) ? 0x40 : opcodes.r8(pc++);
+ dasm_ea(stream, pc, opcodes, ead & 0x7f, 0, dmode, szd);
+
+ // Reinterpret PC-relative source offsets by working backwards
+ if ((eas & 0x7f) == 0x7d)
+ {
+ u8 xb1 = opcodes.r8(pcs + 1);
+ const offs_t disppc = pcs + (BIT(xb1, 7) ? 2 : 3);
+ switch (xb1 & 0xf0)
+ {
+ case 0x00: case 0x40: case 0x80:
+ util::stream_format(stream, " ; H'%06X", disppc & 0xffffff);
+ break;
+
+ case 0x10: case 0x50: case 0x90:
+ util::stream_format(stream, " ; H'%06X", (disppc + 1 + s8(opcodes.r8(disppc))) & 0xffffff);
+ break;
+
+ case 0x20: case 0x60: case 0xa0:
+ util::stream_format(stream, " ; H'%06X", (disppc + 2 + s16(opcodes.r16(disppc))) & 0xffffff);
+ break;
+
+ case 0x30: case 0x70: case 0xb0:
+ util::stream_format(stream, " ; H'%06X", (disppc + 4 + opcodes.r32(disppc)) & 0xffffff);
+ break;
+ }
+ }
+}
+
+void h16_disassembler::dasm_branch_disp(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, u8 sz) const
+{
+ switch (sz)
+ {
+ case 0:
+ {
+ u8 disp = opcodes.r8(pc++);
+ util::stream_format(stream, "H'%06X", (pc + s8(disp)) & 0xffffff);
+ break;
+ }
+
+ case 1:
+ {
+ u16 disp = opcodes.r16(pc);
+ pc += 2;
+ util::stream_format(stream, "H'%06X", (pc + s16(disp)) & 0xffffff);
+ break;
+ }
+
+ case 2:
+ {
+ u32 disp = opcodes.r32(pc);
+ pc += 4;
+ util::stream_format(stream, "H'%06X", (pc + disp) & 0xffffff);
+ break;
+ }
+ }
+}
+
+offs_t h16_disassembler::disassemble(std::ostream &stream, offs_t pc, const h16_disassembler::data_buffer &opcodes, const h16_disassembler::data_buffer &params)
+{
+ const offs_t pc0 = pc;
+ offs_t flags = SUPPORTED;
+ u8 op = opcodes.r8(pc++);
+ switch (op)
+ {
+ case 0x00: case 0x01: case 0x02:
+ case 0x04: case 0x05: case 0x06:
+ case 0x08: case 0x09: case 0x0a:
+ case 0x0c: case 0x0d: case 0x0e:
+ util::stream_format(stream, "%-9s", string_format("%s.%c", s_basic_ops[BIT(op, 2, 2)], "BWL"[op & 0x03]));
+ dasm_eas_ead(stream, pc, opcodes,
+ (op & 0x0c) == 0x0c ? ea_mode::UNSIGNED : ea_mode::SIGNED,
+ (op & 0x0c) == 0x08 ? ea_mode::SIGNED : ea_mode::DESTINATION,
+ op & 0x03);
+ break;
+
+ case 0x10: case 0x11: case 0x12:
+ case 0x18: case 0x19: case 0x1a:
+ case 0x1c: case 0x1d: case 0x1e:
+ util::stream_format(stream, "%-9s#", string_format("%s.%c", s_basic_ops[BIT(op, 2, 2)], "BWL"[op & 0x03]));
+ if (op == 0x1c)
+ util::stream_format(stream, "H'%02X", opcodes.r8(pc++));
+ else
+ format_s8(stream, opcodes.r8(pc++));
+ stream << ", ";
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, (op & 0x0c) == 0x08 ? ea_mode::SIGNED : ea_mode::DESTINATION, op & 0x03);
+ break;
+
+ case 0x14: case 0x15: case 0x16:
+ util::stream_format(stream, "%-9s", string_format("CLR.%c", "BWL"[op & 0x03]));
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, op & 0x03);
+ break;
+
+ case 0x20: case 0x21: case 0x22:
+ case 0x24: case 0x25: case 0x26:
+ case 0x28: case 0x29: case 0x2a:
+ case 0x2c: case 0x2d: case 0x2e:
+ util::stream_format(stream, "%-9s", string_format("%s.%c", s_basic_ops[BIT(op, 2, 2)], "BWL"[op & 0x03]));
+ format_register_to_register(stream, opcodes.r8(pc++));
+ break;
+
+ case 0x30: case 0x31: case 0x32:
+ case 0x34: case 0x35: case 0x36:
+ case 0x38: case 0x39: case 0x3a:
+ case 0x3c: case 0x3d: case 0x3e:
+ {
+ u8 xb = opcodes.r8(pc++);
+ util::stream_format(stream, "%-9s", string_format("%s.%c", s_basic_ops[BIT(op, 2, 2)], "BWL"[op & 0x03]));
+ util::stream_format(stream, "#%d, ", !BIT(op, 3) || !BIT(xb, 3) ? xb & 0x0f : int(xb & 0x0f) - 16);
+ format_register(stream, 0, xb >> 4);
+ break;
+ }
+
+ case 0x40: case 0x41: case 0x42:
+ case 0x44: case 0x45: case 0x46:
+ case 0x48: case 0x49: case 0x4a:
+ case 0x4c: case 0x4d: case 0x4e:
+ util::stream_format(stream, "%-9s", string_format("%sS.%c", s_basic_ops[BIT(op, 2, 2)], "BWL"[op & 0x03]));
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::SIGNED, ea_mode::DESTINATION, op & 0x03, 2);
+ break;
+
+ case 0x50: case 0x51: case 0x52:
+ case 0x54: case 0x55: case 0x56:
+ util::stream_format(stream, "%-9s", string_format("%sX.%c", s_basic_ops[BIT(op, 2, 2)], "BWL"[op & 0x03]));
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::UNSIGNED, ea_mode::DESTINATION, op & 0x03);
+ break;
+
+ case 0x58: case 0x59: case 0x5a:
+ util::stream_format(stream, "%-9s", string_format("TST.%c", "BWL"[op & 0x03]));
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::SIGNED, op & 0x03);
+ break;
+
+ case 0x5c: case 0x5d: case 0x5e:
+ util::stream_format(stream, "%-9s", string_format("MOVF.%c", "BWL"[op & 0x03]));
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, op & 0x03);
+ break;
+
+ case 0x60: case 0x61: case 0x62:
+ case 0x64: case 0x65: case 0x66:
+ case 0x68: case 0x69: case 0x6a:
+ case 0x6c: case 0x6d: case 0x6e:
+ {
+ u8 xb = opcodes.r8(pc++);
+ if (BIT(op, 3))
+ util::stream_format(stream, "%-9s", string_format("%s.%c", s_bit_ops[BIT(xb, 5, 2)], "BWL"[op & 0x03]));
+ else
+ util::stream_format(stream, "%-9s", string_format("%s.%c", s_sft_ops[BIT(xb, 5, 3)], "BWL"[op & 0x03]));
+ if (BIT(op, 2))
+ util::stream_format(stream, "#%d", xb & 0x1f);
+ else
+ format_register(stream, 0, xb & 0x0f);
+ stream << ", ";
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, op & 0x03);
+ break;
+ }
+
+ case 0x70: case 0x71: case 0x72:
+ {
+ util::stream_format(stream, "%-9s", string_format("STM.%c", "BWL"[op & 0x03]));
+ std::ostringstream eadbuf;
+ dasm_ea(eadbuf, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::MEMORY, op & 0x03);
+ format_register_list(stream, opcodes.r16(pc));
+ pc += 2;
+ util::stream_format(stream, ", %s", eadbuf.str());
+ break;
+ }
+
+ case 0x74: case 0x75: case 0x76:
+ util::stream_format(stream, "%-9s", string_format("LDM.%c", "BWL"[op & 0x03]));
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::MEMORY, op & 0x03);
+ stream << ", ";
+ format_register_list(stream, opcodes.r16(pc));
+ pc += 2;
+ break;
+
+ case 0x78: case 0x79: case 0x7a:
+ util::stream_format(stream, "%-9s", string_format("MOVTPE.%c", "BWL"[op & 0x03]));
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::UNSIGNED, ea_mode::PLAIN_MEMORY, op & 0x03);
+ break;
+
+ case 0x7c: case 0x7d: case 0x7e:
+ util::stream_format(stream, "%-9s", string_format("MOVFPE.%c", "BWL"[op & 0x03]));
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::PLAIN_MEMORY, ea_mode::DESTINATION, op & 0x03);
+ break;
+
+ case 0x80: case 0x81: case 0x82:
+ case 0x84: case 0x85: case 0x86:
+ case 0x88: case 0x89: case 0x8a:
+ util::stream_format(stream, "%-9s", string_format("%s.%c", s_logical_ops[BIT(op, 2, 2)], "BWL"[op & 0x03]));
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::UNSIGNED, ea_mode::DESTINATION, op & 0x03);
+ break;
+
+ case 0x8c: case 0x8d: case 0x8e:
+ case 0x9c: case 0x9d: case 0x9e:
+ util::stream_format(stream, "%-9s", string_format("NEG%s.%c", BIT(op, 4) ? "X" : "", "BWL"[op & 0x03]));
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, op & 0x03);
+ break;
+
+ case 0x90: case 0x91: case 0x92:
+ util::stream_format(stream, "%-9s", string_format("NOT.%c", "BWL"[op & 0x03]));
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, op & 0x03);
+ break;
+
+ case 0x94: case 0x95:
+ {
+ u8 xb1 = opcodes.r8(pc++);
+ if ((xb1 & 0x30) == 0 || (xb1 & 0x70) == 0x20 || (xb1 & 0x70) == 0x50)
+ {
+ u8 xb2 = opcodes.r8(pc++);
+ if (BIT(xb1, 7))
+ {
+ u8 xb3 = opcodes.r8(pc++);
+ util::stream_format(stream, "S%s/%s/%c.%c ", (xb1 & 0x30) == 0 ? "SCH" : "CMP", s_term_conditions[xb3 & 0x0f], "FB"[BIT(xb1, 6)], "BW"[BIT(op, 0)]);
+ format_register_to_register(stream, xb2);
+ stream << ", ";
+ format_register(stream, 0, xb1 & 0x0f);
+ stream << ", ";
+ format_register(stream, 0, xb3 >> 4);
+ }
+ else
+ {
+ util::stream_format(stream, "S%s/%c.%c ", (xb1 & 0x30) == 0 ? "MOV" : "STR", "FB"[BIT(xb1, 6)], "BW"[BIT(op, 0)]);
+ format_register_to_register(stream, xb2);
+ stream << ", ";
+ format_register(stream, 0, xb1 & 0x0f);
+ }
+ }
+ else
+ stream << "{RIE}";
+ break;
+ }
+
+ case 0x98: case 0x99: case 0x9a:
+ util::stream_format(stream, "%-9s", string_format("BRA.%c", "BWL"[op & 0x03]));
+ dasm_branch_disp(stream, pc, opcodes, op & 0x03);
+ break;
+
+ case 0x9b:
+ util::stream_format(stream, "%-9s", "JMP");
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::MEMORY, 2);
+ break;
+
+ case 0xa0: case 0xa1: case 0xa2: case 0xb0: case 0xb1: case 0xb2:
+ util::stream_format(stream, "%-9s", string_format("B%s.%c", BIT(op, 4) ? "NE" : "EQ", "BWL"[op & 0x03]));
+ dasm_branch_disp(stream, pc, opcodes, op & 0x03);
+ break;
+
+ case 0xa3: case 0xa7:
+ util::stream_format(stream, "%-9s", BIT(op, 2) ? "DSUB" : "DADD");
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::SIGNED, ea_mode::DESTINATION, 0);
+ break;
+
+ case 0xa4: case 0xa5: case 0xa6:
+ util::stream_format(stream, "%-9s", string_format("B%s.%c", s_conditions[opcodes.r8(pc++) & 0x0f], "BWL"[op & 0x03]));
+ dasm_branch_disp(stream, pc, opcodes, op & 0x03);
+ break;
+
+ case 0xa8: case 0xa9: case 0xaa:
+ util::stream_format(stream, "%-9s", string_format("BSR.%c", "BWL"[op & 0x03]));
+ dasm_branch_disp(stream, pc, opcodes, op & 0x03);
+ flags |= STEP_OVER;
+ break;
+
+ case 0xab:
+ util::stream_format(stream, "%-9s", "JSR");
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::MEMORY, 2);
+ flags |= STEP_OVER;
+ break;
+
+ case 0xac: case 0xad: case 0xae: case 0xbc: case 0xbd: case 0xbe:
+ util::stream_format(stream, "%-9s", string_format("EXT%c.%c", "US"[BIT(op, 4)], "WLB"[op & 0x03]));
+ format_register(stream, 0, opcodes.r8(pc++) & 0x0f);
+ break;
+
+ case 0xb3:
+ util::stream_format(stream, "%-9s", "XCH");
+ format_register_to_register(stream, opcodes.r8(pc++));
+ break;
+
+ case 0xb4: case 0xb5: case 0xb6:
+ {
+ u8 xb = opcodes.r8(pc++);
+ util::stream_format(stream, "%-9s", string_format("SCB/%s.%c", s_conditions[xb & 0x0f], "BWL"[op & 0x03]));
+ format_register(stream, 0, xb >> 4);
+ stream << ", ";
+ dasm_branch_disp(stream, pc, opcodes, op & 0x03);
+ break;
+ }
+
+ case 0xb7:
+ util::stream_format(stream, "%-9s", string_format("SET/%s", s_conditions[opcodes.r8(pc++) & 0x0f]));
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, 0);
+ break;
+
+ case 0xb8: case 0xb9: case 0xba:
+ util::stream_format(stream, "%-9s", string_format("RTD.%c", "BWL"[op & 0x03]));
+ dasm_ea(stream, pc, opcodes, 0x71 + (op & 0x03), 0, ea_mode::SIGNED, op & 0x03);
+ flags |= STEP_OUT;
+ break;
+
+ case 0xbb:
+ stream << "RTS";
+ flags |= STEP_OUT;
+ break;
+
+ case 0xbf:
+ util::stream_format(stream, "%-9s", "MOVA");
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::ADDRESS, ea_mode::DESTINATION, 2);
+ break;
+
+ case 0xd0: case 0xd1: case 0xd2:
+ util::stream_format(stream, "%-9s", string_format("LINK", "BWL"[op & 0x03]));
+ format_register(stream, 0, opcodes.r8(pc++) & 0x0f);
+ stream << ", ";
+ dasm_ea(stream, pc, opcodes, 0x71 + (op & 0x03), 0, ea_mode::SIGNED, op & 0x03);
+ break;
+
+ case 0xd3:
+ util::stream_format(stream, "%-9s", "UNLK");
+ format_register(stream, 0, opcodes.r8(pc++) & 0x0f);
+ break;
+
+ case 0xd4: case 0xd5: case 0xd6:
+ util::stream_format(stream, "%-9s", s_bf_ops[op & 0x03]);
+ format_register_to_register(stream, opcodes.r8(pc++));
+ stream << ", ";
+ if (op == 0xd5)
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::BITFIELD, ea_mode::BITFIELD, 1, 2);
+ else
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::BITFIELD, ea_mode::BITFIELD, 2, 1);
+ break;
+
+ case 0xd7:
+ util::stream_format(stream, "%-9s", "BFMOV");
+ format_register_to_register(stream, opcodes.r8(pc++));
+ stream << ", ";
+ format_register_to_register(stream, opcodes.r8(pc++));
+ stream << ", ";
+ format_register_to_register(stream, opcodes.r8(pc++));
+ break;
+
+ case 0xe0: case 0xe1:
+ util::stream_format(stream, "%-9s", string_format("MOVTP.%c", "WL"[BIT(op, 0)]));
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::UNSIGNED, ea_mode::PLAIN_MEMORY, BIT(op, 0) ? 2 : 1);
+ break;
+
+ case 0xe2: case 0xe3:
+ util::stream_format(stream, "%-9s", string_format("MOVFP.%c", "WL"[BIT(op, 0)]));
+ dasm_eas_ead(stream, pc, opcodes, ea_mode::PLAIN_MEMORY, ea_mode::DESTINATION, BIT(op, 0) ? 2 : 1);
+ break;
+
+ case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ util::stream_format(stream, "%-9s", "CGBN");
+ if (BIT(op, 1))
+ util::stream_format(stream, "#H'%02X", opcodes.r8(pc++));
+ else
+ format_register(stream, 0, opcodes.r8(pc++) & 0x0f);
+ if (BIT(op, 0))
+ {
+ stream << ", ";
+ format_register_list(stream, opcodes.r16(pc));
+ pc += 2;
+ }
+ break;
+
+ case 0xe8:
+ stream << "PGBN";
+ break;
+
+ case 0xe9:
+ util::stream_format(stream, "%-9s", "PGBN");
+ format_register_list(stream, opcodes.r16(pc));
+ pc += 2;
+ break;
+
+ case 0xea: case 0xeb:
+ util::stream_format(stream, "%-9s", string_format("SWAP.%c", "BW"[BIT(op, 0)]));
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, BIT(op, 0) + 1);
+ break;
+
+ case 0xec:
+ util::stream_format(stream, "%-9s", "TAS");
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, 0);
+ break;
+
+ case 0xee: case 0xef:
+ {
+ u8 xb = opcodes.r8(pc++);
+ if ((xb & 0xa0) == 0)
+ {
+ util::stream_format(stream, "%-9s", string_format("%sX%c.%c ", BIT(op, 0) ? "DIV" : "MUL", "SU"[BIT(xb, 6)], "BW"[BIT(xb, 4)]));
+ if (BIT(xb, 4))
+ dasm_eas_ead(stream, pc, opcodes, BIT(xb, 6) ? ea_mode::UNSIGNED : ea_mode::SIGNED, ea_mode::DESTINATION, 1, 2);
+ else
+ dasm_eas_ead(stream, pc, opcodes, BIT(xb, 6) ? ea_mode::UNSIGNED : ea_mode::SIGNED, ea_mode::DESTINATION, 0, 1);
+ }
+ else
+ stream << "{RIE}";
+ break;
+ }
+
+ case 0xf0:
+ stream << "RESET";
+ break;
+
+ case 0xf1:
+ stream << "RTE";
+ flags |= STEP_OUT;
+ break;
+
+ case 0xf2:
+ util::stream_format(stream, "%-9s#%d", "TRAPA", opcodes.r8(pc++) & 0x0f);
+ flags |= STEP_OVER;
+ break;
+
+ case 0xf3:
+ util::stream_format(stream, "TRAP/%s", s_conditions[opcodes.r8(pc++) & 0x0f]);
+ flags |= STEP_OVER;
+ break;
+
+ case 0xf4:
+ stream << "RTR";
+ flags |= STEP_OUT;
+ break;
+
+ case 0xf5:
+ stream << "SLEEP";
+ break;
+
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc:
+ {
+ u8 cr = opcodes.r8(pc++);
+ util::stream_format(stream, "%-9s", s_cr_ops[op & 0x07]);
+ if (op >= 0xfb)
+ {
+ format_cr(stream, cr);
+ stream << ", ";
+ }
+ if (op == 0xfc)
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::DESTINATION, get_cr_size(cr));
+ else
+ {
+ dasm_ea(stream, pc, opcodes, opcodes.r8(pc++) & 0x7f, 0, ea_mode::UNSIGNED, get_cr_size(cr));
+ if (op < 0xfb)
+ {
+ stream << ", ";
+ format_cr(stream, cr);
+ }
+ }
+ break;
+ }
+
+ case 0xfd:
+ stream << "ICBN";
+ break;
+
+ case 0xfe:
+ stream << "DCBN";
+ break;
+
+ case 0xff:
+ stream << "NOP";
+ break;
+
+ default:
+ stream << "{RIE}";
+ break;
+ }
+
+ return ((pc - pc0) & LENGTHMASK) | flags;
+}
diff --git a/src/devices/cpu/h16/h16dasm.h b/src/devices/cpu/h16/h16dasm.h
new file mode 100644
index 00000000000..e8a633728f8
--- /dev/null
+++ b/src/devices/cpu/h16/h16dasm.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_H16_H16DASM_H
+#define MAME_CPU_H16_H16DASM_H
+
+#pragma once
+
+class h16_disassembler : public util::disasm_interface
+{
+public:
+ // construction/destruction
+ h16_disassembler();
+
+ // disassembler overrides
+ virtual u32 opcode_alignment() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+private:
+ enum class ea_mode {
+ SIGNED,
+ UNSIGNED,
+ DESTINATION,
+ MEMORY,
+ PLAIN_MEMORY,
+ ADDRESS,
+ BITFIELD
+ };
+
+ static const char *const s_conditions[16];
+ static const char *const s_term_conditions[16];
+ static const char *const s_basic_ops[4];
+ static const char *const s_logical_ops[3];
+ static const char *const s_sft_ops[8];
+ static const char *const s_bit_ops[4];
+ static const char *const s_bf_ops[3];
+ static const char *const s_cr_ops[5];
+
+ // formatting/disassembly helpers
+ void format_register(std::ostream &stream, char bank, u8 n) const;
+ void format_register_to_register(std::ostream &stream, u8 rr) const;
+ void format_register_list(std::ostream &stream, u16 rl) const;
+ u8 get_cr_size(u8 cr) const;
+ void format_cr(std::ostream &stream, u8 cr) const;
+ void format_s8(std::ostream &stream, u8 data) const;
+ void format_s16(std::ostream &stream, u16 data) const;
+ void format_s32(std::ostream &stream, u32 data) const;
+ void dasm_displacement(std::ostream &stream, offs_t &pc, const data_buffer &opcodes, u8 sd) const;
+ void dasm_ea(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, u8 ea, char bank, ea_mode mode, u8 sz) const;
+ void dasm_eas_ead(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, ea_mode smode, ea_mode dmode, u8 sz) const;
+ void dasm_eas_ead(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, ea_mode smode, ea_mode dmode, u8 szs, u8 szd) const;
+ void dasm_branch_disp(std::ostream &stream, offs_t &pc, const h16_disassembler::data_buffer &opcodes, u8 sz) const;
+};
+
+#endif // MAME_CPU_H16_H16DASM_H
diff --git a/src/devices/cpu/h16/hd641016.cpp b/src/devices/cpu/h16/hd641016.cpp
new file mode 100644
index 00000000000..2fa5249d562
--- /dev/null
+++ b/src/devices/cpu/h16/hd641016.cpp
@@ -0,0 +1,235 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Hitachi HD641016 16-bit MPU
+
+ Currently this device is just a stub with no actual execution core.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "hd641016.h"
+#include "h16dasm.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(HD641016, hd641016_device, "hd641016", "Hitachi HD641016")
+
+hd641016_device::hd641016_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : cpu_device(mconfig, HD641016, tag, owner, clock)
+ , m_program_config("program", ENDIANNESS_BIG, 16, 24, 0)
+ , m_data_config("data", ENDIANNESS_BIG, 32, 10, 0, address_map_constructor(FUNC(hd641016_device::ram_map), this))
+ , m_io_config("I/O", ENDIANNESS_BIG, 32, 9, 0, address_map_constructor(FUNC(hd641016_device::io_map), this))
+ , m_pc(0)
+ , m_ssp(0)
+ , m_bsp(0)
+ , m_ebr(0)
+ , m_rbr(0)
+ , m_ibr(0)
+ , m_cbnr(0)
+ , m_sr(0)
+ , m_bmr(0)
+ , m_gbnr(0)
+ , m_vbnr(0)
+ , m_icount(0)
+{
+}
+
+void hd641016_device::ram_map(address_map &map)
+{
+ map(0x000, 0x3ff).ram().share("ram"); // 1K on-chip high-speed RAM
+}
+
+void hd641016_device::io_map(address_map &map)
+{
+ map.unmap_value(0);
+ //map(0x128, 0x129).rw(FUNC(hd641016_device::abr0_r), FUNC(hd641016_device::abr0_w));
+ //map(0x12a, 0x12b).rw(FUNC(hd641016_device::arr0_r), FUNC(hd641016_device::arr0_w));
+ //map(0x12c, 0x12d).rw(FUNC(hd641016_device::awcr0_r), FUNC(hd641016_device::awcr0_w));
+ //map(0x12e, 0x12f).rw(FUNC(hd641016_device::abr1_r), FUNC(hd641016_device::abr1_w));
+ //map(0x130, 0x131).rw(FUNC(hd641016_device::arr1_r), FUNC(hd641016_device::arr1_w));
+ //map(0x132, 0x133).rw(FUNC(hd641016_device::awcr1_r), FUNC(hd641016_device::awcr1_w));
+ //map(0x134, 0x135).rw(FUNC(hd641016_device::abr2_r), FUNC(hd641016_device::abr2_w));
+ //map(0x136, 0x137).rw(FUNC(hd641016_device::arr2_r), FUNC(hd641016_device::arr2_w));
+ //map(0x138, 0x139).rw(FUNC(hd641016_device::awcr2_r), FUNC(hd641016_device::awcr2_w));
+ //map(0x13a, 0x13b).rw(FUNC(hd641016_device::abr3_r), FUNC(hd641016_device::abr3_w));
+ //map(0x13c, 0x13d).rw(FUNC(hd641016_device::arr3_r), FUNC(hd641016_device::arr3_w));
+ //map(0x13e, 0x13f).rw(FUNC(hd641016_device::awcr3_r), FUNC(hd641016_device::awcr3_w));
+ //map(0x140, 0x141).rw(FUNC(hd641016_device::ipr0_r), FUNC(hd641016_device::ipr0_w));
+ //map(0x142, 0x143).rw(FUNC(hd641016_device::ipr1_r), FUNC(hd641016_device::ipr1_w));
+ //map(0x144, 0x145).rw(FUNC(hd641016_device::ipr2_r), FUNC(hd641016_device::ipr2_w));
+ //map(0x146, 0x147).rw(FUNC(hd641016_device::icr_r), FUNC(hd641016_device::icr_w));
+ //map(0x14e, 0x14f).rw(FUNC(hd641016_device::pcr0_r), FUNC(hd641016_device::pcr0_w));
+ //map(0x158, 0x158).rw(FUNC(hd641016_device::asci0_rxb_r), FUNC(hd641016_device::asci0_txb_w));
+ //map(0x159, 0x159).r(FUNC(hd641016_device::asci0_st0_r));
+ //map(0x15a, 0x15a).rw(FUNC(hd641016_device::asci0_st1_r), FUNC(hd641016_device::asci0_st1_w));
+ //map(0x15b, 0x15b).rw(FUNC(hd641016_device::asci0_st2_r), FUNC(hd641016_device::asci0_st2_w));
+ //map(0x15e, 0x15e).rw(FUNC(hd641016_device::asci0_ie0_r), FUNC(hd641016_device::asci0_ie0_w));
+ //map(0x15f, 0x15f).rw(FUNC(hd641016_device::asci0_ie1_r), FUNC(hd641016_device::asci0_ie1_w));
+ //map(0x160, 0x160).rw(FUNC(hd641016_device::asci0_ie2_r), FUNC(hd641016_device::asci0_ie2_w));
+ //map(0x162, 0x162).w(FUNC(hd641016_device::asci0_cmd_w));
+ //map(0x163, 0x163).rw(FUNC(hd641016_device::asci0_md0_r), FUNC(hd641016_device::asci0_md0_w));
+ //map(0x164, 0x164).rw(FUNC(hd641016_device::asci0_md1_r), FUNC(hd641016_device::asci0_md1_w));
+ //map(0x165, 0x165).rw(FUNC(hd641016_device::asci0_md2_r), FUNC(hd641016_device::asci0_md2_w));
+ //map(0x166, 0x166).rw(FUNC(hd641016_device::asci0_ctl_r), FUNC(hd641016_device::asci0_ctl_w));
+ //map(0x16a, 0x16a).rw(FUNC(hd641016_device::asci0_tmc_r), FUNC(hd641016_device::asci0_tmc_w));
+ //map(0x16b, 0x16b).rw(FUNC(hd641016_device::asci0_rxs_r), FUNC(hd641016_device::asci0_rxs_w));
+ //map(0x16c, 0x16c).rw(FUNC(hd641016_device::asci0_txs_r), FUNC(hd641016_device::asci0_txs_w));
+ //map(0x170, 0x170).rw(FUNC(hd641016_device::asci1_rxb_r), FUNC(hd641016_device::asci1_txb_w));
+ //map(0x171, 0x171).r(FUNC(hd641016_device::asci1_st0_r));
+ //map(0x172, 0x172).rw(FUNC(hd641016_device::asci1_st1_r), FUNC(hd641016_device::asci1_st1_w));
+ //map(0x173, 0x173).rw(FUNC(hd641016_device::asci1_st2_r), FUNC(hd641016_device::asci1_st2_w));
+ //map(0x176, 0x176).rw(FUNC(hd641016_device::asci1_ie0_r), FUNC(hd641016_device::asci1_ie0_w));
+ //map(0x177, 0x177).rw(FUNC(hd641016_device::asci1_ie1_r), FUNC(hd641016_device::asci1_ie1_w));
+ //map(0x178, 0x178).rw(FUNC(hd641016_device::asci1_ie2_r), FUNC(hd641016_device::asci1_ie2_w));
+ //map(0x17a, 0x17a).w(FUNC(hd641016_device::asci1_cmd_w));
+ //map(0x17b, 0x17b).rw(FUNC(hd641016_device::asci1_md0_r), FUNC(hd641016_device::asci1_md0_w));
+ //map(0x17c, 0x17c).rw(FUNC(hd641016_device::asci1_md1_r), FUNC(hd641016_device::asci1_md1_w));
+ //map(0x17d, 0x17d).rw(FUNC(hd641016_device::asci1_md2_r), FUNC(hd641016_device::asci1_md2_w));
+ //map(0x17e, 0x17e).rw(FUNC(hd641016_device::asci1_ctl_r), FUNC(hd641016_device::asci1_ctl_w));
+ //map(0x182, 0x182).rw(FUNC(hd641016_device::asci1_tmc_r), FUNC(hd641016_device::asci1_tmc_w));
+ //map(0x183, 0x183).rw(FUNC(hd641016_device::asci1_rxs_r), FUNC(hd641016_device::asci1_rxs_w));
+ //map(0x184, 0x184).rw(FUNC(hd641016_device::asci1_txs_r), FUNC(hd641016_device::asci1_txs_w));
+ //map(0x18e, 0x18f).rw(FUNC(hd641016_device::tmr1_ucr_r), FUNC(hd641016_device::tmr1_ucr_w));
+ //map(0x190, 0x191).rw(FUNC(hd641016_device::tmr1_ccra_r), FUNC(hd641016_device::tmr1_ccra_w));
+ //map(0x192, 0x193).rw(FUNC(hd641016_device::tmr1_ccrb_r), FUNC(hd641016_device::tmr1_ccrb_w));
+ //map(0x194, 0x195).rw(FUNC(hd641016_device::tmr1_cntr_r), FUNC(hd641016_device::tmr1_cntr_w));
+ //map(0x196, 0x197).r(FUNC(hd641016_device::tmr1_str_r));
+ //map(0x198, 0x189).rw(FUNC(hd641016_device::tmr2_ucr_r), FUNC(hd641016_device::tmr2_ucr_w));
+ //map(0x19a, 0x19b).rw(FUNC(hd641016_device::tmr2_ccra_r), FUNC(hd641016_device::tmr2_ccra_w));
+ //map(0x19c, 0x19d).rw(FUNC(hd641016_device::tmr2_ccrb_r), FUNC(hd641016_device::tmr2_ccrb_w));
+ //map(0x19e, 0x19f).rw(FUNC(hd641016_device::tmr2_cntr_r), FUNC(hd641016_device::tmr2_cntr_w));
+ //map(0x1a0, 0x1a1).r(FUNC(hd641016_device::tmr2_str_r));
+ //map(0x1b0, 0x1b3).rw(FUNC(hd641016_device::dmac0_madr_r), FUNC(hd641016_device::dmac0_madr_w));
+ //map(0x1b4, 0x1b7).rw(FUNC(hd641016_device::dmac0_dadr_r), FUNC(hd641016_device::dmac0_dadr_w));
+ //map(0x1b8, 0x1b9).rw(FUNC(hd641016_device::dmac0_etcr_r), FUNC(hd641016_device::dmac0_etcr_w));
+ //map(0x1ba, 0x1bb).rw(FUNC(hd641016_device::dmac0_btcr_r), FUNC(hd641016_device::dmac0_btcr_w));
+ //map(0x1bc, 0x1bd).rw(FUNC(hd641016_device::dmac0_chcra_r), FUNC(hd641016_device::dmac0_chcra_w));
+ //map(0x1be, 0x1bf).rw(FUNC(hd641016_device::dmac0_chcrb_r), FUNC(hd641016_device::dmac0_chcrb_w));
+ //map(0x1c0, 0x1c3).rw(FUNC(hd641016_device::dmac1_madr_r), FUNC(hd641016_device::dmac1_madr_w));
+ //map(0x1c4, 0x1c7).rw(FUNC(hd641016_device::dmac1_dadr_r), FUNC(hd641016_device::dmac1_dadr_w));
+ //map(0x1c8, 0x1c9).rw(FUNC(hd641016_device::dmac1_etcr_r), FUNC(hd641016_device::dmac1_etcr_w));
+ //map(0x1ca, 0x1cb).rw(FUNC(hd641016_device::dmac1_btcr_r), FUNC(hd641016_device::dmac1_btcr_w));
+ //map(0x1cc, 0x1cd).rw(FUNC(hd641016_device::dmac1_chcra_r), FUNC(hd641016_device::dmac1_chcra_w));
+ //map(0x1ce, 0x1cf).rw(FUNC(hd641016_device::dmac1_chcrb_r), FUNC(hd641016_device::dmac1_chcrb_w));
+ //map(0x1d0, 0x1d3).rw(FUNC(hd641016_device::dmac2_madr_r), FUNC(hd641016_device::dmac2_madr_w));
+ //map(0x1d4, 0x1d7).rw(FUNC(hd641016_device::dmac2_dadr_r), FUNC(hd641016_device::dmac2_dadr_w));
+ //map(0x1d8, 0x1d9).rw(FUNC(hd641016_device::dmac2_etcr_r), FUNC(hd641016_device::dmac2_etcr_w));
+ //map(0x1da, 0x1db).rw(FUNC(hd641016_device::dmac2_btcr_r), FUNC(hd641016_device::dmac2_btcr_w));
+ //map(0x1dc, 0x1dd).rw(FUNC(hd641016_device::dmac2_chcra_r), FUNC(hd641016_device::dmac2_chcra_w));
+ //map(0x1de, 0x1df).rw(FUNC(hd641016_device::dmac2_chcrb_r), FUNC(hd641016_device::dmac2_chcrb_w));
+ //map(0x1e0, 0x1e3).rw(FUNC(hd641016_device::dmac3_madr_r), FUNC(hd641016_device::dmac3_madr_w));
+ //map(0x1e4, 0x1e7).rw(FUNC(hd641016_device::dmac3_dadr_r), FUNC(hd641016_device::dmac3_dadr_w));
+ //map(0x1e8, 0x1e9).rw(FUNC(hd641016_device::dmac3_etcr_r), FUNC(hd641016_device::dmac3_etcr_w));
+ //map(0x1ea, 0x1eb).rw(FUNC(hd641016_device::dmac3_btcr_r), FUNC(hd641016_device::dmac3_btcr_w));
+ //map(0x1ec, 0x1ed).rw(FUNC(hd641016_device::dmac3_chcra_r), FUNC(hd641016_device::dmac3_chcra_w));
+ //map(0x1ee, 0x1ef).rw(FUNC(hd641016_device::dmac3_chcrb_r), FUNC(hd641016_device::dmac3_chcrb_w));
+ //map(0x1f0, 0x1f1).rw(FUNC(hd641016_device::dmac_opcr_r), FUNC(hd641016_device::dmac_opcr_w));
+ //map(0x1f8, 0x1f9).rw(FUNC(hd641016_device::mcr_r), FUNC(hd641016_device::mcr_w));
+}
+
+device_memory_interface::space_config_vector hd641016_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config),
+ std::make_pair(AS_DATA, &m_data_config),
+ std::make_pair(AS_IO, &m_io_config)
+ };
+}
+
+std::unique_ptr<util::disasm_interface> hd641016_device::create_disassembler()
+{
+ return std::make_unique<h16_disassembler>();
+}
+
+void hd641016_device::device_start()
+{
+ space(AS_PROGRAM).specific(m_program);
+ space(AS_PROGRAM).cache(m_cache);
+ space(AS_DATA).cache(m_data);
+ space(AS_IO).specific(m_io);
+
+ set_icountptr(m_icount);
+
+ // register state
+ state_add(H16_PC, "PC", m_pc).mask(0xffffff);
+ state_add(STATE_GENPC, "GENPC", m_pc).mask(0xffffff).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).mask(0xffffff).noshow();
+ state_add(H16_SSP, "SSP", m_ssp);
+ state_add(H16_BSP, "BSP", m_bsp);
+ state_add(H16_EBR, "EBR", m_ebr);
+ state_add(H16_RBR, "RBR", m_rbr);
+ state_add(H16_IBR, "IBR", m_ibr);
+ state_add(H16_CBNR, "CBNR", m_cbnr);
+ state_add(H16_SR, "SR", m_sr).mask(0xb71f);
+ state_add<u16>(H16_CCR, "CCR",
+ [this]() { return m_sr & 0x001f; },
+ [this](u16 data) { m_sr = (m_sr & 0xb700) | data; }
+ ).mask(0x001f).noshow();
+ state_add(STATE_GENFLAGS, "FLAGS", m_sr).mask(0xb71f).formatstr("%14s").noshow();
+ state_add(H16_BMR, "BMR", m_bmr);
+ state_add(H16_GBNR, "GBNR", m_gbnr);
+ state_add(H16_VBNR, "VBNR", m_vbnr);
+ u32 *const internal_ram = static_cast<u32 *>(memshare("ram")->ptr());
+ for (int n = 0; n < 16; n++)
+ {
+ std::string rname = n == 15 ? "USP" : string_format("R%d", n);
+ state_add<u32>(H16_R0 + n, rname.c_str(),
+ [this, n, internal_ram]() { return internal_ram[0xf0 - ((m_gbnr & global_bank_mask()) << 4) + n]; },
+ [this, n, internal_ram](u32 data) { internal_ram[0xf0 - ((m_gbnr & global_bank_mask()) << 4) + n] = data; }
+ );
+ }
+
+ // save state
+ save_item(NAME(m_pc));
+ save_item(NAME(m_ssp));
+ save_item(NAME(m_bsp));
+ save_item(NAME(m_ebr));
+ save_item(NAME(m_rbr));
+ save_item(NAME(m_ibr));
+ save_item(NAME(m_cbnr));
+ save_item(NAME(m_sr));
+ save_item(NAME(m_bmr));
+ save_item(NAME(m_gbnr));
+ save_item(NAME(m_vbnr));
+}
+
+void hd641016_device::device_reset()
+{
+ m_ebr &= 0xff000000;
+ m_rbr = 0x00fff800 | (m_rbr & 0xff0003ff);
+ m_ibr = 0x00ff0000 | (m_ibr & 0xff00ffff);
+ m_cbnr = 0x00000000;
+ m_sr = 0x2700 | (m_sr & 0x001f);
+ m_bmr = 0xa4;
+ m_gbnr &= 0xf0;
+ m_vbnr &= 0xf7;
+}
+
+void hd641016_device::execute_run()
+{
+ m_ssp = m_program.read_dword(0x000000);
+ m_pc = m_program.read_dword(0x000004);
+ debugger_instruction_hook(m_pc);
+
+ m_icount = 0;
+}
+
+void hd641016_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("%c-%c%c-<%d> %c%c%c%c%c",
+ BIT(m_sr, 15) ? 'T' : '.',
+ BIT(m_sr, 13) ? 'S' : 'U',
+ BIT(m_sr, 12) ? 'I' : '.',
+ BIT(m_sr, 8, 3),
+ BIT(m_sr, 4) ? 'X' : '.',
+ BIT(m_sr, 3) ? 'N' : '.',
+ BIT(m_sr, 2) ? 'Z' : '.',
+ BIT(m_sr, 1) ? 'V' : '.',
+ BIT(m_sr, 0) ? 'C' : '.');
+ break;
+ }
+}
diff --git a/src/devices/cpu/h16/hd641016.h b/src/devices/cpu/h16/hd641016.h
new file mode 100644
index 00000000000..1c93f5a2ff3
--- /dev/null
+++ b/src/devices/cpu/h16/hd641016.h
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/****************************************************************************
+ Vss
+ A11/D10 -----------------------+ | +---------------------- A10/D9
+ A12/D11 ---------------------+ | | | +-------------------- A9/D8
+ A13/D12 -------------------+ | | | | | +------------------ A8/D7
+ A14/D13 -----------------+ | | | | | | | +---------------- A7/D6
+ A15/D14 ---------------+ | | | | | | | | | +-------------- A6/D5
+ A16/D15 -------------+ | | | | | | | | | | | +------------ A5/D4
+ A17 -----------+ | | | | | | | | | | | | | +---------- A4/D3
+ A18 ---------+ | | | | | | | | | | | | | | | +-------- A3/D2
+ A19 -------+ | | | | | | | | | | | | | | | | | +------ A2/D1
+ A20 -----+ | | | | | | | | | | | | | | | | | | | +---- A1/D0
+ _1_1_|_|_|_|_|_|_|_|_|_8_8_8_8_8_7_7_7_7_7_
+ / 1 0 9 8 7 6 5 4 3 2 1 4 3 2 1 0 9 8 7 6 5 \
+ /--------------------------------------------|
+ A21 --| 12 * 74 |-- _IRQ1
+ A22 --| 13 73 |-- _IRQ0
+ A23 --| 14 72 |-- _NMI
+ Vss --| 15 71 |-- _BRTRY
+ _AS --| 16 70 |-- _RES
+ _WAIT --| 17 69 |-- Vss
+ Vcc --| 18 68 |-- EXTAL
+ _HDS --| 19 67 |-- (NC)
+ _LDS --| 20 66 |-- XTAL
+ R/_W --| 21 65 |-- _BREQ
+ S/_U --| 22 HD641016CP 64 |-- (NC)
+ Vss --| 23 63 |-- Vcc
+ PF --| 24 62 |-- E
+ (NC) --| 25 61 |-- ϕ
+ (NC) --| 26 60 |-- _BACK
+ TIOB2 --| 27 59 |-- _IACK
+ TIOA2 --| 28 58 |-- PCS1
+ TIOB1 --| 29 57 |-- PCS0
+ TIOA1 --| 30 56 |-- ST2
+ (NC) --| 31 55 |-- ST1
+ RXD0 --| 32 54 |-- ST0
+ |--------------------------------------------|
+ \ 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 /
+ --3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0-1-2-3-
+ TXD0 -----+ | | | | | | | | | | | | | | | | | | | +---- _DONE
+ RXC0 -------+ | | | | | | | | | | | | | | | | | +------ _DACK0
+ TXC0 ---------+ | | | | | | | | | | | | | | | +-------- _DREQ0
+ _CTS0 -----------+ | | | | | | | | | | | | | +---------- _DACK1
+ _DCD0 -------------+ | | | | | | | | | | | +------------ _DREQ1
+ _RTS0 ---------------+ | | | | | | | | | +-------------- _DACK2
+ RXD1 -----------------+ | | | | | | | +---------------- _DREQ2
+ TXD1 -------------------+ | | | | | +------------------ _RTS1/_DACK3
+ RXC1 ---------------------+ | | | +-------------------- _DCD1/_DREQ3
+ TXC1 -----------------------+ | +---------------------- Vss
+ _CTS1
+
+****************************************************************************/
+
+#ifndef MAME_CPU_H16_HD641016_H
+#define MAME_CPU_H16_HD641016_H
+
+#pragma once
+
+class hd641016_device : public cpu_device
+{
+public:
+ enum
+ {
+ H16_PC,
+ H16_SSP,
+ H16_BSP,
+ H16_EBR,
+ H16_RBR,
+ H16_IBR,
+ H16_CBNR,
+ H16_SR,
+ H16_CCR,
+ H16_BMR,
+ H16_GBNR,
+ H16_VBNR,
+ H16_R0, H16_R1, H16_R2, H16_R3, H16_R4, H16_R5, H16_R6, H16_R7,
+ H16_R8, H16_R9, H16_R10, H16_R11, H16_R12, H16_R13, H16_R14,
+ H16_USP,
+ H16_CR0, H16_CR1, H16_CR2, H16_CR3, H16_CR4, H16_CR5, H16_CR6, H16_CR7,
+ H16_CR8, H16_CR9, H16_CR10, H16_CR11, H16_CR12, H16_CR13, H16_CR14, H16_CR15,
+ H16_PR0, H16_PR1, H16_PR2, H16_PR3, H16_PR4, H16_PR5, H16_PR6, H16_PR7,
+ H16_PR8, H16_PR9, H16_PR10, H16_PR11, H16_PR12, H16_PR13, H16_PR14, H16_PR15
+ };
+
+ // device type constructor
+ hd641016_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ 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); }
+ virtual void execute_run() override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ // 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;
+
+private:
+ u8 global_bank_mask() const { return BIT(m_bmr, 4) ? 7 : (2 << (m_bmr & 3)) - 1; }
+
+ // internal maps
+ void ram_map(address_map &map);
+ void io_map(address_map &map);
+
+ // address spaces
+ address_space_config m_program_config;
+ address_space_config m_data_config;
+ address_space_config m_io_config;
+ memory_access<24, 1, 0, ENDIANNESS_BIG>::specific m_program;
+ memory_access<24, 1, 0, ENDIANNESS_BIG>::cache m_cache;
+ memory_access<10, 2, 0, ENDIANNESS_BIG>::cache m_data;
+ memory_access<9, 2, 0, ENDIANNESS_BIG>::specific m_io;
+
+ u32 m_pc;
+ u32 m_ssp;
+ u32 m_bsp;
+ u32 m_ebr;
+ u32 m_rbr;
+ u32 m_ibr;
+ u32 m_cbnr;
+ u16 m_sr;
+ u8 m_bmr;
+ u8 m_gbnr;
+ u8 m_vbnr;
+ s32 m_icount;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(HD641016, hd641016_device)
+
+#endif // MAME_CPU_H16_HD641016_H