summaryrefslogtreecommitdiffstatshomepage
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
parentb445d101357be7d62f3dee88d29e66bfc59a5bc3 (diff)
ns32000: Skeleton CPU device with disassembler for NS32000 family.
bbc: Added preliminary Acorn 32016 2nd Processor, incomplete CPU emulation.
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--scripts/src/cpu.lua17
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/bus/bbc/tube/tube.cpp12
-rw-r--r--src/devices/bus/bbc/tube/tube_32016.cpp210
-rw-r--r--src/devices/bus/bbc/tube/tube_32016.h71
-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
-rw-r--r--src/tools/unidasm.cpp2
11 files changed, 1571 insertions, 5 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index d846e8b6abd..14130a37ae7 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -409,6 +409,8 @@ if (BUSES["BBC_TUBE"]~=null) then
files {
MAME_DIR .. "src/devices/bus/bbc/tube/tube.cpp",
MAME_DIR .. "src/devices/bus/bbc/tube/tube.h",
+ MAME_DIR .. "src/devices/bus/bbc/tube/tube_32016.cpp",
+ MAME_DIR .. "src/devices/bus/bbc/tube/tube_32016.h",
MAME_DIR .. "src/devices/bus/bbc/tube/tube_6502.cpp",
MAME_DIR .. "src/devices/bus/bbc/tube/tube_6502.h",
MAME_DIR .. "src/devices/bus/bbc/tube/tube_80186.cpp",
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index e8084e2a362..8c461e0ce16 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -2835,3 +2835,20 @@ if (CPUS["MEG"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/sound/megd.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/sound/megd.h")
end
+
+--------------------------------------------------
+-- National Semiconductor NS32000 series
+--@src/devices/cpu/ns32000/ns32000.h,CPUS["NS32000"] = true
+--------------------------------------------------
+
+if (CPUS["NS32000"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/cpu/ns32000/ns32000.cpp",
+ MAME_DIR .. "src/devices/cpu/ns32000/ns32000.h",
+ }
+end
+
+if (CPUS["NS32000"]~=null or _OPTIONS["with-tools"]) then
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/ns32000/ns32000dasm.cpp")
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/ns32000/ns32000dasm.h")
+end
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index bfe03e65404..d957b76c9b9 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -137,6 +137,7 @@ CPUS["NANOPROCESSOR"] = true
CPUS["CLIPPER"] = true
CPUS["CAPRICORN"] = true
CPUS["ALPHA"] = true
+CPUS["NS32000"] = true
--CPUS["DSPP"] = true
CPUS["HPC"] = true
CPUS["MEG"] = true
diff --git a/src/devices/bus/bbc/tube/tube.cpp b/src/devices/bus/bbc/tube/tube.cpp
index c0ff49915a6..602ea3c845a 100644
--- a/src/devices/bus/bbc/tube/tube.cpp
+++ b/src/devices/bus/bbc/tube/tube.cpp
@@ -112,6 +112,7 @@ void bbc_tube_slot_device::host_w(offs_t offset, uint8_t data)
// slot devices
+#include "tube_32016.h"
#include "tube_6502.h"
#include "tube_80186.h"
#include "tube_80286.h"
@@ -133,7 +134,7 @@ void bbc_tube_devices(device_slot_interface &device)
{
device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */
device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */
- //device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
+ device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
device.option_add("arm", BBC_TUBE_ARM); /* Acorn ANC13 ARM Evaluation System */
device.option_add("80286", BBC_TUBE_80286); /* Acorn 80286 2nd Processor */
//device.option_add("a500", BBC_TUBE_A500); /* Acorn A500 2nd Processor */
@@ -142,8 +143,8 @@ void bbc_tube_devices(device_slot_interface &device)
//device.option_add("hdp68k", BBC_TUBE_HDP68K); /* Torch Unicorn (HDP68K) */
//device.option_add("x25", BBC_TUBE_X25); /* Econet X25 Gateway */
device.option_add("zep100", BBC_TUBE_ZEP100); /* Torch Z80 Communicator (ZEP100) (Torch) */
- //device.option_add("zep100l", BBC_TUBE_ZEP100L); /* Torch Z80 Communicator (ZEP100) (Acorn 8271) */
- //device.option_add("zep100w", BBC_TUBE_ZEP100W); /* Torch Z80 Communicator (ZEP100) (Acorn 1770) */
+ //device.option_add("zep100l", BBC_TUBE_ZEP100L); /* Torch Z80 Communicator (ZEP100) (Model B) */
+ //device.option_add("zep100w", BBC_TUBE_ZEP100W); /* Torch Z80 Communicator (ZEP100) (Model B+) */
/* Acorn ANC21 Universal 2nd Processor Unit */
device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */
device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */
@@ -160,11 +161,12 @@ void bbc_extube_devices(device_slot_interface &device)
{
device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */
device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */
- //device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
+ device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
device.option_add("arm", BBC_TUBE_ARM); /* Acorn ANC13 ARM Evaluation System */
device.option_add("80286", BBC_TUBE_80286); /* Acorn 80286 2nd Processor */
//device.option_add("a500", BBC_TUBE_A500); /* Acorn A500 2nd Processor */
//device.option_add("pmsb2p", BBC_TUBE_PMSB2P); /* PMS B2P-6502 */
+ //device.option_add("zep100m", BBC_TUBE_ZEP100M); /* Torch Z80 Communicator (ZEP100) (Master) */
/* Acorn ANC21 Universal 2nd Processor Unit */
device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */
device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */
@@ -181,7 +183,6 @@ void bbc_intube_devices(device_slot_interface &device)
{
device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */
device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */
- //device.option_add("zep100m", BBC_TUBE_ZEP100M); /* Torch Z80 Communicator (ZEP100) (Master) */
//device.option_add("arm7", BBC_TUBE_ARM7); /* Sprow ARM7 co-processor */
device.option_add("rc6502", BBC_TUBE_RC6502); /* ReCo6502 (6502) */
device.option_add("rc65816", BBC_TUBE_RC65816); /* ReCo6502 (65816) */
@@ -196,6 +197,7 @@ void electron_tube_devices(device_slot_interface &device)
{
device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */
device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */
+ device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
device.option_add("arm", BBC_TUBE_ARM); /* Acorn ANC13 ARM Evaluation System */
device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */
device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */
diff --git a/src/devices/bus/bbc/tube/tube_32016.cpp b/src/devices/bus/bbc/tube/tube_32016.cpp
new file mode 100644
index 00000000000..7b6ac355e42
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_32016.cpp
@@ -0,0 +1,210 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn ANC05 32016 2nd processor
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC05_320162ndproc.html
+
+ Acorn ANC06 Cambridge Co-Processor
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC06_CamCoPro.html
+
+ IC1 (ULA) TUBE
+ IC2 (MMU) NS32082 Not fitted
+ IC3 (CPU) NS32016
+ IC4 (TCU) NS32201
+ IC20 (FPU) NS32081
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "tube_32016.h"
+#include "softlist_dev.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_TUBE_32016, bbc_tube_32016_device, "bbc_tube_32016", "Acorn 32016 2nd processor")
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( tube_32016_mem )
+//-------------------------------------------------
+
+void bbc_tube_32016_device::tube_32016_mem(address_map &map)
+{
+ map(0x000000, 0xffffff).rw(FUNC(bbc_tube_32016_device::read), FUNC(bbc_tube_32016_device::write));
+ map(0xf90000, 0xf90001).portr("CONFIG");
+ map(0xfffff0, 0xffffff).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask32(0x00ff);
+}
+
+//-------------------------------------------------
+// ROM( tube_32016 )
+//-------------------------------------------------
+
+ROM_START(tube_32016)
+ ROM_REGION(0x8000, "rom", 0)
+ ROM_DEFAULT_BIOS("200")
+ ROM_SYSTEM_BIOS(0, "200", "Pandora v2.00")
+ ROMX_LOAD("pan200lo.rom", 0x0000, 0x4000, CRC(b1980fd0) SHA1(8084f8896cd22953abefbd43c51e1a422b30e28d), ROM_SKIP(1) | ROM_BIOS(0)) // 0201-764-02 Pandora Lo
+ ROMX_LOAD("pan200hi.rom", 0x0001, 0x4000, CRC(cab98d6b) SHA1(dfad1f4180c50757a74fcfe3a0ee7d7b48eb1bee), ROM_SKIP(1) | ROM_BIOS(0)) // 0201-763-02 Pandora Hi
+ ROM_SYSTEM_BIOS(1, "100", "Pandora v1.00")
+ ROMX_LOAD("pan100.rom", 0x0000, 0x8000, BAD_DUMP CRC(75333006) SHA1(996cd120103039390c9b979b16c327bb95da72e4), ROM_BIOS(1)) // 0201-763-01, 0201-764-01 Pandora
+ ROM_SYSTEM_BIOS(2, "061", "Pandora v0.61")
+ ROMX_LOAD("pan061lo.rom", 0x0000, 0x4000, CRC(6f801b35) SHA1(ce31f7c10603f3d15a06a8e32bde40df0639e446), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("pan061hi.rom", 0x0001, 0x4000, CRC(c00b1ab0) SHA1(e6a705232278c518340ddc69ea51af91965fa332), ROM_SKIP(1) | ROM_BIOS(2))
+ROM_END
+
+//-------------------------------------------------
+// INPUT_PORTS( tube_32016 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(tube_32016)
+ PORT_START("CONFIG")
+ PORT_DIPNAME(0x80, 0x80, "H") PORT_DIPLOCATION("LKS:1")
+ PORT_DIPSETTING(0x80, "FPU")
+ PORT_DIPSETTING(0x00, "No FPU")
+
+ PORT_DIPNAME(0x40, 0x00, "G") PORT_DIPLOCATION("LKS:2")
+ PORT_DIPSETTING(0x40, "MMU")
+ PORT_DIPSETTING(0x00, "No MMU")
+
+ PORT_DIPNAME(0x20, 0x00, "F") PORT_DIPLOCATION("LKS:3")
+ PORT_DIPSETTING(0x20, "Reserved")
+ PORT_DIPSETTING(0x00, "Reserved")
+
+ PORT_DIPNAME(0x10, 0x00, "E") PORT_DIPLOCATION("LKS:4")
+ PORT_DIPSETTING(0x10, "Reserved")
+ PORT_DIPSETTING(0x00, "Reserved")
+
+ PORT_DIPNAME(0x08, 0x00, "D") PORT_DIPLOCATION("LKS:5")
+ PORT_DIPSETTING(0x08, "Reserved")
+ PORT_DIPSETTING(0x00, "Reserved")
+
+ PORT_DIPNAME(0x04, 0x00, "C") PORT_DIPLOCATION("LKS:6")
+ PORT_DIPSETTING(0x04, "Reserved")
+ PORT_DIPSETTING(0x00, "Reserved")
+
+ PORT_DIPNAME(0x02, 0x00, "B") PORT_DIPLOCATION("LKS:7")
+ PORT_DIPSETTING(0x02, "Reserved")
+ PORT_DIPSETTING(0x00, "Reserved")
+
+ PORT_DIPNAME(0x01, 0x00, "A") PORT_DIPLOCATION("LKS:8")
+ PORT_DIPSETTING(0x01, "Reserved")
+ PORT_DIPSETTING(0x00, "Reserved")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_tube_32016_device::device_add_mconfig(machine_config &config)
+{
+ NS32016(config, m_maincpu, 12_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_32016_device::tube_32016_mem);
+
+ TUBE(config, m_ula);
+ m_ula->pnmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI);
+ m_ula->pirq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
+
+ /* internal ram */
+ RAM(config, m_ram).set_default_size("1M").set_default_value(0);
+
+ /* software lists */
+ SOFTWARE_LIST(config, "flop_ls_32016").set_original("bbc_flop_32016");
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_tube_32016_device::device_rom_region() const
+{
+ return ROM_NAME( tube_32016 );
+}
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_tube_32016_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( tube_32016 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_tube_32016_device - constructor
+//-------------------------------------------------
+
+bbc_tube_32016_device::bbc_tube_32016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_TUBE_32016, tag, owner, clock)
+ , device_bbc_tube_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_ula(*this, "ula")
+ , m_ram(*this, "ram")
+ , m_rom(*this, "rom")
+ , m_rom_enabled(true)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_tube_32016_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_tube_32016_device::device_reset()
+{
+ m_rom_enabled = true;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_tube_32016_device::host_r(offs_t offset)
+{
+ return m_ula->host_r(offset);
+}
+
+void bbc_tube_32016_device::host_w(offs_t offset, uint8_t data)
+{
+ m_ula->host_w(offset, data);
+}
+
+
+READ8_MEMBER(bbc_tube_32016_device::read)
+{
+ uint16_t data = 0xffff;
+
+ if (m_rom_enabled)
+ data = m_rom->base()[offset & 0x3fff];
+ else if (offset < m_ram->size())
+ data = m_ram->pointer()[offset];
+
+ return data;
+}
+
+WRITE8_MEMBER(bbc_tube_32016_device::write)
+{
+ /* clear ROM select on first write */
+ if (!machine().side_effects_disabled()) m_rom_enabled = false;
+
+ if (offset < m_ram->size())
+ m_ram->pointer()[offset] = data;
+}
diff --git a/src/devices/bus/bbc/tube/tube_32016.h b/src/devices/bus/bbc/tube/tube_32016.h
new file mode 100644
index 00000000000..864b8173703
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_32016.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn ANC05 32016 2nd processor
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC05_320162ndproc.html
+
+ Acorn ANC06 Cambridge Co-Processor
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC06_CamCoPro.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_TUBE_32016_H
+#define MAME_BUS_BBC_TUBE_32016_H
+
+#include "tube.h"
+#include "cpu/ns32000/ns32000.h"
+#include "machine/ram.h"
+#include "machine/tube.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_tube_32016_device
+
+class bbc_tube_32016_device :
+ public device_t,
+ public device_bbc_tube_interface
+{
+public:
+ // construction/destruction
+ bbc_tube_32016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t host_r(offs_t offset) override;
+ virtual void host_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<ns32016_cpu_device> m_maincpu;
+ required_device<tube_device> m_ula;
+ required_device<ram_device> m_ram;
+ required_memory_region m_rom;
+
+ DECLARE_READ8_MEMBER(read);
+ DECLARE_WRITE8_MEMBER(write);
+
+ void tube_32016_mem(address_map &map);
+
+ bool m_rom_enabled;
+};
+
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_TUBE_32016, bbc_tube_32016_device)
+
+
+#endif /* MAME_BUS_BBC_TUBE_32016_H */
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
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 81b9f448140..c668fcba82d 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -99,6 +99,7 @@ using util::BIT;
#include "cpu/mn10200/mn102dis.h"
#include "cpu/nanoprocessor/nanoprocessor_dasm.h"
#include "cpu/nec/necdasm.h"
+#include "cpu/ns32000/ns32000dasm.h"
#include "cpu/nuon/nuondasm.h"
#include "cpu/patinhofeio/patinho_feio_dasm.h"
#include "cpu/pdp1/pdp1dasm.h"
@@ -420,6 +421,7 @@ static const dasm_table_entry dasm_table[] =
{ "mn10200", le, 0, []() -> util::disasm_interface * { return new mn10200_disassembler; } },
{ "nanoprocessor", le, 0, []() -> util::disasm_interface * { return new hp_nanoprocessor_disassembler; } },
{ "nec", le, 0, []() -> util::disasm_interface * { return new nec_disassembler; } },
+ { "ns32000", le, 0, []() -> util::disasm_interface * { return new ns32000_disassembler; } },
{ "nuon", be, 0, []() -> util::disasm_interface * { return new nuon_disassembler; } },
{ "nsc8105", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(8105); } },
{ "patinho_feio", le, 0, []() -> util::disasm_interface * { return new patinho_feio_disassembler; } },