summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/ns32000
diff options
context:
space:
mode:
author Nigel Barnes <Pernod70@users.noreply.github.com>2019-03-23 11:55:09 +0000
committer Nigel Barnes <Pernod70@users.noreply.github.com>2019-03-23 11:55:09 +0000
commit9e122168ef4fdbb9158bc8a4fd0e5e86900496f0 (patch)
treed3ba3c8087a701574e0bacb8ae9c24fd0d084069 /src/devices/cpu/ns32000
parentb445d101357be7d62f3dee88d29e66bfc59a5bc3 (diff)
ns32000: Skeleton CPU device with disassembler for NS32000 family.
bbc: Added preliminary Acorn 32016 2nd Processor, incomplete CPU emulation.
Diffstat (limited to 'src/devices/cpu/ns32000')
-rw-r--r--src/devices/cpu/ns32000/ns32000.cpp160
-rw-r--r--src/devices/cpu/ns32000/ns32000.h149
-rw-r--r--src/devices/cpu/ns32000/ns32000dasm.cpp834
-rw-r--r--src/devices/cpu/ns32000/ns32000dasm.h118
4 files changed, 1261 insertions, 0 deletions
diff --git a/src/devices/cpu/ns32000/ns32000.cpp b/src/devices/cpu/ns32000/ns32000.cpp
new file mode 100644
index 00000000000..6596d28f8dd
--- /dev/null
+++ b/src/devices/cpu/ns32000/ns32000.cpp
@@ -0,0 +1,160 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/*****************************************************************************
+*
+* ns32000.cpp
+*
+* NS32000 CPU family
+*
+*****************************************************************************/
+
+#include "emu.h"
+#include "ns32000.h"
+#include "ns32000dasm.h"
+#include "debugger.h"
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NS32008, ns32008_cpu_device, "ns32008", "National Semiconductor NS32008")
+DEFINE_DEVICE_TYPE(NS32016, ns32016_cpu_device, "ns32016", "National Semiconductor NS32016")
+DEFINE_DEVICE_TYPE(NS32032, ns32032_cpu_device, "ns32032", "National Semiconductor NS32032")
+
+
+//-------------------------------------------------
+// ns32000_cpu_device - constructor
+//-------------------------------------------------
+
+ns32000_cpu_device::ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int databits, int addrbits)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_program_config("program", ENDIANNESS_LITTLE, databits, addrbits, 0)
+ , m_icount(0)
+{
+}
+
+ns32008_cpu_device::ns32008_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : ns32000_cpu_device(mconfig, NS32008, tag, owner, clock, 8, 24)
+{
+}
+
+ns32016_cpu_device::ns32016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : ns32000_cpu_device(mconfig, NS32016, tag, owner, clock, 16, 24)
+{
+}
+
+ns32032_cpu_device::ns32032_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : ns32000_cpu_device(mconfig, NS32032, tag, owner, clock, 32, 24)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ns32000_cpu_device::device_start()
+{
+ set_icountptr(m_icount);
+
+ save_item(NAME(m_pc));
+ save_item(NAME(m_r));
+ save_item(NAME(m_f));
+
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
+
+ // dedicated registers
+ state_add(NS32000_PC, "PC", m_pc);
+ state_add(NS32000_SB, "SB", m_sb);
+ state_add(NS32000_FP, "FP", m_fp);
+ state_add(NS32000_SP1, "SP1", m_sp1);
+ state_add(NS32000_SP0, "SP0", m_sp0);
+ state_add(NS32000_INTBASE, "INTBASE", m_intbase);
+ state_add(NS32000_PSR, "PSR", m_psr);
+ state_add(NS32000_MOD, "MOD", m_mod);
+
+ // general registers
+ for (unsigned i = 0; i < 8; i++)
+ state_add(NS32000_R0 + i, util::string_format("R%d", i).c_str(), m_r[i]);
+
+ // floating point registers
+ //for (unsigned i = 0; i < 8; i++)
+ // state_add(NS32000_R7 + i, util::string_format("F%d", i).c_str(), m_f[i]);
+
+ // set our instruction counter
+ //set_icountptr(m_icount);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ns32000_cpu_device::device_reset()
+{
+ m_nmi_line = false;
+ m_irq_line = false;
+
+ m_pc = 0;
+}
+
+//-------------------------------------------------
+// execute_run - execute a timeslice's worth of
+// opcodes
+//-------------------------------------------------
+
+void ns32000_cpu_device::execute_run()
+{
+ while (m_icount > 0)
+ {
+ debugger_instruction_hook(m_pc);
+
+ m_icount--;
+ }
+}
+
+//-------------------------------------------------
+// execute_set_input - act on a changed input/
+// interrupt line
+//-------------------------------------------------
+
+void ns32000_cpu_device::execute_set_input(int inputnum, int state)
+{
+ switch (inputnum)
+ {
+ case INPUT_LINE_NMI:
+ // NMI is edge triggered
+ m_nmi_line = m_nmi_line || (state == ASSERT_LINE);
+ break;
+
+ case INPUT_LINE_IRQ0:
+ // IRQ is line triggered
+ m_irq_line = state == ASSERT_LINE;
+ break;
+ }
+}
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or nullptr if
+// the space doesn't exist
+//-------------------------------------------------
+
+device_memory_interface::space_config_vector ns32000_cpu_device::memory_space_config() const
+{
+ return space_config_vector{ std::make_pair(AS_PROGRAM, &m_program_config) };
+}
+
+bool ns32000_cpu_device::memory_translate(int spacenum, int intention, offs_t &address)
+{
+ return true;
+}
+
+//-------------------------------------------------
+// disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+std::unique_ptr<util::disasm_interface> ns32000_cpu_device::create_disassembler()
+{
+ return std::make_unique<ns32000_disassembler>();
+}
diff --git a/src/devices/cpu/ns32000/ns32000.h b/src/devices/cpu/ns32000/ns32000.h
new file mode 100644
index 00000000000..7b17cafba99
--- /dev/null
+++ b/src/devices/cpu/ns32000/ns32000.h
@@ -0,0 +1,149 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/*****************************************************************************
+*
+* ns32000.h
+*
+* NS32000 CPU family
+*
+*****************************************************************************/
+
+#ifndef MAME_CPU_NS32016_NS32016_H
+#define MAME_CPU_NS32016_NS32016_H
+
+#pragma once
+
+
+/***********************************************************************
+ CONSTANTS
+***********************************************************************/
+
+
+
+/***********************************************************************
+ TYPE DEFINITIONS
+***********************************************************************/
+
+class ns32000_cpu_device : public cpu_device
+{
+public:
+ // construction/destruction
+ ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int databits, int addrbits);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual u32 execute_min_cycles() const override { return 1; }
+ virtual u32 execute_max_cycles() const override { return 6; }
+ virtual u32 execute_input_lines() const override { return 2; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+ virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == INPUT_LINE_NMI; }
+
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ // addressing modes
+ enum
+ {
+ ADDRESSING_MODE_REGISTER_0 = 0,
+ ADDRESSING_MODE_REGISTER_1,
+ ADDRESSING_MODE_REGISTER_2,
+ ADDRESSING_MODE_REGISTER_3,
+ ADDRESSING_MODE_REGISTER_4,
+ ADDRESSING_MODE_REGISTER_5,
+ ADDRESSING_MODE_REGISTER_6,
+ ADDRESSING_MODE_REGISTER_7,
+ ADDRESSING_MODE_REGISTER_0_RELATIVE,
+ ADDRESSING_MODE_REGISTER_1_RELATIVE,
+ ADDRESSING_MODE_REGISTER_2_RELATIVE,
+ ADDRESSING_MODE_REGISTER_3_RELATIVE,
+ ADDRESSING_MODE_REGISTER_4_RELATIVE,
+ ADDRESSING_MODE_REGISTER_5_RELATIVE,
+ ADDRESSING_MODE_REGISTER_6_RELATIVE,
+ ADDRESSING_MODE_REGISTER_7_RELATIVE,
+ ADDRESSING_MODE_FRAME_MEMORY_RELATIVE,
+ ADDRESSING_MODE_STACK_MEMORY_RELATIVE,
+ ADDRESSING_MODE_STATIC_MEMORY_RELATIVE,
+ ADDRESSING_MODE_RESERVED,
+ ADDRESSING_MODE_IMMEDIATE,
+ ADDRESSING_MODE_ABSOLUTE,
+ ADDRESSING_MODE_EXTERNAL,
+ ADDRESSING_MODE_TOP_OF_STACK,
+ ADDRESSING_MODE_FRAME_MEMORY,
+ ADDRESSING_MODE_STACK_MEMORY,
+ ADDRESSING_MODE_STATIC_MEMORY,
+ ADDRESSING_MODE_PROGRAM_MEMORY,
+ ADDRESSING_MODE_INDEX_BYTES,
+ ADDRESSING_MODE_INDEX_WORDS,
+ ADDRESSING_MODE_INDEX_DOUBLE_WORDS,
+ ADDRESSING_MODE_INDEX_QUAD_WORDS,
+ };
+
+ // registers
+ enum
+ {
+ NS32000_PC = 1,
+ NS32000_SB, NS32000_FP, NS32000_SP1, NS32000_SP0, NS32000_INTBASE, NS32000_PSR, NS32000_MOD,
+ NS32000_R0, NS32000_R1, NS32000_R2, NS32000_R3, NS32000_R4, NS32000_R5, NS32000_R6, NS32000_R7,
+ };
+
+private:
+ // configuration
+ address_space_config m_program_config;
+
+ // emulation state
+ int m_icount;
+
+ u32 m_pc;
+ u32 m_sb;
+ u32 m_fp;
+ u32 m_sp1;
+ u32 m_sp0;
+ u32 m_intbase;
+ u32 m_psr;
+ u32 m_mod;
+ u32 m_r[8];
+ u32 m_f[8];
+
+ u8 m_irq_line;
+ u8 m_nmi_line;
+};
+
+class ns32008_cpu_device : public ns32000_cpu_device
+{
+public:
+ ns32008_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class ns32016_cpu_device : public ns32000_cpu_device
+{
+public:
+ ns32016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class ns32032_cpu_device : public ns32000_cpu_device
+{
+public:
+ ns32032_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+/***********************************************************************
+ DEVICE TYPE DECLARATIONS
+***********************************************************************/
+
+DECLARE_DEVICE_TYPE(NS32008, ns32008_cpu_device)
+DECLARE_DEVICE_TYPE(NS32016, ns32016_cpu_device)
+DECLARE_DEVICE_TYPE(NS32032, ns32032_cpu_device)
+
+#endif // MAME_CPU_NS32016_NS32016_H
diff --git a/src/devices/cpu/ns32000/ns32000dasm.cpp b/src/devices/cpu/ns32000/ns32000dasm.cpp
new file mode 100644
index 00000000000..983abefdd3e
--- /dev/null
+++ b/src/devices/cpu/ns32000/ns32000dasm.cpp
@@ -0,0 +1,834 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/*****************************************************************************
+*
+* ns32000dasm.cpp
+*
+* NS32000 CPU Disassembly
+*
+*****************************************************************************/
+
+#include "emu.h"
+#include "ns32000dasm.h"
+
+// instruction field extraction
+#define Format0cond(x) ((x >> 4) & 0x0f)
+
+#define Format1op(x) ((x >> 4) & 0x0f)
+
+#define Format2i(x) ((x >> 0) & 0x03)
+#define Format2op(x) ((x >> 4) & 0x07)
+#define Format2short(x) ((x >> 7) & 0x0f)
+#define Format2gen(x) ((x >> 11) & 0x1f)
+
+#define Format3i(x) ((x >> 0) & 0x03)
+#define Format3op(x) ((x >> 7) & 0x0f)
+#define Format3gen(x) ((x >> 11) & 0x1f)
+
+#define Format4i(x) ((x >> 0) & 0x03)
+#define Format4op(x) ((x >> 2) & 0x0f)
+#define Format4gen2(x) ((x >> 6) & 0x1f)
+#define Format4gen1(x) ((x >> 11) & 0x1f)
+
+#define Format5i(x) ((x >> 8) & 0x03)
+#define Format5op(x) ((x >> 10) & 0x07)
+#define Format5short(x) ((x >> 15) & 0x0f)
+
+#define Format6i(x) ((x >> 8) & 0x03)
+#define Format6op(x) ((x >> 10) & 0x0f)
+#define Format6gen2(x) ((x >> 14) & 0x1f)
+#define Format6gen1(x) ((x >> 19) & 0x1f)
+
+#define Format7i(x) ((x >> 8) & 0x03)
+#define Format7op(x) ((x >> 10) & 0x0f)
+#define Format7gen2(x) ((x >> 14) & 0x1f)
+#define Format7gen1(x) ((x >> 19) & 0x1f)
+
+#define Format8i(x) ((x >> 8) & 0x03)
+#define Format8op(x) (((x >> 8) & 0x04) | ((x >> 6) & 0x03))
+#define Format8reg(x) ((x >> 11) & 0x07)
+#define Format8gen2(x) ((x >> 14) & 0x1f)
+#define Format8gen1(x) ((x >> 19) & 0x1f)
+
+#define Format9i(x) ((x >> 8) & 0x03)
+#define Format9f(x) ((x >> 10) & 0x01)
+#define Format9op(x) ((x >> 11) & 0x07)
+#define Format9gen2(x) ((x >> 14) & 0x1f)
+#define Format9gen1(x) ((x >> 19) & 0x1f)
+
+#define Format11f(x) ((x >> 8) & 0x01)
+#define Format11op(x) ((x >> 10) & 0x0f)
+#define Format11gen2(x) ((x >> 14) & 0x1f)
+#define Format11gen1(x) ((x >> 19) & 0x1f)
+
+#define Format14i(x) ((x >> 8) & 0x01)
+#define Format14op(x) ((x >> 10) & 0x0f)
+#define Format14short(x) ((x >> 15) & 0x1f)
+#define Format14gen1(x) ((x >> 19) & 0x1f)
+
+// instructions
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format0_op[1] =
+{
+ { "Bcond", DISP, 0, 0, 0, 0 }
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format1_op[16] =
+{
+ { "BSR", DISP, 0, 0, 0, STEP_OVER },
+ { "RET", DISP, 0, 0, 0, STEP_OUT },
+ { "CXP", DISP, 0, 0, 0, STEP_OVER },
+ { "RXP", DISP, 0, 0, 0, STEP_OUT },
+ { "RETT", 0, 0, 0, 0, STEP_OUT },
+ { "RETI", DISP, 0, 0, 0, STEP_OUT },
+ { "SAVE", IMM, 0, 0, 0, 0 },
+ { "RESTORE", IMM, 0, 0, 0, 0 },
+ { "ENTER", IMM, DISP, 0, 0, 0 },
+ { "EXIT", IMM, 0, 0, 0, 0 },
+ { "NOP", 0, 0, 0, 0, 0 },
+ { "WAIT", 0, 0, 0, 0, 0 },
+ { "DIA", 0, 0, 0, 0, 0 },
+ { "FLAG", 0, 0, 0, 0, 0 },
+ { "SVC", 0, 0, 0, 0, 0 },
+ { "BPT", 0, 0, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format2_op[8] =
+{
+ { "ADDQi", QUICK, GEN | RMW | I, 0, 0, 0 },
+ { "CMPQi", QUICK, GEN | READ | I, 0, 0, 0 },
+ { "SPRi", SHORT, GEN | WRITE | I, 0, 0, 0 },
+ { "Scondi", GEN | WRITE | I, 0, 0, 0, 0 },
+ { "ACBi", QUICK, GEN | RMW | I, DISP, 0, 0 },
+ { "MOVQi", QUICK, GEN | WRITE | I, 0, 0, 0 },
+ { "LPRi", SHORT, GEN | READ | I, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format3_op[16] =
+{
+ { "CXPD", GEN | ADDR, 0, 0, 0, STEP_OVER },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "BICPSRi", GEN | READ | I, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "JUMP", GEN | ADDR, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "BISPSRB", GEN | READ | B, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "ADJSPi", GEN | READ | I, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "JSR", GEN | ADDR, 0, 0, 0, STEP_OVER },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "CASEi", GEN | READ | I, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format4_op[16] =
+{
+ { "ADDi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "CMPi", GEN | READ | I, GEN | READ | I, 0, 0, 0 },
+ { "BICi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "ADDCi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "MOVi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 },
+ { "ORi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "SUBi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "ADDR", GEN | ADDR, GEN | WRITE | D, 0, 0, 0 },
+ { "ANDi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "SUBCi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "TBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
+ { "XORi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format5_op[16] =
+{
+ { "MOVSi", OPTIONS, 0, 0, 0, 0 },
+ { "CMPSi", OPTIONS, 0, 0, 0, 0 },
+ { "SETCFG", SHORT, 0, 0, 0, 0 },
+ { "SKPSi", OPTIONS, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format6_op[16] =
+{
+ { "ROTi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 },
+ { "ASHi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 },
+ { "CBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
+ { "CBITIi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "LSHi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 },
+ { "SBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
+ { "SBITIi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
+ { "NEGi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 },
+ { "NOTi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "SUBPi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "ABSi", GEN | READ | I, GEN | READ | I, 0, 0, 0 },
+ { "COM", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 },
+ { "IBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
+ { "ADDPi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format7_op[16] =
+{
+ { "MOVMi", GEN | ADDR, GEN | ADDR, DISP, 0, 0 },
+ { "CMPMi", GEN | ADDR, GEN | ADDR, DISP, 0, 0 },
+ { "INSSi", GEN | READ | I, GEN | REGADDR, IMM, 0, 0 },
+ { "EXTSi", GEN | REGADDR, GEN | WRITE | I, IMM, 0, 0 },
+ { "MOVXBW", GEN | READ | B, GEN | WRITE | W, 0, 0, 0 },
+ { "MOVZBW", GEN | READ | B, GEN | WRITE | W, 0, 0, 0 },
+ { "MOVZiD", GEN | READ | I, GEN | WRITE | D, 0, 0, 0 },
+ { "MOVXiD", GEN | READ | I, GEN | WRITE | D, 0, 0, 0 },
+ { "MULi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "MEIi", GEN | READ | I, GEN | RMW | I2, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "DEIi", GEN | READ | I, GEN | RMW | I2, 0, 0, 0 },
+ { "QUOi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "REMi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "MODi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+ { "DIVi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format8_op[] =
+{
+ { "EXTi", REG, GEN | REGADDR, GEN | WRITE | I, DISP, 0 },
+ { "CVTP", REG, GEN | ADDR, GEN | WRITE | D, 0, 0 },
+ { "INSi", REG, GEN | READ | I, GEN | REGADDR, DISP, 0 },
+ { "CHECKi", REG, GEN | ADDR, GEN | READ | I, 0, 0 },
+ { "INDEXi", REG, GEN | READ | I, GEN | READ | I, 0, 0 },
+ { "FFSi", GEN | READ | I, GEN | RMW | B, 0, 0, 0 },
+ { "MOVSUi", GEN | ADDR, GEN | ADDR, 0, 0, 0 },
+ { "MOVUSi", GEN | ADDR, GEN | ADDR, 0, 0, 0 }
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format9_op[] =
+{
+ { "MOVif", GEN | READ | I, GEN | WRITE | F, 0, 0, 0 },
+ { "LFSR", GEN | READ | D, 0, 0, 0, 0 },
+ { "MOVLF", GEN | READ | L, GEN | WRITE | F, 0, 0, 0 },
+ { "MOVFL", GEN | READ | F, GEN | WRITE | L, 0, 0, 0 },
+ { "ROUNDfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 },
+ { "TRUNCfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 },
+ { "SFSR", GEN | WRITE | D, 0, 0, 0, 0 },
+ { "FLOORfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format11_op[] =
+{
+ { "ADDf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 },
+ { "MOVf", GEN | READ | F, GEN | WRITE | F, 0, 0, 0 },
+ { "CMPf", GEN | READ | F, GEN | READ | F, 0, 0, 0 }, // POLYf
+ { "Trap (SLAVE)", 0, 0, 0, 0, 0 }, // DOTf
+ { "SUBf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 }, // SCALBf
+ { "NEGf", GEN | READ | F, GEN | WRITE | F, 0, 0, 0 }, // LOGBf
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "DIVf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 },
+ { "Trap (SLAVE)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "MULf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 },
+ { "ABSf", GEN | READ | F, GEN | READ | F, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+};
+const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format14_op[] =
+{
+ { "RDVAL", GEN | ADDR, 0, 0, 0, 0 },
+ { "WRVAL", GEN | ADDR, 0, 0, 0, 0 },
+ { "LMR", SHORT, GEN | READ | D, 0, 0, 0 },
+ { "SMR", SHORT, GEN | WRITE | D, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 }, // CINV
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+ { "Trap (UND)", 0, 0, 0, 0, 0 },
+};
+
+
+const char *const ns32000_disassembler::Format0[] =
+{
+ "Bcond"
+};
+const char *const ns32000_disassembler::Format1[] =
+{
+ "BSR", "RET", "CXP", "RXP", "RETT", "RETI", "SAVE", "RESTORE", "ENTER", "EXIT", "NOP", "WAIT", "DIA", "FLAG", "SVC", "BPT"
+};
+const char *const ns32000_disassembler::Format2[] =
+{
+ "ADDQi", "CMPQi", "SPRi", "Scondi", "ACBi", "MOVQi", "LPRi"
+};
+const char *const ns32000_disassembler::Format3[] =
+{
+ "CXPD", "Trap (UND)", "BICPSR", "Trap (UND)", "JUMP", "Trap (UND)", "BISPSR", "Trap (UND)", "Trap (UND)", "Trap (UND)", "ADJSPi", "Trap (UND)", "JSR", "Trap (UND)", "CASEi", "Trap (UND)"
+};
+const char *const ns32000_disassembler::Format4[] =
+{
+ "ADDi", "CMPi", "BICi", "Trap (UND)", "ADDCi", "MOVi", "ORi", "Trap (UND)", "SUBi", "ADDR", "ANDi", "Trap (UND)", "SUBCi", "TBITi", "XORi", "Trap (UND)"
+};
+const char *const ns32000_disassembler::Format5[] =
+{
+ "MOVSi", "CMPSi", "SETCFG", "SKPSi", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)"
+};
+const char *const ns32000_disassembler::Format6[] =
+{
+ "ROTi", "ASHi", "CBITi", "CBITIi", "Trap (UND)", "LSHi", "SBITi", "SBITIi", "NEGi", "NOTi", "Trap (UND)", "SUBPi", "ABSi", "COM", "IBITi", "ADDPi"
+};
+const char *const ns32000_disassembler::Format7[] =
+{
+ "MOVMi", "CMPMi", "INSSi", "EXTSi", "MOVXBW", "MOVZBW", "MOVZiD", "MOVXiD", "MULi", "MEIi", "Trap (UND)", "DEIi", "QUOi", "REMi", "MODi", "DIVi"
+};
+const char *const ns32000_disassembler::Format8[] =
+{
+ "EXTi", "CVTP", "INSi", "CHECKi", "INDEXi", "FFSi", "MOVSUi", "MOVUSi"
+};
+const char *const ns32000_disassembler::Format9[] =
+{
+ "MOVif", "LFSR", "MOVLF", "MOVFL", "ROUNDfi", "TRUNCfi", "SFSR", "FLOORfi"
+};
+const char *const ns32000_disassembler::Format11[] =
+{
+ "ADDf", "MOVf", "CMPf", "Trap (SLAVE)", "SUBf", "NEGf", "Trap (UND)", "Trap (UND)", "DIVf", "Trap (SLAVE)", "Trap (UND)", "Trap (UND)", "MULf", "ABSf", "Trap (UND)", "Trap (UND)"
+};
+const char *const ns32000_disassembler::Format14[] =
+{
+ "RDVAL", "WRVAL", "LMR", "SMR", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)"
+};
+
+// types
+const char *const ns32000_disassembler::iType[] =
+{
+ "B", "W", " ", "D"
+};
+const char *const ns32000_disassembler::fType[] =
+{
+ "L", "F"
+};
+const char *const ns32000_disassembler::cType[] =
+{
+ "Q", "D"
+};
+
+// index byte sizes
+const char *const ns32000_disassembler::indexSize[] =
+{
+ "B", "W", "D", "Q"
+};
+
+// short codes
+const char *const ns32000_disassembler::cond[] =
+{
+ "EQ", "NE", "CS", "CC", "HI", "LS", "GT", "LE", "FS", "FC", "LO", "HS", "LT", "GE", "R", "N"
+};
+const char *const ns32000_disassembler::areg[] =
+{
+ "US", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "FP", "SP", "SB", "(reserved)", "(reserved)", "PSR", "INTBASE", "MOD"
+};
+const char *const ns32000_disassembler::mreg[] =
+{
+ "BPR0", "BPR1", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "MSR", "BCNT", "PTB0", "PTB1", "(reserved)", "EIA"
+};
+
+// register names
+const char *const ns32000_disassembler::R[] =
+{
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7"
+};
+const char *const ns32000_disassembler::M[] =
+{
+ "FP", "SP", "SB"
+};
+const char *const ns32000_disassembler::PR[] =
+{
+ "UPSR", "DCR", "BPC", "DSR", "CAR", "", "", "", "FP", "SP", "SB", "USP", "CFG", "PSR", "INTBASE", "MOD"
+};
+
+int8_t ns32000_disassembler::short2int(uint8_t val)
+{
+ return (val & 0x08) ? val | 0xf0 : val;
+}
+
+std::string ns32000_disassembler::mnemonic_index(std::string form, std::string itype, std::string ftype)
+{
+ if (itype.size() && form.find('i') != std::string::npos)
+ form.replace(form.find('i'), 1, itype);
+ if (ftype.size() && form.find('f') != std::string::npos)
+ form.replace(form.find('f'), 1, ftype);
+ return form;
+}
+
+uint8_t ns32000_disassembler::opcode_format(uint8_t byte)
+{
+ switch (byte & 0x0f)
+ {
+ case 0x0a: return 0;
+ case 0x02: return 1;
+ case 0x0c:
+ case 0x0d:
+ case 0x0f:
+ if ((byte & 0x70) != 0x70)
+ return 2;
+ else
+ return 3;
+ }
+
+ if ((byte & 0x03) != 0x02) return 4;
+
+ switch (byte)
+ {
+ case 0x0e: return 5;
+ case 0x4e: return 6;
+ case 0xce: return 7;
+ case 0x2e:
+ case 0x6e:
+ case 0xae:
+ case 0xee: return 8;
+ case 0x3e: return 9;
+ case 0x7e: return 10;
+ case 0xbe: return 11;
+ case 0xfe: return 12;
+ case 0x9e: return 13;
+ case 0x1e: return 14;
+ }
+
+ return 99; /* unknown format */
+}
+
+inline std::string ns32000_disassembler::get_option_list(uint8_t cfg)
+{
+ std::string option_list;
+
+ option_list.append("[");
+ if (BIT(cfg, 0)) option_list.append("I,");
+ if (BIT(cfg, 1)) option_list.append("F,");
+ if (BIT(cfg, 2)) option_list.append("M,");
+ if (BIT(cfg, 3)) option_list.append("C,");
+ if (option_list.back() == ',') option_list.pop_back();
+ option_list.append("]");
+
+ return option_list;
+}
+
+inline std::string ns32000_disassembler::get_options(uint8_t opts)
+{
+ std::string options;
+
+ options.append(" ");
+ if ((opts & 0x02) == 0x02) options.append("B,");
+ if ((opts & 0x04) == 0x04) options.append("W,");
+ if ((opts & 0x0c) == 0x0c) options.append("U,");
+ if (options.back() == ',') options.pop_back();
+
+ return options;
+}
+
+inline int32_t ns32000_disassembler::get_disp(offs_t &pc, const data_buffer &opcodes)
+{
+ /* displacement can be upto 3 bytes */
+ uint32_t disp = bitswap<32>(opcodes.r32(pc), 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24);
+
+ switch ((disp >> 29) & 0x07)
+ {
+ case 0: case 1: /* 7 bit positive */
+ disp = (disp >> 24);
+ pc += 1;
+ break;
+
+ case 2: case 3: /* 7 bit negative */
+ disp = (disp >> 24) | 0xffffff80;
+ pc += 1;
+ break;
+
+ case 4: /* 14 bit positive */
+ disp = (disp >> 16) & 0x3fff;
+ pc += 2;
+ break;
+
+ case 5: /* 14 bit negative */
+ disp = (disp >> 16) | 0xffffc000;
+ pc += 2;
+ break;
+
+ case 6: /* 30 bit positive */
+ disp = disp & 0x3fffffff;
+ pc += 4;
+ break;
+
+ case 7: /* 30 bit negative */
+ pc += 4;
+ break;
+ }
+
+ return disp;
+}
+
+inline std::string ns32000_disassembler::get_reg_list(offs_t &pc, const data_buffer &opcodes, bool reverse)
+{
+ std::string reg_list;
+
+ uint8_t byte = opcodes.r8(pc++);
+
+ reg_list.append("[");
+ for (int i = 0; i < 8; i++)
+ {
+ if (BIT(byte, i)) reg_list.append(R[reverse ? (~i & 7) : (i & 7)]).append(",");
+ }
+ if (reg_list.back() == ',') reg_list.pop_back();
+ reg_list.append("]");
+
+ return reg_list;
+}
+
+void ns32000_disassembler::stream_gen(std::ostream &stream, u8 gen_addr, u8 op_len, offs_t &pc, const data_buffer &opcodes)
+{
+ uint8_t index_byte;
+ int32_t disp1, disp2;
+
+ switch (gen_addr)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ /* Register */
+ util::stream_format(stream, "%s", R[gen_addr & 0x07]);
+ break;
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ /* Register Relative */
+ disp1 = get_disp(pc, opcodes);
+ util::stream_format(stream, "%+d(%s)", disp1, R[gen_addr & 0x07]);
+ break;
+ case 0x10: case 0x11: case 0x12:
+ /* Memory Relative */
+ disp1 = get_disp(pc, opcodes);
+ disp2 = get_disp(pc, opcodes);
+ util::stream_format(stream, "#X%02X(#X%02X(%s))", disp2, disp1, M[gen_addr & 0x03]);
+ break;
+ case 0x13:
+ /* Reserved */
+ util::stream_format(stream, "(reserved)");
+ break;
+ case 0x14:
+ /* Immediate */
+ disp1 = bitswap<32>(opcodes.r32(pc), 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24);
+ util::stream_format(stream, "#X%02X", (op_len == 0 ? (disp1 >> 24) : (op_len == 1 ? (disp1 >> 16) : disp1)));
+ pc += op_len + 1;
+ break;
+ case 0x15:
+ /* Absolute */
+ disp1 = get_disp(pc, opcodes);
+ util::stream_format(stream, "@#X%02X", disp1);
+ break;
+ case 0x16:
+ /* External */
+ disp1 = get_disp(pc, opcodes);
+ disp2 = get_disp(pc, opcodes);
+ util::stream_format(stream, "EXT(%d)+%d", disp1, disp2);
+ break;
+ case 0x17:
+ /* Top Of Stack */
+ util::stream_format(stream, "TOS");
+ break;
+ case 0x18: case 0x19: case 0x1a:
+ /* Memory Space */
+ disp1 = get_disp(pc, opcodes);
+ util::stream_format(stream, "#X%02X(%s)", disp1, M[gen_addr & 0x03]);
+ break;
+ case 0x1b:
+ /* Memory Space */
+ disp1 = get_disp(pc, opcodes);
+ util::stream_format(stream, "#X%06X", m_base_pc + disp1);
+ break;
+ case 0x1c:
+ /* Scaled Index */
+ index_byte = opcodes.r8(pc++);
+ stream_gen(stream, index_byte >> 3, op_len, pc, opcodes);
+ util::stream_format(stream, "[%s:%c]", R[index_byte & 0x07], indexSize[gen_addr & 0x03]);
+ break;
+ }
+}
+
+offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ uint32_t flags = SUPPORTED;
+
+ uint32_t opcode;
+ std::string mnemonic;
+ uint8_t temp8;
+
+ /* opcode can be upto 3 bytes */
+ opcode = opcodes.r32(pc);
+ m_base_pc = pc;
+
+ switch (opcode_format(opcode))
+ {
+ case 0: /* Format 0 */
+ pc += 1;
+ util::stream_format(stream, "%-8s #X%06X", std::string("B").append(cond[Format0cond(opcode)]), m_base_pc + get_disp(pc, opcodes));
+ break;
+
+ case 0x01: /* Format 1 */
+ pc += 1;
+ switch (Format1op(opcode))
+ {
+ case 0x00:
+ util::stream_format(stream, "%-8s #X%06X", Format1[Format1op(opcode)], m_base_pc + get_disp(pc, opcodes));
+ break;
+ case 0x01:
+ util::stream_format(stream, "%-8s #X%02X", Format1[Format1op(opcode)], get_disp(pc, opcodes) & 0xffffff);
+ break;
+ case 0x02:
+ util::stream_format(stream, "%-8s EXT(%d)", Format1[Format1op(opcode)], get_disp(pc, opcodes));
+ break;
+ case 0x03: case 0x04:
+ util::stream_format(stream, "%-8s #X%02X", Format1[Format1op(opcode)], get_disp(pc, opcodes) & 0xffffff);
+ break;
+ case 0x05:
+ util::stream_format(stream, "%-8s", Format1[Format1op(opcode)]);
+ break;
+ case 0x06:
+ util::stream_format(stream, "%-8s %s", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, false));
+ break;
+ case 0x07: case 0x09:
+ util::stream_format(stream, "%-8s %s", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, true));
+ break;
+ case 0x08:
+ util::stream_format(stream, "%-8s %s, %d", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, false), get_disp(pc, opcodes));
+ break;
+ case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ util::stream_format(stream, "%-8s", Format1[Format1op(opcode)]);
+ break;
+ }
+ break;
+
+ case 0x02: /* Format 2 */
+ pc += 2;
+ mnemonic = mnemonic_index(Format2[Format2op(opcode)], iType[Format2i(opcode)], "");
+ switch (Format2op(opcode))
+ {
+ case 0x00: case 0x01: case 0x05:
+ util::stream_format(stream, "%-8s %+d, ", mnemonic, short2int(Format2short(opcode)));
+ stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes);
+ break;
+ case 0x02: case 0x06:
+ util::stream_format(stream, "%-8s %s, ", mnemonic, areg[Format2short(opcode)]);
+ stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes);
+ break;
+ case 0x03:
+ util::stream_format(stream, "%-8s ", std::string("S").append(cond[Format2short(opcode)]).append(iType[Format2i(opcode)]));
+ stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes);
+ break;
+ case 0x04:
+ util::stream_format(stream, "%-8s %+d, ", mnemonic, short2int(Format2short(opcode)));
+ stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes);
+ util::stream_format(stream, ", #X%06x", m_base_pc + get_disp(pc, opcodes));
+ break;
+ }
+ break;
+
+ case 0x03: /* Format 3 */
+ pc += 2;
+ mnemonic = mnemonic_index(Format3[Format3op(opcode)], iType[Format3i(opcode)], "");
+ switch (Format3op(opcode))
+ {
+ case 0x00: case 0x02: case 0x04: case 0x06: case 0x0a: case 0x0c: case 0x0e:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format3gen(opcode), Format3i(opcode), pc, opcodes);
+ break;
+ default: /* Trap */
+ util::stream_format(stream, "%-8s ", mnemonic);
+ break;
+ }
+ break;
+
+ case 0x04: /* Format 4 */
+ pc += 2;
+ mnemonic = mnemonic_index(Format4[Format4op(opcode)], iType[Format4i(opcode)], "");
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format4gen1(opcode), Format4i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format4gen2(opcode), Format4i(opcode), pc, opcodes);
+ break;
+
+ case 0x05: /* Format 5 */
+ pc += 3;
+ mnemonic = mnemonic_index(Format5[Format5op(opcode)], iType[Format5i(opcode)], "");
+ switch ((opcode >> 10) & 0x0f)
+ {
+ case 0x00: case 0x01: case 0x03:
+ if (Format5short(opcode) & 0x01)
+ util::stream_format(stream, "%-8s %s", std::string(Format5[Format5op(opcode)]).append("T"), get_options(Format5short(opcode)));
+ else
+ util::stream_format(stream, "%-8s %s", mnemonic, get_options(Format5short(opcode)));
+ break;
+ case 0x02:
+ util::stream_format(stream, "%-8s %s", Format5[Format5op(opcode)], get_option_list(Format5short(opcode)));
+ break;
+ default: /* Trap */
+ util::stream_format(stream, "%-8s ", mnemonic);
+ break;
+ }
+ break;
+
+ case 0x06: /* Format 6 */
+ pc += 3;
+ mnemonic = mnemonic_index(Format6[Format6op(opcode)], iType[Format6i(opcode)], "");
+ switch ((opcode >> 10) & 0x0f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format6gen1(opcode), Format6i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format6gen2(opcode), Format6i(opcode), pc, opcodes);
+ break;
+ default: /* Trap */
+ util::stream_format(stream, "%-8s ", mnemonic);
+ break;
+ }
+ break;
+
+ case 0x07: /* Format 7 */
+ pc += 3;
+ mnemonic = mnemonic_index(Format7[Format7op(opcode)], iType[Format7i(opcode)], "");
+ switch (Format7op(opcode))
+ {
+ case 0x00: case 0x01:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes);
+ util::stream_format(stream, ", %d", get_disp(pc, opcodes));
+ break;
+ case 0x02: case 0x03:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes);
+ temp8 = opcodes.r8(pc++);
+ util::stream_format(stream, ", %d, %d", temp8 >> 5, temp8 + 1);
+ break;
+ case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes);
+ break;
+ default: /* Trap */
+ util::stream_format(stream, "%-8s ", mnemonic);
+ break;
+ }
+ break;
+
+ case 0x08: /* Format 8 */
+ pc += 3;
+ mnemonic = mnemonic_index(Format8[Format8op(opcode)], iType[Format8i(opcode)], "");
+ switch (Format8op(opcode))
+ {
+ case 0x00: case 0x02:
+ util::stream_format(stream, "%-8s %s, ", mnemonic, R[Format8reg(opcode)]);
+ stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes);
+ util::stream_format(stream, ", %d", get_disp(pc, opcodes));
+ break;
+ case 0x01: case 0x03: case 0x04:
+ util::stream_format(stream, "%-8s %s, ", mnemonic, R[Format8reg(opcode)]);
+ stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes);
+ break;
+ case 0x05:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes);
+ break;
+ case 0x06:
+ if (Format8reg(opcode) == 0x01)
+ util::stream_format(stream, "%-8s ", std::string(Format8[Format8op(opcode)]).append(iType[Format8i(opcode)]));
+ else
+ util::stream_format(stream, "%-8s ", std::string(Format8[Format8op(opcode) + 1]).append(iType[Format8i(opcode)]));
+ stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes);
+ break;
+ }
+ break;
+
+ case 0x09: /* Format 9 */
+ pc += 3;
+ mnemonic = mnemonic_index(Format9[Format9op(opcode)], iType[Format9i(opcode)], fType[Format9f(opcode)]);
+ switch (Format9op(opcode))
+ {
+ case 0x00: case 0x02: case 0x04: case 0x05: case 0x07:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format9gen1(opcode), Format9i(opcode), pc, opcodes);
+ util::stream_format(stream, ", ");
+ stream_gen(stream, Format9gen2(opcode), Format9i(opcode), pc, opcodes);
+ break;
+ case 0x01: case 0x06:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format9gen1(opcode), Format9i(opcode), pc, opcodes);
+ break;
+ }
+
+ case 0x0b: /* Format 11 */
+ pc += 3;
+ mnemonic = mnemonic_index(Format11[Format11op(opcode)], nullptr, fType[Format11f(opcode)]);
+ switch (Format11op(opcode))
+ {
+ case 0x00: case 0x01: case 0x02: case 0x04: case 0x05 : case 0x08: case 0x0c : case 0x0d:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format11gen1(opcode), Format11f(opcode), pc, opcodes);
+ util::stream_format(stream, ",");
+ stream_gen(stream, Format11gen2(opcode), Format11f(opcode), pc, opcodes);
+ break;
+ default: /* Trap */
+ util::stream_format(stream, "%-8s ", mnemonic);
+ break;
+ }
+ break;
+
+ case 0x0a: /* Format 10 */
+ case 0x0c: /* Format 12 */
+ case 0x0d: /* Format 13 */
+ pc += 3;
+ util::stream_format(stream, "Trap (UND)");
+ break;
+
+ case 0x0e: /* Format 14 */
+ pc += 3;
+ mnemonic = mnemonic_index(Format14[Format14op(opcode)], iType[Format14i(opcode)], "");
+ switch (Format14op(opcode))
+ {
+ case 0x00: case 0x01:
+ util::stream_format(stream, "%-8s ", mnemonic);
+ stream_gen(stream, Format14gen1(opcode), Format14i(opcode), pc, opcodes);
+ break;
+ case 0x02: case 0x03:
+ util::stream_format(stream, "%-8s %s, ", mnemonic, mreg[Format14short(opcode)]);
+ stream_gen(stream, Format14gen1(opcode), Format14i(opcode), pc, opcodes);
+ break;
+ default: /* Trap */
+ util::stream_format(stream, "%-8s ", mnemonic);
+ break;
+ }
+ break;
+
+ default:
+ pc += 1;
+ util::stream_format(stream, "unknown instruction format");
+ break;
+ }
+
+ return (pc - m_base_pc) | flags;
+}
diff --git a/src/devices/cpu/ns32000/ns32000dasm.h b/src/devices/cpu/ns32000/ns32000dasm.h
new file mode 100644
index 00000000000..e9c970c9829
--- /dev/null
+++ b/src/devices/cpu/ns32000/ns32000dasm.h
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/*****************************************************************************
+*
+* ns32000dasm.cpp
+*
+* NS32000 CPU Disassembly
+*
+*****************************************************************************/
+
+#ifndef MAME_CPU_NS32000_NS32000DASM_H
+#define MAME_CPU_NS32000_NS32000DASM_H
+
+#pragma once
+
+class ns32000_disassembler : public util::disasm_interface
+{
+public:
+
+ ns32000_disassembler() = default;
+ virtual ~ns32000_disassembler() = default;
+
+ virtual u32 opcode_alignment() const override { return 1; }
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+private:
+ /* implied operand attributes */
+ enum
+ {
+ REG = 16,
+ QUICK,
+ SHORT,
+ IMM,
+ DISP,
+ GEN,
+ OPTIONS,
+ };
+ /* access classes */
+ enum
+ {
+ READ = 8,
+ WRITE,
+ RMW,
+ ADDR,
+ REGADDR
+ };
+ /* length attributes */
+ enum
+ {
+ B = 0,
+ W = 1,
+ D = 3,
+ I,
+ I2,
+ F,
+ L
+ };
+ struct NS32000_OPCODE {
+ const char *mnemonic;
+ u32 operand1;
+ u32 operand;
+ u32 operand3;
+ u32 operand4;
+ offs_t dasm_flags;
+ };
+
+ static const NS32000_OPCODE format0_op[1];
+ static const NS32000_OPCODE format1_op[16];
+ static const NS32000_OPCODE format2_op[8];
+ static const NS32000_OPCODE format3_op[16];
+ static const NS32000_OPCODE format4_op[16];
+ static const NS32000_OPCODE format5_op[16];
+ static const NS32000_OPCODE format6_op[16];
+ static const NS32000_OPCODE format7_op[16];
+ static const NS32000_OPCODE format8_op[16];
+ static const NS32000_OPCODE format9_op[16];
+ static const NS32000_OPCODE format11_op[16];
+ static const NS32000_OPCODE format14_op[16];
+
+
+ static char const *const Format0[];
+ static char const *const Format1[];
+ static char const *const Format2[];
+ static char const *const Format3[];
+ static char const *const Format4[];
+ static char const *const Format5[];
+ static char const *const Format6[];
+ static char const *const Format7[];
+ static char const *const Format8[];
+ static char const *const Format9[];
+ static char const *const Format11[];
+ static char const *const Format14[];
+ static char const *const iType[];
+ static char const *const fType[];
+ static char const *const cType[];
+ static char const *const indexSize[];
+ static char const *const cond[];
+ static char const *const areg[];
+ static char const *const mreg[];
+ static char const *const R[];
+ static char const *const M[];
+ static char const *const PR[];
+
+ std::string mnemonic_index(std::string form, std::string itype, std::string ftype);
+ uint8_t opcode_format(uint8_t byte);
+ int8_t short2int(uint8_t val);
+ static inline int32_t get_disp(offs_t &pc, const data_buffer &opcodes);
+ static inline std::string get_option_list(uint8_t cfg);
+ static inline std::string get_options(uint8_t opts);
+ static inline std::string get_reg_list(offs_t &pc, const data_buffer &opcodes, bool reverse);
+
+ void stream_gen(std::ostream &stream, u8 gen_addr, u8 op_len, offs_t &pc, const data_buffer &opcodes);
+
+ u32 m_base_pc;
+ unsigned m_pcmask;
+};
+
+#endif