ns32000: implemented dei, corrected neg

This commit is contained in:
Patrick Mackinlay 2020-09-10 12:58:34 +07:00
parent 2eb5d9485e
commit d8a323ede5
2 changed files with 120 additions and 79 deletions

View File

@ -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;

View File

@ -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