Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
macros.h
Go to the documentation of this file.
1 /*
2  * Z80Ex, ZILoG Z80 CPU emulator.
3  *
4  * by Pigmaker57 aka boo_boo [pigmaker57@kahoh57.info]
5  * modified by Gabor Lenart LGB [lgblgblgb@gmail.com] for Xep128 and Xemu
6  *
7  * contains some code from the FUSE project (http://fuse-emulator.sourceforge.net)
8  * Released under GNU GPL v2
9  *
10  */
11 
12 #ifndef _Z80EX_MACROS_H_INCLUDED
13 #define _Z80EX_MACROS_H_INCLUDED
14 
15 
16 /* Macros used for accessing the registers */
17 #define A z80ex.af.b.h
18 #define F z80ex.af.b.l
19 #define AF z80ex.af.w
20 
21 #define B z80ex.bc.b.h
22 #define C z80ex.bc.b.l
23 #define BC z80ex.bc.w
24 
25 #define D z80ex.de.b.h
26 #define E z80ex.de.b.l
27 #define DE z80ex.de.w
28 
29 #define H z80ex.hl.b.h
30 #define L z80ex.hl.b.l
31 #define HL z80ex.hl.w
32 
33 #define A_ z80ex.af_.b.h
34 #define F_ z80ex.af_.b.l
35 #define AF_ z80ex.af_.w
36 
37 #define B_ z80ex.bc_.b.h
38 #define C_ z80ex.bc_.b.l
39 #define BC_ z80ex.bc_.w
40 
41 #define D_ z80ex.de_.b.h
42 #define E_ z80ex.de_.b.l
43 #define DE_ z80ex.de_.w
44 
45 #define H_ z80ex.hl_.b.h
46 #define L_ z80ex.hl_.b.l
47 #define HL_ z80ex.hl_.w
48 
49 #define IXH z80ex.ix.b.h
50 #define IXL z80ex.ix.b.l
51 #define IX z80ex.ix.w
52 
53 #define IYH z80ex.iy.b.h
54 #define IYL z80ex.iy.b.l
55 #define IY z80ex.iy.w
56 
57 #define SPH z80ex.sp.b.h
58 #define SPL z80ex.sp.b.l
59 #define SP z80ex.sp.w
60 
61 #define PCH z80ex.pc.b.h
62 #define PCL z80ex.pc.b.l
63 #define PC z80ex.pc.w
64 
65 #define I z80ex.i
66 #define R z80ex.r
67 #define R7 z80ex.r7
68 
69 #define IFF1 z80ex.iff1
70 #define IFF2 z80ex.iff2
71 #define IM z80ex.im
72 
73 #define MEMPTRh z80ex.memptr.b.h
74 #define MEMPTRl z80ex.memptr.b.l
75 #define MEMPTR z80ex.memptr.w
76 
77 /* The flags */
78 
79 #define FLAG_C 0x01
80 #define FLAG_N 0x02
81 #define FLAG_P 0x04
82 #define FLAG_V FLAG_P
83 #define FLAG_3 0x08
84 #define FLAG_H 0x10
85 #define FLAG_5 0x20
86 #define FLAG_Z 0x40
87 #define FLAG_S 0x80
88 
89 /*read opcode*/
90 #define READ_OP_M1() (z80ex.int_vector_req? z80ex_intread_cb() : z80ex_mread_cb(PC++, 1))
91 
92 /*read opcode argument*/
93 #define READ_OP() (z80ex.int_vector_req? z80ex_intread_cb() : z80ex_mread_cb(PC++, 0))
94 
95 
96 #ifndef Z80EX_OPSTEP_FAST_AND_ROUGH
97 
98 #ifdef Z80EX_TSTATE_CALLBACK
99 /*wait until end of opcode-tstate given (to be used on opcode execution).*/
100 #define T_WAIT_UNTIL(t_state) \
101 { \
102  unsigned nn; \
103  if(!IS_TSTATE_CB) { \
104  if (t_state > z80ex.op_tstate) { \
105  z80ex.tstate += t_state - z80ex.op_tstate; \
106  z80ex.op_tstate = t_state; \
107  } \
108  } \
109  else { \
110  for(nn=z80ex.op_tstate;nn < t_state;nn++) { \
111  z80ex.op_tstate++; \
112  z80ex.tstate++; \
113  z80ex_tstate_cb(); \
114  } \
115  } \
116 }
117 
118 #else
119 #define T_WAIT_UNTIL(t_state) \
120  if (t_state > z80ex.op_tstate) { \
121  z80ex.tstate += t_state - z80ex.op_tstate; \
122  z80ex.op_tstate = t_state; \
123  }
124 #endif
125 
126 #ifdef Z80EX_TSTATE_CALLBACK
127 /*spend <amount> t-states (not affecting opcode-tstate counter,
128 for using outside of certain opcode execution)*/
129 #define TSTATES(amount) \
130 {\
131  int nn;\
132  if(!IS_TSTATE_CB) { \
133  z80ex.tstate += amount; \
134  } \
135  else { \
136  for(nn=0; nn < amount; nn++) { \
137  z80ex.tstate++; \
138  z80ex_tstate_cb(); \
139  }\
140  } \
141 }
142 #else
143 #define TSTATES(amount) z80ex.tstate += amount
144 #endif
145 
146 /*read byte from memory*/
147 #define READ_MEM(result, addr, t_state) \
148 { \
149  T_WAIT_UNTIL(t_state); \
150  result=(z80ex_mread_cb((addr), 0)); \
151 }
152 
153 /*read byte from port*/
154 #define READ_PORT(result, port, t_state) \
155 { \
156  T_WAIT_UNTIL(t_state); \
157  result=(z80ex_pread_cb((port))); \
158 }
159 
160 /*write byte to memory*/
161 #define WRITE_MEM(addr, vbyte, t_state) \
162 { \
163  T_WAIT_UNTIL(t_state); \
164  z80ex_mwrite_cb(addr, vbyte); \
165 }
166 
167 /*write byte to port*/
168 #define WRITE_PORT(port, vbyte, t_state) \
169 { \
170  T_WAIT_UNTIL(t_state); \
171  z80ex_pwrite_cb((port), vbyte); \
172 }
173 
174 #else
175 /*Z80EX_OPSTEP_FAST_AND_ROUGH*/
176 
177 #define T_WAIT_UNTIL(t_state) {z80ex.tstate = t_state; z80ex.op_tstate = t_state;}
178 
179 #define TSTATES(amount) {z80ex.tstate += amount;}
180 
181 /*read byte from memory*/
182 #define READ_MEM(result, addr, t_state) \
183 { \
184  result=(z80ex_mread_cb((addr), 0)); \
185 }
186 
187 /*read byte from port*/
188 #define READ_PORT(result, port, t_state) \
189 { \
190  result=(z80ex_pread_cb((port))); \
191 }
192 
193 /*write byte to memory*/
194 #define WRITE_MEM(addr, vbyte, t_state) \
195 { \
196  z80ex_mwrite_cb(addr, vbyte); \
197 }
198 
199 /*write byte to port*/
200 #define WRITE_PORT(port, vbyte, t_state) \
201 { \
202  z80ex_pwrite_cb((port), vbyte); \
203 }
204 
205 #endif
206 /*<< #ifndef Z80EX_OPSTEP_FAST_AND_ROUGH*/
207 
208 
209 /* instructions */
210 
211 #define AND(value)\
212 {\
213  A &= (value);\
214  F = FLAG_H | sz53p_table[A];\
215 }
216 
217 #define ADC(a, value)\
218 {\
219  Z80EX_WORD adctemp = A + (value) + ( F & FLAG_C ); \
220  Z80EX_BYTE lookup = ( ( A & 0x88 ) >> 3 ) | \
221  ( ( (value) & 0x88 ) >> 2 ) | \
222  ( ( adctemp & 0x88 ) >> 1 ); \
223  A=adctemp;\
224  F = ( adctemp & 0x100 ? FLAG_C : 0 ) |\
225  halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] |\
226  sz53_table[A];\
227 }
228 
229 #define ADC16(hl, value)\
230 {\
231  Z80EX_DWORD add16temp= HL + (value) + ( F & FLAG_C ); \
232  Z80EX_BYTE lookup = ( ( HL & 0x8800 ) >> 11 ) | \
233  ( ( (value) & 0x8800 ) >> 10 ) | \
234  ( ( add16temp & 0x8800 ) >> 9 ); \
235  MEMPTR=hl+1;\
236  HL = add16temp;\
237  F = ( add16temp & 0x10000 ? FLAG_C : 0 )|\
238  overflow_add_table[lookup >> 4] |\
239  ( H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |\
240  halfcarry_add_table[lookup&0x07]|\
241  ( HL ? 0 : FLAG_Z );\
242 }
243 
244 #define ADD(a, value)\
245 {\
246  Z80EX_WORD addtemp = A + (value); \
247  Z80EX_BYTE lookup = ( ( A & 0x88 ) >> 3 ) | \
248  ( ( (value) & 0x88 ) >> 2 ) | \
249  ( ( addtemp & 0x88 ) >> 1 ); \
250  A=addtemp;\
251  F = ( addtemp & 0x100 ? FLAG_C : 0 ) |\
252  halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] |\
253  sz53_table[A];\
254 }
255 
256 #define ADD16(value1,value2)\
257 {\
258  Z80EX_DWORD add16temp = (value1) + (value2); \
259  Z80EX_BYTE lookup = ( ( (value1) & 0x0800 ) >> 11 ) | \
260  ( ( (value2) & 0x0800 ) >> 10 ) | \
261  ( ( add16temp & 0x0800 ) >> 9 ); \
262  MEMPTR=value1+1;\
263  (value1) = add16temp;\
264  F = ( F & ( FLAG_V | FLAG_Z | FLAG_S ) ) |\
265  ( add16temp & 0x10000 ? FLAG_C : 0 )|\
266  ( ( add16temp >> 8 ) & ( FLAG_3 | FLAG_5 ) ) |\
267  halfcarry_add_table[lookup];\
268 }
269 
270 #define BIT( bit, value ) \
271 { \
272  F = ( F & FLAG_C ) | FLAG_H | sz53p_table[(value) & (0x01 << (bit))] | ((value) & 0x28); \
273 }
274 
275 /*BIT n,(IX+d/IY+d) and BIT n,(HL)*/
276 #define BIT_MPTR( bit, value) \
277 { \
278  F = ( F & FLAG_C ) | FLAG_H | (sz53p_table[(value) & (0x01 << (bit))] & 0xD7) | ((MEMPTRh) & 0x28); \
279 }
280 
281 #define CALL(addr, wr1, wr2) \
282 {\
283  PUSH(PC,wr1,wr2); \
284  PC=addr; \
285  MEMPTR=addr;\
286 }
287 
288 #define CP(value)\
289 {\
290  Z80EX_WORD cptemp = A - value; \
291  Z80EX_BYTE lookup = ( ( A & 0x88 ) >> 3 ) | \
292  ( ( (value) & 0x88 ) >> 2 ) | \
293  ( ( cptemp & 0x88 ) >> 1 ); \
294  F = ( cptemp & 0x100 ? FLAG_C : ( cptemp ? 0 : FLAG_Z ) ) | FLAG_N |\
295  halfcarry_sub_table[lookup & 0x07] |\
296  overflow_sub_table[lookup >> 4] |\
297  ( value & ( FLAG_3 | FLAG_5 ) ) |\
298  ( cptemp & FLAG_S );\
299 }
300 
301 #define DEC(value)\
302 {\
303  F = ( F & FLAG_C ) | ( (value)&0x0f ? 0 : FLAG_H ) | FLAG_N;\
304  (value)--;\
305  F |= ( (value)==0x7f ? FLAG_V : 0 ) | sz53_table[value];\
306 }
307 
308 #define DEC16(value)\
309 {\
310  (value)--;\
311 }
312 
313 #define INC(value)\
314 {\
315  (value)++;\
316  F = ( F & FLAG_C ) | ( (value)==0x80 ? FLAG_V : 0 ) |\
317  ( (value)&0x0f ? 0 : FLAG_H ) | sz53_table[(value)];\
318 }
319 
320 #define INC16(value)\
321 {\
322  (value)++;\
323 }
324 
325 #define LD(dst, src) \
326 {\
327  dst=src; \
328 }
329 
330 /*ld (nnnn|BC|DE), A*/
331 #define LD_A_TO_ADDR_MPTR(dst, src, addr) \
332 {\
333  dst=src; \
334  MEMPTRh=A;\
335  MEMPTRl=((addr+1) & 0xFF);\
336 }
337 
338 /*ld a,(BC|DE|nnnn)*/
339 #define LD_A_FROM_ADDR_MPTR(dst, src, addr) \
340 {\
341  dst=src; \
342  MEMPTR=addr+1;\
343 }
344 
345 #define LD16(dst, src) \
346 {\
347  dst=src; \
348 }
349 
350 /*ld (nnnn),BC|DE|SP|HL|IX|IY*/
351 #define LD_RP_TO_ADDR_MPTR_16(dst, src, addr) \
352 {\
353  dst=src; \
354  MEMPTR=addr+1;\
355 }
356 
357 /*ld BC|DE|SP|HL|IX|IY,(nnnn)*/
358 #define LD_RP_FROM_ADDR_MPTR_16(dst, src, addr) \
359 {\
360  dst=src; \
361  MEMPTR=addr+1;\
362 }
363 
364 #define JP_NO_MPTR(addr) \
365 { \
366  PC=addr; \
367 }
368 
369 #define JP(addr) \
370 { \
371  PC=addr; \
372  MEMPTR=addr;\
373 }
374 
375 #define JR(offset) \
376 {\
377  PC+=offset; \
378  MEMPTR=PC;\
379 }
380 
381 #define OR(value)\
382 {\
383  A |= (value);\
384  F = sz53p_table[A];\
385 }
386 
387 #define OUT(port,reg, wr) \
388 {\
389  WRITE_PORT(port,reg,wr); \
390  MEMPTR=port+1;\
391 }
392 
393 /*OUT (nn),A*/
394 #define OUT_A(port,reg, wr) \
395 {\
396  WRITE_PORT(port,reg,wr); \
397  MEMPTRl=((port+1) & 0xFF);\
398  MEMPTRh=A;\
399 }
400 
401 #define IN(reg,port,rd) \
402 {\
403  READ_PORT(reg,port,rd); \
404  F = ( F & FLAG_C) | sz53p_table[(reg)];\
405  MEMPTR=port+1;\
406 }
407 
408 /*IN A,(nn)*/
409 #define IN_A(reg,port,rd) \
410 {\
411  READ_PORT(reg,port,rd); \
412  MEMPTR=port+1;\
413 }
414 
415 #define IN_F(port, rd) \
416 {\
417  Z80EX_BYTE val; \
418  READ_PORT(val, port, rd); \
419  F = ( F & FLAG_C) | sz53p_table[(val)];\
420  MEMPTR=port+1;\
421 }
422 
423 #define POP(rp, rd1, rd2) \
424 {\
425  Z80EX_REGPAIR_T tmp; \
426  READ_MEM(tmp.b.l,SP++,rd1);\
427  READ_MEM(tmp.b.h,SP++,rd2);\
428  rp=tmp.w;\
429 }
430 
431 /*wr1=t-states before first byte, wr2=t-states before second*/
432 #define PUSH(rp, wr1, wr2) \
433 {\
434  Z80EX_REGPAIR_T tmp; \
435  tmp.w=rp; \
436  WRITE_MEM(--SP, tmp.b.h, wr1); \
437  WRITE_MEM(--SP, tmp.b.l, wr2); \
438 }
439 
440 #define RET(rd1, rd2) \
441 {\
442  POP(PC, rd1, rd2);\
443  MEMPTR=PC;\
444 }
445 
446 #define RL(value)\
447 {\
448  Z80EX_BYTE rltemp = (value); \
449  (value) = ( (value)<<1 ) | ( F & FLAG_C );\
450  F = ( rltemp >> 7 ) | sz53p_table[(value)];\
451 }
452 
453 #define RLC(value)\
454 {\
455  (value) = ( (value)<<1 ) | ( (value)>>7 );\
456  F = ( (value) & FLAG_C ) | sz53p_table[(value)];\
457 }
458 
459 #define RR(value)\
460 {\
461  Z80EX_BYTE rrtemp = (value); \
462  (value) = ( (value)>>1 ) | ( F << 7 );\
463  F = ( rrtemp & FLAG_C ) | sz53p_table[(value)];\
464 }
465 
466 #define RRC(value)\
467 {\
468  F = (value) & FLAG_C;\
469  (value) = ( (value)>>1 ) | ( (value)<<7 );\
470  F |= sz53p_table[(value)];\
471 }
472 
473 #define RST(value, w1, w2)\
474 {\
475  PUSH(PC, w1, w2);\
476  PC=(value);\
477  MEMPTR=PC;\
478 }
479 
480 #define SBC(a, value)\
481 {\
482  Z80EX_WORD sbctemp = A - (value) - ( F & FLAG_C ); \
483  Z80EX_BYTE lookup = ( ( A & 0x88 ) >> 3 ) | \
484  ( ( (value) & 0x88 ) >> 2 ) | \
485  ( ( sbctemp & 0x88 ) >> 1 ); \
486  A=sbctemp;\
487  F = ( sbctemp & 0x100 ? FLAG_C : 0 ) | FLAG_N |\
488  halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] |\
489  sz53_table[A];\
490 }
491 
492 #define SBC16(hl, value)\
493 {\
494  Z80EX_DWORD sub16temp = HL - (value) - (F & FLAG_C); \
495  Z80EX_BYTE lookup = ( ( HL & 0x8800 ) >> 11 ) | \
496  ( ( (value) & 0x8800 ) >> 10 ) | \
497  ( ( sub16temp & 0x8800 ) >> 9 ); \
498  MEMPTR=hl+1;\
499  HL = sub16temp;\
500  F = ( sub16temp & 0x10000 ? FLAG_C : 0 ) |\
501  FLAG_N | overflow_sub_table[lookup >> 4] |\
502  ( H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |\
503  halfcarry_sub_table[lookup&0x07] |\
504  ( HL ? 0 : FLAG_Z) ;\
505 }
506 
507 #define SLA(value)\
508 {\
509  F = (value) >> 7;\
510  (value) <<= 1;\
511  F |= sz53p_table[(value)];\
512 }
513 
514 #define SLL(value)\
515 {\
516  F = (value) >> 7;\
517  (value) = ( (value) << 1 ) | 0x01;\
518  F |= sz53p_table[(value)];\
519 }
520 
521 #define SRA(value)\
522 {\
523  F = (value) & FLAG_C;\
524  (value) = ( (value) & 0x80 ) | ( (value) >> 1 );\
525  F |= sz53p_table[(value)];\
526 }
527 
528 #define SRL(value)\
529 {\
530  F = (value) & FLAG_C;\
531  (value) >>= 1;\
532  F |= sz53p_table[(value)];\
533 }
534 
535 #define SUB(value)\
536 {\
537  Z80EX_WORD subtemp = A - (value); \
538  Z80EX_BYTE lookup = ( ( A & 0x88 ) >> 3 ) | \
539  ( ( (value) & 0x88 ) >> 2 ) | \
540  ( (subtemp & 0x88 ) >> 1 ); \
541  A=subtemp;\
542  F = ( subtemp & 0x100 ? FLAG_C : 0 ) | FLAG_N |\
543  halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] |\
544  sz53_table[A];\
545 }
546 
547 #define XOR(value)\
548 {\
549  A ^= (value);\
550  F = sz53p_table[A];\
551 }
552 
553 #define RRD(rd, wr) \
554 {\
555  Z80EX_BYTE bytetemp;\
556  READ_MEM(bytetemp, HL, rd);\
557  WRITE_MEM(HL, ( A << 4 ) | ( bytetemp >> 4 ) ,wr);\
558  A = ( A & 0xf0 ) | ( bytetemp & 0x0f );\
559  F = ( F & FLAG_C ) | sz53p_table[A];\
560  MEMPTR=HL+1;\
561 }
562 
563 #define RLD(rd, wr) \
564 {\
565  Z80EX_BYTE bytetemp;\
566  READ_MEM(bytetemp, HL, rd);\
567  WRITE_MEM(HL, (bytetemp << 4 ) | ( A & 0x0f ) ,wr);\
568  A = ( A & 0xf0 ) | ( bytetemp >> 4 );\
569  F = ( F & FLAG_C ) | sz53p_table[A];\
570  MEMPTR=HL+1;\
571 }
572 
573 
574 #define IM_(mode)\
575 {\
576  IM=mode;\
577 }
578 
579 #define LD_A_R() \
580 {\
581  A=(R&0x7f) | (R7&0x80);\
582  F = ( F & FLAG_C ) | sz53_table[A] | ( IFF2 ? FLAG_V : 0 );\
583  if (z80ex.nmos) z80ex.reset_PV_on_int=1;\
584 }
585 
586 #define LD_R_A() \
587 {\
588  R=R7=A;\
589 }
590 
591 #define LD_A_I() \
592 {\
593  A=I;\
594  F = ( F & FLAG_C ) | sz53_table[A] | ( IFF2 ? FLAG_V : 0 );\
595  if (z80ex.nmos) z80ex.reset_PV_on_int=1;\
596 }
597 
598 #define NEG() \
599 {\
600  Z80EX_BYTE bytetemp=A;\
601  A=0;\
602  SUB(bytetemp);\
603 }
604 
605 #define RETI(rd1, rd2) \
606 {\
607  IFF1=IFF2;\
608  RET(rd1, rd2);\
609  z80ex_reti_cb(); \
610 }
611 
612 /*same as RETI, only opcode is different*/
613 #define RETN(rd1, rd2) \
614 {\
615  IFF1=IFF2;\
616  RET(rd1, rd2);\
617 }
618 
619 #define LDI(rd, wr) \
620 {\
621  Z80EX_BYTE bytetemp;\
622  READ_MEM(bytetemp, HL, rd);\
623  BC--;\
624  WRITE_MEM(DE,bytetemp,wr);\
625  DE++; HL++;\
626  bytetemp += A;\
627  F = ( F & ( FLAG_C | FLAG_Z | FLAG_S ) ) | ( BC ? FLAG_V : 0 ) |\
628  ( bytetemp & FLAG_3 ) | ( (bytetemp & 0x02) ? FLAG_5 : 0 );\
629 }
630 
631 #define CPI(rd) \
632 {\
633  Z80EX_BYTE value,bytetemp,lookup;\
634  READ_MEM(value, HL, rd);\
635  bytetemp = A - value;\
636  lookup = ( ( A & 0x08 ) >> 3 ) |\
637  ( ( (value) & 0x08 ) >> 2 ) |\
638  ( ( bytetemp & 0x08 ) >> 1 );\
639  HL++; BC--;\
640  F = ( F & FLAG_C ) | ( BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |\
641  halfcarry_sub_table[lookup] | ( bytetemp ? 0 : FLAG_Z ) |\
642  ( bytetemp & FLAG_S );\
643  if(F & FLAG_H) bytetemp--;\
644  F |= ( bytetemp & FLAG_3 ) | ( (bytetemp&0x02) ? FLAG_5 : 0 );\
645  MEMPTR=MEMPTR+1;\
646 }
647 
648 /*undocumented flag effects for block output operations*/
649 #define OUT_BL(pbyte) \
650 {\
651  Z80EX_BYTE kval;\
652  kval=pbyte+L;\
653  if((pbyte+L) > 255) F |= (FLAG_C | FLAG_H);\
654  F |= parity_table[((kval & 7) ^ B)];\
655 }
656 
657 /*undocumented flag effects for block input operations*/
658 #define IN_BL(pbyte, c_add) \
659 {\
660  Z80EX_BYTE kval;\
661  kval=pbyte+((C+(c_add)) & 0xff);\
662  if((pbyte+((C+(c_add)) & 0xff)) > 255) F |= (FLAG_C | FLAG_H);\
663  F |= parity_table[((kval & 7) ^ B)];\
664 }
665 
666 #define INI(rd, wr) \
667 {\
668  Z80EX_BYTE initemp;\
669  MEMPTR=BC+1;\
670  READ_PORT(initemp, BC, rd);\
671  WRITE_MEM( HL, initemp, wr );\
672  B--; HL++;\
673  F = ( initemp & 0x80 ? FLAG_N : 0 ) | sz53_table[B];\
674  IN_BL(initemp,1);\
675 }
676 
677 #define OUTI(rd, wr) \
678 {\
679  Z80EX_BYTE outitemp;\
680  READ_MEM(outitemp, HL, rd);\
681  B--; \
682  MEMPTR=BC+1;\
683  WRITE_PORT(BC,outitemp,wr);\
684  HL++;\
685  F = (outitemp & 0x80 ? FLAG_N : 0 ) | sz53_table[B];\
686  OUT_BL(outitemp);\
687 }
688 
689 #define LDD(rd, wr) \
690 {\
691  Z80EX_BYTE bytetemp;\
692  READ_MEM(bytetemp, HL, rd);\
693  BC--;\
694  WRITE_MEM(DE,bytetemp,wr);\
695  DE--; HL--;\
696  bytetemp += A;\
697  F = ( F & ( FLAG_C | FLAG_Z | FLAG_S ) ) | ( BC ? FLAG_V : 0 ) |\
698  ( bytetemp & FLAG_3 ) | ( (bytetemp & 0x02) ? FLAG_5 : 0 );\
699 }
700 
701 #define CPD(rd) \
702 {\
703  Z80EX_BYTE value,bytetemp,lookup;\
704  READ_MEM(value, HL, rd);\
705  bytetemp = A - value;\
706  lookup = ( ( A & 0x08 ) >> 3 ) |\
707  ( ( (value) & 0x08 ) >> 2 ) |\
708  ( ( bytetemp & 0x08 ) >> 1 );\
709  HL--; BC--;\
710  F = ( F & FLAG_C ) | ( BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |\
711  halfcarry_sub_table[lookup] | ( bytetemp ? 0 : FLAG_Z ) |\
712  ( bytetemp & FLAG_S );\
713  if(F & FLAG_H) bytetemp--;\
714  F |= ( bytetemp & FLAG_3 ) | ( (bytetemp&0x02) ? FLAG_5 : 0 );\
715  MEMPTR=MEMPTR-1;\
716 }
717 
718 #define IND(rd,wr) \
719 {\
720  Z80EX_BYTE initemp;\
721  MEMPTR=BC-1;\
722  READ_PORT(initemp, BC, rd);\
723  WRITE_MEM( HL, initemp, wr );\
724  B--; HL--;\
725  F = ( initemp & 0x80 ? FLAG_N : 0 ) | sz53_table[B];\
726  IN_BL(initemp,-1)\
727 }
728 
729 #define OUTD(rd, wr) \
730 {\
731  Z80EX_BYTE outitemp;\
732  READ_MEM(outitemp, HL, rd);\
733  B--;\
734  MEMPTR=BC-1;\
735  WRITE_PORT(BC,outitemp,wr);\
736  HL--;\
737  F = (outitemp & 0x80 ? FLAG_N : 0 ) | sz53_table[B];\
738  OUT_BL(outitemp);\
739 }
740 
741 #define LDIR(t1,t2,rd,wr) \
742 {\
743  Z80EX_BYTE bytetemp;\
744  READ_MEM(bytetemp, HL, rd);\
745  WRITE_MEM(DE,bytetemp,wr);\
746  HL++; DE++; BC--;\
747  bytetemp += A;\
748  F = ( F & ( FLAG_C | FLAG_Z | FLAG_S ) ) | ( BC ? FLAG_V : 0 ) |\
749  ( bytetemp & FLAG_3 ) | ( (bytetemp & 0x02) ? FLAG_5 : 0 );\
750  if(BC) {\
751  PC-=2;\
752  T_WAIT_UNTIL(t2);\
753  MEMPTR=PC+1;\
754  }\
755  else\
756  {\
757  T_WAIT_UNTIL(t1);\
758  }\
759 }
760 
761 #define CPIR(t1, t2, rd) \
762 {\
763  Z80EX_BYTE value,bytetemp,lookup;\
764  READ_MEM(value, HL, rd);\
765  bytetemp = A - value;\
766  lookup = ( ( A & 0x08 ) >> 3 ) |\
767  ( ( (value) & 0x08 ) >> 2 ) |\
768  ( ( bytetemp & 0x08 ) >> 1 );\
769  HL++; BC--;\
770  F = ( F & FLAG_C ) | ( BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |\
771  halfcarry_sub_table[lookup] | ( bytetemp ? 0 : FLAG_Z ) |\
772  ( bytetemp & FLAG_S );\
773  if(F & FLAG_H) bytetemp--;\
774  F |= ( bytetemp & FLAG_3 ) | ( (bytetemp&0x02) ? FLAG_5 : 0 );\
775  if( ( F & ( FLAG_V | FLAG_Z ) ) == FLAG_V ) {\
776  PC-=2;\
777  MEMPTR=PC+1;\
778  T_WAIT_UNTIL(t2);\
779  }\
780  else\
781  {\
782  MEMPTR=MEMPTR+1;\
783  T_WAIT_UNTIL(t1);\
784  }\
785 }
786 
787 #define INIR(t1,t2,rd,wr) \
788 {\
789  Z80EX_BYTE initemp;\
790  READ_PORT(initemp, BC, rd);\
791  WRITE_MEM( HL, initemp, wr);\
792  MEMPTR=BC+1;\
793  B--; HL++;\
794  F = ( initemp & 0x80 ? FLAG_N : 0 ) | sz53_table[B];\
795  if( B ) {\
796  PC -= 2;\
797  T_WAIT_UNTIL(t2);\
798  }\
799  else\
800  {\
801  T_WAIT_UNTIL(t1);\
802  }\
803  IN_BL(initemp,1)\
804 }
805 
806 #define OTIR(t1,t2,rd,wr) \
807 {\
808  Z80EX_BYTE outitemp;\
809  READ_MEM(outitemp, HL, rd);\
810  B--;\
811  MEMPTR=BC+1;\
812  WRITE_PORT(BC, outitemp, wr);\
813  HL++;\
814  F = (outitemp & 0x80 ? FLAG_N : 0 ) | sz53_table[B];\
815  if( B ) {\
816  PC -= 2;\
817  T_WAIT_UNTIL(t2);\
818  }\
819  else\
820  {\
821  T_WAIT_UNTIL(t1);\
822  }\
823  OUT_BL(outitemp);\
824 }
825 
826 #define LDDR(t1,t2,rd,wr) \
827 {\
828  Z80EX_BYTE bytetemp;\
829  READ_MEM(bytetemp, HL, rd);\
830  WRITE_MEM(DE,bytetemp,wr);\
831  HL--; DE--; BC--;\
832  bytetemp += A;\
833  F = ( F & ( FLAG_C | FLAG_Z | FLAG_S ) ) | ( BC ? FLAG_V : 0 ) |\
834  ( bytetemp & FLAG_3 ) | ( (bytetemp & 0x02) ? FLAG_5 : 0 );\
835  if(BC) {\
836  PC-=2;\
837  T_WAIT_UNTIL(t2);\
838  MEMPTR=PC+1;\
839  }\
840  else\
841  {\
842  T_WAIT_UNTIL(t1);\
843  }\
844 }
845 
846 #define CPDR(t1,t2,rd) \
847 {\
848  Z80EX_BYTE value,bytetemp,lookup;\
849  READ_MEM(value, HL, rd);\
850  bytetemp = A - value;\
851  lookup = ( ( A & 0x08 ) >> 3 ) |\
852  ( ( (value) & 0x08 ) >> 2 ) |\
853  ( ( bytetemp & 0x08 ) >> 1 );\
854  HL--; BC--;\
855  F = ( F & FLAG_C ) | ( BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |\
856  halfcarry_sub_table[lookup] | ( bytetemp ? 0 : FLAG_Z ) |\
857  ( bytetemp & FLAG_S );\
858  if(F & FLAG_H) bytetemp--;\
859  F |= ( bytetemp & FLAG_3 ) | ( (bytetemp&0x02) ? FLAG_5 : 0 );\
860  if( ( F & ( FLAG_V | FLAG_Z ) ) == FLAG_V ) {\
861  PC-=2;\
862  MEMPTR=PC+1;\
863  T_WAIT_UNTIL(t2);\
864  }\
865  else\
866  {\
867  MEMPTR=MEMPTR-1;\
868  T_WAIT_UNTIL(t1);\
869  }\
870 }
871 
872 #define INDR(t1,t2,rd,wr) \
873 {\
874  Z80EX_BYTE initemp;\
875  READ_PORT(initemp, BC, rd);\
876  WRITE_MEM( HL, initemp, wr );\
877  MEMPTR=BC-1;\
878  B--; HL--;\
879  F = ( initemp & 0x80 ? FLAG_N : 0 ) | sz53_table[B];\
880  if( B ) {\
881  PC -= 2;\
882  T_WAIT_UNTIL(t2);\
883  }\
884  else\
885  {\
886  T_WAIT_UNTIL(t1);\
887  }\
888  IN_BL(initemp,-1)\
889 }
890 
891 #define OTDR(t1,t2,rd,wr) \
892 {\
893  Z80EX_BYTE outitemp;\
894  READ_MEM(outitemp, HL, rd);\
895  B--;\
896  MEMPTR=BC-1;\
897  WRITE_PORT(BC,outitemp,wr);\
898  HL--;\
899  F = (outitemp & 0x80 ? FLAG_N : 0 ) | sz53_table[B];\
900  if( B ) {\
901  PC -= 2;\
902  T_WAIT_UNTIL(t2);\
903  }\
904  else\
905  {\
906  T_WAIT_UNTIL(t1);\
907  }\
908  OUT_BL(outitemp);\
909 }
910 
911 #define RLCA() \
912 {\
913  A = ( A << 1 ) | ( A >> 7 );\
914  F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |\
915  ( A & ( FLAG_C | FLAG_3 | FLAG_5 ) );\
916 }
917 
918 #define RRCA() \
919 {\
920  F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) | ( A & FLAG_C );\
921  A = ( A >> 1) | ( A << 7 );\
922  F |= ( A & ( FLAG_3 | FLAG_5 ) );\
923 }
924 
925 #define DJNZ(offset, t1, t2) \
926 {\
927  B--;\
928  if(B) {\
929  PC += offset;\
930  MEMPTR=PC;\
931  T_WAIT_UNTIL(t2);\
932  }\
933  else\
934  {\
935  T_WAIT_UNTIL(t1);\
936  }\
937 }
938 
939 #define RLA() \
940 {\
941  Z80EX_BYTE bytetemp = A;\
942  A = ( A << 1 ) | ( F & FLAG_C );\
943  F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |\
944  ( A & ( FLAG_3 | FLAG_5 ) ) | ( bytetemp >> 7 );\
945 }
946 
947 #define RRA() \
948 {\
949  Z80EX_BYTE bytetemp = A;\
950  A = ( A >> 1 ) | ( F << 7 );\
951  F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |\
952  ( A & ( FLAG_3 | FLAG_5 ) ) | ( bytetemp & FLAG_C ) ;\
953 }
954 
955 #define DAA() \
956 {\
957  const Z80EX_BYTE *tdaa = (daatab+(A+0x100*((F & 3) + ((F >> 2) & 4)))*2);\
958  F = *tdaa; A = *(tdaa + 1);\
959 }
960 
961 /* old, non-exact version, from FUSE
962 #define DAA() \
963 {\
964  Z80EX_BYTE add = 0, carry = ( F & FLAG_C );\
965  if( ( F & FLAG_H ) || ( (A & 0x0f)>9 ) ) add=6;\
966  if( carry || (A > 0x9f ) ) add|=0x60;\
967  if( A > 0x99 ) carry=1;\
968  if ( F & FLAG_N ) {\
969  SUB(add);\
970  } else {\
971  if( (A>0x90) && ( (A & 0x0f)>9) ) add|=0x60;\
972  ADD(A, add);\
973  }\
974  F = ( F & ~( FLAG_C | FLAG_P) ) | carry | parity_table[A];\
975 }
976 */
977 
978 #define EX(rp1,rp2) \
979 {\
980  Z80EX_WORD wordtemp=rp1; rp1=rp2; rp2=wordtemp;\
981 }
982 
983 #define EX_MPTR(rp1,rp2) \
984 {\
985  Z80EX_WORD wordtemp=rp1; rp1=rp2; rp2=wordtemp;\
986  MEMPTR=wordtemp;\
987 }
988 
989 #define CPL() \
990 {\
991  A ^= 0xff;\
992  F = ( F & ( FLAG_C | FLAG_P | FLAG_Z | FLAG_S ) ) |\
993  ( A & ( FLAG_3 | FLAG_5 ) ) | ( FLAG_N | FLAG_H );\
994 }
995 
996 #define SCF() \
997 {\
998  F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |\
999  ( A & ( FLAG_3 | FLAG_5 ) ) |\
1000  FLAG_C;\
1001 }
1002 
1003 #define CCF() \
1004 {\
1005  F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |\
1006  ( ( F & FLAG_C ) ? FLAG_H : FLAG_C ) | ( A & ( FLAG_3 | FLAG_5 ) );\
1007 }
1008 
1009 #define HALT() \
1010 {\
1011  z80ex.halted=1;\
1012  PC--;\
1013 }
1014 
1015 #define EXX() \
1016 {\
1017  Z80EX_WORD wordtemp;\
1018  wordtemp = BC; BC = BC_; BC_ = wordtemp;\
1019  wordtemp = DE; DE = DE_; DE_ = wordtemp;\
1020  wordtemp = HL; HL = HL_; HL_ = wordtemp;\
1021 }
1022 
1023 #define DI() \
1024 {\
1025  IFF1=IFF2=0;\
1026 }
1027 
1028 #define EI() \
1029 {\
1030  IFF1 = IFF2 = 1;\
1031  z80ex.noint_once=1;\
1032 }
1033 
1034 #define SET(bit, val) \
1035 {\
1036  val |= (1 << bit);\
1037 }
1038 
1039 #define RES(bit, val) \
1040 {\
1041  val &= ~(1 << bit);\
1042 }
1043 
1044 
1045 #endif