summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/ns32000/ns32000.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/ns32000/ns32000.cpp')
-rw-r--r--src/devices/cpu/ns32000/ns32000.cpp1659
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;
+}