summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/cpu.lua17
-rw-r--r--scripts/target/mame/arcade.lua1
-rw-r--r--scripts/target/mame/mess.lua3
-rw-r--r--src/devices/cpu/cr16b/cr16b.cpp107
-rw-r--r--src/devices/cpu/cr16b/cr16b.h63
-rw-r--r--src/devices/cpu/cr16b/cr16bdasm.cpp1051
-rw-r--r--src/devices/cpu/cr16b/cr16bdasm.h66
-rw-r--r--src/mame/drivers/glcx.cpp (renamed from src/mame/drivers/vtech_unk1.cpp)36
-rw-r--r--src/mame/mame.lst10
-rw-r--r--src/mame/mess.flt2
-rw-r--r--src/tools/unidasm.cpp3
11 files changed, 1339 insertions, 20 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index c77f74ff90f..f49d8e48927 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -2933,3 +2933,20 @@ if (CPUS["F2MC16"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16dasm.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16dasm.h")
end
+
+--------------------------------------------------
+-- National Semiconductor CR16B
+--@src/devices/cpu/cr16b/cr16bdasm.h,CPUS["CR16B"] = true
+--------------------------------------------------
+
+if (CPUS["CR16B"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/cpu/cr16b/cr16b.cpp",
+ MAME_DIR .. "src/devices/cpu/cr16b/cr16b.h",
+ }
+end
+
+if (CPUS["CR16B"]~=null or _OPTIONS["with-tools"]) then
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/cr16b/cr16bdasm.cpp")
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/cr16b/cr16bdasm.h")
+end
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 336ddf2e91e..ee57494f9f4 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -136,6 +136,7 @@ CPUS["DSPP"] = true
CPUS["HPC"] = true
--CPUS["RII"] = true
--CPUS["BCP"] = true
+--CPUS["CR16B"] = true
--------------------------------------------------
-- specify available sound cores
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index f9415ed552f..b0c13015da0 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -145,6 +145,7 @@ CPUS["DSPV"] = true
CPUS["RII"] = true
CPUS["BCP"] = true
CPUS["F2MC16"] = true
+CPUS["CR16B"] = true
--------------------------------------------------
-- specify available sound cores; some of these are
@@ -3730,7 +3731,7 @@ files {
MAME_DIR .. "src/mame/drivers/gamemachine.cpp",
MAME_DIR .. "src/mame/drivers/geniusiq.cpp",
MAME_DIR .. "src/mame/drivers/geniusjr.cpp",
- MAME_DIR .. "src/mame/drivers/vtech_unk1.cpp",
+ MAME_DIR .. "src/mame/drivers/glcx.cpp",
MAME_DIR .. "src/mame/drivers/vtech_unk2.cpp",
MAME_DIR .. "src/mame/drivers/vtech_eu3a12.cpp",
MAME_DIR .. "src/mame/drivers/iqunlim.cpp",
diff --git a/src/devices/cpu/cr16b/cr16b.cpp b/src/devices/cpu/cr16b/cr16b.cpp
new file mode 100644
index 00000000000..e3f330bf3f7
--- /dev/null
+++ b/src/devices/cpu/cr16b/cr16b.cpp
@@ -0,0 +1,107 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ National Semiconductor CompactRISC CR16B
+
+ Currently this device is just a stub with no actual execution core.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cr16b.h"
+#include "cr16bdasm.h"
+
+// device type definitions
+DEFINE_DEVICE_TYPE(CR16B, cr16b_device, "cr16b", "CompactRISC CR16B")
+
+cr16b_device::cr16b_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor map)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_space_config("program", ENDIANNESS_LITTLE, 16, 21, 0, map)
+ , m_space(nullptr)
+ , m_cache(nullptr)
+ , m_regs{0}
+ , m_pc(0)
+ , m_isp(0)
+ , m_intbase(0)
+ , m_psr(0)
+ , m_cfg(0)
+ , m_dcr(0)
+ , m_dsr(0)
+ , m_car(0)
+ , m_icount(0)
+{
+}
+
+// TODO: figure out some actual device types instead
+cr16b_device::cr16b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : cr16b_device(mconfig, CR16B, tag, owner, clock, address_map_constructor())
+{
+}
+
+std::unique_ptr<util::disasm_interface> cr16b_device::create_disassembler()
+{
+ return std::make_unique<cr16b_disassembler>();
+}
+
+device_memory_interface::space_config_vector cr16b_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_space_config),
+ };
+}
+
+void cr16b_device::device_start()
+{
+ m_space = &space(AS_PROGRAM);
+ m_cache = m_space->cache<1, 0, ENDIANNESS_LITTLE>();
+
+ set_icountptr(m_icount);
+
+ state_add(CR16_PC, "PC", m_pc).mask(0x1ffffe);
+ state_add(STATE_GENPC, "GENPC", m_pc).callimport().noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).callimport().noshow();
+ state_add(CR16_ISP, "ISP", m_isp).mask(0x00ffff).formatstr("%06X");
+ state_add(CR16_INTBASE, "INTBASE", m_intbase).mask(0x1ffffe);
+ state_add(CR16_PSR, "PSR", m_psr).mask(0x0ee7).formatstr("%04X");
+ for (int i = 0; i < 13; i++)
+ state_add(CR16_R0 + i, string_format("R%d", i).c_str(), m_regs[i]);
+ state_add(CR16_R13, "ERA", m_regs[13]);
+ state_add(CR16_R14, "RA", m_regs[14]);
+ state_add(CR16_R15, "SP", m_regs[15]);
+
+ save_item(NAME(m_regs));
+ save_item(NAME(m_pc));
+ save_item(NAME(m_isp));
+ save_item(NAME(m_intbase));
+ save_item(NAME(m_psr));
+ save_item(NAME(m_cfg));
+ save_item(NAME(m_dcr));
+ save_item(NAME(m_dsr));
+ save_item(NAME(m_car));
+}
+
+void cr16b_device::device_reset()
+{
+ // Save old values of PC and PSR in R0 and R1
+ m_regs[0] = (m_pc & 0x01fffe) >> 1;
+ m_regs[1] = (m_pc & 0x1e0000) >> 5 | (m_psr & 0x0fff);
+
+ // Reset internal registers
+ m_pc = 0;
+ m_cfg = 0;
+ m_dcr = 0;
+ m_psr = 0x0200; // PSR.E = 1
+}
+
+void cr16b_device::execute_run()
+{
+ debugger_instruction_hook(m_pc);
+
+ m_icount = 0;
+}
+
+void cr16b_device::execute_set_input(int inputnum, int state)
+{
+ // TODO
+}
diff --git a/src/devices/cpu/cr16b/cr16b.h b/src/devices/cpu/cr16b/cr16b.h
new file mode 100644
index 00000000000..9dbca95f4f4
--- /dev/null
+++ b/src/devices/cpu/cr16b/cr16b.h
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_CR16B_CR16B_H
+#define MAME_CPU_CR16B_CR16B_H 1
+
+#pragma once
+
+
+class cr16b_device : public cpu_device
+{
+public:
+ cr16b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ enum {
+ CR16_PC, CR16_ISP, CR16_INTBASE,
+ CR16_PSR, CR16_CFG, CR16_DCR, CR16_DSR, CR16_CAR,
+ CR16_R0, CR16_R1, CR16_R2, CR16_R3,
+ CR16_R4, CR16_R5, CR16_R6, CR16_R7,
+ CR16_R8, CR16_R9, CR16_R10, CR16_R11,
+ CR16_R12, CR16_R13, CR16_R14, CR16_R15
+ };
+
+protected:
+ // construction/destruction
+ cr16b_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor map);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) 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;
+
+private:
+ // address space
+ address_space_config m_space_config;
+ address_space *m_space;
+ memory_access_cache<1, 0, ENDIANNESS_LITTLE> *m_cache;
+
+ // internal state
+ u16 m_regs[16];
+ u32 m_pc;
+ u32 m_isp;
+ u32 m_intbase;
+ u16 m_psr;
+ u16 m_cfg;
+ u16 m_dcr;
+ u16 m_dsr;
+ u32 m_car;
+ s32 m_icount;
+};
+
+DECLARE_DEVICE_TYPE(CR16B, cr16b_device)
+
+#endif // MAME_CPU_CR16B_CR16B_H
diff --git a/src/devices/cpu/cr16b/cr16bdasm.cpp b/src/devices/cpu/cr16b/cr16bdasm.cpp
new file mode 100644
index 00000000000..e52ab7e02f2
--- /dev/null
+++ b/src/devices/cpu/cr16b/cr16bdasm.cpp
@@ -0,0 +1,1051 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ National Semiconductor CompactRISC CR16B disassembler
+
+ Core architecture versions supported by this disassembler:
+ * CR16A: 17-bit PC
+ * CR16B: 21-bit PC using large memory model, enhanced instruction set
+
+ CR16C has a 24-bit PC and expands the instruction set still further.
+ Its instruction encoding is entirely different and is therefore not
+ supported here.
+
+ It should be noted that the PC is guaranteed to be always aligned to
+ even addresses. To this end, whenever the PC is stored in or loaded
+ from a register or register pair or a stack, the bits are shifted
+ right or left by one.
+
+***************************************************************************/
+
+#include "util/disasmintf.h"
+#include "cr16bdasm.h"
+
+#include "util/strformat.h"
+
+using osd::u32;
+using util::BIT;
+using offs_t = u32;
+
+cr16b_disassembler::cr16b_disassembler(cr16_arch arch)
+ : util::disasm_interface()
+ , m_arch(arch)
+{
+}
+
+cr16a_disassembler::cr16a_disassembler()
+ : cr16b_disassembler(cr16_arch::CR16A)
+{
+}
+
+cr16b_disassembler::cr16b_disassembler()
+ : cr16b_disassembler(cr16_arch::CR16B)
+{
+}
+
+u32 cr16b_disassembler::opcode_alignment() const
+{
+ return 2;
+}
+
+// Condition codes
+const char *const cr16b_disassembler::s_cc[14] =
+{
+ "eq", "ne",
+ "cs", "cc",
+ "hi", "ls",
+ "gt", "le",
+ "fs", "fc",
+ "lo", "hs",
+ "lt", "ge"
+};
+
+
+void cr16b_disassembler::format_reg(std::ostream &stream, u8 reg)
+{
+ if (reg == 15)
+ stream << "sp";
+ else if (reg == 14)
+ stream << "ra";
+ else if (reg == 13 && m_arch != cr16_arch::CR16A)
+ stream << "era"; // R13 in SMM
+ else
+ util::stream_format(stream, "r%d", reg);
+}
+
+void cr16b_disassembler::format_rpair(std::ostream &stream, u8 reg)
+{
+ if (reg == 13 && m_arch != cr16_arch::CR16A)
+ stream << "(ra,era)";
+ else
+ util::stream_format(stream, "(r%d,r%d)", reg + 1, reg);
+}
+
+void cr16a_disassembler::format_rproc(std::ostream &stream, u8 reg)
+{
+ switch (reg)
+ {
+ case 1:
+ stream << "psr";
+ break;
+
+ case 3:
+ stream << "intbase";
+ break;
+
+ case 11:
+ stream << "isp";
+ break;
+
+ default:
+ stream << "res";
+ break;
+ }
+}
+
+void cr16b_disassembler::format_rproc(std::ostream &stream, u8 reg)
+{
+ switch (reg)
+ {
+ case 1:
+ stream << "psr";
+ break;
+
+ case 3:
+ stream << "intbasel";
+ break;
+
+ case 4:
+ stream << "intbaseh";
+ break;
+
+ case 5:
+ stream << "cfg";
+ break;
+
+ case 7:
+ stream << "dsr";
+ break;
+
+ case 9:
+ stream << "dcr";
+ break;
+
+ case 11:
+ stream << "isp";
+ break;
+
+ case 13:
+ stream << "carl";
+ break;
+
+ case 14:
+ stream << "carh";
+ break;
+
+ default:
+ stream << "res";
+ break;
+ }
+}
+
+void cr16b_disassembler::format_short_imm(std::ostream &stream, u8 imm)
+{
+ // 5-bit short immediate value (0 to 15, -16, -14 to -1)
+ if (imm == 0)
+ stream << "$0";
+ else if (imm >= 0x10)
+ util::stream_format(stream, "$-0x%01X", 0x10 - (imm & 0x0f));
+ else
+ util::stream_format(stream, "$0x%01X", imm);
+}
+
+void cr16b_disassembler::format_short_imm_unsigned(std::ostream &stream, u8 imm, bool i)
+{
+ if (imm == 0)
+ stream << "$0";
+ else if (i)
+ util::stream_format(stream, "$0x%04X", (imm >= 0x10) ? 0xfff0 | (imm & 0x0f) : imm);
+ else
+ util::stream_format(stream, "$0x%02X", (imm >= 0x10) ? 0xf0 | (imm & 0x0f) : imm);
+}
+
+void cr16b_disassembler::format_short_imm_decimal(std::ostream &stream, u8 imm)
+{
+ if (imm >= 0x10)
+ util::stream_format(stream, "$-%d", 0x10 - (imm & 0x0f));
+ else
+ util::stream_format(stream, "$%d", imm);
+}
+
+void cr16b_disassembler::format_medium_imm(std::ostream &stream, u16 imm, bool i)
+{
+ if (i)
+ util::stream_format(stream, "$0x%04X", imm);
+ else
+ util::stream_format(stream, "$0x%02X", imm & 0xff);
+}
+
+void cr16b_disassembler::format_medium_imm_decimal(std::ostream &stream, u16 imm)
+{
+ util::stream_format(stream, "$%d", s16(imm));
+}
+
+void cr16b_disassembler::format_imm21(std::ostream &stream, u32 imm)
+{
+ util::stream_format(stream, "$0x%06X", imm);
+}
+
+void cr16b_disassembler::format_disp5(std::ostream &stream, u8 disp)
+{
+ // 5-bit short displacement (0 to 15, 16 to 30 even)
+ if (disp == 0)
+ stream << "0";
+ else
+ util::stream_format(stream, "0x%X", disp);
+}
+
+void cr16b_disassembler::format_disp16(std::ostream &stream, u16 disp)
+{
+ // 16-bit displacement (0 to 64K-1)
+ util::stream_format(stream, "0x%X", disp);
+}
+
+void cr16b_disassembler::format_disp18(std::ostream &stream, u32 disp)
+{
+ // 18-bit medium displacement (-128K to 128K-1 or 0 to 256K-1, result truncated to 18 bits)
+ if (disp == 0)
+ stream << "0";
+ else if (disp >= 0x20000)
+ util::stream_format(stream, "-0x%X", 0x40000 - disp);
+ else
+ util::stream_format(stream, "0x%X", disp);
+}
+
+void cr16b_disassembler::format_abs18(std::ostream &stream, u32 addr)
+{
+ // 18-bit absolute (any memory location within first 256K)
+ util::stream_format(stream, "0x%05X", addr);
+}
+
+void cr16b_disassembler::format_pc_disp5(std::ostream &stream, offs_t pc, u8 disp)
+{
+ if (m_arch == cr16_arch::CR16A)
+ util::stream_format(stream, "0x%05X", (disp >= 0x10 ? pc + 0x20 - disp : pc + disp) & 0x1ffff); // SMM
+ else
+ util::stream_format(stream, "0x%06X", (disp >= 0x10 ? pc + 0x20 - disp : pc + disp) & 0x1fffff); // LMM
+}
+
+void cr16b_disassembler::format_pc_disp9(std::ostream &stream, offs_t pc, u16 disp)
+{
+ if (m_arch == cr16_arch::CR16A)
+ util::stream_format(stream, "0x%05X", (disp >= 0x100 ? pc + 0x200 - disp : pc + disp) & 0x1ffff); // SMM
+ else
+ util::stream_format(stream, "0x%06X", (disp >= 0x100 ? pc + 0x200 - disp : pc + disp) & 0x1fffff); // LMM
+}
+
+void cr16b_disassembler::format_pc_disp17(std::ostream &stream, offs_t pc, u32 disp)
+{
+ util::stream_format(stream, "0x%05X", (disp >= 0x10000 ? pc + 0x20000 - disp : pc + disp) & 0x1ffff);
+}
+
+void cr16b_disassembler::format_pc_disp21(std::ostream &stream, offs_t pc, u32 disp)
+{
+ util::stream_format(stream, "0x%06X", (pc + ((disp & 0x0ffffe) | (disp & 0x000001) << 20)) & 0x1fffff);
+}
+
+void cr16b_disassembler::format_excp_vector(std::ostream &stream, u8 vec)
+{
+ switch (vec)
+ {
+ case 0x05: // Supervisor call
+ stream << "svc";
+ break;
+
+ case 0x06: // Division by zero
+ stream << "dvz";
+ break;
+
+ case 0x07: // Flag
+ stream << "flg";
+ break;
+
+ case 0x08: // Breakpoint
+ stream << "bpt";
+ break;
+
+ case 0x0a: // Undefined instruction
+ stream << "und";
+ break;
+
+ case 0x0e: // Debug
+ stream << (m_arch != cr16_arch::CR16A ? "dbg" : "und ; reserved");
+ break;
+
+ default:
+ stream << "und ; reserved";
+ break;
+ }
+}
+
+offs_t cr16b_disassembler::disassemble(std::ostream &stream, offs_t pc, const cr16b_disassembler::data_buffer &opcodes, const cr16b_disassembler::data_buffer &params)
+{
+ u16 opcode = opcodes.r16(pc);
+
+ if (BIT(opcode, 15))
+ {
+ // Load and store group (excluding LOADM, STORM)
+ if (BIT(opcode, 14))
+ {
+ util::stream_format(stream, "stor%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ stream << ", ";
+ }
+ else
+ util::stream_format(stream, "load%c ", BIT(opcode, 13) ? 'w' : 'b');
+
+ switch (opcode & 0x1801)
+ {
+ case 0x1001:
+ format_disp18(stream, u32(opcode & 0x0600) << 7 | opcodes.r16(pc + 2));
+ stream << "(";
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ")";
+ if (!BIT(opcode, 14))
+ {
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ }
+ return 4 | SUPPORTED;
+
+ case 0x1801:
+ if ((opcode & 0x001e) == 0x001e)
+ format_abs18(stream, u32(opcode & 0x0600) << 7 | opcodes.r16(pc + 2));
+ else
+ {
+ format_disp18(stream, u32(opcode & 0x0600) << 7 | opcodes.r16(pc + 2));
+ format_rpair(stream, (opcode & 0x001e) >> 1);
+ }
+ if (!BIT(opcode, 14))
+ {
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ }
+ return 4 | SUPPORTED;
+
+ default:
+ format_disp5(stream, (opcode & 0x1e00) >> 8 | (opcode & 0x0001));
+ stream << "(";
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ")";
+ if (!BIT(opcode, 14))
+ {
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ }
+ return 2 | SUPPORTED;
+ }
+ }
+ else switch (opcode & 0x7e01)
+ {
+ case 0x0000: case 0x0001: case 0x2000: case 0x2001:
+ util::stream_format(stream, "add%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x0200: case 0x0201: case 0x2200: case 0x2201:
+ if (opcode == 0x0200) // NOP = ADDU $0, R0
+ stream << "nop";
+ else
+ {
+ util::stream_format(stream, "addu%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+ }
+ return 2 | SUPPORTED;
+
+ case 0x0400: case 0x0401: case 0x2400: case 0x2401:
+ case 0x4401: case 0x6401:
+ // Bit manipulation and store immediate (memory operand)
+ if (m_arch == cr16_arch::CR16A)
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+ switch (opcode & 0x00c0)
+ {
+ case 0x0000:
+ util::stream_format(stream, "cbit%c $%d", BIT(opcode, 13) ? 'w' : 'b', (opcode & 0x001e) >> 1);
+ break;
+
+ case 0x0040:
+ util::stream_format(stream, "sbit%c $%d", BIT(opcode, 13) ? 'w' : 'b', (opcode & 0x001e) >> 1);
+ break;
+
+ case 0x0080:
+ util::stream_format(stream, "tbit%c $%d", BIT(opcode, 13) ? 'w' : 'b', (opcode & 0x001e) >> 1);
+ break;
+
+ case 0x00c0:
+ util::stream_format(stream, "stor%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_short_imm(stream, (opcode & 0x001e) >> 1); // unsigned 4-bit value
+ break;
+ }
+ if (BIT(opcode, 14))
+ {
+ stream << ",0(";
+ format_reg(stream, (opcode & 0x0120) >> 5);
+ stream << ")";
+ return 2 | SUPPORTED;
+ }
+ else
+ {
+ stream << ", ";
+ if (BIT(opcode, 0))
+ {
+ format_disp16(stream, opcodes.r16(pc + 2));
+ stream << "(";
+ format_reg(stream, (opcode & 0x0120) >> 5);
+ stream << ")";
+ }
+ else
+ format_abs18(stream, u32(opcode & 0x0100) << 9 | u32(opcode & 0x0020) << 11 | opcodes.r16(pc + 2));
+ return 4 | SUPPORTED;
+ }
+
+ case 0x0600: case 0x0601: case 0x2600: case 0x2601:
+ util::stream_format(stream, "mul%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x0800: case 0x0801: case 0x2800: case 0x2801:
+ util::stream_format(stream, "ashu%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm_decimal(stream, opcodes.r16(pc + 2));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm_decimal(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x0a00: case 0x0a01: case 0x2a00: case 0x2a01:
+ util::stream_format(stream, "lsh%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm_decimal(stream, opcodes.r16(pc + 2));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm_decimal(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x0c00: case 0x0c01: case 0x2c00: case 0x2c01:
+ util::stream_format(stream, "xor%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm_unsigned(stream, opcode & 0x001f, BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x0e00: case 0x0e01: case 0x2e00: case 0x2e01:
+ util::stream_format(stream, "cmp%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x1000: case 0x1001: case 0x3000: case 0x3001:
+ util::stream_format(stream, "and%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm_unsigned(stream, opcode & 0x001f, BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x1200: case 0x1201: case 0x3200: case 0x3201:
+ util::stream_format(stream, "addc%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x1400:
+ // Conditional or unconditional branch to small address
+ if ((opcode & 0x000e) == 0x000e || (opcode & 0x01e0) != 0x01e0)
+ {
+ if ((opcode & 0x01e0) == 0x01c0)
+ stream << "br ";
+ else
+ util::stream_format(stream, "b%s ", s_cc[(opcode & 0x01e0) >> 5]);
+ format_pc_disp17(stream, pc, u32(opcode & 0x0010) << 12 | opcodes.r16(pc + 2));
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+
+ case 0x1401: case 0x3401:
+ // Compare and branch group
+ if (m_arch == cr16_arch::CR16A)
+ stream << "res";
+ else
+ {
+ util::stream_format(stream, "b%s%c%c ", BIT(opcode, 7) ? "ne" : "eq", BIT(opcode, 6) ? '1' : '0', BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x0120) >> 5);
+ stream << ", ";
+ format_pc_disp5(stream, pc, opcode & 0x001e);
+ }
+ return 2 | SUPPORTED;
+
+ case 0x1600:
+ // Jump and link to large address
+ if (m_arch == cr16_arch::CR16A)
+ stream << "res";
+ else
+ {
+ stream << "jal ";
+ format_rpair(stream, (opcode & 0x01e0) >> 5);
+ stream << ", ";
+ format_rpair(stream, (opcode & 0x001e) >> 1);
+ }
+ return 2 | SUPPORTED;
+
+ case 0x1601:
+ if ((opcode & 0x01e0) != 0x01e0 && m_arch != cr16_arch::CR16A)
+ {
+ if ((opcode & 0x01e0) == 0x01c0)
+ stream << "jump ";
+ else
+ util::stream_format(stream, "j%s ", s_cc[(opcode & 0x01e0) >> 5]);
+ format_rpair(stream, (opcode & 0x001e) >> 1);
+ return 2 | (opcode == 0x17db ? STEP_OUT : 0) | SUPPORTED;
+ }
+ else
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+
+ case 0x1800: case 0x1801: case 0x3800: case 0x3801:
+ util::stream_format(stream, "mov%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm_unsigned(stream, opcode & 0x001f, BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x1a00: case 0x1a01: case 0x3a00: case 0x3a01:
+ util::stream_format(stream, "subc%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x1c00: case 0x1c01: case 0x3c00: case 0x3c01:
+ util::stream_format(stream, "or%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm_unsigned(stream, opcode & 0x001f, BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x1e00: case 0x1e01: case 0x3e00: case 0x3e01:
+ util::stream_format(stream, "sub%c ", BIT(opcode, 13) ? 'w' : 'b');
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm(stream, opcodes.r16(pc + 2), BIT(opcode, 13));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x3400:
+ // Branch and link to small address
+ if ((opcode & 0x000e) == 0x000e)
+ {
+ stream << "bal ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ stream << ", ";
+ format_pc_disp17(stream, pc, u32(opcode & 0x0010) << 12 | opcodes.r16(pc + 2));
+ return 4 | STEP_OVER | SUPPORTED;
+ }
+ else
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+
+ case 0x3600: case 0x3601:
+ // TBIT imm, reg only exists as a word operation
+ stream << "tbit ";
+ if ((opcode & 0x001f) == 0x0011)
+ {
+ format_medium_imm_decimal(stream, opcodes.r16(pc + 2));
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_short_imm_decimal(stream, opcode & 0x001f);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x4000: case 0x4200: case 0x4400: case 0x4600:
+ case 0x4800: case 0x4a00: case 0x4c00: case 0x4e00:
+ case 0x5000: case 0x5200: case 0x5400: case 0x5600:
+ case 0x5800: case 0x5a00: case 0x5c00: case 0x5e00:
+ // Conditional or unconditional branch with 9-bit displacement
+ if ((opcode & 0x01e0) != 0x01e0)
+ {
+ if ((opcode & 0x01e0) == 0x01c0)
+ stream << "br ";
+ else
+ util::stream_format(stream, "b%s ", s_cc[(opcode & 0x01e0) >> 5]);
+ format_pc_disp9(stream, pc, (opcode & 0x1e00) >> 4 | (opcode & 0x001e));
+ }
+ else
+ stream << "res";
+ return 2 | SUPPORTED;
+
+ case 0x4001: case 0x6001:
+ util::stream_format(stream, "add%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x4201: case 0x6201:
+ util::stream_format(stream, "addu%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x4601: case 0x6601:
+ util::stream_format(stream, "mul%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x4801: case 0x6801:
+ util::stream_format(stream, "ashu%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x4a01: case 0x6a01:
+ util::stream_format(stream, "lsh%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x4c01: case 0x6c01:
+ util::stream_format(stream, "xor%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x4e01: case 0x6e01:
+ util::stream_format(stream, "cmp%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x5001: case 0x7001:
+ util::stream_format(stream, "and%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x5201: case 0x7201:
+ util::stream_format(stream, "addc%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x5401:
+ if ((opcode & 0x01e0) != 0x01e0)
+ {
+ if ((opcode & 0x01e0) == 0x01c0)
+ stream << "jump ";
+ else
+ util::stream_format(stream, "j%s ", s_cc[(opcode & 0x01e0) >> 5]);
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ return 2 | (opcode == 0x55dd ? STEP_OUT : 0) | SUPPORTED;
+ }
+ else
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+
+ case 0x5801: case 0x7801:
+ util::stream_format(stream, "mov%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x5a01: case 0x7a01:
+ util::stream_format(stream, "subc%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x5c01: case 0x7c01:
+ util::stream_format(stream, "or%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x5e01: case 0x7e01:
+ util::stream_format(stream, "sub%c ", BIT(opcode, 13) ? 'w' : 'b');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x6000:
+ if (m_arch == cr16_arch::CR16A)
+ stream << "res";
+ else
+ {
+ stream << "mulsb ";
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ }
+ return 2 | SUPPORTED;
+
+ case 0x6200:
+ if (m_arch == cr16_arch::CR16A)
+ stream << "res";
+ else
+ {
+ stream << "mulsw ";
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_rpair(stream, (opcode & 0x01e0) >> 5);
+ }
+ return 2 | SUPPORTED;
+
+ case 0x6400: case 0x6600:
+ if (m_arch == cr16_arch::CR16A)
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+ else
+ {
+ stream << "movd ";
+ format_imm21(stream, u32(opcode & 0x0200) << 11 | u32(opcode & 0x000e) << 16 | u32(opcode & 0x0010) << 12 | opcodes.r16(pc + 2));
+ stream << ", ";
+ format_rpair(stream, (opcode & 0x01e0) >> 5);
+ return 4 | SUPPORTED;
+ }
+
+ case 0x6800: case 0x6a00:
+ util::stream_format(stream, "mov%cb ", BIT(opcode, 9) ? 'z' : 'x');
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x6c00:
+ // Push and pop group
+ if (m_arch == cr16_arch::CR16A)
+ stream << "res";
+ else
+ {
+ if (BIT(opcode, 8))
+ stream << "popret ";
+ else if (BIT(opcode, 7))
+ stream << "pop ";
+ else
+ stream << "push ";
+ util::stream_format(stream, "$%d, ", ((opcode & 0x0060) >> 5) + 1);
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ if (BIT(opcode, 8))
+ {
+ util::stream_format(stream, " ; %cMM", BIT(opcode, 7) ? 'L' : 'S');
+ return 2 | STEP_OUT | SUPPORTED;
+ }
+ }
+ return 2 | SUPPORTED;
+
+ case 0x6e00:
+ if ((opcode & 0x01c0) != 0x01c0)
+ {
+ util::stream_format(stream, "s%s ", s_cc[(opcode & 0x01e0) >> 5]);
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ }
+ else
+ stream << "res";
+ return 2 | SUPPORTED;
+
+ case 0x7000:
+ stream << "lpr ";
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_rproc(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x7200:
+ stream << "spr ";
+ format_rproc(stream, (opcode & 0x01e0) >> 5);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ return 2 | SUPPORTED;
+
+ case 0x7400:
+ // Conditional or unconditional branch to large address
+ if ((opcode & 0x01e0) != 0x01e0 && m_arch != cr16_arch::CR16A)
+ {
+ if ((opcode & 0x01e0) == 0x01c0)
+ stream << "br ";
+ else
+ util::stream_format(stream, "b%s ", s_cc[(opcode & 0x01e0) >> 5]);
+ format_pc_disp21(stream, pc, u32(opcode & 0x000e) << 16 | u32(opcode & 0x0010) << 12 | opcodes.r16(pc + 2));
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+
+ case 0x7401:
+ // Jump and link to small address
+ stream << "jal ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ return 2 | SUPPORTED;
+
+ case 0x7600:
+ // Branch and link to large address
+ if (m_arch == cr16_arch::CR16A)
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+ else
+ {
+ stream << "bal ";
+ format_rpair(stream, (opcode & 0x01e0) >> 5);
+ stream << ", ";
+ format_pc_disp21(stream, pc, u32(opcode & 0x000e) << 16 | u32(opcode & 0x0010) << 12 | opcodes.r16(pc + 2));
+ return 4 | STEP_OVER | SUPPORTED;
+ }
+
+ case 0x7601:
+ // TBIT reg, reg only exists as a word operation
+ stream << "tbit ";
+ format_reg(stream, (opcode & 0x001e) >> 1);
+ stream << ", ";
+ format_reg(stream, (opcode & 0x01e0) >> 5);
+ return 2 | SUPPORTED;
+
+ case 0x7800:
+ if (opcode == 0x79fe)
+ {
+ stream << "retx";
+ return 2 | STEP_OUT | SUPPORTED;
+ }
+ else
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+
+ case 0x7a00:
+ if ((opcode & 0x01e0) == 0x01e0)
+ {
+ stream << "excp ";
+ format_excp_vector(stream, (opcode & 0x001e) >> 1);
+ return 2 | STEP_OVER | SUPPORTED;
+ }
+ else
+ {
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+
+ case 0x7c00:
+ if (opcode == 0x7dde)
+ stream << "di";
+ else if (opcode == 0x7dfe)
+ stream << "ei";
+ else
+ stream << "res";
+ return 2 | SUPPORTED;
+
+ case 0x7e00:
+ // Various special operations
+ if (opcode == 0x7ffe)
+ stream << "wait";
+ else if (m_arch == cr16_arch::CR16A)
+ stream << "res";
+ else if ((opcode & 0x000c) == 0x0000)
+ {
+ stream << "muluw ";
+ format_reg(stream, (opcode & 0x0012) >> 1);
+ stream << ", ";
+ format_rpair(stream, (opcode & 0x01e0) >> 5);
+ }
+ else if ((opcode & 0x011e) == 0x0004)
+ {
+ if (BIT(opcode, 7))
+ stream << "storm ";
+ else
+ stream << "loadm ";
+ util::stream_format(stream, "$%d", ((opcode & 0x0060) >> 5) + 1);
+ }
+ else if (opcode == 0x7fe6)
+ stream << "eiwait";
+ else
+ stream << "res";
+ return 2 | SUPPORTED;
+
+ default:
+ stream << "res";
+ return 2 | SUPPORTED;
+ }
+}
diff --git a/src/devices/cpu/cr16b/cr16bdasm.h b/src/devices/cpu/cr16b/cr16bdasm.h
new file mode 100644
index 00000000000..e8e96ed1a67
--- /dev/null
+++ b/src/devices/cpu/cr16b/cr16bdasm.h
@@ -0,0 +1,66 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_CR16B_CR16BDASM_H
+#define MAME_CPU_CR16B_CR16BDASM_H 1
+
+#pragma once
+
+class cr16b_disassembler : public util::disasm_interface
+{
+public:
+ // construction/destruction
+ cr16b_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;
+
+protected:
+ enum cr16_arch
+ {
+ CR16A,
+ CR16B
+ };
+
+ cr16b_disassembler(cr16_arch arch);
+
+ // internal helpers
+ void format_reg(std::ostream &stream, u8 reg);
+ void format_rpair(std::ostream &stream, u8 reg);
+ virtual void format_rproc(std::ostream &stream, u8 reg);
+ void format_short_imm(std::ostream &stream, u8 imm);
+ void format_short_imm_unsigned(std::ostream &stream, u8 imm, bool i);
+ void format_short_imm_decimal(std::ostream &stream, u8 imm);
+ void format_medium_imm(std::ostream &stream, u16 imm, bool i);
+ void format_medium_imm_decimal(std::ostream &stream, u16 imm);
+ void format_imm21(std::ostream &stream, u32 imm);
+ void format_disp5(std::ostream &stream, u8 disp);
+ void format_disp16(std::ostream &stream, u16 disp);
+ void format_disp18(std::ostream &stream, u32 disp);
+ void format_abs18(std::ostream &stream, u32 addr);
+ void format_pc_disp5(std::ostream &stream, offs_t pc, u8 disp);
+ void format_pc_disp9(std::ostream &stream, offs_t pc, u16 disp);
+ void format_pc_disp17(std::ostream &stream, offs_t pc, u32 disp);
+ void format_pc_disp21(std::ostream &stream, offs_t pc, u32 disp);
+ void format_excp_vector(std::ostream &stream, u8 vec);
+
+private:
+ // static tables
+ static const char *const s_cc[14];
+
+ // architecture version
+ const cr16_arch m_arch;
+};
+
+class cr16a_disassembler : public cr16b_disassembler
+{
+public:
+ // construction/destruction
+ cr16a_disassembler();
+
+protected:
+ virtual void format_rproc(std::ostream &stream, u8 reg) override;
+};
+
+#endif // MAME_CPU_CR16B_CR16BDASM_H
diff --git a/src/mame/drivers/vtech_unk1.cpp b/src/mame/drivers/glcx.cpp
index b8c7c310e1f..31f8a18f717 100644
--- a/src/mame/drivers/vtech_unk1.cpp
+++ b/src/mame/drivers/glcx.cpp
@@ -1,8 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
-// Unknown CPU type
-
// gl6600cx uses a NSC1028 system-on-a-chip designed by National Semiconductor specifically for VTech
// http://web.archive.org/web/19991127134657/http://www.national.com/news/item/0,1735,425,00.html
@@ -46,33 +44,45 @@ TMP47C241MG = TCLS-47 series 4-bit CPU with 2048x8 internal ROM
*/
#include "emu.h"
+#include "cpu/cr16b/cr16b.h"
#include "screen.h"
-class gl8008cx_state : public driver_device
+class glcx_state : public driver_device
{
public:
- gl8008cx_state(const machine_config &mconfig, device_type type, const char *tag)
+ glcx_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
{ }
- void gl8008cx(machine_config &config);
+ void glcx(machine_config &config);
private:
virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ void mem_map(address_map &map);
+
+ required_device<cr16b_device> m_maincpu;
};
-uint32_t gl8008cx_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+uint32_t glcx_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
return 0;
}
-static INPUT_PORTS_START( gl8008cx )
+void glcx_state::mem_map(address_map &map)
+{
+ map(0x000000, 0x1fffff).rom().region("maincpu", 0);
+}
+
+static INPUT_PORTS_START( glcx )
INPUT_PORTS_END
-void gl8008cx_state::gl8008cx(machine_config &config)
+void glcx_state::glcx(machine_config &config)
{
/* basic machine hardware */
- // UNKNOWN(config, "maincpu", unknown); // CPU type is unknown, epoxy blob
+ CR16B(config, m_maincpu, 10000000); // FIXME: determine exact type and clock
+ m_maincpu->set_addrmap(AS_PROGRAM, &glcx_state::mem_map);
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@@ -80,7 +90,7 @@ void gl8008cx_state::gl8008cx(machine_config &config)
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
screen.set_size(512, 256);
screen.set_visarea(0, 512-1, 0, 256-1);
- screen.set_screen_update(FUNC(gl8008cx_state::screen_update));
+ screen.set_screen_update(FUNC(glcx_state::screen_update));
}
ROM_START( gl6600cx )
@@ -105,6 +115,6 @@ ROM_START( bs9009cx )
ROM_END
-COMP( 1999, gl6600cx, 0, 0, gl8008cx, gl8008cx, gl8008cx_state, empty_init, "Video Technology", "Genius Leader 6600 CX (Germany)", MACHINE_IS_SKELETON )
-COMP( 1999, gl8008cx, 0, 0, gl8008cx, gl8008cx, gl8008cx_state, empty_init, "Video Technology", "Genius Leader 8008 CX (Germany)", MACHINE_IS_SKELETON)
-COMP( 1999, bs9009cx, 0, 0, gl8008cx, gl8008cx, gl8008cx_state, empty_init, "Video Technology", "BrainStation 9009 CXL (Germany)", MACHINE_IS_SKELETON)
+COMP( 1999, gl6600cx, 0, 0, glcx, glcx, glcx_state, empty_init, "Video Technology", "Genius Leader 6600 CX (Germany)", MACHINE_IS_SKELETON )
+COMP( 1999, gl8008cx, 0, 0, glcx, glcx, glcx_state, empty_init, "Video Technology", "Genius Leader 8008 CX (Germany)", MACHINE_IS_SKELETON)
+COMP( 1999, bs9009cx, 0, 0, glcx, glcx, glcx_state, empty_init, "Video Technology", "BrainStation 9009 CXL (Germany)", MACHINE_IS_SKELETON)
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 403810a5bf1..36fdb352d48 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -14279,6 +14279,11 @@ glass10 // (c) 1993 - Ref 931021
glass10a // (c) 1993 - Ref 931021 shows "Break Edition" on a real PCB
glasskr // (c) 1994 - Ref 931021 shows 1994 version, Anime girls, unprotected
+@source:glcx.cpp
+bs9009cx // 1999 BrainStation 9009 CXL (Germany)
+gl6600cx // 1999 Genius Leader 6600 CX (Germany)
+gl8008cx // 1999 Genius Leader 8008 CX (Germany)
+
@source:globalfr.cpp
gl_coc // Carry On Clubbin' (Global)
gl_coc29 //
@@ -39299,11 +39304,6 @@ laser700 // 1984? Laser 700
@source:vtech_eu3a12.cpp
vreadere
-@source:vtech_unk1.cpp
-bs9009cx // 1999 BrainStation 9009 CXL (Germany)
-gl6600cx // 1999 Genius Leader 6600 CX (Germany)
-gl8008cx // 1999 Genius Leader 8008 CX (Germany)
-
@source:vtech_unk2.cpp
glmmc // 199? Genius Master Mega Color
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 3f3d380f2d0..04c9b4055aa 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -294,6 +294,7 @@ genpc.cpp
gimix.cpp
gizmondo.cpp
glasgow.cpp
+glcx.cpp
gmaster.cpp
goupil.cpp
gp2x.cpp
@@ -900,7 +901,6 @@ vta2000.cpp
vtech1.cpp
vtech2.cpp
vtech_eu3a12.cpp
-vtech_unk1.cpp
vtech_unk2.cpp
wangpc.cpp
wicat.cpp
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 29363f53f19..89089b3a688 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -38,6 +38,7 @@ using util::BIT;
#include "cpu/cop400/cop444ds.h"
#include "cpu/cosmac/cosdasm.h"
#include "cpu/cp1610/1610dasm.h"
+#include "cpu/cr16b/cr16bdasm.h"
#include "cpu/cubeqcpu/cubedasm.h"
#include "cpu/dsp16/dsp16dis.h"
#include "cpu/dsp32/dsp32dis.h"
@@ -338,6 +339,8 @@ static const dasm_table_entry dasm_table[] =
{ "cop444", le, 0, []() -> util::disasm_interface * { return new cop444_disassembler; } },
{ "cop424", le, 0, []() -> util::disasm_interface * { return new cop424_disassembler; } },
{ "cp1610", be, -1, []() -> util::disasm_interface * { return new cp1610_disassembler; } },
+ { "cr16a", le, 0, []() -> util::disasm_interface * { return new cr16a_disassembler; } },
+ { "cr16b", le, 0, []() -> util::disasm_interface * { return new cr16b_disassembler; } },
{ "cquestlin", be, -3, []() -> util::disasm_interface * { return new cquestlin_disassembler; } },
{ "cquestrot", be, -3, []() -> util::disasm_interface * { return new cquestrot_disassembler; } },
{ "cquestsnd", be, -3, []() -> util::disasm_interface * { return new cquestsnd_disassembler; } },