diff options
Diffstat (limited to 'src/devices/cpu/mn1880/mn1880.cpp')
-rw-r--r-- | src/devices/cpu/mn1880/mn1880.cpp | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/src/devices/cpu/mn1880/mn1880.cpp b/src/devices/cpu/mn1880/mn1880.cpp index 9ea47debcb0..32b14a8a640 100644 --- a/src/devices/cpu/mn1880/mn1880.cpp +++ b/src/devices/cpu/mn1880/mn1880.cpp @@ -64,6 +64,20 @@ contents of locations about to be written to may show misleading values. Likewise, PCs at which watchpoint hits occur may be incorrectly reported for writes. + * Due to the pipelining of writes, an interrupt may be accepted during + an instruction which attempts to disable interrupts by setting the + IEMASK bit, which may be cleared instead when control reaches the next + sequential instruction from a RETI. This sequencing glitch is + documented in the MN187XX23 user's manual, along with a failsafe way + of setting IEMASK, and similar workarounds in extant program code + suggest it is likewise present in the MN1880 series. + * The optional MMU, which expands the memory spaces in certain models + which contain neither internal ROM nor RAM, has been emulated only + to the extent required by psr500, though it likely has a few other + features and quirks. + * In DF mode, MOV (da),(YP) and MOV (XP),(da) apparently need to take + the high byte of the direct address from the opposite pointer, + despite MN1870 documentation suggesting these use the same pointer. ***************************************************************************/ @@ -328,8 +342,9 @@ void mn1880_device::device_reset() m_mmu_enable = 0; } -bool mn1880_device::memory_translate(int spacenum, int intention, offs_t &address) +bool mn1880_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) { + target_space = &space(spacenum); switch (spacenum) { case AS_PROGRAM: @@ -693,7 +708,7 @@ void mn1880_device::execute_run() case microstate::MOV36_1: if (BIT(cpu.fs, 5)) - m_da |= cpu.xp & 0xff00; + m_da |= cpu.yp & 0xff00; m_ustate = microstate::MOV36_2; break; @@ -712,7 +727,7 @@ void mn1880_device::execute_run() m_tmp1 = m_data.read_byte(mmu_data_translate(m_da)); m_da = input; if (BIT(cpu.fs, 5)) - m_da |= cpu.yp & 0xff00; + m_da |= cpu.xp & 0xff00; m_ustate = microstate::MOV56_2; break; @@ -2156,7 +2171,7 @@ void mn1880_device::execute_run() case microstate::ADDRE8_1: ++cpu.ip; if (BIT(cpu.fs, 5)) - m_da |= cpu.yp & 0x00ff; + m_da |= cpu.yp & 0xff00; m_tmp2 = input; m_ustate = microstate::ADDRE8_2; break; @@ -2165,15 +2180,15 @@ void mn1880_device::execute_run() m_tmp1 = m_data.read_byte(mmu_data_translate(m_da)); m_da = m_tmp2; if (BIT(cpu.fs, 5)) - m_da |= cpu.xp & 0x00ff; + m_da |= cpu.xp & 0xff00; m_ustate = microstate::ADDRE8_3; break; case microstate::ADDRE8_3: if (BIT(cpu.ir, 1)) - setl(cpu.yp, cpu.addcz(cpu.yp & 0x00ff, m_data.read_byte(mmu_data_translate(m_da)), false, false)); + setl(cpu.yp, cpu.addcz(m_tmp1, m_data.read_byte(mmu_data_translate(m_da)), false, false)); else - setl(cpu.xp, cpu.addcz(cpu.xp & 0x00ff, m_data.read_byte(mmu_data_translate(m_da)), false, false)); + setl(cpu.xp, cpu.addcz(m_tmp1, m_data.read_byte(mmu_data_translate(m_da)), false, false)); m_ustate = microstate::NOP_1; // TODO: output queue (XPl only?) break; @@ -2182,7 +2197,7 @@ void mn1880_device::execute_run() m_tmp2 = m_da & 0x00ff; m_da = input; if (BIT(cpu.fs, 5)) - m_da |= (BIT(cpu.ir, 1) ? cpu.yp : cpu.xp) & 0x00ff; + m_da |= (BIT(cpu.ir, 1) ? cpu.yp : cpu.xp) & 0xff00; m_ustate = microstate::ADDRE9_2; break; @@ -2416,7 +2431,7 @@ void mn1880_device::execute_run() { // IRQ0 (first of four external edge inputs?) has the highest priority (after RESET) unsigned level = 32 - count_leading_zeros_32((m_irq - 1) & ~m_irq); - (void)standard_irq_callback(level); + (void)standard_irq_callback(level, cpu.ip); cpu.ie &= ~(1 << level); // No separate in-service lockout; handler must re-enable specific interrupt m_if &= ~(1 << level); cpu.iemask = true; |