Z80.c
  1  /** Z80: portable Z80 emulator *******************************/
  2  /**                                                         **/
  3  /**                           Z80.c                         **/
  4  /**                                                         **/
  5  /** This file contains implementation for Z80 CPU. Don't    **/
  6  /** forget to provide RdZ80(), WrZ80(), InZ80(), OutZ80(),  **/
  7  /** LoopZ80(), and PatchZ80() functions to accomodate the   **/
  8  /** emulated machine's architecture.                        **/
  9  /**                                                         **/
 10  /** Copyright (C) Marat Fayzullin 1994-2005                 **/
 11  /**     You are not allowed to distribute this software     **/
 12  /**     commercially. Please, notify me, if you make any    **/   
 13  /**     changes to this file.                               **/
 14  /*************************************************************/
 15  #include "shared.h" // For endianess!!!
 16  
 17  #include "Z80.h"
 18  #include "Tables.h"
 19  #include <stdio.h>
 20  
 21  /** INLINE ***************************************************/
 22  /** Different compilers inline C functions differently.     **/
 23  /*************************************************************/
 24  #ifdef __GNUC__
 25  #define INLINE inline
 26  #else
 27  #define INLINE static
 28  #endif
 29  
 30  /** System-Dependent Stuff ***********************************/
 31  /** This is system-dependent code put here to speed things  **/
 32  /** up. It has to stay inlined to be fast.                  **/
 33  /*************************************************************/
 34  #ifdef COLEM
 35  extern byte *Page[];
 36  INLINE byte RdZ80(WORD A) { return(Page[A>>15][A&0x7FFF]); }
 37  #endif
 38  #ifdef MG
 39  extern byte *Page[];
 40  INLINE byte RdZ80(WORD A) { return(Page[A>>13][A&0x1FFF]); }
 41  #endif
 42  #ifdef FMSX
 43  extern byte *RAM[],PSL[],SSLReg;
 44  INLINE byte RdZ80(WORD A)
 45  {
 46    if(A!=0xFFFF) return(RAM[A>>13][A&0x1FFF]);
 47    else return((PSL[3]==3)? ~SSLReg:RAM[7][0x1FFF]);
 48  }
 49  #endif
 50  
 51  #define S(Fl)        R->AF.B.l|=Fl
 52  #define R(Fl)        R->AF.B.l&=~(Fl)
 53  #define FLAGS(Rg,Fl) R->AF.B.l=Fl|ZSTable[Rg]
 54  
 55  #define M_RLC(Rg)      \
 56    R->AF.B.l=Rg>>7;Rg=(Rg<<1)|R->AF.B.l;R->AF.B.l|=PZSTable[Rg]
 57  #define M_RRC(Rg)      \
 58    R->AF.B.l=Rg&0x01;Rg=(Rg>>1)|(R->AF.B.l<<7);R->AF.B.l|=PZSTable[Rg]
 59  #define M_RL(Rg)       \
 60    if(Rg&0x80)          \
 61    {                    \
 62      Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \
 63      R->AF.B.l=PZSTable[Rg]|C_FLAG; \
 64    }                    \
 65    else                 \
 66    {                    \
 67      Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \
 68      R->AF.B.l=PZSTable[Rg];        \
 69    }
 70  #define M_RR(Rg)       \
 71    if(Rg&0x01)          \
 72    {                    \
 73      Rg=(Rg>>1)|(R->AF.B.l<<7);     \
 74      R->AF.B.l=PZSTable[Rg]|C_FLAG; \
 75    }                    \
 76    else                 \
 77    {                    \
 78      Rg=(Rg>>1)|(R->AF.B.l<<7);     \
 79      R->AF.B.l=PZSTable[Rg];        \
 80    }
 81    
 82  #define M_SLA(Rg)      \
 83    R->AF.B.l=Rg>>7;Rg<<=1;R->AF.B.l|=PZSTable[Rg]
 84  #define M_SRA(Rg)      \
 85    R->AF.B.l=Rg&C_FLAG;Rg=(Rg>>1)|(Rg&0x80);R->AF.B.l|=PZSTable[Rg]
 86  
 87  #define M_SLL(Rg)      \
 88    R->AF.B.l=Rg>>7;Rg=(Rg<<1)|0x01;R->AF.B.l|=PZSTable[Rg]
 89  #define M_SRL(Rg)      \
 90    R->AF.B.l=Rg&0x01;Rg>>=1;R->AF.B.l|=PZSTable[Rg]
 91  
 92  #define M_BIT(Bit,Rg)  \
 93    R->AF.B.l=(R->AF.B.l&C_FLAG)|H_FLAG|PZSTable[Rg&(1<<Bit)]
 94  
 95  #define M_SET(Bit,Rg) Rg|=1<<Bit
 96  #define M_RES(Bit,Rg) Rg&=~(1<<Bit)
 97  
 98  #define M_POP(Rg)      \
 99    R->Rg.B.l=RdZ80(R->SP.W++);R->Rg.B.h=RdZ80(R->SP.W++)
