ns32000: Skeleton CPU device with disassembler for NS32000 family.

bbc: Added preliminary Acorn 32016 2nd Processor, incomplete CPU emulation.
This commit is contained in:
Nigel Barnes 2019-03-23 11:55:09 +00:00
parent b445d10135
commit 9e122168ef
11 changed files with 1571 additions and 5 deletions

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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>();
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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; } },