/* Return nonzero if a pending NMI should be dispatched now. This takes account for the internal delays of the 6510, but does not actually check the status of the NMI line. */ inline static int interrupt_check_nmi_delay(interrupt_cpu_status_t *cs, CLOCK cpu_clk) { CLOCK nmi_clk = cs->nmi_clk + INTERRUPT_DELAY; /* BRK (0x00) delays the NMI by one opcode. */ /* TODO DO_INTERRUPT sets last opcode to 0: can NMI occur right after IRQ? */ if (OPINFO_NUMBER(*cs->last_opcode_info_ptr) == 0x00) { return 0; } /* Branch instructions delay IRQs and NMI by one cycle if branch is taken with no page boundary crossing. */ if (OPINFO_DELAYS_INTERRUPT(*cs->last_opcode_info_ptr)) { nmi_clk++; } if (cpu_clk >= nmi_clk) { return 1; } return 0; }
/* Handle matrix fetch events. FIXME: could be made slightly faster. */ void ted_fetch_alarm_handler(CLOCK offset, void *data) { CLOCK last_opcode_first_write_clk, last_opcode_last_write_clk; /* This kludgy thing is used to emulate the behavior of the 6510 when BA goes low. When BA goes low, every read access stops the processor until BA is high again; write accesses happen as usual instead. */ if (offset > 0) { switch (OPINFO_NUMBER(last_opcode_info)) { case 0: /* In BRK, IRQ and NMI the 3rd, 4th and 5th cycles are write accesses, while the 1st, 2nd, 6th and 7th are read accesses. */ last_opcode_first_write_clk = maincpu_clk - 10; last_opcode_last_write_clk = maincpu_clk - 6; break; case 0x20: /* In JSR, the 4th and 5th cycles are write accesses, while the 1st, 2nd, 3rd and 6th are read accesses. */ last_opcode_first_write_clk = maincpu_clk - 6; last_opcode_last_write_clk = maincpu_clk - 4; break; default: /* In all the other opcodes, all the write accesses are the last ones. */ if (maincpu_num_write_cycles() != 0) { last_opcode_last_write_clk = maincpu_clk - 2; last_opcode_first_write_clk = maincpu_clk - maincpu_num_write_cycles() * 2; } else { last_opcode_first_write_clk = (CLOCK)0; last_opcode_last_write_clk = last_opcode_first_write_clk; } break; } } else { /* offset <= 0, i.e. offset == 0 */ /* If we are called with no offset, we don't have to care about write accesses. */ last_opcode_first_write_clk = last_opcode_last_write_clk = 0; } { CLOCK sub; CLOCK write_offset; if (ted.fetch_clk < (last_opcode_first_write_clk - 1) || ted.fetch_clk > last_opcode_last_write_clk) { sub = 0; } else { sub = last_opcode_last_write_clk - ted.fetch_clk + 1; } handle_fetch_matrix(offset, sub, &write_offset); last_opcode_first_write_clk += write_offset; last_opcode_last_write_clk += write_offset; } if ((offset > 11) && (ted.fastmode)) { dma_maincpu_steal_cycles(ted.fetch_clk, -(((signed)offset - 11) / 2), 0); ted_delay_oldclk(-(((signed)offset - 11) / 2)); } }