mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
st2xxx: Fix regression by preventing IRQ level from changing between vector pulls
This commit is contained in:
parent
2b1dec62d8
commit
fa321cc7ce
@ -65,6 +65,7 @@ st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, co
|
|||||||
, m_misc(0)
|
, m_misc(0)
|
||||||
, m_ireq(0)
|
, m_ireq(0)
|
||||||
, m_iena(0)
|
, m_iena(0)
|
||||||
|
, m_irq_level(0xff)
|
||||||
, m_lssa(0)
|
, m_lssa(0)
|
||||||
, m_lvpw(0)
|
, m_lvpw(0)
|
||||||
, m_lxmax(0)
|
, m_lxmax(0)
|
||||||
@ -187,6 +188,7 @@ void st2xxx_device::save_common_registers()
|
|||||||
save_item(NAME(m_misc));
|
save_item(NAME(m_misc));
|
||||||
save_item(NAME(m_ireq));
|
save_item(NAME(m_ireq));
|
||||||
save_item(NAME(m_iena));
|
save_item(NAME(m_iena));
|
||||||
|
save_item(NAME(m_irq_level));
|
||||||
if (st2xxx_lctr_mask() != 0)
|
if (st2xxx_lctr_mask() != 0)
|
||||||
{
|
{
|
||||||
save_item(NAME(m_lssa));
|
save_item(NAME(m_lssa));
|
||||||
@ -282,20 +284,34 @@ void st2xxx_device::device_reset()
|
|||||||
m_bctr = 0;
|
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)
|
u8 st2xxx_device::read_vector(u16 adr)
|
||||||
{
|
{
|
||||||
if (adr >= 0xfffe)
|
if (adr >= 0xfffe)
|
||||||
{
|
{
|
||||||
u16 ireq_active = m_ireq & m_iena;
|
if (adr == 0xfffe)
|
||||||
if (ireq_active != 0 && irq_taken)
|
|
||||||
{
|
{
|
||||||
// IREQH interrupts have priority over IREQL interrupts
|
set_irq_service(true);
|
||||||
ireq_active = swapendian_int16(ireq_active);
|
|
||||||
int level = 31 - int(8 ^ count_leading_zeros_32(ireq_active & -ireq_active));
|
// Make sure this doesn't change in between vector pull cycles
|
||||||
adr -= (level + 3) << 1;
|
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",
|
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,
|
PPC,
|
||||||
m_ireq,
|
m_ireq,
|
||||||
m_iena,
|
m_iena,
|
||||||
@ -303,11 +319,9 @@ u8 st2xxx_device::read_vector(u16 adr)
|
|||||||
|
|
||||||
if (BIT(adr, 0))
|
if (BIT(adr, 0))
|
||||||
{
|
{
|
||||||
m_ireq &= ~(1 << level);
|
m_ireq &= ~(1 << m_irq_level);
|
||||||
update_irq_state();
|
update_irq_state();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
set_irq_service(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return downcast<mi_st2xxx &>(*mintf).read_vector(adr);
|
return downcast<mi_st2xxx &>(*mintf).read_vector(adr);
|
||||||
|
@ -135,6 +135,7 @@ protected:
|
|||||||
|
|
||||||
void set_irq_service(bool state) { downcast<mi_st2xxx &>(*mintf).irq_service = state; }
|
void set_irq_service(bool state) { downcast<mi_st2xxx &>(*mintf).irq_service = state; }
|
||||||
void update_irq_state() { irq_state = (m_ireq & m_iena) != 0; }
|
void update_irq_state() { irq_state = (m_ireq & m_iena) != 0; }
|
||||||
|
u8 active_irq_level() const;
|
||||||
|
|
||||||
TIMER_CALLBACK_MEMBER(bt_interrupt);
|
TIMER_CALLBACK_MEMBER(bt_interrupt);
|
||||||
TIMER_CALLBACK_MEMBER(lcd_interrupt);
|
TIMER_CALLBACK_MEMBER(lcd_interrupt);
|
||||||
@ -268,6 +269,7 @@ protected:
|
|||||||
|
|
||||||
u16 m_ireq;
|
u16 m_ireq;
|
||||||
u16 m_iena;
|
u16 m_iena;
|
||||||
|
u8 m_irq_level;
|
||||||
|
|
||||||
u16 m_lssa;
|
u16 m_lssa;
|
||||||
u8 m_lvpw;
|
u8 m_lvpw;
|
||||||
|
Loading…
Reference in New Issue
Block a user