API reference#
#include <Z80.h>
Types#
Callback pointers#
-
typedef zuint8 (*Z80Read)(void *context, zuint16 address)#
Defines a pointer to a
Z80
callback function invoked to perform a read operation.- Param context:
The
Z80::context
of the calling object.- Param address:
The memory address or I/O port to read from.
- Return:
The byte read.
-
typedef void (*Z80Write)(void *context, zuint16 address, zuint8 value)#
Defines a pointer to a
Z80
callback function invoked to perform a write operation.- Param context:
The
Z80::context
of the calling object.- Param address:
The memory address or I/O port to write to.
- Param value:
The byte to write.
-
typedef void (*Z80Halt)(void *context, zuint8 signal)#
Defines a pointer to a
Z80
callback function invoked to notify a signal change on the HALT line.- Param context:
The
Z80::context
of the calling object.- Param signal:
A code specifying the type of signal change.
-
typedef void (*Z80Notify)(void *context)#
Defines a pointer to a
Z80
callback function invoked to notify an event.- Param context:
The
Z80::context
of the calling object.
Emulator object#
-
struct Z80#
A Z80 CPU emulator.
A
Z80
object contains the state of an emulated Z80 CPU, pointers to callback functions that interconnect the emulator with the external logic and a context that is passed to these functions.Because no constructor function is provided, it is mandatory to directly initialize all callback pointers and
Z80::options
before using an object of this type. Optional callbacks must be set toZ_NULL
when not in use.Public Members
-
zusize cycles#
Number of clock cycles already executed.
-
zusize cycle_limit#
Maximum number of clock cycles to be executed.
-
void *context#
Pointer to pass as the first argument to all callback functions.
This member is intended to hold a reference to the context to which the object belongs. It is safe not to initialize it when this is not necessary.
-
Z80Read fetch_opcode#
Invoked to perform an opcode fetch.
This callback indicates the beginning of an opcode fetch M-cycle. The function must return the byte located at the memory address specified by the second argument.
-
Z80Read fetch#
Invoked to perform a memory read on instruction data.
This callback indicates the beginning of a memory read M-cycle during which the CPU fetches one byte of instruction data (i.e., one byte of the instruction that is neither a prefix nor an opcode). The function must return the byte located at the memory address specified by the second argument.
-
Z80Read read#
Invoked to perform a memory read.
This callback indicates the beginning of a memory read M-cycle. The function must return the byte located at the memory address specified by the second argument.
-
Z80Write write#
Invoked to perform a memory write.
This callback indicates the beginning of a memory write M-cycle. The function must write the third argument into the memory location specified by the second argument.
-
Z80Read in#
Invoked to perform an I/O port read.
This callback indicates the beginning of an I/O read M-cycle. The function must return the byte read from the I/O port specified by the second argument.
-
Z80Write out#
Invoked to perform an I/O port write.
This callback indicates the beginning of an I/O write M-cycle. The function must write the third argument to the I/O port specified by the second argument.
-
Z80Halt halt#
Invoked to notify a signal change on the HALT line.
This callback is optional and must be set to
Z_NULL
when not in use. Its invocation is always deferred until the next emulation step so that the emulator can abort the signal change if any invalidating condition occurs, such as the acceptance of an interrupt during the execution of ahalt
instruction.The second parameter of the function specifies the type of signal change and can only contain a boolean value if the Z80 library has not been built with special RESET support:
1
indicates that the HALT line is going low during the last clock cycle of ahalt
instruction, which means that the CPU is entering the HALT state.0
indicates that the HALT line is going high during the last clock cycle of an internal NOP executed during the HALT state, i.e., the CPU is exiting the HALT state due to an interrupt or normal RESET.
If the library has been built with special RESET support, the values
Z80_HALT_EXIT_EARLY
andZ80_HALT_CANCEL
are also possible for the second parameter.
-
Z80Read nop#
Invoked to perform an opcode fetch that corresponds to an internal NOP.
This callback indicates the beginning of an opcode fetch M-cycle of 4 clock cycles that is generated in the following two cases:
During the HALT state, the CPU repeatedly executes an internal NOP that fetches the next opcode after the
halt
instruction without incrementing the PC register. This opcode is read again and again until an exit condition occurs (i.e., NMI, INT or RESET).After detecting a special RESET signal, the CPU completes the ongoing instruction or interrupt response and then zeroes the PC register during the first clock cycle of the next M1 cycle. If no interrupt has been accepted at the end of the instruction or interrupt response, the CPU produces an internal NOP to allow for the fetch-execute overlap to take place, during which it fetches the next opcode and zeroes PC.
This callback is optional but note that setting it to
Z_NULL
is equivalent to enablingZ80_OPTION_HALT_SKIP
.
-
Z80Read nmia#
Invoked to perform an opcode fetch that corresponds to a non-maskable interrupt acknowledge M-cycle.
This callback is optional and must be set to
Z_NULL
when not in use. It indicates the beginning of an NMI acknowledge M-cycle. The value returned by the function is ignored.
-
Z80Read inta#
Invoked to perform a data bus read that corresponds to a maskable interrupt acknowledge M-cycle.
This callback is optional and must be set to
Z_NULL
when not in use. It indicates the beginning of an INT acknowledge M-cycle. The function must return the byte that the interrupting I/O device supplies to the CPU via the data bus during this M-cycle.When this callback is
Z_NULL
, the emulator assumes that the value read from the data bus is0xFF
.
-
Z80Read int_fetch#
Invoked to perform a memory read on instruction data during a maskable interrupt response in mode 0.
The role of this callback is analogous to that of
Z80::fetch
, but it is specific to the INT response in mode 0. Ideally, the function should return a byte of instruction data that the interrupting I/O device supplies to the CPU via the data bus, but depending on the emulated hardware, the device may not be able to do this during a memory read M-cycle because the memory is addressed instead, in which case the function must return the byte located at the memory address specified by the second parameter.This callback will only be invoked if
Z80::inta
is notZ_NULL
and returns an opcode that implies subsequent memory read M-cycles to fetch the non-opcode bytes of the instruction, so it is safe not to initialize it or set it toZ_NULL
if such a scenario is not possible.
-
Z80Notify ld_i_a#
Invoked to notify that an
ld i,a
instruction has been fetched.This callback is optional and must be set to
Z_NULL
when not in use. It is invoked before executing the instruction.
-
Z80Notify ld_r_a#
Invoked to notify that an
ld r,a
instruction has been fetched.This callback is optional and must be set to
Z_NULL
when not in use. It is invoked before executing the instruction.
-
Z80Notify reti#
Invoked to notify that a
reti
instruction has been fetched.This callback is optional and must be set to
Z_NULL
when not in use. It is invoked before executing the instruction.
-
Z80Notify retn#
Invoked to notify that a
retn
instruction has been fetched.This callback is optional and must be set to
Z_NULL
when not in use. It is invoked before executing the instruction.
-
Z80Read hook#
Invoked when a trap is fetched.
This callback is optional and must be set to
Z_NULL
when not in use, in which case the opcode of the trap will be executed normally. The function receives the memory address of the trap as the second parameter and must return the opcode to be executed instead of the trap. If the function returns a trap (i.e.,Z80_HOOK
), the emulator will do nothing, so the trap will be fetched again unless the function has modifiedZ80::pc
or replaced the trap in memory with another opcode. Also note that returning a trap does not revert the increment ofZ80::r
performed before each opcode fetch.
-
Z80Illegal illegal#
Invoked to delegate the execution of an illegal instruction.
This callback is optional and must be set to
Z_NULL
when not in use. Only those instructions with the0xED
prefix that behave the same as two consecutivenop
instructions are considered illegal. The function receives the illegal opcode as the second parameter and must return the number of clock cycles taken by the instruction.At the time of invoking this callback, and relative to the start of the instruction, only
Z80::r
has been incremented (twice), soZ80::pc
still contains the memory address of the0xED
prefix.
-
ZInt32 data#
Temporary storage used for instruction fetch.
-
ZInt16 ix_iy[2]#
Index registers, IX and IY.
-
ZInt16 pc#
Register PC (program counter).
-
ZInt16 sp#
Register SP (stack pointer).
-
ZInt16 xy#
Temporary index register.
All instructions with the
0xDD
prefix behave exactly the same as their counterparts with the0xFD
prefix, differing only in the index register: the former use IX, whereas the latter use IY. When one of these prefixes is fetched, the corresponding index register is copied into this member; the instruction logic is then executed and finally this member is copied back into the index register.
-
ZInt16 memptr#
Register MEMPTR, also known as WZ.
-
ZInt16 af#
Register pair AF (accumulator and flags).
-
ZInt16 bc#
Register pair BC.
-
ZInt16 de#
Register pair DE.
-
ZInt16 hl#
Register pair HL.
-
ZInt16 af_#
Register pair AF’.
-
ZInt16 bc_#
Register pair BC’.
-
ZInt16 de_#
Register pair DE’.
-
ZInt16 hl_#
Register pair HL’.
-
zuint8 r#
Register R (memory refresh).
-
zuint8 i#
Register I (interrupt vector base).
-
zuint8 r7#
Backup of bit 7 of the R register.
The Z80 CPU increments the R register during each M1 cycle without altering its most significant bit, commonly known as R7. However, the emulator only performs normal full-byte increments for speed reasons, which eventually corrupts R7.
Before entering the execution loop, both
z80_execute
andz80_run
copyZ80::r
into this member to preserve the value of R7, so that they can restore it before returning. The emulation of theld r, a
instruction also updates the value of this member.
-
zuint8 im#
Maskable interrupt mode.
Contains the number of the maskable interrupt mode in use:
0
,1
or2
.
-
zuint8 request#
Requests pending to be responded.
-
zuint8 resume#
Type of unfinished operation to be resumed.
-
zuint8 iff1#
Interrupt enable flip-flop #1 (IFF1).
-
zuint8 iff2#
Interrupt enable flip-flop #2 (IFF2).
-
zuint8 q#
Q factor.
-
zuint8 options#
Emulation options.
This member specifies the different emulation options that are enabled. It is mandatory to initialize it before using the emulator. Setting it to
0
disables all options.
-
zuint8 int_line#
State of the INT line.
The value of this member is
1
if the INT line is low; otherwise,0
.
-
zusize cycles#
Functions#
Powering the CPU#
Running the emulation#
-
zusize z80_execute(Z80 *self, zusize cycles)#
Runs a
Z80
for a given number of clockcycles
, executing only instructions without responding to signals.- Parameters:
self – Pointer to the object on which the function is called.
cycles – Number of clock cycles to be emulated.
- Returns:
The actual number of clock cycles emulated.
Stopping the emulation#
-
static inline void z80_break(Z80 *self)#
Ends the emulation loop of
z80_execute
orz80_run
.This function should only be used inside callback functions. It zeroes
Z80::cycle_limit
, thus breaking the emulation loop after the completion of the ongoing emulation step.- Parameters:
self – Pointer to the object on which the function is called.
Requesting interrupts#
-
void z80_int(Z80 *self, zboolean state)#
Sets the state of the INT line of a
Z80
.- Parameters:
self – Pointer to the object on which the function is called.
state –
Z_TRUE
= set line low;Z_FALSE
= set line high.
-
void z80_nmi(Z80 *self)#
Triggers the NMI line of a
Z80
.- Parameters:
self – Pointer to the object on which the function is called.
-
void z80_instant_reset(Z80 *self)#
Performs an instantaneous normal RESET on a
Z80
.- Parameters:
self – Pointer to the object on which the function is called.
-
void z80_special_reset(Z80 *self)#
Sends a special RESET signal to a
Z80
.See also
http://www.primrosebank.net/computers/z80/z80_special_reset.htm
US Patent 4486827
- Parameters:
self – Pointer to the object on which the function is called.
Obtaining information#
-
static inline zuint8 z80_in_cycle(Z80 const *self)#
Obtains the clock cycle, relative to the start of the instruction, at which the I/O read M-cycle being executed by a
Z80
begins.- Parameters:
self – Pointer to the object on which the function is called.
- Returns:
The clock cycle at which the I/O read M-cycle begins.
-
static inline zuint8 z80_out_cycle(Z80 const *self)#
Obtains the clock cycle, relative to the start of the instruction, at which the I/O write M-cycle being executed by a
Z80
begins.- Parameters:
self – Pointer to the object on which the function is called.
- Returns:
The clock cycle at which the I/O write M-cycle begins.
Macros#
Library version#
Limits#
-
Z80_MAXIMUM_CYCLES#
Maximum number of clock cycles that
z80_run
andz80_execute
can emulate.
-
Z80_MAXIMUM_CYCLES_PER_STEP#
Maximum number of clock cycles that
z80_run
will emulate if instructed to execute 1 clock cycle.This is the number of clock cycles it takes to execute the longest instruction through interrupt mode 0, not counting the M-cycle used to fetch a
0xDD
or0xFD
prefix. Forz80_execute
, subtract 4 clock cycles from this value.
-
Z80_MINIMUM_CYCLES_PER_STEP#
Minimum number of clock cycles that
z80_run
orz80_execute
will emulate if instructed to execute 1 clock cycle.
Opcodes#
Flags#
Configuration#
-
Z80_OPTION_HALT_SKIP#
Z80::options
bitmask that enables the HALTskip optimization.
-
Z80_OPTION_IM0_RETX_NOTIFICATIONS#
Z80::options
bitmask that enables notifications for anyreti
orretn
instruction executed during the interrupt mode 0 response.
-
Z80_OPTION_LD_A_IR_BUG#
Z80::options
bitmask that enables emulation of the bug affecting the Zilog Z80 NMOS, which causes the P/V flag to be reset when a maskable interrupt is accepted during the execution of theld a,{i|r}
instructions.
-
Z80_OPTION_OUT_VC_255#
Z80::options
bitmask that enables emulation of theout (c),255
instruction, specific to the Zilog Z80 CMOS.
-
Z80_OPTION_XQ#
Z80::options
bitmask that enables the XQ factor in the emulation of theccf
andscf
instructions.
-
Z80_OPTION_YQ#
Z80::options
bitmask that enables the YQ factor in the emulation of theccf
andscf
instructions.
-
Z80_MODEL_ZILOG_NMOS#
Z80::options
bitmask that enables full emulation of the Zilog NMOS models.
-
Z80_MODEL_ZILOG_CMOS#
Z80::options
bitmask that enables full emulation of the Zilog CMOS models.
-
Z80_MODEL_NEC_NMOS#
Z80::options
bitmask that enables full emulation of the NEC NMOS models.
-
Z80_MODEL_ST_CMOS#
Z80::options
bitmask that enables full emulation of the ST CMOS models.
Requests#
-
Z80_REQUEST_INT#
Z80::request
bitmask indicating that the INT line is low and interrupts are enabled.
-
Z80_REQUEST_NMI#
Z80::request
bitmask indicating that an NMI signal has been received.
-
Z80_REQUEST_REJECT_NMI#
Z80::request
bitmask that prevents the NMI signal from being accepted.
-
Z80_REQUEST_SPECIAL_RESET#
Z80::request
bitmask indicating that a special RESET signal has been received.
Resume codes#
Sometimes the emulator runs out of clock cycles while performing long tasks that can exceed Z80_MAXIMUM_CYCLES_PER_STEP
. In these cases, the emulation stops and Z80::resume
is set to one of the following values:
-
Z80_RESUME_HALT#
Z80::resume
value indicating that the emulator ran out of clock cycles during the HALT state.
-
Z80_RESUME_XY#
Z80::resume
value indicating that the emulator ran out of clock cycles by fetching a prefix0xDD
or0xFD
.
-
Z80_RESUME_IM0_XY#
Z80::resume
value indicating that the emulator ran out of clock cycles by fetching a prefix0xDD
or0xFD
, during a maskable interrupt response in mode 0.
HALT state codes#
Register accessors#
-
Z80_WZ#
Same as
Z80_MEMPTR
.
-
Z80_WZH#
Same as
Z80_MEMPTRH
.
-
Z80_WZL#
Same as
Z80_MEMPTRL
.
-
Z80_XYH(object)#
Accesses the most significant byte of the temporary index register of a
Z80
object
.