diff options
Diffstat (limited to 'src/devices/cpu/m6502/st2xxx.cpp')
-rw-r--r-- | src/devices/cpu/m6502/st2xxx.cpp | 70 |
1 files changed, 44 insertions, 26 deletions
diff --git a/src/devices/cpu/m6502/st2xxx.cpp b/src/devices/cpu/m6502/st2xxx.cpp index 2c24f65f653..4dbaf96b3b3 100644 --- a/src/devices/cpu/m6502/st2xxx.cpp +++ b/src/devices/cpu/m6502/st2xxx.cpp @@ -35,16 +35,17 @@ #include "emu.h" #include "st2xxx.h" -#define LOG_IRQ (1 << 1U) -#define LOG_BT (1 << 2U) -#define LOG_LCDC (1 << 3U) +#define LOG_IRQ (1U << 1) +#define LOG_BT (1U << 2) +#define LOG_LCDC (1U << 3) +#define VERBOSE LOG_IRQ //#define VERBOSE (LOG_IRQ | LOG_BT | LOG_LCDC) #include "logmacro.h" st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram) - : r65c02_device(mconfig, type, tag, owner, clock) + : w65c02s_device(mconfig, type, tag, owner, clock) , m_data_config("data", ENDIANNESS_LITTLE, 8, data_bits, 0) - , m_in_port_cb(*this) + , m_in_port_cb(*this, 0xff) , m_out_port_cb(*this) , m_prr_mask(data_bits <= 14 ? 0 : ((u16(1) << (data_bits - 14)) - 1) | (has_banked_ram ? 0x8000 : 0)) , m_drr_mask(data_bits <= 15 ? 0 : ((u16(1) << (data_bits - 15)) - 1) | (has_banked_ram ? 0x8000 : 0)) @@ -64,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) @@ -96,12 +98,6 @@ device_memory_interface::space_config_vector st2xxx_device::memory_space_config( }; } -void st2xxx_device::device_resolve_objects() -{ - m_in_port_cb.resolve_all_safe(0xff); - m_out_port_cb.resolve_all_safe(); -} - TIMER_CALLBACK_MEMBER(st2xxx_device::bt_interrupt) { // BTSR must be cleared each time the interrupt is serviced @@ -130,7 +126,7 @@ void st2xxx_device::init_base_timer(u16 ireq) if (st2xxx_bt_divider(n) != 0) { m_bt_mask |= 1 << n; - m_base_timer[n] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2xxx_device::bt_interrupt), this)); + m_base_timer[n] = timer_alloc(FUNC(st2xxx_device::bt_interrupt), this); } } @@ -149,7 +145,7 @@ void st2xxx_device::init_lcd_timer(u16 ireq) m_lcd_ireq = ireq; assert(m_lcd_ireq != 0); - m_lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2xxx_device::lcd_interrupt), this)); + m_lcd_timer = timer_alloc(FUNC(st2xxx_device::lcd_interrupt), this); } void st2xxx_device::save_common_registers() @@ -186,6 +182,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)); @@ -281,24 +278,47 @@ void st2xxx_device::device_reset() m_bctr = 0; } -u8 st2xxx_device::acknowledge_irq() +u8 st2xxx_device::active_irq_level() const { // IREQH interrupts have priority over IREQL interrupts - for (int pri = 0; pri < 16; pri++) + 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) { - int level = pri ^ 8; - if (BIT(m_ireq & m_iena, level)) + if (adr == 0xfffe) { - LOGMASKED(LOG_IRQ, "%s interrupt acknowledged (PC = $%04X, vector = $%04X)\n", - st2xxx_irq_name(level), + 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(m_irq_level), PPC, - 0x7ff8 - (level << 1)); - m_ireq &= ~(1 << level); - update_irq_state(); - return level; + m_ireq, + m_iena, + adr & 0x7fff); + + if (BIT(adr, 0)) + { + m_ireq &= ~(1 << m_irq_level); + update_irq_state(); + } } } - throw emu_fatalerror("ST2XXX: no IRQ to acknowledge!\n"); + return downcast<mi_st2xxx &>(*mintf).read_vector(adr); } u8 st2xxx_device::pdata_r(offs_t offset) @@ -892,5 +912,3 @@ void st2xxx_device::bdiv_w(u8 data) { m_bdiv = data; } - -#include "cpu/m6502/st2xxx.hxx" |