ns32000: add support for ns32532

* refactor slave interfaces
* add crude /rdy emulation
This commit is contained in:
Patrick Mackinlay 2024-02-15 17:57:13 +07:00
parent 61870af881
commit d779f98bcb
10 changed files with 1042 additions and 531 deletions

View File

@ -6,6 +6,64 @@
#pragma once
namespace ns32000
{
enum st_mask : unsigned
{
ST_ICI = 0x0, // bus idle (CPU busy)
ST_ICW = 0x1, // bus idle (CPU wait)
ST_ISE = 0x3, // bus idle (slave execution)
ST_IAM = 0x4, // interrupt acknowledge, master
ST_IAC = 0x5, // interrupt acknowledge, cascaded
ST_EIM = 0x6, // end of interrupt, master
ST_EIC = 0x7, // end of interrupt, cascaded
ST_SIF = 0x8, // sequential instruction fetch
ST_NIF = 0x9, // non-sequential instruction fetch
ST_ODT = 0xa, // operand data transfer
ST_RMW = 0xb, // read RMW operand
ST_EAR = 0xc, // effective address read
ST_SOP = 0xd, // slave operand
ST_SST = 0xe, // slave status
ST_SID = 0xf, // slave ID
ST_PT1 = 0xd, // access pte1 by MMU (32532)
ST_PT2 = 0xe, // access pte2 by MMU (32532)
ST_SLV = 0x10, // slave access ST4 (32532)
};
}
class ns32000_state_interface
{
public:
virtual void state_add(device_state_interface &parent, int &index) = 0;
};
class ns32000_fpu_interface
: public device_interface
, public ns32000_state_interface
{
protected:
ns32000_fpu_interface(machine_config const &mconfig, device_t &device)
: device_interface(device, "ns32000_fpu")
{
}
};
class ns32000_mmu_interface
: public device_interface
, public ns32000_state_interface
{
public:
enum translate_result : unsigned { COMPLETE, CANCEL, ABORT };
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool flag = false, bool suppress = false) = 0;
protected:
ns32000_mmu_interface(machine_config const &mconfig, device_t &device)
: device_interface(device, "ns32000_mmu")
{
}
};
class ns32000_slave_interface : public device_interface
{
public:
@ -19,14 +77,15 @@ public:
enum slave_status : u16
{
SLAVE_Q = 0x0001,
SLAVE_L = 0x0004,
SLAVE_F = 0x0020,
SLAVE_Z = 0x0040,
SLAVE_N = 0x0080,
};
SLAVE_Q = 0x0001, // quit (1=error)
SLAVE_L = 0x0004,
SLAVE_F = 0x0020,
SLAVE_Z = 0x0040,
SLAVE_N = 0x0080,
SLAVE_TS = 0x8000, // trap status (1=UND, 0=FPU)
virtual void state_add(device_state_interface &parent, int &index) = 0;
SLAVE_OK = 0,
};
protected:
ns32000_slave_interface(machine_config const &mconfig, device_t &device, char const *type)
@ -38,19 +97,6 @@ protected:
devcb_write_line m_out_scb;
};
class ns32000_mmu_interface : public ns32000_slave_interface
{
public:
enum translate_result : unsigned { COMPLETE, CANCEL, ABORT };
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs = false, bool debug = false) = 0;
protected:
ns32000_mmu_interface(machine_config const &mconfig, device_t &device)
: ns32000_slave_interface(mconfig, device)
{
}
};
class ns32000_slow_slave_interface : public ns32000_slave_interface
{
public:
@ -69,7 +115,7 @@ protected:
class ns32000_fast_slave_interface : public ns32000_slave_interface
{
public:
virtual u32 read_st(int *icount = nullptr) = 0;
virtual u32 read_st32(int *icount = nullptr) = 0;
virtual u32 read() = 0;
virtual void write(u32 data) = 0;

File diff suppressed because it is too large Load Diff

View File

@ -8,24 +8,23 @@
#include "common.h"
template <int Width>
template <int HighBits, int Width>
class ns32000_device : public cpu_device
{
public:
template <typename T> void set_fpu(T &&tag) { m_fpu.set_tag(std::forward<T>(tag)); }
template <typename T> void set_mmu(T &&tag) { m_mmu.set_tag(std::forward<T>(tag)); }
// construction/destruction
ns32000_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
void rdy_w(int state) { m_ready = !state; }
protected:
ns32000_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, int databits, int addrbits);
ns32000_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
// device_t overrides
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
// device_execute_interface overrides
// device_execute_interface implementation
virtual u32 execute_min_cycles() const noexcept override { return 1; }
virtual u32 execute_max_cycles() const noexcept override { return 6; }
virtual u32 execute_input_lines() const noexcept override { return 2; }
@ -33,14 +32,14 @@ protected:
virtual void execute_set_input(int inputnum, int state) override;
virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return inputnum == INPUT_LINE_NMI; }
// device_memory_interface overrides
// device_memory_interface implementation
virtual space_config_vector memory_space_config() const override;
virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
// device_state_interface overrides
// device_state_interface implementation
virtual void state_string_export(device_state_entry const &entry, std::string &str) const override;
// device_disasm_interface overrides
// device_disasm_interface implementation
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
enum addr_mode_type : unsigned
@ -133,16 +132,27 @@ protected:
s64 gen_read_sx(addr_mode mode);
void gen_write(addr_mode mode, u64 data);
// register helpers
u32 &SP();
u32 &SP(bool user);
virtual u32 const PSR_MSK() { return 0x0fe7; }
// other execution helpers
bool condition(unsigned const cc);
void flags(u32 const src1, u32 const src2, u32 const dest, unsigned const size, bool const subtraction);
void interrupt(unsigned const type, u32 const return_address);
void interrupt(unsigned const type);
virtual void lpr(unsigned reg, addr_mode const mode, bool user, unsigned &tex);
virtual void spr(unsigned reg, addr_mode const mode, bool user, unsigned &tex);
// slave protocol helpers
u16 slave(u8 opbyte, u16 opword, addr_mode op1, addr_mode op2);
virtual u16 slave(u8 opbyte, u16 opword, addr_mode op1, addr_mode op2);
u16 slave_slow(ns32000_slow_slave_interface &slave, u8 opbyte, u16 opword, addr_mode op1, addr_mode op2);
u16 slave_fast(ns32000_fast_slave_interface &slave, u8 opbyte, u16 opword, addr_mode op1, addr_mode op2);
u32 m_cfg; // configuration register
typename memory_access<HighBits, Width, 0, ENDIANNESS_LITTLE>::specific m_bus[16];
private:
u32 const m_address_mask;
@ -158,14 +168,12 @@ private:
address_space_config m_rmw_config;
address_space_config m_ear_config;
optional_device<ns32000_slave_interface> m_fpu;
optional_device<ns32000_fpu_interface> m_fpu;
optional_device<ns32000_mmu_interface> m_mmu;
// emulation state
int m_icount;
typename memory_access<24, Width, 0, ENDIANNESS_LITTLE>::specific m_bus[16];
u32 m_ssp; // saved stack pointer
u16 m_sps; // saved program status
@ -177,44 +185,85 @@ private:
u32 m_intbase; // interrupt base
u16 m_psr; // processor status
u16 m_mod; // module
u8 m_cfg; // configuration
u32 m_r[8];
u32 m_f[8];
bool m_nmi_line;
bool m_int_line;
bool m_wait;
bool m_sequential;
bool m_ready;
};
class ns32008_device : public ns32000_device<0>
class ns32008_device : public ns32000_device<24, 0>
{
public:
ns32008_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
};
class ns32016_device : public ns32000_device<1>
class ns32016_device : public ns32000_device<24, 1>
{
public:
ns32016_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
};
class ns32032_device : public ns32000_device<2>
class ns32032_device : public ns32000_device<24, 2>
{
public:
ns32032_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
};
class ns32332_device : public ns32000_device<2>
class ns32332_device : public ns32000_device<32, 2>
{
public:
ns32332_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
};
class ns32532_device
: public ns32000_device<32, 2>
, public ns32000_mmu_interface
{
public:
ns32532_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
// ns32000_mmu_interface implementation
virtual void state_add(device_state_interface &parent, int &index) override;
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool rdwrval = false, bool suppress = false) override;
protected:
// device_t implementation
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_reset() override;
// device_memory_interface implementation
virtual space_config_vector memory_space_config() const override;
virtual u32 const PSR_MSK() override { return 0x0ff7; }
virtual void lpr(unsigned reg, addr_mode const mode, bool user, unsigned &tex) override;
virtual void spr(unsigned reg, addr_mode const mode, bool user, unsigned &tex) override;
virtual u16 slave(u8 opbyte, u16 opword, addr_mode op1, addr_mode op2) override;
private:
address_space_config m_pt1_config;
address_space_config m_pt2_config;
// memory management registers
u32 m_ptb[2]; // page table base pointer
u32 m_tear; // translation exception address
u32 m_mcr; // memory management control
u32 m_msr; // memory management status
// debug registers
u32 m_dcr; // debug condition
u32 m_dsr; // debug status
u32 m_car; // compare address
u32 m_bpc; // breakpoint program counter
};
DECLARE_DEVICE_TYPE(NS32008, ns32008_device)
DECLARE_DEVICE_TYPE(NS32016, ns32016_device)
DECLARE_DEVICE_TYPE(NS32032, ns32032_device)
DECLARE_DEVICE_TYPE(NS32332, ns32332_device)
DECLARE_DEVICE_TYPE(NS32532, ns32532_device)
#endif // MAME_CPU_NS32000_NS32000_H

