summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m6502/st2xxx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/m6502/st2xxx.cpp')
-rw-r--r--src/devices/cpu/m6502/st2xxx.cpp70
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"