From 78ae683049b1ff8cd0f450ee7ec9df4faf2f9f86 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Fri, 12 Aug 2022 10:48:33 +0700 Subject: ns32000: various virtual memory bug fixes * use active super/user address translation in debugger * ensure CXP, RXP, RETT, RETI, ENTER and CXPD instructions restart properly after a fault * correct RDVAL/WRVAL logic --- src/devices/cpu/ns32000/ns32000.cpp | 120 +++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/src/devices/cpu/ns32000/ns32000.cpp b/src/devices/cpu/ns32000/ns32000.cpp index 2dc43b4dfd0..d3f04bbd5d3 100644 --- a/src/devices/cpu/ns32000/ns32000.cpp +++ b/src/devices/cpu/ns32000/ns32000.cpp @@ -991,11 +991,15 @@ template void ns32000_device::execute_run() SP -= 4; mem_write(ST_ODT, SP, m_pc + bytes); - tex = top(SIZE_D, m_mod + 4) + top(SIZE_W, link_base + index * 4) * 2 + top(SIZE_W, SP) + top(SIZE_D, SP) + top(SIZE_D, u16(desc)) * 2 + 16; + u16 const mod = u16(desc); + u32 const sb = mem_read(ST_ODT, mod + 0); + u32 const pc = mem_read(ST_ODT, mod + 8) + (desc >> 16); - m_mod = u16(desc); - m_sb = mem_read(ST_ODT, m_mod + 0); - m_pc = mem_read(ST_ODT, m_mod + 8) + (desc >> 16); + tex = top(SIZE_D, m_mod + 4) + top(SIZE_W, link_base + index * 4) * 2 + top(SIZE_W, SP) + top(SIZE_D, SP) + top(SIZE_D, mod) * 2 + 16; + + m_pc = pc; + m_mod = mod; + m_sb = sb; m_sequential = false; } break; @@ -1005,13 +1009,17 @@ template void ns32000_device::execute_run() { s32 const constant = displacement(bytes); - m_pc = mem_read(ST_ODT, SP); + u32 const pc = mem_read(ST_ODT, SP); SP += 4; - m_mod = mem_read(ST_ODT, SP); + u16 const mod = mem_read(ST_ODT, SP); SP += 4; + u32 const sb = mem_read(ST_ODT, mod); + + tex = top(SIZE_D, SP) + top(SIZE_W, SP) + top(SIZE_D, mod) + 2; - m_sb = mem_read(ST_ODT, m_mod + 0); - tex = top(SIZE_D, SP) + top(SIZE_W, SP) + top(SIZE_D, SP) + 2; + m_pc = pc; + m_mod = mod; + m_sb = sb; SP += constant; m_sequential = false; } @@ -1023,19 +1031,22 @@ template void ns32000_device::execute_run() { s32 const constant = displacement(bytes); - u32 &sp(SP); - m_pc = mem_read(ST_ODT, sp); - sp += 4; - m_mod = mem_read(ST_ODT, sp); - sp += 2; - m_psr = mem_read(ST_ODT, sp) & PSR_MSK; - sp += 2; - - m_sb = mem_read(ST_ODT, m_mod); - + u32 const pc = mem_read(ST_ODT, SP); + SP += 4; + u16 const mod = mem_read(ST_ODT, SP); + SP += 2; + u16 const psr = mem_read(ST_ODT, SP) & PSR_MSK; + SP += 2; + u32 const sb = mem_read(ST_ODT, mod); + + tex = top(SIZE_D, SP) + top(SIZE_W, SP) * 2 + top(SIZE_D, mod) + 35; + + m_pc = pc; + m_mod = mod; + m_psr = psr; + m_sb = sb; SP += constant; m_sequential = false; - tex = top(SIZE_D, sp) + top(SIZE_W, sp) * 2 + top(SIZE_D, m_mod) + 35; } else interrupt(ILL, m_pc); @@ -1059,20 +1070,23 @@ template void ns32000_device::execute_run() } } - u32 &sp(SP); - m_pc = mem_read(ST_ODT, sp); - sp += 2; - mem_read(ST_ODT, sp); - sp += 2; - m_mod = mem_read(ST_ODT, sp); - sp += 2; - m_psr = mem_read(ST_ODT, sp) & PSR_MSK; - sp += 2; - - m_sb = mem_read(ST_ODT, m_mod); + u32 const pc = mem_read(ST_ODT, SP); + SP += 2; + mem_read(ST_ODT, SP); + SP += 2; + u16 const mod = mem_read(ST_ODT, SP); + SP += 2; + u16 const psr = mem_read(ST_ODT, SP) & PSR_MSK; + SP += 2; + u32 const sb = mem_read(ST_ODT, mod); + + tex = top(SIZE_B) + top(SIZE_W, SP) * 3 + top(SIZE_D) * 3 + 39; + + m_pc = pc; + m_mod = mod; + m_psr = psr; + m_sb = sb; m_sequential = false; - - tex = top(SIZE_B) + top(SIZE_W) * 3 + top(SIZE_D) * 3 + 39; } else interrupt(ILL, m_pc); @@ -1122,8 +1136,8 @@ template void ns32000_device::execute_run() SP -= 4; mem_write(ST_ODT, SP, m_fp); + u32 const fp = SP; tex = top(SIZE_D, SP) + 18; - m_fp = SP; SP -= constant; for (unsigned i = 0; i < 8; i++) @@ -1135,6 +1149,8 @@ template void ns32000_device::execute_run() tex += top(SIZE_D, SP) + 4; } } + + m_fp = fp; } break; case 0x9: @@ -1420,12 +1436,15 @@ template void ns32000_device::execute_run() mem_write(ST_ODT, SP, m_pc + bytes); u32 const desc = mem_read(ST_ODT, address); + u16 const mod = u16(desc); + u32 const sb = mem_read(ST_ODT, mod + 0); + u32 const pc = mem_read(ST_ODT, mod + 8) + (desc >> 16); - m_mod = u16(desc); - m_sb = mem_read(ST_ODT, m_mod + 0); - m_pc = mem_read(ST_ODT, m_mod + 8) + (desc >> 16); + tex = mode[0].tea + top(SIZE_W, address) * 3 + top(SIZE_D, mod) * 3 + 13; - tex = mode[0].tea + top(SIZE_W, address) * 3 + top(SIZE_D, m_mod) * 3 + 13; + m_pc = pc; + m_mod = mod; + m_sb = sb; m_sequential = false; } else @@ -3339,9 +3358,6 @@ template void ns32000_device::execute_run() mode[0].addr(); decode(mode, bytes); - // dummy read - mem_read(ST_ODT, ea(mode[0]), true); - u16 const status = slave(opbyte, opword, mode[0], mode[1]); if (!(status & ns32000_slave_interface::SLAVE_Q)) { @@ -3364,9 +3380,6 @@ template void ns32000_device::execute_run() mode[0].addr(); decode(mode, bytes); - // dummy read - mem_read(ST_ODT, ea(mode[0]), true); - u16 const status = slave(opbyte, opword, mode[0], mode[1]); if (!(status & ns32000_slave_interface::SLAVE_Q)) { @@ -3491,7 +3504,7 @@ template device_memory_interface::space_config_vector ns32000_device template bool ns32000_device::memory_translate(int spacenum, int intention, offs_t &address) { - return !m_mmu || m_mmu->translate(space(spacenum), spacenum, address, intention & TRANSLATE_USER_MASK, intention & TRANSLATE_WRITE, false, intention & TRANSLATE_DEBUG_MASK) == ns32000_mmu_interface::COMPLETE; + return !m_mmu || m_mmu->translate(space(spacenum), spacenum, address, m_psr & PSR_U, intention & TRANSLATE_WRITE, false, intention & TRANSLATE_DEBUG_MASK) == ns32000_mmu_interface::COMPLETE; } template std::unique_ptr ns32000_device::create_disassembler() @@ -3560,6 +3573,16 @@ template u16 ns32000_device::slave_slow(ns32000_slow_slave_in break; } } + else if (op1.access == ADDR) + { + u32 const data = ea(op1); + + slave.write_op(u16(data >> 0)); + slave.write_op(u16(data >> 16)); + + // single-byte memory read cycle + mem_read(ST_ODT, data, true); + } if ((op2.access == READ || op2.access == RMW) && !(op2.type == REG && op2.slave)) { @@ -3640,6 +3663,15 @@ template u16 ns32000_device::slave_fast(ns32000_fast_slave_in break; } } + else if (op1.access == ADDR) + { + u32 const data = ea(op1); + + slave.write(u32(data)); + + // single-byte memory read cycle + mem_read(ST_ODT, data, true); + } if ((op2.access == READ || op2.access == RMW) && !(op2.type == REG && op2.slave)) { -- cgit v1.2.3