st2xxx: Fix regression by preventing IRQ level from changing between vector pulls

This commit is contained in:
AJR 2022-01-30 15:02:08 -05:00
parent 2b1dec62d8
commit fa321cc7ce
2 changed files with 26 additions and 10 deletions

View File

@ -65,6 +65,7 @@ st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, co
, m_misc(0)
, m_ireq(0)
, m_iena(0)
, m_irq_level(0xff)
, m_lssa(0)
, m_lvpw(0)
, m_lxmax(0)
@ -187,6 +188,7 @@ void st2xxx_device::save_common_registers()
save_item(NAME(m_misc));
save_item(NAME(m_ireq));
save_item(NAME(m_iena));
save_item(NAME(m_irq_level));
if (st2xxx_lctr_mask() != 0)
{
save_item(NAME(m_lssa));
@ -282,20 +284,34 @@ void st2xxx_device::device_reset()
m_bctr = 0;
}
u8 st2xxx_device::active_irq_level() const
{
// IREQH interrupts have priority over IREQL interrupts
u16 ireq_active = swapendian_int16(m_ireq & m_iena);
if (ireq_active != 0)
return 31 - (8 ^ count_leading_zeros_32(ireq_active & -ireq_active));
else
return 0xff;
}
u8 st2xxx_device::read_vector(u16 adr)
{
if (adr >= 0xfffe)
{
u16 ireq_active = m_ireq & m_iena;
if (ireq_active != 0 && irq_taken)
if (adr == 0xfffe)
{
// IREQH interrupts have priority over IREQL interrupts
ireq_active = swapendian_int16(ireq_active);
int level = 31 - int(8 ^ count_leading_zeros_32(ireq_active & -ireq_active));
adr -= (level + 3) << 1;
set_irq_service(true);
// Make sure this doesn't change in between vector pull cycles
m_irq_level = irq_taken ? active_irq_level() : 0xff;
}
if (m_irq_level != 0xff)
{
adr -= (m_irq_level + 3) << 1;
LOGMASKED(LOG_IRQ, "Acknowledging %s interrupt (PC = $%04X, IREQ = $%04X, IENA = $%04X, vector pull from $%04X)\n",
st2xxx_irq_name(level),
st2xxx_irq_name(m_irq_level),
PPC,
m_ireq,
m_iena,
@ -303,11 +319,9 @@ u8 st2xxx_device::read_vector(u16 adr)
if (BIT(adr, 0))
{
m_ireq &= ~(1 << level);
m_ireq &= ~(1 << m_irq_level);
update_irq_state();
}
else
set_irq_service(true);
}
}
return downcast<mi_st2xxx &>(*mintf).read_vector(adr);

View File

@ -135,6 +135,7 @@ protected:
void set_irq_service(bool state) { downcast<mi_st2xxx &>(*mintf).irq_service = state; }
void update_irq_state() { irq_state = (m_ireq & m_iena) != 0; }
u8 active_irq_level() const;
TIMER_CALLBACK_MEMBER(bt_interrupt);
TIMER_CALLBACK_MEMBER(lcd_interrupt);
@ -268,6 +269,7 @@ protected:
u16 m_ireq;
u16 m_iena;
u8 m_irq_level;
u16 m_lssa;
u8 m_lvpw;