summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mn1880/mn1880.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mn1880/mn1880.cpp')
-rw-r--r--src/devices/cpu/mn1880/mn1880.cpp33
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;