mirror of
https://github.com/holub/mame
synced 2025-10-04 08:28:39 +03:00
ns32000: Skeleton CPU device with disassembler for NS32000 family.
bbc: Added preliminary Acorn 32016 2nd Processor, incomplete CPU emulation.
This commit is contained in:
parent
b445d10135
commit
9e122168ef
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
210
src/devices/bus/bbc/tube/tube_32016.cpp
Normal file
210
src/devices/bus/bbc/tube/tube_32016.cpp
Normal 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;
|
||||
}
|
71
src/devices/bus/bbc/tube/tube_32016.h
Normal file
71
src/devices/bus/bbc/tube/tube_32016.h
Normal 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 */
|
160
src/devices/cpu/ns32000/ns32000.cpp
Normal file
160
src/devices/cpu/ns32000/ns32000.cpp
Normal 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>();
|
||||
}
|
149
src/devices/cpu/ns32000/ns32000.h
Normal file
149
src/devices/cpu/ns32000/ns32000.h
Normal 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
|
834
src/devices/cpu/ns32000/ns32000dasm.cpp
Normal file
834
src/devices/cpu/ns32000/ns32000dasm.cpp
Normal 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 ¶ms)
|
||||
{
|
||||
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;
|
||||
}
|
118
src/devices/cpu/ns32000/ns32000dasm.h
Normal file
118
src/devices/cpu/ns32000/ns32000dasm.h
Normal 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 ¶ms) 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
|
@ -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; } },
|
||||
|
Loading…
Reference in New Issue
Block a user