mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
pc532: add floating-point unit
* ns32381: add new device * ns32k: refactor slave interface * ns32k: fix format 9 instruction decoding
This commit is contained in:
parent
bdda7084bb
commit
ca431df745
@ -32,38 +32,6 @@ namespace ns32000
|
||||
};
|
||||
}
|
||||
|
||||
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:
|
||||
@ -75,6 +43,14 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
enum slave_idbyte : u8
|
||||
{
|
||||
FORMAT_9 = 0x3e, // fpu
|
||||
FORMAT_11 = 0xbe, // fpu
|
||||
FORMAT_12 = 0xfe, // fpu
|
||||
FORMAT_14 = 0x1e, // mmu
|
||||
};
|
||||
|
||||
enum slave_status : u16
|
||||
{
|
||||
SLAVE_Q = 0x0001, // quit (1=error)
|
||||
@ -87,6 +63,8 @@ public:
|
||||
SLAVE_OK = 0,
|
||||
};
|
||||
|
||||
virtual void state_add(device_state_interface &parent, int &index) = 0;
|
||||
|
||||
protected:
|
||||
ns32000_slave_interface(machine_config const &mconfig, device_t &device, char const *type)
|
||||
: device_interface(device, type)
|
||||
@ -97,31 +75,52 @@ protected:
|
||||
devcb_write_line m_out_scb;
|
||||
};
|
||||
|
||||
class ns32000_slow_slave_interface : public ns32000_slave_interface
|
||||
class ns32000_fpu_interface : public ns32000_slave_interface
|
||||
{
|
||||
public:
|
||||
virtual void write_id(u16 data) = 0;
|
||||
virtual void write_op(u16 data) = 0;
|
||||
virtual u16 read_st(int *icount = nullptr) = 0;
|
||||
virtual u16 read_op() = 0;
|
||||
|
||||
protected:
|
||||
ns32000_slow_slave_interface(machine_config const &mconfig, device_t &device)
|
||||
ns32000_fpu_interface(machine_config const &mconfig, device_t &device)
|
||||
: ns32000_slave_interface(mconfig, device)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class ns32000_fast_slave_interface : public ns32000_slave_interface
|
||||
class ns32000_mmu_interface : public ns32000_slave_interface
|
||||
{
|
||||
public:
|
||||
virtual u32 read_st32(int *icount = nullptr) = 0;
|
||||
virtual u32 read() = 0;
|
||||
virtual void write(u32 data) = 0;
|
||||
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)
|
||||
: ns32000_slave_interface(mconfig, device)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class ns32000_slow_slave_interface : public device_interface
|
||||
{
|
||||
public:
|
||||
virtual u16 slow_status(int *icount = nullptr) = 0;
|
||||
virtual u16 slow_read() = 0;
|
||||
virtual void slow_write(u16 data) = 0;
|
||||
|
||||
protected:
|
||||
ns32000_slow_slave_interface(machine_config const &mconfig, device_t &device)
|
||||
: device_interface(device, "ns32000_slave_slow")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class ns32000_fast_slave_interface : public device_interface
|
||||
{
|
||||
public:
|
||||
virtual u32 fast_status(int *icount = nullptr) = 0;
|
||||
virtual u32 fast_read() = 0;
|
||||
virtual void fast_write(u32 data) = 0;
|
||||
|
||||
protected:
|
||||
ns32000_fast_slave_interface(machine_config const &mconfig, device_t &device)
|
||||
: ns32000_slave_interface(mconfig, device)
|
||||
: device_interface(device, "ns32000_slave_fast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -3128,14 +3128,14 @@ template <int HighBits, int Width> void ns32000_device<HighBits, Width>::execute
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x3e:
|
||||
case ns32000_slave_interface::FORMAT_9:
|
||||
// format 9: xxxx xyyy yyoo ofii 0011 1110
|
||||
if (m_cfg & CFG_F)
|
||||
{
|
||||
u16 const opword = fetch<u16>(bytes);
|
||||
|
||||
addr_mode mode[] = { addr_mode(BIT(opword, 11, 5)), addr_mode(BIT(opword, 6, 5)) };
|
||||
size_code const size_f = BIT(opword, 0) ? SIZE_D : SIZE_Q;
|
||||
size_code const size_f = BIT(opword, 2) ? SIZE_D : SIZE_Q;
|
||||
size_code const size = size_code(opword & 3);
|
||||
|
||||
switch (BIT(opword, 3, 3))
|
||||
@ -3234,7 +3234,7 @@ template <int HighBits, int Width> void ns32000_device<HighBits, Width>::execute
|
||||
case 0x7e: // format 10
|
||||
interrupt(UND);
|
||||
break;
|
||||
case 0xbe:
|
||||
case ns32000_slave_interface::FORMAT_11:
|
||||
// format 11: xxxx xyyy yyoo oo0f 1011 1110
|
||||
if (m_cfg & CFG_F)
|
||||
{
|
||||
@ -3366,7 +3366,7 @@ template <int HighBits, int Width> void ns32000_device<HighBits, Width>::execute
|
||||
else
|
||||
interrupt(UND);
|
||||
break;
|
||||
case 0xfe:
|
||||
case ns32000_slave_interface::FORMAT_12:
|
||||
// format 12: xxxx xyyy yyoo oo0f 1111 1110
|
||||
if ((m_cfg & CFG_F) && type() == NS32332)
|
||||
{
|
||||
@ -3459,7 +3459,7 @@ template <int HighBits, int Width> void ns32000_device<HighBits, Width>::execute
|
||||
case 0x9e: // format 13
|
||||
interrupt(UND);
|
||||
break;
|
||||
case 0x1e:
|
||||
case ns32000_slave_interface::FORMAT_14:
|
||||
// format 14: xxxx xsss s0oo ooii 0001 1110
|
||||
if (!(m_psr & PSR_U))
|
||||
{
|
||||
@ -3671,7 +3671,7 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave(u8
|
||||
{
|
||||
switch (opbyte)
|
||||
{
|
||||
case 0x1e:
|
||||
case ns32000_slave_interface::FORMAT_14:
|
||||
if (!m_mmu)
|
||||
fatalerror("slave mmu coprocessor not configured (%s)\n", machine().describe_context());
|
||||
|
||||
@ -3681,9 +3681,9 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave(u8
|
||||
return slave_slow(dynamic_cast<ns32000_slow_slave_interface &>(*m_mmu), opbyte, opword, op1, op2);
|
||||
break;
|
||||
|
||||
case 0x3e:
|
||||
case 0xbe:
|
||||
case 0xfe:
|
||||
case ns32000_slave_interface::FORMAT_9:
|
||||
case ns32000_slave_interface::FORMAT_11:
|
||||
case ns32000_slave_interface::FORMAT_12:
|
||||
if (!m_fpu)
|
||||
fatalerror("slave fpu coprocessor not configured (%s)\n", machine().describe_context());
|
||||
|
||||
@ -3701,8 +3701,8 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave(u8
|
||||
|
||||
template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_slow(ns32000_slow_slave_interface &slave, u8 opbyte, u16 opword, addr_mode op1, addr_mode op2)
|
||||
{
|
||||
slave.write_id(opbyte);
|
||||
slave.write_op(swapendian_int16(opword));
|
||||
slave.slow_write(opbyte);
|
||||
slave.slow_write(swapendian_int16(opword));
|
||||
|
||||
if ((op1.access == READ || op1.access == RMW) && !(op1.type == REG && op1.slave))
|
||||
{
|
||||
@ -3711,20 +3711,20 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_sl
|
||||
switch (op1.size)
|
||||
{
|
||||
case SIZE_B:
|
||||
slave.write_op(u8(data));
|
||||
slave.slow_write(u8(data));
|
||||
break;
|
||||
case SIZE_W:
|
||||
slave.write_op(u16(data));
|
||||
slave.slow_write(u16(data));
|
||||
break;
|
||||
case SIZE_D:
|
||||
slave.write_op(u16(data >> 0));
|
||||
slave.write_op(u16(data >> 16));
|
||||
slave.slow_write(u16(data >> 0));
|
||||
slave.slow_write(u16(data >> 16));
|
||||
break;
|
||||
case SIZE_Q:
|
||||
slave.write_op(u16(data >> 0));
|
||||
slave.write_op(u16(data >> 16));
|
||||
slave.write_op(u16(data >> 32));
|
||||
slave.write_op(u16(data >> 48));
|
||||
slave.slow_write(u16(data >> 0));
|
||||
slave.slow_write(u16(data >> 16));
|
||||
slave.slow_write(u16(data >> 32));
|
||||
slave.slow_write(u16(data >> 48));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3732,8 +3732,8 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_sl
|
||||
{
|
||||
u32 const data = ea(op1);
|
||||
|
||||
slave.write_op(u16(data >> 0));
|
||||
slave.write_op(u16(data >> 16));
|
||||
slave.slow_write(u16(data >> 0));
|
||||
slave.slow_write(u16(data >> 16));
|
||||
|
||||
// single-byte memory read cycle
|
||||
mem_read<u8>(ns32000::ST_ODT, data, true);
|
||||
@ -3746,41 +3746,41 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_sl
|
||||
switch (op2.size)
|
||||
{
|
||||
case SIZE_B:
|
||||
slave.write_op(u8(data));
|
||||
slave.slow_write(u8(data));
|
||||
break;
|
||||
case SIZE_W:
|
||||
slave.write_op(u16(data));
|
||||
slave.slow_write(u16(data));
|
||||
break;
|
||||
case SIZE_D:
|
||||
slave.write_op(u16(data >> 0));
|
||||
slave.write_op(u16(data >> 16));
|
||||
slave.slow_write(u16(data >> 0));
|
||||
slave.slow_write(u16(data >> 16));
|
||||
break;
|
||||
case SIZE_Q:
|
||||
slave.write_op(u16(data >> 0));
|
||||
slave.write_op(u16(data >> 16));
|
||||
slave.write_op(u16(data >> 32));
|
||||
slave.write_op(u16(data >> 48));
|
||||
slave.slow_write(u16(data >> 0));
|
||||
slave.slow_write(u16(data >> 16));
|
||||
slave.slow_write(u16(data >> 32));
|
||||
slave.slow_write(u16(data >> 48));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u16 const status = slave.read_st(&m_icount);
|
||||
u16 const status = slave.slow_status(&m_icount);
|
||||
|
||||
if (!(status & ns32000_slave_interface::SLAVE_Q))
|
||||
{
|
||||
if ((op2.access == WRITE || op2.access == RMW) && !(op2.type == REG && op2.slave))
|
||||
{
|
||||
u64 data = slave.read_op();
|
||||
u64 data = slave.slow_read();
|
||||
|
||||
switch (op2.size)
|
||||
{
|
||||
case SIZE_D:
|
||||
data |= u64(slave.read_op()) << 16;
|
||||
data |= u64(slave.slow_read()) << 16;
|
||||
break;
|
||||
case SIZE_Q:
|
||||
data |= u64(slave.read_op()) << 16;
|
||||
data |= u64(slave.read_op()) << 32;
|
||||
data |= u64(slave.read_op()) << 48;
|
||||
data |= u64(slave.slow_read()) << 16;
|
||||
data |= u64(slave.slow_read()) << 32;
|
||||
data |= u64(slave.slow_read()) << 48;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -3795,7 +3795,7 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_sl
|
||||
|
||||
template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_fast(ns32000_fast_slave_interface &slave, u8 opbyte, u16 opword, addr_mode op1, addr_mode op2)
|
||||
{
|
||||
slave.write(u32(opbyte) << 24 | u32(swapendian_int16(opword)) << 8);
|
||||
slave.fast_write(u32(opbyte) << 24 | u32(swapendian_int16(opword)) << 8);
|
||||
|
||||
if ((op1.access == READ || op1.access == RMW) && !(op1.type == REG && op1.slave))
|
||||
{
|
||||
@ -3804,17 +3804,17 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_fa
|
||||
switch (op1.size)
|
||||
{
|
||||
case SIZE_B:
|
||||
slave.write(u8(data));
|
||||
slave.fast_write(u8(data));
|
||||
break;
|
||||
case SIZE_W:
|
||||
slave.write(u16(data));
|
||||
slave.fast_write(u16(data));
|
||||
break;
|
||||
case SIZE_D:
|
||||
slave.write(u32(data));
|
||||
slave.fast_write(u32(data));
|
||||
break;
|
||||
case SIZE_Q:
|
||||
slave.write(u32(data >> 0));
|
||||
slave.write(u32(data >> 32));
|
||||
slave.fast_write(u32(data >> 0));
|
||||
slave.fast_write(u32(data >> 32));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3822,7 +3822,7 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_fa
|
||||
{
|
||||
u32 const data = ea(op1);
|
||||
|
||||
slave.write(u32(data));
|
||||
slave.fast_write(u32(data));
|
||||
|
||||
// single-byte memory read cycle
|
||||
mem_read<u8>(ns32000::ST_ODT, data, true);
|
||||
@ -3835,32 +3835,32 @@ template <int HighBits, int Width> u16 ns32000_device<HighBits, Width>::slave_fa
|
||||
switch (op2.size)
|
||||
{
|
||||
case SIZE_B:
|
||||
slave.write(u8(data));
|
||||
slave.fast_write(u8(data));
|
||||
break;
|
||||
case SIZE_W:
|
||||
slave.write(u16(data));
|
||||
slave.fast_write(u16(data));
|
||||
break;
|
||||
case SIZE_D:
|
||||
slave.write(u32(data));
|
||||
slave.fast_write(u32(data));
|
||||
break;
|
||||
case SIZE_Q:
|
||||
slave.write(u32(data >> 0));
|
||||
slave.write(u32(data >> 32));
|
||||
slave.fast_write(u32(data >> 0));
|
||||
slave.fast_write(u32(data >> 32));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: status is optional in fast protocol
|
||||
u32 const status = slave.read_st32(&m_icount);
|
||||
u32 const status = slave.fast_status(&m_icount);
|
||||
|
||||
if (!(status & ns32000_slave_interface::SLAVE_Q))
|
||||
{
|
||||
if ((op2.access == WRITE || op2.access == RMW) && !(op2.type == REG && op2.slave))
|
||||
{
|
||||
u64 data = slave.read();
|
||||
u64 data = slave.fast_read();
|
||||
|
||||
if (op2.size == SIZE_Q)
|
||||
data |= u64(slave.read()) << 32;
|
||||
data |= u64(slave.fast_read()) << 32;
|
||||
|
||||
gen_write(op2, data);
|
||||
}
|
||||
@ -4162,7 +4162,7 @@ void ns32532_device::spr(unsigned reg, addr_mode const mode, bool user, unsigned
|
||||
|
||||
u16 ns32532_device::slave(u8 opbyte, u16 opword, addr_mode op1, addr_mode op2)
|
||||
{
|
||||
if (opbyte == 0x1e)
|
||||
if (opbyte == FORMAT_14)
|
||||
{
|
||||
switch (BIT(opword, 2, 4))
|
||||
{
|
||||
|
@ -461,7 +461,7 @@ offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, data_b
|
||||
u16 const opword = opcodes.r16(pc + bytes); bytes += 2;
|
||||
|
||||
addr_mode mode[] = { addr_mode(BIT(opword, 11, 5)), addr_mode(BIT(opword, 6, 5)) };
|
||||
size_code const size_f = BIT(opword, 0) ? SIZE_D : SIZE_Q;
|
||||
size_code const size_f = BIT(opword, 2) ? SIZE_D : SIZE_Q;
|
||||
size_code const size = size_code(opword & 3);
|
||||
|
||||
switch (BIT(opword, 3, 3))
|
||||
@ -473,7 +473,7 @@ offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, data_b
|
||||
mode[0].size_i(size);
|
||||
mode[1].size_f(size_f);
|
||||
decode(mode, pc, opcodes, bytes);
|
||||
util::stream_format(stream, "MOV%c%c %s, %s", size_char[size], BIT(opword, 0) ? 'F' : 'L', mode[0].mode, mode[1].mode);
|
||||
util::stream_format(stream, "MOV%c%c %s, %s", size_char[size], BIT(opword, 2) ? 'F' : 'L', mode[0].mode, mode[1].mode);
|
||||
break;
|
||||
case 1:
|
||||
// LFSR src
|
||||
@ -508,7 +508,7 @@ offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, data_b
|
||||
mode[0].size_f(size_f);
|
||||
mode[1].size_i(size);
|
||||
decode(mode, pc, opcodes, bytes);
|
||||
util::stream_format(stream, "ROUND%c%c %s, %s", BIT(opword, 0) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode);
|
||||
util::stream_format(stream, "ROUND%c%c %s, %s", BIT(opword, 2) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode);
|
||||
break;
|
||||
case 5:
|
||||
// TRUNCfi src,dst
|
||||
@ -517,7 +517,7 @@ offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, data_b
|
||||
mode[0].size_f(size_f);
|
||||
mode[1].size_i(size);
|
||||
decode(mode, pc, opcodes, bytes);
|
||||
util::stream_format(stream, "TRUNC%c%c %s, %s", BIT(opword, 0) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode);
|
||||
util::stream_format(stream, "TRUNC%c%c %s, %s", BIT(opword, 2) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode);
|
||||
break;
|
||||
case 6:
|
||||
// SFSR dst
|
||||
@ -534,7 +534,7 @@ offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, data_b
|
||||
mode[0].size_f(size_f);
|
||||
mode[1].size_i(size);
|
||||
decode(mode, pc, opcodes, bytes);
|
||||
util::stream_format(stream, "FLOOR%c%c %s, %s", BIT(opword, 0) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode);
|
||||
util::stream_format(stream, "FLOOR%c%c %s, %s", BIT(opword, 2) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,9 @@
|
||||
* - Microprocessor Databook, Series 32000, NSC800, 1989 Edition, National Semiconductor
|
||||
*
|
||||
* TODO:
|
||||
* - NS32381
|
||||
* - poly/scalb/logb/dot
|
||||
* - ns32381 timing
|
||||
* - no-result operations
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -21,6 +23,7 @@
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(NS32081, ns32081_device, "ns32081", "National Semiconductor NS32081 Floating-Point Unit")
|
||||
DEFINE_DEVICE_TYPE(NS32381, ns32381_device, "ns32381", "National Semiconductor NS32381 Floating-Point Unit")
|
||||
|
||||
enum fsr_mask : u32
|
||||
{
|
||||
@ -31,6 +34,7 @@ enum fsr_mask : u32
|
||||
FSR_IF = 0x00000040, // inexact result flag
|
||||
FSR_RM = 0x00000180, // rounding mode
|
||||
FSR_SWF = 0x0000fe00, // software field
|
||||
FSR_RMB = 0x00010000, // (32381 only) register modify bit
|
||||
};
|
||||
|
||||
enum rm_mask : u32
|
||||
@ -61,132 +65,141 @@ enum state : unsigned
|
||||
RESULT = 5, // result word available
|
||||
};
|
||||
|
||||
enum idbyte : u8
|
||||
{
|
||||
FORMAT_9 = 0x3e,
|
||||
FORMAT_11 = 0xbe,
|
||||
};
|
||||
|
||||
enum operand_length : unsigned
|
||||
{
|
||||
LENGTH_F = 4, // single precision
|
||||
LENGTH_L = 8, // double precision
|
||||
};
|
||||
|
||||
enum size_code : unsigned
|
||||
{
|
||||
SIZE_B = 0,
|
||||
SIZE_W = 1,
|
||||
SIZE_D = 3,
|
||||
};
|
||||
|
||||
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)
|
||||
ns32081_device_base::ns32081_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, ns32000_fpu_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
void ns32081_device::device_start()
|
||||
void ns32081_device_base::device_start()
|
||||
{
|
||||
save_item(NAME(m_fsr));
|
||||
save_item(NAME(m_f));
|
||||
|
||||
save_item(NAME(m_state));
|
||||
save_item(NAME(m_idbyte));
|
||||
save_item(NAME(m_opword));
|
||||
|
||||
save_item(STRUCT_MEMBER(m_op, expected));
|
||||
save_item(STRUCT_MEMBER(m_op, issued));
|
||||
save_item(STRUCT_MEMBER(m_op, value));
|
||||
save_item(NAME(m_status));
|
||||
|
||||
save_item(NAME(m_state));
|
||||
save_item(NAME(m_status));
|
||||
save_item(NAME(m_tcy));
|
||||
|
||||
m_complete = timer_alloc(FUNC(ns32081_device::complete), this);
|
||||
}
|
||||
|
||||
void ns32081_device::device_reset()
|
||||
void ns32081_device_base::device_reset()
|
||||
{
|
||||
m_fsr = 0;
|
||||
std::fill(std::begin(m_f), std::end(m_f), 0);
|
||||
|
||||
m_state = IDLE;
|
||||
m_idbyte = 0;
|
||||
m_opword = 0;
|
||||
m_status = 0;
|
||||
m_tcy = 0;
|
||||
}
|
||||
|
||||
void ns32081_device::state_add(device_state_interface &parent, int &index)
|
||||
void ns32081_device_base::state_add(device_state_interface &parent, int &index)
|
||||
{
|
||||
parent.state_add(index++, "FSR", m_fsr).formatstr("%04X");
|
||||
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
parent.state_add(index++, util::string_format("F%d", i).c_str(), m_f[i]).formatstr("%08X");
|
||||
}
|
||||
|
||||
u16 ns32081_device::read_st(int *icount)
|
||||
{
|
||||
if (m_state == STATUS)
|
||||
{
|
||||
m_state = (m_op[2].issued == m_op[2].expected) ? IDLE : RESULT;
|
||||
|
||||
if (icount)
|
||||
*icount -= m_tcy;
|
||||
|
||||
LOG("read_st status 0x%04x tcy %d %s (%s)\n", m_status, m_tcy,
|
||||
(m_state == RESULT ? "results pending" : "complete"), machine().describe_context());
|
||||
|
||||
return m_status;
|
||||
}
|
||||
|
||||
logerror("protocol error reading status word (%s)\n", machine().describe_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 ns32081_device::read_op()
|
||||
template <typename T> T ns32081_device_base::read()
|
||||
{
|
||||
if (m_state == RESULT && m_op[2].issued < m_op[2].expected)
|
||||
{
|
||||
u16 const data = u16(m_op[2].value >> (m_op[2].issued * 8));
|
||||
LOG("read_op word %d data 0x%04x (%s)\n", m_op[2].issued >> 1, data, machine().describe_context());
|
||||
T const data = m_op[2].value >> (m_op[2].issued * 8);
|
||||
|
||||
m_op[2].issued += 2;
|
||||
m_op[2].issued += sizeof(T);
|
||||
|
||||
LOG("read %d data 0x%0*x (%s)\n",
|
||||
m_op[2].issued / sizeof(T), sizeof(T) * 2, data, machine().describe_context());
|
||||
|
||||
if (m_op[2].issued == m_op[2].expected)
|
||||
{
|
||||
LOG("read_op last result word issued\n");
|
||||
LOG("read complete\n");
|
||||
m_state = IDLE;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
logerror("protocol error reading result word (%s)\n", machine().describe_context());
|
||||
logerror("read protocol error (%s)\n", machine().describe_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ns32081_device::write_id(u16 data)
|
||||
{
|
||||
bool const match = (data == FORMAT_9) || (data == FORMAT_11);
|
||||
|
||||
if (match)
|
||||
{
|
||||
LOG("write_id match 0x%04x (%s)\n", data, machine().describe_context());
|
||||
m_state = OPERATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("write_id ignore 0x%04x (%s)\n", data, machine().describe_context());
|
||||
m_state = IDLE;
|
||||
}
|
||||
|
||||
m_idbyte = u8(data);
|
||||
}
|
||||
|
||||
void ns32081_device::write_op(u16 data)
|
||||
template <typename T> void ns32081_device_base::write(T data)
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case IDLE:
|
||||
if (sizeof(T) == 4)
|
||||
{
|
||||
// decode instruction
|
||||
if (!decode(BIT(data, 24, 8), swapendian_int16(BIT(data, 8, 16))))
|
||||
return;
|
||||
|
||||
m_state = OPERAND;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("write idbyte 0x%04x (%s)\n", data, machine().describe_context());
|
||||
if ((data == FORMAT_9) || (data == FORMAT_11) || (type() == NS32381 && data == FORMAT_12))
|
||||
{
|
||||
// record idbyte
|
||||
m_idbyte = data;
|
||||
|
||||
m_state = OPERATION;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OPERATION:
|
||||
m_opword = swapendian_int16(data);
|
||||
LOG("write_op opword 0x%04x (%s)\n", m_opword, machine().describe_context());
|
||||
LOG("write opword 0x%0*x (%s)\n", sizeof(T) * 2, data, machine().describe_context());
|
||||
|
||||
// decode instruction
|
||||
decode(m_idbyte, swapendian_int16(data));
|
||||
|
||||
m_state = OPERAND;
|
||||
break;
|
||||
|
||||
case OPERAND:
|
||||
// check awaiting operand data
|
||||
if (m_op[0].issued < m_op[0].expected || m_op[1].issued < m_op[1].expected)
|
||||
{
|
||||
unsigned const n = (m_op[0].issued < m_op[0].expected) ? 0 : 1;
|
||||
operand &op = m_op[n];
|
||||
|
||||
LOG("write operand %d data 0x%0*x (%s)\n",
|
||||
n, sizeof(T) * 2, data, machine().describe_context());
|
||||
|
||||
// insert data into operand value
|
||||
op.value |= u64(data) << (op.issued * 8);
|
||||
op.issued += sizeof(T);
|
||||
}
|
||||
else
|
||||
logerror("write protocol error unexpected operand data 0x%0*x (%s)\n",
|
||||
sizeof(T) * 2, data, machine().describe_context());
|
||||
break;
|
||||
}
|
||||
|
||||
// start execution when all operands are available
|
||||
if (m_state == OPERAND && m_op[0].issued >= m_op[0].expected && m_op[1].issued >= m_op[1].expected)
|
||||
execute();
|
||||
}
|
||||
|
||||
bool ns32081_device_base::decode(u8 const idbyte, u16 const opword)
|
||||
{
|
||||
LOG("decode idbyte 0x%02x opword 0x%04x (%s)\n", idbyte, opword, machine().describe_context());
|
||||
|
||||
m_idbyte = idbyte;
|
||||
m_opword = opword;
|
||||
|
||||
// initialize operands
|
||||
for (operand &op : m_op)
|
||||
@ -196,14 +209,15 @@ void ns32081_device::write_op(u16 data)
|
||||
op.value = 0;
|
||||
}
|
||||
|
||||
// decode operands
|
||||
if (m_idbyte == FORMAT_9)
|
||||
switch (m_idbyte)
|
||||
{
|
||||
case FORMAT_9:
|
||||
{
|
||||
// format 9: 1111 1222 22oo ofii
|
||||
unsigned const f_length = BIT(m_opword, 2) ? LENGTH_F : LENGTH_L;
|
||||
unsigned const size = m_opword & 3;
|
||||
|
||||
switch ((m_opword >> 3) & 7)
|
||||
switch (BIT(m_opword, 3, 3))
|
||||
{
|
||||
case 0: // movif
|
||||
m_op[0].expected = size + 1;
|
||||
@ -231,10 +245,11 @@ void ns32081_device::write_op(u16 data)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (m_idbyte == FORMAT_11)
|
||||
break;
|
||||
case FORMAT_11:
|
||||
{
|
||||
// format 11: 1111 1222 22oo oo0f
|
||||
unsigned const opcode = (m_opword >> 2) & 15;
|
||||
unsigned const opcode = BIT(m_opword, 2, 4);
|
||||
unsigned const f_length = BIT(m_opword, 0) ? LENGTH_F : LENGTH_L;
|
||||
|
||||
m_op[0].expected = f_length;
|
||||
@ -247,69 +262,65 @@ void ns32081_device::write_op(u16 data)
|
||||
if (opcode != 2)
|
||||
m_op[2].expected = f_length;
|
||||
}
|
||||
break;
|
||||
case FORMAT_12:
|
||||
{
|
||||
// format 12: 1111 1222 22oo oo0f
|
||||
unsigned const f_length = BIT(m_opword, 0) ? LENGTH_F : LENGTH_L;
|
||||
|
||||
switch (BIT(m_opword, 2, 4))
|
||||
{
|
||||
case 2: // polyf
|
||||
case 3: // dotf
|
||||
m_op[0].expected = f_length;
|
||||
m_op[1].expected = f_length;
|
||||
break;
|
||||
case 4: // scalbf
|
||||
m_op[0].expected = f_length;
|
||||
m_op[1].expected = f_length;
|
||||
m_op[2].expected = f_length;
|
||||
break;
|
||||
case 5: // logbf
|
||||
m_op[0].expected = f_length;
|
||||
m_op[2].expected = f_length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG("decode idbyte 0x%02x unknown (%s)\n", m_idbyte, machine().describe_context());
|
||||
return false;
|
||||
}
|
||||
|
||||
// operand 1 in register
|
||||
if (m_op[0].expected && !(m_opword & 0xc000))
|
||||
if (m_op[0].expected && !BIT(m_opword, 14, 2))
|
||||
{
|
||||
// exclude integer operands
|
||||
if (m_idbyte == FORMAT_11 || ((m_opword >> 3) & 7) > 1)
|
||||
if (m_idbyte != FORMAT_9 || (BIT(m_opword, 3, 3) > 1))
|
||||
{
|
||||
unsigned const reg = (m_opword >> 11) & 7;
|
||||
LOG("write_op read f%d\n", reg);
|
||||
|
||||
m_op[0].value = m_f[reg ^ 0];
|
||||
if (m_op[0].expected == 8)
|
||||
m_op[0].value |= u64(m_f[reg ^ 1]) << 32;
|
||||
reg_get(m_op[0].expected, m_op[0].value, BIT(m_opword, 11, 3));
|
||||
|
||||
m_op[0].issued = m_op[0].expected;
|
||||
}
|
||||
}
|
||||
|
||||
// operand 2 in register
|
||||
if (m_op[1].expected && !(m_opword & 0x0600))
|
||||
if (m_op[1].expected && !BIT(m_opword, 9, 2))
|
||||
{
|
||||
unsigned const reg = (m_opword >> 6) & 7;
|
||||
LOG("write_op read f%d\n", reg);
|
||||
|
||||
m_op[1].value = m_f[reg ^ 0];
|
||||
if (m_op[1].expected == 8)
|
||||
m_op[1].value |= u64(m_f[reg ^ 1]) << 32;
|
||||
reg_get(m_op[1].expected, m_op[1].value, BIT(m_opword, 6, 3));
|
||||
|
||||
m_op[1].issued = m_op[1].expected;
|
||||
}
|
||||
|
||||
m_state = OPERAND;
|
||||
break;
|
||||
|
||||
case OPERAND:
|
||||
// check awaiting operand word
|
||||
if (m_op[0].issued < m_op[0].expected || m_op[1].issued < m_op[1].expected)
|
||||
{
|
||||
unsigned const n = (m_op[0].issued < m_op[0].expected) ? 0 : 1;
|
||||
operand &op = m_op[n];
|
||||
|
||||
LOG("write_op op%d data 0x%04x (%s)\n", n, data, machine().describe_context());
|
||||
|
||||
// insert word into operand value
|
||||
op.value |= u64(data) << (op.issued * 8);
|
||||
op.issued += 2;
|
||||
}
|
||||
else
|
||||
logerror("protocol error unexpected operand word 0x%04x (%s)\n", data, machine().describe_context());
|
||||
break;
|
||||
}
|
||||
|
||||
// start execution when all operands are available
|
||||
if (m_state == OPERAND && m_op[0].issued >= m_op[0].expected && m_op[1].issued >= m_op[1].expected)
|
||||
execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ns32081_device::execute()
|
||||
void ns32081_device_base::execute()
|
||||
{
|
||||
softfloat_exceptionFlags = 0;
|
||||
u32 const fsr = m_fsr;
|
||||
m_fsr &= ~FSR_TT;
|
||||
|
||||
softfloat_exceptionFlags = 0;
|
||||
m_status = 0;
|
||||
m_tcy = 0;
|
||||
|
||||
@ -317,28 +328,20 @@ void ns32081_device::execute()
|
||||
{
|
||||
case FORMAT_9:
|
||||
// format 9: 1111 1222 22oo ofii
|
||||
{
|
||||
bool const single = BIT(m_opword, 2);
|
||||
unsigned const f_length = single ? LENGTH_F : LENGTH_L;
|
||||
unsigned const size = m_opword & 3;
|
||||
|
||||
switch ((m_opword >> 3) & 7)
|
||||
switch (BIT(m_opword, 3, 3))
|
||||
{
|
||||
case 0:
|
||||
// MOVif src,dest
|
||||
// gen,gen
|
||||
// read.i,write.f
|
||||
{
|
||||
s32 const src =
|
||||
(size == SIZE_D) ? s32(m_op[0].value) :
|
||||
(size == SIZE_W) ? s16(m_op[0].value) :
|
||||
s8(m_op[0].value);
|
||||
s32 const src = util::sext<s32>(m_op[0].value, m_op[0].expected * 8);
|
||||
|
||||
if (single)
|
||||
if (m_op[2].expected == LENGTH_F)
|
||||
m_op[2].value = i32_to_f32(src).v;
|
||||
else
|
||||
m_op[2].value = i32_to_f64(src).v;
|
||||
m_op[2].expected = f_length;
|
||||
|
||||
m_tcy = 53;
|
||||
}
|
||||
break;
|
||||
@ -362,97 +365,83 @@ void ns32081_device::execute()
|
||||
// gen,gen
|
||||
// read.L,write.F
|
||||
m_op[2].value = f64_to_f32(float64_t{ m_op[0].value }).v;
|
||||
m_op[2].expected = f_length;
|
||||
m_tcy = (m_opword & 0xc000) ? 23 : 27;
|
||||
|
||||
m_tcy = BIT(m_opword, 14, 2) ? 23 : 27;
|
||||
break;
|
||||
case 3:
|
||||
// MOVFL src,dest
|
||||
// gen,gen
|
||||
// read.F,write.L
|
||||
m_op[2].value = f32_to_f64(float32_t{ u32(m_op[0].value) }).v;
|
||||
m_op[2].expected = f_length;
|
||||
m_tcy = (m_opword & 0xc000) ? 22 : 26;
|
||||
|
||||
m_tcy = BIT(m_opword, 14, 2) ? 22 : 26;
|
||||
break;
|
||||
case 4:
|
||||
// ROUNDfi src,dest
|
||||
// gen,gen
|
||||
// read.f,write.i
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
m_op[2].value = f32_to_i64(float32_t{ u32(m_op[0].value) }, softfloat_round_near_even, true);
|
||||
else
|
||||
m_op[2].value = f64_to_i64(float64_t{ m_op[0].value }, softfloat_round_near_even, true);
|
||||
|
||||
if ((size == SIZE_D && s64(m_op[2].value) != s32(m_op[2].value))
|
||||
|| (size == SIZE_W && s64(m_op[2].value) != s16(m_op[2].value))
|
||||
|| (size == SIZE_B && s64(m_op[2].value) != s8(m_op[2].value)))
|
||||
if (s64(m_op[2].value) != util::sext<s64>(m_op[2].value, m_op[2].expected * 8))
|
||||
softfloat_exceptionFlags |= softfloat_flag_overflow;
|
||||
|
||||
m_op[2].expected = size + 1;
|
||||
m_tcy = (m_opword & 0xc000) ? 53 : 66;
|
||||
m_tcy = BIT(m_opword, 14, 2) ? 53 : 66;
|
||||
break;
|
||||
case 5:
|
||||
// TRUNCfi src,dest
|
||||
// gen,gen
|
||||
// read.f,write.i
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
m_op[2].value = f32_to_i64(float32_t{ u32(m_op[0].value) }, softfloat_round_minMag, true);
|
||||
else
|
||||
m_op[2].value = f64_to_i64(float64_t{ m_op[0].value }, softfloat_round_minMag, true);
|
||||
|
||||
if ((size == SIZE_D && s64(m_op[2].value) != s32(m_op[2].value))
|
||||
|| (size == SIZE_W && s64(m_op[2].value) != s16(m_op[2].value))
|
||||
|| (size == SIZE_B && s64(m_op[2].value) != s8(m_op[2].value)))
|
||||
if (s64(m_op[2].value) != util::sext<s64>(m_op[2].value, m_op[2].expected * 8))
|
||||
softfloat_exceptionFlags |= softfloat_flag_overflow;
|
||||
|
||||
m_op[2].expected = size + 1;
|
||||
m_tcy = (m_opword & 0xc000) ? 53 : 66;
|
||||
m_tcy = BIT(m_opword, 14, 2) ? 53 : 66;
|
||||
break;
|
||||
case 6:
|
||||
// SFSR dest
|
||||
// gen
|
||||
// write.D
|
||||
m_op[2].value = fsr;
|
||||
m_op[2].expected = 4;
|
||||
|
||||
m_tcy = 13;
|
||||
break;
|
||||
case 7:
|
||||
// FLOORfi src,dest
|
||||
// gen,gen
|
||||
// read.f,write.i
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
m_op[2].value = f32_to_i64(float32_t{ u32(m_op[0].value) }, softfloat_round_min, true);
|
||||
else
|
||||
m_op[2].value = f64_to_i64(float64_t{ m_op[0].value }, softfloat_round_min, true);
|
||||
|
||||
if ((size == SIZE_D && s64(m_op[2].value) != s32(m_op[2].value))
|
||||
|| (size == SIZE_W && s64(m_op[2].value) != s16(m_op[2].value))
|
||||
|| (size == SIZE_B && s64(m_op[2].value) != s8(m_op[2].value)))
|
||||
if (s64(m_op[2].value) != util::sext<s64>(m_op[2].value, m_op[2].expected * 8))
|
||||
softfloat_exceptionFlags |= softfloat_flag_overflow;
|
||||
|
||||
m_op[2].expected = size + 1;
|
||||
m_tcy = (m_opword & 0xc000) ? 53 : 66;
|
||||
m_tcy = BIT(m_opword, 14, 2) ? 53 : 66;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_11:
|
||||
// format 11: 1111122222oooo0f
|
||||
{
|
||||
bool const single = BIT(m_opword, 0);
|
||||
unsigned const f_length = single ? LENGTH_F : LENGTH_L;
|
||||
|
||||
switch ((m_opword >> 2) & 15)
|
||||
// format 11: 1111 1222 22oo oo0f
|
||||
switch (BIT(m_opword, 2, 4))
|
||||
{
|
||||
case 0x0:
|
||||
// ADDf src,dest
|
||||
// gen,gen
|
||||
// read.f,rmw.f
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
m_op[2].value = f32_add(float32_t{ u32(m_op[1].value) }, float32_t{ u32(m_op[0].value) }).v;
|
||||
else
|
||||
m_op[2].value = f64_add(float64_t{ m_op[1].value }, float64_t{ m_op[0].value }).v;
|
||||
m_op[2].expected = f_length;
|
||||
|
||||
m_tcy = (m_opword & 0xc600) ? 70 : 74;
|
||||
break;
|
||||
case 0x1:
|
||||
@ -460,8 +449,8 @@ void ns32081_device::execute()
|
||||
// gen,gen
|
||||
// read.f,write.f
|
||||
m_op[2].value = m_op[0].value;
|
||||
m_op[2].expected = f_length;
|
||||
m_tcy = (m_opword & 0xc000) ? 23 : 27;
|
||||
|
||||
m_tcy = BIT(m_opword, 14, 2) ? 23 : 27;
|
||||
break;
|
||||
case 0x2:
|
||||
// CMPf src1,src2
|
||||
@ -469,9 +458,10 @@ void ns32081_device::execute()
|
||||
// read.f,read.f
|
||||
if (m_op[0].value == m_op[1].value)
|
||||
m_status |= SLAVE_Z;
|
||||
if ((single && f32_le(float32_t{ u32(m_op[1].value) }, float32_t{ u32(m_op[0].value) }))
|
||||
|| (!single && f64_le(float64_t{ m_op[1].value }, float64_t{ m_op[0].value })))
|
||||
if ((m_op[0].expected == LENGTH_F && f32_le(float32_t{ u32(m_op[1].value) }, float32_t{ u32(m_op[0].value) }))
|
||||
|| (m_op[0].expected == LENGTH_L && f64_le(float64_t{ m_op[1].value }, float64_t{ m_op[0].value })))
|
||||
m_status |= SLAVE_N;
|
||||
|
||||
m_tcy = (m_opword & 0xc600) ? 45 : 49;
|
||||
break;
|
||||
case 0x3:
|
||||
@ -483,34 +473,34 @@ void ns32081_device::execute()
|
||||
// SUBf src,dest
|
||||
// gen,gen
|
||||
// read.f,rmw.f
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
m_op[2].value = f32_sub(float32_t{ u32(m_op[1].value) }, float32_t{ u32(m_op[0].value) }).v;
|
||||
else
|
||||
m_op[2].value = f64_sub(float64_t{ m_op[1].value }, float64_t{ m_op[0].value }).v;
|
||||
m_op[2].expected = f_length;
|
||||
|
||||
m_tcy = (m_opword & 0xc600) ? 70 : 74;
|
||||
break;
|
||||
case 0x5:
|
||||
// NEGf src,dest
|
||||
// gen,gen
|
||||
// read.f,write.f
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
m_op[2].value = f32_mul(float32_t{ u32(m_op[0].value) }, i32_to_f32(-1)).v;
|
||||
else
|
||||
m_op[2].value = f64_mul(float64_t{ m_op[0].value }, i32_to_f64(-1)).v;
|
||||
m_op[2].expected = f_length;
|
||||
m_tcy = (m_opword & 0xc000) ? 20 : 24;
|
||||
|
||||
m_tcy = BIT(m_opword, 14, 2) ? 20 : 24;
|
||||
break;
|
||||
case 0x8:
|
||||
// DIVf src,dest
|
||||
// gen,gen
|
||||
// read.f,rmw.f
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
m_op[2].value = f32_div(float32_t{ u32(m_op[1].value) }, float32_t{ u32(m_op[0].value) }).v;
|
||||
else
|
||||
m_op[2].value = f64_div(float64_t{ m_op[1].value }, float64_t{ m_op[0].value }).v;
|
||||
m_op[2].expected = f_length;
|
||||
m_tcy = ((m_opword & 0xc600) ? 55 : 59) + (single ? 30 : 60);
|
||||
|
||||
m_tcy = ((m_opword & 0xc600) ? 55 : 59) + (m_op[0].expected == LENGTH_F ? 30 : 60);
|
||||
break;
|
||||
case 0x9:
|
||||
// Trap(SLAVE)
|
||||
@ -521,18 +511,18 @@ void ns32081_device::execute()
|
||||
// MULf src,dest
|
||||
// gen,gen
|
||||
// read.f,rmw.f
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
m_op[2].value = f32_mul(float32_t{ u32(m_op[1].value) }, float32_t{ u32(m_op[0].value) }).v;
|
||||
else
|
||||
m_op[2].value = f64_mul(float64_t{ m_op[1].value }, float64_t{ m_op[0].value }).v;
|
||||
m_op[2].expected = f_length;
|
||||
m_tcy = ((m_opword & 0xc600) ? 30 : 34) + (single ? 14 : 28);
|
||||
|
||||
m_tcy = ((m_opword & 0xc600) ? 30 : 34) + (m_op[0].expected == LENGTH_F ? 14 : 28);
|
||||
break;
|
||||
case 0xd:
|
||||
// ABSf src,dest
|
||||
// gen,gen
|
||||
// read.f,write.f
|
||||
if (single)
|
||||
if (m_op[0].expected == LENGTH_F)
|
||||
if (f32_lt(float32_t{ u32(m_op[0].value) }, float32_t{ 0 }))
|
||||
m_op[2].value = f32_mul(float32_t{ u32(m_op[0].value) }, i32_to_f32(-1)).v;
|
||||
else
|
||||
@ -542,10 +532,43 @@ void ns32081_device::execute()
|
||||
m_op[2].value = f64_mul(float64_t{ m_op[0].value }, i32_to_f64(-1)).v;
|
||||
else
|
||||
m_op[2].value = float64_t{ m_op[0].value }.v;
|
||||
m_op[2].expected = f_length;
|
||||
m_tcy = (m_opword & 0xc000) ? 20 : 24;
|
||||
|
||||
m_tcy = BIT(m_opword, 14, 2) ? 20 : 24;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_12:
|
||||
// format 12: 1111 1222 22oo oo0f
|
||||
switch (BIT(m_opword, 2, 4))
|
||||
{
|
||||
case 0x2:
|
||||
// POLYf src1,src2
|
||||
// gen,gen
|
||||
// read.f,read.f
|
||||
m_fsr |= FSR_RMB;
|
||||
break;
|
||||
case 0x3:
|
||||
// DOTf src1,src2
|
||||
// gen,gen
|
||||
// read.f,read.f
|
||||
m_fsr |= FSR_RMB;
|
||||
break;
|
||||
case 0x4:
|
||||
// SCALBf src,dest
|
||||
// gen,gen
|
||||
// read.f,rmw.f
|
||||
break;
|
||||
case 0x5:
|
||||
// LOGBf src,dest
|
||||
// gen,gen
|
||||
// read.f,write.f
|
||||
break;
|
||||
default:
|
||||
// Trap(SLAVE)
|
||||
m_fsr |= TT_ILL;
|
||||
m_status = SLAVE_Q;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -595,47 +618,177 @@ void ns32081_device::execute()
|
||||
"addf", "movf", "cmpf", nullptr, "subf", "negf", nullptr, nullptr,
|
||||
"divf", nullptr, nullptr, nullptr, "mulf", "absf", nullptr, nullptr
|
||||
};
|
||||
static char const *format12[] =
|
||||
{
|
||||
nullptr, nullptr, "polyf", "dotf", "scalbf", "logbf", nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
|
||||
};
|
||||
|
||||
char const *operation = nullptr;
|
||||
switch (m_idbyte)
|
||||
{
|
||||
case FORMAT_9: operation = format9[BIT(m_opword, 3, 3)]; break;
|
||||
case FORMAT_11: operation = format11[BIT(m_opword, 2, 4)]; break;
|
||||
case FORMAT_12: operation = format12[BIT(m_opword, 2, 4)]; break;
|
||||
}
|
||||
|
||||
if (m_status & SLAVE_Q)
|
||||
LOG("execute %s 0x%x,0x%x exception\n",
|
||||
(m_idbyte == FORMAT_9)
|
||||
? format9[(m_opword >> 3) & 7]
|
||||
: format11[(m_opword >> 2) & 15],
|
||||
m_op[0].value, m_op[1].value);
|
||||
LOG("execute %s 0x%x,0x%x exception\n", operation, m_op[0].value, m_op[1].value);
|
||||
else
|
||||
LOG("execute %s 0x%x,0x%x result 0x%x\n",
|
||||
(m_idbyte == FORMAT_9)
|
||||
? format9[(m_opword >> 3) & 7]
|
||||
: format11[(m_opword >> 2) & 15],
|
||||
m_op[0].value, m_op[1].value, m_op[2].value);
|
||||
LOG("execute %s 0x%x,0x%x result 0x%x\n", operation, m_op[0].value, m_op[1].value, m_op[2].value);
|
||||
}
|
||||
|
||||
// write-back floating point register results
|
||||
if (m_op[2].expected && !(m_opword & 0x0600))
|
||||
if (m_op[2].expected && !BIT(m_opword, 9, 2))
|
||||
{
|
||||
// exclude integer results (roundfi, truncfi, sfsr, floorfi)
|
||||
if (m_idbyte == FORMAT_11 || ((m_opword >> 3) & 7) < 4)
|
||||
if (m_idbyte != FORMAT_9 || (BIT(m_opword, 3, 3) < 4))
|
||||
{
|
||||
unsigned const reg = (m_opword >> 6) & 7;
|
||||
reg_set(BIT(m_opword, 6, 3), m_op[2].expected, m_op[2].value);
|
||||
|
||||
LOG("execute write-back f%d\n", reg);
|
||||
|
||||
m_f[reg ^ 0] = u32(m_op[2].value >> 0);
|
||||
if (m_op[2].expected == 8)
|
||||
m_f[reg ^ 1] = u32(m_op[2].value >> 32);
|
||||
if (type() == NS32381)
|
||||
m_fsr |= FSR_RMB;
|
||||
|
||||
m_op[2].issued = m_op[2].expected;
|
||||
}
|
||||
}
|
||||
|
||||
m_state = STATUS;
|
||||
|
||||
if (!m_out_scb.isunset())
|
||||
m_complete->adjust(attotime::from_ticks(m_tcy, clock()));
|
||||
|
||||
m_state = STATUS;
|
||||
}
|
||||
|
||||
void ns32081_device::complete(s32 param)
|
||||
u16 ns32081_device_base::status(int *icount)
|
||||
{
|
||||
if (m_state == STATUS)
|
||||
{
|
||||
m_state = (m_op[2].issued == m_op[2].expected) ? IDLE : RESULT;
|
||||
|
||||
if (icount)
|
||||
*icount -= m_tcy;
|
||||
|
||||
LOG("status 0x%04x tcy %d %s (%s)\n", m_status, m_tcy,
|
||||
(m_state == RESULT ? "results pending" : "complete"), machine().describe_context());
|
||||
|
||||
return m_status;
|
||||
}
|
||||
|
||||
logerror("status protocol error (%s)\n", machine().describe_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ns32081_device_base::complete(s32 param)
|
||||
{
|
||||
m_out_scb(0);
|
||||
m_out_scb(1);
|
||||
}
|
||||
|
||||
ns32081_device::ns32081_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: ns32081_device_base(mconfig, NS32081, tag, owner, clock)
|
||||
, ns32000_slow_slave_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
void ns32081_device::device_start()
|
||||
{
|
||||
ns32081_device_base::device_start();
|
||||
|
||||
save_item(NAME(m_f));
|
||||
}
|
||||
|
||||
void ns32081_device::device_reset()
|
||||
{
|
||||
ns32081_device_base::device_reset();
|
||||
|
||||
std::fill(std::begin(m_f), std::end(m_f), 0);
|
||||
}
|
||||
|
||||
void ns32081_device::state_add(device_state_interface &parent, int &index)
|
||||
{
|
||||
ns32081_device_base::state_add(parent, index);
|
||||
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
parent.state_add(index++, util::string_format("F%d", i).c_str(), m_f[i]).formatstr("%08X");
|
||||
}
|
||||
|
||||
void ns32081_device::reg_get(unsigned const op_size, u64 &op_value, unsigned const reg) const
|
||||
{
|
||||
op_value = m_f[reg ^ 0];
|
||||
if (op_size == LENGTH_L)
|
||||
op_value |= u64(m_f[reg ^ 1]) << 32;
|
||||
|
||||
if (op_size == LENGTH_L)
|
||||
LOG("reg_get f%d:%d data 0x%016x\n", reg ^ 1, reg ^ 0, op_value);
|
||||
else
|
||||
LOG("reg_get f%d data 0x%08x\n", reg, op_value);
|
||||
}
|
||||
|
||||
void ns32081_device::reg_set(unsigned const reg, unsigned const op_size, u64 const op_value)
|
||||
{
|
||||
if (op_size == LENGTH_L)
|
||||
LOG("reg_set f%d:%d data 0x%016x\n", reg ^ 1, reg ^ 0, op_value);
|
||||
else
|
||||
LOG("reg_set f%d data 0x%08x\n", reg, op_value);
|
||||
|
||||
m_f[reg ^ 0] = u32(op_value >> 0);
|
||||
if (op_size == LENGTH_L)
|
||||
m_f[reg ^ 1] = u32(op_value >> 32);
|
||||
}
|
||||
|
||||
ns32381_device::ns32381_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: ns32081_device_base(mconfig, NS32381, tag, owner, clock)
|
||||
, ns32000_slow_slave_interface(mconfig, *this)
|
||||
, ns32000_fast_slave_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
void ns32381_device::device_start()
|
||||
{
|
||||
ns32081_device_base::device_start();
|
||||
|
||||
save_item(NAME(m_l));
|
||||
}
|
||||
|
||||
void ns32381_device::device_reset()
|
||||
{
|
||||
std::fill(std::begin(m_l), std::end(m_l), 0);
|
||||
}
|
||||
|
||||
void ns32381_device::state_add(device_state_interface &parent, int &index)
|
||||
{
|
||||
ns32081_device_base::state_add(parent, index);
|
||||
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
parent.state_add(index++, util::string_format("L%d", i).c_str(), m_l[i]).formatstr("%016X");
|
||||
}
|
||||
|
||||
void ns32381_device::reg_get(unsigned const op_size, u64 &op_value, unsigned const reg) const
|
||||
{
|
||||
if (op_size == LENGTH_L)
|
||||
op_value = m_l[reg];
|
||||
else if (reg & 1)
|
||||
op_value = m_l[reg & 6] >> 32;
|
||||
else
|
||||
op_value = u32(m_l[reg & 6]);
|
||||
|
||||
if (op_size == LENGTH_L)
|
||||
LOG("reg_get l%d data 0x%016x\n", reg, op_value);
|
||||
else
|
||||
LOG("reg_get f%d data 0x%08x\n", reg, op_value);
|
||||
}
|
||||
|
||||
void ns32381_device::reg_set(unsigned const reg, unsigned const op_size, u64 const op_value)
|
||||
{
|
||||
if (op_size == LENGTH_L)
|
||||
LOG("reg_set l%d data 0x%016x\n", reg, op_value);
|
||||
else
|
||||
LOG("reg_set f%d data 0x%08x\n", reg, op_value);
|
||||
|
||||
if (op_size == LENGTH_L)
|
||||
m_l[reg] = op_value;
|
||||
else if (reg & 1)
|
||||
m_l[reg & 6] = (op_value << 32) | u32(m_l[reg & 6]);
|
||||
else
|
||||
m_l[reg & 6] = (m_l[reg & 6] & 0xffff'ffff'0000'0000ULL) | u32(op_value);
|
||||
}
|
||||
|
@ -8,54 +8,119 @@
|
||||
|
||||
#include "cpu/ns32000/common.h"
|
||||
|
||||
class ns32081_device
|
||||
class ns32081_device_base
|
||||
: public device_t
|
||||
, public ns32000_slow_slave_interface
|
||||
, public ns32000_fpu_interface
|
||||
{
|
||||
protected:
|
||||
ns32081_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
// device_t implementation
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// ns32000_slave_interface implementation
|
||||
virtual void state_add(device_state_interface &parent, int &index) override;
|
||||
|
||||
// slave interface handlers
|
||||
template <typename T> T read();
|
||||
template <typename T> void write(T data);
|
||||
|
||||
// execution helpers
|
||||
bool decode(u8 const idbyte, u16 const opword);
|
||||
void execute();
|
||||
u16 status(int *icount);
|
||||
void complete(s32 param);
|
||||
|
||||
// register helpers
|
||||
virtual void reg_get(unsigned const op_size, u64 &op_value, unsigned const reg) const = 0;
|
||||
virtual void reg_set(unsigned const reg, unsigned const op_size, u64 const op_value) = 0;
|
||||
|
||||
private:
|
||||
emu_timer *m_complete;
|
||||
|
||||
u32 m_fsr; // floating-point status register
|
||||
|
||||
// operating state
|
||||
u32 m_state;
|
||||
u8 m_idbyte;
|
||||
u16 m_opword;
|
||||
struct operand
|
||||
{
|
||||
u32 expected;
|
||||
u32 issued;
|
||||
u64 value;
|
||||
}
|
||||
m_op[3];
|
||||
u16 m_status;
|
||||
u32 m_tcy;
|
||||
};
|
||||
|
||||
class ns32081_device
|
||||
: public ns32081_device_base
|
||||
, public ns32000_slow_slave_interface
|
||||
{
|
||||
public:
|
||||
ns32081_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
// ns32000_slave_interface implementation
|
||||
virtual void state_add(device_state_interface &parent, int &index) override;
|
||||
|
||||
virtual u16 read_st(int *icount = nullptr) override;
|
||||
virtual u16 read_op() override;
|
||||
|
||||
virtual void write_id(u16 data) override;
|
||||
virtual void write_op(u16 data) override;
|
||||
// ns32000_slow_slave_interface implementation
|
||||
virtual u16 slow_status(int *icount = nullptr) override { return status(icount); }
|
||||
virtual u16 slow_read() override { return read<u16>(); }
|
||||
virtual void slow_write(u16 data) override { write<u16>(data); }
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
void execute();
|
||||
void complete(s32 param);
|
||||
// register helpers
|
||||
virtual void reg_get(unsigned const op_size, u64 &op_value, unsigned const reg) const override;
|
||||
virtual void reg_set(unsigned const reg, unsigned const op_size, u64 const op_value) override;
|
||||
|
||||
private:
|
||||
emu_timer *m_complete;
|
||||
|
||||
// registers
|
||||
u32 m_fsr;
|
||||
u32 m_f[8];
|
||||
};
|
||||
|
||||
// operating state
|
||||
u8 m_idbyte;
|
||||
u16 m_opword;
|
||||
struct operand
|
||||
{
|
||||
unsigned expected;
|
||||
unsigned issued;
|
||||
u64 value;
|
||||
}
|
||||
m_op[3];
|
||||
u16 m_status;
|
||||
class ns32381_device
|
||||
: public ns32081_device_base
|
||||
, public ns32000_slow_slave_interface
|
||||
, public ns32000_fast_slave_interface
|
||||
{
|
||||
public:
|
||||
ns32381_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
// implementation state
|
||||
unsigned m_state;
|
||||
unsigned m_tcy;
|
||||
// ns32000_slave_interface implementation
|
||||
virtual void state_add(device_state_interface &parent, int &index) override;
|
||||
|
||||
// ns32000_slow_slave_interface implementation
|
||||
virtual u16 slow_status(int *icount = nullptr) override { return status(icount); }
|
||||
virtual u16 slow_read() override { return read<u16>(); }
|
||||
virtual void slow_write(u16 data) override { write<u16>(data); }
|
||||
|
||||
// ns32000_fast_slave_interface implementation
|
||||
virtual u32 fast_status(int *icount = nullptr) override { return status(icount); }
|
||||
virtual u32 fast_read() override { return read<u32>(); }
|
||||
virtual void fast_write(u32 data) override { write<u32>(data); }
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// register helpers
|
||||
virtual void reg_get(unsigned const op_size, u64 &op_value, unsigned const reg) const override;
|
||||
virtual void reg_set(unsigned const reg, unsigned const op_size, u64 const op_value) override;
|
||||
|
||||
private:
|
||||
// registers
|
||||
u64 m_l[8];
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(NS32081, ns32081_device)
|
||||
DECLARE_DEVICE_TYPE(NS32381, ns32381_device)
|
||||
|
||||
#endif // MAME_MACHINE_NS32081_H
|
||||
|
@ -34,11 +34,6 @@ enum state : unsigned
|
||||
RESULT = 6, // result word available
|
||||
};
|
||||
|
||||
enum idbyte : u8
|
||||
{
|
||||
FORMAT_14 = 0x1e,
|
||||
};
|
||||
|
||||
enum reg_mask : unsigned
|
||||
{
|
||||
BPR0 = 0x0, // breakpoint register 0
|
||||
@ -127,8 +122,8 @@ enum eia_mask : u32
|
||||
|
||||
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)
|
||||
, ns32000_mmu_interface(mconfig, *this)
|
||||
, ns32000_slow_slave_interface(mconfig, *this)
|
||||
, m_bpr{}
|
||||
, m_pf{}
|
||||
, m_sc(0)
|
||||
@ -172,7 +167,7 @@ void ns32082_device::state_add(device_state_interface &parent, int &index)
|
||||
parent.state_add(index++, "MSR", m_msr).formatstr("%08X");
|
||||
}
|
||||
|
||||
u16 ns32082_device::read_st(int *icount)
|
||||
u16 ns32082_device::slow_status(int *icount)
|
||||
{
|
||||
if (m_state == STATUS)
|
||||
{
|
||||
@ -181,63 +176,54 @@ u16 ns32082_device::read_st(int *icount)
|
||||
if (icount)
|
||||
*icount -= m_tcy;
|
||||
|
||||
LOG("read_st status 0x%04x tcy %d %s (%s)\n", m_status, m_tcy,
|
||||
LOG("status 0x%04x tcy %d %s (%s)\n", m_status, m_tcy,
|
||||
(m_state == RESULT ? "results pending" : "complete"), machine().describe_context());
|
||||
|
||||
return m_status;
|
||||
}
|
||||
|
||||
logerror("read_st protocol error reading status word (%s)\n", machine().describe_context());
|
||||
logerror("status protocol error (%s)\n", machine().describe_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 ns32082_device::read_op()
|
||||
u16 ns32082_device::slow_read()
|
||||
{
|
||||
if (m_state == RESULT && m_op[2].issued < m_op[2].expected)
|
||||
{
|
||||
u16 const data = u16(m_op[2].value >> (m_op[2].issued * 8));
|
||||
LOG("read_op word %d data 0x%04x (%s)\n", m_op[2].issued >> 1, data, machine().describe_context());
|
||||
LOG("read %d data 0x%04x (%s)\n", m_op[2].issued >> 1, data, machine().describe_context());
|
||||
|
||||
m_op[2].issued += 2;
|
||||
|
||||
if (m_op[2].issued == m_op[2].expected)
|
||||
{
|
||||
LOG("read_op last result word issued\n");
|
||||
LOG("read complete\n");
|
||||
m_state = IDLE;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
logerror("read_op protocol error reading result word (%s)\n", machine().describe_context());
|
||||
logerror("read protocol error (%s)\n", machine().describe_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ns32082_device::write_id(u16 data)
|
||||
{
|
||||
bool const match = (data == FORMAT_14);
|
||||
|
||||
if (match)
|
||||
{
|
||||
LOG("write_id match 0x%04x (%s)\n", data, machine().describe_context());
|
||||
m_state = OPERATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("write_id ignore 0x%04x (%s)\n", data, machine().describe_context());
|
||||
m_state = IDLE;
|
||||
}
|
||||
|
||||
m_idbyte = u8(data);
|
||||
}
|
||||
|
||||
void ns32082_device::write_op(u16 data)
|
||||
void ns32082_device::slow_write(u16 data)
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case IDLE:
|
||||
LOG("write idbyte 0x%04x (%s)\n", data, machine().describe_context());
|
||||
if (data == FORMAT_14)
|
||||
{
|
||||
m_idbyte = u8(data);
|
||||
m_state = OPERATION;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPERATION:
|
||||
m_opword = swapendian_int16(data);
|
||||
LOG("write_op opword 0x%04x (%s)\n", m_opword, machine().describe_context());
|
||||
LOG("write opword 0x%04x (%s)\n", m_opword, machine().describe_context());
|
||||
|
||||
m_tcy = 0;
|
||||
|
||||
@ -282,14 +268,16 @@ void ns32082_device::write_op(u16 data)
|
||||
unsigned const n = (m_op[0].issued < m_op[0].expected) ? 0 : 1;
|
||||
operand &op = m_op[n];
|
||||
|
||||
LOG("write_op op%d data 0x%04x (%s)\n", n, data, machine().describe_context());
|
||||
LOG("write operand %d data 0x%04x (%s)\n",
|
||||
n, data, machine().describe_context());
|
||||
|
||||
// insert word into operand value
|
||||
op.value |= u64(data) << (op.issued * 8);
|
||||
op.issued += 2;
|
||||
}
|
||||
else
|
||||
logerror("write_op protocol error unexpected operand word 0x%04x (%s)\n", data, machine().describe_context());
|
||||
logerror("write protocol error unexpected operand data 0x%04x (%s)\n",
|
||||
data, machine().describe_context());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -10,24 +10,25 @@
|
||||
|
||||
class ns32082_device
|
||||
: public device_t
|
||||
, public ns32000_slow_slave_interface
|
||||
, public ns32000_mmu_interface
|
||||
, public ns32000_slow_slave_interface
|
||||
{
|
||||
public:
|
||||
ns32082_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
// ns32000_slave_interface implementation
|
||||
virtual void state_add(device_state_interface &parent, int &index) override;
|
||||
|
||||
virtual u16 read_st(int *icount = nullptr) override;
|
||||
virtual u16 read_op() override;
|
||||
|
||||
virtual void write_id(u16 data) override;
|
||||
virtual void write_op(u16 data) override;
|
||||
// ns32000_slow_slave_interface implementation
|
||||
virtual u16 slow_status(int *icount = nullptr) override;
|
||||
virtual u16 slow_read() override;
|
||||
virtual void slow_write(u16 data) override;
|
||||
|
||||
// ns32000_mmu_interface implementation
|
||||
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
|
||||
// device_t implementation
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
@ -51,16 +52,16 @@ private:
|
||||
u16 m_opword;
|
||||
struct operand
|
||||
{
|
||||
unsigned expected;
|
||||
unsigned issued;
|
||||
u32 expected;
|
||||
u32 issued;
|
||||
u64 value;
|
||||
}
|
||||
m_op[3];
|
||||
u16 m_status;
|
||||
|
||||
// implementation state
|
||||
unsigned m_state;
|
||||
unsigned m_tcy;
|
||||
u32 m_state;
|
||||
u32 m_tcy;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(NS32082, ns32082_device)
|
||||
|
@ -10,7 +10,6 @@
|
||||
* - https://www.nic.funet.fi/pub/misc/pc532/
|
||||
*
|
||||
* TODO:
|
||||
* - ns32381
|
||||
* - et532
|
||||
*
|
||||
* WIP:
|
||||
@ -47,7 +46,7 @@ public:
|
||||
pc532_state(machine_config const &mconfig, device_type type, char const *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_cpu(*this, "cpu")
|
||||
//, m_fpu(*this, "fpu")
|
||||
, m_fpu(*this, "fpu")
|
||||
, m_icu(*this, "icu")
|
||||
, m_rtc(*this, "rtc")
|
||||
, m_ncr5380(*this, "slot:7:ncr5380")
|
||||
@ -61,7 +60,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void init();
|
||||
void pc532(machine_config &config);
|
||||
|
||||
protected:
|
||||
@ -71,7 +69,7 @@ protected:
|
||||
template <unsigned ST> void cpu_map(address_map &map);
|
||||
|
||||
required_device<ns32532_device> m_cpu;
|
||||
//required_device<ns32381_device> m_fpu;
|
||||
required_device<ns32381_device> m_fpu;
|
||||
required_device<ns32202_device> m_icu;
|
||||
|
||||
required_device<ds1315_device> m_rtc;
|
||||
@ -113,12 +111,6 @@ private:
|
||||
m_state;
|
||||
};
|
||||
|
||||
void pc532_state::init()
|
||||
{
|
||||
// HACK: disable unemulated FPU
|
||||
m_eprom[0x7c00 >> 2] &= ~0x02;
|
||||
}
|
||||
|
||||
void pc532_state::machine_start()
|
||||
{
|
||||
// install phantom rtc using memory taps
|
||||
@ -312,8 +304,8 @@ void pc532_state::pc532(machine_config &config)
|
||||
// ODT required because system software uses explicit MOV instead of RETI instructions
|
||||
m_cpu->set_addrmap(ns32000::ST_ODT, &pc532_state::cpu_map<ns32000::ST_ODT>);
|
||||
|
||||
//NS32381(config, m_fpu, 50_MHz_XTAL / 2);
|
||||
//m_cpu->set_fpu(m_fpu);
|
||||
NS32381(config, m_fpu, 50_MHz_XTAL / 2);
|
||||
m_cpu->set_fpu(m_fpu);
|
||||
|
||||
NS32202(config, m_icu, 3.6864_MHz_XTAL);
|
||||
m_icu->out_int().set_inputline(m_cpu, INPUT_LINE_IRQ0).invert();
|
||||
@ -327,7 +319,7 @@ void pc532_state::pc532(machine_config &config)
|
||||
NSCSI_CONNECTOR(config, "slot:1", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "slot:2", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "slot:3", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "slot:7").option_set("ncr5380", NCR5380).machine_config(
|
||||
NSCSI_CONNECTOR(config, "slot:7").option_set("ncr5380", NCR5380).machine_config( // DP8490
|
||||
[this](device_t *device)
|
||||
{
|
||||
ncr5380_device &ncr5380(downcast<ncr5380_device &>(*device));
|
||||
@ -413,4 +405,4 @@ ROM_END
|
||||
} // anonymous namespace
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
|
||||
COMP(1989, pc532, 0, 0, pc532, 0, pc532_state, init, "George Scolaro", "pc532", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
|
||||
COMP(1989, pc532, 0, 0, pc532, 0, pc532_state, empty_init, "George Scolaro", "pc532", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
|
||||
|
Loading…
Reference in New Issue
Block a user