diff --git a/API/Z80.h b/API/Z80.h
index da46799..4249299 100644
--- a/API/Z80.h
+++ b/API/Z80.h
@@ -28,8 +28,7 @@
*
* @details The Z80 library implements a fast, small and accurate emulator
* of the Zilog Z80. It emulates all that is known to date about this CPU,
- * including the undocumented flags and instructions, MEMPTR, Q, and the
- * special RESET.
+ * including the undocumented behaviour, MEMPTR, Q and the special RESET.
*
* @version 0.2
* @date 2022-05-29
@@ -52,72 +51,89 @@
# endif
#endif
-/** @brief The major version number of the Z80 library. */
+/** @brief Major version number of the Z80 library. */
#define Z80_LIBRARY_VERSION_MAJOR 0
-/** @brief The minor version number of the Z80 library. */
+/** @brief Minor version number of the Z80 library. */
#define Z80_LIBRARY_VERSION_MINOR 2
-/** @brief The micro version number of the Z80 library. */
+/** @brief Micro version number of the Z80 library. */
#define Z80_LIBRARY_VERSION_MICRO 0
-/** @brief A string literal with the version number of the Z80 library. */
+/** @brief String literal with the version number of the Z80 library. */
#define Z80_LIBRARY_VERSION_STRING "0.2"
-/** @brief The maximum number of clock cycles that the @ref z80_run and @ref
+/** @brief Maximum number of clock cycles that the @ref z80_run and @ref
* z80_execute functions can emulate per call. */
#define Z80_CYCLE_LIMIT (Z_USIZE_MAXIMUM - Z_USIZE(30))
#define Z80_CYCLES_PER_RESET 5
-/** @brief The 8-bit value interpreted as a hook by the Z80 emulator, which
- * corresponds to the ld h,h opcode in the Z80 ISA. */
+/** @brief Opcode interpreted as a hook by the Z80 emulator, which
+ * corresponds to the ld h,h instruction of the Z80 ISA. */
#define Z80_HOOK Z_UINT8(0x64)
-/** @brief Defines a pointer to a callback function used by the Z80 emulator
- * to read a byte.
+/** @brief Defines a pointer to a @ref Z80 callback function invoked to perform
+ * a read operation.
*
- * @param context The value of the @ref Z80.context member variable of the
- * object invoking the callback.
+ * @param context The value of the @ref Z80.context member of the calling
+ * object.
* @param address The memory address or I/O port to read from.
* @return The byte read. */
typedef zuint8 (* Z80Read)(void *context, zuint16 address);
-/** @brief Defines a pointer to a callback function used by the Z80 emulator
- * to write a byte.
+/** @brief Defines a pointer to a @ref Z80 callback function invoked to perform
+ * a write operation.
*
- * @param context The value of the @ref Z80.context member variable of the
- * object invoking the callback.
+ * @param context The value of the @ref Z80.context member of the calling
+ * object.
* @param address The memory address or I/O port to write to.
* @param value The byte to write. */
typedef void (* Z80Write)(void *context, zuint16 address, zuint8 value);
-/** @brief Defines a pointer to a callback function used by the Z80 emulator
- * to notify the change of state of the HALT line.
+/** @brief Defines a pointer to a @ref Z80 callback function invoked to notify
+ * a signal change on the HALT line.
*
- * @param context The value of the @ref Z80.context member variable of the
- * object invoking the callback.
+ * @param context The value of the @ref Z80.context member of the calling
+ * object.
* @param state
* @c TRUE if the HALT line goes low (the CPU enters the HALT state);
* @c FALSE if the HALT line goes high (the CPU exits the HALT state). */
typedef void (* Z80HALT)(void *context, zboolean state);
-/** @brief Defines a pointer to a callback function used by the Z80 emulator
- * to notify an event.
+/** @brief Defines a pointer to a @ref Z80 callback function invoked to notify
+ * an event.
*
- * @param context The value of the @ref Z80.context member variable of the
- * object invoking the callback. */
+ * @param context The value of the @ref Z80.context member of the calling
+ * object. */
typedef void (* Z80Notify)(void *context);
+/** @brief Defines a pointer to a @ref Z80 callback function invoked to delegate
+ * the emulation of an illegal instruction.
+ *
+ * @param context The value of the @ref Z80.context member variable of the
+ * calling object.
+ * @param opcode The illegal opcode.
+ * @return The number of clock cycles consumed by the instruction. */
+
+typedef zuint8 (* Z80Illegal)(void *context, zuint8 opcode);
+
+/** @brief Defines a pointer to a @ref Z80 callback function invoked to obtain
+ * the duration of a RESET signal.
+ *
+ * @param context The value of the @ref Z80.context member of the calling
+ * object.
+ * @param address The value in the address bus when the RESET signal begins.
+ * @return The number of clock cycles that the RESET signal lasts. */
typedef zusize (* Z80Reset)(void *context, zuint16 address);
@@ -125,280 +141,183 @@ typedef zusize (* Z80Reset)(void *context, zuint16 address);
*
* @brief A Z80 CPU emulator.
*
- * @details @c Z80 contains the state of an emulated Z80 CPU
- * and the callback pointers needed to interconnect it with the external logic.
- * Before using an object of this type, some of its members
- * must be initialized. In particular the following (in alphabetical order):
- * @ref Z80.context, @ref Z80.fetch, @ref Z80.fetch_opcode, @ref Z80.halt_nop,
- * @ref Z80.in, @ref Z80.out, @ref Z80.read, @ref Z80.write, @ref Z80.read_bus,
- * @ref Z80.halt, @ref Z80.inta, @ref Z80.reti @ref Z80.hook and @ref
- * Z80.options.
- *
- * Callback | Mandatory
- * --------------------- | ---------
- * @ref Z80.fetch_opcode | yes
- * @ref Z80.fetch | yes
- * @ref Z80.read | yes
- * @ref Z80.write | yes
- * @ref Z80.in | yes
- * @ref Z80.out | yes
- * @ref Z80.halt | no
- * @ref Z80.halt_nop | no
- * @ref Z80.nmia | yes
- * @ref Z80.inta | yes
- * @ref Z80.int_fetch | no
- * @ref Z80.ld_i_a | no
- * @ref Z80.ld_r_a | no
- * @ref Z80.reti | no
- * @ref Z80.retn | no
- * @ref Z80.hook | no
- */
+ * @details @c Z80 contains the state of an emulated Z80 CPU and the callback
+ * pointers needed to interconnect it with the external logic. */
typedef struct {
- /** @brief Clock cycle counter.
- *
- * This clock cycle counter is updated as the emulator executes
- * instructions and responds to different signals. */
+ /** @brief Number of clock cycles executed. */
zusize cycles;
- /** @brief Maximum number of clock cycles to be executed in the current
- * invokation of @ref z80_run. */
+ /** @brief Maximum number of clock cycles to be executed. */
zusize cycle_limit;
- /** @brief Pointer passed as the first argument to the callbacks.
+ /** @brief Pointer to pass as first argument to callbacks.
*
- * @details This member variable can be used to maintain a reference to
- * the object or context to which the Z80 emulator object belongs. */
+ * @details This member is intended to maintain a reference to the
+ * context to which the object belongs. */
void *context;
- /** @brief Callback used to perform opcode fetch operations.
- *
- * @details This type of operation is used by the CPU to read the first
- * byte of an instruction or an instruction prefix. A succession of
- * @c DDh and/or @c FDh prefixes will cause multiple consecutive such
- * operations until an opcode is fetched. In the instructions with
- * double prefix (@c CBDDh or @c CBFDh), only the prefixes are fetched
- * with this operation, the remaining 2 bytes are accessed by using
- * normal memory read operations.
- *
- * The emulator always incrementents the R register @b before calling
- * this callback, but the value of its most-significant bit (R7) is not
- * preserved for speed optimization reasons. In the rare case that the
- * callback function needs to access that register, it must take R7
- * from the 7th bit of the @c r7 member variable.
- *
- * Implementations that do not distinguish between opcode fetch and
- * memory read operations should use the same callback function for
- * both.
+ /** @brief Callback invoked to perform an opcode fetch.
*
* @attention This callback is mandatory, initializing it to @c Z_NULL
* will cause the emulator to crash. */
Z80Read fetch_opcode;
- /** @brief Callback used to perform memory read operations on instruction data.
+ /** @brief Callback invoked to perform a memory read on instruction
+ * data.
*
* @attention This callback is mandatory, initializing it to @c Z_NULL
* will cause the emulator to crash. */
Z80Read fetch;
- /** @brief Callback used to perform a memory read operation.
- *
- * @details This type of operation is used by the CPU to read a byte
- * from a memory address.
+ /** @brief Callback invoked to perform a memory read.
*
* @attention This callback is mandatory, initializing it to @c Z_NULL
* will cause the emulator to crash. */
Z80Read read;
- /** @brief Callback used to perform a memory write operation.
- *
- * @details This type of operation is used by the CPU to write a byte
- * to a memory address.
+ /** @brief Callback invoked to peform a memory write.
*
* @attention This callback is mandatory, initializing it to @c Z_NULL
* will cause the emulator to crash. */
Z80Write write;
- /** @brief Callback used to perform an I/O read operation.
- *
- * @details This type of operation is used by the CPU to read a byte
- * from an I/O port.
+ /** @brief Callback invoked to perform an I/O read.
*
* @attention This callback is mandatory, initializing it to @c Z_NULL
* will cause the emulator to crash. */
Z80Read in;
- /** @brief Callback used to perform an I/O write operation.
- *
- * @details This type of operation is used by the CPU to write a byte
- * to an I/O port.
+ /** @brief Callback invoked to perform an I/O write.
*
* @attention This callback is mandatory, initializing it to @c Z_NULL
* will cause the emulator to crash. */
Z80Write out;
- /** @brief Callback used to notify that the state of the HALT output
- * line has changed.
+ /** @brief Callback invoked when the state of the HALT line changes.
*
- * @details The @c HALT instruction halts the CPU by not incrementing
- * the PC register, so the instruction is re-executed until an
- * interrupt is accepted. Only then the PC register is incremented
- * again and the next instruction is executed. The HALT output line is
- * active (low) during the HALT state.
- *
- * The emulator invokes this callback after changing the value of the
- * @c halt_line member variable and, when exiting the HALT state,
- * immediately before executing the interrupt response.
- *
- * @attention This callback is optional and @b must be initialized to
+ * @attention This callback is optional and must be initialized to
* @c Z_NULL if not used. */
Z80HALT halt;
- /** @brief Callback invoked... */
+ /** @brief Callback invoked to perform the disregarded opcode fetch of
+ * an internal NOP operation.
+ *
+ * @attention This callback is optional and must be initialized to
+ * @c Z_NULL if not used. */
Z80Read nop;
- /** @brief Callback invoked... */
+ /** @brief Callback invoked to perform the disregarded opcode fetch of
+ * a non-maskable interrupt acknowledge.
+ *
+ * @attention This callback is optional and must be initialized to
+ * @c Z_NULL if not used. */
Z80Read nmia;
- /** @brief Callback used to notify a maskable interrupt acknowledge
- * (INTA).
+ /** @brief Callback invoked to perform the data bus read of a maskable
+ * interrupt acknowledge.
*
- * @details When a maskable interrupt (INT) is accepted, the CPU
- * generates a special M1 cycle to indicate that the interrupting I/O
- * device can write to the data bus. Two wait clock cycles are added
- * to this M1 cycle, allowing sufficient time to identify which device
- * must insert the data.
- *
- * The emulator invokes this callback during the execution of the INT
- * response. It should be used to identify and prepare the context of
- * the interrupting device, so that subsequent invocations of the @c
- * read_bus callback can read the interrupt response vector or the
- * instruction to be executed.
- *
- * @note This callback is optional and @b must be initialized to @c
- * Z_NULL if not used.
-
- * @details When a maskable interrupt (INT) is accepted, the CPU reads
- * the interrupt response data provided by the interrupting device via
- * the data bus. Usually only one data bus read operation is performed
- * during the INT acknowledge cycle, but when the CPU responds to the
- * interrupt in mode 0, it will perform as many such operations as
- * needed to read the byte sequence of the instruction to be executed.
- *
- * The emulator invokes this callback during the execution of the INT
- * response. The return value is ignored in interrupt mode 1. In mode
- * 0, the emulator invokes this callback as many times as needed to
- * read a complete instruction. Illegal instructions and instruction
- * prefix sequences are fully supported.
- *
- * @attention This callback is optional and @b must be initialized to
- * @c Z_NULL if not used, in which case the emulator will assume that
- * the byte read from the data bus is always @c FFh. */
+ * @attention This callback is optional and must be initialized to
+ * @c Z_NULL if not used. */
Z80Read inta;
- /** @brief Callback used to perform a data bus read operation during a
- * maskable interrupt (INT) response.
- **/
+ /** @brief Callback invoked to perform a memory read on instruction data
+ * during a maskable interrupt response in mode 0.
+ *
+ * @attention This callback becomes mandatory when the @c Z80.inta
+ * callback is used. Initializing it to @c Z_NULL will cause the
+ * emulator to crash. */
Z80Read int_fetch;
+ /* @brief Callback invoked to query the duration of a reset signal.
+ *
+ * @attention This callback is optional and must be initialized to
+ * @c Z_NULL if not used. */
+
Z80Reset reset;
- /** @brief Callback invoked before executing the ld i,a
- * instruction. */
+ /** @brief Callback invoked when an ld i,a instruction is
+ * fetched.
+ *
+ * @attention This callback is optional and must be initialized to
+ * @c Z_NULL if not used. */
Z80Notify ld_i_a;
- /** @brief Callback invoked before executing the ld r,a
- * instruction.
+ /** @brief Callback invoked when an ld r,a instruction is
+ * fetched.
*
- * @attention This callback is optional and @b must be initialized to
+ * @attention This callback is optional and must be initialized to
* @c Z_NULL if not used. */
Z80Notify ld_r_a;
- /** @brief Callback invoked before executing the @c reti instruction.
+ /** @brief Callback invoked when a @c reti instruction is fetched.
*
- * The Z80 Counter/Timer Circuit (CTC) detects the two-byte @c reti
- * opcode when it is fetched by the CPU. This instruction is used to
- * return from an ISR and signal that the computer should initialize
- * the daisy-chain enable lines for control of nested priority
- * interrupt handling.
- *
- * Although the Z80 CTC is not part of the CPU, the emulator can signal
- * the execution of a @c reti instruction by invoking this callback in
- * order to simplify the emulation of machines that use daisy-chain
- * interrupt servicing, thus avoiding having to implement the detection
- * of this instruction externally, which is not optimal and would cause
- * a speed penalty.
- *
- * @attention This callback is optional and @b must be initialized to
+ * @attention This callback is optional and must be initialized to
* @c Z_NULL if not used. */
Z80Notify reti;
- /** @brief Callback invoked before executing the @c retn instruction.
-
- * @attention This callback is optional and @b must be initialized to
+ /** @brief Callback invoked when a @c retn instruction is fetched.
+ *
+ * @attention This callback is optional and must be initialized to
* @c Z_NULL if not used. */
Z80Notify retn;
- /** @brief Callback invoked...
+ /** @brief Callback invoked when a trap is fecthed.
*
- * @attention This callback is optional and @b must be initialized to
+ * @attention This callback is optional and must be initialized to
* @c Z_NULL if not used. */
Z80Read hook;
+ /** @brief Callback invoked to delegate the emulation of an illegal
+ * opcode.
+ *
+ * @attention This callback is optional and must be initialized to
+ * @c Z_NULL if not used. */
+
+ Z80Illegal illegal;
+
/** @brief Temporary storage used for instruction fetch. */
ZInt32 data;
- /** @brief Temporay IX/IY register. */
+ ZInt16 xy; /**< @brief Temporay IX/IY register. */
+ ZInt16 memptr; /**< @brief MEMPTR register. */
+ ZInt16 pc; /**< @brief PC register. */
+ ZInt16 sp; /**< @brief SP register. */
+ ZInt16 ix; /**< @brief IX register. */
+ ZInt16 iy; /**< @brief IY register. */
+ ZInt16 af; /**< @brief AF register. */
+ ZInt16 bc; /**< @brief BC register. */
+ ZInt16 de; /**< @brief DE register. */
+ ZInt16 hl; /**< @brief HL register. */
+ ZInt16 af_; /**< @brief AF' register. */
+ ZInt16 bc_; /**< @brief BC' register. */
+ ZInt16 de_; /**< @brief DE' register. */
+ ZInt16 hl_; /**< @brief HL' register. */
+ zuint8 r; /**< @brief R register. */
+ zuint8 i; /**< @brief I register. */
- ZInt16 xy;
-
- ZInt16 memptr; /**< @brief MEMPTR register. */
- ZInt16 pc; /**< @brief PC register. */
- ZInt16 sp; /**< @brief SP register. */
- ZInt16 ix; /**< @brief IX register. */
- ZInt16 iy; /**< @brief IY register. */
- ZInt16 af; /**< @brief AF register. */
- ZInt16 bc; /**< @brief BC register. */
- ZInt16 de; /**< @brief DE register. */
- ZInt16 hl; /**< @brief HL register. */
- ZInt16 af_; /**< @brief AF' register. */
- ZInt16 bc_; /**< @brief BC' register. */
- ZInt16 de_; /**< @brief DE' register. */
- ZInt16 hl_; /**< @brief HL' register. */
- zuint8 r; /**< @brief R register. */
- zuint8 i; /**< @brief I register. */
-
- /** @brief The most significant bit of the R register (R7).
- *
- * @details The R register is incremented during each M1 cycle, but its
- * most significant bit (R7) is not affected. For optimization reasons,
- * this behavior is not emulated in every M1 cycle, so successive
- * increments of R corrupt R7. @c z80_run keeps the value of R7 in this
- * temporary member variable while executing operations and copies it
- * back to R before returning. Since this variable is a snapshot of the
- * R register at a given time, the value of the 7 least significant
- * bits must be considered garbage. */
+ /** @brief The most significant bit of the R register. */
zuint8 r7;
@@ -409,21 +328,19 @@ typedef struct {
zuint8 im;
- /** @brief Number of signals pending to be processed. */
+ /** @brief Requests pending to be responded. */
zuint8 request;
- /** @brief TODO */
+ /** @brief Type of unfinished operation to be resumed. */
zuint8 resume;
- zuint8 iff1; /**< @brief Interrupt flip-flop 1 (IFF1). */
- zuint8 iff2; /**< @brief Interrupt flip-flop 2 (IFF2). */
- zuint8 q; /**< @brief Q register. */
+ zuint8 iff1; /**< @brief Interrupt enable flip-flop 1 (IFF1). */
+ zuint8 iff2; /**< @brief Interrupt enable flip-flop 2 (IFF2). */
+ zuint8 q; /**< @brief Q register. */
- /** @brief CPU model.
- *
- * @details todo... */
+ /** @brief Emulation options. */
zuint8 options;
@@ -443,49 +360,6 @@ typedef struct {
zuint8 halt_line;
} Z80;
-#define Z80_MEMPTR(self) (self).memptr.uint16_value
-#define Z80_MEMPTRH(self) (self).memptr.uint8_values.at_1
-#define Z80_MEMPTRL(self) (self).memptr.uint8_values.at_0
-#define Z80_PC(self) (self).pc.uint16_value
-#define Z80_SP(self) (self).sp.uint16_value
-#define Z80_XY(self) (self).xy.uint16_value
-#define Z80_IX(self) (self).ix.uint16_value
-#define Z80_IY(self) (self).iy.uint16_value
-#define Z80_AF(self) (self).af.uint16_value
-#define Z80_BC(self) (self).bc.uint16_value
-#define Z80_DE(self) (self).de.uint16_value
-#define Z80_HL(self) (self).hl.uint16_value
-#define Z80_AF_(self) (self).af_.uint16_value
-#define Z80_BC_(self) (self).bc_.uint16_value
-#define Z80_DE_(self) (self).de_.uint16_value
-#define Z80_HL_(self) (self).hl_.uint16_value
-#define Z80_PCH(self) (self).pc.uint8_values.at_1
-#define Z80_PCL(self) (self).pc.uint8_values.at_0
-#define Z80_SPH(self) (self).sp.uint8_values.at_1
-#define Z80_SPL(self) (self).sp.uint8_values.at_0
-#define Z80_XYH(self) (self).xy.uint8_values.at_1
-#define Z80_XYL(self) (self).xy.uint8_values.at_0
-#define Z80_IXH(self) (self).ix.uint8_values.at_1
-#define Z80_IXL(self) (self).ix.uint8_values.at_0
-#define Z80_IYH(self) (self).iy.uint8_values.at_1
-#define Z80_IYL(self) (self).iy.uint8_values.at_0
-#define Z80_A(self) (self).af.uint8_values.at_1
-#define Z80_F(self) (self).af.uint8_values.at_0
-#define Z80_B(self) (self).bc.uint8_values.at_1
-#define Z80_C(self) (self).bc.uint8_values.at_0
-#define Z80_D(self) (self).de.uint8_values.at_1
-#define Z80_E(self) (self).de.uint8_values.at_0
-#define Z80_H(self) (self).hl.uint8_values.at_1
-#define Z80_L(self) (self).hl.uint8_values.at_0
-#define Z80_A_(self) (self).af_.uint8_values.at_1
-#define Z80_F_(self) (self).af_.uint8_values.at_0
-#define Z80_B_(self) (self).bc_.uint8_values.at_1
-#define Z80_C_(self) (self).bc_.uint8_values.at_0
-#define Z80_D_(self) (self).de_.uint8_values.at_1
-#define Z80_E_(self) (self).de_.uint8_values.at_0
-#define Z80_H_(self) (self).hl_.uint8_values.at_1
-#define Z80_L_(self) (self).hl_.uint8_values.at_0
-
#define Z80_SF 128
#define Z80_ZF 64
#define Z80_YF 32
@@ -495,29 +369,55 @@ typedef struct {
#define Z80_NF 2
#define Z80_CF 1
-#define Z80_OPTION_LD_A_IR_BUG 1
-#define Z80_OPTION_OUT_VC_255 2
-#define Z80_OPTION_XQ 8
-#define Z80_OPTION_HALT_SKIP 16
-#define Z80_OPTION_YQ 32
+/** @brief @ref Z80 option that enables the HALTskip optimization. */
+
+#define Z80_OPTION_HALT_SKIP 16
+
+/** @brief @ref Z80 option 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 the ld a,{i|r} instructions. */
+
+#define Z80_OPTION_LD_A_IR_BUG 1
+
+/** @brief @ref Z80 option that enables emulation of the out (c),255
+ * instruction, specific to the Zilog Z80 CMOS. */
+
+#define Z80_OPTION_OUT_VC_255 2
+
+/** @brief @ref Z80 option that enables the XQ factor in the emulation of the
+ * ccf/scf instructions. */
+
+#define Z80_OPTION_XQ 8
+
+/** @brief @ref Z80 option that enables the YQ factor in the emulation of the
+ * ccf/scf instructions. */
+
+#define Z80_OPTION_YQ 32
+
+/** @brief @ref Z80 option that enables all the options required to fully
+ * emulate a Zilog NMOS CPU. */
-/** @brief Zilog Z80 NMOS emulation. */
#define Z80_MODEL_ZILOG_NMOS \
(Z80_OPTION_LD_A_IR_BUG | Z80_OPTION_XQ | Z80_OPTION_YQ)
-/** @brief Zilog Z80 CMOS emulation. */
+/** @brief @ref Z80 option that enables all the options required to fully
+ * emulate a Zilog CMOS CPU. */
+
#define Z80_MODEL_ZILOG_CMOS \
(Z80_OPTION_OUT_VC_255 | Z80_OPTION_XQ | Z80_OPTION_YQ)
-/** @brief NEC NMOS emulation. */
+/** @brief @ref Z80 option that enables all the options required to fully
+ * emulate a NEC NMOS CPU. */
+
#define Z80_MODEL_NEC_NMOS \
Z80_OPTION_LD_A_IR_BUG
-/** @brief SGS-Thomson NMOS emulation. */
+/** @brief @ref Z80 option that enables all the options required to fully
+ * emulate a SGS-Thomson CMOS CPU. */
+
#define Z80_MODEL_ST_CMOS \
(Z80_OPTION_LD_A_IR_BUG | Z80_OPTION_YQ)
-
#define Z80_REQUEST_RESET 3
#define Z80_REQUEST_REJECT_NMI 4
#define Z80_REQUEST_NMI 8 /**< NMI pending. */
@@ -537,9 +437,180 @@ typedef struct {
#define Z80_RESUME_SPECIAL_RESET_XY 5
#define Z80_RESUME_SPECIAL_RESET_NOP 6
+
+/** @brief Accesses the MEMPTR register of a @ref Z80 @c object. */
+
+#define Z80_MEMPTR(object) (object).memptr.uint16_value
+
+/** @brief Accesses the PC register of a @ref Z80 @c object. */
+
+#define Z80_PC(object) (object).pc.uint16_value
+
+/** @brief Accesses the SP register of a @ref Z80 @c object. */
+
+#define Z80_SP(object) (object).sp.uint16_value
+
+/** @brief Accesses the temporary IX/IY register of a @ref Z80 @c object */
+
+#define Z80_XY(object) (object).xy.uint16_value
+
+/** @brief Accesses the IX register of a @ref Z80 @c object. */
+
+#define Z80_IX(object) (object).ix.uint16_value
+
+/** @brief Accesses the IY register of a @ref Z80 @c object. */
+
+#define Z80_IY(object) (object).iy.uint16_value
+
+/** @brief Accesses the AF register of a @ref Z80 @c object. */
+
+#define Z80_AF(object) (object).af.uint16_value
+
+/** @brief Accesses the BC register of a @ref Z80 @c object. */
+
+#define Z80_BC(object) (object).bc.uint16_value
+
+/** @brief Accesses the DE register of a @ref Z80 @c object. */
+
+#define Z80_DE(object) (object).de.uint16_value
+
+/** @brief Accesses the HL register of a @ref Z80 @c object. */
+
+#define Z80_HL(object) (object).hl.uint16_value
+
+/** @brief Accesses the AF' register of a @ref Z80 @c object. */
+
+#define Z80_AF_(object) (object).af_.uint16_value
+
+/** @brief Accesses the BC' register of a @ref Z80 @c object. */
+
+#define Z80_BC_(object) (object).bc_.uint16_value
+
+/** @brief Accesses the DE' register of a @ref Z80 @c object. */
+
+#define Z80_DE_(object) (object).de_.uint16_value
+
+/** @brief Accesses the HL' register of a @ref Z80 @c object. */
+
+#define Z80_HL_(object) (object).hl_.uint16_value
+
+/** @brief Accesses the high byte of the MEMPTR register of a @ref Z80
+ * @c object. */
+
+#define Z80_MEMPTRH(object) (object).memptr.uint8_values.at_1
+
+/** @brief Accesses the low byte of the MEMPTR register of a @ref Z80
+ * @c object. */
+
+#define Z80_MEMPTRL(object) (object).memptr.uint8_values.at_0
+
+/** @brief Accesses the high byte of the PC register of a @ref Z80 @c object. */
+
+#define Z80_PCH(object) (object).pc.uint8_values.at_1
+
+/** @brief Accesses the low byte of the PC register of a @ref Z80 @c object. */
+
+#define Z80_PCL(object) (object).pc.uint8_values.at_0
+
+/** @brief Accesses the high byte of the SP register of a @ref Z80 @c object. */
+
+#define Z80_SPH(object) (object).sp.uint8_values.at_1
+
+/** @brief Accesses the low byte of the SP register of a @ref Z80 @c object. */
+
+#define Z80_SPL(object) (object).sp.uint8_values.at_0
+
+/** @brief Accesses the temporary IXH/IYH register of a @ref Z80 @c object. */
+
+#define Z80_XYH(object) (object).xy.uint8_values.at_1
+
+/** @brief Accesses the temporary IXL/IYL register of a @ref Z80 @c object. */
+
+#define Z80_XYL(object) (object).xy.uint8_values.at_0
+
+/** @brief Accesses the IXH register of a @ref Z80 @c object. */
+
+#define Z80_IXH(object) (object).ix.uint8_values.at_1
+
+/** @brief Accesses the IXL register of a @ref Z80 @c object. */
+
+#define Z80_IXL(object) (object).ix.uint8_values.at_0
+
+/** @brief Accesses the IYH register of a @ref Z80 @c object. */
+
+#define Z80_IYH(object) (object).iy.uint8_values.at_1
+
+/** @brief Accesses the IYL register of a @ref Z80 @c object. */
+
+#define Z80_IYL(object) (object).iy.uint8_values.at_0
+
+/** @brief Accesses the A register of a @ref Z80 @c object. */
+
+#define Z80_A(object) (object).af.uint8_values.at_1
+
+/** @brief Accesses the F register of a @ref Z80 @c object. */
+
+#define Z80_F(object) (object).af.uint8_values.at_0
+
+/** @brief Accesses the B register of a @ref Z80 @c object. */
+
+#define Z80_B(object) (object).bc.uint8_values.at_1
+
+/** @brief Accesses the C register of a @ref Z80 @c object. */
+
+#define Z80_C(object) (object).bc.uint8_values.at_0
+
+/** @brief Accesses the D register of a @ref Z80 @c object. */
+
+#define Z80_D(object) (object).de.uint8_values.at_1
+
+/** @brief Accesses the E register of a @ref Z80 @c object. */
+
+#define Z80_E(object) (object).de.uint8_values.at_0
+
+/** @brief Accesses the H register of a @ref Z80 @c object. */
+
+#define Z80_H(object) (object).hl.uint8_values.at_1
+
+/** @brief Accesses the L register of a @ref Z80 @c object. */
+
+#define Z80_L(object) (object).hl.uint8_values.at_0
+
+/** @brief Accesses the A' register of a @ref Z80 @c object. */
+
+#define Z80_A_(object) (object).af_.uint8_values.at_1
+
+/** @brief Accesses the F' register of a @ref Z80 @c object. */
+
+#define Z80_F_(object) (object).af_.uint8_values.at_0
+
+/** @brief Accesses the B' register of a @ref Z80 @c object. */
+
+#define Z80_B_(object) (object).bc_.uint8_values.at_1
+
+/** @brief Accesses the C' register of a @ref Z80 @c object. */
+
+#define Z80_C_(object) (object).bc_.uint8_values.at_0
+
+/** @brief Accesses the D' register of a @ref Z80 @c object. */
+
+#define Z80_D_(object) (object).de_.uint8_values.at_1
+
+/** @brief Accesses the E' register of a @ref Z80 @c object. */
+
+#define Z80_E_(object) (object).de_.uint8_values.at_0
+
+/** @brief Accesses the H' register of a @ref Z80 @c object. */
+
+#define Z80_H_(object) (object).hl_.uint8_values.at_1
+
+/** @brief Accesses the L' register of a @ref Z80 @c object. */
+
+#define Z80_L_(object) (object).hl_.uint8_values.at_0
+
Z_EXTERN_C_BEGIN
-/** @brief Sets the power state of a Z80 emulator.
+/** @brief Sets the power state of a @ref Z80 object.
*
* @param self Pointer to the object on which the function is called.
* @param state
@@ -554,7 +625,7 @@ Z80_API void z80_power(Z80 *self, zboolean state);
Z80_API void z80_instant_reset(Z80 *self);
-/** @brief Sends a normal RESET signal to a Z80 emulator.
+/** @brief Sends a normal RESET signal to a @ref Z80 object.
*
* @details todo
*
@@ -574,16 +645,16 @@ Z80_API void z80_reset(Z80 *self);
Z80_API void z80_special_reset(Z80 *self);
-/** @brief Sets the state of the INT line of a Z80 emulator.
+/** @brief Sets the state of the INT line of a @ref Z80 object.
*
* @param self Pointer to the object on which the function is called.
* @param state
- * @c TRUE = ON (line low);
- * @c FALSE = OFF (line high). */
+ * @c TRUE = set line low;
+ * @c FALSE = set line high. */
Z80_API void z80_int(Z80 *self, zboolean state);
-/** @brief Sends a NMI signal to a Z80 emulator.
+/** @brief Triggers the NMI line of a @ref Z80 object.
*
* @param self Pointer to the object on which the function is called. */
diff --git a/HISTORY b/HISTORY
index 351f6c9..0054ed6 100644
--- a/HISTORY
+++ b/HISTORY
@@ -54,44 +54,46 @@ Changes:
34. Added optional emulation of the normal and special RESET signals, along with
the new z80_reset and z80_special_reset functions to emit them. The old
z80_reset function is now called z80_instant_reset.
-35. Added emulation of the NMI acknowledge M-cycle through the new Z80::nmia
+35. Added the Z80::fetch_opcode and Z80::fetch callbacks to perform opcode fetch
+ operations and memory read operations on instruction data respectively.
+36. Added the Z80::nop callback to perform disregarded opcode fetch operations
+ during internal NOP M-cycles.
+37. Added emulation of the NMI acknowledge M-cycle through the new Z80::nmia
callback.
-36. Added emulation of the INT acknowledge M-cycle through the new Z80::inta
+38. Added emulation of the INT acknowledge M-cycle through the new Z80::inta
callback, which replaces Z80::int_data.
-37. Added optional full emulation of the interrupt mode 0, along with the new
+39. Added optional full emulation of the interrupt mode 0, along with the new
Z80::int_fetch callback to perform bus read operations on instruction data.
If not enabled at compile-time, the old simplified emulation is built, which
supports only the most typical instructions.
-38. Added accurate flag behavior in the following instructions: "ldir", "lddr",
+40. Added four callbacks to notify the execution of important instructions:
+ Z80::ld_i_a, Z80::ld_r_a, Z80::reti and Z80::retn.
+41. Added hooking functionality through the "ld h,h" instruction and the new
+ Z80::hook callback.
+42. Added the Z80::illegal callback to delegate the emulation of illegal
+ instructions.
+43. Added accurate flag behavior in the following instructions: "ldir", "lddr",
"cpir", "cpdr", "inir", "indr", "otir" and "otdr".
-39. Added emulation of the interrupt acceptance deferral that occurs during the
+44. Added emulation of the interrupt acceptance deferral that occurs during the
"reti" and "retn" instructions.
-40. Added MEMPTR emulation. The "bit N,(hl)" instruction now produces a correct
+45. Added MEMPTR emulation. The "bit N,(hl)" instruction now produces a correct
value of F.
-41. Added optional emulation of the Q "register". If enabled at compile-time,
+46. Added optional emulation of the Q "register". If enabled at compile-time,
the "ccf" and "scf" instructions produce a correct value of F.
-42. Added emulation options that can be configured at runtime.
-43. Added emulation of the "out (c),255" instruction (Zilog Z80 CMOS).
-44. Added optional emulation of the bug affecting the "ld a,{i|r}" instructions
+47. Added emulation options that can be configured at runtime.
+48. Added emulation of the "out (c),255" instruction (Zilog Z80 CMOS).
+49. Added optional emulation of the bug affecting the "ld a,{i|r}" instructions
(Zilog Z80 NMOS). If enabled at compile-time, the P/V flag is reset when an
INT is accepted during the execution of these instructions.
-45. Added the Z80::fetch_opcode and Z80::fetch callbacks to perform opcode fetch
- operations and memory read operations on instruction data respectively.
-46. Added hooking functionality through the "ld h,h" instruction and the new
- Z80::hook callback.
-47. Added the Z80::nop callback to perform disregarded opcode fetch operations
- during internal NOP M-cycles.
-48. Added four callbacks to notify the execution of important instructions:
- Z80::ld_i_a, Z80::ld_r_a, Z80::reti and Z80::retn.
-49. Removed Z80::state. Replaced with individual members for the registers, the
+50. Removed Z80::state. Replaced with individual members for the registers, the
interrupt enable flip-flops and the interrupt mode.
-50. Removed the superfluous EI flag. The previous opcode is checked instead,
+51. Removed the superfluous EI flag. The previous opcode is checked instead,
which is faster and makes the Z80 object smaller.
-51. Removed all module-related stuff.
-52. Optimizations in flag computation and condition evaluation.
-53. New source code comments and improvements to existing ones.
-54. Improved code aesthetics.
-55. Other improvements, optimizations and minor changes.
+52. Removed all module-related stuff.
+53. Optimizations in flag computation and condition evaluation.
+54. New source code comments and improvements to existing ones.
+55. Improved code aesthetics.
+56. Other improvements, optimizations and minor changes.
Z80 v0.1 (2018-11-10)
diff --git a/documentation/APIReference.rst b/documentation/APIReference.rst
index b838188..940dc7f 100644
--- a/documentation/APIReference.rst
+++ b/documentation/APIReference.rst
@@ -2,53 +2,111 @@
API reference
=============
-Macros
-------
+Library version macros
+----------------------
.. doxygendefine:: Z80_LIBRARY_VERSION_MAJOR
.. doxygendefine:: Z80_LIBRARY_VERSION_MINOR
.. doxygendefine:: Z80_LIBRARY_VERSION_MICRO
.. doxygendefine:: Z80_LIBRARY_VERSION_STRING
-.. doxygendefine:: Z80_CYCLE_LIMIT
-.. doxygendefine:: Z80_HOOK
-.. doxygendefine:: Z80_MODEL_ZILOG_NMOS
-.. doxygendefine:: Z80_MODEL_ZILOG_CMOS
-
-.. doxygendefine:: Z80_REQUEST_SPECIAL_RESET
-.. doxygendefine:: Z80_REQUEST_RESET
-.. doxygendefine:: Z80_REQUEST_NMI
-.. doxygendefine:: Z80_REQUEST_INT
-
-.. doxygendefine:: Z80_RESUME_HALT
-.. doxygendefine:: Z80_RESUME_XY
-.. doxygendefine:: Z80_RESUME_IM0_XY
-
-Callback Types
+Callback types
--------------
.. doxygentypedef:: Z80Read
.. doxygentypedef:: Z80Write
.. doxygentypedef:: Z80HALT
.. doxygentypedef:: Z80Notify
+.. doxygentypedef:: Z80Illegal
+.. doxygentypedef:: Z80Reset
-Objects
--------
+Emulator object
+---------------
.. doxygenstruct:: Z80
- :members:
+ :members:
+
+Emulation options
+-----------------
+
+.. doxygendefine:: Z80_OPTION_HALT_SKIP
+.. doxygendefine:: Z80_OPTION_LD_A_IR_BUG
+.. doxygendefine:: Z80_OPTION_OUT_VC_255
+.. doxygendefine:: Z80_OPTION_XQ
+.. doxygendefine:: Z80_OPTION_YQ
+.. doxygendefine:: Z80_MODEL_ZILOG_NMOS
+.. doxygendefine:: Z80_MODEL_ZILOG_CMOS
+.. doxygendefine:: Z80_MODEL_NEC_NMOS
+.. doxygendefine:: Z80_MODEL_ST_CMOS
+
+Register accessors
+------------------
+
+.. doxygendefine:: Z80_MEMPTR
+.. doxygendefine:: Z80_PC
+.. doxygendefine:: Z80_SP
+.. doxygendefine:: Z80_XY
+.. doxygendefine:: Z80_IX
+.. doxygendefine:: Z80_IY
+.. doxygendefine:: Z80_AF
+.. doxygendefine:: Z80_BC
+.. doxygendefine:: Z80_DE
+.. doxygendefine:: Z80_HL
+.. doxygendefine:: Z80_AF_
+.. doxygendefine:: Z80_BC_
+.. doxygendefine:: Z80_DE_
+.. doxygendefine:: Z80_HL_
+.. doxygendefine:: Z80_MEMPTRH
+.. doxygendefine:: Z80_MEMPTRL
+.. doxygendefine:: Z80_PCH
+.. doxygendefine:: Z80_PCL
+.. doxygendefine:: Z80_SPH
+.. doxygendefine:: Z80_SPL
+.. doxygendefine:: Z80_XYH
+.. doxygendefine:: Z80_XYL
+.. doxygendefine:: Z80_IXH
+.. doxygendefine:: Z80_IXL
+.. doxygendefine:: Z80_IYH
+.. doxygendefine:: Z80_IYL
+.. doxygendefine:: Z80_A
+.. doxygendefine:: Z80_F
+.. doxygendefine:: Z80_B
+.. doxygendefine:: Z80_C
+.. doxygendefine:: Z80_D
+.. doxygendefine:: Z80_E
+.. doxygendefine:: Z80_H
+.. doxygendefine:: Z80_L
+.. doxygendefine:: Z80_A_
+.. doxygendefine:: Z80_F_
+.. doxygendefine:: Z80_B_
+.. doxygendefine:: Z80_C_
+.. doxygendefine:: Z80_D_
+.. doxygendefine:: Z80_E_
+.. doxygendefine:: Z80_H_
+.. doxygendefine:: Z80_L_
+
+Limits
+------
+
+.. doxygendefine:: Z80_CYCLE_LIMIT
+
+Hooking
+-------
+
+.. doxygendefine:: Z80_HOOK
+
Functions
---------
-.. doxygenfunction:: z80_in_offset
+.. doxygenfunction:: z80_in_cycle
.. doxygenfunction:: z80_instant_reset
-.. doxygenfunction:: z80_out_offset
+.. doxygenfunction:: z80_out_cycle
.. doxygenfunction:: z80_execute
.. doxygenfunction:: z80_int
.. doxygenfunction:: z80_nmi
-.. doxygenfunction:: z80_normal_reset
.. doxygenfunction:: z80_power
.. doxygenfunction:: z80_refresh_address
+.. doxygenfunction:: z80_reset
.. doxygenfunction:: z80_run
.. doxygenfunction:: z80_special_reset
diff --git a/documentation/VersionHistory.rst b/documentation/VersionHistory.rst
index bca150a..943e8fd 100644
--- a/documentation/VersionHistory.rst
+++ b/documentation/VersionHistory.rst
@@ -33,7 +33,7 @@ Changes:
22. Fixed the clock cycles of the ``dec XY`` and ``in (c)`` instructions.
23. Fixed the ``read_16`` function so that the order in which the compiler evaluates expressions does not affect the order of the memory read operations.
24. Fixed the order in which the memory write operations are performed when the SP register is involved. This affects the NMI response, the INT response in modes 1 and 2, and the following instructions: ``ex (sp),{hl|XY}``, ``push TT``, ``push XY``, ``call WORD``, ``call Z,WORD`` and ``rst N``.
-25. Fixed the handling of illegal instructions to avoid stack overflows in long sequences of ``DDh`` / ``FDh`` prefixes.
+25. Fixed the handling of illegal instructions to avoid stack overflows in long sequences of ``DDh/FDh`` prefixes.
26. Fixed several implicit conversions to avoid warnings about loss of sign and precision.
27. Fixed some bitwise operations to avoid undefined behavior and arithmetic right shifts on signed integers.
28. Fixed violations of the C standard in several identifiers.
@@ -43,27 +43,28 @@ Changes:
32. Replaced all ``ld {J,K|O,P}`` instructions that have the same destination and source register with NOPs.
33. Reimplemented the HALT state. The emulation should now be fully accurate. HALTskip is also supported.
34. Added optional emulation of the normal and special RESET signals, along with the new ``z80_reset`` and ``z80_special_reset`` functions to emit them. The old ``z80_reset`` function is now called ``z80_instant_reset``.
-35. Added emulation of the NMI acknowledge M-cycle through the new ``Z80::nmia`` callback.
-36. Added emulation of the INT acknowledge M-cycle through the new ``Z80::inta`` callback, which replaces ``Z80::int_data``.
-37. Added optional full emulation of the interrupt mode 0, along with the new ``Z80::int_fetch`` callback to perform bus read operations on instruction data. If not enabled at compile-time, the old simplified emulation is built, which supports only the most typical instructions.
-38. Added accurate flag behavior in the following instructions: ``ldir``, ``lddr``, ``cpir``, ``cpdr``, ``inir``, ``indr``, ``otir`` and ``otdr``.
-39. Added emulation of the interrupt acceptance deferral that occurs during the ``reti`` and ``retn`` instructions.
-40. Added MEMPTR emulation. The ``bit N,(hl)`` instruction now produces a correct value of F.
-41. Added optional emulation of the Q "register". If enabled at compile-time, the ``ccf`` and ``scf`` instructions produce a correct value of F.
-42. Added emulation options that can be configured at runtime.
-43. Added emulation of the ``out (c),255`` instruction (Zilog Z80 CMOS).
-44. Added optional emulation of the bug affecting the ``ld a,{i|r}`` instructions (Zilog Z80 NMOS). If enabled at compile-time, the P/V flag is reset when an INT is accepted during the execution of these instructions.
-45. Added the ``Z80::fetch_opcode`` and ``Z80::fetch`` callbacks to perform opcode fetch operations and memory read operations on instruction data respectively.
-46. Added hooking functionality through the ``ld h,h`` instruction and the new ``Z80::hook`` callback.
-47. Added the ``Z80::nop`` callback to perform disregarded opcode fetch operations during internal NOP M-cycles.
-48. Added four callbacks to notify the execution of important instructions: ``Z80::ld_i_a``, ``Z80::ld_r_a``, ``Z80::reti`` and ``Z80::retn``.
-49. Removed ``Z80::state``. Replaced with individual members for the registers, the interrupt enable flip-flops and the interrupt mode.
-50. Removed the superfluous EI flag. The previous opcode is checked instead, which is faster and makes the ``Z80`` object smaller.
-51. Removed all module-related stuff.
-52. Optimizations in flag computation and condition evaluation.
-53. New source code comments and improvements to existing ones.
-54. Improved code aesthetics.
-55. Other improvements, optimizations and minor changes.
+35. Added the ``Z80::fetch_opcode`` and ``Z80::fetch`` callbacks to perform opcode fetch operations and memory read operations on instruction data respectively.
+36. Added the ``Z80::nop callback`` to perform disregarded opcode fetch operations during internal NOP M-cycles.
+37. Added emulation of the NMI acknowledge M-cycle through the new ``Z80::nmia`` callback.
+38. Added emulation of the INT acknowledge M-cycle through the new ``Z80::inta`` callback, which replaces ``Z80::int_data``.
+39. Added optional full emulation of the interrupt mode 0, along with the new ``Z80::int_fetch`` callback to perform bus read operations on instruction data. If not enabled at compile-time, the old simplified emulation is built, which supports only the most typical instructions.
+40. Added four callbacks to notify the execution of important instructions: ``Z80::ld_i_a``, ``Z80::ld_r_a``, ``Z80::reti`` and ``Z80::retn``.
+41. Added hooking functionality through the ``ld h,h`` instruction and the new ``Z80::hook`` callback.
+42. Added the ``Z80::illegal`` callback to delegate the emulation of illegal instructions.
+43. Added accurate flag behavior in the following instructions: ``ldir``, ``lddr``, ``cpir``, ``cpdr``, ``inir``, ``indr``, ``otir`` and ``otdr``.
+44. Added emulation of the interrupt acceptance deferral that occurs during the ``reti`` and ``retn`` instructions.
+45. Added MEMPTR emulation. The ``bit N,(hl)`` instruction now produces a correct value of F.
+46. Added optional emulation of the Q "register". If enabled at compile-time, the ``ccf`` and ``scf`` instructions produce a correct value of F.
+47. Added emulation options that can be configured at runtime.
+48. Added emulation of the ``out (c),255`` instruction (Zilog Z80 CMOS).
+49. Added optional emulation of the bug affecting the ``ld a,{i|r}`` instructions (Zilog Z80 NMOS). If enabled at compile-time, the P/V flag is reset when an INT is accepted during the execution of these instructions.
+50. Removed ``Z80::state``. Replaced with individual members for the registers, the interrupt enable flip-flops and the interrupt mode.
+51. Removed the superfluous EI flag. The previous opcode is checked instead, which is faster and makes the ``Z80`` object smaller.
+52. Removed all module-related stuff.
+53. Optimizations in flag computation and condition evaluation.
+54. New source code comments and improvements to existing ones.
+55. Improved code aesthetics.
+56. Other improvements, optimizations and minor changes.
v0.1 (2018-11-10)
=================
diff --git a/sources/Z80.c b/sources/Z80.c
index c922696..68b62c6 100644
--- a/sources/Z80.c
+++ b/sources/Z80.c
@@ -1890,6 +1890,7 @@ INSTRUCTION(xy_xy)
INSTRUCTION(ed_illegal)
{
+ if (self->illegal != Z_NULL) return self->illegal(CONTEXT, DATA[0]);
Q_0
PC += 2;
return 8;
@@ -1898,7 +1899,7 @@ INSTRUCTION(ed_illegal)
/*------------------------------------------------------------------------.
| Illegal instructions with DDh or FDh prefix cause the CPU to ignore the |
-| prefix, that is, the byte immediately following the prefix is treated |
+| prefix, i.e., the byte immediately following the prefix is interpreted |
| as the first byte of a new instruction. The prefix consumes 4 T-states. |
'========================================================================*/
@@ -1907,13 +1908,11 @@ INSTRUCTION(xy_illegal)
PC++;
DATA[0] = DATA[1];
- if ((self->cycles += 4) >= self->cycle_limit)
- {
- RESUME = Z80_RESUME_XY;
- return 0;
- }
+ if ((self->cycles += 4) < self->cycle_limit)
+ return instruction_table[DATA[0]](self);
- return instruction_table[DATA[0]](self);
+ RESUME = Z80_RESUME_XY;
+ return 0;
}
diff --git a/sources/test-Z80.c b/sources/test-Z80.c
index 2cb6cc3..5807be1 100644
--- a/sources/test-Z80.c
+++ b/sources/test-Z80.c
@@ -764,6 +764,7 @@ int main(int argc, char **argv)
cpu.ld_r_a =
cpu.reti =
cpu.retn = Z_NULL;
+ cpu.illegal = Z_NULL;
/* Ensure that all specified test numbers are valid. */
for (ii = i; i < argc; i++)