100  #define M_PUSH(Rg)     \
101    WrZ80(--R->SP.W,R->Rg.B.h);WrZ80(--R->SP.W,R->Rg.B.l)
102  
103  #define M_CALL         \
104    J.B.l=RdZ80(R->PC.W++);J.B.h=RdZ80(R->PC.W++);         \
105    WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l); \
106    R->PC.W=J.W
107  
108  #define M_JP  J.B.l=RdZ80(R->PC.W++);J.B.h=RdZ80(R->PC.W);R->PC.W=J.W
109  #define M_JR  R->PC.W+=(offset)RdZ80(R->PC.W)+1
110  #define M_RET R->PC.B.l=RdZ80(R->SP.W++);R->PC.B.h=RdZ80(R->SP.W++)
111  
112  #define M_RST(Ad)      \
113    WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l);R->PC.W=Ad
114  
115  #define M_LDWORD(Rg)   \
116    R->Rg.B.l=RdZ80(R->PC.W++);R->Rg.B.h=RdZ80(R->PC.W++)
117  
118  #define M_ADD(Rg)      \
119    J.W=R->AF.B.h+Rg;     \
120    R->AF.B.l=            \
121      (~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \
122      J.B.h|ZSTable[J.B.l]|                        \
123      ((R->AF.B.h^Rg^J.B.l)&H_FLAG);               \
124    R->AF.B.h=J.B.l       
125  
126  #define M_SUB(Rg)      \
127    J.W=R->AF.B.h-Rg;    \
128    R->AF.B.l=           \
129      ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
130      N_FLAG|-J.B.h|ZSTable[J.B.l]|                      \
131      ((R->AF.B.h^Rg^J.B.l)&H_FLAG);                     \
132    R->AF.B.h=J.B.l
133  
134  #define M_ADC(Rg)      \
135    J.W=R->AF.B.h+Rg+(R->AF.B.l&C_FLAG); \
136    R->AF.B.l=                           \
137      (~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \
138      J.B.h|ZSTable[J.B.l]|              \
139      ((R->AF.B.h^Rg^J.B.l)&H_FLAG);     \
140    R->AF.B.h=J.B.l
141  
142  #define M_SBC(Rg)      \
143    J.W=R->AF.B.h-Rg-(R->AF.B.l&C_FLAG); \
144    R->AF.B.l=                           \
145      ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
146      N_FLAG|-J.B.h|ZSTable[J.B.l]|      \
147      ((R->AF.B.h^Rg^J.B.l)&H_FLAG);     \
148    R->AF.B.h=J.B.l
149  
150  #define M_CP(Rg)       \
151    J.W=R->AF.B.h-Rg;    \
152    R->AF.B.l=           \
153      ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
154      N_FLAG|-J.B.h|ZSTable[J.B.l]|                      \
155      ((R->AF.B.h^Rg^J.B.l)&H_FLAG)
156  
157  #define M_AND(Rg) R->AF.B.h&=Rg;R->AF.B.l=H_FLAG|PZSTable[R->AF.B.h]
158  #define M_OR(Rg)  R->AF.B.h|=Rg;R->AF.B.l=PZSTable[R->AF.B.h]
159  #define M_XOR(Rg) R->AF.B.h^=Rg;R->AF.B.l=PZSTable[R->AF.B.h]
160  
161  #define M_IN(Rg)        \
162    Rg=InZ80(R->BC.B.l);  \
163    R->AF.B.l=PZSTable[Rg]|(R->AF.B.l&C_FLAG)
164  
165  #define M_INC(Rg)       \
166    Rg++;                 \
167    R->AF.B.l=            \
168      (R->AF.B.l&C_FLAG)|ZSTable[Rg]|           \
169      (Rg==0x80? V_FLAG:0)|(Rg&0x0F? 0:H_FLAG)
170  
171  #define M_DEC(Rg)       \
172    Rg--;                 \
173    R->AF.B.l=            \
174      N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \
175      (Rg==0x7F? V_FLAG:0)|((Rg&0x0F)==0x0F? H_FLAG:0)
176  
177  #define M_ADDW(Rg1,Rg2) \
178    J.W=(R->Rg1.W+R->Rg2.W)&0xFFFF;                        \
179    R->AF.B.l=                                             \
180      (R->AF.B.l&~(H_FLAG|N_FLAG|C_FLAG))|                 \
181      ((R->Rg1.W^R->Rg2.W^J.W)&0x1000? H_FLAG:0)|          \
182      (((long)R->Rg1.W+(long)R->Rg2.W)&0x10000? C_FLAG:0); \
183    R->Rg1.W=J.W
184  
185  #define M_ADCW(Rg)      \
186    I=R->AF.B.l&C_FLAG;J.W=(R->HL.W+R->Rg.W+I)&0xFFFF;           \
187    R->AF.B.l=                                                   \
188      (((long)R->HL.W+(long)R->Rg.W+(long)I)&0x10000? C_FLAG:0)| \
189      (~(R->HL.W^R->Rg.W)&(R->Rg.W^J.W)&0x8000? V_FLAG:0)|       \
190      ((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)|                  \
191      (J.W? 0:Z_FLAG)|(J.B.h&S_FLAG);                            \
192    R->HL.W=J.W
193     
194  #define M_SBCW(Rg)      \
195    I=R->AF.B.l&C_FLAG;J.W=(R->HL.W-R->Rg.W-I)&0xFFFF;           \
196    R->AF.B.l=                                                   \
197      N_FLAG|                                                    \
198      (((long)R->HL.W-(long)R->Rg.W-(long)I)&0x10000? C_FLAG:0)| \
199      ((R->HL.W^R->Rg.W)&(R->HL.W^J.W)&0x8000? V_FLAG:0)|        \
200      ((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)|                  \
201      (J.W? 0:Z_FLAG)|(J.B.h&S_FLAG);                            \
202    R->HL.W=J.W
203  
204  enum Codes
205  {
206    NOP,LD_BC_WORD,LD_xBC_A,INC_BC,INC_B,DEC_B,LD_B_BYTE,RLCA,
207    EX_AF_AF,ADD_HL_BC,LD_A_xBC,DEC_BC,INC_C,DEC_C,LD_C_BYTE,RRCA,
208    DJNZ,LD_DE_WORD,LD_xDE_A,INC_DE,INC_D,DEC_D,LD_D_BYTE,RLA,
209    JR,ADD_HL_DE,LD_A_xDE,DEC_DE,INC_E,DEC_E,LD_E_BYTE,RRA,
210    JR_NZ,LD_HL_WORD,LD_xWORD_HL,INC_HL,INC_H,DEC_H,LD_H_BYTE,DAA,
211    JR_Z,ADD_HL_HL,LD_HL_xWORD,DEC_HL,INC_L,DEC_L,LD_L_BYTE,CPL,
212    JR_NC,LD_SP_WORD,LD_xWORD_A,INC_SP,INC_xHL,DEC_xHL,LD_xHL_BYTE,SCF,
213    JR_C,ADD_HL_SP,LD_A_xWORD,DEC_SP,INC_A,DEC_A,LD_A_BYTE,CCF,
214    LD_B_B,LD_B_C,LD_B_D,LD_B_E,LD_B_H,LD_B_L,LD_B_xHL,LD_B_A,
215    LD_C_B,LD_C_C,LD_C_D,LD_C_E,LD_C_H,LD_C_L,LD_C_xHL,LD_C_A,
216    LD_D_B,LD_D_C,LD_D_D,LD_D_E,LD_D_H,LD_D_L,LD_D_xHL,LD_D_A,
217    LD_E_B,LD_E_C,LD_E_D,LD_E_E,LD_E_H,LD_E_L,LD_E_xHL,LD_E_A,
218    LD_H_B,LD_H_C,LD_H_D,LD_H_E,LD_H_H,LD_H_L,LD_H_xHL,LD_H_A,
219    LD_L_B,LD_L_C,LD_L_D,LD_L_E,LD_L_H,LD_L_L,LD_L_xHL,LD_L_A,
220    LD_xHL_B,LD_xHL_C,LD_xHL_D,LD_xHL_E,LD_xHL_H,LD_xHL_L,HALT,LD_xHL_A,
221    LD_A_B,LD_A_C,LD_A_D,LD_A_E,LD_A_H,LD_A_L,LD_A_xHL,LD_A_A,
222    ADD_B,ADD_C,ADD_D,ADD_E,ADD_H,ADD_L,ADD_xHL,ADD_A,
223    ADC_B,ADC_C,ADC_D,ADC_E,ADC_H,ADC_L,ADC_xHL,ADC_A,
224    SUB_B,SUB_C,SUB_D,SUB_E,SUB_H,SUB_L,SUB_xHL,SUB_A,
225    SBC_B,SBC_C,SBC_D,SBC_E,SBC_H,SBC_L,SBC_xHL,SBC_A,
226    AND_B,AND_C,AND_D,AND_E,AND_H,AND_L,AND_xHL,AND_A,
227    XOR_B,XOR_C,XOR_D,XOR_E,XOR_H,XOR_L,XOR_xHL,XOR_A,
228    OR_B,OR_C,OR_D,OR_E,OR_H,OR_L,OR_xHL,OR_A,
229    CP_B,CP_C,CP_D,CP_E,CP_H,CP_L,CP_xHL,CP_A,
230    RET_NZ,POP_BC,JP_NZ,JP,CALL_NZ,PUSH_BC,ADD_BYTE,RST00,
231    RET_Z,RET,JP_Z,PFX_CB,CALL_Z,CALL,ADC_BYTE,RST08,
232    RET_NC,POP_DE,JP_NC,OUTA,CALL_NC,PUSH_DE,SUB_BYTE,RST10,
233    RET_C,EXX,JP_C,INA,CALL_C,PFX_DD,SBC_BYTE,RST18,
234    RET_PO,POP_HL,JP_PO,EX_HL_xSP,CALL_PO,PUSH_HL,AND_BYTE,RST20,
235    RET_PE,LD_PC_HL,JP_PE,EX_DE_HL,CALL_PE,PFX_ED,XOR_BYTE,RST28,
236    RET_P,POP_AF,JP_P,DI,CALL_P,PUSH_AF,OR_BYTE,RST30,
237    RET_M,LD_SP_HL,JP_M,EI,CALL_M,PFX_FD,CP_BYTE,RST38
238  };
239  
240  enum CodesCB
241  {
242    RLC_B,RLC_C,RLC_D,RLC_E,RLC_H,RLC_L,RLC_xHL,RLC_A,
243    RRC_B,RRC_C,RRC_D,RRC_E,RRC_H,RRC_L,RRC_xHL,RRC_A,
244    RL_B,RL_C,RL_D,RL_E,RL_H,RL_L,RL_xHL,RL_A,
245    RR_B,RR_C,RR_D,RR_E,RR_H,RR_L,RR_xHL,RR_A,
246    SLA_B,SLA_C,SLA_D,SLA_E,SLA_H,SLA_L,SLA_xHL,SLA_A,
247    SRA_B,SRA_C,SRA_D,SRA_E,SRA_H,SRA_L,SRA_xHL,SRA_A,
248    SLL_B,SLL_C,SLL_D,SLL_E,SLL_H,SLL_L,SLL_xHL,SLL_A,
249    SRL_B,SRL_C,SRL_D,SRL_E,SRL_H,SRL_L,SRL_xHL,SRL_A,
250    BIT0_B,BIT0_C,BIT0_D,BIT0_E,BIT0_H,BIT0_L,BIT0_xHL,BIT0_A,
251    BIT1_B,BIT1_C,BIT1_D,BIT1_E,BIT1_H,BIT1_L,BIT1_xHL,BIT1_A,
252    BIT2_B,BIT2_C,BIT2_D,BIT2_E,BIT2_H,BIT2_L,BIT2_xHL,BIT2_A,
253    BIT3_B,BIT3_C,BIT3_D,BIT3_E,BIT3_H,BIT3_L,BIT3_xHL,BIT3_A,
254    BIT4_B,BIT4_C,BIT4_D,BIT4_E,BIT4_H,BIT4_L,BIT4_xHL,BIT4_A,
255    BIT5_B,BIT5_C,BIT5_D,BIT5_E,BIT5_H,BIT5_L,BIT5_xHL,BIT5_A,
256    BIT6_B,BIT6_C,BIT6_D,BIT6_E,BIT6_H,BIT6_L,BIT6_xHL,BIT6_A,
257    BIT7_B,BIT7_C,BIT7_D,BIT7_E,BIT7_H,BIT7_L,BIT7_xHL,BIT7_A,
258    RES0_B,RES0_C,RES0_D,RES0_E,RES0_H,RES0_L,RES0_xHL,RES0_A,
259    RES1_B,RES1_C,RES1_D,RES1_E,RES1_H,RES1_L,RES1_xHL,RES1_A,
260    RES2_B,RES2_C,RES2_D,RES2_E,RES2_H,RES2_L,RES2_xHL,RES2_A,
261    RES3_B,RES3_C,RES3_D,RES3_E,RES3_H,RES3_L,RES3_xHL,RES3_A,
262    RES4_B,RES4_C,RES4_D,RES4_E,RES4_H,RES4_L,RES4_xHL,RES4_A,
263    RES5_B,RES5_C,RES5_D,RES5_E,RES5_H,RES5_L,RES5_xHL,RES5_A,
264    RES6_B,RES6_C,RES6_D,RES6_E,RES6_H,RES6_L,RES6_xHL,RES6_A,
265    RES7_B,RES7_C,RES7_D,RES7_E,RES7_H,RES7_L,RES7_xHL,RES7_A,  
266    SET0_B,SET0_C,SET0_D,SET0_E,SET0_H,SET0_L,SET0_xHL,SET0_A,
267    SET1_B,SET1_C,SET1_D,SET1_E,SET1_H,SET1_L,SET1_xHL,SET1_A,
268    SET2_B,SET2_C,SET2_D,SET2_E,SET2_H,SET2_L,SET2_xHL,SET2_A,
269    SET3_B,SET3_C,SET3_D,SET3_E,SET3_H,SET3_L,SET3_xHL,SET3_A,
270    SET4_B,SET4_C,SET4_D,SET4_E,SET4_H,SET4_L,SET4_xHL,SET4_A,
271    SET5_B,SET5_C,SET5_D,SET5_E,SET5_H,SET5_L,SET5_xHL,SET5_A,
272    SET6_B,SET6_C,SET6_D,SET6_E,SET6_H,SET6_L,SET6_xHL,SET6_A,
273    SET7_B,SET7_C,SET7_D,SET7_E,SET7_H,SET7_L,SET7_xHL,SET7_A
274  };
275    
276  enum CodesED
277  {
278    DB_00,DB_01,DB_02,DB_03,DB_04,DB_05,DB_06,DB_07,
279    DB_08,DB_09,DB_0A,DB_0B,DB_0C,DB_0D,DB_0E,DB_0F,
280    DB_10,DB_11,DB_12,DB_13,DB_14,DB_15,DB_16,DB_17,
281    DB_18,DB_19,DB_1A,DB_1B,DB_1C,DB_1D,DB_1E,DB_1F,
282    DB_20,DB_21,DB_22,DB_23,DB_24,DB_25,DB_26,DB_27,
283    DB_28,DB_29,DB_2A,DB_2B,DB_2C,DB_2D,DB_2E,DB_2F,
284    DB_30,DB_31,DB_32,DB_33,DB_34,DB_35,DB_36,DB_37,
285    DB_38,DB_39,DB_3A,DB_3B,DB_3C,DB_3D,DB_3E,DB_3F,
286    IN_B_xC,OUT_xC_B,SBC_HL_BC,LD_xWORDe_BC,NEG,RETN,IM_0,LD_I_A,
287    IN_C_xC,OUT_xC_C,ADC_HL_BC,LD_BC_xWORDe,DB_4C,RETI,DB_,LD_R_A,
288    IN_D_xC,OUT_xC_D,SBC_HL_DE,LD_xWORDe_DE,DB_54,DB_55,IM_1,LD_A_I,
289    IN_E_xC,OUT_xC_E,ADC_HL_DE,LD_DE_xWORDe,DB_5C,DB_5D,IM_2,LD_A_R,
290    IN_H_xC,OUT_xC_H,SBC_HL_HL,LD_xWORDe_HL,DB_64,DB_65,DB_66,RRD,
291    IN_L_xC,OUT_xC_L,ADC_HL_HL,LD_HL_xWORDe,DB_6C,DB_6D,DB_6E,RLD,
292    IN_F_xC,DB_71,SBC_HL_SP,LD_xWORDe_SP,DB_74,DB_75,DB_76,DB_77,
293    IN_A_xC,OUT_xC_A,ADC_HL_SP,LD_SP_xWORDe,DB_7C,DB_7D,DB_7E,DB_7F,
294    DB_80,DB_81,DB_82,DB_83,DB_84,DB_85,DB_86,DB_87,
295    DB_88,DB_89,DB_8A,DB_8B,DB_8C,DB_8D,DB_8E,DB_8F,
296    DB_90,DB_91,DB_92,DB_93,DB_94,DB_95,DB_96,DB_97,
297    DB_98,DB_99,DB_9A,DB_9B,DB_9C,DB_9D,DB_9E,DB_9F,
298    LDI,CPI,INI,OUTI,DB_A4,DB_A5,DB_A6,DB_A7,
299    LDD,CPD,IND,OUTD,DB_AC,DB_AD,DB_AE,DB_AF,
300    LDIR,CPIR,INIR,OTIR,DB_B4,DB_B5,DB_B6,DB_B7,
301    LDDR,CPDR,INDR,OTDR,DB_BC,DB_BD,DB_BE,DB_BF,
302    DB_C0,DB_C1,DB_C2,DB_C3,DB_C4,DB_C5,DB_C6,DB_C7,
303    DB_C8,DB_C9,DB_CA,DB_CB,DB_CC,DB_CD,DB_CE,DB_CF,
304    DB_D0,DB_D1,DB_D2,DB_D3,DB_D4,DB_D5,DB_D6,DB_D7,
305    DB_D8,DB_D9,DB_DA,DB_DB,DB_DC,DB_DD,DB_DE,DB_DF,
306    DB_E0,DB_E1,DB_E2,DB_E3,DB_E4,DB_E5,DB_E6,DB_E7,
307    DB_E8,DB_E9,DB_EA,DB_EB,DB_EC,DB_ED,DB_EE,DB_EF,
308    DB_F0,DB_F1,DB_F2,DB_F3,DB_F4,DB_F5,DB_F6,DB_F7,
309    DB_F8,DB_F9,DB_FA,DB_FB,DB_FC,DB_FD,DB_FE,DB_FF
310  };
311  
312  static void CodesCB(register Z80 *R)
313  {
314    register byte I;
315  
316    I=RdZ80(R->PC.W++);
317    R->ICount-=CyclesCB[I];
318    switch(I)
319    {
320  #include "CodesCB.h"
321      default:
322        if(R->TrapBadOps)
323          printf
324          (   
325            "[Z80 %lX] Unrecognized instruction: CB %02X at PC=%04X\n",
326            (long)(R->User),RdZ80(R->PC.W-1),R->PC.W-2
327          );
328    }
329  }
330  
331  static void CodesDDCB(register Z80 *R)
332  {
333    register pair J;
334    register byte I;
335  
336  #define XX IX    
337    J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
338    I=RdZ80(R->PC.W++);
339    R->ICount-=CyclesXXCB[I];
340    switch(I)
341    {
342  #include "CodesXCB.h"
343      default:
344        if(R->TrapBadOps)
345          printf
346          (
347            "[Z80 %lX] Unrecognized instruction: DD CB %02X %02X at PC=%04X\n",
348            (long)(R->User),RdZ80(R->PC.W-2),RdZ80(R->PC.W-1),R->PC.W-4
349          );
350    }
351  #undef XX
352  }
353  
354  static void CodesFDCB(register Z80 *R)
355  {
356    register pair J;
357    register byte I;
358  
359  #define XX IY
360    J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
361    I=RdZ80(R->PC.W++);
362    R->ICount-=CyclesXXCB[I];
363    switch(I)
364    {
365  #include "CodesXCB.h"
366      default:
367        if(R->TrapBadOps)
368          printf
369          (
370            "[Z80 %lX] Unrecognized instruction: FD CB %02X %02X at PC=%04X\n",
371            (long)R->User,RdZ80(R->PC.W-2),RdZ80(R->PC.W-1),R->PC.W-4
372          );
373    }
374  #undef XX
375  }
376  
377  static void CodesED(register Z80 *R)
378  {
379    register byte I;
380    register pair J;
381  
382    I=RdZ80(R->PC.W++);
383    R->ICount-=CyclesED[I];
384    switch(I)
385    {
386  #include "CodesED.h"
387      case PFX_ED:
388        R->PC.W--;break;
389      default:
390        if(R->TrapBadOps)
391          printf
392          (
393            "[Z80 %lX] Unrecognized instruction: ED %02X at PC=%04X\n",
394            (long)R->User,RdZ80(R->PC.W-1),R->PC.W-2
395          );
396    }
397  }
398  
399  static void CodesDD(register Z80 *R)
400  {
401    register byte I;
402    register pair J;
403  
404  #define XX IX
405    I=RdZ80(R->PC.W++);
406    R->ICount-=CyclesXX[I];
407    switch(I)
408    {
409  #include "CodesXX.h"
410      case PFX_FD:
411      case PFX_DD:
412        R->PC.W--;break;
413      case PFX_CB:
414        CodesDDCB(R);break;
415      default:
416        if(R->TrapBadOps)
417          printf
418          (
419            "[Z80 %lX] Unrecognized instruction: DD %02X at PC=%04X\n",
420            (long)R->User,RdZ80(R->PC.W-1),R->PC.W-2
421          );
422    }
423  #undef XX
424  }
425  
426  static void CodesFD(register Z80 *R)
427  {
428    register byte I;
429    register pair J;
430  
431  #define XX IY
432    I=RdZ80(R->PC.W++);
433    R->ICount-=CyclesXX[I];
434    switch(I)
435    {
436  #include "CodesXX.h"
437      case PFX_FD:
438      case PFX_DD:
439        R->PC.W--;break;
440      case PFX_CB:
441        CodesFDCB(R);break;
442      default:
443          printf
444          (
445            "Unrecognized instruction: FD %02X at PC=%04X\n",
446            RdZ80(R->PC.W-1),R->PC.W-2
447          );
448    }
449  #undef XX
450  }
451  
452  /** ResetZ80() ***********************************************/
453  /** This function can be used to reset the register struct  **/
454  /** before starting execution with Z80(). It sets the       **/
455  /** registers to their supposed initial values.             **/
456  /*************************************************************/
457  void ResetZ80(Z80 *R)
458  {
459    R->PC.W     = 0x0000;
460    R->SP.W     = 0xF000;
461    R->AF.W     = 0x0000;
462    R->BC.W     = 0x0000;
463    R->DE.W     = 0x0000;
464    R->HL.W     = 0x0000;
465    R->AF1.W    = 0x0000;
466    R->BC1.W    = 0x0000;
467    R->DE1.W    = 0x0000;
468    R->HL1.W    = 0x0000;
469    R->IX.W     = 0x0000;
470    R->IY.W     = 0x0000;
471    R->I        = 0x00;
472    R->IFF      = 0x00;
473    R->ICount   = R->IPeriod;
474    R->IRequest = INT_NONE;
475  }
476  
477  /** ExecZ80() ************************************************/
478  /** This function will execute a single Z80 opcode. It will **/
479  /** then return next PC, and current register values in R.  **/
480  /*************************************************************/
481  WORD ExecZ80(Z80 *R)
482  {
483    register byte I;
484    register pair J;
485  
486    I=RdZ80(R->PC.W++);
487    R->ICount-=Cycles[I];
488    switch(I)
489    {
490  #include "Codes.h"
491      case PFX_CB: CodesCB(R);break;
492      case PFX_ED: CodesED(R);break;
493      case PFX_FD: CodesFD(R);break;
494      case PFX_DD: CodesDD(R);break;
495    }
496  
497    /* We are done */
498    return(R->PC.W);
499  }
500  
501  /** IntZ80() *************************************************/
502  /** This function will generate interrupt of given vector.  **/
503  /*************************************************************/
504  void IntZ80(Z80 *R,WORD Vector)
505  {
506    if((R->IFF&IFF_1)||(Vector==INT_NMI))
507    {
508      /* If HALTed, take CPU off HALT instruction */
509      if(R->IFF&IFF_HALT) { R->PC.W++;R->IFF&=~IFF_HALT; }
510  
511      /* Save PC on stack */
512      M_PUSH(PC);
513  
514      /* Automatically reset IRequest if needed */
515      if(R->IAutoReset&&(Vector==R->IRequest)) R->IRequest=INT_NONE;
516  
517      /* If it is NMI... */
518      if(Vector==INT_NMI)
519      {
520        /* Copy IFF1 to IFF2 */
521        if(R->IFF&IFF_1) R->IFF|=IFF_2; else R->IFF&=~IFF_2;
522        /* Clear IFF1 */
523        R->IFF&=~(IFF_1|IFF_EI);
524        /* Jump to hardwired NMI vector */
525        R->PC.W=0x0066;
526        /* Done */
527        return;
528      }
529  
530      /* Further interrupts off */
531      R->IFF&=~(IFF_1|IFF_2|IFF_EI);
532  
533      /* If in IM2 mode... */
534      if(R->IFF&IFF_IM2)
535      {
536        /* Make up the vector address */
537        Vector=(Vector&0xFF)|((WORD)(R->I)<<8);
538        /* Read the vector */
539        R->PC.B.l=RdZ80(Vector++);
540        R->PC.B.h=RdZ80(Vector);
541        /* Done */
542        return;
543      }
544  
545      /* If in IM1 mode, just jump to hardwired IRQ vector */
546      if(R->IFF&IFF_IM1) { R->PC.W=0x0038;return; }
547  
548      /* If in IM0 mode... */
549  
550      /* Jump to a vector */
551      switch(Vector)
552      {
553        case INT_RST00: R->PC.W=0x0000;break;
554        case INT_RST08: R->PC.W=0x0008;break;
555        case INT_RST10: R->PC.W=0x0010;break;
556        case INT_RST18: R->PC.W=0x0018;break;
557        case INT_RST20: R->PC.W=0x0020;break;
558        case INT_RST28: R->PC.W=0x0028;break;
559        case INT_RST30: R->PC.W=0x0030;break;
560        case INT_RST38: R->PC.W=0x0038;break;
561      }
562    }
563  }
564  
565  /** RunZ80() *************************************************/
566  /** This function will run Z80 code until an LoopZ80() call **/
567  /** returns INT_QUIT. It will return the PC at which        **/
568  /** emulation stopped, and current register values in R.    **/
569  /*************************************************************/
570  WORD RunZ80(Z80 *R)
571  {
572    register byte I;
573    register pair J;
574    int ras=0;
575   
576    for(;;)
577    {
578  #ifdef DEBUG
579      /* Turn tracing on when reached trap address */
580      if(R->PC.W==R->Trap) R->Trace=1;
581      /* Call single-step debugger, exit if requested */
582      if(R->Trace)
583        if(!DebugZ80(R)) return(R->PC.W);
584  #endif
585  
586      I=RdZ80(R->PC.W++);
587      R->ICount-=Cycles[I];
588      switch(I)
589      {
590  #include "Codes.h"
591        case PFX_CB: CodesCB(R);break;
592        case PFX_ED: CodesED(R);break;
593        case PFX_FD: CodesFD(R);break;
594        case PFX_DD: CodesDD(R);break;
595      }
596   
597      /* If cycle counter expired... */
598      if(R->ICount<=0)
599      {
600        /* If we have come after EI, get address from IRequest */
601        /* Otherwise, get it from the loop handler             */
602        if(R->IFF&IFF_EI)
603        {
604          R->IFF=(R->IFF&~IFF_EI)|IFF_1; /* Done with AfterEI state */
605          R->ICount+=R->IBackup-1;       /* Restore the ICount      */
606  
607          /* Call periodic handler or set pending IRQ */
608          if(R->ICount>0) J.W=R->IRequest;
609          else
610          {
611            J.W=LoopZ80(R, &ras);        /* Call periodic handler    */
612            R->ICount+=R->IPeriod; /* Reset the cycle counter  */
613            if(J.W==INT_NONE) J.W=R->IRequest;  /* Pending IRQ */
614          }
615        }
616        else
617        {
618          J.W=LoopZ80(R, &ras);          /* Call periodic handler    */
619          R->ICount+=R->IPeriod;   /* Reset the cycle counter  */
620          if(J.W==INT_NONE) J.W=R->IRequest;    /* Pending IRQ */
621        }
622  
623        if(J.W==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT */
624        if(J.W!=INT_NONE) IntZ80(R,J.W);   /* Int-pt if needed */
625      }
626      if (ras == 1) break;
627    }
628  
629    /* Execution stopped */
630    return(R->PC.W);
631  }