View File

@ -21,19 +21,19 @@ s32 ns32000_disassembler::displacement(offs_t pc, data_buffer const &opcodes, un
u32 const byte2 = opcodes.r8(pc + bytes++);
u32 const byte3 = opcodes.r8(pc + bytes++);
return (s32((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3) << 2) >> 2;
return util::sext((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3, 30);
}
else
{
// word displacement
u8 const byte1 = opcodes.r8(pc + bytes++);
return s16(((byte0 << 8) | byte1) << 2) >> 2;
return util::sext((byte0 << 8) | byte1, 14);
}
}
else
// byte displacement
return s8(byte0 << 1) >> 1;
return util::sext(byte0, 7);
}
std::string ns32000_disassembler::displacement_string(offs_t pc, data_buffer const &opcodes, unsigned &bytes, std::string const zero)

View File

@ -2,13 +2,13 @@
// copyright-holders:Patrick Mackinlay
/*
* National Semiconductor 32081 Floating-Point Unit.
* National Semiconductor NS32081 Floating-Point Unit.
*
* Sources:
* - Microprocessor Databook, Series 32000, NSC800, 1989 Edition, National Semiconductor
*
* TODO:
* - testing
* - NS32381
*/
#include "emu.h"
@ -20,7 +20,7 @@
#include "logmacro.h"
DEFINE_DEVICE_TYPE(NS32081, ns32081_device, "ns32081", "National Semiconductor 32081 Floating-Point Unit")
DEFINE_DEVICE_TYPE(NS32081, ns32081_device, "ns32081", "National Semiconductor NS32081 Floating-Point Unit")
enum fsr_mask : u32
{
@ -83,6 +83,7 @@ enum size_code : unsigned
ns32081_device::ns32081_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, NS32081, tag, owner, clock)
, ns32000_slow_slave_interface(mconfig, *this)
, ns32000_fpu_interface(mconfig, *this)
{
}

