/[VRac]/Z80/src/Z80.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /Z80/src/Z80.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26