diff options
Diffstat (limited to 'src/devices/cpu/z80')
-rw-r--r-- | src/devices/cpu/z80/z80.cpp | 144 | ||||
-rw-r--r-- | src/devices/cpu/z80/z80.h | 4 |
2 files changed, 84 insertions, 64 deletions
diff --git a/src/devices/cpu/z80/z80.cpp b/src/devices/cpu/z80/z80.cpp index e798a1153b2..345ea4334bf 100644 --- a/src/devices/cpu/z80/z80.cpp +++ b/src/devices/cpu/z80/z80.cpp @@ -10,7 +10,6 @@ * - If LD A,I or LD A,R is interrupted, P/V flag gets reset, even if IFF2 * was set before this instruction (implemented, but not enabled: we need * document Z80 types first, see below) - * - WAIT only stalls between instructions now, it should stall immediately. * - Ideally, the tiny differences between Z80 types should be supported, * currently known differences: * - LD A,I/R P/V flag reset glitch is fixed on CMOS Z80 @@ -3125,27 +3124,6 @@ OP(op,fe) { cp(arg()); OP(op,ff) { rst(0x38); } /* RST 7 */ -void z80_device::take_nmi() -{ - /* there isn't a valid previous program counter */ - PRVPC = -1; - - /* Check if processor was halted */ - leave_halt(); - -#if HAS_LDAIR_QUIRK - /* reset parity flag after LD A,I or LD A,R */ - if (m_after_ldair) F &= ~PF; -#endif - - m_iff1 = 0; - push(m_pc); - PCD = 0x0066; - WZ=PCD; - m_icount -= 11; - m_nmi_pending = FALSE; -} - void z80_device::take_interrupt() { int irq_vector; @@ -3228,11 +3206,6 @@ void z80_device::take_interrupt() m_icount -= m_cc_ex[0xff]; } WZ=PCD; - -#if HAS_LDAIR_QUIRK - /* reset parity flag after LD A,I or LD A,R */ - if (m_after_ldair) F &= ~PF; -#endif } void nsc800_device::take_interrupt_nsc800() @@ -3266,11 +3239,6 @@ void nsc800_device::take_interrupt_nsc800() m_icount -= m_cc_op[0xff] + cc_ex[0xff]; WZ=PCD; - -#if HAS_LDAIR_QUIRK - /* reset parity flag after LD A,I or LD A,R */ - if (m_after_ldair) F &= ~PF; -#endif } /**************************************************************************** @@ -3506,25 +3474,44 @@ void nsc800_device::device_reset() } /**************************************************************************** - * Execute 'cycles' T-states. + * Execute 'cycles' T-states. Return number of T-states really executed ****************************************************************************/ void z80_device::execute_run() { + /* check for NMIs on the way in; they can only be set externally */ + /* via timers, and can't be dynamically enabled, so it is safe */ + /* to just check here */ + if (m_nmi_pending) + { + LOG(("Z80 '%s' take NMI\n", tag())); + PRVPC = -1; /* there isn't a valid previous program counter */ + leave_halt(); /* Check if processor was halted */ + +#if HAS_LDAIR_QUIRK + /* reset parity flag after LD A,I or LD A,R */ + if (m_after_ldair) F &= ~PF; +#endif + m_after_ldair = FALSE; + + m_iff1 = 0; + push(m_pc); + PCD = 0x0066; + WZ=PCD; + m_icount -= 11; + m_nmi_pending = FALSE; + } + do { - if (m_wait_state) + /* check for IRQs before each instruction */ + if (m_irq_state != CLEAR_LINE && m_iff1 && !m_after_ei) { - // stalled - m_icount = 0; - return; - } - - // check for interrupts before each instruction - if (m_nmi_pending) - take_nmi(); - else if (m_irq_state != CLEAR_LINE && m_iff1 && !m_after_ei) +#if HAS_LDAIR_QUIRK + /* reset parity flag after LD A,I or LD A,R */ + if (m_after_ldair) F &= ~PF; +#endif take_interrupt(); - + } m_after_ei = FALSE; m_after_ldair = FALSE; @@ -3537,25 +3524,34 @@ void z80_device::execute_run() void nsc800_device::execute_run() { - do + /* check for NMIs on the way in; they can only be set externally */ + /* via timers, and can't be dynamically enabled, so it is safe */ + /* to just check here */ + if (m_nmi_pending) { - if (m_wait_state) - { - // stalled - m_icount = 0; - return; - } + LOG(("Z80 '%s' take NMI\n", tag())); + PRVPC = -1; /* there isn't a valid previous program counter */ + leave_halt(); /* Check if processor was halted */ + + m_iff1 = 0; + push(m_pc); + PCD = 0x0066; + WZ=PCD; + m_icount -= 11; + m_nmi_pending = FALSE; + } - // check for interrupts before each instruction - if (m_nmi_pending) - take_nmi(); - else if ((m_nsc800_irq_state[NSC800_RSTA] != CLEAR_LINE || m_nsc800_irq_state[NSC800_RSTB] != CLEAR_LINE || m_nsc800_irq_state[NSC800_RSTC] != CLEAR_LINE) && m_iff1 && !m_after_ei) + do + { + /* check for NSC800 IRQs line RSTA, RSTB, RSTC */ + if ((m_nsc800_irq_state[NSC800_RSTA] != CLEAR_LINE || m_nsc800_irq_state[NSC800_RSTB] != CLEAR_LINE || m_nsc800_irq_state[NSC800_RSTC] != CLEAR_LINE) && m_iff1 && !m_after_ei) take_interrupt_nsc800(); - else if (m_irq_state != CLEAR_LINE && m_iff1 && !m_after_ei) + + /* check for IRQs before each instruction */ + if (m_irq_state != CLEAR_LINE && m_iff1 && !m_after_ei) take_interrupt(); m_after_ei = FALSE; - m_after_ldair = FALSE; PRVPC = PCD; debugger_instruction_hook(this, PCD); @@ -3591,9 +3587,6 @@ void z80_device::execute_set_input(int inputnum, int state) case Z80_INPUT_LINE_WAIT: m_wait_state = state; break; - - default: - break; } } @@ -3601,6 +3594,17 @@ void nsc800_device::execute_set_input(int inputnum, int state) { switch (inputnum) { + case Z80_INPUT_LINE_BUSRQ: + m_busrq_state = state; + break; + + case INPUT_LINE_NMI: + /* mark an NMI pending on the rising edge */ + if (m_nmi_state == CLEAR_LINE && state != CLEAR_LINE) + m_nmi_pending = TRUE; + m_nmi_state = state; + break; + case NSC800_RSTA: m_nsc800_irq_state[NSC800_RSTA] = state; break; @@ -3613,8 +3617,17 @@ void nsc800_device::execute_set_input(int inputnum, int state) m_nsc800_irq_state[NSC800_RSTC] = state; break; - default: - z80_device::execute_set_input(inputnum, state); + case INPUT_LINE_IRQ0: + /* update the IRQ state via the daisy chain */ + m_irq_state = state; + if (m_daisy.present()) + m_irq_state = m_daisy.update_irq_state(); + + /* the main execute loop will take the interrupt */ + break; + + case Z80_INPUT_LINE_WAIT: + m_wait_state = state; break; } } @@ -3737,3 +3750,10 @@ nsc800_device::nsc800_device(const machine_config &mconfig, const char *tag, dev } const device_type NSC800 = &device_creator<nsc800_device>; + + + +WRITE_LINE_MEMBER( z80_device::irq_line ) +{ + set_input_line( INPUT_LINE_IRQ0, state ); +} diff --git a/src/devices/cpu/z80/z80.h b/src/devices/cpu/z80/z80.h index 38cc207347e..c523f101a24 100644 --- a/src/devices/cpu/z80/z80.h +++ b/src/devices/cpu/z80/z80.h @@ -19,7 +19,6 @@ enum NSC800_RSTB, NSC800_RSTC, Z80_INPUT_LINE_WAIT, - Z80_INPUT_LINE_BOGUSWAIT, /* WAIT pin implementation used to be nonexistent, please remove this when all drivers are updated with Z80_INPUT_LINE_WAIT */ Z80_INPUT_LINE_BUSRQ }; @@ -42,6 +41,8 @@ class z80_device : public cpu_device public: z80_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + DECLARE_WRITE_LINE_MEMBER( irq_line ); + void z80_set_cycle_tables(const UINT8 *op, const UINT8 *cb, const UINT8 *ed, const UINT8 *xy, const UINT8 *xycb, const UINT8 *ex); template<class _Object> static devcb_base &set_irqack_cb(device_t &device, _Object object) { return downcast<z80_device &>(device).m_irqack_cb.set_callback(object); } template<class _Object> static devcb_base &set_refresh_cb(device_t &device, _Object object) { return downcast<z80_device &>(device).m_refresh_cb.set_callback(object); } @@ -237,7 +238,6 @@ protected: void ei(); void take_interrupt(); - void take_nmi(); // address spaces const address_space_config m_program_config; |