diff options
Diffstat (limited to 'src/devices/cpu/ns32000/ns32000.cpp')
-rw-r--r-- | src/devices/cpu/ns32000/ns32000.cpp | 1659 |
1 files changed, 1211 insertions, 448 deletions
diff --git a/src/devices/cpu/ns32000/ns32000.cpp b/src/devices/cpu/ns32000/ns32000.cpp index 4b796f8f345..acfddfcdd29 100644 --- a/src/devices/cpu/ns32000/ns32000.cpp +++ b/src/devices/cpu/ns32000/ns32000.cpp @@ -14,14 +14,14 @@ DEFINE_DEVICE_TYPE(NS32032, ns32032_device, "ns32032", "National Semiconductor N /* * TODO: * - prefetch queue - * - fetch/ea/data/rmw cycles + * - fetch/ea/data/rmw bus cycles * - address translation/abort - * - floating point and other unimplemented instructions + * - unimplemented instructions * - format 6: subp,addp - * - format 7: cmpm * - format 8: movus/movsu + * - format 14: rdval,wrval,lmr,smr * - cascaded interrupts - * - instruction cycles + * - opcode/operand/memory clock cycles * - 32332, 32532 */ @@ -71,22 +71,15 @@ enum trap_type : unsigned UND = 10, // undefined opcode }; -enum size_code : unsigned -{ - SIZE_B = 0, - SIZE_W = 1, - SIZE_D = 3, - SIZE_Q = 7, -}; - static const u32 size_mask[] = { 0x000000ffU, 0x0000ffffU, 0x00000000U, 0xffffffffU }; #define SP ((m_psr & PSR_S) ? m_sp1 : m_sp0) -ns32000_device::ns32000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int databits, int addrbits) +template <int Width>ns32000_device<Width>::ns32000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int databits, int addrbits) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_LITTLE, databits, addrbits, 0) , m_interrupt_config("interrupt", ENDIANNESS_LITTLE, databits, addrbits, 0) + , m_fpu(*this, finder_base::DUMMY_TAG) , m_icount(0) { } @@ -106,7 +99,7 @@ ns32032_device::ns32032_device(const machine_config &mconfig, const char *tag, d { } -void ns32000_device::device_start() +template <int Width> void ns32000_device<Width>::device_start() { set_icountptr(m_icount); @@ -132,27 +125,27 @@ void ns32000_device::device_start() state_add(STATE_GENFLAGS, "GENFLAGS", m_psr).mask(0xfe7).formatstr("%10s").noshow(); // dedicated registers - int const reg_base = 16; - state_add(reg_base + 0, "PC", m_pc); - state_add(reg_base + 1, "SB", m_sb); - state_add(reg_base + 2, "FP", m_fp); - state_add(reg_base + 3, "SP1", m_sp1); - state_add(reg_base + 4, "SP0", m_sp0); - state_add(reg_base + 5, "INTBASE", m_intbase); - state_add(reg_base + 6, "PSR", m_psr); - state_add(reg_base + 7, "MOD", m_mod); - state_add(reg_base + 8, "CFG", m_cfg); + int index = 0; + state_add(index++, "PC", m_pc); + state_add(index++, "SB", m_sb); + state_add(index++, "FP", m_fp); + state_add(index++, "SP1", m_sp1); + state_add(index++, "SP0", m_sp0); + state_add(index++, "INTBASE", m_intbase); + state_add(index++, "PSR", m_psr); + state_add(index++, "MOD", m_mod); + state_add(index++, "CFG", m_cfg); // general registers for (unsigned i = 0; i < 8; i++) - state_add(i, util::string_format("R%d", i).c_str(), m_r[i]); + state_add(index++, util::string_format("R%d", i).c_str(), m_r[i]); // floating point registers - //for (unsigned i = 0; i < 8; i++) - // state_add(8 + i, util::string_format("F%d", i).c_str(), m_f[i]); + if (m_fpu) + m_fpu->state_add(*this, index); } -void ns32000_device::device_reset() +template <int Width> void ns32000_device<Width>::device_reset() { for (std::pair<int, address_space_config const *> s : memory_space_config()) space(has_configured_map(s.first) ? s.first : 0).cache(m_bus[s.first]); @@ -166,7 +159,7 @@ void ns32000_device::device_reset() m_wait = false; } -void ns32000_device::state_string_export(device_state_entry const &entry, std::string &str) const +template <int Width> void ns32000_device<Width>::state_string_export(device_state_entry const &entry, std::string &str) const { switch (entry.index()) { @@ -186,7 +179,7 @@ void ns32000_device::state_string_export(device_state_entry const &entry, std::s } } -s32 ns32000_device::displacement(unsigned &bytes) +template <int Width> s32 ns32000_device<Width>::displacement(unsigned &bytes) { s32 disp = space(0).read_byte(m_pc + bytes); if (BIT(disp, 7)) @@ -214,7 +207,7 @@ s32 ns32000_device::displacement(unsigned &bytes) return disp; } -void ns32000_device::decode(addr_mode *mode, unsigned imm_size, unsigned &bytes) +template <int Width> void ns32000_device<Width>::decode(addr_mode *mode, unsigned &bytes) { bool scaled[] = { false, false }; @@ -277,12 +270,14 @@ void ns32000_device::decode(addr_mode *mode, unsigned imm_size, unsigned &bytes) break; case 0x14: // immediate - switch (imm_size) + switch (mode[i].size) { - case SIZE_B: mode[i].base = space(0).read_byte(m_pc + bytes); bytes += 1; break; - case SIZE_W: mode[i].base = swapendian_int16(space(0).read_word_unaligned(m_pc + bytes)); bytes += 2; break; - case SIZE_D: mode[i].base = swapendian_int32(space(0).read_dword_unaligned(m_pc + bytes)); bytes += 4; break; + case SIZE_B: mode[i].imm = space(0).read_byte(m_pc + bytes); break; + case SIZE_W: mode[i].imm = swapendian_int16(space(0).read_word_unaligned(m_pc + bytes)); break; + case SIZE_D: mode[i].imm = swapendian_int32(space(0).read_dword_unaligned(m_pc + bytes)); break; + case SIZE_Q: mode[i].imm = swapendian_int64(space(0).read_qword_unaligned(m_pc + bytes)); break; } + bytes += mode[i].size + 1; mode[i].type = IMM; break; case 0x15: @@ -325,7 +320,7 @@ void ns32000_device::decode(addr_mode *mode, unsigned imm_size, unsigned &bytes) } } -u32 ns32000_device::ea(addr_mode const mode) +template <int Width> u32 ns32000_device<Width>::ea(addr_mode const mode) { u32 base; @@ -352,38 +347,36 @@ u32 ns32000_device::ea(addr_mode const mode) return base + mode.disp; } -u64 ns32000_device::gen_read(addr_mode mode, unsigned size) +template <int Width> u64 ns32000_device<Width>::gen_read(addr_mode mode) { u64 data = 0; switch (mode.type) { case IMM: - data = mode.base; + data = mode.imm; break; case REG: - if (size == SIZE_Q) - data = (u64(m_r[mode.gen ^ 1]) << 32) | m_r[mode.gen ^ 0]; - else - data = m_r[mode.gen] & size_mask[size]; + data = m_r[mode.gen] & size_mask[mode.size]; break; case TOS: - if (size) - if (size == 3) - data = space(0).read_dword_unaligned(SP); - else - data = space(0).read_word_unaligned(SP); - else - data = space(0).read_byte(SP); + switch (mode.size) + { + case SIZE_B: data = space(0).read_byte(SP); break; + case SIZE_W: data = space(0).read_word_unaligned(SP); break; + case SIZE_D: data = space(0).read_dword_unaligned(SP); break; + case SIZE_Q: data = space(0).read_qword_unaligned(SP); break; + } // post-increment stack pointer - SP += size + 1; + if (mode.access == READ) + SP += mode.size + 1; break; default: - switch (size) + switch (mode.size) { case SIZE_B: data = space(0).read_byte(ea(mode)); break; case SIZE_W: data = space(0).read_word_unaligned(ea(mode)); break; @@ -396,11 +389,11 @@ u64 ns32000_device::gen_read(addr_mode mode, unsigned size) return data; } -s64 ns32000_device::gen_read_sx(addr_mode mode, unsigned size) +template <int Width> s64 ns32000_device<Width>::gen_read_sx(addr_mode mode) { - u64 data = gen_read(mode, size); + u64 data = gen_read(mode); - switch (size) + switch (mode.size) { case SIZE_B: data = s8(data); break; case SIZE_W: data = s16(data); break; @@ -411,35 +404,30 @@ s64 ns32000_device::gen_read_sx(addr_mode mode, unsigned size) return data; } -void ns32000_device::gen_write(addr_mode mode, unsigned size, u64 data) +template <int Width> void ns32000_device<Width>::gen_write(addr_mode mode, u64 data) { switch (mode.type) { case REG: - if (size == SIZE_Q) - { - m_r[mode.gen ^ 0] = u32(data); - m_r[mode.gen ^ 1] = data >> 32; - } - else - m_r[mode.gen] = (m_r[mode.gen] & ~size_mask[size]) | (data & size_mask[size]); + m_r[mode.gen] = (m_r[mode.gen] & ~size_mask[mode.size]) | (data & size_mask[mode.size]); break; case TOS: // pre-decrement stack pointer - SP -= size + 1; + if (mode.access == WRITE) + SP -= mode.size + 1; - if (size) - if (size == 3) - space(0).write_dword_unaligned(SP, data); - else - space(0).write_word_unaligned(SP, data); - else - space(0).write_byte(SP, data); + switch (mode.size) + { + case SIZE_B: space(0).write_byte(SP, data); break; + case SIZE_W: space(0).write_word_unaligned(SP, data); break; + case SIZE_D: space(0).write_dword_unaligned(SP, data); break; + case SIZE_Q: space(0).write_qword_unaligned(SP, data); break; + } break; default: - switch (size) + switch (mode.size) { case SIZE_B: space(0).write_byte(ea(mode), data); break; case SIZE_W: space(0).write_word_unaligned(ea(mode), data); break; @@ -450,7 +438,7 @@ void ns32000_device::gen_write(addr_mode mode, unsigned size, u64 data) } } -bool ns32000_device::condition(unsigned const cc) +template <int Width> bool ns32000_device<Width>::condition(unsigned const cc) { switch (cc & 15) { @@ -492,7 +480,7 @@ bool ns32000_device::condition(unsigned const cc) return false; } -void ns32000_device::flags(u32 const src1, u32 const src2, u32 const dest, unsigned const size, bool const subtraction) +template <int Width> void ns32000_device<Width>::flags(u32 const src1, u32 const src2, u32 const dest, unsigned const size, bool const subtraction) { unsigned const sign_bit = (size + 1) * 8 - 1; @@ -508,7 +496,7 @@ void ns32000_device::flags(u32 const src1, u32 const src2, u32 const dest, unsig m_psr |= PSR_F; } -void ns32000_device::interrupt(unsigned const vector, u32 const return_address, bool const trap) +template <int Width> void ns32000_device<Width>::interrupt(unsigned const vector, u32 const return_address, bool const trap) { // clear trace pending flag if (vector == TRC) @@ -541,9 +529,13 @@ void ns32000_device::interrupt(unsigned const vector, u32 const return_address, m_pc = space(0).read_dword_unaligned(m_mod + 8) + u16(descriptor >> 16); // TODO: flush queue + m_sequential = false; + + if (trap && (machine().debug_flags & DEBUG_FLAG_ENABLED)) + debug()->exception_hook(vector); } -void ns32000_device::execute_run() +template <int Width> void ns32000_device<Width>::execute_run() { while (m_icount > 0) { @@ -597,18 +589,24 @@ void ns32000_device::execute_run() u8 const opbyte = space(0).read_byte(m_pc); unsigned bytes = 1; + unsigned tcy = 1; + m_sequential = true; if ((opbyte & 15) == 10) { // format 0: cccc 1010 - // Bcond dest + // Bcond dst // disp - s32 const dest = displacement(bytes); + s32 const dst = displacement(bytes); if (condition(opbyte >> 4)) - m_pc += dest; + { + m_pc += dst; + m_sequential = false; + tcy = 6; + } else - m_pc += bytes; + tcy = 7; } else if ((opbyte & 15) == 2) { @@ -616,15 +614,17 @@ void ns32000_device::execute_run() switch (opbyte >> 4) { case 0x0: - // BSR dest + // BSR dst // disp { - s32 const dest = displacement(bytes); + s32 const dst = displacement(bytes); SP -= 4; space(0).write_dword_unaligned(SP, m_pc + bytes); - m_pc += dest; + m_pc += dst; + m_sequential = false; + tcy = 6; } break; case 0x1: @@ -637,6 +637,8 @@ void ns32000_device::execute_run() SP += 4 + constant; m_pc = addr; + m_sequential = false; + tcy = 2; } break; case 0x2: @@ -656,6 +658,8 @@ void ns32000_device::execute_run() m_mod = u16(descriptor); m_sb = space(0).read_dword_unaligned(m_mod + 0); m_pc = space(0).read_dword_unaligned(m_mod + 8) + u16(descriptor >> 16); + m_sequential = false; + tcy = 16; } break; case 0x3: @@ -671,6 +675,8 @@ void ns32000_device::execute_run() m_sb = space(0).read_dword_unaligned(m_mod + 0); SP += constant; + m_sequential = false; + tcy = 2; } break; case 0x4: @@ -691,6 +697,8 @@ void ns32000_device::execute_run() m_sb = space(0).read_dword_unaligned(m_mod); SP += constant; + m_sequential = false; + tcy = 35; } else interrupt(ILL, m_pc); @@ -711,6 +719,8 @@ void ns32000_device::execute_run() sp += 2; m_sb = space(0).read_dword_unaligned(m_mod); + m_sequential = false; + tcy = 39; } else interrupt(ILL, m_pc); @@ -721,16 +731,17 @@ void ns32000_device::execute_run() { u8 const reglist = space(0).read_byte(m_pc + bytes++); + tcy = 13; for (unsigned i = 0; i < 8; i++) { if (BIT(reglist, i)) { SP -= 4; space(0).write_dword_unaligned(SP, m_r[i]); + tcy += 4; } } } - m_pc += bytes; break; case 0x7: // RESTORE reglist @@ -738,16 +749,17 @@ void ns32000_device::execute_run() { u8 const reglist = space(0).read_byte(m_pc + bytes++); + tcy = 12; for (unsigned i = 0; i < 8; i++) { if (BIT(reglist, i)) { m_r[7 - i] = space(0).read_dword_unaligned(SP); SP += 4; + tcy += 5; } } } - m_pc += bytes; break; case 0x8: // ENTER reglist,constant @@ -761,16 +773,17 @@ void ns32000_device::execute_run() m_fp = SP; SP -= constant; + tcy = 18; for (unsigned i = 0; i < 8; i++) { if (BIT(reglist, i)) { SP -= 4; space(0).write_dword_unaligned(SP, m_r[i]); + tcy += 4; } } } - m_pc += bytes; break; case 0x9: // EXIT reglist @@ -778,47 +791,54 @@ void ns32000_device::execute_run() { u8 const reglist = space(0).read_byte(m_pc + bytes++); + tcy = 17; for (unsigned i = 0; i < 8; i++) { if (BIT(reglist, i)) { m_r[7 - i] = space(0).read_dword_unaligned(SP); SP += 4; + tcy += 5; } } SP = m_fp; m_fp = space(0).read_dword_unaligned(SP); SP += 4; } - m_pc += bytes; break; case 0xa: // NOP - m_pc += bytes; + tcy = 3; break; case 0xb: // WAIT m_wait = true; - m_pc += bytes; + tcy = 6; break; case 0xc: // DIA m_wait = true; + tcy = 3; break; case 0xd: // FLAG if (m_psr & PSR_F) + { interrupt(FLG, m_pc); + tcy = 44; + } else - m_pc += bytes; + tcy = 6; break; case 0xe: // SVC interrupt(SVC, m_pc); + tcy = 40; break; case 0xf: // BPT interrupt(BPT, m_pc); + tcy = 40; break; } } @@ -832,187 +852,201 @@ void ns32000_device::execute_run() addr_mode mode[] = { addr_mode((opword >> 11) & 31), addr_mode(0x13) }; unsigned const quick = (opword >> 7) & 15; - unsigned const size = opbyte & 3; - - decode(mode, size, bytes); + size_code const size = size_code(opbyte & 3); switch ((opbyte >> 4) & 7) { case 0: - // ADDQi src,dest + // ADDQi src,dst // quick,gen // rmw.i { - mode[0].rmw(); + mode[0].rmw_i(size); + decode(mode, bytes); u32 const src1 = s32(quick << 28) >> 28; - u32 const src2 = gen_read(mode[0], size); + u32 const src2 = gen_read(mode[0]); - u32 const dest = src1 + src2; - flags(src1, src2, dest, size, false); + u32 const dst = src1 + src2; + flags(src1, src2, dst, size, false); - gen_write(mode[0], size, dest); + gen_write(mode[0], dst); + + tcy = (mode[0].type == REG) ? 4 : 6; } - m_pc += bytes; break; case 1: // CMPQi src1,src2 // quick,gen // read.i { - u32 const src1 = s32(quick << 28) >> 28; - u32 const src2 = gen_read(mode[0], size); + mode[0].read_i(size); + decode(mode, bytes); + + u32 const src1 = (s32(quick << 28) >> 28) & size_mask[size]; + u32 const src2 = gen_read(mode[0]); m_psr &= ~(PSR_N | PSR_Z | PSR_L); if ((size == SIZE_D && s32(src1) > s32(src2)) - || ((size == SIZE_W && s16(src1) > s16(src2)) - || ((size == SIZE_B && s8(src1) > s8(src2))))) + || ((size == SIZE_W && s16(src1) > s16(src2)) + || ((size == SIZE_B && s8(src1) > s8(src2))))) m_psr |= PSR_N; if (src1 == src2) m_psr |= PSR_Z; if ((size == SIZE_D && u32(src1) > u32(src2)) - || ((size == SIZE_W && u16(src1) > u16(src2)) - || ((size == SIZE_B && u8(src1) > u8(src2))))) + || ((size == SIZE_W && u16(src1) > u16(src2)) + || ((size == SIZE_B && u8(src1) > u8(src2))))) m_psr |= PSR_L; + + tcy = 3; } - m_pc += bytes; break; case 2: - // SPRi procreg,dest + // SPRi procreg,dst // short,gen // write.i + mode[0].write_i(size); + decode(mode, bytes); + switch (quick) { case 0x0: // US // TODO: user stack pointer? - gen_write(mode[0], size, m_sp1); - m_pc += bytes; + gen_write(mode[0], m_sp1); break; case 0x8: // FP - gen_write(mode[0], size, m_fp); - m_pc += bytes; + gen_write(mode[0], m_fp); break; case 0x9: // SP - gen_write(mode[0], size, SP); - m_pc += bytes; + gen_write(mode[0], SP); break; case 0xa: // SB - gen_write(mode[0], size, m_sb); - m_pc += bytes; + gen_write(mode[0], m_sb); break; case 0xd: // PSR if (!(m_psr & PSR_U)) - { - gen_write(mode[0], size, m_psr); - m_pc += bytes; - } + gen_write(mode[0], m_psr); else interrupt(ILL, m_pc); break; case 0xe: // INTBASE if (!(m_psr & PSR_U)) - { - gen_write(mode[0], size, m_intbase); - m_pc += bytes; - } + gen_write(mode[0], m_intbase); else interrupt(ILL, m_pc); break; case 0xf: // MOD - gen_write(mode[0], size, m_mod); - m_pc += bytes; + gen_write(mode[0], m_mod); break; } + + // TODO: tcy 21-27 + tcy = 21; break; case 3: - // Scondi dest + // Scondi dst // gen // write.i - gen_write(mode[0], size, condition(quick)); - m_pc += bytes; + { + mode[0].write_i(size); + decode(mode, bytes); + + bool const dst = condition(quick); + gen_write(mode[0], dst); + + tcy = dst ? 10 : 9; + } break; case 4: - // ACBi inc,index,dest + // ACBi inc,index,dst // quick,gen,disp // rmw.i { - mode[0].rmw(); + mode[0].rmw_i(size); + decode(mode, bytes); s32 const inc = s32(quick << 28) >> 28; - u32 index = gen_read(mode[0], size); - s32 const dest = displacement(bytes); + u32 index = gen_read(mode[0]); + s32 const dst = displacement(bytes); index += inc; - gen_write(mode[0], size, index); + gen_write(mode[0], index); if (index & size_mask[size]) - m_pc += dest; + { + m_pc += dst; + m_sequential = false; + + tcy = (mode[0].type == REG) ? 17 : 15; + } else - m_pc += bytes; + tcy = (mode[0].type == REG) ? 18 : 16; } break; case 5: - // MOVQi src,dest + // MOVQi src,dst // quick,gen // write.i - gen_write(mode[0], size, s32(quick << 28) >> 28); - m_pc += bytes; + mode[0].write_i(size); + decode(mode, bytes); + + gen_write(mode[0], s32(quick << 28) >> 28); + + tcy = (mode[0].type == REG) ? 3 : 2; break; case 6: // LPRi procreg,src // short,gen // read.i + mode[0].read_i(size); + decode(mode, bytes); + switch (quick) { - case 0x0: // US - // TODO: user stack pointer? - m_sp1 = gen_read(mode[0], size); - m_pc += bytes; + case 0x0: // UPSR + m_psr = (m_psr & 0xff00) | u8(gen_read(mode[0])); break; case 0x8: // FP - m_fp = gen_read(mode[0], size); - m_pc += bytes; + m_fp = gen_read(mode[0]); break; case 0x9: // SP - SP = gen_read(mode[0], size); - m_pc += bytes; + SP = gen_read(mode[0]); break; case 0xa: // SB - m_sb = gen_read(mode[0], size); - m_pc += bytes; + m_sb = gen_read(mode[0]); break; case 0xd: // PSR if (!(m_psr & PSR_U)) { - u32 const src = gen_read(mode[0], size); + u32 const src = gen_read(mode[0]); - if (size == 0) + if (size == SIZE_B) m_psr = (m_psr & 0xff00) | u8(src); else m_psr = src; - - m_pc += bytes; } else interrupt(ILL, m_pc); break; case 0xe: // INTBASE if (!(m_psr & PSR_U)) - { - m_intbase = gen_read(mode[0], size); - m_pc += bytes; - } + m_intbase = gen_read(mode[0]); else interrupt(ILL, m_pc); break; case 0xf: // MOD - m_mod = gen_read(mode[0], size); - m_pc += bytes; + m_mod = gen_read(mode[0]); + break; + default: + interrupt(UND, m_pc); break; } + + // TODO: tcy 19-33 + tcy = 19; break; case 7: // format 3: gggg gooo o111 11ii @@ -1022,96 +1056,142 @@ void ns32000_device::execute_run() // CXPD desc // gen // addr + if (size == SIZE_D) { mode[0].addr(); + decode(mode, bytes); - u32 const desc = gen_read(mode[0], SIZE_D); + u32 const descriptor = gen_read(mode[0]); SP -= 4; space(0).write_dword_unaligned(SP, m_mod); SP -= 4; space(0).write_dword_unaligned(SP, m_pc + bytes); - m_mod = u16(desc); + m_mod = u16(descriptor); m_sb = space(0).read_dword_unaligned(m_mod + 0); - m_pc = u16(desc >> 16) + space(0).read_dword_unaligned(m_mod + 8); + m_pc = space(0).read_dword_unaligned(m_mod + 8) + u16(descriptor >> 16); + m_sequential = false; + + tcy = 13; } + else + interrupt(UND, m_pc); break; case 0x2: // BICPSRi src // gen // read.[BW] - if (size == 0 || !(m_psr & PSR_U)) + if (size == SIZE_B || size == SIZE_W) { - // FIXME: read.D? - u16 const src = gen_read(mode[0], size); + mode[0].read_i(size); + decode(mode, bytes); + + if (size == SIZE_B || !(m_psr & PSR_U)) + { + u16 const src = gen_read(mode[0]); + + m_psr &= ~src; - m_psr &= ~src; - m_pc += bytes; + tcy = (size == SIZE_B) ? 18 : 30; + } + else + interrupt(ILL, m_pc); } else - interrupt(ILL, m_pc); + interrupt(UND, m_pc); break; case 0x4: - // JUMP dest + // JUMP dst // gen // addr - mode[0].addr(); + if (size == SIZE_D) + { + mode[0].addr(); + decode(mode, bytes); - // FIXME: size != 3? - m_pc = ea(mode[0]); + m_pc = ea(mode[0]); + m_sequential = false; + + tcy = 2; + } + else + interrupt(UND, m_pc); break; case 0x6: // BISPSRi src // gen // read.[BW] - if (size == 0 || !(m_psr & PSR_U)) + if (size == SIZE_B || size == SIZE_W) { - // FIXME: read.D? + mode[0].read_i(size); + decode(mode, bytes); + + if (size == SIZE_B || !(m_psr & PSR_U)) + { + u16 const src = gen_read(mode[0]); - u16 const src = gen_read(mode[0], size); + m_psr |= src; - m_psr |= src; - m_pc += bytes; + tcy = (size == SIZE_B) ? 18 : 30; + } + else + interrupt(ILL, m_pc); } else - interrupt(ILL, m_pc); + interrupt(UND, m_pc); break; case 0xa: // ADJSPi src // gen // read.i { - s32 const src = gen_read_sx(mode[0], size); + mode[0].read_i(size); + decode(mode, bytes); + + s32 const src = gen_read_sx(mode[0]); SP -= src; + + tcy = 6; } - m_pc += bytes; break; case 0xc: - // JSR dest + // JSR dst // gen // addr + if (size == SIZE_D) { mode[0].addr(); + decode(mode, bytes); SP -= 4; space(0).write_dword_unaligned(SP, m_pc + bytes); m_pc = ea(mode[0]); + m_sequential = false; + + tcy = 5; } + else + interrupt(UND, m_pc); break; case 0xe: // CASEi src // gen // read.i { - s32 const src = gen_read_sx(mode[0], size); + mode[0].read_i(size); + decode(mode, bytes); + + s32 const src = gen_read_sx(mode[0]); m_pc += src; + m_sequential = false; + + tcy = 4; } break; - default: interrupt(UND, m_pc); break; @@ -1126,175 +1206,214 @@ void ns32000_device::execute_run() bytes = 2; addr_mode mode[2] = { addr_mode((opword >> 11) & 31), addr_mode((opword >> 6) & 31) }; - unsigned const size = opbyte & 3; - - decode(mode, size, bytes); + size_code const size = size_code(opbyte & 3); switch ((opbyte >> 2) & 15) { case 0x0: - // ADDi src,dest + // ADDi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); + + u32 const src1 = gen_read(mode[0]); + u32 const src2 = gen_read(mode[1]); - u32 const src1 = gen_read(mode[0], size); - u32 const src2 = gen_read(mode[1], size); + u32 const dst = src1 + src2; + flags(src1, src2, dst, size, false); - u32 const dest = src1 + src2; - flags(src1, src2, dest, size, false); + gen_write(mode[1], dst); - gen_write(mode[1], size, dest); + tcy = (mode[1].type == REG) ? 4 : 3; } - m_pc += bytes; break; case 0x1: // CMPi src1,src2 // gen,gen // read.i,read.i { - u32 const src1 = gen_read(mode[0], size); - u32 const src2 = gen_read(mode[1], size); + mode[0].read_i(size); + mode[1].read_i(size); + decode(mode, bytes); + + u32 const src1 = gen_read(mode[0]); + u32 const src2 = gen_read(mode[1]); m_psr &= ~(PSR_N | PSR_Z | PSR_L); if ((size == SIZE_D && s32(src1) > s32(src2)) - || ((size == SIZE_W && s16(src1) > s16(src2)) - || ((size == SIZE_B && s8(src1) > s8(src2))))) + || ((size == SIZE_W && s16(src1) > s16(src2)) + || ((size == SIZE_B && s8(src1) > s8(src2))))) m_psr |= PSR_N; if (src1 == src2) m_psr |= PSR_Z; if ((size == SIZE_D && u32(src1) > u32(src2)) - || ((size == SIZE_W && u16(src1) > u16(src2)) - || ((size == SIZE_B && u8(src1) > u8(src2))))) + || ((size == SIZE_W && u16(src1) > u16(src2)) + || ((size == SIZE_B && u8(src1) > u8(src2))))) m_psr |= PSR_L; + + tcy = 3; } - m_pc += bytes; break; case 0x2: - // BICi src,dest + // BICi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); + + u32 const src = gen_read(mode[0]); + u32 const dst = gen_read(mode[1]); - u32 const src = gen_read(mode[0], size); - u32 const dest = gen_read(mode[1], size); + gen_write(mode[1], dst & ~src); - gen_write(mode[1], size, dest & ~src); + tcy = (mode[1].type == REG) ? 4 : 3; } - m_pc += bytes; break; case 0x4: - // ADDCi src,dest + // ADDCi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); + + u32 const src1 = gen_read(mode[0]); + u32 const src2 = gen_read(mode[1]); - u32 const src1 = gen_read(mode[0], size); - u32 const src2 = gen_read(mode[1], size); + u32 const dst = src1 + src2 + (m_psr & PSR_C); + flags(src1, src2, dst, size, false); - u32 const dest = src1 + src2 + (m_psr & PSR_C); - flags(src1, src2, dest, size, false); + gen_write(mode[1], dst); - gen_write(mode[1], size, dest); + tcy = (mode[1].type == REG) ? 4 : 3; } - m_pc += bytes; break; case 0x5: - // MOVi src,dest + // MOVi src,dst // gen,gen // read.i,write.i { - u32 const src = gen_read(mode[0], size); + mode[0].read_i(size); + mode[1].write_i(size); + decode(mode, bytes); - gen_write(mode[1], size, src); + u32 const src = gen_read(mode[0]); + + gen_write(mode[1], src); + + tcy = (mode[1].type == REG) ? 3 : 1; } - m_pc += bytes; break; case 0x6: - // ORi src,dest + // ORi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); + + u32 const src = gen_read(mode[0]); + u32 const dst = gen_read(mode[1]); - u32 const src = gen_read(mode[0], size); - u32 const dest = gen_read(mode[1], size); + gen_write(mode[1], src | dst); - gen_write(mode[1], size, src | dest); + tcy = (mode[1].type == REG) ? 4 : 3; } - m_pc += bytes; break; case 0x8: - // SUBi src,dest + // SUBi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); - u32 const src1 = gen_read(mode[0], size); - u32 const src2 = gen_read(mode[1], size); + u32 const src1 = gen_read(mode[0]); + u32 const src2 = gen_read(mode[1]); - u32 const dest = src2 - src1; - flags(src1, src2, dest, size, true); + u32 const dst = src2 - src1; + flags(src1, src2, dst, size, true); - gen_write(mode[1], size, dest); + gen_write(mode[1], dst); + + tcy = (mode[1].type == REG) ? 4 : 3; } - m_pc += bytes; break; case 0x9: - // ADDR src,dest + // ADDR src,dst // gen,gen // addr,write.D - mode[0].addr(); + if (size == SIZE_D) + { + mode[0].addr(); + mode[1].write_i(size); + decode(mode, bytes); + + gen_write(mode[1], ea(mode[0])); - gen_write(mode[1], SIZE_D, ea(mode[0])); - m_pc += bytes; + tcy = (mode[1].type == REG) ? 3 : 2; + } + else + interrupt(UND, m_pc); break; case 0xa: - // ANDi src,dest + // ANDi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); + + u32 const src = gen_read(mode[0]); + u32 const dst = gen_read(mode[1]); - u32 const src = gen_read(mode[0], size); - u32 const dest = gen_read(mode[1], size); + gen_write(mode[1], src & dst); - gen_write(mode[1], size, src & dest); + tcy = (mode[1].type == REG) ? 4 : 3; } - m_pc += bytes; break; case 0xc: - // SUBCi src,dest + // SUBCi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); - u32 const src1 = gen_read(mode[0], size); - u32 const src2 = gen_read(mode[1], size); + u32 const src1 = gen_read(mode[0]); + u32 const src2 = gen_read(mode[1]); - u32 const dest = src2 - src1 - (m_psr & PSR_C); - flags(src1, src2, dest, size, true); + u32 const dst = src2 - src1 - (m_psr & PSR_C); + flags(src1, src2, dst, size, true); - gen_write(mode[1], size, dest); + gen_write(mode[1], dst); + + tcy = (mode[1].type == REG) ? 4 : 3; } - m_pc += bytes; break; case 0xd: // TBITi offset,base // gen,gen // read.i,regaddr { + mode[0].read_i(size); mode[1].regaddr(); + decode(mode, bytes); - s32 const offset = gen_read_sx(mode[0], size); + s32 const offset = gen_read_sx(mode[0]); if (mode[1].type == REG) { @@ -1302,6 +1421,8 @@ void ns32000_device::execute_run() m_psr |= PSR_F; else m_psr &= ~PSR_F; + + tcy = 4; } else { @@ -1311,23 +1432,27 @@ void ns32000_device::execute_run() m_psr |= PSR_F; else m_psr &= ~PSR_F; + + tcy = 14; } } - m_pc += bytes; break; case 0xe: - // XORi src,dest + // XORi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); - u32 const src = gen_read(mode[0], size); - u32 const dest = gen_read(mode[1], size); + u32 const src = gen_read(mode[0]); + u32 const dst = gen_read(mode[1]); - gen_write(mode[1], size, src ^ dest); + gen_write(mode[1], src ^ dst); + + tcy = (mode[1].type == REG) ? 4 : 3; } - m_pc += bytes; break; } } @@ -1339,7 +1464,7 @@ void ns32000_device::execute_run() u16 const opword = space(0).read_word_unaligned(m_pc + bytes); bytes += 2; - unsigned const size = opword & 3; + size_code const size = size_code(opword & 3); // string instruction options bool const translate = BIT(opword, 7); @@ -1350,6 +1475,8 @@ void ns32000_device::execute_run() { case 0: // MOVSi options + tcy = (translate || backward || uw) ? 54 : 18; + m_psr &= ~PSR_F; while (m_r[0]) { @@ -1361,6 +1488,8 @@ void ns32000_device::execute_run() if (translate) data = space(0).read_byte(m_r[3] + u8(data)); + tcy += translate ? 27 : (backward || uw) ? 24 : 13; + bool const match = !((m_r[4] ^ data) & size_mask[size]); if ((uw == 1 && !match) || (uw == 3 && match)) { @@ -1388,10 +1517,11 @@ void ns32000_device::execute_run() m_r[0]--; } - m_pc += bytes; break; case 1: // CMPSi options + tcy = 53; + m_psr |= PSR_Z; m_psr &= ~(PSR_N | PSR_F | PSR_L); while (m_r[0]) @@ -1408,6 +1538,8 @@ void ns32000_device::execute_run() if (translate) src1 = space(0).read_byte(m_r[3] + u8(src1)); + tcy += translate ? 38 : 35; + bool const match = !((m_r[4] ^ src1) & size_mask[size]); if ((uw == 1 && !match) || (uw == 3 && match)) { @@ -1420,13 +1552,13 @@ void ns32000_device::execute_run() m_psr &= ~PSR_Z; if ((size == SIZE_D && s32(src1) > s32(src2)) - || ((size == SIZE_W && s16(src1) > s16(src2)) - || ((size == SIZE_B && s8(src1) > s8(src2))))) + || ((size == SIZE_W && s16(src1) > s16(src2)) + || ((size == SIZE_B && s8(src1) > s8(src2))))) m_psr |= PSR_N; if ((size == SIZE_D && u32(src1) > u32(src2)) - || ((size == SIZE_W && u16(src1) > u16(src2)) - || ((size == SIZE_B && u8(src1) > u8(src2))))) + || ((size == SIZE_W && u16(src1) > u16(src2)) + || ((size == SIZE_B && u8(src1) > u8(src2))))) m_psr |= PSR_L; break; @@ -1445,7 +1577,6 @@ void ns32000_device::execute_run() m_r[0]--; } - m_pc += bytes; break; case 2: // SETCFG cfglist @@ -1453,13 +1584,16 @@ void ns32000_device::execute_run() if (!(m_psr & PSR_U)) { m_cfg = (opword >> 7) & 15; - m_pc += bytes; + + tcy = 15; } else interrupt(ILL, m_pc); break; case 3: // SKPSi options + tcy = 51; + m_psr &= ~PSR_F; while (m_r[0]) { @@ -1471,6 +1605,8 @@ void ns32000_device::execute_run() if (translate) data = space(0).read_byte(m_r[3] + u8(data)); + tcy += translate ? 30 : 27; + bool const match = !((m_r[4] ^ data) & size_mask[size]); if ((uw == 1 && !match) || (uw == 3 && match)) { @@ -1485,7 +1621,6 @@ void ns32000_device::execute_run() m_r[0]--; } - m_pc += bytes; break; default: interrupt(UND, m_pc); @@ -1500,45 +1635,48 @@ void ns32000_device::execute_run() bytes += 2; addr_mode mode[] = { addr_mode((opword >> 11) & 31), addr_mode((opword >> 6) & 31) }; - unsigned const size = opword & 3; - - // byte-size immediates for ROT, ASH and LSH - decode(mode, ((opword >> 2) & 10) ? size : SIZE_B, bytes); + size_code const size = size_code(opword & 3); switch ((opword >> 2) & 15) { case 0x0: - // ROTi count,dest + // ROTi count,dst // gen,gen // read.B,rmw.i { - mode[1].rmw(); + mode[0].read_i(SIZE_B); + mode[1].rmw_i(size); + decode(mode, bytes); - s32 const count = gen_read_sx(mode[0], SIZE_B); - u32 const src = gen_read(mode[1], size); + s32 const count = gen_read_sx(mode[0]); + u32 const src = gen_read(mode[1]); unsigned const limit = (size + 1) * 8 - 1; - u32 const dest = ((src << (count & limit)) & size_mask[size]) | ((src & size_mask[size]) >> (limit - (count & limit))); + u32 const dst = ((src << (count & limit)) & size_mask[size]) | ((src & size_mask[size]) >> (limit - (count & limit) + 1)); + + gen_write(mode[1], dst); - gen_write(mode[1], size, dest); + tcy = 14 + (count & limit); } - m_pc += bytes; break; case 0x1: - // ASHi count,dest + // ASHi count,dst // gen,gen // read.B,rmw.i { - mode[1].rmw(); + mode[0].read_i(SIZE_B); + mode[1].rmw_i(size); + decode(mode, bytes); - s32 const count = gen_read_sx(mode[0], SIZE_B); - s32 const src = gen_read_sx(mode[1], size); + s32 const count = gen_read_sx(mode[0]); + s32 const src = gen_read_sx(mode[1]); - u32 const dest = (count < 0) ? (src >> -count) : (src << count); + u32 const dst = (count < 0) ? (src >> -count) : (src << count); - gen_write(mode[1], size, dest); + gen_write(mode[1], dst); + + tcy = 14 + std::abs(count); } - m_pc += bytes; break; case 0x2: // CBITi offset,base @@ -1549,9 +1687,11 @@ void ns32000_device::execute_run() // gen,gen // read.i,regaddr { + mode[0].read_i(size); mode[1].regaddr(); + decode(mode, bytes); - s32 const offset = gen_read_sx(mode[0], size); + s32 const offset = gen_read_sx(mode[0]); if (mode[1].type == REG) { @@ -1561,6 +1701,8 @@ void ns32000_device::execute_run() m_psr &= ~PSR_F; m_r[mode[1].gen] &= ~(1U << (offset & 31)); + + tcy = 7; } else { @@ -1573,28 +1715,32 @@ void ns32000_device::execute_run() m_psr &= ~PSR_F; space(0).write_byte(byte_ea, byte & ~(1U << (offset & 7))); + + tcy = 15; } } - m_pc += bytes; break; case 0x4: interrupt(UND, m_pc); break; case 0x5: - // LSHi count,dest + // LSHi count,dst // gen,gen // read.B,rmw.i { - mode[1].rmw(); + mode[0].read_i(SIZE_B); + mode[1].rmw_i(size); + decode(mode, bytes); + + s32 const count = gen_read_sx(mode[0]); + u32 const src = gen_read(mode[1]); - s32 const count = gen_read_sx(mode[0], SIZE_B); - u32 const src = gen_read(mode[1], size); + u32 const dst = (count < 0) ? (src >> -count) : (src << count); - u32 const dest = (count < 0) ? (src >> -count) : (src << count); + gen_write(mode[1], dst); - gen_write(mode[1], size, dest); + tcy = 14 + std::abs(count); } - m_pc += bytes; break; case 0x6: // SBITi offset,base @@ -1605,9 +1751,11 @@ void ns32000_device::execute_run() // gen,gen // read.i,regaddr { + mode[0].read_i(size); mode[1].regaddr(); + decode(mode, bytes); - s32 const offset = gen_read_sx(mode[0], size); + s32 const offset = gen_read_sx(mode[0]); if (mode[1].type == REG) { @@ -1616,7 +1764,9 @@ void ns32000_device::execute_run() else m_psr &= ~PSR_F; - m_r[mode[1].gen] |= ~(1U << (offset & 31)); + m_r[mode[1].gen] |= (1U << (offset & 31)); + + tcy = 7; } else { @@ -1628,17 +1778,22 @@ void ns32000_device::execute_run() else m_psr &= ~PSR_F; - space(0).write_byte(byte_ea, byte | ~(1U << (offset & 7))); + space(0).write_byte(byte_ea, byte | (1U << (offset & 7))); + + tcy = 15; } } - m_pc += bytes; break; case 0x8: - // NEGi src,dest + // NEGi src,dst // gen,gen // read.i,write.i { - u32 const src = gen_read(mode[0], size); + mode[0].read_i(size); + mode[1].write_i(size); + decode(mode, bytes); + + u32 const src = gen_read(mode[0]); if (src) m_psr |= PSR_C; @@ -1648,75 +1803,93 @@ void ns32000_device::execute_run() if ((src ^ ~(size_mask[size] >> 1)) & size_mask[size]) { m_psr &= ~PSR_F; - gen_write(mode[1], size, -src); + gen_write(mode[1], -src); } else { m_psr |= PSR_F; - gen_write(mode[1], size, src); + gen_write(mode[1], src); } + + tcy = 5; } - m_pc += bytes; break; case 0x9: - // NOTi src,dest + // NOTi src,dst // gen,gen // read.i,write.i { - u32 const src = gen_read(mode[0], size); + mode[0].read_i(size); + mode[1].write_i(size); + decode(mode, bytes); - gen_write(mode[1], size, src ^ 1U); + u32 const src = gen_read(mode[0]); + + gen_write(mode[1], src ^ 1U); + + tcy = 5; } - m_pc += bytes; break; case 0xa: interrupt(UND, m_pc); break; case 0xb: - // SUBPi src,dest + // SUBPi src,dst // gen,gen // read.i,rmw.i fatalerror("unimplemented: subp (%s)\n", machine().describe_context()); + + // TODO: tcy 16/18 break; case 0xc: - // ABSi src,dest + // ABSi src,dst // gen,gen // read.i,write.i { - s32 const src = gen_read_sx(mode[0], size); + mode[0].read_i(size); + mode[1].write_i(size); + decode(mode, bytes); - s32 const dest = std::abs(src); + s32 const src = gen_read_sx(mode[0]); m_psr &= ~PSR_F; - if (BIT(dest, ((size + 1) * 8 - 1))) + if (src == s32(0x80000000) >> (32 - (size + 1) * 8)) { m_psr |= PSR_F; - gen_write(mode[1], size, src); + gen_write(mode[1], src); } else - gen_write(mode[1], size, dest); + gen_write(mode[1], std::abs(src)); + + tcy = (src < 0) ? 9 : 8; } - m_pc += bytes; break; case 0xd: - // COMi src,dest + // COMi src,dst // gen,gen // read.i,write.i { - u32 const src = gen_read(mode[0], size); + mode[0].read_i(size); + mode[1].write_i(size); + decode(mode, bytes); + + u32 const src = gen_read(mode[0]); + + gen_write(mode[1], ~src); - gen_write(mode[1], size, ~src); + tcy = 7; } - m_pc += bytes; break; case 0xe: // IBITi offset,base // gen,gen // read.i,regaddr { + mode[0].read_i(size); mode[1].regaddr(); + decode(mode, bytes); - s32 const offset = gen_read_sx(mode[0], size); + s32 const offset = gen_read_sx(mode[0]); if (mode[1].type == REG) { @@ -1726,6 +1899,8 @@ void ns32000_device::execute_run() m_psr &= ~PSR_F; m_r[mode[1].gen] ^= (1U << (offset & 31)); + + tcy = 9; } else { @@ -1738,15 +1913,18 @@ void ns32000_device::execute_run() m_psr &= ~PSR_F; space(0).write_byte(byte_ea, byte ^ (1U << (offset & 7))); + + tcy = 17; } } - m_pc += bytes; break; case 0xf: - // ADDPi src,dest + // ADDPi src,dst // gen,gen // read.i,rmw.i fatalerror("unimplemented: addp (%s)\n", machine().describe_context()); + + // TODO: tcy 16/18 break; } } @@ -1758,9 +1936,7 @@ void ns32000_device::execute_run() bytes += 2; addr_mode mode[2] = { addr_mode((opword >> 11) & 31), addr_mode((opword >> 6) & 31) }; - unsigned const size = opword & 3; - - decode(mode, size, bytes); + size_code const size = size_code(opword & 3); switch ((opword >> 2) & 15) { @@ -1771,164 +1947,280 @@ void ns32000_device::execute_run() { mode[0].addr(); mode[1].addr(); + decode(mode, bytes); u32 block1 = ea(mode[0]); u32 block2 = ea(mode[1]); - s32 length = displacement(bytes); + unsigned const num = displacement(bytes) / (size + 1) + 1; // TODO: aligned/unaligned transfers? - for (unsigned num = 0; num * (size + 1) < length; num++) + for (unsigned i = 0; i < num; i++) { switch (size) { case SIZE_B: space(0).write_byte(block2, space(0).read_byte(block1)); break; case SIZE_W: space(0).write_word_unaligned(block2, space(0).read_word_unaligned(block1)); break; case SIZE_D: space(0).write_dword_unaligned(block2, space(0).read_dword_unaligned(block1)); break; + default: + // can't happen + break; } block1 += (size + 1); block2 += (size + 1); } + + tcy = 20 + 3 * num; } - m_pc += bytes; break; case 0x1: // CMPMi block1,block2,length // gen,gen,disp // addr,addr - fatalerror("unimplemented: cmpm (%s)\n", machine().describe_context()); + { + mode[0].addr(); + mode[1].addr(); + decode(mode, bytes); + + u32 block1 = ea(mode[0]); + u32 block2 = ea(mode[1]); + unsigned const num = displacement(bytes) / (size + 1) + 1; + + tcy = 24; + + m_psr |= PSR_Z; + m_psr &= ~(PSR_N | PSR_L); + + // TODO: aligned/unaligned transfers? + for (unsigned i = 0; i < num; i++) + { + s32 int1 = 0; + s32 int2 = 0; + + switch (size) + { + case SIZE_B: + int1 = s8(space(0).read_byte(block1)); + int2 = s8(space(0).read_byte(block2)); + break; + case SIZE_W: + int1 = s16(space(0).read_word_unaligned(block1)); + int2 = s16(space(0).read_word_unaligned(block2)); + break; + case SIZE_D: + int1 = s32(space(0).read_dword_unaligned(block1)); + int2 = s32(space(0).read_dword_unaligned(block2)); + break; + default: + // can't happen + break; + } + + tcy += 9; + + if (int1 != int2) + { + m_psr &= ~PSR_Z; + if (int1 > int2) + m_psr |= PSR_N; + if (u32(int1) > u32(int2)) + m_psr |= PSR_L; + + break; + } + + block1 += (size + 1); + block2 += (size + 1); + } + } break; case 0x2: // INSSi src,base,offset,length // gen,gen,imm // read.i,regaddr { + mode[0].read_i(size); mode[1].regaddr(); + decode(mode, bytes); u8 const imm = space(0).read_byte(m_pc + bytes++); unsigned const offset = imm >> 5; u32 const mask = ((2ULL << (imm & 31)) - 1) << offset; - u32 const src = gen_read(mode[0], size); - u32 const base = gen_read(mode[1], SIZE_D); + u32 const src = gen_read(mode[0]); + u32 const base = gen_read(mode[1]); - gen_write(mode[1], SIZE_D, (base & ~mask) | ((src << offset) & mask)); + gen_write(mode[1], (base & ~mask) | ((src << offset) & mask)); + + // TODO: tcy 39-49 + tcy = 39; } - m_pc += bytes; break; case 0x3: - // EXTSi base,dest,offset,length + // EXTSi base,dst,offset,length // gen,gen,imm // regaddr,write.i { mode[0].regaddr(); + mode[1].write_i(size); + decode(mode, bytes); u8 const imm = space(0).read_byte(m_pc + bytes++); unsigned const offset = imm >> 5; u32 const mask = (2ULL << (imm & 31)) - 1; - u32 const base = gen_read(mode[0], SIZE_D); - u32 const dest = (base >> offset) & mask; + u32 const base = gen_read(mode[0]); + u32 const dst = (base >> offset) & mask; + + gen_write(mode[1], dst); - gen_write(mode[1], size, dest); + // TODO: tcy 26-36 + tcy = 26; } - m_pc += bytes; break; case 0x4: - // MOVXBW src,dest + // MOVXBW src,dst // gen,gen // read.B,write.W + if (size == SIZE_B) { - u8 const src = gen_read(mode[0], size); - s16 const dest = s8(src); + mode[0].read_i(size); + mode[1].write_i(SIZE_W); + decode(mode, bytes); + + u8 const src = gen_read(mode[0]); + s16 const dst = s8(src); - gen_write(mode[1], SIZE_W, dest); + gen_write(mode[1], dst); + + tcy = 6; } - m_pc += bytes; + else + interrupt(UND, m_pc); break; case 0x5: - // MOVZBW src,dest + // MOVZBW src,dst // gen,gen // read.B,write.W + if (size == SIZE_B) { - u8 const src = gen_read(mode[0], size); - u16 const dest = src; + mode[0].read_i(size); + mode[1].write_i(SIZE_W); + decode(mode, bytes); + + u8 const src = gen_read(mode[0]); + u16 const dst = src; - gen_write(mode[1], SIZE_W, dest); + gen_write(mode[1], dst); + + tcy = 5; } - m_pc += bytes; + else + interrupt(UND, m_pc); break; case 0x6: - // MOVZiD src,dest + // MOVZiD src,dst // gen,gen // read.[BW],write.D + if (size == SIZE_B || size == SIZE_W) { - u32 const src = gen_read(mode[0], size); + mode[0].read_i(size); + mode[1].write_i(SIZE_D); + decode(mode, bytes); - gen_write(mode[1], SIZE_D, src); + u32 const src = gen_read(mode[0]); + + gen_write(mode[1], src); + + tcy = 5; } - m_pc += bytes; + else + interrupt(UND, m_pc); break; case 0x7: - // MOVXiD src,dest + // MOVXiD src,dst // gen,gen // read.[BW],write.D + if (size == SIZE_B || size == SIZE_W) { - u32 const src = gen_read(mode[0], size); - s32 const dest = (size == SIZE_W) ? s16(src) : s8(src); + mode[0].read_i(size); + mode[1].write_i(SIZE_D); + decode(mode, bytes); - gen_write(mode[1], SIZE_D, dest); + u32 const src = gen_read(mode[0]); + s32 const dst = (size == SIZE_W) ? s16(src) : s8(src); + + gen_write(mode[1], dst); + + tcy = 6; } - m_pc += bytes; + else + interrupt(UND, m_pc); break; case 0x8: - // MULi src,dest + // MULi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); - u32 const src1 = gen_read(mode[0], size); - u32 const src2 = gen_read(mode[1], size); + u32 const src1 = gen_read(mode[0]); + u32 const src2 = gen_read(mode[1]); - u32 const dest = src1 * src2; + u32 const dst = src1 * src2; - gen_write(mode[1], size, dest); + gen_write(mode[1], dst); + + tcy = 15; } - m_pc += bytes; break; case 0x9: - // MEIi src,dest + // MEIi src,dst // gen,gen // read.i,rmw.2i { - mode[1].rmw(); - unsigned const size2 = size * 2 + 1; + mode[0].read_i(size); + mode[1].rmw_i(size_code(size * 2 + 1)); + decode(mode, bytes); - u32 const src1 = gen_read(mode[0], size); - u32 const src2 = gen_read(mode[1], size); + u32 const src1 = gen_read(mode[0]); + u32 const src2 = ((mode[1].type == REG) + ? m_r[mode[1].gen ^ 0] + : gen_read(mode[1])) & size_mask[size]; - u64 const dest = mulu_32x32(src1, src2); + u64 const dst = mulu_32x32(src1, src2); - gen_write(mode[1], size2, dest); + if (mode[1].type == REG) + { + m_r[mode[1].gen ^ 0] = (m_r[mode[1].gen ^ 0] & ~size_mask[size]) | ((dst >> 0) & size_mask[size]); + m_r[mode[1].gen ^ 1] = (m_r[mode[1].gen ^ 1] & ~size_mask[size]) | ((dst >> ((size + 1) * 8)) & size_mask[size]); + } + else + gen_write(mode[1], dst); + + tcy = 23; } - m_pc += bytes; break; case 0xa: interrupt(UND, m_pc); break; case 0xb: - // DEIi src,dest + // DEIi src,dst // gen,gen // read.i,rmw.2i { - mode[1].rmw(); - unsigned const size2 = size * 2 + 1; + mode[0].read_i(size); + mode[1].rmw_i(size_code(size * 2 + 1)); + decode(mode, bytes); - u32 const src1 = gen_read(mode[0], size); + u32 const src1 = gen_read(mode[0]); if (src1) { - u64 const src2 = gen_read(mode[1], size2); + u64 const src2 = (mode[1].type == REG) + ? (u64(m_r[mode[1].gen ^ 1] & size_mask[size]) << ((size + 1) * 8)) | (m_r[mode[1].gen ^ 0] & size_mask[size]) + : gen_read(mode[1]); u32 const quotient = src2 / src1; u32 const remainder = src2 % src1; @@ -1937,11 +2229,15 @@ void ns32000_device::execute_run() { m_r[mode[1].gen ^ 0] = (m_r[mode[1].gen ^ 0] & ~size_mask[size]) | (remainder & size_mask[size]); m_r[mode[1].gen ^ 1] = (m_r[mode[1].gen ^ 1] & ~size_mask[size]) | (quotient & size_mask[size]); + + tcy = 31; } else - gen_write(mode[1], size2, (u64(quotient) << ((size + 1) * 8)) | remainder); + { + gen_write(mode[1], (u64(quotient) << ((size + 1) * 8)) | remainder); - m_pc += bytes; + tcy = 38; + } } else { @@ -1954,21 +2250,25 @@ void ns32000_device::execute_run() } break; case 0xc: - // QUOi src,dest + // QUOi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); - s32 const src1 = gen_read_sx(mode[0], size); + s32 const src1 = gen_read_sx(mode[0]); if (src1) { - s32 const src2 = gen_read_sx(mode[1], size); + s32 const src2 = gen_read_sx(mode[1]); + + s32 const dst = src2 / src1; - s32 const dest = src2 / src1; + gen_write(mode[1], dst); - gen_write(mode[1], size, dest); - m_pc += bytes; + // TODO: tcy 49-55 + tcy = 49; } else { @@ -1981,21 +2281,25 @@ void ns32000_device::execute_run() } break; case 0xd: - // REMi src,dest + // REMi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); - s32 const src1 = gen_read_sx(mode[0], size); + s32 const src1 = gen_read_sx(mode[0]); if (src1) { - s32 const src2 = gen_read_sx(mode[1], size); + s32 const src2 = gen_read_sx(mode[1]); + + s32 const dst = src2 % src1; - s32 const dest = src2 % src1; + gen_write(mode[1], dst); - gen_write(mode[1], size, dest); - m_pc += bytes; + // TODO: tcy 57-62 + tcy = 57; } else { @@ -2008,21 +2312,25 @@ void ns32000_device::execute_run() } break; case 0xe: - // MODi src,dest + // MODi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); - u32 const src1 = gen_read_sx(mode[0], size); + s32 const src1 = gen_read_sx(mode[0]); if (src1) { - u32 const src2 = gen_read_sx(mode[1], size); + s32 const src2 = gen_read_sx(mode[1]); - s32 const dest = (src1 + (src2 % src1)) % src1; + s32 const dst = (src1 + (src2 % src1)) % src1; - gen_write(mode[1], size, dest); - m_pc += bytes; + gen_write(mode[1], dst); + + // TODO: tcy 54-73 + tcy = 54; } else { @@ -2035,26 +2343,29 @@ void ns32000_device::execute_run() } break; case 0xf: - // DIVi src,dest + // DIVi src,dst // gen,gen // read.i,rmw.i { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(size); + decode(mode, bytes); - s32 const src1 = gen_read_sx(mode[0], size); + s32 const src1 = gen_read_sx(mode[0]); if (src1) { - s32 const src2 = gen_read_sx(mode[1], size); + s32 const src2 = gen_read_sx(mode[1]); s32 const quotient = src2 / src1; s32 const remainder = src2 % src1; if ((quotient < 0) && remainder) - gen_write(mode[1], size, quotient - 1); + gen_write(mode[1], quotient - 1); else - gen_write(mode[1], size, quotient); + gen_write(mode[1], quotient); - m_pc += bytes; + // TODO: tcy 58-68 + tcy = 58; } else { @@ -2080,108 +2391,150 @@ void ns32000_device::execute_run() addr_mode mode[2] = { addr_mode((opword >> 11) & 31), addr_mode((opword >> 6) & 31) }; unsigned const reg = (opword >> 3) & 7; - unsigned const size = opword & 3; - - decode(mode, size, bytes); + size_code const size = size_code(opword & 3); switch ((opword & 4) | (opbyte >> 6)) { case 0: - // EXTi offset,base,dest,length + // EXTi offset,base,dst,length // reg,gen,gen,disp // regaddr,write.i { mode[0].regaddr(); + mode[1].write_i(size); + decode(mode, bytes); s32 const offset = m_r[reg]; s32 const length = displacement(bytes); u32 const mask = (1U << length) - 1; - u32 dest; + u32 dst; if (mode[0].type != REG) { u32 const base_ea = ea(mode[0]) + (offset >> 3); u32 const base = space(0).read_dword_unaligned(base_ea); - dest = (base >> (offset & 7)); + dst = (base >> (offset & 7)); + + // TODO: tcy 17-51 + tcy = 17; } else - dest = (m_r[mode[0].gen] >> (offset & 31)); + { + dst = (m_r[mode[0].gen] >> (offset & 31)); + + // TODO: tcy 19-29 + tcy = 19; + } - gen_write(mode[1], size, dest & mask); + gen_write(mode[1], dst & mask); } break; case 1: - // CVTP offset,base,dest + // CVTP offset,base,dst // reg,gen,gen // addr,write.D + if (size == SIZE_D) { - // TODO: size != SIZE_D? mode[0].addr(); + mode[1].write_i(size); + decode(mode, bytes); s32 const offset = s32(m_r[reg]); u32 const base = ea(mode[0]); - gen_write(mode[1], size, base * 8 + offset); + gen_write(mode[1], base * 8 + offset); + + tcy = 7; } + else + interrupt(UND, m_pc); break; case 2: // INSi offset,src,base,length // reg,gen,gen,disp // read.i,regaddr { + mode[0].read_i(size); mode[1].regaddr(); + decode(mode, bytes); s32 const offset = m_r[reg]; s32 const length = displacement(bytes); - u32 const src = gen_read(mode[0], size); + u32 const src = gen_read(mode[0]); - u32 dest; + u32 dst; if (mode[1].type == REG) { u32 const base = m_r[mode[1].gen]; u32 const mask = ((1U << length) - 1) << (offset & 31); - dest = (base & ~mask) | ((src << (offset & 31)) & mask); + dst = (base & ~mask) | ((src << (offset & 31)) & mask); + + // TODO: tcy 29-39 + tcy = 29; } else { - u32 const base_ea = ea(mode[0]) + (offset >> 3); + u32 const base_ea = ea(mode[1]) + (offset >> 3); u32 const base = space(0).read_dword_unaligned(base_ea); u32 const mask = ((1U << length) - 1) << (offset & 7); - dest = (base & ~mask) | ((src << (offset & 7)) & mask); + dst = (base & ~mask) | ((src << (offset & 7)) & mask); + + // TODO: tcy 28-96 + tcy = 28; } - gen_write(mode[1], SIZE_D, dest); + gen_write(mode[1], dst); } break; case 3: - // CHECKi dest,bounds,src + // CHECKi dst,bounds,src // reg,gen,gen // addr,read.i { mode[0].addr(); + mode[1].read_i(size); + decode(mode, bytes); u32 const bounds = ea(mode[0]); - s32 const src = gen_read_sx(mode[1], size); + s32 const src = gen_read_sx(mode[1]); s32 lower = 0; s32 upper = 0; switch (size) { - case SIZE_B: lower = s8(space(0).read_byte(bounds + 0)); upper = s8(space(0).read_byte(bounds + 1)); break; - case SIZE_W: lower = s16(space(0).read_word_unaligned(bounds + 0)); upper = s16(space(0).read_word_unaligned(bounds + 2)); break; - case SIZE_D: lower = s32(space(0).read_dword_unaligned(bounds + 0)); upper = s32(space(0).read_dword_unaligned(bounds + 4)); break; + case SIZE_B: + upper = s8(space(0).read_byte(bounds + 0)); + lower = s8(space(0).read_byte(bounds + 1)); + break; + case SIZE_W: + upper = s16(space(0).read_word_unaligned(bounds + 0)); + lower = s16(space(0).read_word_unaligned(bounds + 2)); + break; + case SIZE_D: + upper = s32(space(0).read_dword_unaligned(bounds + 0)); + lower = s32(space(0).read_dword_unaligned(bounds + 4)); + break; + default: + // can't happen + break; } if (src >= lower && src <= upper) { m_psr &= ~PSR_F; m_r[reg] = src - lower; + + tcy = 11; } else + { m_psr |= PSR_F; + + tcy = (src >= lower) ? 7 : 10; + } } break; case 4: @@ -2189,10 +2542,16 @@ void ns32000_device::execute_run() // reg,gen,gen // read.i,read.i { - u32 const length = gen_read(mode[0], size); - u32 const index = gen_read(mode[1], size); + mode[0].read_i(size); + mode[1].read_i(size); + decode(mode, bytes); + + u32 const length = gen_read(mode[0]); + u32 const index = gen_read(mode[1]); m_r[reg] = m_r[reg] * (length + 1) + index; + + tcy = 25; } break; case 5: @@ -2200,10 +2559,12 @@ void ns32000_device::execute_run() // gen,gen // read.i,rmw.B { - mode[1].rmw(); + mode[0].read_i(size); + mode[1].rmw_i(SIZE_B); + decode(mode, bytes); - u32 const base = gen_read(mode[0], size); - u32 offset = gen_read(mode[1], SIZE_B); + u32 const base = gen_read(mode[0]); + u32 offset = gen_read(mode[1]); unsigned const limit = (size + 1) * 8; m_psr |= PSR_F; @@ -2216,39 +2577,348 @@ void ns32000_device::execute_run() else offset++; - gen_write(mode[1], SIZE_B, offset & limit); + gen_write(mode[1], offset & (limit - 1)); + + // TODO: tcy 24-28 + tcy = 24; } break; case 6: - // MOVSU/MOVUS src,dest + // MOVSU/MOVUS src,dst // gen,gen // addr,addr { mode[0].addr(); mode[1].addr(); + decode(mode, bytes); fatalerror("unimplemented: movsu/movus (%s)\n", machine().describe_context()); + + tcy = 33; } break; } } - m_pc += bytes; break; - case 0x3e: // format 9 - // TODO: floating point + case 0x3e: + // format 9: xxxx xyyy yyoo ofii 0011 1110 + if (m_cfg & CFG_F) + { + if (!m_fpu) + fatalerror("floating point unit not configured (%s)\n", machine().describe_context()); + + u16 const opword = space(0).read_word_unaligned(m_pc + bytes); + bytes += 2; + + addr_mode mode[2] = { addr_mode((opword >> 11) & 31), addr_mode((opword >> 6) & 31) }; + size_code const size_f = BIT(opword, 0) ? SIZE_D : SIZE_Q; + size_code const size = size_code(opword & 3); + + m_fpu->write_id(opbyte); + m_fpu->write_op(swapendian_int16(opword)); + + switch ((opword >> 3) & 7) + { + case 0: + // MOVif src,dst + // gen,gen + // read.i,write.f + mode[0].read_i(size); + mode[1].write_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 1: + // LFSR src + // gen + // read.D + mode[0].read_i(size); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 2: + // MOVLF src,dst + // gen,gen + // read.L,write.F + mode[0].read_f(SIZE_Q); + mode[1].write_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 3: + // MOVFL src,dst + // gen,gen + // read.F,write.L + mode[0].read_f(SIZE_D); + mode[1].write_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 4: + // ROUNDfi src,dst + // gen,gen + // read.f,write.i + mode[0].read_f(size_f); + mode[1].write_i(size); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 5: + // TRUNCfi src,dst + // gen,gen + // read.f,write.i + mode[0].read_f(size_f); + mode[1].write_i(size); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 6: + // SFSR dst + // gen + // write.D + mode[0].write_i(size); + decode(mode, bytes); + + if (slave(mode[1], mode[0])) + interrupt(FPU, m_pc); + break; + case 7: + // FLOORfi src,dst + // gen,gen + // read.f,write.i + mode[0].read_f(size_f); + mode[1].write_i(size); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + } + } + else + interrupt(UND, m_pc); break; case 0x7e: // format 10 interrupt(UND, m_pc); break; - case 0xbe: // format 11 - // TODO: floating point + case 0xbe: + // format 11: xxxx xyyy yyoo oo0f 1011 1110 + if (m_cfg & CFG_F) + { + if (!m_fpu) + fatalerror("floating point unit not configured (%s)\n", machine().describe_context()); + + u16 const opword = space(0).read_word_unaligned(m_pc + bytes); + bytes += 2; + + addr_mode mode[2] = { addr_mode((opword >> 11) & 31), addr_mode((opword >> 6) & 31) }; + size_code const size_f = BIT(opword, 0) ? SIZE_D : SIZE_Q; + + m_fpu->write_id(opbyte); + m_fpu->write_op(swapendian_int16(opword)); + + switch ((opword >> 2) & 15) + { + case 0x0: + // ADDf src,dst + // gen,gen + // read.f,rmw.f + mode[0].read_f(size_f); + mode[1].rmw_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 0x1: + // MOVf src,dst + // gen,gen + // read.f,write.f + mode[0].read_f(size_f); + mode[1].write_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 0x2: + // CMPf src1,src2 + // gen,gen + // read.f,read.f + { + mode[0].read_f(size_f); + mode[1].read_f(size_f); + decode(mode, bytes); + + u16 const status = slave(mode[0], mode[1]); + if (!(status & ns32000_slave_interface::SLAVE_Q)) + { + m_psr &= ~(PSR_N | PSR_Z | PSR_L); + m_psr |= status & (ns32000_slave_interface::SLAVE_N | ns32000_slave_interface::SLAVE_Z | ns32000_slave_interface::SLAVE_L); + } + else + interrupt(FPU, m_pc); + } + break; + case 0x3: + // Trap(SLAVE) + // operands from ns32532 datasheet + mode[0].read_f(size_f); + mode[1].read_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 0x4: + // SUBf src,dst + // gen,gen + // read.f,rmw.f + mode[0].read_f(size_f); + mode[1].rmw_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 0x5: + // NEGf src,dst + // gen,gen + // read.f,write.f + mode[0].read_f(size_f); + mode[1].write_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 0x8: + // DIVf src,dst + // gen,gen + // read.f,rmw.f + mode[0].read_f(size_f); + mode[1].rmw_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 0x9: + // Trap(SLAVE) + // operands from ns32532 datasheet + mode[0].read_f(size_f); + mode[1].write_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 0xc: + // MULf src,dst + // gen,gen + // read.f,rmw.f + mode[0].read_f(size_f); + mode[1].rmw_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + case 0xd: + // ABSf src,dst + // gen,gen + // read.f,write.f + mode[0].read_f(size_f); + mode[1].write_f(size_f); + decode(mode, bytes); + + if (slave(mode[0], mode[1])) + interrupt(FPU, m_pc); + break; + } + } + else + interrupt(UND, m_pc); break; case 0xfe: // format 12 case 0x9e: // format 13 interrupt(UND, m_pc); break; - case 0x1e: // format 14 - // TODO: mmu + case 0x1e: + // format 14: xxxx xsss s0oo ooii 0001 1110 + if (!(m_psr & PSR_U)) + { + if (m_cfg & CFG_M) + { + u16 const opword = space(0).read_word_unaligned(m_pc + bytes); + bytes += 2; + + addr_mode mode[] = { addr_mode((opword >> 11) & 31), addr_mode(0x13) }; + + //unsigned const quick = (opword >> 7) & 15; + size_code const size = size_code(opword & 3); + + // TODO: mmu instructions + switch ((opword >> 2) & 15) + { + case 0: + // RDVAL loc + // gen + // addr + mode[0].addr(); + decode(mode, bytes); + + tcy = 21; + break; + case 1: + // WRVAL loc + // gen + // addr + mode[0].addr(); + decode(mode, bytes); + + tcy = 21; + break; + case 2: + // LMR mmureg,src + // short,gen + // read.D + mode[0].read_i(size); + decode(mode, bytes); + + tcy = 30; + break; + case 3: + // SMR mmureg,dst + // short,gen + // write.D + mode[0].write_i(size); + decode(mode, bytes); + + tcy = 25; + break; + default: + interrupt(UND, m_pc); + break; + } + } + else + interrupt(UND, m_pc); + } + else + interrupt(ILL, m_pc); break; case 0x16: // format 15.0 case 0x36: // format 15.1 @@ -2271,15 +2941,18 @@ void ns32000_device::execute_run() break; } + if (m_sequential) + m_pc += bytes; + // trace trap if (m_psr & PSR_P) interrupt(TRC, m_pc); - m_icount--; + m_icount -= tcy; } } -void ns32000_device::execute_set_input(int inputnum, int state) +template <int Width> void ns32000_device<Width>::execute_set_input(int inputnum, int state) { if (state) m_wait = false; @@ -2298,7 +2971,7 @@ void ns32000_device::execute_set_input(int inputnum, int state) } } -device_memory_interface::space_config_vector ns32000_device::memory_space_config() const +template <int Width> device_memory_interface::space_config_vector ns32000_device<Width>::memory_space_config() const { return space_config_vector{ std::make_pair(AS_PROGRAM, &m_program_config), @@ -2312,12 +2985,102 @@ device_memory_interface::space_config_vector ns32000_device::memory_space_config }; } -bool ns32000_device::memory_translate(int spacenum, int intention, offs_t &address) +template <int Width> bool ns32000_device<Width>::memory_translate(int spacenum, int intention, offs_t &address) { return true; } -std::unique_ptr<util::disasm_interface> ns32000_device::create_disassembler() +template <int Width> std::unique_ptr<util::disasm_interface> ns32000_device<Width>::create_disassembler() { return std::make_unique<ns32000_disassembler>(); } + +template <int Width> u16 ns32000_device<Width>::slave(addr_mode op1, addr_mode op2) +{ + if ((op1.access == READ || op1.access == RMW) && !(op1.type == REG && op1.slave)) + { + u64 const data = gen_read(op1); + + switch (op1.size) + { + case SIZE_B: + m_fpu->write_op(u8(data)); + break; + case SIZE_W: + m_fpu->write_op(u16(data)); + break; + case SIZE_D: + m_fpu->write_op(u16(data >> 0)); + m_fpu->write_op(u16(data >> 16)); + break; + case SIZE_Q: + m_fpu->write_op(u16(data >> 0)); + m_fpu->write_op(u16(data >> 16)); + m_fpu->write_op(u16(data >> 32)); + m_fpu->write_op(u16(data >> 48)); + break; + } + } + + if ((op2.access == READ || op2.access == RMW) && !(op2.type == REG && op2.slave)) + { + u64 const data = gen_read(op2); + + switch (op2.size) + { + case SIZE_B: + m_fpu->write_op(u8(data)); + break; + case SIZE_W: + m_fpu->write_op(u16(data)); + break; + case SIZE_D: + m_fpu->write_op(u16(data >> 0)); + m_fpu->write_op(u16(data >> 16)); + break; + case SIZE_Q: + m_fpu->write_op(u16(data >> 0)); + m_fpu->write_op(u16(data >> 16)); + m_fpu->write_op(u16(data >> 32)); + m_fpu->write_op(u16(data >> 48)); + break; + } + } + + u16 const status = m_fpu->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 = m_fpu->read_op(); + + switch (op2.size) + { + case SIZE_D: + data |= u64(m_fpu->read_op()) << 16; + break; + case SIZE_Q: + data |= u64(m_fpu->read_op()) << 16; + data |= u64(m_fpu->read_op()) << 32; + data |= u64(m_fpu->read_op()) << 48; + break; + default: + break; + } + + gen_write(op2, data); + } + } + else + { + // restore stack pointer + if (op1.type == TOS && op1.access == READ) + SP -= op1.size + 1; + + if (op2.type == TOS && op2.access == READ) + SP -= op2.size + 1; + } + + return status; +} |