]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/md/z80.c
devcons: fix permissions for reboot and sysstat
[plan9front.git] / sys / src / games / md / z80.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "dat.h"
5 #include "fns.h"
6
7 u8int s[16], ipage, intm, z80irq;
8 u16int ix[2];
9 u16int spc, scurpc, sp;
10 int halt;
11
12 enum {
13         FLAGC = 0x01,
14         FLAGN = 0x02,
15         FLAGV = 0x04,
16         FLAGH = 0x10,
17         FLAGZ = 0x40,
18         FLAGS = 0x80
19 };
20 enum { rB, rC, rD, rE, rH, rL, rHL, rA, rF = rHL };
21 #define BC() (s[rB] << 8 | s[rC])
22 #define DE() (s[rD] << 8 | s[rE])
23 #define HL() (s[rH] << 8 | s[rL])
24
25 static u8int
26 fetch8(void)
27 {
28         return z80read(spc++);
29 }
30
31 static u16int
32 fetch16(void)
33 {
34         u16int u;
35         
36         u = z80read(spc++);
37         return u | z80read(spc++) << 8;
38 }
39
40 static void
41 push8(u8int u)
42 {
43         z80write(--sp, u);
44 }
45
46 static void
47 push16(u16int u)
48 {
49         z80write(--sp, u >> 8);
50         z80write(--sp, u);
51 }
52
53 static u8int
54 pop8(void)
55 {
56         return z80read(sp++);
57 }
58
59 static u16int
60 pop16(void)
61 {
62         u16int v;
63         
64         v = z80read(sp++);
65         return v | z80read(sp++) << 8;
66 }
67
68 static u16int
69 read16(u16int n)
70 {
71         return z80read(n) | z80read(n+1) << 8;
72 }
73
74 static void
75 write16(u16int n, u16int v)
76 {
77         z80write(n++, v);
78         z80write(n, v >> 8);
79 }
80
81 static int
82 parity(u8int v)
83 {
84         return (((v * 0x0101010101010101ULL) & 0x8040201008040201ULL) % 0x1FF) & 1;
85 }
86
87 static int
88 move(u8int dst, u8int src)
89 {
90         if(dst == rHL){
91                 if(src == rHL){
92                         halt = 1;
93                         return 4;
94                 }
95                 z80write(HL(), s[src]);
96                 return 7;
97         }
98         if(src == rHL){
99                 s[dst] = z80read(HL());
100                 return 7;
101         }
102         s[dst] = s[src];
103         return 4;
104 }
105
106 static int
107 alu(u8int op, u8int n)
108 {
109         u8int v4;
110         u8int u;
111         u16int v;
112         int t;
113
114         switch(n){
115         case 8: u = fetch8(); t = 3; break;
116         case 10: u = ix[0]; t = 4; break;
117         case 11: u = ix[1]; t = 4; break;
118         case 12: u = ix[0] >> 8; t = 4; break;
119         case 13: u = ix[1] >> 8; t = 4; break;
120         case 14: u = z80read(ix[0] + fetch8()); t = 15; break;
121         case 15: u = z80read(ix[1] + fetch8()); t = 15; break;
122         case rHL:
123                 u = z80read(HL());
124                 t = 3;
125                 break;
126         default:
127                 u = s[n];
128                 t = 0;
129         }
130         v4 = 0;
131         switch(op){
132         default:
133                 v4 = (s[rA] & 0x0f) + (u & 0x0f);
134                 v = s[rA] + u;
135                 break;
136         case 1:
137                 v4 = (s[rA] & 0x0f) + (u & 0x0f) + (s[rF] & 1);
138                 v = s[rA] + u + (s[rF] & 1);
139                 break;
140         case 2:
141         case 7:
142                 v4 = (s[rA] & 0x0f) + (~u & 0x0f) + 1;
143                 v = s[rA] + (u ^ 0xff) + 1;
144                 break;
145         case 3:
146                 v4 = (s[rA] & 0x0f) + (~u & 0x0f) + (~s[rF] & 1);
147                 v = s[rA] + (u ^ 0xff) + (~s[rF] & 1);
148                 break;
149         case 4: v = s[rA] & u; break;
150         case 5: v = s[rA] ^ u; break;
151         case 6: v = s[rA] | u; break;
152         }
153         s[rF] = 0;
154         if((u8int)v == 0)
155                 s[rF] |= FLAGZ;
156         if((v & 0x80) != 0)
157                 s[rF] |= FLAGS;
158         if(op < 2){
159                 if((v & 0x100) != 0)
160                         s[rF] |= FLAGC;
161                 if((v4 & 0x10) != 0)
162                         s[rF] |= FLAGH;
163                 if((~(s[rA] ^ u) & (s[rA] ^ v) & 0x80) != 0)
164                         s[rF] |= FLAGV;
165         }else if(op < 4 || op == 7){
166                 s[rF] |= FLAGN;
167                 if((v & 0x100) == 0)
168                         s[rF] |= FLAGC;
169                 if((v4 & 0x10) == 0)
170                         s[rF] |= FLAGH;
171                 if(((s[rA] ^ u) & (s[rA] ^ v) & 0x80) != 0)
172                         s[rF] |= FLAGV;
173         }else{
174                 if(!parity(v))
175                         s[rF] |= FLAGV;
176                 if(op == 4)
177                         s[rF] |= FLAGH;
178         }
179         if(op != 7)
180                 s[rA] = v;
181         return 4+t;
182 }
183
184 static int
185 branch(int cc, int t)
186 {
187         u16int v;
188         
189         v = (s8int)fetch8();
190         if(!cc)
191                 return t + 7;
192         spc += v;
193         return t + 12;
194 }
195
196 static u8int
197 inc(u8int v)
198 {
199         s[rF] &= FLAGC;
200         ++v;
201         if(v == 0)
202                 s[rF] |= FLAGZ;
203         if((v & 0x80) != 0)
204                 s[rF] |= FLAGS;
205         if(v == 0x80)
206                 s[rF] |= FLAGV;
207         if((v & 0xf) == 0)
208                 s[rF] |= FLAGH;
209         return v;
210 }
211
212 static u8int
213 dec(u8int v)
214 {
215         --v;
216         s[rF] = s[rF] & FLAGC | FLAGN;
217         if(v == 0)
218                 s[rF] |= FLAGZ;
219         if((v & 0x80) != 0)
220                 s[rF] |= FLAGS;
221         if(v == 0x7f)
222                 s[rF] |= FLAGV;
223         if((v & 0xf) == 0xf)
224                 s[rF] |= FLAGH;
225         return v;
226 }
227
228 static int
229 addhl(u16int u)
230 {
231         u32int v;
232         
233         s[rF] &= ~(FLAGN|FLAGC|FLAGH);
234         v = HL() + u;
235         if((v & 0x10000) != 0)
236                 s[rF] |= FLAGC;
237         if((HL() & 0xfff) + (u & 0xfff) >= 0x1000)
238                 s[rF] |= FLAGH;
239         s[rL] = v;
240         s[rH] = v >> 8;
241         return 11;
242 }
243
244 static void
245 adchl(u16int u)
246 {
247         u32int v, v4;
248         
249         v = HL() + u + (s[rF] & FLAGC);
250         v4 = (HL() & 0xfff) + (u & 0xfff) + (s[rF] & FLAGC);
251         s[rF] = 0;
252         if((v & 0x10000) != 0)
253                 s[rF] |= FLAGC;
254         if((v4 & 0x1000) != 0)
255                 s[rF] |= FLAGH;
256         if((u16int)v == 0)
257                 s[rF] |= FLAGZ;
258         if((v & 0x8000) != 0)
259                 s[rF] |= FLAGS;
260         if((~(HL() ^ u) & (HL() ^ v) & 0x8000) != 0)
261                 s[rF] |= FLAGV;
262         s[rL] = v;
263         s[rH] = v >> 8;
264 }
265
266 static void
267 sbchl(u16int u)
268 {
269         u32int v, v4;
270         
271         v = HL() + (u16int)~u + (~s[rF] & FLAGC);
272         v4 = (HL() & 0xfff) + (~u & 0xfff) + (~s[rF] & FLAGC);
273         s[rF] = FLAGN;
274         if((v & 0x10000) == 0)
275                 s[rF] |= FLAGC;
276         if((v4 & 0x1000) == 0)
277                 s[rF] |= FLAGH;
278         if((u16int)v == 0)
279                 s[rF] |= FLAGZ;
280         if((v & 0x8000) != 0)
281                 s[rF] |= FLAGS;
282         if(((HL() ^ u) & (HL() ^ v) & 0x8000) != 0)
283                 s[rF] |= FLAGV;
284         s[rL] = v;
285         s[rH] = v >> 8;
286 }
287
288 static int
289 addindex(int n, u16int u)
290 {
291         u32int v;
292         
293         s[rF] &= ~(FLAGN|FLAGC|FLAGH);
294         v = ix[n] + u;
295         if((v & 0x10000) != 0)
296                 s[rF] |= FLAGC;
297         if((ix[n] & 0xfff) + (u & 0xfff) >= 0x1000)
298                 s[rF] |= FLAGH;
299         ix[n] = v;
300         return 15;
301 }
302
303 static int
304 jump(int cc)
305 {
306         u16int v;
307         
308         v = fetch16();
309         if(cc)
310                 spc = v;
311         return 10;
312 }
313
314 static int
315 call(u16int a, int cc)
316 {
317         if(!cc)
318                 return 10;
319         push16(spc);
320         spc = a;
321         return 17;
322 }
323
324 static void
325 swap(u8int a)
326 {
327         u8int v;
328         
329         v = s[a];
330         s[a] = s[a + 8];
331         s[a + 8] = v;
332 }
333
334 static int
335 bits(int i)
336 {
337         u8int op, v, n, m, c;
338         u16int a;
339         int t;
340         
341         SET(a, v, t);
342         if(i >= 0){
343                 a = ix[i] + fetch8();
344                 v = z80read(a);
345                 t = 23;
346         }
347         op = fetch8();
348         n = op & 7;
349         m = op >> 3 & 7;
350         if(i < 0){
351                 a = HL();
352                 if(n == 6){
353                         v = z80read(a);
354                         t = 15;
355                 }else{
356                         v = s[n];
357                         t = 8;
358                 }
359         }
360         switch(op >> 6){
361         case 0:
362                 c = s[rF] & FLAGC;
363                 switch(m){
364                 default: s[rF] = v >> 7; v = v << 1 | v >> 7; break;
365                 case 1:  s[rF] = v & 1; v = v >> 1 | v << 7; break;
366                 case 2:  s[rF] = v >> 7; v = v << 1 | c; break;
367                 case 3:  s[rF] = v & 1; v = v >> 1 | c << 7; break;
368                 case 4:  s[rF] = v >> 7; v = v << 1; break;
369                 case 5:  s[rF] = v & 1; v = v & 0x80 | v >> 1; break;
370                 case 6:  s[rF] = v >> 7; v = v << 1 | 1; break;
371                 case 7:  s[rF] = v & 1; v >>= 1; break;
372                 }
373                 if(v == 0)
374                         s[rF] |= FLAGZ;
375                 if((v & 0x80) != 0)
376                         s[rF] |= FLAGS;
377                 if(!parity(v))
378                         s[rF] |= FLAGV;
379                 break;
380         case 1:
381                 s[rF] = s[rF] & ~(FLAGN|FLAGZ) | FLAGH;
382                 if((v & 1<<m) == 0)
383                         s[rF] |= FLAGZ;
384                 return t;
385         case 2:
386                 v &= ~(1<<m);
387                 break;
388         case 3:
389                 v |= (1<<m);
390         }
391         if(n == 6)
392                 z80write(a, v);
393         else
394                 s[n] = v;
395         return t;
396 }
397
398 static int
399 ed(void)
400 {
401         u8int op, v, u, l;
402         u16int a;
403         
404         op = fetch8();
405         switch(op){
406         case 0xa0: case 0xa1: case 0xa8: case 0xa9:
407         case 0xb0: case 0xb1: case 0xb8: case 0xb9:
408                 switch(op & 3){
409                 default:
410                         z80write(DE(), z80read(HL()));
411                         s[rF] &= ~(FLAGN|FLAGH);
412                         l = 1;
413                         break;
414                 case 1:
415                         u = z80read(HL());
416                         v = s[rA] - u;
417                         s[rF] = s[rF] & ~(FLAGS|FLAGZ|FLAGH) | FLAGN;
418                         l = v != 0;
419                         if((v & 0x80) != 0)
420                                 s[rF] |= FLAGS;
421                         if(v == 0)
422                                 s[rF] |= FLAGZ;
423                         if((s[rA] & 0xf) < (u & 0xf))
424                                 s[rF] |= FLAGH;
425                         break;
426                 }
427                 if((op & 8) != 0){
428                         if((op & 3) == 0 && s[rE]-- == 0)
429                                 s[rD]--;
430                         if(s[rL]-- == 0)
431                                 s[rH]--;
432                 }else{
433                         if((op & 3) == 0 && ++s[rE] == 0)
434                                 s[rD]++;
435                         if(++s[rL] == 0)
436                                 s[rH]++;
437                 }
438                 if(s[rC]-- == 0)
439                         s[rB]--;
440                 if((s[rC] | s[rB]) != 0){
441                         s[rF] |= FLAGV;
442                         if((op & 0x10) != 0 && l){
443                                 spc -= 2;
444                                 return 21;
445                         }
446                 }else
447                         s[rF] &= ~FLAGV;
448                 return 16;
449         case 0x42: sbchl(BC()); return 15;
450         case 0x52: sbchl(DE()); return 15;
451         case 0x62: sbchl(HL()); return 15;
452         case 0x72: sbchl(sp); return 15;
453         case 0x43: write16(fetch16(), BC()); return 20;
454         case 0x53: write16(fetch16(), DE()); return 20;
455         case 0x63: write16(fetch16(), HL()); return 20;
456         case 0x73: write16(fetch16(), sp); return 20;
457         case 0x44:
458                 s[rA] = -s[rA];
459                 s[rF] = FLAGN;
460                 if(s[rA] == 0)
461                         s[rF] |= FLAGZ;
462                 else
463                         s[rF] |= FLAGC;
464                 if((s[rA] & 0x80) != 0)
465                         s[rF] |= FLAGS;
466                 if(s[rA] == 0x80)
467                         s[rF] |= FLAGV;
468                 if((s[rA] & 0xf) != 0)
469                         s[rF] |= FLAGH;
470                 return 8;
471         case 0x46: intm &= 0xc0; return 8;
472         case 0x56: intm = intm & 0xc0 | 1; return 8;
473         case 0x47: ipage = s[rA]; return 9;
474         case 0x57: s[rA] = ipage; return 9;
475         case 0x67:
476                 v = z80read(HL());
477                 z80write(HL(), v >> 4 | s[rA] << 4);
478                 s[rA] = s[rA] & 0xf0 | v & 0x0f;
479                 if(0){
480         case 0x6f:
481                         v = z80read(HL());
482                         z80write(HL(), v << 4 | s[rA] & 0xf);
483                         s[rA] = s[rA] & 0xf0 | v >> 4;
484                 }
485                 s[rF] &= FLAGC;
486                 if(s[rA] == 0)
487                         s[rF] |= FLAGZ;
488                 if((s[rA] & 0x80) != 0)
489                         s[rF] |= FLAGS;
490                 if(!parity(s[rA]))
491                         s[rF] |= FLAGV;
492                 return 18;
493         case 0x4a: adchl(BC()); return 15;
494         case 0x5a: adchl(DE()); return 15;
495         case 0x6a: adchl(HL()); return 15;
496         case 0x7a: adchl(sp); return 15;
497         case 0x4b: a = fetch16(); s[rC] = z80read(a++); s[rB] = z80read(a); return 20;
498         case 0x5b: a = fetch16(); s[rE] = z80read(a++); s[rD] = z80read(a); return 20;
499         case 0x6b: a = fetch16(); s[rL] = z80read(a++); s[rH] = z80read(a); return 20;
500         case 0x7b: sp = read16(fetch16()); return 20;
501         case 0x4d: spc = pop16(); return 14;
502         case 0x5e: intm = intm & 0xc0 | 2; return 8;
503         case 0x4f: return 9;
504         }
505         sysfatal("undefined z80 opcode ed%.2x at pc=%#.4x", op, scurpc);
506         return 0;
507 }
508
509 static int
510 index(int n)
511 {
512         u8int op;
513         u16int v;
514         
515         op = fetch8();
516         switch(op){
517         case 0x40: case 0x41: case 0x42: case 0x43: case 0x47:
518         case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4f:
519         case 0x50: case 0x51: case 0x52: case 0x53: case 0x57:
520         case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5f:
521         case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7f:
522                 s[op >> 3 & 7] = s[op & 7];
523                 return 8;
524         case 0x60: case 0x61: case 0x62: case 0x63: case 0x67:
525                 ix[n] = ix[n] & 0xff | s[op & 7] << 8;
526                 return 8;
527         case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6f:
528                 ix[n] = ix[n] & 0xff00 | s[op & 7];
529                 return 8;
530         case 0x65: ix[n] = ix[n] << 8 | ix[n] & 0xff; return 8;
531         case 0x6c: ix[n] = ix[n] >> 8 | ix[n] & 0xff00; return 8;
532         case 0x64: case 0x6d: return 8;
533         case 0x70: case 0x71: case 0x72: case 0x73:
534         case 0x74: case 0x75: case 0x77:
535                 z80write(ix[n] + fetch8(), s[op & 7]);
536                 return 19;
537         case 0x44: case 0x4c: case 0x54: case 0x5c: case 0x7c:
538                 s[op >> 3 & 7] = ix[n] >> 8;
539                 return 8;
540         case 0x45: case 0x4d: case 0x55: case 0x5d: case 0x7d:
541                 s[op >> 3 & 7] = ix[n];
542                 return 8;
543         case 0x46: case 0x4e: case 0x56: case 0x5e: case 0x66: case 0x6e: case 0x7e:
544                 s[op >> 3 & 7] = z80read(ix[n] + fetch8());
545                 return 19;
546         case 0x84: case 0x8c: case 0x94: case 0x9c:
547         case 0xa4: case 0xac: case 0xb4: case 0xbc:
548                 return alu(op >> 3 & 7, 12 + n);
549         case 0x85: case 0x8d: case 0x95: case 0x9d:
550         case 0xa5: case 0xad: case 0xb5: case 0xbd:
551                 return alu(op >> 3 & 7, 10 + n);
552         case 0x86: case 0x8e: case 0x96: case 0x9e:
553         case 0xa6: case 0xae: case 0xb6: case 0xbe:
554                 return alu(op >> 3 & 7, 14 + n);        
555         
556         case 0x21: ix[n] = fetch16(); return 14;
557         case 0xe1: ix[n] = pop16(); return 14;
558         case 0x22: write16(fetch16(), ix[n]); return 20;
559         case 0x23: ix[n]++; return 10;
560         case 0xe3: v = ix[n]; ix[n] = read16(sp); write16(sp, v); return 23;
561         case 0x24: inc(ix[n] >> 8); ix[n] += 0x100; return 8;
562         case 0x34: v = ix[n] + fetch8(); z80write(v, inc(z80read(v))); return 23;
563         case 0x25: dec(ix[n] >> 8); ix[n] -= 0x100; return 8;
564         case 0x35: v = ix[n] + fetch8(); z80write(v, dec(z80read(v))); return 23;
565         case 0xe5: push16(ix[n]); return 15;
566         case 0x26: ix[n] = ix[n] & 0xff | fetch8() << 8; return 11;
567         case 0x36: v = ix[n] + fetch8(); z80write(v, fetch8()); return 19;
568         case 0x09: return addindex(n, BC());
569         case 0x19: return addindex(n, DE());
570         case 0x29: return addindex(n, ix[n]);
571         case 0x39: return addindex(n, sp);
572         case 0xe9: spc = ix[n]; return 8;
573         case 0xf9: sp = ix[n]; return 10;
574         case 0x2a: ix[n] = read16(fetch16()); return 20;
575         case 0x2b: ix[n]--; return 10;
576         case 0xcb: return bits(n);
577         case 0x2c: inc(ix[n]++); return 8;
578         case 0x2d: dec(ix[n]--); return 8;
579         case 0x2e: ix[n] = ix[n] & 0xff00 | fetch8(); return 11;
580         }
581         sysfatal("undefined z80 opcode %.2x%.2x at pc=%#.4x", n ? 0xfd : 0xdd, op, scurpc);
582         return 0;
583 }
584
585 int
586 z80step(void)
587 {
588         u8int op;
589         u16int v, w;
590
591         if((z80bus & RESET) != 0){
592                 scurpc = spc = 0;
593                 intm = 0;
594                 ipage = 0;
595                 return 1;
596         }
597         if((z80bus & BUSACK) != 0){
598                 if((z80bus & BUSREQ) == 0)
599                         z80bus &= ~BUSACK;
600                 return 1;
601         }
602         if((z80bus & BUSREQ) != 0){
603                 z80bus |= BUSACK;
604                 return 1;
605         }
606         if(z80irq != 0 && (intm & 0x80) != 0){
607                 push16(spc);
608                 intm &= 0x3f;
609                 switch(intm & 3){
610                 case 1:
611                         spc = 0x38;
612                         return 2;
613                 default:
614                         sysfatal("z80 interrupt in mode %d", intm & 3);
615                 }
616         }
617         scurpc = spc;
618         if(0)
619                 print("%x AF %.2x%.2x BC %.2x%.2x DE %.2x%.2x HL %.2x%.2x IX %.4x IY %.4x\n", scurpc, s[rA], s[rF], s[rB], s[rC], s[rD], s[rE], s[rH], s[rL], ix[0], ix[1]);
620         op = fetch8();
621         switch(op >> 6){
622         case 1: return move(op >> 3 & 7, op & 7);
623         case 2: return alu(op >> 3 & 7, op & 7);
624         }
625         switch(op){
626         case 0x00: return 4;
627         case 0x10: return branch(--s[rB] != 0, 1);
628         case 0x20: return branch((s[rF] & FLAGZ) == 0, 0);
629         case 0x30: return branch((s[rF] & FLAGC) == 0, 0);
630         case 0x01: s[rC] = fetch8(); s[rB] = fetch8(); return 10;
631         case 0x11: s[rE] = fetch8(); s[rD] = fetch8(); return 10;
632         case 0x21: s[rL] = fetch8(); s[rH] = fetch8(); return 10;
633         case 0x31: sp = fetch16(); return 10;
634         case 0x02: z80write(BC(), s[rA]); return 7;
635         case 0x12: z80write(DE(), s[rA]); return 7;
636         case 0x22: v = fetch16(); z80write(v++, s[rL]); z80write(v, s[rH]); return 16;
637         case 0x32: z80write(fetch16(), s[rA]); return 13;
638         case 0x03: if(++s[rC] == 0) s[rB]++; return 6;
639         case 0x13: if(++s[rE] == 0) s[rD]++; return 6;
640         case 0x23: if(++s[rL] == 0) s[rH]++; return 6;
641         case 0x33: sp++; return 6;
642         case 0x04: inc(s[rB]++); return 4;
643         case 0x14: inc(s[rD]++); return 4;
644         case 0x24: inc(s[rH]++); return 4;
645         case 0x34: z80write(HL(), inc(z80read(HL()))); return 11;
646         case 0x05: dec(s[rB]--); return 4;
647         case 0x15: dec(s[rD]--); return 4;
648         case 0x25: dec(s[rH]--); return 4;
649         case 0x35: z80write(HL(), dec(z80read(HL()))); return 11;
650         case 0x06: s[rB] = fetch8(); return 7;
651         case 0x16: s[rD] = fetch8(); return 7;
652         case 0x26: s[rH] = fetch8(); return 7;
653         case 0x36: z80write(HL(), fetch8()); return 10;
654         case 0x07:
655                 s[rF] = s[rF] & ~(FLAGC|FLAGN|FLAGH) | s[rA] >> 7;
656                 s[rA] = s[rA] << 1 | s[rA] >> 7;
657                 return 4;
658         case 0x17:
659                 v = s[rF] & FLAGC;
660                 s[rF] = s[rF] & ~(FLAGC|FLAGN|FLAGH) | s[rA] >> 7;
661                 s[rA] = s[rA] << 1 | v;
662                 return 4;
663         case 0x27:
664                 if(s[rA] > 0x99 || (s[rF] & FLAGC) != 0){
665                         s[rF] |= FLAGC;
666                         v = 0x60;
667                 }else{
668                         s[rF] &= ~FLAGC;
669                         v = 0;
670                 }
671                 if((s[rA] & 0xf) > 9 || (s[rF] & FLAGH) != 0)
672                         v |= 6;
673                 w = s[rA];
674                 if((s[rF] & FLAGN) != 0)
675                         s[rA] -= v;
676                 else
677                         s[rA] += v;
678                 s[rF] &= ~(FLAGV|FLAGS|FLAGZ|FLAGH);
679                 if(((s[rA] ^ w) & 0x10) != 0)
680                         s[rF] |= FLAGH;
681                 if(!parity(s[rA]))
682                         s[rF] |= FLAGV;
683                 if(s[rA] == 0)
684                         s[rF] |= FLAGZ;
685                 if((s[rA] & 0x80) != 0)
686                         s[rF] |= FLAGS;
687                 return 4;
688         case 0x37: s[rF] = s[rF] & ~(FLAGN | FLAGH) | FLAGC; return 4;
689         case 0x08:
690                 swap(rA);
691                 swap(rF);
692                 return 4;
693         case 0x18: return branch(1, 0);
694         case 0x28: return branch((s[rF] & FLAGZ) != 0, 0);
695         case 0x38: return branch((s[rF] & FLAGC) != 0, 0);
696         case 0x09: return addhl(BC());
697         case 0x19: return addhl(DE());
698         case 0x29: return addhl(HL());
699         case 0x39: return addhl(sp);
700         case 0x0a: s[rA] = z80read(BC()); return 7;
701         case 0x1a: s[rA] = z80read(DE()); return 7;
702         case 0x2a: v = fetch16(); s[rL] = z80read(v++); s[rH] = z80read(v); return 16;
703         case 0x3a: s[rA] = z80read(fetch16()); return 13;
704         case 0x0b: if(s[rC]-- == 0) s[rB]--; return 6;
705         case 0x1b: if(s[rE]-- == 0) s[rD]--; return 6;
706         case 0x2b: if(s[rL]-- == 0) s[rH]--; return 6;
707         case 0x3b: sp--; return 6;
708         case 0x0c: inc(s[rC]++); return 4;
709         case 0x1c: inc(s[rE]++); return 4;
710         case 0x2c: inc(s[rL]++); return 4;
711         case 0x3c: inc(s[rA]++); return 4;
712         case 0x0d: dec(s[rC]--); return 4;
713         case 0x1d: dec(s[rE]--); return 4;
714         case 0x2d: dec(s[rL]--); return 4;
715         case 0x3d: dec(s[rA]--); return 4;
716         case 0x0e: s[rC] = fetch8(); return 7;
717         case 0x1e: s[rE] = fetch8(); return 7;
718         case 0x2e: s[rL] = fetch8(); return 7;
719         case 0x3e: s[rA] = fetch8(); return 7;
720         case 0x0f:
721                 s[rF] = s[rF] & ~(FLAGC|FLAGN|FLAGH) | s[rA] & 1;
722                 s[rA] = s[rA] >> 1 | s[rA] << 7;
723                 return 4;
724         case 0x1f:
725                 v = s[rF] << 7;
726                 s[rF] = s[rF] & ~(FLAGC|FLAGN|FLAGH) | s[rA] & 1;
727                 s[rA] = s[rA] >> 1 | v;
728                 return 4;
729         case 0x2f:
730                 s[rF] |= FLAGN|FLAGH;
731                 s[rA] ^= 0xff;
732                 return 4;
733         case 0x3f:
734                 s[rF] = s[rF] & ~(FLAGN|FLAGH) ^ FLAGC | s[rF] << 4 & FLAGH;
735                 return 4;
736         case 0xc0: if((s[rF] & FLAGZ) == 0) {spc = pop16(); return 11;} return 5;
737         case 0xd0: if((s[rF] & FLAGC) == 0) {spc = pop16(); return 11;} return 5;
738         case 0xe0: if((s[rF] & FLAGV) == 0) {spc = pop16(); return 11;} return 5;
739         case 0xf0: if((s[rF] & FLAGS) == 0) {spc = pop16(); return 11;} return 5;
740         case 0xc1: s[rC] = pop8(); s[rB] = pop8(); return 10;
741         case 0xd1: s[rE] = pop8(); s[rD] = pop8(); return 10;
742         case 0xe1: s[rL] = pop8(); s[rH] = pop8(); return 10;
743         case 0xf1: s[rF] = pop8(); s[rA] = pop8(); return 10;
744         case 0xc2: return jump((s[rF] & FLAGZ) == 0);
745         case 0xd2: return jump((s[rF] & FLAGC) == 0);
746         case 0xe2: return jump((s[rF] & FLAGV) == 0);
747         case 0xf2: return jump((s[rF] & FLAGS) == 0);
748         case 0xc3: return jump(1);
749         case 0xd3: z80out(fetch8(), s[rA]); return 11;
750         case 0xe3:
751                 v = HL();
752                 s[rL] = z80read(sp);
753                 s[rH] = z80read(sp + 1);
754                 write16(sp, v);
755                 return 19;
756         case 0xf3: intm &= 0x3f; return 4;
757         case 0xc4: return call(fetch16(), (s[rF] & FLAGZ) == 0);
758         case 0xd4: return call(fetch16(), (s[rF] & FLAGC) == 0);
759         case 0xe4: return call(fetch16(), (s[rF] & FLAGV) == 0);
760         case 0xf4: return call(fetch16(), (s[rF] & FLAGS) == 0);
761         case 0xc5: push8(s[rB]); push8(s[rC]); return 11;
762         case 0xd5: push8(s[rD]); push8(s[rE]); return 11;
763         case 0xe5: push8(s[rH]); push8(s[rL]); return 11;
764         case 0xf5: push8(s[rA]); push8(s[rF]); return 11;
765         case 0xc6: return alu(0, 8);
766         case 0xd6: return alu(2, 8);
767         case 0xe6: return alu(4, 8);
768         case 0xf6: return alu(6, 8);
769         case 0xc7: return call(0x00, 1);
770         case 0xd7: return call(0x10, 1);
771         case 0xe7: return call(0x20, 1);
772         case 0xf7: return call(0x30, 1);
773         case 0xc8: if((s[rF] & FLAGZ) != 0) {spc = pop16(); return 11;} return 5;
774         case 0xd8: if((s[rF] & FLAGC) != 0) {spc = pop16(); return 11;} return 5;
775         case 0xe8: if((s[rF] & FLAGV) != 0) {spc = pop16(); return 11;} return 5;
776         case 0xf8: if((s[rF] & FLAGS) != 0) {spc = pop16(); return 11;} return 5;
777         case 0xc9: spc = pop16(); return 10;
778         case 0xd9:
779                 swap(rB);
780                 swap(rC);
781                 swap(rD);
782                 swap(rE);
783                 swap(rH);
784                 swap(rL);
785                 return 4;
786         case 0xe9: spc = HL(); return 4;
787         case 0xf9: sp = HL(); return 6;
788         case 0xca: return jump((s[rF] & FLAGZ) != 0);
789         case 0xda: return jump((s[rF] & FLAGC) != 0);
790         case 0xea: return jump((s[rF] & FLAGV) != 0);
791         case 0xfa: return jump((s[rF] & FLAGS) != 0);
792         case 0xcb: return bits(-1);
793         case 0xdb: s[rA] = z80in(fetch8()); return 11;
794         case 0xeb:
795                 v = DE();
796                 s[rD] = s[rH];
797                 s[rE] = s[rL];
798                 s[rH] = v >> 8;
799                 s[rL] = v;
800                 return 4;
801         case 0xfb: intm |= 0xc0; return 4;
802         case 0xcc: return call(fetch16(), (s[rF] & FLAGZ) != 0);
803         case 0xdc: return call(fetch16(), (s[rF] & FLAGC) != 0);
804         case 0xec: return call(fetch16(), (s[rF] & FLAGV) != 0);
805         case 0xfc: return call(fetch16(), (s[rF] & FLAGS) != 0);
806         case 0xcd: return call(fetch16(), 1);
807         case 0xdd: return index(0);
808         case 0xed: return ed();
809         case 0xfd: return index(1);
810         case 0xce: return alu(1, 8);
811         case 0xde: return alu(3, 8);
812         case 0xee: return alu(5, 8);
813         case 0xfe: return alu(7, 8);
814         case 0xcf: return call(0x08, 1);
815         case 0xdf: return call(0x18, 1);
816         case 0xef: return call(0x28, 1);
817         case 0xff: return call(0x38, 1);
818         }
819         sysfatal("undefined z80 opcode %#.2x at pc=%#.4x", op, scurpc);
820         return 0;
821 }