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 }