summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2020-09-10 12:58:34 +0700
committer Patrick Mackinlay <pmackinlay@hotmail.com>2020-09-10 12:58:34 +0700
commitd8a323ede5fd52fd671beac03276d2a445f1c9b3 (patch)
treebaa0b75cf0335e8b61c4139fcd7f374eec66679f
parent2eb5d9485e86cad71b4e155d48d6e3e03de3b364 (diff)
ns32000: implemented dei, corrected neg
-rw-r--r--src/devices/cpu/ns32000/ns32000.cpp195
-rw-r--r--src/devices/cpu/ns32000/ns32000.h4
2 files changed, 120 insertions, 79 deletions
diff --git a/src/devices/cpu/ns32000/ns32000.cpp b/src/devices/cpu/ns32000/ns32000.cpp
index 41743521755..4b796f8f345 100644
--- a/src/devices/cpu/ns32000/ns32000.cpp
+++ b/src/devices/cpu/ns32000/ns32000.cpp
@@ -18,7 +18,7 @@ DEFINE_DEVICE_TYPE(NS32032, ns32032_device, "ns32032", "National Semiconductor N
* - address translation/abort
* - floating point and other unimplemented instructions
* - format 6: subp,addp
- * - format 7: cmpm, dei
+ * - format 7: cmpm
* - format 8: movus/movsu
* - cascaded interrupts
* - instruction cycles
@@ -240,8 +240,13 @@ void ns32000_device::decode(addr_mode *mode, unsigned imm_size, unsigned &bytes)
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x04: case 0x05: case 0x06: case 0x07:
// register
- mode[i].base = m_r[mode[i].gen];
- mode[i].type = scaled[i] ? MEM : REG;
+ if (scaled[i])
+ {
+ mode[i].base = m_r[mode[i].gen];
+ mode[i].type = MEM;
+ }
+ else
+ mode[i].type = REG;
break;
case 0x08: case 0x09: case 0x0a: case 0x0b:
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
@@ -326,6 +331,10 @@ u32 ns32000_device::ea(addr_mode const mode)
switch (mode.type)
{
+ case REG:
+ base = m_r[mode.gen];
+ break;
+
case IND:
base = m_bus[12].read_dword_unaligned(mode.base);
break;
@@ -343,9 +352,9 @@ u32 ns32000_device::ea(addr_mode const mode)
return base + mode.disp;
}
-u32 ns32000_device::gen_read(addr_mode mode, unsigned size)
+u64 ns32000_device::gen_read(addr_mode mode, unsigned size)
{
- u32 data = 0;
+ u64 data = 0;
switch (mode.type)
{
@@ -354,7 +363,10 @@ u32 ns32000_device::gen_read(addr_mode mode, unsigned size)
break;
case REG:
- data = mode.base + mode.disp;
+ 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];
break;
case TOS:
@@ -371,30 +383,32 @@ u32 ns32000_device::gen_read(addr_mode mode, unsigned size)
break;
default:
- if (size)
- if (size == 3)
- data = space(0).read_dword_unaligned(ea(mode));
- else
- data = space(0).read_word_unaligned(ea(mode));
- else
- data = space(0).read_byte(ea(mode));
+ switch (size)
+ {
+ case SIZE_B: data = space(0).read_byte(ea(mode)); break;
+ case SIZE_W: data = space(0).read_word_unaligned(ea(mode)); break;
+ case SIZE_D: data = space(0).read_dword_unaligned(ea(mode)); break;
+ case SIZE_Q: data = space(0).read_qword_unaligned(ea(mode)); break;
+ }
break;
}
return data;
}
-s32 ns32000_device::gen_read_sx(addr_mode mode, unsigned size)
+s64 ns32000_device::gen_read_sx(addr_mode mode, unsigned size)
{
- u32 const data = gen_read(mode, size);
+ u64 data = gen_read(mode, size);
- if (size)
- if (size == SIZE_D)
- return s32(data);
- else
- return s16(data);
- else
- return s8(data);
+ switch (size)
+ {
+ case SIZE_B: data = s8(data); break;
+ case SIZE_W: data = s16(data); break;
+ case SIZE_D: data = s32(data); break;
+ case SIZE_Q: data = s64(data); break;
+ }
+
+ return data;
}
void ns32000_device::gen_write(addr_mode mode, unsigned size, u64 data)
@@ -402,7 +416,13 @@ void ns32000_device::gen_write(addr_mode mode, unsigned size, u64 data)
switch (mode.type)
{
case REG:
- m_r[mode.gen] = (m_r[mode.gen] & ~size_mask[size]) | (data & size_mask[size]);
+ 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]);
break;
case TOS:
@@ -426,7 +446,6 @@ void ns32000_device::gen_write(addr_mode mode, unsigned size, u64 data)
case SIZE_D: space(0).write_dword_unaligned(ea(mode), data); break;
case SIZE_Q: space(0).write_qword_unaligned(ea(mode), data); break;
}
-
break;
}
}
@@ -846,17 +865,17 @@ void ns32000_device::execute_run()
m_psr &= ~(PSR_N | PSR_Z | PSR_L);
- if ((size == 3 && s32(src1) > s32(src2))
- || ((size == 1 && s16(src1) > s16(src2))
- || ((size == 0 && s8(src1) > s8(src2)))))
+ if ((size == SIZE_D && s32(src1) > s32(src2))
+ || ((size == SIZE_W && s16(src1) > s16(src2))
+ || ((size == SIZE_B && s8(src1) > s8(src2)))))
m_psr |= PSR_N;
- if ((src1 & size_mask[size]) == (src2 & size_mask[size]))
+ if (src1 == src2)
m_psr |= PSR_Z;
- if ((size == 3 && u32(src1) > u32(src2))
- || ((size == 1 && u16(src1) > u16(src2))
- || ((size == 0 && u8(src1) > u8(src2)))))
+ if ((size == SIZE_D && u32(src1) > u32(src2))
+ || ((size == SIZE_W && u16(src1) > u16(src2))
+ || ((size == SIZE_B && u8(src1) > u8(src2)))))
m_psr |= PSR_L;
}
m_pc += bytes;
@@ -950,25 +969,25 @@ void ns32000_device::execute_run()
{
case 0x0: // US
// TODO: user stack pointer?
- m_sp1 = gen_read(mode[0], size) & size_mask[size];
+ m_sp1 = gen_read(mode[0], size);
m_pc += bytes;
break;
case 0x8: // FP
- m_fp = gen_read(mode[0], size) & size_mask[size];
+ m_fp = gen_read(mode[0], size);
m_pc += bytes;
break;
case 0x9: // SP
- SP = gen_read(mode[0], size) & size_mask[size];
+ SP = gen_read(mode[0], size);
m_pc += bytes;
break;
case 0xa: // SB
- m_sb = gen_read(mode[0], size) & size_mask[size];
+ m_sb = gen_read(mode[0], size);
m_pc += bytes;
break;
case 0xd: // PSR
if (!(m_psr & PSR_U))
{
- u32 const src = gen_read(mode[0], size) & size_mask[size];
+ u32 const src = gen_read(mode[0], size);
if (size == 0)
m_psr = (m_psr & 0xff00) | u8(src);
@@ -983,14 +1002,14 @@ void ns32000_device::execute_run()
case 0xe: // INTBASE
if (!(m_psr & PSR_U))
{
- m_intbase = gen_read(mode[0], size) & size_mask[size];
+ m_intbase = gen_read(mode[0], size);
m_pc += bytes;
}
else
interrupt(ILL, m_pc);
break;
case 0xf: // MOD
- m_mod = gen_read(mode[0], size) & size_mask[size];
+ m_mod = gen_read(mode[0], size);
m_pc += bytes;
break;
}
@@ -1140,17 +1159,17 @@ void ns32000_device::execute_run()
m_psr &= ~(PSR_N | PSR_Z | PSR_L);
- if ((size == 3 && s32(src1) > s32(src2))
- || ((size == 1 && s16(src1) > s16(src2))
- || ((size == 0 && s8(src1) > s8(src2)))))
+ if ((size == SIZE_D && s32(src1) > s32(src2))
+ || ((size == SIZE_W && s16(src1) > s16(src2))
+ || ((size == SIZE_B && s8(src1) > s8(src2)))))
m_psr |= PSR_N;
- if ((src1 & size_mask[size]) == (src2 & size_mask[size]))
+ if (src1 == src2)
m_psr |= PSR_Z;
- if ((size == 3 && u32(src1) > u32(src2))
- || ((size == 1 && u16(src1) > u16(src2))
- || ((size == 0 && u8(src1) > u8(src2)))))
+ if ((size == SIZE_D && u32(src1) > u32(src2))
+ || ((size == SIZE_W && u16(src1) > u16(src2))
+ || ((size == SIZE_B && u8(src1) > u8(src2)))))
m_psr |= PSR_L;
}
m_pc += bytes;
@@ -1218,8 +1237,8 @@ void ns32000_device::execute_run()
{
mode[1].rmw();
- u32 const src1 = gen_read(mode[0], size) & size_mask[size];
- u32 const src2 = gen_read(mode[1], size) & size_mask[size];
+ u32 const src1 = gen_read(mode[0], size);
+ u32 const src2 = gen_read(mode[1], size);
u32 const dest = src2 - src1;
flags(src1, src2, dest, size, true);
@@ -1258,8 +1277,8 @@ void ns32000_device::execute_run()
{
mode[1].rmw();
- u32 const src1 = gen_read(mode[0], size) & size_mask[size];
- u32 const src2 = gen_read(mode[1], size) & size_mask[size];
+ u32 const src1 = gen_read(mode[0], size);
+ u32 const src2 = gen_read(mode[1], size);
u32 const dest = src2 - src1 - (m_psr & PSR_C);
flags(src1, src2, dest, size, true);
@@ -1569,7 +1588,7 @@ void ns32000_device::execute_run()
mode[1].rmw();
s32 const count = gen_read_sx(mode[0], SIZE_B);
- u32 const src = gen_read(mode[1], size) & size_mask[size];
+ u32 const src = gen_read(mode[1], size);
u32 const dest = (count < 0) ? (src >> -count) : (src << count);
@@ -1621,20 +1640,20 @@ void ns32000_device::execute_run()
{
u32 const src = gen_read(mode[0], size);
- if (src & size_mask[size])
+ if (src)
m_psr |= PSR_C;
else
m_psr &= ~PSR_C;
if ((src ^ ~(size_mask[size] >> 1)) & size_mask[size])
{
- m_psr |= PSR_F;
- gen_write(mode[1], size, src);
+ m_psr &= ~PSR_F;
+ gen_write(mode[1], size, -src);
}
else
{
- m_psr &= ~PSR_F;
- gen_write(mode[1], size, -src);
+ m_psr |= PSR_F;
+ gen_write(mode[1], size, src);
}
}
m_pc += bytes;
@@ -1845,9 +1864,8 @@ void ns32000_device::execute_run()
// read.[BW],write.D
{
u32 const src = gen_read(mode[0], size);
- u32 const dest = src & size_mask[size];
- gen_write(mode[1], SIZE_D, dest);
+ gen_write(mode[1], SIZE_D, src);
}
m_pc += bytes;
break;
@@ -1885,22 +1903,14 @@ void ns32000_device::execute_run()
// read.i,rmw.2i
{
mode[1].rmw();
+ unsigned const size2 = size * 2 + 1;
u32 const src1 = gen_read(mode[0], size);
u32 const src2 = gen_read(mode[1], size);
- u64 const dest = mulu_32x32(src1 & size_mask[size], src2 & size_mask[size]);
+ u64 const dest = mulu_32x32(src1, src2);
- if (mode[1].type == REG)
- {
- unsigned const lo = mode[1].gen;
- unsigned const hi = lo ^ 1;
-
- m_r[lo] = (m_r[lo] & ~size_mask[size]) | (dest & size_mask[size]);
- m_r[hi] = (m_r[hi] & ~size_mask[size]) | ((dest >> ((size + 1) * 8)) & size_mask[size]);
- }
- else
- gen_write(mode[1], size * 2 + 1, dest);
+ gen_write(mode[1], size2, dest);
}
m_pc += bytes;
break;
@@ -1911,7 +1921,37 @@ void ns32000_device::execute_run()
// DEIi src,dest
// gen,gen
// read.i,rmw.2i
- fatalerror("unimplemented: dei (%s)\n", machine().describe_context());
+ {
+ mode[1].rmw();
+ unsigned const size2 = size * 2 + 1;
+
+ u32 const src1 = gen_read(mode[0], size);
+ if (src1)
+ {
+ u64 const src2 = gen_read(mode[1], size2);
+
+ u32 const quotient = src2 / src1;
+ u32 const remainder = src2 % src1;
+
+ if (mode[1].type == REG)
+ {
+ 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]);
+ }
+ else
+ gen_write(mode[1], size2, (u64(quotient) << ((size + 1) * 8)) | remainder);
+
+ m_pc += bytes;
+ }
+ else
+ {
+ // restore stack pointer
+ if (mode[0].type == TOS)
+ SP -= size + 1;
+
+ interrupt(DVZ, m_pc);
+ }
+ }
break;
case 0xc:
// QUOi src,dest
@@ -2006,12 +2046,13 @@ void ns32000_device::execute_run()
{
s32 const src2 = gen_read_sx(mode[1], size);
- div_t const dest = std::div(src2, src1);
+ s32 const quotient = src2 / src1;
+ s32 const remainder = src2 % src1;
- if ((dest.quot < 0) && dest.rem)
- gen_write(mode[1], size, dest.quot - 1);
+ if ((quotient < 0) && remainder)
+ gen_write(mode[1], size, quotient - 1);
else
- gen_write(mode[1], size, dest.quot);
+ gen_write(mode[1], size, quotient);
m_pc += bytes;
}
@@ -2093,7 +2134,7 @@ void ns32000_device::execute_run()
s32 const offset = m_r[reg];
s32 const length = displacement(bytes);
- u32 const src = gen_read(mode[0], size) & size_mask[size];
+ u32 const src = gen_read(mode[0], size);
u32 dest;
if (mode[1].type == REG)
@@ -2148,8 +2189,8 @@ void ns32000_device::execute_run()
// reg,gen,gen
// read.i,read.i
{
- u32 const length = gen_read(mode[0], size) & size_mask[size];
- u32 const index = gen_read(mode[1], size) & size_mask[size];
+ u32 const length = gen_read(mode[0], size);
+ u32 const index = gen_read(mode[1], size);
m_r[reg] = m_r[reg] * (length + 1) + index;
}
@@ -2162,7 +2203,7 @@ void ns32000_device::execute_run()
mode[1].rmw();
u32 const base = gen_read(mode[0], size);
- u32 offset = gen_read(mode[1], SIZE_B) & size_mask[size];
+ u32 offset = gen_read(mode[1], SIZE_B);
unsigned const limit = (size + 1) * 8;
m_psr |= PSR_F;
diff --git a/src/devices/cpu/ns32000/ns32000.h b/src/devices/cpu/ns32000/ns32000.h
index dea909cdc68..af5977fe52e 100644
--- a/src/devices/cpu/ns32000/ns32000.h
+++ b/src/devices/cpu/ns32000/ns32000.h
@@ -71,8 +71,8 @@ private:
// operand read/write helpers
u32 ea(addr_mode const mode);
- u32 gen_read(addr_mode mode, unsigned size);
- s32 gen_read_sx(addr_mode mode, unsigned size);
+ u64 gen_read(addr_mode mode, unsigned size);
+ s64 gen_read_sx(addr_mode mode, unsigned size);
void gen_write(addr_mode mode, unsigned size, u64 data);
// other execution helpers