summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m6805/hd6305.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/m6805/hd6305.cpp')
-rw-r--r--src/devices/cpu/m6805/hd6305.cpp623
1 files changed, 623 insertions, 0 deletions
diff --git a/src/devices/cpu/m6805/hd6305.cpp b/src/devices/cpu/m6805/hd6305.cpp
new file mode 100644
index 00000000000..2cc866c7494
--- /dev/null
+++ b/src/devices/cpu/m6805/hd6305.cpp
@@ -0,0 +1,623 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb, Olivier Galibert
+/*
+
+Hitachi HD6305 series
+
+TODO:
+- HD6305xx has a 14-bit address space, not 13 (memory_access in m6805.h)
+- add unimplemented opcodes: STOP, WAIT, DAA, and HD63705Z0 also has MUL
+- add HD63705Z0 peripherals
+
+*/
+
+#include "emu.h"
+#include "hd6305.h"
+#include "m6805defs.h"
+
+hd6305_device::hd6305_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock,
+ device_type const type,
+ configuration_params const &params,
+ address_map_constructor internal_map) :
+ m6805_base_device(mconfig, tag, owner, clock, type, params, internal_map),
+ m_sci_clk(*this),
+ m_sci_tx(*this),
+ m_read_port(*this, 0xff),
+ m_write_port(*this)
+{
+ std::fill(m_port_ddr_override.begin(), m_port_ddr_override.end(), 0x00);
+}
+
+// common peripherals
+
+void hd6305_device::device_start()
+{
+ m6805_base_device::device_start();
+
+ save_item(NAME(m_port_data));
+ save_item(NAME(m_port_ddr));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_prescaler));
+ save_item(NAME(m_tcr));
+ save_item(NAME(m_ssr));
+ save_item(NAME(m_scr));
+ save_item(NAME(m_mr));
+ save_item(NAME(m_timer_last_update));
+ save_item(NAME(m_sci_tx_data));
+ save_item(NAME(m_sci_tx_filled));
+ save_item(NAME(m_sci_tx_byte));
+ save_item(NAME(m_sci_tx_step));
+
+ m_timer_timer = timer_alloc(FUNC(hd6305_device::timer_cb), this);
+ m_timer_sci = timer_alloc(FUNC(hd6305_device::sci_cb), this);
+}
+
+void hd6305_device::device_reset()
+{
+ m6805_base_device::device_reset();
+
+ std::fill(m_port_data.begin(), m_port_data.end(), 0x00);
+ std::fill(m_port_ddr.begin(), m_port_ddr.end(), 0x00);
+
+ m_tdr = 0xf0;
+ m_prescaler = 0x7f;
+ m_tcr = 0x50;
+ m_ssr = 0x3f;
+ m_scr = 0x00;
+ m_mr = 0x5f;
+
+ m_timer_last_update = total_cycles();
+
+ m_sci_tx_data = 0;
+
+ m_sci_tx_filled = false;
+ m_sci_tx_byte = 0;
+ m_sci_tx_step = 0;
+
+ m_sci_clk(1);
+ m_sci_tx(1);
+}
+
+template<int Port>
+u8 hd6305_device::port_r()
+{
+ const u8 ddr = m_port_ddr[Port] & ~m_port_ddr_override[Port];
+ if(ddr == 0xff)
+ return m_port_data[Port];
+
+ return (m_port_data[Port] & ddr) | (m_read_port[Port]() & ~ddr);
+}
+
+template<int Port>
+void hd6305_device::port_w(u8 data)
+{
+ if(data != m_port_data[Port]) {
+ m_port_data[Port] = data;
+ m_write_port[Port](Port, data | ~m_port_ddr[Port], m_port_ddr[Port]);
+ }
+}
+
+template<int Port>
+u8 hd6305_device::port_ddr_r()
+{
+ return m_port_ddr[Port];
+}
+
+template<int Port>
+void hd6305_device::port_ddr_w(u8 data)
+{
+ if(data != m_port_ddr[Port]) {
+ logerror("port %d ddr %c%c%c%c%c%c%c%c\n",
+ Port,
+ BIT(data, 7) ? 'o': 'i',
+ BIT(data, 6) ? 'o': 'i',
+ BIT(data, 5) ? 'o': 'i',
+ BIT(data, 4) ? 'o': 'i',
+ BIT(data, 3) ? 'o': 'i',
+ BIT(data, 2) ? 'o': 'i',
+ BIT(data, 1) ? 'o': 'i',
+ BIT(data, 0) ? 'o': 'i');
+
+ m_port_ddr[Port] = data;
+ m_write_port[Port](Port, m_port_data[Port] | ~data, data);
+ }
+}
+
+void hd6305_device::timer_update_regs()
+{
+ if(machine().side_effects_disabled())
+ return;
+
+ u32 counter = m_prescaler;
+ u64 tc = machine().time().as_ticks(clock())/4;
+ u32 cycles = tc - m_timer_last_update;
+
+ u32 next_counter = counter + cycles;
+ u32 shift = BIT(m_tcr, 0, 3);
+ u32 steps = shift ? (((next_counter >> (shift-1)) + 1) >> 1) - (((counter >> (shift-1)) + 1) >> 1) : cycles;
+
+ m_tdr -= steps;
+ m_prescaler = next_counter & 0x7f;
+ m_timer_last_update = tc;
+ if(!m_tdr && steps) {
+ m_tcr |= 0x80;
+ if(!BIT(m_tcr, 6))
+ m_pending_interrupts |= 1 << HD6305_INT_TIMER1;
+ }
+}
+
+void hd6305_device::timer_wait_next_timeout()
+{
+ u32 shift = BIT(m_tcr, 0, 3);
+ u32 cycles;
+ if(shift == 0)
+ cycles = 1;
+ else {
+ u32 masked_prescaler = ((1 << shift) - 1) & m_prescaler;
+ if(masked_prescaler >= (1 << (shift-1)))
+ cycles = (3 << (shift-1)) - masked_prescaler;
+ else
+ cycles = (1 << (shift-1)) - masked_prescaler;
+ }
+ if(m_tdr != 1)
+ cycles += (m_tdr ? m_tdr - 1 : 0xff) << shift;
+ m_timer_timer->adjust(attotime::from_ticks(cycles*4, clock()));
+}
+
+u8 hd6305_device::timer_data_r()
+{
+ timer_update_regs();
+ return m_tdr;
+}
+
+void hd6305_device::timer_data_w(u8 data)
+{
+ timer_update_regs();
+ m_tdr = data;
+ timer_wait_next_timeout();
+}
+
+u8 hd6305_device::timer_ctrl_r()
+{
+ timer_update_regs();
+ return m_tcr;
+}
+
+void hd6305_device::timer_ctrl_w(u8 data)
+{
+ timer_update_regs();
+ u8 old = m_tcr;
+ m_tcr = (m_tcr & data & 0x80) | (data & 0x7f);
+ if((old ^ m_tcr) & 0x7f) {
+ logerror("timer ctrl %02x irq=%s, %s clock=%s%s prescale=%d\n", data,
+ BIT(m_tcr, 7) ? "on" : "off",
+ BIT(m_tcr, 6) ? "disabled" : "enabled",
+ BIT(m_tcr, 4, 2) == 0 ? "e" : BIT(m_tcr, 4, 2) == 1 ? "e&timer" : BIT(m_tcr, 4, 2) == 2 ? "off" : "timer",
+ BIT(m_tcr, 3) ? " reset prescaler" : "",
+ 1 << BIT(m_tcr, 0, 3));
+
+ if(BIT(m_tcr, 4, 2) != 0)
+ logerror("WARNING: timer mode not implemented\n");
+ }
+ if((m_tcr & 0xc0) == 0x80)
+ m_pending_interrupts |= 1 << HD6305_INT_TIMER1;
+ else
+ m_pending_interrupts &= ~(1 << HD6305_INT_TIMER1);
+ if(BIT(m_tcr, 3)) {
+ m_prescaler = 0x7f;
+ m_tcr &= ~0x08;
+ }
+
+ timer_wait_next_timeout();
+}
+
+
+TIMER_CALLBACK_MEMBER(hd6305_device::timer_cb)
+{
+ timer_update_regs();
+ timer_wait_next_timeout();
+}
+
+u8 hd6305_device::misc_r()
+{
+ return m_mr;
+}
+
+void hd6305_device::misc_w(u8 data)
+{
+ m_mr = (m_mr & data & 0x80) | (data & 0x60) | 0x1f;
+ logerror("misc %02x int2=%s, %s int=%s\n", data,
+ BIT(m_mr, 7) ? "on" : "off",
+ BIT(m_mr, 6) ? "disabled" : "enabled",
+ BIT(m_mr, 5) ? "edge" : "level");
+}
+
+void hd6305_device::sci_timer_step()
+{
+ m_timer_sci->adjust(attotime::from_ticks(1 << (BIT(m_scr, 0, 4) + 2), clock()));
+}
+
+TIMER_CALLBACK_MEMBER(hd6305_device::sci_cb)
+{
+ if(m_sci_tx_step == 16) {
+ m_ssr |= 0x80;
+ if(!BIT(m_ssr, 5))
+ m_pending_interrupts |= 1 << HD6305_INT_SCI;
+
+ if(m_sci_tx_filled) {
+ m_sci_tx_filled = false;
+ m_sci_clk(0);
+ m_sci_tx_byte = m_sci_tx_data;
+ logerror("transmit %02x\n", m_sci_tx_byte);
+ m_sci_tx(m_sci_tx_byte & 0x01);
+ m_sci_tx_step = 1;
+ } else {
+ m_sci_tx_step = 0;
+ return;
+ }
+ } else {
+ if(m_sci_tx_step & 1)
+ m_sci_clk(1);
+ else {
+ m_sci_clk(0);
+ m_sci_tx((m_sci_tx_byte >> (m_sci_tx_step >> 1)) & 0x01);
+ }
+ m_sci_tx_step++;
+ }
+
+ sci_timer_step();
+}
+
+u8 hd6305_device::sci_ctrl_r()
+{
+ return m_scr;
+}
+
+void hd6305_device::sci_ctrl_w(u8 data)
+{
+ m_scr = data;
+ logerror("sci ctrl %02x d3=%s d4=%s d5=%s rate=%d\n", data,
+ BIT(data, 7) ? "data_out" : "gpio",
+ BIT(data, 6) ? "data_in" : "gpio",
+ BIT(data, 5) == 0 ? "gpio" : BIT(data, 4) ? "clock_in" : "clock_out",
+ clock()/(1 << (BIT(data, 0, 4) + 3)));
+}
+
+u8 hd6305_device::sci_ssr_r()
+{
+ return m_ssr;
+}
+
+void hd6305_device::sci_ssr_w(u8 data)
+{
+ m_ssr = ((m_ssr & data) & 0xc0) | (data & 0x38) | 7;
+ logerror("sci ssr w %02x sci irq=%s, %s timer2 irq=%s, %s%s\n", data,
+ BIT(m_ssr, 7) ? "on" : "off",
+ BIT(m_ssr, 5) ? "disabled" : "enabled",
+ BIT(m_ssr, 6) ? "on" : "off",
+ BIT(m_ssr, 4) ? "disabled" : "enabled",
+ BIT(m_ssr, 3) ? "reset sci prescaler" : "");
+
+ if((m_ssr & 0xa0) == 0x80)
+ m_pending_interrupts |= 1 << HD6305_INT_SCI;
+ else
+ m_pending_interrupts &= ~(1 << HD6305_INT_SCI);
+}
+
+u8 hd6305_device::sci_data_r()
+{
+ if(!machine().side_effects_disabled())
+ logerror("sci data r\n");
+ return 0x00;
+}
+
+void hd6305_device::sci_data_w(u8 data)
+{
+ m_sci_tx_data = data;
+ if(m_sci_tx_step == 0) {
+ m_sci_tx_filled = false;
+ m_sci_clk(0);
+ m_sci_tx_byte = m_sci_tx_data;
+ logerror("transmit %02x\n", m_sci_tx_byte);
+ m_sci_tx(m_sci_tx_byte & 0x01);
+ m_sci_tx_step = 1;
+ sci_timer_step();
+ } else
+ m_sci_tx_filled = true;
+}
+
+void hd6305_device::execute_set_input(int inputnum, int state)
+{
+ // TODO: edge vs. level on int1
+ if(inputnum == HD6305_INT_IRQ1 || inputnum == HD6305_INT_IRQ2) {
+ if(m_irq_state[inputnum] != state) {
+ m_irq_state[inputnum] = state;
+
+ if(state != CLEAR_LINE)
+ m_pending_interrupts |= 1 << inputnum;
+ }
+ }
+}
+
+void hd6305_device::interrupt_vector()
+{
+ if((m_pending_interrupts & (1 << HD6305_INT_IRQ1)) != 0) {
+ m_pending_interrupts &= ~(1 << HD6305_INT_IRQ1);
+ rm16<false>(0x1ffa, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD6305_INT_IRQ2)) != 0) {
+ m_pending_interrupts &= ~(1 << HD6305_INT_IRQ2);
+ rm16<false>(0x1ff8, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD6305_INT_TIMER1)) != 0) {
+ // TODO: 1ff6 when in wait...
+ m_pending_interrupts &= ~(1 << HD6305_INT_TIMER1);
+ rm16<false>(0x1ff8, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD6305_INT_TIMER2)) != 0) {
+ m_pending_interrupts &= ~(1 << HD6305_INT_TIMER2);
+ rm16<false>(0x1ff4, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD6305_INT_SCI)) != 0) {
+ m_pending_interrupts &= ~(1 << HD6305_INT_SCI);
+ rm16<false>(0x1ff4, m_pc);
+ }
+}
+
+
+/****************************************************************************
+ * HD6305V0 section
+ ****************************************************************************/
+
+hd6305v0_device::hd6305v0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ hd6305_device(
+ mconfig,
+ tag,
+ owner,
+ clock,
+ HD6305V0,
+ { s_hmos_s_ops, s_hd6305_cycles, 14, 0x00ff, 0x00c0, 0x1fff, 0x1ffc },
+ address_map_constructor(FUNC(hd6305v0_device::internal_map), this))
+{
+}
+
+void hd6305v0_device::internal_map(address_map &map)
+{
+ map(0x0000, 0x0000).rw(FUNC(hd6305v0_device::port_r<0>), FUNC(hd6305v0_device::port_w<0>));
+ map(0x0001, 0x0001).rw(FUNC(hd6305v0_device::port_r<1>), FUNC(hd6305v0_device::port_w<1>));
+ map(0x0002, 0x0002).rw(FUNC(hd6305v0_device::port_r<2>), FUNC(hd6305v0_device::port_w<2>));
+ map(0x0003, 0x0003).rw(FUNC(hd6305v0_device::port_r<3>), FUNC(hd6305v0_device::port_w<3>));
+ map(0x0004, 0x0004).rw(FUNC(hd6305v0_device::port_ddr_r<0>), FUNC(hd6305v0_device::port_ddr_w<0>));
+ map(0x0005, 0x0005).rw(FUNC(hd6305v0_device::port_ddr_r<1>), FUNC(hd6305v0_device::port_ddr_w<1>));
+ map(0x0006, 0x0006).rw(FUNC(hd6305v0_device::port_ddr_r<2>), FUNC(hd6305v0_device::port_ddr_w<2>));
+ map(0x0007, 0x0007).rw(FUNC(hd6305v0_device::port_ddr_r<3>), FUNC(hd6305v0_device::port_ddr_w<3>));
+ map(0x0008, 0x0008).rw(FUNC(hd6305v0_device::timer_data_r), FUNC(hd6305v0_device::timer_data_w));
+ map(0x0009, 0x0009).rw(FUNC(hd6305v0_device::timer_ctrl_r), FUNC(hd6305v0_device::timer_ctrl_w));
+ map(0x000a, 0x000a).rw(FUNC(hd6305v0_device::misc_r), FUNC(hd6305v0_device::misc_w));
+ map(0x0010, 0x0010).rw(FUNC(hd6305v0_device::sci_ctrl_r), FUNC(hd6305v0_device::sci_ctrl_w));
+ map(0x0011, 0x0011).rw(FUNC(hd6305v0_device::sci_ssr_r), FUNC(hd6305v0_device::sci_ssr_w));
+ map(0x0012, 0x0012).rw(FUNC(hd6305v0_device::sci_data_r), FUNC(hd6305v0_device::sci_data_w));
+ map(0x0040, 0x00ff).ram();
+ map(0x1000, 0x1fff).rom().region(DEVICE_SELF, 0);
+}
+
+
+/****************************************************************************
+ * HD6305Y0 section
+ ****************************************************************************/
+
+hd6305y0_device::hd6305y0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ hd6305_device(
+ mconfig,
+ tag,
+ owner,
+ clock,
+ HD6305Y0,
+ { s_hmos_s_ops, s_hd6305_cycles, 14, 0x00ff, 0x00c0, 0x1fff, 0x1ffc },
+ address_map_constructor(FUNC(hd6305y0_device::internal_map), this))
+{
+}
+
+void hd6305y0_device::internal_map(address_map &map)
+{
+ map(0x0000, 0x0000).rw(FUNC(hd6305y0_device::port_r<0>), FUNC(hd6305y0_device::port_w<0>));
+ map(0x0001, 0x0001).rw(FUNC(hd6305y0_device::port_r<1>), FUNC(hd6305y0_device::port_w<1>));
+ map(0x0002, 0x0002).rw(FUNC(hd6305y0_device::port_r<2>), FUNC(hd6305y0_device::port_w<2>));
+ map(0x0003, 0x0003).r(FUNC(hd6305y0_device::port_r<3>));
+ map(0x0004, 0x0004).w(FUNC(hd6305y0_device::port_ddr_w<0>));
+ map(0x0005, 0x0005).w(FUNC(hd6305y0_device::port_ddr_w<1>));
+ map(0x0006, 0x0006).w(FUNC(hd6305y0_device::port_ddr_w<2>));
+ map(0x0007, 0x0007).w(FUNC(hd6305y0_device::port_ddr_w<6>));
+ map(0x0008, 0x0008).rw(FUNC(hd6305y0_device::timer_data_r), FUNC(hd6305y0_device::timer_data_w));
+ map(0x0009, 0x0009).rw(FUNC(hd6305y0_device::timer_ctrl_r), FUNC(hd6305y0_device::timer_ctrl_w));
+ map(0x000a, 0x000a).rw(FUNC(hd6305y0_device::misc_r), FUNC(hd6305y0_device::misc_w));
+ map(0x000b, 0x000b).rw(FUNC(hd6305y0_device::port_r<4>), FUNC(hd6305y0_device::port_w<4>));
+ map(0x000c, 0x000c).rw(FUNC(hd6305y0_device::port_r<5>), FUNC(hd6305y0_device::port_w<5>));
+ map(0x000d, 0x000d).rw(FUNC(hd6305y0_device::port_r<6>), FUNC(hd6305y0_device::port_w<6>));
+ map(0x0010, 0x0010).rw(FUNC(hd6305y0_device::sci_ctrl_r), FUNC(hd6305y0_device::sci_ctrl_w));
+ map(0x0011, 0x0011).rw(FUNC(hd6305y0_device::sci_ssr_r), FUNC(hd6305y0_device::sci_ssr_w));
+ map(0x0012, 0x0012).rw(FUNC(hd6305y0_device::sci_data_r), FUNC(hd6305y0_device::sci_data_w));
+ map(0x0040, 0x013f).ram();
+ map(0x0140, 0x1fff).rom().region(DEVICE_SELF, 0);
+}
+
+void hd6305y0_device::device_reset()
+{
+ hd6305_device::device_reset();
+
+ // ports E and F are write-only
+ m_port_ddr[4] = m_port_ddr[5] = 0xff;
+}
+
+
+/****************************************************************************
+ * HD6305Y2 section
+ ****************************************************************************/
+
+hd6305y2_device::hd6305y2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ hd6305_device(
+ mconfig,
+ tag,
+ owner,
+ clock,
+ HD6305Y2,
+ { s_hmos_s_ops, s_hd6305_cycles, 14, 0x00ff, 0x00c0, 0x1fff, 0x1ffc },
+ address_map_constructor(FUNC(hd6305y2_device::internal_map), this))
+{
+}
+
+void hd6305y2_device::internal_map(address_map &map)
+{
+ map(0x0000, 0x0000).rw(FUNC(hd6305y2_device::port_r<0>), FUNC(hd6305y2_device::port_w<0>));
+ map(0x0001, 0x0001).rw(FUNC(hd6305y2_device::port_r<1>), FUNC(hd6305y2_device::port_w<1>));
+ map(0x0002, 0x0002).rw(FUNC(hd6305y2_device::port_r<2>), FUNC(hd6305y2_device::port_w<2>));
+ map(0x0003, 0x0003).r(FUNC(hd6305y2_device::port_r<3>));
+ map(0x0004, 0x0004).w(FUNC(hd6305y2_device::port_ddr_w<0>));
+ map(0x0005, 0x0005).w(FUNC(hd6305y2_device::port_ddr_w<1>));
+ map(0x0006, 0x0006).w(FUNC(hd6305y2_device::port_ddr_w<2>));
+ map(0x0008, 0x0008).rw(FUNC(hd6305y2_device::timer_data_r), FUNC(hd6305y2_device::timer_data_w));
+ map(0x0009, 0x0009).rw(FUNC(hd6305y2_device::timer_ctrl_r), FUNC(hd6305y2_device::timer_ctrl_w));
+ map(0x000a, 0x000a).rw(FUNC(hd6305y2_device::misc_r), FUNC(hd6305y2_device::misc_w));
+ map(0x0010, 0x0010).rw(FUNC(hd6305y2_device::sci_ctrl_r), FUNC(hd6305y2_device::sci_ctrl_w));
+ map(0x0011, 0x0011).rw(FUNC(hd6305y2_device::sci_ssr_r), FUNC(hd6305y2_device::sci_ssr_w));
+ map(0x0012, 0x0012).rw(FUNC(hd6305y2_device::sci_data_r), FUNC(hd6305y2_device::sci_data_w));
+ // All other page zero addresses up to 0x001f are reserved
+ map(0x0040, 0x013f).ram();
+}
+
+
+/****************************************************************************
+ * HD63705Z0 section
+ ****************************************************************************/
+
+hd63705z0_device::hd63705z0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ hd6305_device(
+ mconfig,
+ tag,
+ owner,
+ clock,
+ HD63705Z0,
+ { s_hmos_b_ops, s_hd63705_cycles, 16, 0x017f, 0x0100, 0x1fff, 0x1ffa },
+ address_map_constructor(FUNC(hd63705z0_device::internal_map), this))
+{
+}
+
+void hd63705z0_device::internal_map(address_map &map)
+{
+ // TODO: ports, timer, SCI
+ map(0x0040, 0x01bf).ram();
+ map(0x01c0, 0x1fff).rom().region(DEVICE_SELF, 0x01c0);
+}
+
+void hd63705z0_device::execute_set_input(int inputnum, int state)
+{
+ if(inputnum == INPUT_LINE_NMI) {
+ if(m_nmi_state != state) {
+ m_nmi_state = state;
+
+ if(state != CLEAR_LINE)
+ m_pending_interrupts |= 1 << HD63705_INT_NMI;
+ }
+ }
+ else if(inputnum <= HD63705_INT_ADCONV) {
+ if(m_irq_state[inputnum] != state) {
+ m_irq_state[inputnum] = state;
+
+ if(state != CLEAR_LINE)
+ m_pending_interrupts |= 1 << inputnum;
+ }
+ }
+}
+
+void hd63705z0_device::interrupt_vector()
+{
+ // Need to add emulation of other interrupt sources here KW-2/4/99
+ // This is just a quick patch for Namco System 2 operation
+
+ if((m_pending_interrupts & (1 << HD63705_INT_IRQ1)) != 0) {
+ m_pending_interrupts &= ~(1 << HD63705_INT_IRQ1);
+ rm16<true>(0x1ff8, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD63705_INT_IRQ2)) != 0) {
+ m_pending_interrupts &= ~(1 << HD63705_INT_IRQ2);
+ rm16<true>(0x1fec, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD63705_INT_ADCONV)) != 0) {
+ m_pending_interrupts &= ~(1 << HD63705_INT_ADCONV);
+ rm16<true>(0x1fea, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD63705_INT_TIMER1)) != 0) {
+ m_pending_interrupts &= ~(1 << HD63705_INT_TIMER1);
+ rm16<true>(0x1ff6, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD63705_INT_TIMER2)) != 0) {
+ m_pending_interrupts &= ~(1 << HD63705_INT_TIMER2);
+ rm16<true>(0x1ff4, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD63705_INT_TIMER3)) != 0) {
+ m_pending_interrupts &= ~(1<<HD63705_INT_TIMER3);
+ rm16<true>(0x1ff2, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD63705_INT_PCI)) != 0) {
+ m_pending_interrupts &= ~(1 << HD63705_INT_PCI);
+ rm16<true>(0x1ff0, m_pc);
+ }
+ else if((m_pending_interrupts & (1 << HD63705_INT_SCI)) != 0) {
+ m_pending_interrupts &= ~(1 << HD63705_INT_SCI);
+ rm16<true>(0x1fee, m_pc);
+ }
+}
+
+void hd63705z0_device::interrupt()
+{
+ // the 6805 latches interrupt requests internally, so we don't clear
+ // pending_interrupts until the interrupt is taken, no matter what the
+ // external IRQ pin does.
+
+ if(BIT(m_pending_interrupts, HD63705_INT_NMI)) {
+ pushword<true>(m_pc);
+ pushbyte<true>(m_x);
+ pushbyte<true>(m_a);
+ pushbyte<true>(m_cc);
+ SEI;
+
+ // no vectors supported, just do the callback to clear irq_state if needed
+ standard_irq_callback(0, m_pc.w.l);
+
+ rm16<true>(0x1ffc, m_pc);
+ m_pending_interrupts &= ~(1 << HD63705_INT_NMI);
+
+ m_icount -= 11;
+ burn_cycles(11);
+ }
+ else if((m_pending_interrupts & ((1 << M6805_IRQ_LINE) | HD63705_INT_MASK)) != 0) {
+ if((CC & IFLAG) == 0) {
+ // standard IRQ
+ pushword<true>(m_pc);
+ pushbyte<true>(m_x);
+ pushbyte<true>(m_a);
+ pushbyte<true>(m_cc);
+ SEI;
+
+ // no vectors supported, just do the callback to clear irq_state if needed
+ standard_irq_callback(0, m_pc.w.l);
+
+ interrupt_vector();
+
+ m_pending_interrupts &= ~(1 << M6805_IRQ_LINE);
+
+ m_icount -= 11;
+ burn_cycles(11);
+ }
+ }
+}
+
+
+DEFINE_DEVICE_TYPE(HD6305V0, hd6305v0_device, "hd6305v0", "Hitachi HD6305V0")
+DEFINE_DEVICE_TYPE(HD6305Y0, hd6305y0_device, "hd6305y0", "Hitachi HD6305Y0")
+DEFINE_DEVICE_TYPE(HD6305Y2, hd6305y2_device, "hd6305y2", "Hitachi HD6305Y2")
+DEFINE_DEVICE_TYPE(HD63705Z0, hd63705z0_device, "hd63705z0", "Hitachi HD63705Z0")