From fa321cc7cee09715d096e6a427ef4b1cb096732f Mon Sep 17 00:00:00 2001 From: AJR Date: Sun, 30 Jan 2022 15:02:08 -0500 Subject: [PATCH] st2xxx: Fix regression by preventing IRQ level from changing between vector pulls --- src/devices/cpu/m6502/st2xxx.cpp | 34 ++++++++++++++++++++++---------- src/devices/cpu/m6502/st2xxx.h | 2 ++ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/devices/cpu/m6502/st2xxx.cpp b/src/devices/cpu/m6502/st2xxx.cpp index bc73afc7750..d0428332878 100644 --- a/src/devices/cpu/m6502/st2xxx.cpp +++ b/src/devices/cpu/m6502/st2xxx.cpp @@ -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(*mintf).read_vector(adr); diff --git a/src/devices/cpu/m6502/st2xxx.h b/src/devices/cpu/m6502/st2xxx.h index 90f7c4d53c9..811c2008d49 100644 --- a/src/devices/cpu/m6502/st2xxx.h +++ b/src/devices/cpu/m6502/st2xxx.h @@ -135,6 +135,7 @@ protected: void set_irq_service(bool state) { downcast(*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;