Module z80emu::host::cycles

source ·
Expand description

This module defines constants indicating the number of T-states of each of the emulated Cpu cycle, to help Clock implementations count those cycles.

Below are the diagrams showing timings for all CPU cycles. The diagrams include the information when the Io::is_irq is being called, compared with the moment when the INT line is being sampled by the real CPU.

§M1 (opcode fetch)

M1 is indicated by a call to Clock::add_m1. The function should return a timestamp that is being passed to the Memory::read_opcode function and should increase the internal counter by at least M1_CYCLE_TS.

       T1  T2  T3  T4
       _   _   _   _   _
      | |_| |_| |_| |_| |_|
      0               ^ M1_CYCLE_TS
A0-15 |---pc--|---ir--|
D0-7      -op-|
MREQ  --_______--___----
RD    --______----------
M1    -________---------
RFSH  ----------_______-
WAIT  ......--..........
      <===============> Memory::read_opcode
                      ^ Io::is_irq ¹
INT   ............___.. ¹

§Memory Read or Write.

This cycle is indicated by a call to Clock::add_mreq. The function should return a timestamp that is being passed to one of: Memory::read_mem, Memory::read_mem16 or Memory::write_mem functions and should increase the internal counter by at least MEMRW_CYCLE_TS.

       T1  T2  T3
       _   _   _   _  
      | |_| |_| |_| |_|
      0           ^ MEMRW_CYCLE_TS
A0-15 |--address--|
D0-7      ---data-|
MREQ  --_________--
RD    --_________-- (read)
WR    ------_____-- (write)
WAIT  .....--......
      <===========> Memory::read_mem/write_mem
                  ^ Io::is_irq ¹
INT   ........___.. ¹

§Input/Output.

This cycle is indicated by a call to Clock::add_io. The function should return a timestamp that is being passed to one of: Io::read_io or Io::write_io functions and should increase the internal counter by at least IO_CYCLE_TS. The aforementioned Io methods can in turn insert an additional number of wait states (visible here as TW) into this cycle.

       T1  T2  TW  T3
       _   _   _   _   _   
      | |_| |_| |_| |_| |_|
      0               ^ IO_CYCLE_TS
          ^ IO_IORQ_LOW_TS
A0-15 |-----port------|
D0-7      |----data---|
IORQ  -----__________--
RD    -----__________-- (read)
WR    -----__________-- (write)
WAIT  .........__......
      <===============> Io::read_io/write_io
                      ^ Io::is_irq ¹
INT   ............___.. ¹

§Interrupt Request/Acknowledge.

This cycle is indicated by a call to Clock::add_irq. The function should return a timestamp that is being passed to the Io::irq_data function and should increase the internal counter by at least IRQ_ACK_CYCLE_TS. The Io::irq_data method can in turn insert an additional number of wait states (visible here as TW) into this cycle.

       T1  T2  TW  TW  T3  T4
       _   _   _   _   _   _
      | |_| |_| |_| |_| |_| |_|
      0                       ^ IRQ_ACK_CYCLE_TS
              ^ INT_IORQ_LOW_TS
A0-15 |------pc-------|---ir--|
D0-7          |--data-|
M1    -________________--------
MREQ  -------------------_____-
IORQ  -----------______--------
WAIT  .............--..........
      <=======================> Io::irq_data

§RETI

This is not a cycle but rather a special case for an instruction which is being used by the Z80 peripherals to detect the end of the interrupt service routine. The currently active device in the daisy chain, with the IEI line high, can deactivate its IEO line and let the device with lower priority take control over the INT line. The diagram shows when the Io::reti is being called while executing the RETI instruction.

       T1  T2  T3  T4  T1  T2  T3  T4  T1  T2  T3  T1  T2  T3
       _   _   _   _   _   _   _   _   _   _   _   _   _   _
      | |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_|
Clock |>>> add_m1 >>>>|>>> add_m1 >>>>|> add_mreq |> add_mreq |
A0-15 |---pc--|---ir--|--pc+1-|---ir--|-----sp----|----sp+1---|
D0-7      -ED-|       |   -4D-|           ----lo--|   ----hi--|
                                      ^ Io::reti(pc+2)        ^ Io::is_irq
INT   ....................................................___..

¹ The INT line is being probed with the rising edge of the final clock at the end of every instruction when the interrupts are enabled, except after the EI instruction and prefixes: 0xDD, 0xFD.

Constants§

  • The minimum number of T-states in a maskable interrupt request/acknowledge cycle before the IORQ goes low and the earliest moment the value might be put on the bus.
  • The minimum number of T-states for an I/O cycle.
  • The minimum number of T-states for an I/O cycle before the IORQ goes low and the earliest moment the value might be available on the bus.
  • The number of T-states in a maskable interrupt request/acknowledge cycle.
  • The minimum number of T-states for an M1 cycle: opcode fetch, non-maskable interrupt and a HALT cycle.
  • The minimum number of T-states for a memory read or write cycle.