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
This commit is contained in:
AJR 2020-03-06 23:23:00 -05:00
parent ef8a18e63a
commit 9cd1748fd1
2 changed files with 33 additions and 15 deletions

View File

@ -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);
}

View File

@ -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 */