summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2020-03-06 23:23:00 -0500
committer AJR <ajrhacker@users.noreply.github.com>2020-03-06 23:23:00 -0500
commit9cd1748fd1b3ad125fc435f20e124974777536a0 (patch)
treeccaa0ba4d362932b2b443364615a4f5e24b3e154 /src/devices/cpu
parentef8a18e63ac8d3cd77aedd34a978888784afc850 (diff)
upd7810: Interrupt-related fixes
- Prevent NMI from being masked out - Make EI take effect only after the following instruction - Inhibit clearing of interrupt flag upon acknowledgment when another interrupt with the same priority is also enabled - Add a crude start bit check to asynchronous serial mode
Diffstat (limited to 'src/devices/cpu')
-rw-r--r--src/devices/cpu/upd7810/upd7810.cpp47
-rw-r--r--src/devices/cpu/upd7810/upd7810.h1
2 files changed, 33 insertions, 15 deletions
diff --git a/src/devices/cpu/upd7810/upd7810.cpp b/src/devices/cpu/upd7810/upd7810.cpp
index ac123b07b46..467817c6086 100644
--- a/src/devices/cpu/upd7810/upd7810.cpp
+++ b/src/devices/cpu/upd7810/upd7810.cpp
@@ -736,7 +736,7 @@ void upd7810_device::upd7810_take_irq()
int irqline = 0;
/* global interrupt disable? */
- if (0 == IFF)
+ if (0 == IFF && !(IRR & INTNMI))
return;
/* check the interrupts in priority sequence */
@@ -751,21 +751,22 @@ void upd7810_device::upd7810_take_irq()
if ((IRR & INTFT0) && 0 == (MKL & 0x02))
{
vector = 0x0008;
- if (!((IRR & INTFT1) && 0 == (MKL & 0x04)))
- IRR&=~INTFT0;
+ if (0 != (MKL & 0x04))
+ IRR&=~INTFT0;
}
else
if ((IRR & INTFT1) && 0 == (MKL & 0x04))
{
vector = 0x0008;
- IRR&=~INTFT1;
+ if (0 != (MKL & 0x02))
+ IRR&=~INTFT1;
}
else
if ((IRR & INTF1) && 0 == (MKL & 0x08))
{
irqline = UPD7810_INTF1;
vector = 0x0010;
- if (!((IRR & INTF2) && 0 == (MKL & 0x10)))
+ if (0 != (MKL & 0x10))
IRR&=~INTF1;
}
else
@@ -773,42 +774,50 @@ void upd7810_device::upd7810_take_irq()
{
irqline = UPD7810_INTF2;
vector = 0x0010;
- IRR&=~INTF2;
+ if (0 != (MKL & 0x08))
+ IRR&=~INTF2;
}
else
if ((IRR & INTFE0) && 0 == (MKL & 0x20))
{
vector = 0x0018;
- if (!((IRR & INTFE1) && 0 == (MKL & 0x40)))
- IRR&=~INTFE0;
+ if (0 != (MKL & 0x40))
+ IRR&=~INTFE0;
}
else
if ((IRR & INTFE1) && 0 == (MKL & 0x40))
{
vector = 0x0018;
- IRR&=~INTFE1;
+ if (0 != (MKL & 0x20))
+ IRR&=~INTFE1;
}
else
if ((IRR & INTFEIN) && 0 == (MKL & 0x80))
{
vector = 0x0020;
+ if (0 != (MKH & 0x01))
+ IRR&=~INTFEIN;
}
else
if ((IRR & INTFAD) && 0 == (MKH & 0x01))
{
vector = 0x0020;
+ if (0 != (MKL & 0x80))
+ IRR&=~INTFAD;
}
else
if ((IRR & INTFSR) && 0 == (MKH & 0x02))
{
vector = 0x0028;
- IRR&=~INTFSR;
+ if (0 != (MKH & 0x04))
+ IRR&=~INTFSR;
}
else
if ((IRR & INTFST) && 0 == (MKH & 0x04))
{
vector = 0x0028;
- IRR&=~INTFST;
+ if (0 != (MKH & 0x02))
+ IRR&=~INTFST;
}
if (vector)
@@ -822,7 +831,7 @@ void upd7810_device::upd7810_take_irq()
WM( SP, PCH );
SP--;
WM( SP, PCL );
- IFF = 0;
+ IFF = m_iff_pending = 0;
PSW &= ~(SK|L0|L1);
PC = vector;
}
@@ -883,7 +892,7 @@ void upd7801_device::upd7810_take_irq()
WM( SP, PCH );
SP--;
WM( SP, PCL );
- IFF = 0;
+ IFF = m_iff_pending = 0;
PSW &= ~(SK|L0|L1);
PC = vector;
}
@@ -1186,6 +1195,12 @@ void upd7810_device::upd7810_sio_input()
{
if (SML & 0x03) /* asynchronous mode ? */
{
+ // start bit check
+ RXD = m_rxd_func();
+ m_rxs = (m_rxs >> 1) | ((uint16_t)RXD << 15);
+ if ((m_rxs & 0xc000) != 0x4000)
+ return;
+
switch (SML & 0xfc)
{
case 0x48: /* 7bits, no parity, 1 stop bit */
@@ -1581,7 +1596,7 @@ void upd7810_device::base_device_start()
m_co0_func.resolve_safe();
m_co1_func.resolve_safe();
m_txd_func.resolve_safe();
- m_rxd_func.resolve_safe(0);
+ m_rxd_func.resolve_safe(1);
m_an0_func.resolve_safe(0);
m_an1_func.resolve_safe(0);
m_an2_func.resolve_safe(0);
@@ -1614,6 +1629,7 @@ void upd7810_device::base_device_start()
save_item(NAME(m_op));
save_item(NAME(m_op2));
save_item(NAME(m_iff));
+ save_item(NAME(m_iff_pending));
save_item(NAME(m_ea.w.l));
save_item(NAME(m_va.w.l));
save_item(NAME(m_bc.w.l));
@@ -1800,6 +1816,7 @@ void upd7810_device::device_reset()
m_op = 0;
m_op2 = 0;
m_iff = 0;
+ m_iff_pending = 0;
m_psw = 0;
m_ea.d = 0;
m_va.d = 0;
@@ -1976,7 +1993,7 @@ void upd7810_device::execute_run()
}
m_icount -= cc;
upd7810_take_irq();
-
+ m_iff = m_iff_pending;
} while (m_icount > 0);
}
diff --git a/src/devices/cpu/upd7810/upd7810.h b/src/devices/cpu/upd7810/upd7810.h
index 5905b931af1..adb0fe88a8e 100644
--- a/src/devices/cpu/upd7810/upd7810.h
+++ b/src/devices/cpu/upd7810/upd7810.h
@@ -239,6 +239,7 @@ protected:
uint8_t m_op; /* opcode */
uint8_t m_op2; /* opcode part 2 */
uint8_t m_iff; /* interrupt enable flip flop */
+ uint8_t m_iff_pending;
uint8_t m_psw; /* processor status word */
PAIR m_ea; /* extended accumulator */
PAIR m_va; /* accumulator + vector register */