diff --git a/API/Z80.h b/API/Z80.h index 4249299..547c423 100644 --- a/API/Z80.h +++ b/API/Z80.h @@ -360,16 +360,16 @@ typedef struct { zuint8 halt_line; } Z80; -#define Z80_SF 128 -#define Z80_ZF 64 -#define Z80_YF 32 -#define Z80_HF 16 -#define Z80_XF 8 -#define Z80_PF 4 -#define Z80_NF 2 -#define Z80_CF 1 +#define Z80_SF 128 /**< @brief Bitmask of the @ref Z80 S flag. */ +#define Z80_ZF 64 /**< @brief Bitmask of the @ref Z80 Z flag. */ +#define Z80_YF 32 /**< @brief Bitmask of the @ref Z80 Y flag. */ +#define Z80_HF 16 /**< @brief Bitmask of the @ref Z80 H flag. */ +#define Z80_XF 8 /**< @brief Bitmask of the @ref Z80 X flag. */ +#define Z80_PF 4 /**< @brief Bitmask of the @ref Z80 P/V flag. */ +#define Z80_NF 2 /**< @brief Bitmask of the @ref Z80 N flag. */ +#define Z80_CF 1 /**< @brief Bitmask of the @ref Z80 C flag. */ -/** @brief @ref Z80 option that enables the HALTskip optimization. */ +/** @brief @ref Z80 option that enables HALTskip. */ #define Z80_OPTION_HALT_SKIP 16 @@ -394,50 +394,81 @@ typedef struct { #define Z80_OPTION_YQ 32 -/** @brief @ref Z80 option that enables all the options required to fully - * emulate a Zilog NMOS CPU. */ +/** @brief @ref Z80 meta-option that enables full emulation of the Zilog NMOS + * models. */ #define Z80_MODEL_ZILOG_NMOS \ (Z80_OPTION_LD_A_IR_BUG | Z80_OPTION_XQ | Z80_OPTION_YQ) -/** @brief @ref Z80 option that enables all the options required to fully - * emulate a Zilog CMOS CPU. */ +/** @brief @ref Z80 meta-option that enables full emulation of the Zilog CMOS + * models. */ #define Z80_MODEL_ZILOG_CMOS \ (Z80_OPTION_OUT_VC_255 | Z80_OPTION_XQ | Z80_OPTION_YQ) -/** @brief @ref Z80 option that enables all the options required to fully - * emulate a NEC NMOS CPU. */ +/** @brief @ref Z80 meta-option that enables full emulation of the NEC NMOS + * models. */ #define Z80_MODEL_NEC_NMOS \ Z80_OPTION_LD_A_IR_BUG -/** @brief @ref Z80 option that enables all the options required to fully - * emulate a SGS-Thomson CMOS CPU. */ +/** @brief @ref Z80 meta-option that enables full emulation of the ST CMOS + * models. */ #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. */ -#define Z80_REQUEST_CLEAR_PC 16 -#define Z80_REQUEST_SPECIAL_RESET 32 -#define Z80_REQUEST_INT 64 /**< INT pending. */ -#define Z80_REQUEST_ANY_RESET 35 +/** @brief @ref Z80 request flag anouncing an incoming RESET signal. */ + +#define Z80_REQUEST_RESET 3 + +/** @brief @ref Z80 request flag that prevents NMI signals from being accepted. + * */ + +#define Z80_REQUEST_REJECT_NMI 4 + +/** @brief @ref Z80 request flag anouncing that a non-maskable interrupt signal + * has been detected.*/ + +#define Z80_REQUEST_NMI 8 + +/** @brief @ref Z80 request flag indicating that... */ + +#define Z80_REQUEST_CLEAR_PC 16 + +/** @brief @ref Z80 request flag anouncing an incoming special RESET signal. */ + +#define Z80_REQUEST_SPECIAL_RESET 32 -#define Z80_REQUEST_RESET 3 -#define Z80_REQUEST_INTERRUPT 5 +#define Z80_REQUEST_INT 64 +#define Z80_REQUEST_ANY_RESET 35 + + +#define Z80_REQUEST_RESET 3 + +#define Z80_REQUEST_INTERRUPT 5 + +/** @brief @ref Z80 resume code that is set when the emulator runs out of clock + * cycles during the HALT state. */ + +#define Z80_RESUME_HALT 1 + +/** @brief @ref Z80 resume code that is set when the emulator runs out of clock + * cycles by fetching a prefix sequence or an illegal instruction with @c DDh + * or @c FDh prefix. */ + +#define Z80_RESUME_XY 2 + +/** @brief @ref Z80 resume code that is set when the emulator runs out of clock + * cycles during a maskable interrupt response in mode 0, by fetching a prefix + * sequence or an illegal instruction with @c DDh or @c FDh prefix. */ + +#define Z80_RESUME_IM0_XY 3 -#define Z80_RESUME_HALT 1 /**< Resume the execution of the HALT state. */ -#define Z80_RESUME_XY 2 /**< Resume at opcode decode stage in INT mode 0. */ -#define Z80_RESUME_IM0_XY 3 /**< Resume at opcode decode stage. */ -#define Z80_RESUME_NORMAL_RESET 4 #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 diff --git a/documentation/APIReference.rst b/documentation/APIReference.rst index 940dc7f..d2326cf 100644 --- a/documentation/APIReference.rst +++ b/documentation/APIReference.rst @@ -10,8 +10,8 @@ Library version macros .. doxygendefine:: Z80_LIBRARY_VERSION_MICRO .. doxygendefine:: Z80_LIBRARY_VERSION_STRING -Callback types --------------- +Types +----- .. doxygentypedef:: Z80Read .. doxygentypedef:: Z80Write @@ -19,15 +19,11 @@ Callback types .. doxygentypedef:: Z80Notify .. doxygentypedef:: Z80Illegal .. doxygentypedef:: Z80Reset - -Emulator object ---------------- - .. doxygenstruct:: Z80 :members: -Emulation options ------------------ +Configuration options +--------------------- .. doxygendefine:: Z80_OPTION_HALT_SKIP .. doxygendefine:: Z80_OPTION_LD_A_IR_BUG @@ -39,6 +35,18 @@ Emulation options .. doxygendefine:: Z80_MODEL_NEC_NMOS .. doxygendefine:: Z80_MODEL_ST_CMOS +Flag bitmasks +------------- + +.. doxygendefine:: Z80_SF +.. doxygendefine:: Z80_ZF +.. doxygendefine:: Z80_YF +.. doxygendefine:: Z80_HF +.. doxygendefine:: Z80_XF +.. doxygendefine:: Z80_PF +.. doxygendefine:: Z80_NF +.. doxygendefine:: Z80_CF + Register accessors ------------------ diff --git a/sources/Z80.c b/sources/Z80.c index 19652b2..d9803e9 100644 --- a/sources/Z80.c +++ b/sources/Z80.c @@ -103,8 +103,8 @@ typedef zuint8 (* Instruction)(Z80 *self); /* MARK: - External Macros */ #define REGISTER_OFFSET(member) (zusize)Z_MEMBER_OFFSET(Z80, member) -#define ROL(value) value = (zuint8)Z_UINT8_ROTATE_LEFT( value, 1) -#define ROR(value) value = (zuint8)Z_UINT8_ROTATE_RIGHT(value, 1) +#define ROL(value) value = Z_UINT8_ROTATE_LEFT( value, 1) +#define ROR(value) value = Z_UINT8_ROTATE_RIGHT(value, 1) /* MARK: - Instance Variable and Callback Shortcuts */ @@ -2219,7 +2219,7 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) else if (REQUEST & Z80_REQUEST_NMI) { - DATA[0] = IFF1 = 0; + IFF1 = 0; if (HALT_LINE) { @@ -2237,7 +2237,6 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) R++; /* M1 */ if (self->nmia != Z_NULL) (void)self->nmia(CONTEXT, PC); - Q_0 # ifdef Z80_WITH_SPECIAL_RESET_SIGNAL PC >>= REQUEST & Z80_REQUEST_CLEAR_PC; @@ -2250,6 +2249,8 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) Z80_REQUEST_REJECT_NMI; # endif + DATA[0] = 0; + Q_0 PUSH(PC); MEMPTR = PC = 0x66; self->cycles += 11; @@ -2284,7 +2285,7 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) # endif zuint8 byte; - DATA[0] = IFF1 = IFF2 = 0; + IFF1 = IFF2 = 0; if (HALT_LINE) { @@ -2305,7 +2306,7 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) | is accepted during the execution of "ld a,{i|r}". | '=====================================================*/ # ifdef Z80_WITH_ZILOG_NMOS_LD_A_IR_BUG - else if ( + if ( (OPTIONS & Z80_OPTION_LD_A_IR_BUG) && (self->data.uint16_array[0] & Z_UINT16_BIG_ENDIAN(Z_UINT16(0xFFF7))) == Z_UINT16_BIG_ENDIAN(Z_UINT16(0xED57)) @@ -2409,12 +2410,8 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) R++; - if ((instruction = ed_instruction_table[DATA[1] = byte = INTA]) == ed_illegal) - self->cycles += (self->illegal == Z_NULL) - ? 4 + 8 - : 4 + self->illegal(CONTEXT, byte); - - else { + if ((instruction = ed_instruction_table[DATA[1] = byte = INTA]) != ed_illegal) + { im0.ld_i_a = self->ld_i_a; im0.ld_r_a = self->ld_r_a; im0.reti = self->reti; @@ -2436,6 +2433,10 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) ? 4 /* ld SS,(WORD) / ld (WORD),SS */ : 2 /* all others */; } + + else self->cycles += (self->illegal == Z_NULL) + ? 4 + 8 + : 4 + self->illegal(CONTEXT, byte); } /* instructions with DDh, FDh, DDCBh or FDCBh prefix */ @@ -2542,6 +2543,7 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) | data read from the data bus is disregarded. | '==========================================================*/ case 1: + DATA[0] = 0; Q_0 PUSH(PC); MEMPTR = PC = 0x38; @@ -2570,6 +2572,7 @@ Z80_API zusize z80_run(Z80 *self, zusize cycles) | v0.91 p. 20. | '=====================================================================*/ case 2: + DATA[0] = 0; Q_0 PUSH(PC); MEMPTR = PC = READ_16((zuint16)(((zuint16)I << 8) | byte));