1 
2 /*
3 
4    z80opc.h
5 
6    This file contains the full collection of
7    opcodes, which will be directly included
8    into z80.c.
9 
10 */
11 
12 /*     -----  Z80 macros -----       */
13 /* these are the real gb-z80-opcodes */
14 
15 #ifndef Z80OPC_INCLUDED
16 #define Z80OPC_INCLUDED
17 
18 /*
19   This might help to save memory on some machines.
20  */
21 #ifndef Z80OPC_GAMEBOYC_SKIP
22 
23 #define M_INCB(reg) { Z80_REG.B.F&=FLAG_C; \
24                     Z80_REG.B.F|=++reg == 0 ? FLAG_Z : 0; \
25                     Z80_REG.B.F|=(reg & 0x0F) == 0 ? FLAG_H :0; }
26 
27 #define M_DECB(reg) { Z80_REG.B.F&=FLAG_C; \
28                     Z80_REG.B.F|=--reg == 0 ? FLAG_Z|FLAG_N : FLAG_N; \
29                     Z80_REG.B.F|=(reg & 0x0F) == 0x0F ? 0 : FLAG_H; }
30 
31 #define M_RLCA       { Z80_REG.B.F=(Z80_REG.B.A & 0x80) >> 3; \
32 		     Z80_REG.B.A=(Z80_REG.B.A<<1)|(Z80_REG.B.A>>7); }
33 
34 #define M_RRCA       { Z80_REG.B.F=(Z80_REG.B.A & 0x01) << 4; \
35 		     Z80_REG.B.A=(Z80_REG.B.A>>1)|(Z80_REG.B.A<<7); }
36 
37 #define M_RLA        { Z80_REG.B.F|=Z80_REG.B.A>>7; \
38                      Z80_REG.B.A<<=1; \
39                      Z80_REG.B.A|=(Z80_REG.B.F & FLAG_C)>>4; \
40                      Z80_REG.B.F=(Z80_REG.B.F & 0x01)<<4; }
41 
42 #define M_RRA        { Z80_REG.B.F|=Z80_REG.B.A & 0x01; \
43                      Z80_REG.B.A>>=1; \
44                      Z80_REG.B.A|=(Z80_REG.B.F & FLAG_C)<<3; \
45                      Z80_REG.B.F=(Z80_REG.B.F & 0x01)<<4; }
46 
47 #define M_ADDHL(wreg) { Z80_REG.B.F&=FLAG_Z|FLAG_N|FLAG_H; \
48                       Z80_REG.B.F|=(((ulong)Z80_REG.W.HL+(ulong)wreg) \
49                                   &0x10000)>>12; \
50                       Z80_REG.W.HL=Z80_REG.W.HL+wreg; }
51 
52 #define M_JR          { Z80_REG.W.PC+=1+(signed char)GetByteAt(Z80_REG.W.PC);\
53                       Z80_TICKS+=Z80CLKS_JR[DBLSPEED]; }
54 
55 #define M_DAA         { if ((Z80_REG.B.F & FLAG_N)==0) { \
56                         if (((Z80_REG.B.A & 0x0F)>9)|| \
57 			    ((Z80_REG.B.F & FLAG_H)>0)) { \
58 			  Z80_REG.B.A+=6; \
59 			  Z80_REG.B.F|=(Z80_REG.B.A & 0xF0)==0 ? \
60 			    FLAG_C|FLAG_H : FLAG_H; \
61 			 } \
62                         if (((Z80_REG.B.A & 0xF0)>0x90)|| \
63 			    ((Z80_REG.B.F & FLAG_C)>0)) { \
64 			  Z80_REG.B.A+=0x60; \
65 			  Z80_REG.B.F|=FLAG_C; \
66 			 } \
67 	                } else { \
68 			   if (((Z80_REG.B.A & 0x0F)>9)|| \
69 			       ((Z80_REG.B.F & FLAG_H)>0)) { \
70 			     Z80_REG.B.A-=6; \
71 			     Z80_REG.B.F|=(Z80_REG.B.A & 0xF0)==0xF0 ? \
72 			       FLAG_C|FLAG_H : FLAG_H; \
73 			 } \
74 			   if (((Z80_REG.B.A & 0xF0)>0x90)|| \
75 			       ((Z80_REG.B.F & FLAG_C)>0)) { \
76 			     Z80_REG.B.A-=0x60; \
77 			     Z80_REG.B.F|=FLAG_C; \
78 			   } \
79 			 } \
80                          Z80_REG.B.F= Z80_REG.B.A==0 ? Z80_REG.B.F | FLAG_Z : \
81                                            Z80_REG.B.F & (0xFF-FLAG_Z); \
82                       }
83 
84 #define M_ADD(reg)    { Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)+(reg & 0x0F)) \
85                                     & 0x10) << 1)| \
86                                     ((((uint)Z80_REG.B.A+ \
87                                      (uint)reg)& 0x100) >> 4)| \
88                                     ((Z80_REG.B.A=(Z80_REG.B.A+reg))==0 ? \
89                                      FLAG_Z : 0); \
90                       }
91 
92 #define M_ADC(reg)    { DUMMY_F=(Z80_REG.B.F & FLAG_C)>0 ? 1 :0; \
93                         Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)+(reg & 0x0F) \
94 				     +DUMMY_F) & 0x10) << 1)| \
95                                     ((((uint)Z80_REG.B.A+ \
96                                      (uint)reg+(uint)DUMMY_F)&0x100)>> 4)| \
97                                     ((Z80_REG.B.A=(Z80_REG.B.A+reg+DUMMY_F)) \
98 				     ==0 ? FLAG_Z : 0); \
99                       }
100 
101 #define M_SUB(reg)    { Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)-(reg & 0x0F)) \
102                                     & 0x10) << 1)| \
103                                     ((((uint)Z80_REG.B.A- \
104                                      (uint)reg)& 0x100) >> 4)| \
105                                     ((Z80_REG.B.A=(Z80_REG.B.A-reg))==0 ? \
106                                      FLAG_Z|FLAG_N : FLAG_N); }
107 
108 #define M_SBC(reg)    { DUMMY_F=(Z80_REG.B.F & FLAG_C)>0 ? 1 :0; \
109                         Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)-(reg & 0x0F) \
110 				     -DUMMY_F) & 0x10) << 1)| \
111                                     ((((uint)Z80_REG.B.A- \
112                                      (uint)reg-(uint)DUMMY_F)&0x100)>> 4)| \
113                                     ((Z80_REG.B.A=(Z80_REG.B.A-reg-DUMMY_F)) \
114 				     ==0 ? FLAG_Z|FLAG_N : FLAG_N); }
115 
116 #define M_AND(reg)    { Z80_REG.B.F=((Z80_REG.B.A=(Z80_REG.B.A & reg))==0) ? \
117                         FLAG_H | FLAG_Z : FLAG_H; }
118 
119 #define M_XOR(reg)    { Z80_REG.B.F=((Z80_REG.B.A=(Z80_REG.B.A ^ reg))==0) ? \
120                         FLAG_Z : 0; }
121 
122 #define M_OR(reg)     { Z80_REG.B.F=((Z80_REG.B.A=(Z80_REG.B.A | reg))==0) ? \
123                         FLAG_Z : 0; }
124 
125 #define M_CP(reg)     { Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)-(reg & 0x0F)) \
126                                     & 0x10) << 1)| \
127                                     ((((uint)Z80_REG.B.A- \
128                                      (uint)reg)& 0x100) >> 4)| \
129                                     (Z80_REG.B.A==reg ?  \
130 				     FLAG_Z|FLAG_N : FLAG_N); }
131 
132 #define M_RET        { Z80_REG.W.PC=GetWordAt(Z80_REG.W.SP); \
133                        Z80_REG.W.SP+=2; \
134                        Z80_TICKS+=Z80CLKS_RET[DBLSPEED]; }
135 
136 #define M_POPW(wreg) { wreg=GetWordAt(Z80_REG.W.SP); \
137                        Z80_REG.W.SP+=2; }
138 
139 #define M_JP         { Z80_REG.W.PC=GetWordAt(Z80_REG.W.PC); \
140                        Z80_TICKS+=Z80CLKS_JP[DBLSPEED]; }
141 
142 #define M_CALL       { Z80_REG.W.SP-=2; \
143                        SetWordAt(Z80_REG.W.SP,Z80_REG.W.PC+2); \
144                        Z80_REG.W.PC=GetWordAt(Z80_REG.W.PC); \
145                        Z80_TICKS+=Z80CLKS_CALL[DBLSPEED]; }
146 
147 #define M_PUSHW(wreg) { Z80_REG.W.SP-=2; \
148                         SetWordAt(Z80_REG.W.SP,wreg); }
149 
150 #endif /* Z80OPC_GAMEBOYC_SKIP */
151 
152 #define M_RST(addr) { Z80_REG.W.SP-=2; \
153                       SetWordAt(Z80_REG.W.SP,Z80_REG.W.PC); \
154                       Z80_REG.W.PC=addr; }
155 
156 #ifndef Z80OPC_GAMEBOYC_SKIP
157 
158 #define M_ADDSPN    { DUMMY_F=GetByteAt(Z80_REG.W.PC++); \
159                       if ((DUMMY_F & 0x80)==0) { \
160                       Z80_REG.B.F=((((Z80_REG.W.SP & 0x0F)+(DUMMY_F & 0x0F)) \
161                                     & 0x10) << 1)| \
162                                     ((((ulong)Z80_REG.W.SP+ \
163                                      (ulong)DUMMY_F)& 0x10000) >> 12); \
164                       Z80_REG.W.SP=Z80_REG.W.SP+DUMMY_F; \
165         	      } else { \
166                       Z80_REG.B.F=((((Z80_REG.W.SP & 0x0F)- \
167                                    ((signed char)DUMMY_F & 0x0F)) \
168                                     & 0x10) << 1)| \
169                                     ((((ulong)Z80_REG.W.SP+ \
170                                      (signed char)DUMMY_F) \
171                                     & 0x10000) >> 12); \
172                       Z80_REG.W.SP=Z80_REG.W.SP+(signed char)DUMMY_F; \
173 		      } \
174                     }
175 
176 #define M_LDHLSPN   { DUMMY_F=GetByteAt(Z80_REG.W.PC++); \
177                       if ((DUMMY_F & 0x80)==0) { \
178                       Z80_REG.B.F=((((Z80_REG.W.SP & 0x0F)+(DUMMY_F & 0x0F)) \
179                                     & 0x10) << 1)| \
180                                     ((((Z80_REG.W.SP & 0xFF)+ \
181                                      (uint)DUMMY_F)& 0x100) >> 4); \
182                       Z80_REG.W.HL=Z80_REG.W.SP+DUMMY_F; \
183         	      } else { \
184                       Z80_REG.B.F=((((Z80_REG.W.SP & 0x0F)- \
185                                    ((signed char)DUMMY_F & 0x0F)) \
186                                     & 0x10) << 1)| \
187                                     ((((Z80_REG.W.SP & 0xFF)+ \
188                                      (signed char)DUMMY_F) \
189                                     & 0x100) >> 4); \
190                       Z80_REG.W.HL=Z80_REG.W.SP+(signed char)DUMMY_F; \
191 		      } \
192                     }
193 
194 
195 /* ----- Z80 macros with CB prefix -----
196    NOTE: RLCA != RLC A etc. !!!
197    DON'T USE DUMMY_F HERE !!              */
198 
199 #define M_CBRLC(reg) { Z80_REG.B.F=(reg & 0x80) >> 3; \
200                      Z80_REG.B.F|=(reg=((reg << 1)|(reg >> 7)))==0 \
201                                   ? FLAG_Z : 0; }
202 
203 #define M_CBRRC(reg) { Z80_REG.B.F=(reg & 0x01) << 4; \
204                      Z80_REG.B.F|=(reg=((reg >> 1)|(reg << 7)))==0 \
205                                   ? FLAG_Z : 0; }
206 
207 #define M_CBRL(reg) { Z80_REG.B.F|=reg >> 7; \
208                       reg<<=1;reg|=(Z80_REG.B.F & FLAG_C)>>4; \
209                       Z80_REG.B.F=(reg==0 ? FLAG_Z : 0)| \
210                                   (Z80_REG.B.F & 0x01)<<4; }
211 
212 #define M_CBRR(reg) { Z80_REG.B.F|=reg & 0x01; \
213                       reg>>=1;reg|=(Z80_REG.B.F & FLAG_C)<<3; \
214                       Z80_REG.B.F=(reg==0 ? FLAG_Z : 0)| \
215                                   (Z80_REG.B.F & 0x01)<<4; }
216 
217 #define M_CBSLA(reg) { Z80_REG.B.F=(reg & 0x80) >> 3; \
218                        Z80_REG.B.F|=(reg=(reg << 1))==0 \
219                                     ? FLAG_Z : 0; }
220 
221 #define M_CBSRA(reg) { Z80_REG.B.F=(reg & 0x01) << 4; \
222                        Z80_REG.B.F|=(reg=((reg >> 1)|(reg & 0x80)))==0 \
223                                     ? FLAG_Z : 0; }
224 
225 #define M_CBSWAP(reg)  { Z80_REG.B.F=(reg=((reg >> 4)|(reg << 4)))==0 ? \
226                                    FLAG_Z : 0; \
227                        }
228 
229 #define M_CBSRL(reg) { Z80_REG.B.F=(reg & 0x01) << 4; \
230                        Z80_REG.B.F|=(reg=(reg >> 1))==0 \
231                                     ? FLAG_Z : 0; }
232 
233 #define M_CBBIT(n,reg) { Z80_REG.B.F=(Z80_REG.B.F & FLAG_C) | FLAG_H | \
234                                      ((reg >> n)&1 ? 0 : FLAG_Z); }
235 
236 #define M_CBRES(n,reg) { reg&=(1 << n)^0xFF; }
237 #define M_CBSET(n,reg) { reg|=1 << n; }
238 
239 #define M_EXECCB(cmd,reg) \
240                           { \
241                             switch (cmd) { \
242 			    case 0x00:M_CBRLC(reg); break; \
243 			    case 0x01:M_CBRRC(reg); break; \
244 			    case 0x02:M_CBRL(reg);  break; \
245 			    case 0x03:M_CBRR(reg);  break; \
246 			    case 0x04:M_CBSLA(reg); break; \
247 			    case 0x05:M_CBSRA(reg); break; \
248 			    case 0x06:M_CBSWAP(reg);break; \
249 			    case 0x07:M_CBSRL(reg); break; \
250                             case 0x08:                     \
251                             case 0x09:                     \
252                             case 0x0A:                     \
253                             case 0x0B:                     \
254                             case 0x0C:                     \
255                             case 0x0D:                     \
256                             case 0x0E:                     \
257                             case 0x0F:                     \
258                               M_CBBIT((cmd & 7),reg);break;\
259                             case 0x10:                     \
260                             case 0x11:                     \
261                             case 0x12:                     \
262                             case 0x13:                     \
263                             case 0x14:                     \
264                             case 0x15:                     \
265                             case 0x16:                     \
266                             case 0x17:                     \
267                               M_CBRES((cmd & 7),reg);break;  \
268                             case 0x18:                     \
269                             case 0x19:                     \
270                             case 0x1A:                     \
271                             case 0x1B:                     \
272                             case 0x1C:                     \
273                             case 0x1D:                     \
274                             case 0x1E:                     \
275                             case 0x1F:                     \
276                               M_CBSET((cmd & 7),reg);break;  \
277 			    } \
278 			  }
279 
280 #define M_PREFIXCB(opc)                                \
281         { \
282 	  switch (opc & 0x07) {                        \
283           case 0:M_EXECCB((opc >> 3),Z80_REG.B.B);break; \
284           case 1:M_EXECCB((opc >> 3),Z80_REG.B.C);break; \
285           case 2:M_EXECCB((opc >> 3),Z80_REG.B.D);break; \
286           case 3:M_EXECCB((opc >> 3),Z80_REG.B.E);break; \
287           case 4:M_EXECCB((opc >> 3),Z80_REG.B.H);break; \
288           case 5:M_EXECCB((opc >> 3),Z80_REG.B.L);break; \
289           case 6:                                        \
290 	    DUMMY_F=GetByteAt(Z80_REG.W.HL);             \
291 	    M_EXECCB((opc >> 3),DUMMY_F);                \
292             if ((opc>>6)!=1)                             \
293 	      SetByteAt(Z80_REG.W.HL,DUMMY_F);           \
294             Z80_TICKS+=Z80CLKS_PREFIXCBINDHL[DBLSPEED];  \
295 	    break;                                       \
296           case 7:M_EXECCB((opc >> 3),Z80_REG.B.A);break; \
297           }                                              \
298           Z80_TICKS+=Z80CLKS_PREFIXCB[DBLSPEED];         \
299 	}
300 
301 #endif /* Z80OPC_GAMEBOYC_SKIP */
302 
303 #endif /* Z80OPC_INCLUDED */
304