ROLAND  0.70
Amstrad Emulator based on Caprice Source rewritten in C++.
macros.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Fred Klaus *
3  * frednet@web.de *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 #ifndef Z80_MACROS_H
21 #define Z80_MACROS_H
22 
23 //#define z80_wait_states iCycleCount=0;
24 //#define z80_int_handler iCycleCount=iCycleCount;
25 
26 
27 /*
28 #define z80_wait_states \
29 { \
30  vdu.access_video_memory(iCycleCount >> 2); \
31  if (sound.sndEnabled()) { \
32  psg.setCycleCountHigh(psg.cycleCountHigh() + iCycleCount); \
33  if (psg.cycleCountHigh() >= sound.sndCycleCountInitHigh()) { \
34  psg.setCycleCountBoth(psg.cycleCountBoth() - sound.sndCycleCountInitBoth()); \
35  (sound.*(psg.synthesizer()))(); \
36  } \
37  } \
38  if (fdc.phase() == EXEC_PHASE) { \
39  fdc.setTimeout(fdc.timeout() - iCycleCount); \
40  if (fdc.timeout() <= 0) { \
41  fdc.addFlags(OVERRUN_flag); \
42  if (fdc.cmdDirection() == FDC_TO_CPU) { \
43  fdc.read_data(); \
44  } \
45  else { \
46  fdc.write_data(0xff); \
47  } \
48  } \
49  } \*/
50  /*if ((cpc.tape_motor) && (cpc.tape_play_button)) { \
51  iTapeCycleCount -= iCycleCount; \
52  if (iTapeCycleCount <= 0) { \
53  Tape_UpdateLevel(); \
54  } \
55  }*/ /*\
56  cpc.setCycleCount(cpc.cycleCount() - iCycleCount); \
57 }
58 
59 
60 #define z80_int_handler \
61 { \
62  if (z80.IFF1) { // process interrupts? \
63  z80.R++; \
64  z80.IFF1 = z80.IFF2 = 0; // clear interrupt flip-flops \
65  z80.int_pending = 0; \
66  cpc.gatearray().setSlCount(cpc.gatearray().slCount() & 0xdf); // clear bit 5 of GA scanline counter \
67  if (z80.HALT) { // HALT instruction active? \
68  z80.HALT = 0; // exit HALT 'loop' \
69  z80.PC.w.l++; // correct PC \
70  } \
71  if (z80.IM < 2) { // interrupt mode 0 or 1? (IM0 = IM1 on the CPC) \
72  iCycleCount = 20; \
73  if (iWSAdjust) { \
74  iCycleCount -= 4; \
75  } \
76  RST(0x0038); \
77  z80_wait_states \
78  } \
79  else { // interrupt mode 2 \
80  tREGPAIR addr; \
81  iCycleCount = 28; // was 76 \
82  if (iWSAdjust) { \
83  iCycleCount -= 4; \
84  } \
85  write_mem(--z80.SP.w.l, z80.PC.b.h); // store high byte of current PC \
86  write_mem(--z80.SP.w.l, z80.PC.b.l); // store low byte of current PC \
87  addr.b.l = 0xff; // assemble pointer \
88  addr.b.h = MF2_RUNNING; \
89  z80.PC.b.l = read_mem(addr.w.l); // retrieve low byte of vector \
90  z80.PC.b.h = read_mem(addr.w.l+1); // retrieve high byte of vector \
91  z80_wait_states \
92  } \
93  } \
94 }
95 
96 */
97 
98 #define z80_int_handler \
99 { \
100  if (z80.IFF1) \
101  { \
102  z80.R++; \
103  z80.IFF1 = z80.IFF2 = 0; \
104  z80.int_pending = 0; \
105  cpc.gatearray().setSlCount(cpc.gatearray().slCount() & 0xdf); \
106  if (z80.HALT) \
107  { \
108  z80.HALT = 0; \
109  z80.PC.w.l++; \
110  } \
111  if (z80.IM < 2) \
112  { \
113  iCycleCount = 20; \
114  if (iWSAdjust) \
115  { \
116  iCycleCount -= 4; \
117  } \
118  RST(0x0038); \
119  z80_wait_states \
120  } \
121  else \
122  { \
123  tREGPAIR addr; \
124  iCycleCount = 28; \
125  if (iWSAdjust) \
126  { \
127  iCycleCount -= 4; \
128  } \
129  write_mem(--z80.SP.w.l, z80.PC.b.h); \
130  write_mem(--z80.SP.w.l, z80.PC.b.l); \
131  addr.b.l = 0xff; \
132  addr.b.h = MF2_RUNNING; \
133  z80.PC.b.l = read_mem(addr.w.l); \
134  z80.PC.b.h = read_mem(addr.w.l+1); \
135  z80_wait_states \
136  } \
137  } \
138 }
139 
140 
141 #define ADC(value) \
142 { \
143  unsigned val = value; \
144  unsigned res = z80.AF.b.h + val + (z80.AF.b.l & Cflag); \
145  z80.AF.b.l = SZ[res & 0xff] | ((res >> 8) & Cflag) | ((z80.AF.b.h ^ res ^ val) & Hflag) | \
146  (((val ^ z80.AF.b.h ^ 0x80) & (val ^ res) & 0x80) >> 5); \
147  z80.AF.b.h = res; \
148 }
149 
150 #define ADD(value) \
151 { \
152  unsigned val = value; \
153  unsigned res = z80.AF.b.h + val; \
154  z80.AF.b.l = SZ[(tUBYTE)res] | ((res >> 8) & Cflag) | ((z80.AF.b.h ^ res ^ val) & Hflag) | \
155  (((val ^ z80.AF.b.h ^ 0x80) & (val ^ res) & 0x80) >> 5); \
156  z80.AF.b.h = (tUBYTE)res; \
157 }
158 
159 #define ADD16(dest, src) \
160 { \
161  tDWORD res = z80.dest.d + z80.src.d; \
162  z80.AF.b.l = (z80.AF.b.l & (Sflag | Zflag | Vflag)) | (((z80.dest.d ^ res ^ z80.src.d) >> 8) & Hflag) | \
163  ((res >> 16) & Cflag) | ((res >> 8) & Xflags); \
164  z80.dest.w.l = (tUWORD)res; \
165 }
166 
167 #define AND(val) \
168 { \
169  z80.AF.b.h &= val; \
170  z80.AF.b.l = SZP[z80.AF.b.h] | Hflag; \
171 }
172 
173 #define CALL \
174 { \
175  tREGPAIR dest; \
176  dest.b.l = read_mem(z80.PC.w.l++); /* subroutine address low byte */ \
177  dest.b.h = read_mem(z80.PC.w.l++); /* subroutine address high byte */ \
178  write_mem(--z80.SP.w.l, z80.PC.b.h); /* store high byte of current PC */ \
179  write_mem(--z80.SP.w.l, z80.PC.b.l); /* store low byte of current PC */ \
180  z80.PC.w.l = dest.w.l; /* continue execution at subroutine */ \
181 }
182 
183 #define CP(value) \
184 { \
185  unsigned val = value; \
186  unsigned res = z80.AF.b.h - val; \
187  z80.AF.b.l = (SZ[res & 0xff] & (Sflag | Zflag)) | (val & Xflags) | ((res >> 8) & Cflag) | Nflag | ((z80.AF.b.h ^ res ^ val) & Hflag) | \
188  ((((val ^ z80.AF.b.h) & (z80.AF.b.h ^ res)) >> 5) & Vflag); \
189 }
190 
191 #define DAA \
192 { \
193  int idx = z80.AF.b.h; \
194  if(z80.AF.b.l & Cflag) \
195  idx |= 0x100; \
196  if(z80.AF.b.l & Hflag) \
197  idx |= 0x200; \
198  if(z80.AF.b.l & Nflag) \
199  idx |= 0x400; \
200  z80.AF.w.l = DAATable[idx]; \
201 }
202 
203 #define DEC(reg) \
204 { \
205  reg--; \
206  z80.AF.b.l = (z80.AF.b.l & Cflag) | SZHV_dec[reg]; \
207 }
208 
209 #define JR \
210 { \
211  signed char offset; \
212  offset = (signed char)(read_mem(z80.PC.w.l)); /* grab signed jump offset */ \
213  z80.PC.w.l += offset + 1; /* add offset & correct PC */ \
214 }
215 
216 #define EXX \
217 { \
218  tREGPAIR temp; \
219  temp = z80.BCx; \
220  z80.BCx = z80.BC; \
221  z80.BC = temp; \
222  temp = z80.DEx; \
223  z80.DEx = z80.DE; \
224  z80.DE = temp; \
225  temp = z80.HLx; \
226  z80.HLx = z80.HL; \
227  z80.HL = temp; \
228 }
229 
230 #define EX(op1, op2) \
231 { \
232  tREGPAIR temp; \
233  temp = op1; \
234  op1 = op2; \
235  op2 = temp; \
236 }
237 
238 #define EX_SP(reg) \
239 { \
240  tREGPAIR temp; \
241  temp.b.l = read_mem(z80.SP.w.l++); \
242  temp.b.h = read_mem(z80.SP.w.l); \
243  write_mem(z80.SP.w.l--, z80.reg.b.h); \
244  write_mem(z80.SP.w.l, z80.reg.b.l); \
245  z80.reg.w.l = temp.w.l; \
246 }
247 
248 #define INC(reg) \
249 { \
250  reg++; \
251  z80.AF.b.l = (z80.AF.b.l & Cflag) | SZHV_inc[reg]; \
252 }
253 
254 #define JP \
255 { \
256  tREGPAIR addr; \
257  addr.b.l = read_mem(z80.PC.w.l++); \
258  addr.b.h = read_mem(z80.PC.w.l); \
259  z80.PC.w.l = addr.w.l; \
260 }
261 
262 #define LD16_MEM(reg) \
263 { \
264  tREGPAIR addr; \
265  addr.b.l = read_mem(z80.PC.w.l++); \
266  addr.b.h = read_mem(z80.PC.w.l++); \
267  z80.reg.b.l = read_mem(addr.w.l); \
268  z80.reg.b.h = read_mem(addr.w.l+1); \
269 }
270 
271 #define LDMEM_16(reg) \
272 { \
273  tREGPAIR addr; \
274  addr.b.l = read_mem(z80.PC.w.l++); \
275  addr.b.h = read_mem(z80.PC.w.l++); \
276  write_mem(addr.w.l, z80.reg.b.l); \
277  write_mem(addr.w.l+1, z80.reg.b.h); \
278 }
279 
280 #define OR(val) \
281 { \
282  z80.AF.b.h |= val; \
283  z80.AF.b.l = SZP[z80.AF.b.h]; \
284 }
285 
286 #define POP(reg) \
287 { \
288  z80.reg.b.l = read_mem(z80.SP.w.l++); \
289  z80.reg.b.h = read_mem(z80.SP.w.l++); \
290 }
291 
292 #define PUSH(reg) \
293 { \
294  write_mem(--z80.SP.w.l, z80.reg.b.h); \
295  write_mem(--z80.SP.w.l, z80.reg.b.l); \
296 }
297 
298 #define RET \
299 { \
300  z80.PC.b.l = read_mem(z80.SP.w.l++); \
301  z80.PC.b.h = read_mem(z80.SP.w.l++); \
302 }
303 
304 #define RLA \
305 { \
306  tUBYTE res = (z80.AF.b.h << 1) | (z80.AF.b.l & Cflag); \
307  tUBYTE carry = (z80.AF.b.h & 0x80) ? Cflag : 0; \
308  z80.AF.b.l = (z80.AF.b.l & (Sflag | Zflag | Pflag)) | carry | (res & Xflags); \
309  z80.AF.b.h = res; \
310 }
311 
312 #define RLCA \
313 { \
314  z80.AF.b.h = (z80.AF.b.h << 1) | (z80.AF.b.h >> 7); \
315  z80.AF.b.l = (z80.AF.b.l & (Sflag | Zflag | Pflag)) | (z80.AF.b.h & (Xflags | Cflag)); \
316 }
317 
318 #define RRA \
319 { \
320  tUBYTE res = (z80.AF.b.h >> 1) | (z80.AF.b.l << 7); \
321  tUBYTE carry = (z80.AF.b.h & 0x01) ? Cflag : 0; \
322  z80.AF.b.l = (z80.AF.b.l & (Sflag | Zflag | Pflag)) | carry | (res & Xflags); \
323  z80.AF.b.h = res; \
324 }
325 
326 #define RRCA \
327 { \
328  z80.AF.b.l = (z80.AF.b.l & (Sflag | Zflag | Pflag)) | (z80.AF.b.h & Cflag); \
329  z80.AF.b.h = (z80.AF.b.h >> 1) | (z80.AF.b.h << 7); \
330  z80.AF.b.l |= (z80.AF.b.h & Xflags); \
331 }
332 
333 #define RST(addr) \
334 { \
335  write_mem(--z80.SP.w.l, z80.PC.b.h); /* store high byte of current PC */ \
336  write_mem(--z80.SP.w.l, z80.PC.b.l); /* store low byte of current PC */ \
337  z80.PC.w.l = addr; /* continue execution at restart address */ \
338 }
339 
340 #define SBC(value) \
341 { \
342  unsigned val = value; \
343  unsigned res = z80.AF.b.h - val - (z80.AF.b.l & Cflag); \
344  z80.AF.b.l = SZ[res & 0xff] | ((res >> 8) & Cflag) | Nflag | ((z80.AF.b.h ^ res ^ val) & Hflag) | \
345  (((val ^ z80.AF.b.h) & (z80.AF.b.h ^ res) & 0x80) >> 5); \
346  z80.AF.b.h = res; \
347 }
348 
349 #define SUB(value) \
350 { \
351  unsigned val = value; \
352  unsigned res = z80.AF.b.h - val; \
353  z80.AF.b.l = SZ[res & 0xff] | ((res >> 8) & Cflag) | Nflag | ((z80.AF.b.h ^ res ^ val) & Hflag) | \
354  (((val ^ z80.AF.b.h) & (z80.AF.b.h ^ res) & 0x80) >> 5); \
355  z80.AF.b.h = res; \
356 }
357 
358 #define XOR(val) \
359 { \
360  z80.AF.b.h ^= val; \
361  z80.AF.b.l = SZP[z80.AF.b.h]; \
362 }
363 
364 #define BIT(bit, reg) \
365  z80.AF.b.l = (z80.AF.b.l & Cflag) | Hflag | SZ_BIT[reg & (1 << bit)]
366 
367 #define BIT_XY BIT
368 
369 // *************************************************************************************
370 
371 #define ADC16(reg) \
372 { \
373  tDWORD res = z80.HL.d + z80.reg.d + (z80.AF.b.l & Cflag); \
374  z80.AF.b.l = (((z80.HL.d ^ res ^ z80.reg.d) >> 8) & Hflag) | \
375  ((res >> 16) & Cflag) | \
376  ((res >> 8) & (Sflag | Xflags)) | \
377  ((res & 0xffff) ? 0 : Zflag) | \
378  (((z80.reg.d ^ z80.HL.d ^ 0x8000) & (z80.reg.d ^ res) & 0x8000) >> 13); \
379  z80.HL.w.l = (tUWORD)res; \
380 }
381 
382 #define CPD \
383 { \
384  tUBYTE val = read_mem(z80.HL.w.l); \
385  tUBYTE res = z80.AF.b.h - val; \
386  z80.HL.w.l--; \
387  z80.BC.w.l--; \
388  z80.AF.b.l = (z80.AF.b.l & Cflag) | (SZ[res] & ~Xflags) | ((z80.AF.b.h ^ val ^ res) & Hflag) | Nflag; \
389  if(z80.AF.b.l & Hflag) res -= 1; \
390  if(res & 0x02) z80.AF.b.l |= 0x20; \
391  if(res & 0x08) z80.AF.b.l |= 0x08; \
392  if(z80.BC.w.l) z80.AF.b.l |= Vflag; \
393 }
394 
395 #define CPDR \
396  CPD; \
397  if(z80.BC.w.l && !(z80.AF.b.l & Zflag)) \
398  { \
399  iCycleCount += cc_ex[bOpCode]; \
400  z80.PC.w.l -= 2; \
401  iWSAdjust++; \
402  }
403 
404 #define CPI \
405 { \
406  tUBYTE val = read_mem(z80.HL.w.l); \
407  tUBYTE res = z80.AF.b.h - val; \
408  z80.HL.w.l++; \
409  z80.BC.w.l--; \
410  z80.AF.b.l = (z80.AF.b.l & Cflag) | (SZ[res] & ~Xflags) | ((z80.AF.b.h ^ val ^ res) & Hflag) | Nflag; \
411  if(z80.AF.b.l & Hflag) res -= 1; \
412  if(res & 0x02) z80.AF.b.l |= 0x20; \
413  if(res & 0x08) z80.AF.b.l |= 0x08; \
414  if(z80.BC.w.l) z80.AF.b.l |= Vflag; \
415 }
416 
417 #define CPIR \
418  CPI; \
419  if(z80.BC.w.l && !(z80.AF.b.l & Zflag)) \
420  { \
421  iCycleCount += cc_ex[bOpCode]; \
422  z80.PC.w.l -= 2; \
423  iWSAdjust++; \
424  }
425 
426 #define IND \
427 { \
428  tUBYTE io = z80_IN_handler(z80.BC); \
429  z80.BC.b.h--; \
430  write_mem(z80.HL.w.l, io); \
431  z80.HL.w.l--; \
432  z80.AF.b.l = SZ[z80.BC.b.h]; \
433  if(io & Sflag) z80.AF.b.l |= Nflag; \
434  if((((z80.BC.b.l - 1) & 0xff) + io) & 0x100) z80.AF.b.l |= Hflag | Cflag; \
435  if((drep_tmp1[z80.BC.b.l & 3][io & 3] ^ breg_tmp2[z80.BC.b.h] ^ (z80.BC.b.l >> 2) ^ (io >> 2)) & 1) \
436  z80.AF.b.l |= Pflag; \
437 }
438 
439 #define INDR \
440  IND; \
441  if(z80.BC.b.h) \
442  { \
443  iCycleCount += cc_ex[bOpCode]; \
444  z80.PC.w.l -= 2; \
445  }
446 
447 #define INI \
448 { \
449  tUBYTE io = z80_IN_handler(z80.BC); \
450  z80.BC.b.h--; \
451  write_mem(z80.HL.w.l, io); \
452  z80.HL.w.l++; \
453  z80.AF.b.l = SZ[z80.BC.b.h]; \
454  if(io & Sflag) z80.AF.b.l |= Nflag; \
455  if((((z80.BC.b.l + 1) & 0xff) + io) & 0x100) z80.AF.b.l |= Hflag | Cflag; \
456  if((irep_tmp1[z80.BC.b.l & 3][io & 3] ^ breg_tmp2[z80.BC.b.h] ^ (z80.BC.b.l >> 2) ^ (io >> 2)) & 1) \
457  z80.AF.b.l |= Pflag; \
458 }
459 
460 #define INIR \
461  INI; \
462  if(z80.BC.b.h) \
463  { \
464  iCycleCount += cc_ex[bOpCode]; \
465  z80.PC.w.l -= 2; \
466  }
467 
468 #define LDD \
469 { \
470  tUBYTE io = read_mem(z80.HL.w.l); \
471  write_mem(z80.DE.w.l, io); \
472  z80.AF.b.l &= Sflag | Zflag | Cflag; \
473  if((z80.AF.b.h + io) & 0x02) z80.AF.b.l |= 0x20; \
474  if((z80.AF.b.h + io) & 0x08) z80.AF.b.l |= 0x08; \
475  z80.HL.w.l--; \
476  z80.DE.w.l--; \
477  z80.BC.w.l--; \
478  if(z80.BC.w.l) z80.AF.b.l |= Vflag; \
479 }
480 
481 #define LDDR \
482  LDD; \
483  if(z80.BC.w.l) \
484  { \
485  iCycleCount += cc_ex[bOpCode]; \
486  z80.PC.w.l -= 2; \
487  }
488 
489 #define LDI \
490 { \
491  tUBYTE io = read_mem(z80.HL.w.l); \
492  write_mem(z80.DE.w.l, io); \
493  z80.AF.b.l &= Sflag | Zflag | Cflag; \
494  if((z80.AF.b.h + io) & 0x02) z80.AF.b.l |= 0x20; \
495  if((z80.AF.b.h + io) & 0x08) z80.AF.b.l |= 0x08; \
496  z80.HL.w.l++; \
497  z80.DE.w.l++; \
498  z80.BC.w.l--; \
499  if(z80.BC.w.l) z80.AF.b.l |= Vflag; \
500 }
501 
502 #define LDIR \
503  LDI; \
504  if(z80.BC.w.l) \
505  { \
506  iCycleCount += cc_ex[bOpCode]; \
507  z80.PC.w.l -= 2; \
508  }
509 
510 #define NEG \
511 { \
512  tUBYTE value = z80.AF.b.h; \
513  z80.AF.b.h = 0; \
514  SUB(value); \
515 }
516 
517 #define OUTD \
518 { \
519  tUBYTE io = read_mem(z80.HL.w.l); \
520  z80.BC.b.h--; \
521  z80_OUT_handler(z80.BC, io); \
522  z80.HL.w.l--; \
523  z80.AF.b.l = SZ[z80.BC.b.h]; \
524  if(io & Sflag) z80.AF.b.l |= Nflag; \
525  if((((z80.BC.b.l - 1) & 0xff) + io) & 0x100) z80.AF.b.l |= Hflag | Cflag; \
526  if((drep_tmp1[z80.BC.b.l & 3][io & 3] ^ breg_tmp2[z80.BC.b.h] ^ (z80.BC.b.l >> 2) ^ (io >> 2)) & 1) \
527  z80.AF.b.l |= Pflag; \
528 }
529 
530 #define OTDR \
531  OUTD; \
532  if(z80.BC.b.h) \
533  { \
534  iCycleCount += cc_ex[bOpCode]; \
535  z80.PC.w.l -= 2; \
536  }
537 
538 #define OUTI \
539 { \
540  tUBYTE io = read_mem(z80.HL.w.l); \
541  z80.BC.b.h--; \
542  z80_OUT_handler(z80.BC, io); \
543  z80.HL.w.l++; \
544  z80.AF.b.l = SZ[z80.BC.b.h]; \
545  if(io & Sflag) z80.AF.b.l |= Nflag; \
546  if((((z80.BC.b.l + 1) & 0xff) + io) & 0x100) z80.AF.b.l |= Hflag | Cflag; \
547  if((irep_tmp1[z80.BC.b.l & 3][io & 3] ^ breg_tmp2[z80.BC.b.h] ^ (z80.BC.b.l >> 2) ^ (io >> 2)) & 1) \
548  z80.AF.b.l |= Pflag; \
549 }
550 
551 #define OTIR \
552  OUTI; \
553  if(z80.BC.b.h) \
554  { \
555  iCycleCount += cc_ex[bOpCode]; \
556  z80.PC.w.l -= 2; \
557  }
558 
559 #define RLD \
560 { \
561  tUBYTE n = read_mem(z80.HL.w.l); \
562  write_mem(z80.HL.w.l, (n << 4) | (z80.AF.b.h & 0x0f)); \
563  z80.AF.b.h = (z80.AF.b.h & 0xf0) | (n >> 4); \
564  z80.AF.b.l = (z80.AF.b.l & Cflag) | SZP[z80.AF.b.h]; \
565 }
566 
567 #define RRD \
568 { \
569  tUBYTE n = read_mem(z80.HL.w.l); \
570  write_mem(z80.HL.w.l, (n >> 4) | (z80.AF.b.h << 4)); \
571  z80.AF.b.h = (z80.AF.b.h & 0xf0) | (n & 0x0f); \
572  z80.AF.b.l = (z80.AF.b.l & Cflag) | SZP[z80.AF.b.h]; \
573 }
574 
575 #define SBC16(reg) \
576 { \
577  tDWORD res = z80.HL.d - z80.reg.d - (z80.AF.b.l & Cflag); \
578  z80.AF.b.l = (((z80.HL.d ^ res ^ z80.reg.d) >> 8) & Hflag) | Nflag | \
579  ((res >> 16) & Cflag) | \
580  ((res >> 8) & (Sflag | Xflags)) | \
581  ((res & 0xffff) ? 0 : Zflag) | \
582  (((z80.reg.d ^ z80.HL.d) & (z80.HL.d ^ res) &0x8000) >> 13); \
583  z80.HL.w.l = (tUWORD)res; \
584 }
585 
586 
587 #endif // Z80_MACROS_H