View File

@ -11,6 +11,7 @@
class ns32081_device
: public device_t
, public ns32000_slow_slave_interface
, public ns32000_fpu_interface
{
public:
ns32081_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
@ -24,7 +25,7 @@ public:
virtual void write_op(u16 data) override;
protected:
// device_t overrides
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;

View File

@ -2,7 +2,7 @@
// copyright-holders:Patrick Mackinlay
/*
* National Semiconductor 32082 Memory Management Unit.
* National Semiconductor NS32082 Memory Management Unit.
*
* Sources:
* - Microprocessor Databook, Series 32000, NSC800, 1989 Edition, National Semiconductor
@ -21,7 +21,7 @@
#include "logmacro.h"
DEFINE_DEVICE_TYPE(NS32082, ns32082_device, "ns32082", "National Semiconductor 32082 Memory Management Unit")
DEFINE_DEVICE_TYPE(NS32082, ns32082_device, "ns32082", "National Semiconductor NS32082 Memory Management Unit")
enum state : unsigned
{
@ -125,25 +125,6 @@ enum eia_mask : u32
EIA_AS = 0x80000000, // address space
};
enum st_mask : unsigned
{
ST_ICI = 0x0, // bus idle (CPU busy)
ST_ICW = 0x1, // bus idle (CPU wait)
ST_ISE = 0x3, // bus idle (slave execution)
ST_IAM = 0x4, // interrupt acknowledge, master
ST_IAC = 0x5, // interrupt acknowledge, cascaded
ST_EIM = 0x6, // end of interrupt, master
ST_EIC = 0x7, // end of interrupt, cascaded
ST_SIF = 0x8, // sequential instruction fetch
ST_NIF = 0x9, // non-sequential instruction fetch
ST_ODT = 0xa, // operand data transfer
ST_RMW = 0xb, // read RMW operand
ST_EAR = 0xc, // effective address read
ST_SOP = 0xd, // slave operand
ST_SST = 0xe, // slave status
ST_SID = 0xf, // slave ID
};
ns32082_device::ns32082_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, NS32082, tag, owner, clock)
, ns32000_slow_slave_interface(mconfig, *this)
@ -402,12 +383,12 @@ void ns32082_device::set_msr(u32 data)
m_msr = (m_msr & ~MSR_WM) | (data & MSR_WM);
}
ns32082_device::translate_result ns32082_device::translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs, bool debug)
ns32082_device::translate_result ns32082_device::translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs, bool suppress)
{
// update program flow trace state
if (pfs && (m_msr & MSR_FT))
{
if (st == ST_NIF)
if (st == ns32000::ST_NIF)
{
m_pf[1] = m_pf[0];
m_pf[0] = address;
@ -427,7 +408,7 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space,
bool const address_space = (m_msr & MSR_DS) && user;
unsigned const access_level = (user && !(m_msr & MSR_AO))
? ((write || st == ST_RMW) ? PL_URW : PL_URO) : ((write || st == ST_RMW) ? PL_SRW : PL_SRO);
? ((write || st == ns32000::ST_RMW) ? PL_URW : PL_URO) : ((write || st == ns32000::ST_RMW) ? PL_SRW : PL_SRO);
u32 const ptb = ((m_ptb[address_space] & PTB_MS) >> 7) | (m_ptb[address_space] & PTB_AB);
@ -440,7 +421,7 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space,
if (access_level > (pte1 & PTE_PL) || !(pte1 & PTE_V))
{
if (m_state == IDLE && !debug)
if (m_state == IDLE && !suppress)
{
// reset error status
m_msr &= ~(MSR_EST | MSR_ED | MSR_TET | MSR_TE);
@ -472,7 +453,7 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space,
}
// set referenced
if (!(pte1 & PTE_R) && !debug)
if (!(pte1 & PTE_R) && !suppress)
space.write_word(pte1_address, u16(pte1 | PTE_R));
// read level 2 page table entry
@ -482,7 +463,7 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space,
if (access_level > (pte2 & PTE_PL) || !(pte2 & PTE_V))
{
if (m_state == IDLE && !debug)
if (m_state == IDLE && !suppress)
{
// reset error status
m_msr &= ~(MSR_EST | MSR_ED | MSR_TET | MSR_TE);
@ -512,7 +493,7 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space,
}
// set modified and referenced
if ((!(pte2 & PTE_R) || (write && !(pte2 & PTE_M))) && !debug)
if ((!(pte2 & PTE_R) || (write && !(pte2 & PTE_M))) && !suppress)
space.write_word(pte2_address, u16(pte2 | (write ? PTE_M : 0) | PTE_R));
address = ((pte1 & PTE_MS) >> 7) | (pte2 & PTE_PFN) | (address & VA_OFFSET);

View File

@ -24,7 +24,7 @@ public:
virtual void write_id(u16 data) override;
virtual void write_op(u16 data) override;
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs = false, bool debug = false) override;
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs = false, bool suppress = false) override;
protected:
// device_t overrides

View File

@ -123,25 +123,6 @@ enum va_mask : u32
VA_OFFSET = 0x00000fff,
};
enum st_mask : unsigned
{
ST_ICI = 0x0, // bus idle (CPU busy)
ST_ICW = 0x1, // bus idle (CPU wait)
ST_ISE = 0x3, // bus idle (slave execution)
ST_IAM = 0x4, // interrupt acknowledge, master
ST_IAC = 0x5, // interrupt acknowledge, cascaded
ST_EIM = 0x6, // end of interrupt, master
ST_EIC = 0x7, // end of interrupt, cascaded
ST_SIF = 0x8, // sequential instruction fetch
ST_NIF = 0x9, // non-sequential instruction fetch
ST_ODT = 0xa, // operand data transfer
ST_RMW = 0xb, // read RMW operand
ST_EAR = 0xc, // effective address read
ST_SOP = 0xd, // slave operand
ST_SST = 0xe, // slave status
ST_SID = 0xf, // slave ID
};
ns32382_device::ns32382_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, NS32382, tag, owner, clock)
, ns32000_fast_slave_interface(mconfig, *this)
@ -184,7 +165,7 @@ void ns32382_device::state_add(device_state_interface &parent, int &index)
parent.state_add(index++, "MSR", m_msr).formatstr("%08X");
}
u32 ns32382_device::read_st(int *icount)
u32 ns32382_device::read_st32(int *icount)
{
if (m_state == STATUS)
{
@ -363,7 +344,7 @@ ns32382_device::translate_result ns32382_device::translate(address_space &space,
bool const address_space = (m_mcr & MCR_DS) && user;
unsigned const access_level = (user && !(m_mcr & MCR_AO))
? ((write || st == ST_RMW) ? PL_URW : PL_URO) : ((write || st == ST_RMW) ? PL_SRW : PL_SRO);
? ((write || st == ns32000::ST_RMW) ? PL_URW : PL_URO) : ((write || st == ns32000::ST_RMW) ? PL_SRW : PL_SRO);
if (m_state == IDLE && !debug)
m_msr &= ~(MSR_STT | MSR_UST | MSR_DDT | MSR_TEX);

View File

@ -20,7 +20,7 @@ public:
virtual void state_add(device_state_interface &parent, int &index) override;
// ns32000_fast_slave_interface overrides
virtual u32 read_st(int *icount = nullptr) override;
virtual u32 read_st32(int *icount = nullptr) override;
virtual void write(u32 data) override;
virtual u32 read() override;