From 040c88bf1d206cbbc47129e3e99d34ffbe4436da Mon Sep 17 00:00:00 2001 From: AJR Date: Sun, 28 Jun 2020 20:03:13 -0400 Subject: [PATCH] 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] --- scripts/src/cpu.lua | 17 + scripts/target/mame/mess.lua | 2 + src/devices/cpu/h16/h16dasm.cpp | 1052 ++++++++++++++++++++++++++++++ src/devices/cpu/h16/h16dasm.h | 55 ++ src/devices/cpu/h16/hd641016.cpp | 235 +++++++ src/devices/cpu/h16/hd641016.h | 142 ++++ src/mame/drivers/korgws.cpp | 105 +++ src/mame/mame.lst | 5 + src/mame/mess.flt | 1 + src/tools/unidasm.cpp | 2 + 10 files changed, 1616 insertions(+) create mode 100644 src/devices/cpu/h16/h16dasm.cpp create mode 100644 src/devices/cpu/h16/h16dasm.h create mode 100644 src/devices/cpu/h16/hd641016.cpp create mode 100644 src/devices/cpu/h16/hd641016.h create mode 100644 src/mame/drivers/korgws.cpp diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 0dcc83b6855..54c0bc7576a 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -592,6 +592,23 @@ if (CPUS["G65816"]~=null or _OPTIONS["with-tools"]) then table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/g65816/g65816ds.h") end +-------------------------------------------------- +-- Hitachi H16 +--@src/devices/cpu/h16/hd641016.h,CPUS["H16"] = true +-------------------------------------------------- + +if (CPUS["H16"]~=null) then + files { + MAME_DIR .. "src/devices/cpu/h16/hd641016.cpp", + MAME_DIR .. "src/devices/cpu/h16/hd641016.h", + } +end + +if (CPUS["H16"]~=null or _OPTIONS["with-tools"]) then + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/h16/h16dasm.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/h16/h16dasm.h") +end + -------------------------------------------------- -- Hitachi H8 (16/32-bit H8/300, H8/300H, H8S2000 and H8S2600 series) --@src/devices/cpu/h8/h8.h,CPUS["H8"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 95da65635ff..d525508a16c 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -71,6 +71,7 @@ CPUS["SPC700"] = true CPUS["E1"] = true CPUS["I860"] = true CPUS["I960"] = true +CPUS["H16"] = true CPUS["H8"] = true CPUS["H8500"] = true CPUS["V810"] = true @@ -2697,6 +2698,7 @@ files { MAME_DIR .. "src/mame/drivers/korgdvp1.cpp", MAME_DIR .. "src/mame/drivers/korgdw8k.cpp", MAME_DIR .. "src/mame/drivers/korgm1.cpp", + MAME_DIR .. "src/mame/drivers/korgws.cpp", MAME_DIR .. "src/mame/drivers/korgz3.cpp", MAME_DIR .. "src/mame/drivers/microkorg.cpp", MAME_DIR .. "src/mame/drivers/poly800.cpp", 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 << ""; + 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 << ""; + } + 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 << ""; + 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 << ""; + 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 << ""; + 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 << ""; + 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 << ""; + 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 << ""; + break; + } + + default: + // Not used + stream << ""; + 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 ¶ms) +{ + 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 ¶ms) 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 hd641016_device::create_disassembler() +{ + return std::make_unique(); +} + +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(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(memshare("ram")->ptr()); + for (int n = 0; n < 16; n++) + { + std::string rname = n == 15 ? "USP" : string_format("R%d", n); + state_add(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 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 diff --git a/src/mame/drivers/korgws.cpp b/src/mame/drivers/korgws.cpp new file mode 100644 index 00000000000..ba3501083a3 --- /dev/null +++ b/src/mame/drivers/korgws.cpp @@ -0,0 +1,105 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/**************************************************************************** + + Skeleton driver for Korg WaveStation vector synthesizer. + +****************************************************************************/ + +#include "emu.h" +#include "cpu/h16/hd641016.h" +#include "cpu/m6502/m3745x.h" +//#include "video/t6963c.h" + +class korgws_state : public driver_device +{ +public: + korgws_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_ksp(*this, "ksp") + { + } + + void korgws(machine_config &config); + void korgwssr(machine_config &config); + +private: + void h16_map(address_map &map); + void wssr_map(address_map &map); + + required_device m_maincpu; + required_device m_ksp; +}; + + +void korgws_state::h16_map(address_map &map) +{ + map(0x000000, 0x000007).rom().region("sysroms", 0); // reset vectors + map(0xc00000, 0xc3ffff).rom().region("sysroms", 0); +} + +void korgws_state::wssr_map(address_map &map) +{ + map(0x000000, 0x000007).rom().region("sysroms", 0); // reset vectors + map(0xc00000, 0xc7ffff).rom().region("sysroms", 0); +} + + +static INPUT_PORTS_START(korgws) +INPUT_PORTS_END + +void korgws_state::korgws(machine_config &config) +{ + HD641016(config, m_maincpu, 20_MHz_XTAL); // HD641016CP10 + m_maincpu->set_addrmap(AS_PROGRAM, &korgws_state::h16_map); + + M37450(config, m_ksp, 20_MHz_XTAL / 2).set_disable(); // M37450M4-233FP +} + +void korgws_state::korgwssr(machine_config &config) +{ + korgws(config); + m_maincpu->set_addrmap(AS_PROGRAM, &korgws_state::wssr_map); +} + +ROM_START(korgwsex) + ROM_REGION16_BE(0x40000, "sysroms", 0) // original EPROM type is NEC D27C1000A-12 + ROM_LOAD16_BYTE("wsex_319_u18.bin", 0x00000, 0x20000, CRC(623eba63) SHA1(5c5e0842d74a9fefbdea01817325a3349f6f9dd6)) + ROM_LOAD16_BYTE("wsex_319_u19.bin", 0x00001, 0x20000, CRC(c7b00f02) SHA1(196e4e403cbae728ec21d27d7b5762963e559028)) + + ROM_REGION(0x2000, "ksp", 0) + ROM_LOAD("m37450m4-233fp.ic34", 0x0000, 0x2000, NO_DUMP) + + ROM_REGION(0x200000, "exroms", 0) + ROM_LOAD("ws3p7.bin", 0x000000, 0x80000, CRC(ac2e21e3) SHA1(57cd4701a5ca91a74536d7f7ead4074cfe605607)) + ROM_LOAD("ws3p8.bin", 0x080000, 0x80000, CRC(7480bacf) SHA1(8d6e61c11ba909767413df2cae09259e6d8b1476)) + ROM_LOAD16_BYTE("ws3p9.bin", 0x100000, 0x80000, CRC(80a23b7b) SHA1(10b1831b1c2d5d63dd9f4e74cfcfb73c2862f59e)) + ROM_LOAD16_BYTE("ws4p0.bin", 0x100001, 0x80000, CRC(adf239cf) SHA1(a2236f1b0f63c3f854f8ec8751aeb9e167ea0f47)) +ROM_END + +ROM_START(korgwsad) + ROM_REGION16_BE(0x40000, "sysroms", 0) + ROM_SYSTEM_BIOS(0, "v125", "v1.25 Firmware") + ROMX_LOAD("wsad_1p25_910205l.ic41", 0x00000, 0x20000, CRC(22e5631e) SHA1(ea51e2f2e9effc3985d547d60b109c40e93d4d33), ROM_BIOS(0) | ROM_SKIP(1)) // 27C1000-15 + ROMX_LOAD("wsad_1p25_910305r.ic40", 0x00001, 0x20000, CRC(6a201cbe) SHA1(ee4194baec787d112795b2f34fb21d752c592179), ROM_BIOS(0) | ROM_SKIP(1)) // MBM27C1000-15z + ROM_SYSTEM_BIOS(1, "v118", "v1.18 Firmware") + ROMX_LOAD("wsad_118_ic204", 0x00000, 0x20000, CRC(ee3fd19e) SHA1(726c7c3cc201d3360d6274118c13871f8aa46fbd), ROM_BIOS(1) | ROM_SKIP(1)) + ROMX_LOAD("wsad_118_ic304", 0x00001, 0x20000, CRC(4ad559a6) SHA1(f0db05586e7c7be0ce93edd1e07e83d27b69b661), ROM_BIOS(1) | ROM_SKIP(1)) + + ROM_REGION(0x2000, "ksp", 0) + ROM_LOAD("m37450m4-233fp.bin", 0x0000, 0x2000, NO_DUMP) +ROM_END + +ROM_START(korgwssr) + ROM_REGION16_BE(0x80000, "sysroms", 0) + ROM_LOAD16_BYTE("920305.ic22", 0x00000, 0x40000, CRC(8307a5da) SHA1(31ce491afb74ac1dfa20ae7320b8d1370fa93698)) + ROM_LOAD16_BYTE("920405.ic23", 0x00001, 0x40000, CRC(2d367253) SHA1(c0f8a104a036dd39d220491cc15713158ab3d62a)) + + ROM_REGION(0x2000, "ksp", 0) + ROM_LOAD("m37450m4-233fp.bin", 0x0000, 0x2000, NO_DUMP) +ROM_END + +SYST(1992, korgwsex, 0, 0, korgws, korgws, korgws_state, empty_init, "Korg", "WaveStation EX", MACHINE_IS_SKELETON) +SYST(1991, korgwsad, 0, 0, korgws, korgws, korgws_state, empty_init, "Korg", "WaveStation A/D", MACHINE_IS_SKELETON) +SYST(1992, korgwssr, 0, 0, korgwssr, korgws, korgws_state, empty_init, "Korg", "WaveStation SR", MACHINE_IS_SKELETON) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 316b4f83ad4..da64ecdd346 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -18938,6 +18938,11 @@ korgm1p1 // korgm1r // korgm1rex // +@source:korgws.cpp +korgwsad // +korgwsex // +korgwssr // + @source:korgz3.cpp korgz3 // diff --git a/src/mame/mess.flt b/src/mame/mess.flt index d2aed24a320..3e624ecbc95 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -473,6 +473,7 @@ korgdss1.cpp korgdvp1.cpp korgdw8k.cpp korgm1.cpp +korgws.cpp korgz3.cpp kramermc.cpp krokha.cpp diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 24cb92f7b7e..1c6c9b1a160 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -57,6 +57,7 @@ using util::BIT; #include "cpu/h8/h8hd.h" #include "cpu/h8/h8s2000d.h" #include "cpu/h8/h8s2600d.h" +#include "cpu/h16/h16dasm.h" #include "cpu/h8500/h8500dasm.h" #include "cpu/hcd62121/hcd62121d.h" #include "cpu/hd61700/hd61700d.h" @@ -399,6 +400,7 @@ static const dasm_table_entry dasm_table[] = { "h8s2000", be, 0, []() -> util::disasm_interface * { return new h8s2000_disassembler; } }, { "h8s2600", be, 0, []() -> util::disasm_interface * { return new h8s2600_disassembler; } }, { "h8500", be, 0, []() -> util::disasm_interface * { return new h8500_disassembler; } }, + { "h16", be, 0, []() -> util::disasm_interface * { return new h16_disassembler; } }, { "hc11", be, 0, []() -> util::disasm_interface * { return new hc11_disassembler; } }, { "hcd62121", le, 0, []() -> util::disasm_interface * { return new hcd62121_disassembler; } }, { "hd61700", le, -1, []() -> util::disasm_interface * { return new hd61700_disassembler; } },