From f4347601a070fa8591901a5d092b18dd3d092b3c Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Mon, 18 Jul 2022 11:18:27 +0700 Subject: ns32000: always perform bus-sized writes to aligned memory --- src/devices/cpu/ns32000/ns32000.cpp | 44 +++++++++++++++++++++++++++++++++---- src/devices/cpu/ns32000/ns32000.h | 2 +- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/devices/cpu/ns32000/ns32000.cpp b/src/devices/cpu/ns32000/ns32000.cpp index 7049907709d..2dc43b4dfd0 100644 --- a/src/devices/cpu/ns32000/ns32000.cpp +++ b/src/devices/cpu/ns32000/ns32000.cpp @@ -340,7 +340,7 @@ template template T ns32000_device::mem_read(unsi return 0; } -template template void ns32000_device::mem_write(unsigned st, u32 address, T data, bool user) +template template void ns32000_device::mem_write(unsigned st, u32 address, u64 data, bool user) { u32 physical = address; ns32000_mmu_interface::translate_result tr = m_mmu ? @@ -402,10 +402,44 @@ template template void ns32000_device::mem_write( else { // aligned access + /* + * Tektronix 4132 firmware requires that MOVB rN, (where mem + * is a word-aligned memory address) drives a 16-bit value from the + * register onto the data bus (with /HBE deasserted). The effect is + * important when the data is being written to a fixed-width 16-bit + * register (Am9516 in this case), as the byte enables are ignored + * and a 16-bit value is latched. This code assumes the same effect + * occurs with word/dword-aligned MOVB/MOVW on the 32032 and 32332. + */ + // TODO: verify how real hardware behaves switch (sizeof(T)) { - case 1: m_bus[st].write_byte(physical, data); break; - case 2: m_bus[st].write_word(physical, data); break; + case 1: + if (Width == 1) + { + unsigned const shift = (physical & 1) * 8; + + m_bus[st].write_word(physical, data << shift, 0xffU << shift); + } + else if (Width == 2) + { + unsigned const shift = (physical & 3) * 8; + + m_bus[st].write_dword(physical, data << shift, 0xffU << shift); + } + else + m_bus[st].write_byte(physical, data); + break; + case 2: + if (Width == 2) + { + unsigned const shift = (physical & 2) * 8; + + m_bus[st].write_dword(physical, data << shift, 0xffffU << shift); + } + else + m_bus[st].write_word(physical, data); + break; case 4: m_bus[st].write_dword(physical, data); break; case 8: m_bus[st].write_qword(physical, data); break; } @@ -1645,7 +1679,9 @@ template void ns32000_device::execute_run() mode[1].write_i(size); decode(mode, bytes); - u32 const src = gen_read(mode[0]); + // special-case non-masked source data when moving from + // register to memory; see comments in mem_write() + u32 const src = (mode[0].type == REG) ? m_r[mode[0].gen] : gen_read(mode[0]); gen_write(mode[1], src); diff --git a/src/devices/cpu/ns32000/ns32000.h b/src/devices/cpu/ns32000/ns32000.h index a18b34040ba..654d8661f8a 100644 --- a/src/devices/cpu/ns32000/ns32000.h +++ b/src/devices/cpu/ns32000/ns32000.h @@ -120,7 +120,7 @@ protected: // memory accessors template T mem_read(unsigned st, u32 address, bool user = false, bool pfs = false); - template void mem_write(unsigned st, u32 address, T data, bool user = false); + template void mem_write(unsigned st, u32 address, u64 data, bool user = false); // instruction fetch/decode helpers template T fetch(unsigned &bytes); -- cgit v1.2.3