diff --git a/src/devices/cpu/ns32000/common.h b/src/devices/cpu/ns32000/common.h index fa978729b49..a93259617c9 100644 --- a/src/devices/cpu/ns32000/common.h +++ b/src/devices/cpu/ns32000/common.h @@ -32,6 +32,38 @@ 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: @@ -43,14 +75,6 @@ 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) @@ -63,8 +87,6 @@ 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) @@ -75,52 +97,31 @@ protected: devcb_write_line m_out_scb; }; -class ns32000_fpu_interface : public ns32000_slave_interface -{ -protected: - ns32000_fpu_interface(machine_config const &mconfig, device_t &device) - : ns32000_slave_interface(mconfig, device) - { - } -}; - -class ns32000_mmu_interface : public ns32000_slave_interface +class ns32000_slow_slave_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 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; + 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) - : device_interface(device, "ns32000_slave_slow") + : ns32000_slave_interface(mconfig, device) { } }; -class ns32000_fast_slave_interface : public device_interface +class ns32000_fast_slave_interface : public ns32000_slave_interface { public: - virtual u32 fast_status(int *icount = nullptr) = 0; - virtual u32 fast_read() = 0; - virtual void fast_write(u32 data) = 0; + virtual u32 read_st32(int *icount = nullptr) = 0; + virtual u32 read() = 0; + virtual void write(u32 data) = 0; protected: ns32000_fast_slave_interface(machine_config const &mconfig, device_t &device) - : device_interface(device, "ns32000_slave_fast") + : ns32000_slave_interface(mconfig, device) { } }; diff --git a/src/devices/cpu/ns32000/ns32000.cpp b/src/devices/cpu/ns32000/ns32000.cpp index 6fef593dfd8..d28d25b03ad 100644 --- a/src/devices/cpu/ns32000/ns32000.cpp +++ b/src/devices/cpu/ns32000/ns32000.cpp @@ -3128,14 +3128,14 @@ template void ns32000_device::execute } } break; - case ns32000_slave_interface::FORMAT_9: + case 0x3e: // format 9: xxxx xyyy yyoo ofii 0011 1110 if (m_cfg & CFG_F) { u16 const opword = fetch(bytes); addr_mode mode[] = { addr_mode(BIT(opword, 11, 5)), addr_mode(BIT(opword, 6, 5)) }; - size_code const size_f = BIT(opword, 2) ? SIZE_D : SIZE_Q; + size_code const size_f = BIT(opword, 0) ? SIZE_D : SIZE_Q; size_code const size = size_code(opword & 3); switch (BIT(opword, 3, 3)) @@ -3234,7 +3234,7 @@ template void ns32000_device::execute case 0x7e: // format 10 interrupt(UND); break; - case ns32000_slave_interface::FORMAT_11: + case 0xbe: // format 11: xxxx xyyy yyoo oo0f 1011 1110 if (m_cfg & CFG_F) { @@ -3366,7 +3366,7 @@ template void ns32000_device::execute else interrupt(UND); break; - case ns32000_slave_interface::FORMAT_12: + case 0xfe: // format 12: xxxx xyyy yyoo oo0f 1111 1110 if ((m_cfg & CFG_F) && type() == NS32332) { @@ -3459,7 +3459,7 @@ template void ns32000_device::execute case 0x9e: // format 13 interrupt(UND); break; - case ns32000_slave_interface::FORMAT_14: + case 0x1e: // format 14: xxxx xsss s0oo ooii 0001 1110 if (!(m_psr & PSR_U)) { @@ -3671,7 +3671,7 @@ template u16 ns32000_device::slave(u8 { switch (opbyte) { - case ns32000_slave_interface::FORMAT_14: + case 0x1e: if (!m_mmu) fatalerror("slave mmu coprocessor not configured (%s)\n", machine().describe_context()); @@ -3681,9 +3681,9 @@ template u16 ns32000_device::slave(u8 return slave_slow(dynamic_cast(*m_mmu), opbyte, opword, op1, op2); break; - case ns32000_slave_interface::FORMAT_9: - case ns32000_slave_interface::FORMAT_11: - case ns32000_slave_interface::FORMAT_12: + case 0x3e: + case 0xbe: + case 0xfe: if (!m_fpu) fatalerror("slave fpu coprocessor not configured (%s)\n", machine().describe_context()); @@ -3701,8 +3701,8 @@ template u16 ns32000_device::slave(u8 template u16 ns32000_device::slave_slow(ns32000_slow_slave_interface &slave, u8 opbyte, u16 opword, addr_mode op1, addr_mode op2) { - slave.slow_write(opbyte); - slave.slow_write(swapendian_int16(opword)); + slave.write_id(opbyte); + slave.write_op(swapendian_int16(opword)); if ((op1.access == READ || op1.access == RMW) && !(op1.type == REG && op1.slave)) { @@ -3711,20 +3711,20 @@ template u16 ns32000_device::slave_sl switch (op1.size) { case SIZE_B: - slave.slow_write(u8(data)); + slave.write_op(u8(data)); break; case SIZE_W: - slave.slow_write(u16(data)); + slave.write_op(u16(data)); break; case SIZE_D: - slave.slow_write(u16(data >> 0)); - slave.slow_write(u16(data >> 16)); + slave.write_op(u16(data >> 0)); + slave.write_op(u16(data >> 16)); break; case SIZE_Q: - slave.slow_write(u16(data >> 0)); - slave.slow_write(u16(data >> 16)); - slave.slow_write(u16(data >> 32)); - slave.slow_write(u16(data >> 48)); + slave.write_op(u16(data >> 0)); + slave.write_op(u16(data >> 16)); + slave.write_op(u16(data >> 32)); + slave.write_op(u16(data >> 48)); break; } } @@ -3732,8 +3732,8 @@ template u16 ns32000_device::slave_sl { u32 const data = ea(op1); - slave.slow_write(u16(data >> 0)); - slave.slow_write(u16(data >> 16)); + slave.write_op(u16(data >> 0)); + slave.write_op(u16(data >> 16)); // single-byte memory read cycle mem_read(ns32000::ST_ODT, data, true); @@ -3746,41 +3746,41 @@ template u16 ns32000_device::slave_sl switch (op2.size) { case SIZE_B: - slave.slow_write(u8(data)); + slave.write_op(u8(data)); break; case SIZE_W: - slave.slow_write(u16(data)); + slave.write_op(u16(data)); break; case SIZE_D: - slave.slow_write(u16(data >> 0)); - slave.slow_write(u16(data >> 16)); + slave.write_op(u16(data >> 0)); + slave.write_op(u16(data >> 16)); break; case SIZE_Q: - slave.slow_write(u16(data >> 0)); - slave.slow_write(u16(data >> 16)); - slave.slow_write(u16(data >> 32)); - slave.slow_write(u16(data >> 48)); + slave.write_op(u16(data >> 0)); + slave.write_op(u16(data >> 16)); + slave.write_op(u16(data >> 32)); + slave.write_op(u16(data >> 48)); break; } } - u16 const status = slave.slow_status(&m_icount); + u16 const status = slave.read_st(&m_icount); if (!(status & ns32000_slave_interface::SLAVE_Q)) { if ((op2.access == WRITE || op2.access == RMW) && !(op2.type == REG && op2.slave)) { - u64 data = slave.slow_read(); + u64 data = slave.read_op(); switch (op2.size) { case SIZE_D: - data |= u64(slave.slow_read()) << 16; + data |= u64(slave.read_op()) << 16; break; case SIZE_Q: - data |= u64(slave.slow_read()) << 16; - data |= u64(slave.slow_read()) << 32; - data |= u64(slave.slow_read()) << 48; + data |= u64(slave.read_op()) << 16; + data |= u64(slave.read_op()) << 32; + data |= u64(slave.read_op()) << 48; break; default: break; @@ -3795,7 +3795,7 @@ template u16 ns32000_device::slave_sl template u16 ns32000_device::slave_fast(ns32000_fast_slave_interface &slave, u8 opbyte, u16 opword, addr_mode op1, addr_mode op2) { - slave.fast_write(u32(opbyte) << 24 | u32(swapendian_int16(opword)) << 8); + slave.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 u16 ns32000_device::slave_fa switch (op1.size) { case SIZE_B: - slave.fast_write(u8(data)); + slave.write(u8(data)); break; case SIZE_W: - slave.fast_write(u16(data)); + slave.write(u16(data)); break; case SIZE_D: - slave.fast_write(u32(data)); + slave.write(u32(data)); break; case SIZE_Q: - slave.fast_write(u32(data >> 0)); - slave.fast_write(u32(data >> 32)); + slave.write(u32(data >> 0)); + slave.write(u32(data >> 32)); break; } } @@ -3822,7 +3822,7 @@ template u16 ns32000_device::slave_fa { u32 const data = ea(op1); - slave.fast_write(u32(data)); + slave.write(u32(data)); // single-byte memory read cycle mem_read(ns32000::ST_ODT, data, true); @@ -3835,32 +3835,32 @@ template u16 ns32000_device::slave_fa switch (op2.size) { case SIZE_B: - slave.fast_write(u8(data)); + slave.write(u8(data)); break; case SIZE_W: - slave.fast_write(u16(data)); + slave.write(u16(data)); break; case SIZE_D: - slave.fast_write(u32(data)); + slave.write(u32(data)); break; case SIZE_Q: - slave.fast_write(u32(data >> 0)); - slave.fast_write(u32(data >> 32)); + slave.write(u32(data >> 0)); + slave.write(u32(data >> 32)); break; } } // TODO: status is optional in fast protocol - u32 const status = slave.fast_status(&m_icount); + u32 const status = slave.read_st32(&m_icount); if (!(status & ns32000_slave_interface::SLAVE_Q)) { if ((op2.access == WRITE || op2.access == RMW) && !(op2.type == REG && op2.slave)) { - u64 data = slave.fast_read(); + u64 data = slave.read(); if (op2.size == SIZE_Q) - data |= u64(slave.fast_read()) << 32; + data |= u64(slave.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 == FORMAT_14) + if (opbyte == 0x1e) { switch (BIT(opword, 2, 4)) { diff --git a/src/devices/cpu/ns32000/ns32000d.cpp b/src/devices/cpu/ns32000/ns32000d.cpp index 170e2c7ae88..4b9c49f813d 100644 --- a/src/devices/cpu/ns32000/ns32000d.cpp +++ b/src/devices/cpu/ns32000/ns32000d.cpp @@ -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, 2) ? SIZE_D : SIZE_Q; + size_code const size_f = BIT(opword, 0) ? 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, 2) ? 'F' : 'L', mode[0].mode, mode[1].mode); + util::stream_format(stream, "MOV%c%c %s, %s", size_char[size], BIT(opword, 0) ? '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, 2) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode); + util::stream_format(stream, "ROUND%c%c %s, %s", BIT(opword, 0) ? '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, 2) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode); + util::stream_format(stream, "TRUNC%c%c %s, %s", BIT(opword, 0) ? '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, 2) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode); + util::stream_format(stream, "FLOOR%c%c %s, %s", BIT(opword, 0) ? 'F' : 'L', size_char[size], mode[0].mode, mode[1].mode); break; } } diff --git a/src/devices/machine/ns32081.cpp b/src/devices/machine/ns32081.cpp index ab406a84d04..ca648423701 100644 --- a/src/devices/machine/ns32081.cpp +++ b/src/devices/machine/ns32081.cpp @@ -8,9 +8,7 @@ * - Microprocessor Databook, Series 32000, NSC800, 1989 Edition, National Semiconductor * * TODO: - * - poly/scalb/logb/dot - * - ns32381 timing - * - no-result operations + * - NS32381 */ #include "emu.h" @@ -23,7 +21,6 @@ #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 { @@ -34,7 +31,6 @@ 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 @@ -65,159 +61,149 @@ 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 }; -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) +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) , ns32000_fpu_interface(mconfig, *this) { } -void ns32081_device_base::device_start() +void ns32081_device::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_tcy)); m_complete = timer_alloc(FUNC(ns32081_device::complete), this); } -void ns32081_device_base::device_reset() +void ns32081_device::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_base::state_add(device_state_interface &parent, int &index) +void ns32081_device::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"); } -template T ns32081_device_base::read() +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() { if (m_state == RESULT && m_op[2].issued < m_op[2].expected) { - T const data = m_op[2].value >> (m_op[2].issued * 8); + 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()); - 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()); + m_op[2].issued += 2; if (m_op[2].issued == m_op[2].expected) { - LOG("read complete\n"); + LOG("read_op last result word issued\n"); m_state = IDLE; } return data; } - logerror("read protocol error (%s)\n", machine().describe_context()); + logerror("protocol error reading result word (%s)\n", machine().describe_context()); return 0; } -template void ns32081_device_base::write(T data) +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) { 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: - LOG("write opword 0x%0*x (%s)\n", sizeof(T) * 2, data, machine().describe_context()); + m_opword = swapendian_int16(data); + LOG("write_op opword 0x%04x (%s)\n", m_opword, 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) + // initialize operands + for (operand &op : m_op) { - 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); + op.expected = 0; + op.issued = 0; + op.value = 0; } - 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) - { - op.expected = 0; - op.issued = 0; - op.value = 0; - } - - switch (m_idbyte) - { - case FORMAT_9: + // decode operands + if (m_idbyte == 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 (BIT(m_opword, 3, 3)) + switch ((m_opword >> 3) & 7) { case 0: // movif m_op[0].expected = size + 1; @@ -245,11 +231,10 @@ bool ns32081_device_base::decode(u8 const idbyte, u16 const opword) break; } } - break; - case FORMAT_11: + else if (m_idbyte == FORMAT_11) { // format 11: 1111 1222 22oo oo0f - unsigned const opcode = BIT(m_opword, 2, 4); + unsigned const opcode = (m_opword >> 2) & 15; unsigned const f_length = BIT(m_opword, 0) ? LENGTH_F : LENGTH_L; m_op[0].expected = f_length; @@ -262,65 +247,69 @@ bool ns32081_device_base::decode(u8 const idbyte, u16 const opword) 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)) + // operand 1 in register + if (m_op[0].expected && !(m_opword & 0xc000)) + { + // exclude integer operands + if (m_idbyte == FORMAT_11 || ((m_opword >> 3) & 7) > 1) { - 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; + 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; + + m_op[0].issued = m_op[0].expected; } } - 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 && !BIT(m_opword, 14, 2)) - { - // exclude integer operands - if (m_idbyte != FORMAT_9 || (BIT(m_opword, 3, 3) > 1)) + // operand 2 in register + if (m_op[1].expected && !(m_opword & 0x0600)) { - reg_get(m_op[0].expected, m_op[0].value, BIT(m_opword, 11, 3)); + unsigned const reg = (m_opword >> 6) & 7; + LOG("write_op read f%d\n", reg); - m_op[0].issued = m_op[0].expected; + m_op[1].value = m_f[reg ^ 0]; + if (m_op[1].expected == 8) + m_op[1].value |= u64(m_f[reg ^ 1]) << 32; + + 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; } - // operand 2 in register - if (m_op[1].expected && !BIT(m_opword, 9, 2)) - { - reg_get(m_op[1].expected, m_op[1].value, BIT(m_opword, 6, 3)); - - m_op[1].issued = m_op[1].expected; - } - - return true; + // 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(); } -void ns32081_device_base::execute() +void ns32081_device::execute() { + softfloat_exceptionFlags = 0; u32 const fsr = m_fsr; m_fsr &= ~FSR_TT; - softfloat_exceptionFlags = 0; m_status = 0; m_tcy = 0; @@ -328,247 +317,235 @@ void ns32081_device_base::execute() { case FORMAT_9: // format 9: 1111 1222 22oo ofii - switch (BIT(m_opword, 3, 3)) { - case 0: - // MOVif src,dest - // gen,gen - // read.i,write.f - { - s32 const src = util::sext(m_op[0].value, m_op[0].expected * 8); + bool const single = BIT(m_opword, 2); + unsigned const f_length = single ? LENGTH_F : LENGTH_L; + unsigned const size = m_opword & 3; - if (m_op[2].expected == LENGTH_F) - m_op[2].value = i32_to_f32(src).v; + switch ((m_opword >> 3) & 7) + { + 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); + + if (single) + 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; + case 1: + // LFSR src + // gen + // read.D + m_fsr = u16(m_op[0].value); + + switch (m_fsr & FSR_RM) + { + case RM_N: softfloat_roundingMode = softfloat_round_near_even; break; + case RM_Z: softfloat_roundingMode = softfloat_round_minMag; break; + case RM_U: softfloat_roundingMode = softfloat_round_max; break; + case RM_D: softfloat_roundingMode = softfloat_round_min; break; + } + m_tcy = 18; + break; + case 2: + // MOVLF src,dest + // 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; + 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; + break; + case 4: + // ROUNDfi src,dest + // gen,gen + // read.f,write.i + if (single) + m_op[2].value = f32_to_i64(float32_t{ u32(m_op[0].value) }, softfloat_round_near_even, true); else - m_op[2].value = i32_to_f64(src).v; + m_op[2].value = f64_to_i64(float64_t{ m_op[0].value }, softfloat_round_near_even, true); - m_tcy = 53; + 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))) + softfloat_exceptionFlags |= softfloat_flag_overflow; + + m_op[2].expected = size + 1; + m_tcy = (m_opword & 0xc000) ? 53 : 66; + break; + case 5: + // TRUNCfi src,dest + // gen,gen + // read.f,write.i + if (single) + 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))) + softfloat_exceptionFlags |= softfloat_flag_overflow; + + m_op[2].expected = size + 1; + m_tcy = (m_opword & 0xc000) ? 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) + 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))) + softfloat_exceptionFlags |= softfloat_flag_overflow; + + m_op[2].expected = size + 1; + m_tcy = (m_opword & 0xc000) ? 53 : 66; + break; } - break; - case 1: - // LFSR src - // gen - // read.D - m_fsr = u16(m_op[0].value); - - switch (m_fsr & FSR_RM) - { - case RM_N: softfloat_roundingMode = softfloat_round_near_even; break; - case RM_Z: softfloat_roundingMode = softfloat_round_minMag; break; - case RM_U: softfloat_roundingMode = softfloat_round_max; break; - case RM_D: softfloat_roundingMode = softfloat_round_min; break; - } - m_tcy = 18; - break; - case 2: - // MOVLF src,dest - // gen,gen - // read.L,write.F - m_op[2].value = f64_to_f32(float64_t{ m_op[0].value }).v; - - 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_tcy = BIT(m_opword, 14, 2) ? 22 : 26; - break; - case 4: - // ROUNDfi src,dest - // gen,gen - // read.f,write.i - 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 (s64(m_op[2].value) != util::sext(m_op[2].value, m_op[2].expected * 8)) - softfloat_exceptionFlags |= softfloat_flag_overflow; - - m_tcy = BIT(m_opword, 14, 2) ? 53 : 66; - break; - case 5: - // TRUNCfi src,dest - // gen,gen - // read.f,write.i - 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 (s64(m_op[2].value) != util::sext(m_op[2].value, m_op[2].expected * 8)) - softfloat_exceptionFlags |= softfloat_flag_overflow; - - m_tcy = BIT(m_opword, 14, 2) ? 53 : 66; - break; - case 6: - // SFSR dest - // gen - // write.D - m_op[2].value = fsr; - - m_tcy = 13; - break; - case 7: - // FLOORfi src,dest - // gen,gen - // read.f,write.i - 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 (s64(m_op[2].value) != util::sext(m_op[2].value, m_op[2].expected * 8)) - softfloat_exceptionFlags |= softfloat_flag_overflow; - - m_tcy = BIT(m_opword, 14, 2) ? 53 : 66; - break; } break; case FORMAT_11: - // format 11: 1111 1222 22oo oo0f - switch (BIT(m_opword, 2, 4)) + // format 11: 1111122222oooo0f { - case 0x0: - // ADDf src,dest - // gen,gen - // read.f,rmw.f - 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; + bool const single = BIT(m_opword, 0); + unsigned const f_length = single ? LENGTH_F : LENGTH_L; - m_tcy = (m_opword & 0xc600) ? 70 : 74; - break; - case 0x1: - // MOVf src,dest - // gen,gen - // read.f,write.f - m_op[2].value = m_op[0].value; - - m_tcy = BIT(m_opword, 14, 2) ? 23 : 27; - break; - case 0x2: - // CMPf src1,src2 - // gen,gen - // read.f,read.f - if (m_op[0].value == m_op[1].value) - m_status |= SLAVE_Z; - 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: - // Trap(SLAVE) - m_fsr |= TT_ILL; - m_status = SLAVE_Q; - break; - case 0x4: - // SUBf src,dest - // gen,gen - // read.f,rmw.f - 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_tcy = (m_opword & 0xc600) ? 70 : 74; - break; - case 0x5: - // NEGf src,dest - // gen,gen - // read.f,write.f - 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_tcy = BIT(m_opword, 14, 2) ? 20 : 24; - break; - case 0x8: - // DIVf src,dest - // gen,gen - // read.f,rmw.f - 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_tcy = ((m_opword & 0xc600) ? 55 : 59) + (m_op[0].expected == LENGTH_F ? 30 : 60); - break; - case 0x9: - // Trap(SLAVE) - m_fsr |= TT_ILL; - m_status = SLAVE_Q; - break; - case 0xc: - // MULf src,dest - // gen,gen - // read.f,rmw.f - 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_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 (m_op[0].expected == LENGTH_F) - if (f32_lt(float32_t{ u32(m_op[0].value) }, float32_t{ 0 })) + switch ((m_opword >> 2) & 15) + { + case 0x0: + // ADDf src,dest + // gen,gen + // read.f,rmw.f + if (single) + 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: + // MOVf src,dest + // 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; + break; + case 0x2: + // CMPf src1,src2 + // gen,gen + // 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 }))) + m_status |= SLAVE_N; + m_tcy = (m_opword & 0xc600) ? 45 : 49; + break; + case 0x3: + // Trap(SLAVE) + m_fsr |= TT_ILL; + m_status = SLAVE_Q; + break; + case 0x4: + // SUBf src,dest + // gen,gen + // read.f,rmw.f + if (single) + 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) m_op[2].value = f32_mul(float32_t{ u32(m_op[0].value) }, i32_to_f32(-1)).v; else - m_op[2].value = float32_t{ u32(m_op[0].value) }.v; - else - if (f64_lt(float64_t{ m_op[0].value }, float64_t{ 0 })) 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; + break; + case 0x8: + // DIVf src,dest + // gen,gen + // read.f,rmw.f + if (single) + 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 = float64_t{ m_op[0].value }.v; - - 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; + 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); + break; + case 0x9: + // Trap(SLAVE) + m_fsr |= TT_ILL; + m_status = SLAVE_Q; + break; + case 0xc: + // MULf src,dest + // gen,gen + // read.f,rmw.f + if (single) + 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); + break; + case 0xd: + // ABSf src,dest + // gen,gen + // read.f,write.f + if (single) + 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 + m_op[2].value = float32_t{ u32(m_op[0].value) }.v; + else + if (f64_lt(float64_t{ m_op[0].value }, float64_t{ 0 })) + 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; + break; + } } break; } @@ -618,177 +595,47 @@ void ns32081_device_base::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", operation, m_op[0].value, m_op[1].value); + 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); else - LOG("execute %s 0x%x,0x%x result 0x%x\n", operation, m_op[0].value, m_op[1].value, m_op[2].value); + 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); } // write-back floating point register results - if (m_op[2].expected && !BIT(m_opword, 9, 2)) + if (m_op[2].expected && !(m_opword & 0x0600)) { // exclude integer results (roundfi, truncfi, sfsr, floorfi) - if (m_idbyte != FORMAT_9 || (BIT(m_opword, 3, 3) < 4)) + if (m_idbyte == FORMAT_11 || ((m_opword >> 3) & 7) < 4) { - reg_set(BIT(m_opword, 6, 3), m_op[2].expected, m_op[2].value); + unsigned const reg = (m_opword >> 6) & 7; - if (type() == NS32381) - m_fsr |= FSR_RMB; + 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); 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; } -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) +void ns32081_device::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); -} diff --git a/src/devices/machine/ns32081.h b/src/devices/machine/ns32081.h index 12a50d9434d..89847175e43 100644 --- a/src/devices/machine/ns32081.h +++ b/src/devices/machine/ns32081.h @@ -8,119 +8,54 @@ #include "cpu/ns32000/common.h" -class ns32081_device_base - : public device_t - , 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 T read(); - template 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 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); - // 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(); } - virtual void slow_write(u16 data) override { write(data); } + 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; 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; + void execute(); + void complete(s32 param); private: + emu_timer *m_complete; + // registers + u32 m_fsr; u32 m_f[8]; -}; -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); + // operating state + u8 m_idbyte; + u16 m_opword; + struct operand + { + unsigned expected; + unsigned issued; + u64 value; + } + m_op[3]; + u16 m_status; - // 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(); } - virtual void slow_write(u16 data) override { write(data); } - - // ns32000_fast_slave_interface implementation - virtual u32 fast_status(int *icount = nullptr) override { return status(icount); } - virtual u32 fast_read() override { return read(); } - virtual void fast_write(u32 data) override { write(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]; + // implementation state + unsigned m_state; + unsigned m_tcy; }; DECLARE_DEVICE_TYPE(NS32081, ns32081_device) -DECLARE_DEVICE_TYPE(NS32381, ns32381_device) #endif // MAME_MACHINE_NS32081_H diff --git a/src/devices/machine/ns32082.cpp b/src/devices/machine/ns32082.cpp index 4fb26bf5219..e58cf546e62 100644 --- a/src/devices/machine/ns32082.cpp +++ b/src/devices/machine/ns32082.cpp @@ -34,6 +34,11 @@ enum state : unsigned RESULT = 6, // result word available }; +enum idbyte : u8 +{ + FORMAT_14 = 0x1e, +}; + enum reg_mask : unsigned { BPR0 = 0x0, // breakpoint register 0 @@ -122,8 +127,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_mmu_interface(mconfig, *this) , ns32000_slow_slave_interface(mconfig, *this) + , ns32000_mmu_interface(mconfig, *this) , m_bpr{} , m_pf{} , m_sc(0) @@ -167,7 +172,7 @@ void ns32082_device::state_add(device_state_interface &parent, int &index) parent.state_add(index++, "MSR", m_msr).formatstr("%08X"); } -u16 ns32082_device::slow_status(int *icount) +u16 ns32082_device::read_st(int *icount) { if (m_state == STATUS) { @@ -176,54 +181,63 @@ u16 ns32082_device::slow_status(int *icount) if (icount) *icount -= m_tcy; - LOG("status 0x%04x tcy %d %s (%s)\n", m_status, 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("status protocol error (%s)\n", machine().describe_context()); + logerror("read_st protocol error reading status word (%s)\n", machine().describe_context()); return 0; } -u16 ns32082_device::slow_read() +u16 ns32082_device::read_op() { 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 %d data 0x%04x (%s)\n", m_op[2].issued >> 1, data, machine().describe_context()); + LOG("read_op word %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 complete\n"); + LOG("read_op last result word issued\n"); m_state = IDLE; } return data; } - logerror("read protocol error (%s)\n", machine().describe_context()); + logerror("read_op protocol error reading result word (%s)\n", machine().describe_context()); return 0; } -void ns32082_device::slow_write(u16 data) +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) { 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 opword 0x%04x (%s)\n", m_opword, machine().describe_context()); + LOG("write_op opword 0x%04x (%s)\n", m_opword, machine().describe_context()); m_tcy = 0; @@ -268,16 +282,14 @@ void ns32082_device::slow_write(u16 data) unsigned const n = (m_op[0].issued < m_op[0].expected) ? 0 : 1; operand &op = m_op[n]; - LOG("write operand %d data 0x%04x (%s)\n", - n, data, machine().describe_context()); + 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("write protocol error unexpected operand data 0x%04x (%s)\n", - data, machine().describe_context()); + logerror("write_op protocol error unexpected operand word 0x%04x (%s)\n", data, machine().describe_context()); break; } diff --git a/src/devices/machine/ns32082.h b/src/devices/machine/ns32082.h index b8232e25116..41986941bb2 100644 --- a/src/devices/machine/ns32082.h +++ b/src/devices/machine/ns32082.h @@ -10,25 +10,24 @@ class ns32082_device : public device_t - , public ns32000_mmu_interface , public ns32000_slow_slave_interface + , public ns32000_mmu_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; - // 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; + 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_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 implementation + // device_t overrides virtual void device_start() override; virtual void device_reset() override; @@ -52,16 +51,16 @@ private: u16 m_opword; struct operand { - u32 expected; - u32 issued; + unsigned expected; + unsigned issued; u64 value; } m_op[3]; u16 m_status; // implementation state - u32 m_state; - u32 m_tcy; + unsigned m_state; + unsigned m_tcy; }; DECLARE_DEVICE_TYPE(NS32082, ns32082_device) diff --git a/src/mame/homebrew/pc532.cpp b/src/mame/homebrew/pc532.cpp index d05b9f317e2..b168505b8f3 100644 --- a/src/mame/homebrew/pc532.cpp +++ b/src/mame/homebrew/pc532.cpp @@ -10,6 +10,7 @@ * - https://www.nic.funet.fi/pub/misc/pc532/ * * TODO: + * - ns32381 * - et532 * * WIP: @@ -46,7 +47,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") @@ -60,6 +61,7 @@ public: { } + void init(); void pc532(machine_config &config); protected: @@ -69,7 +71,7 @@ protected: template void cpu_map(address_map &map); required_device m_cpu; - required_device m_fpu; + //required_device m_fpu; required_device m_icu; required_device m_rtc; @@ -111,6 +113,12 @@ 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 @@ -304,8 +312,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); - 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(); @@ -319,7 +327,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( // DP8490 + NSCSI_CONNECTOR(config, "slot:7").option_set("ncr5380", NCR5380).machine_config( [this](device_t *device) { ncr5380_device &ncr5380(downcast(*device)); @@ -404,5 +412,5 @@ ROM_END } // anonymous namespace -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -COMP(1989, pc532, 0, 0, pc532, 0, pc532_state, empty_init, "George Scolaro", "pc532", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW) +/* 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)