1 /* Emulations of the ED operations of the Z80 instruction set.
2  * Copyright (C) 1994 Ian Collier.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 #define input(var) {  unsigned short u;\
20                       var=u=in(b,c);\
21                       tstates+=u>>8;\
22                       f=(f&1)|(var&0xa8)|((!var)<<6)|parity(var);\
23                    }
24 #define sbchl(x) {    unsigned short z=(x);\
25                       unsigned long t=(hl-z-cy)&0x1ffff;\
26                       f=((t>>8)&0xa8)|(t>>16)|2|\
27                         (((hl&0xfff)<(z&0xfff)+cy)<<4)|\
28                         (((hl^z)&(hl^t)&0x8000)>>13)|\
29                         ((!(t&0xffff))<<6)|2;\
30                       l=t;\
31                       h=t>>8;\
32                    }
33 
34 #define adchl(x) {    unsigned short z=(x);\
35                       unsigned long t=hl+z+cy;\
36                       f=((t>>8)&0xa8)|(t>>16)|\
37                         (((hl&0xfff)+(z&0xfff)+cy>0xfff)<<4)|\
38                         (((~hl^z)&(hl^t)&0x8000)>>13)|\
39                         ((!(t&0xffff))<<6)|2;\
40                       l=t;\
41                       h=t>>8;\
42                  }
43 
44 #define neg (a=-a,\
45             f=(a&0xa8)|((!a)<<6)|(((a&15)>0)<<4)|((a==128)<<2)|2|(a>0))
46 
47 {
48    unsigned char op=fetch(pc);
49    pc++;
50    radjust++;
51    switch(op){
52 instr(0x40,8);
53    input(b);
54 endinstr;
55 
56 instr(0x41,8);
57    tstates+=out(b,c,b);
58 endinstr;
59 
60 instr(0x42,11);
61    sbchl(bc);
62 endinstr;
63 
64 instr(0x43,16);
65    {unsigned short addr=fetch2(pc);
66     pc+=2;
67     store2b(addr,b,c);
68    }
69 endinstr;
70 
71 instr(0x44,4);
72    neg;
73 endinstr;
74 
75 instr(0x45,4);
76    iff1=iff2;
77    ret;
78 endinstr;
79 
80 instr(0x46,4);
81    im=0;
82 endinstr;
83 
84 instr(0x47,5);
85    i=a;
86 endinstr;
87 
88 instr(0x48,8);
89    input(c);
90 endinstr;
91 
92 instr(0x49,8);
93    tstates+=out(b,c,c);
94 endinstr;
95 
96 instr(0x4a,11);
97    adchl(bc);
98 endinstr;
99 
100 instr(0x4b,16);
101    {unsigned short addr=fetch2(pc);
102     pc+=2;
103     c=fetch(addr);
104     b=fetch(addr+1);
105    }
106 endinstr;
107 
108 instr(0x4c,4);
109    neg;
110 endinstr;
111 
112 instr(0x4d,4);
113    ret;
114 endinstr;
115 
116 instr(0x4e,4);
117    im=1;
118 endinstr;
119 
120 instr(0x4f,5);
121    r=a;
122    radjust=r;
123 endinstr;
124 
125 instr(0x50,8);
126    input(d);
127 endinstr;
128 
129 instr(0x51,8);
130    tstates+=out(b,c,d);
131 endinstr;
132 
133 instr(0x52,11);
134    sbchl(de);
135 endinstr;
136 
137 instr(0x53,16);
138    {unsigned short addr=fetch2(pc);
139     pc+=2;
140     store2b(addr,d,e);
141    }
142 endinstr;
143 
144 instr(0x54,4);
145    neg;
146 endinstr;
147 
148 instr(0x55,4);
149    ret;
150 endinstr;
151 
152 instr(0x56,4);
153    im=2;
154 endinstr;
155 
156 instr(0x57,5);
157    a=i;
158    f=(f&1)|(a&0xa8)|((!a)<<6)|(iff2<<2);
159 endinstr;
160 
161 instr(0x58,8);
162    input(e);
163 endinstr;
164 
165 instr(0x59,8);
166    tstates+=out(b,c,e);
167 endinstr;
168 
169 instr(0x5a,11);
170    adchl(de);
171 endinstr;
172 
173 instr(0x5b,16);
174    {unsigned short addr=fetch2(pc);
175     pc+=2;
176     e=fetch(addr);
177     d=fetch(addr+1);
178    }
179 endinstr;
180 
181 instr(0x5c,4);
182    neg;
183 endinstr;
184 
185 instr(0x5d,4);
186    ret;
187 endinstr;
188 
189 instr(0x5e,4);
190    im=3;
191 endinstr;
192 
193 instr(0x5f,5);
194    r=(r&0x80)|(radjust&0x7f);
195    a=r;
196    f=(f&1)|(a&0xa8)|((!a)<<6)|(iff2<<2);
197 endinstr;
198 
199 instr(0x60,8);
200    input(h);
201 endinstr;
202 
203 instr(0x61,8);
204    tstates+=out(b,c,h);
205 endinstr;
206 
207 instr(0x62,11);
208    sbchl(hl);
209 endinstr;
210 
211 instr(0x63,16);
212    {unsigned short addr=fetch2(pc);
213     pc+=2;
214     store2b(addr,h,l);
215    }
216 endinstr;
217 
218 instr(0x64,4);
219    neg;
220 endinstr;
221 
222 instr(0x65,4);
223    ret;
224 endinstr;
225 
226 instr(0x66,4);
227    im=0;
228 endinstr;
229 
230 instr(0x67,14);
231    {unsigned char t=fetch(hl);
232     unsigned char u=(a<<4)|(t>>4);
233     a=(a&0xf0)|(t&0x0f);
234     store(hl,u);
235     f=(f&1)|(a&0xa8)|((!a)<<6)|parity(a);
236    }
237 endinstr;
238 
239 instr(0x68,8);
240    input(l);
241 endinstr;
242 
243 instr(0x69,8);
244    tstates+=out(b,c,l);
245 endinstr;
246 
247 instr(0x6a,11);
248    adchl(hl);
249 endinstr;
250 
251 instr(0x6b,16);
252    {unsigned short addr=fetch2(pc);
253     pc+=2;
254     l=fetch(addr);
255     h=fetch(addr+1);
256    }
257 endinstr;
258 
259 instr(0x6c,4);
260    neg;
261 endinstr;
262 
263 instr(0x6d,4);
264    ret;
265 endinstr;
266 
267 instr(0x6e,4);
268    im=1;
269 endinstr;
270 
271 instr(0x6f,5);
272    {unsigned char t=fetch(hl);
273     unsigned char u=(a&0x0f)|(t<<4);
274     a=(a&0xf0)|(t>>4);
275     store(hl,u);
276     f=(f&1)|(a&0xa8)|((!a)<<6)|parity(a);
277    }
278 endinstr;
279 
280 instr(0x70,8);
281    {unsigned char x;input(x);}
282 endinstr;
283 
284 instr(0x71,8);
285    tstates+=out(b,c,0);
286 endinstr;
287 
288 instr(0x72,11);
289    sbchl(sp);
290 endinstr;
291 
292 instr(0x73,16);
293    {unsigned short addr=fetch2(pc);
294     pc+=2;
295     store2(addr,sp);
296    }
297 endinstr;
298 
299 instr(0x74,4);
300    neg;
301 endinstr;
302 
303 instr(0x75,4);
304    ret;
305 endinstr;
306 
307 instr(0x76,4);
308    im=2;
309 endinstr;
310 
311 instr(0x78,8);
312    input(a);
313 endinstr;
314 
315 instr(0x79,8);
316    tstates+=out(b,c,a);
317 endinstr;
318 
319 instr(0x7a,11);
320    adchl(sp);
321 endinstr;
322 
323 instr(0x7b,16);
324    {unsigned short addr=fetch2(pc);
325     pc+=2;
326     sp=fetch2(addr);
327    }
328 endinstr;
329 
330 instr(0x7c,4);
331    neg;
332 endinstr;
333 
334 instr(0x7d,4);
335    ret;
336 endinstr;
337 
338 instr(0x7e,4);
339    im=3;
340 endinstr;
341 
342 instr(0xa0,12);
343    {unsigned char x=fetch(hl);
344     store(de,x);
345     if(!++l)h++;
346     if(!++e)d++;
347     if(!c--)b--;
348     f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
349    }
350 endinstr;
351 
352 instr(0xa1,12);
353    {unsigned char carry=cy;
354     cpa(fetch(hl));
355     if(!++l)h++;
356     if(!c--)b--;
357     f=(f&0xfa)|carry|(((b|c)>0)<<2);
358    }
359 endinstr;
360 
361 instr(0xa2,12);
362    {unsigned short t=in(b,c);
363     store(hl,t);
364     tstates+=t>>8;
365     if(!++l)h++;
366     b--;
367     f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c)&4);
368    }
369 endinstr;
370 
371 instr(0xa3,12); /* I can't determine the correct flags outcome for the
372                    block OUT instructions.  Spec says that the carry
373                    flag is left unchanged and N is set to 1, but that
374                    doesn't seem to be the case... */
375    {unsigned char x=fetch(hl);
376     tstates+=out(b,c,x);
377     if(!++l)h++;
378     b--;
379     f=(f&1)|0x12|(b&0xa8)|((b==0)<<6);
380    }
381 endinstr;
382 
383 instr(0xa8,12);
384    {unsigned char x=fetch(hl);
385     store(de,x);
386     if(!l--)h--;
387     if(!e--)d--;
388     if(!c--)b--;
389     f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
390    }
391 endinstr;
392 
393 instr(0xa9,12);
394    {unsigned char carry=cy;
395     cpa(fetch(hl));
396     if(!l--)h--;
397     if(!c--)b--;
398     f=(f&0xfa)|carry|(((b|c)>0)<<2);
399    }
400 endinstr;
401 
402 instr(0xaa,12);
403    {unsigned short t=in(b,c);
404     store(hl,t);
405     tstates+=t>>8;
406     if(!l--)h--;
407     b--;
408     f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c^4)&4);
409    }
410 endinstr;
411 
412 instr(0xab,12);
413    {unsigned char x=fetch(hl);
414     tstates+=out(b,c,x);
415     if(!l--)h--;
416     b--;
417     f=(f&1)|0x12|(b&0xa8)|((b==0)<<6);
418    }
419 endinstr;
420 
421 /* Note: the Z80 implements "*R" as "*" followed by JR -2.  No reason
422    to change this... */
423 
424 instr(0xb0,12);
425    {unsigned char x=fetch(hl);
426     store(de,x);
427     if(!++l)h++;
428     if(!++e)d++;
429     if(!c--)b--;
430     f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
431     if(b|c)pc-=2,tstates+=5;
432    }
433 endinstr;
434 
435 instr(0xb1,12);
436    {unsigned char carry=cy;
437     cpa(fetch(hl));
438     if(!++l)h++;
439     if(!c--)b--;
440     f=(f&0xfa)|carry|(((b|c)>0)<<2);
441     if((f&0x44)==4)pc-=2,tstates+=5;
442    }
443 endinstr;
444 
445 instr(0xb2,12);
446    {unsigned short t=in(b,c);
447     store(hl,t);
448     tstates+=t>>8;
449     if(!++l)h++;
450     b--;
451     f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c)&4);
452     if(b)pc-=2,tstates+=5;
453    }
454 endinstr;
455 
456 instr(0xb3,12);
457    {unsigned char x=fetch(hl);
458     tstates+=out(b,c,x);
459     if(!++l)h++;
460     b--;
461     f=(f&1)|0x12|(b&0xa8)|((b==0)<<6);
462     if(b)pc-=2,tstates+=5;
463    }
464 endinstr;
465 
466 instr(0xb8,12);
467    {unsigned char x=fetch(hl);
468     store(de,x);
469     if(!l--)h--;
470     if(!e--)d--;
471     if(!c--)b--;
472     f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
473     if(b|c)pc-=2,tstates+=5;
474    }
475 endinstr;
476 
477 instr(0xb9,12);
478    {unsigned char carry=cy;
479     cpa(fetch(hl));
480     if(!l--)h--;
481     if(!c--)b--;
482     f=(f&0xfa)|carry|(((b|c)>0)<<2);
483     if((f&0x44)==4)pc-=2,tstates+=5;
484    }
485 endinstr;
486 
487 instr(0xba,12);
488    {unsigned short t=in(b,c);
489     store(hl,t);
490     tstates+=t>>8;
491     if(!l--)h--;
492     b--;
493     f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c^4)&4);
494     if(b)pc-=2,tstates+=5;
495    }
496 endinstr;
497 
498 instr(0xbb,12);
499    {unsigned char x=fetch(hl);
500     tstates+=out(b,c,x);
501     if(!l--)h--;
502     b--;
503     f=(f&1)|0x12|(b&0xa8)|((b==0)<<6);
504     if(b)pc-=2,tstates+=5;
505    }
506 endinstr;
507 
508 default: tstates+=4;
509 
510 }}
511