]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/md/cpu.c
8a7e8db86e22811517af591947ad5472d7a1c3f5
[plan9front.git] / sys / src / games / md / cpu.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "dat.h"
5 #include "fns.h"
6
7 enum {
8         FLAGS = 1<<13,
9         FLAGX = 16,
10         FLAGN = 8,
11         FLAGZ = 4,
12         FLAGV = 2,
13         FLAGC = 1,
14 };
15
16 u32int r[16], pc, curpc;
17 u32int asp, irq, stop;
18 extern u32int irql[8];
19 u32int irqla[8];
20 u16int rS;
21 static u32int op;
22 int trace, tim;
23 #define ra (r+8)
24
25 static void
26 undef(void)
27 {
28         sysfatal("undefined opcode %#o at pc=%#.6x", op, curpc);
29 }
30
31 static u16int
32 fetch16(void)
33 {
34         u16int v;
35         
36         v = memread(pc);
37         pc += 2;
38         return v;
39 }
40
41 static u32int
42 fetch32(void)
43 {
44         u32int v;
45         
46         v = fetch16() << 16;
47         return v | fetch16();
48 }
49
50 static void
51 push16(u16int u)
52 {
53         ra[7] -= 2;
54         memwrite(ra[7], u, -1);
55 }
56
57 static u16int
58 pop16(void)
59 {
60         u16int v;
61         
62         v = memread(ra[7]);
63         ra[7] += 2;
64         return v;
65 }
66
67 static void
68 push32(u32int u)
69 {
70         ra[7] -= 4;
71         memwrite(ra[7], u >> 16, -1);
72         memwrite(ra[7] + 2, u, -1);
73 }
74
75 static u32int
76 pop32(void)
77 {
78         u32int v;
79         v = memread(ra[7]) << 16;
80         v |= memread(ra[7] + 2);
81         ra[7] += 4;
82         return v;
83 }
84
85 static vlong
86 amode(int m, int n, int s)
87 {
88         u16int w;
89         u32int v;
90         
91         m &= 7;
92         n &= 7;
93         s &= 3;
94         if(n == 7 && s == 0)
95                 s++;
96         switch(m){
97         case 0:
98                 return ~n;
99         case 1:
100                 return ~(n+8);
101         case 2:
102                 tim += s == 2 ? 8 : 4;
103                 return ra[n];
104         case 3:
105                 v = ra[n];
106                 ra[n] += 1<<s;
107                 tim += s == 2 ? 8 : 4;
108                 return v;
109         case 4:
110                 tim += s == 2 ? 10 : 6;
111                 return ra[n] -= 1<<s;
112         case 5:
113                 tim += s == 2 ? 12 : 8;
114                 return (u32int)(ra[n] + (s16int)fetch16());
115         case 6:
116                 tim += s == 2 ? 14 : 10;
117                 w = fetch16();
118                 v = r[w >> 12];
119                 if((w & 1<<11) == 0)
120                         v = (s16int)v;
121                 return (u32int)(ra[n] + v + (s8int)w);
122         case 7:
123                 switch(n){
124                 case 0:
125                         tim += s == 2 ? 12 : 8;
126                         return (u32int)(s16int)fetch16();
127                 case 1:
128                         tim += s == 2 ? 16 : 12;
129                         return fetch32();
130                 case 2:
131                         tim += s == 2 ? 12 : 8;
132                         v = fetch16();
133                         return (u32int)(pc + (s16int)v - 2);
134                 case 3:
135                         tim += s == 2 ? 14 : 4;
136                         w = fetch16();
137                         v = r[w >> 12];
138                         if((w & 1<<11) == 0)
139                                 v = (s16int)v;
140                         return (u32int)(pc + v + (s8int)w - 2);
141                 case 4:
142                         tim += s == 2 ? 8 : 4;
143                         v = pc;
144                         pc += 1<<s;
145                         if(s == 0)
146                                 v = pc++;
147                         return v;
148                 default:
149                         undef();
150                 }
151         default:
152                 undef();
153         }
154         return 0;
155 }
156
157 static u32int
158 rmode(vlong a, int s)
159 {
160         u32int v;
161
162         if(a >= 0){
163                 switch(s & 3){
164                 case 0:
165                         v = memread(a);
166                         if((a & 1) == 0)
167                                 v >>= 8;
168                         return (s8int) v;
169                 default:
170                         return (s16int) memread(a);
171                 case 2:
172                         v = memread(a) << 16;
173                         return v | memread(a + 2);
174                 }
175         }
176         v = r[~a];
177         switch(s & 3){
178         case 0: return (s8int) v;
179         case 1: return (s16int) v;
180         default: return v;
181         }
182 }
183
184 static void
185 wmode(vlong a, int s, u32int v)
186 {
187         int n;
188
189         if(a >= 0){
190                 switch(s & 3){
191                 case 0:
192                         memwrite(a, (u8int)v | (u8int)v << 8, (a & 1) != 0 ? 0xff : 0xff00);
193                         return;
194                 default:
195                         memwrite(a, v, -1);
196                         return;
197                 case 2:
198                         memwrite(a, v >> 16, -1);
199                         memwrite(a + 2, v, -1);
200                         return;
201                 }
202         }
203         n = ~a;
204         if(n < 8){
205                 switch(s){
206                 case 0: r[n] = r[n] & 0xffffff00 | v & 0xff; break;
207                 case 1: r[n] = r[n] & 0xffff0000 | v & 0xffff; break;
208                 default: r[n] = v;
209                 }
210         }else{
211                 if(s == 1)
212                         v = (s16int) v;
213                 r[n] = v;
214         }
215 }
216
217 static void
218 nz(u32int v, int s)
219 {
220         switch(s){
221         case 0: v = (s8int) v; break;
222         case 1: v = (s16int) v; break;
223         }
224         rS &= ~(FLAGC|FLAGN|FLAGV|FLAGZ);
225         if(v == 0)
226                 rS |= FLAGZ;
227         if((s32int)v < 0)
228                 rS |= FLAGN;
229 }
230
231 static u32int
232 add(u32int u, u32int w, int c, int s)
233 {
234         u64int v;
235
236         rS &= ~(FLAGN|FLAGV|FLAGC);
237         switch(s){
238         case 0:
239                 v = (u8int)w + (u8int)u + c;
240                 if(v >= 0x100)
241                         rS |= FLAGC;
242                 if((v & 0x80) != 0)
243                         rS |= FLAGN;
244                 if((~(w ^ u) & (v ^ u) & 0x80) != 0)
245                         rS |= FLAGV;
246                 if((u8int)v != 0)
247                         rS &= ~FLAGZ;
248                 break;
249         case 1:
250                 v = (u16int)w + (u16int)u + c;
251                 if(v >= 0x10000)
252                         rS |= FLAGC;
253                 if((v & 0x8000) != 0)
254                         rS |= FLAGN;
255                 if((~(w ^ u) & (v ^ u) & 0x8000) != 0)
256                         rS |= FLAGV;
257                 if((u16int)v != 0)
258                         rS &= ~FLAGZ;
259                 break;
260         default:
261                 v = (u64int)w + u + c;
262                 if((v >> 32) != 0)
263                         rS |= FLAGC;
264                 if((v & 0x80000000) != 0)
265                         rS |= FLAGN;
266                 if((~(w ^ u) & (v ^ u) & 0x80000000) != 0)
267                         rS |= FLAGV;
268                 if((u32int)v != 0)
269                         rS &= ~FLAGZ;
270                 break;
271         }
272         return v;
273
274
275 static u32int
276 sub(u32int u, u32int w, int c, int s)
277 {
278         u64int v;
279
280         rS &= ~(FLAGN|FLAGV|FLAGC);
281         switch(s){
282         case 0:
283                 v = (u8int)u - (u8int)w - c;
284                 if(v >= 0x100)
285                         rS |= FLAGC;
286                 if((v & 0x80) != 0)
287                         rS |= FLAGN;
288                 if(((w ^ u) & (v ^ u) & 0x80) != 0)
289                         rS |= FLAGV;
290                 if((u8int)v != 0)
291                         rS &= ~FLAGZ;
292                 break;
293         case 1:
294                 v = (u16int)u - (u16int)w - c;
295                 if(v >= 0x10000)
296                         rS |= FLAGC;
297                 if((v & 0x8000) != 0)
298                         rS |= FLAGN;
299                 if(((w ^ u) & (v ^ u) & 0x8000) != 0)
300                         rS |= FLAGV;
301                 if((u16int)v != 0)
302                         rS &= ~FLAGZ;
303                 break;
304         default:
305                 v = (u64int)u - w - c;
306                 if((v >> 32) != 0)
307                         rS |= FLAGC;
308                 if((v & 0x80000000) != 0)
309                         rS |= FLAGN;
310                 if(((w ^ u) & (v ^ u) & (1<<31)) != 0)
311                         rS |= FLAGV;
312                 if((u32int)v != 0)
313                         rS &= ~FLAGZ;
314                 break;
315         }
316         return v;
317 }
318
319 static int
320 cond(int n)
321 {
322         switch(n){
323         case 0: return 1; break;
324         default: return 0; break;
325         case 2: return (rS & (FLAGC|FLAGZ)) == 0; break;
326         case 3: return (rS & (FLAGC|FLAGZ)) != 0; break;
327         case 4: return (rS & FLAGC) == 0; break;
328         case 5: return (rS & FLAGC) != 0; break;
329         case 6: return (rS & FLAGZ) == 0; break;
330         case 7: return (rS & FLAGZ) != 0; break;
331         case 8: return (rS & FLAGV) == 0; break;
332         case 9: return (rS & FLAGV) != 0; break;
333         case 10: return (rS & FLAGN) == 0; break;
334         case 11: return (rS & FLAGN) != 0; break;
335         case 12: return ((rS ^ (rS << 2)) & FLAGN) == 0; break;
336         case 13: return ((rS ^ (rS << 2)) & FLAGN) != 0; break;
337         case 14: return ((rS ^ (rS << 2)) & FLAGN) == 0 && (rS & FLAGZ) == 0; break;
338         case 15: return ((rS ^ (rS << 2)) & FLAGN) != 0 || (rS & FLAGZ) != 0; break;
339         }
340 }
341
342 static u32int
343 rot(u32int v, int m, int n, int s)
344 {
345         int l, ll, x, vf;
346         u32int msb;
347         
348         msb = 1 << ((8 << s) - 1);
349         v &= (msb << 1) - 1;
350         if(m == 0)
351                 x = (v & msb) != 0;
352         else
353                 x = 0;
354         if((m & 6) == 4)
355                 ll = l = (rS & FLAGX) != 0;
356         else
357                 ll = l = 0;
358         vf = 0;
359         while(n--){
360                 if((m & 1) == 0){
361                         l = v & 1;
362                         v >>= 1;
363                 }else{
364                         l = (v & msb) != 0;
365                         v <<= 1;
366                 }
367                 rS = rS & ~FLAGX | l << 4;
368                 if(m >= 6)
369                         x = l;
370                 else if(m >= 4){
371                         x = ll;
372                         ll = l;
373                 }
374                 if((m & 1) == 0){
375                         if(x != 0)
376                                 v |= msb;
377                 }else
378                         v |= x;
379                 vf |= x ^ (v & msb) != 0;
380                 tim += 2;
381         }
382         nz(v, s);
383         rS |= l;
384         if(m <= 1 && vf)
385                 rS |= FLAGV;
386         tim += s == 2 ? 8 : 6;
387         return v;
388 }
389
390 static u8int
391 addbcd(u8int a, u8int b)
392 {
393         int r;
394         
395         r = (a & 0xf) + (b & 0xf) + ((rS & FLAGX) != 0);
396         if(r > 0x09) r += 0x06;
397         if(r > 0x1f) r -= 0x10;
398         r += (a & 0xf0) + (b & 0xf0);
399         if(r > 0x9f) r += 0x60;
400         if((u8int)r != 0)
401                 rS &= ~FLAGZ;
402         if(r > 0xff)
403                 rS |= FLAGC|FLAGX;
404         else
405                 rS &= ~(FLAGC|FLAGX);
406         return r;
407 }
408
409 static u8int
410 subbcd(u8int a, u8int b)
411 {
412         int x;
413         
414         x = (a & 0xf) + (~b & 0xf) + ((rS & FLAGX) == 0);
415         if(x < 0x10) x -= 0x06;
416         if(x < 0) x += 0x10;
417         x += (a & 0xf0) + (~b & 0xf0);
418         if(x > 0xff)
419                 rS &= ~(FLAGC|FLAGX);
420         else{
421                 rS |= FLAGC|FLAGX;
422                 x -= 0x60;
423         }
424         if((u8int)x != 0)
425                 rS &= ~FLAGZ;
426         return x;
427 }
428
429 static void
430 dtime(u16int op, u8int s)
431 {
432         if((op & 0x100) != 0){
433                 if(s == 2)
434                         if((op & 0x30) == 0 || (op & 0x3f) == 0x3c)
435                                 tim += 8;
436                         else
437                                 tim += 6;
438                 else
439                         tim += 4;
440         }else
441                 tim += s == 2 ? 12 : 8;
442 }
443
444 static void
445 stime(int a, u8int s)
446 {
447         if(a)
448                 tim += s == 2 ? 6 : 4;
449         else
450                 tim += s == 2 ? 12 : 8;
451 }
452
453 static void
454 trap(int n, u32int pcv)
455 {
456         int l, v;
457         u32int sr, t;
458         
459         sr = rS;
460         if(n < 0){
461                 for(l = 7; l > ((rS >> 8) & 7); l--)
462                         if((irql[l] & irq) != 0)
463                                 break;
464                 v = intack(l);
465                 rS = rS & ~0x700 | l << 8;
466                 tim += 44;
467         }else{
468                 switch(n){
469                 case 2: case 3: tim += 50; break;
470                 case 5: tim += 38; break;
471                 case 6: tim += 40; break;
472                 default: tim += 34; break;
473                 }
474                 v = n;
475         }
476         if((rS & FLAGS) == 0){
477                 t = asp;
478                 asp = ra[7];
479                 ra[7] = t;
480         }
481         rS |= FLAGS;
482         push32(pcv);
483         push16(sr);
484         pc = memread(v * 4) << 16;
485         pc |= memread(v * 4 + 2);
486         stop = 0;
487 }
488
489 void
490 cpureset(void)
491 {
492         u32int v;
493         int i;
494
495         ra[7] = memread(0) << 16 | memread(2);
496         pc = memread(4) << 16 | memread(6);
497         rS = 0x2700;
498         for(i = 7, v = 0; i >= 0; i--){
499                 irqla[i] = v;
500                 v |= irql[i];
501         }
502 }
503
504 int
505 step(void)
506 {
507         u32int v, w;
508         vlong a;
509         int s;
510         int n, m, d;
511         static int cnt;
512
513         if(0 && pc == 0x4118c){
514                 trace++;
515                 print("%x\n", curpc);
516         }
517         tim = 0;
518         curpc = pc;
519         if(irq && (irqla[(rS >> 8) & 7] & irq) != 0){
520                 trap(-1, curpc);
521                 return tim;
522         }
523         if(stop)
524                 return 1;
525         op = fetch16();
526         if(trace)
527                 print("%.6ux %.6uo %.4ux %.8ux | %.8ux %.8ux %.8ux %.8ux | %.8ux %.8ux %.8ux\n", curpc, op, rS, memread(ra[7])<<16|memread(ra[7]+2), r[0], r[1], r[2], r[3], ra[0], ra[6], ra[7]);
528         s = op >> 6 & 3;
529         n = op >> 9 & 7;
530         switch(op >> 12){
531         case 0:
532                 if((op & 0x3f) == 0x3c){ /* (ORI|ANDI|EORI) to (CCR|SR) */
533                         if(s == 1 && (rS & FLAGS) == 0){
534                                 trap(8, curpc);
535                                 break;
536                         }
537                         v = rS;
538                         w = fetch16();
539                         switch(n){
540                         case 0: v |= w; break;
541                         case 1: v &= w; break;
542                         case 5: v ^= w; break;
543                         default: undef();
544                         }
545                         if(s != 1)
546                                 v = v & 0xff | rS & 0xff00;
547                         rS = v;
548                         if(s == 1 && (rS & FLAGS) == 0){
549                                 v = ra[7];
550                                 ra[7] = asp;
551                                 asp = v;
552                         }
553                         tim += 20;
554                         break;
555                 }
556                 if((op & 0x138) == 0x108){ /* MOVEP */
557                         a = ra[op & 7] + (s16int)fetch16();
558                         switch(s){
559                         case 0:
560                                 v = (u8int)rmode(a, 0) << 8;
561                                 v |= (u8int)rmode(a + 2, 0);
562                                 r[n] = r[n] & 0xff00 | v;
563                                 tim += 16;
564                                 break;
565                         case 1:
566                                 v = (u8int)rmode(a, 0) << 24;
567                                 v |= (u8int)rmode(a + 2, 0) << 16;
568                                 v |= (u8int)rmode(a + 4, 0) << 8;
569                                 v |= (u8int)rmode(a + 6, 0);
570                                 tim += 24;
571                                 r[n] = v;
572                                 break;
573                         case 2:
574                                 wmode(a, 0, r[n] >> 8);
575                                 wmode(a + 2, 0, r[n]);
576                                 tim += 16;
577                                 break;
578                         case 3:
579                                 wmode(a, 0, r[n] >> 24);
580                                 wmode(a + 2, 0, r[n] >> 16);
581                                 wmode(a + 4, 0, r[n] >> 8);
582                                 wmode(a + 6, 0, r[n]);
583                                 tim += 24;
584                                 break;
585                         }
586                         break;
587                 }
588                 if((op & 0x100) != 0 || n == 4){ /* BTST, BCHG, BCLR, BSET */
589                         if((op & 0x100) != 0)
590                                 w = r[n];
591                         else
592                                 w = fetch16();
593                         if((op & 0x38) != 0){
594                                 n = 0;
595                                 w = 1<<(w & 7);
596                         }else{
597                                 n = 2;
598                                 w = 1<<(w & 31);
599                         }
600                         a = amode(op >> 3, op, n);
601                         v = rmode(a, n);
602                         rS &= ~FLAGZ;
603                         if((v & w) == 0)
604                                 rS |= FLAGZ;
605                         switch(s){
606                         case 1: v ^= w; break;
607                         case 2: v &= ~w; if(n == 2) tim += 2; break;
608                         case 3: v |= w; break;
609                         }
610                         if(s != 0){
611                                 wmode(a, n, v);
612                                 tim += (op & 0x100) != 0 ? 8 : 12;
613                         }else{
614                                 tim += (op & 0x100) != 0 ? 4 : 8;
615                                 if(n == 2)
616                                         tim += 2;
617                         }
618                         break;
619                 }
620                 switch(s){
621                 case 0: w = (s8int)fetch16(); break;
622                 default: w = fetch16(); break;
623                 case 2: w = fetch32(); break;
624                 }
625                 a = amode(op >> 3, op, s);
626                 v = rmode(a, s);
627                 switch(n){
628                 case 0: nz(v |= w, s); break;
629                 case 1: nz(v &= w, s); break;
630                 case 2: rS |= FLAGZ; v = sub(v, w, 0, s); break;
631                 case 3: rS |= FLAGZ; v = add(v, w, 0, s); break;
632                 case 5: nz(v ^= w, s); break;
633                 case 6: rS |= FLAGZ; sub(v, w, 0, s); break;
634                 default: undef();
635                 }
636                 if(a < 0)
637                         tim += s == 2 ? (n == 1 || n == 6 ? 14 : 16) : 8;
638                 else
639                         tim += s == 2 ? 20 : 12;
640                 if(n != 6)
641                         wmode(a, s, v);
642                 break;
643         case 1: /* MOVE */
644                 s = 0;
645                 goto move;
646         case 2:
647                 s = 2;
648                 goto move;
649         case 3:
650                 s = 1;
651         move:
652                 v = rmode(amode(op >> 3, op, s), s);
653                 wmode(amode(op >> 6, op >> 9, s), s, v);
654                 if((op & 0x1c0) != 0x40)
655                         nz(v, s);
656                 tim += 4;
657                 break;
658         case 4:
659                 if((op & 0x1c0) == 0x1c0){ /* LEA */
660                         ra[n] = amode(op >> 3, op, 2);
661                         break;
662                 }
663                 if((op & 0x1c0) == 0x180){ /* CHK */
664                         a = amode(op >> 3, op, s);
665                         v = rmode(a, s);
666                         if((s32int)r[n] < 0 || (s32int)r[n] > (s32int)v)
667                                 trap(6, curpc);
668                         else
669                                 tim += 10;
670                 }
671                 if((op & 0xb80) == 0x880 && (op & 0x38) >= 0x10){ /* MOVEM */
672                         s = (op >> 6 & 1) + 1;
673                         w = fetch16();
674                         if((op & 0x38) == 0x18){
675                                 n = op & 7;
676                                 a = ra[n];
677                                 for(m = 0; m < 16; m++){
678                                         if((w & 1) != 0){
679                                                 r[m] = rmode(a, s);
680                                                 a += 1<<s;
681                                                 tim += 2<<s;
682                                         }
683                                         w >>= 1;
684                                 }
685                                 ra[n] = a;
686                                 tim += 12;
687                                 break;
688                         }
689                         if((op & 0x38) == 0x20){
690                                 n = op & 7;
691                                 a = ra[n];
692                                 for(m = 0; m < 16; m++){
693                                         if((w & 1) != 0){
694                                                 a -= 1<<s;
695                                                 wmode(a, s, r[15 - m]);
696                                                 tim += 2<<s;
697                                         }
698                                         w >>= 1;
699                                 }
700                                 ra[n] = a;
701                                 tim += 8;
702                                 break;
703                         }
704                         a = amode(op >> 3, op, s);
705                         for(m = 0; m < 16; m++){
706                                 if((w & 1) != 0){
707                                         if((op & 0x400) != 0)
708                                                 r[m] = rmode(a, s);
709                                         else
710                                                 wmode(a, s, r[m]);
711                                         a += 1<<s;
712                                         tim += 2<<s;
713                                 }
714                                 w >>= 1;
715                         }
716                         tim += (op & 0x400) != 0 ? 8 : 12;
717                         break;
718                 }
719                 switch(op >> 8 & 0xf){
720                 case 0:
721                         if(s == 3){ /* MOVE from SR */
722                                 if((rS & FLAGS) != 0){
723                                         a = amode(op >> 3, op, 1);
724                                         wmode(a, 1, rS);
725                                         tim += a < 0 ? 6 : 8;
726                                 }else
727                                         trap(8, curpc);
728                                 break;
729                         } /* NEGX */
730                         a = amode(op >> 3, op, s);
731                         m = (rS & FLAGX) != 0;
732                         d = 1<<(8<<s)-1;
733                         v = rmode(a, s);
734                         w = -(v+m) & (d << 1) - 1;
735                         rS &= ~(FLAGC|FLAGX|FLAGN|FLAGV);
736                         if((w & d) != 0)
737                                 rS |= FLAGN;
738                         if(m && w == d)
739                                 rS |= FLAGV;
740                         if(w != 0){
741                                 rS |= FLAGC|FLAGX;
742                                 rS &= ~FLAGZ;
743                         }
744                         wmode(a, s, w);
745                         stime(a < 0, s);
746                         break;
747                 case 2: /* CLR */
748                         a = amode(op >> 3, op, s);
749                         wmode(a, s, 0);
750                         nz(0, 0);
751                         stime(a < 0, s);
752                         break;
753                 case 4:
754                         if(s == 3){ /* MOVE to CCR */
755                                 rS = rS & 0xff00 | rmode(amode(op >> 3, op, 1), 1);
756                                 tim += 12;
757                                 break;
758                         } /* NEG */
759                         a = amode(op >> 3, op, s);
760                         v = -rmode(a, s);
761                         nz(v, s);
762                         rS = rS & ~FLAGX | ~rS << 2 & FLAGX | ~rS >> 2 & FLAGC;
763                         wmode(a, s, v);
764                         stime(a < 0, s);
765                         break;
766                 case 6:
767                         if(s == 3){ /* MOVE to SR */
768                                 if((rS & FLAGS) != 0){
769                                         rS = rmode(amode(op >> 3, op, 1), 1);
770                                         if((rS & FLAGS) == 0){
771                                                 v = asp;
772                                                 asp = ra[7];
773                                                 ra[7] = v;
774                                         }
775                                         tim += 12;
776                                 }else
777                                         trap(8, curpc);
778                                 break;
779                         } /* NOT */
780                         a = amode(op >> 3, op, s);
781                         v = ~rmode(a, s);
782                         nz(v, s);
783                         wmode(a, s, v);
784                         stime(a < 0, s);
785                         break;
786                 case 8:
787                         n = op & 7;
788                         switch(s){
789                         case 0: /* NBCD */
790                                 a = amode(op >> 3, op, 0);
791                                 v = rmode(a, 0);
792                                 wmode(a, 0, subbcd(0, v));
793                                 if(a < 0)
794                                         tim += 8;
795                                 else
796                                         tim += 6;
797                                 break;
798                         case 1:
799                                 if((op >> 3 & 7) != 0){
800                                         push32(amode(op >> 3, op, 0)); /* PEA */
801                                         tim += 8;
802                                 }else{
803                                         nz(r[n] = r[n] >> 16 | r[n] << 16, 2); /* SWAP */
804                                         tim += 4;
805                                 }
806                                 break;
807                         case 2: /* EXT */
808                                 nz(r[n] = r[n] & 0xffff0000 | (u16int)(s8int)r[n], 1);
809                                 tim += 4;
810                                 break;
811                         case 3: /* EXT */
812                                 nz(r[n] = (s16int)r[n], 2);
813                                 tim += 4;
814                                 break;
815                         }
816                         break;
817                 case 10:
818                         if(s == 3){ /* TAS */
819                                 a = amode(op >> 3, op, 0);
820                                 v = rmode(a, 0);
821                                 nz(v, 0);
822                                 wmode(a, s, v | 0x80);
823                                 tim += a < 0 ? 4 : 14;
824                                 break;
825                         } /* TST */
826                         a = amode(op >> 3, op, s);
827                         nz(rmode(a, s), s);
828                         tim += 4;
829                         break;
830                 case 14:
831                         v = op >> 4 & 0xf;
832                         n = op & 7;
833                         if(v == 4){ /* TRAP */
834                                 trap(0x20 | op & 0xf, pc);
835                                 break;
836                         }else if(v == 5){
837                                 if((op & 8) == 0){ /* LINK */
838                                         push32(ra[n]);
839                                         ra[n] = ra[7];
840                                         ra[7] += (s16int)fetch16();
841                                         tim += 16;
842                                 }else{ /* UNLK */
843                                         ra[7] = ra[n];
844                                         ra[n] = pop32();
845                                         tim += 12;
846                                 }
847                                 break;
848                         }else if(v == 6){ /* MOVE USP */
849                                 if((rS & FLAGS) != 0){
850                                         if((op & 8) != 0)
851                                                 ra[n] = asp;
852                                         else
853                                                 asp = ra[n];
854                                         tim += 4;
855                                 }else
856                                         trap(8, curpc);
857                                 break;
858                         }
859                         if((op & 0xc0) == 0xc0){ /* JMP */
860                                 pc = amode(op >> 3, op, 2);
861                                 tim += 4;
862                                 break;
863                         }
864                         if((op & 0xc0) == 0x80){ /* JSR */
865                                 a = amode(op >> 3, op, 2);
866                                 push32(pc);
867                                 pc = a;
868                                 tim += 12;
869                                 break;
870                         }
871                         switch(op){
872                         case 0x4e70: tim += 132; break; /* RESET */
873                         case 0x4e71: tim += 4; break; /* NOP */
874                         case 0x4e72: /* STOP */
875                                 if((rS & FLAGS) != 0){
876                                         rS = fetch16();
877                                         stop = 1;
878                                 }else
879                                         trap(8, curpc);
880                                 tim += 4;
881                                 break;
882                         case 0x4e73: /* RTE */
883                                 if((rS & FLAGS) != 0){
884                                         v = rS;
885                                         rS = pop16();
886                                         pc = pop32();
887                                         if(((v ^ rS) & FLAGS) != 0){
888                                                 v = asp;
889                                                 asp = ra[7];
890                                                 ra[7] = v;
891                                         }
892                                         tim += 20;
893                                 }else
894                                         trap(8, curpc);
895                                 break;
896                         case 0x4e75: pc = pop32(); tim += 16; break; /* RTS */
897                         case 0x4e76: if((rS & FLAGV) != 0) trap(7, curpc); tim += 4; break; /* TRAPV */
898                         case 0x4e77: /* RTR */
899                                 rS = rS & 0xff00 | pop16() & 0xff;
900                                 pc = pop32();
901                                 tim += 20;
902                                 break;
903                         default: undef();
904                         }
905                         break;
906                 default:
907                         undef();
908                 }
909                 break;
910         case 5:
911                 if((op & 0xf8) == 0xc8){ /* DBcc */
912                         n = op & 7;
913                         v = (s16int)fetch16();
914                         if(!cond((op >> 8) & 0xf)){
915                                 if((u16int)r[n] != 0){
916                                         r[n]--;
917                                         pc = pc + v - 2;
918                                         tim += 10;
919                                 }else{
920                                         r[n] |= 0xffff;
921                                         tim += 14;
922                                 }
923                         }else
924                                 tim += 12;
925                         break;
926                 }
927                 if(s == 3){ /* Scc */
928                         a = amode(op >> 3, op, 0);
929                         v = cond(op >> 8 & 0xf);
930                         wmode(a, 0, -v);
931                         if(a < 0)
932                                 tim += 4 + 2 * v;
933                         else
934                                 tim += 8;
935                         break;
936                 } /* ADDQ, SUBQ */
937                 rS |= FLAGZ;
938                 if((op & 0x38) == 0x08)
939                         s = 2;
940                 a = amode(op >> 3, op, s);
941                 v = rmode(a, s);
942                 if(n == 0)
943                         n = 8;
944                 if((op & 0x100) == 0)
945                         v = add(v, n, 0, s);
946                 else
947                         v = sub(v, n, 0, s);
948                 rS = rS & ~FLAGX | rS << 4 & FLAGX;
949                 if(a < 0)
950                         tim += s == 2 || (op & 0x130) == 0x110 ? 8 : 4;
951                 else
952                         tim += s == 2 ? 12 : 8;
953                 wmode(a, s, v);
954                 break;
955         case 6: /* BRA */
956                 v = (s8int)op;
957                 if(v == 0)
958                         v = (s16int)fetch16();
959                 else if(v == (u32int)-1)
960                         v = fetch32();
961                 if((op & 0xf00) == 0x100){ /* BSR */
962                         push32(pc);
963                         pc = curpc + 2 + v;
964                         tim += 18;
965                         break;
966                 }
967                 if(cond((op >> 8) & 0xf)){
968                         pc = curpc + 2 + v;
969                         tim += 10;
970                 }else
971                         tim += (u8int)(op + 1) <= 1 ? 12 : 8;
972                 break;
973         case 7: /* MOVEQ */
974                 r[n] = (s8int)op;
975                 nz(r[n], 0);
976                 tim += 4;
977                 break;
978         case 8:
979                 if(s == 3){ /* DIVU, DIVS */
980                         a = amode(op >> 3, op, 1);
981                         v = rmode(a, 1);
982                         if(v == 0){
983                                 trap(5, curpc);
984                                 break;
985                         }
986                         if((op & 0x100) != 0){
987                                 w = (s32int)r[n] % (s16int)v;
988                                 v = (s32int)r[n] / (s16int)v;
989                                 if(((s16int)w ^ (s16int)v) < 0)
990                                         w = -w;
991                                 if(v != (u32int)(s16int)v){
992                                         rS = rS & ~FLAGC | FLAGV;
993                                         break;
994                                 }
995                                 tim += 158;
996                         }else{
997                                 w = r[n] % (u16int)v;
998                                 v = r[n] / (u16int)v;
999                                 if(v >= 0x10000){
1000                                         rS = rS & ~FLAGC | FLAGV;
1001                                         break;
1002                                 }
1003                                 tim += 140;
1004                         }
1005                         r[n] = (u16int)v | w << 16;
1006                         nz(v, 1);
1007                         break;
1008                 }
1009                 if((op & 0x1f0) == 0x100){ /* SBCD */
1010                         n = (op >> 9) & 7;
1011                         m = op & 7;
1012                         if((op & 8) != 0){
1013                                 a = amode(4, n, 0);
1014                                 v = rmode(a, 0);
1015                                 w = rmode(amode(4, m, 0), 0);
1016                                 v = subbcd(v, w);
1017                                 wmode(a, 0, v);
1018                                 tim += 18;
1019                         }else{
1020                                 r[n] = r[n] & 0xffffff00 | subbcd((u8int)r[n], (u8int)r[m]);
1021                                 tim += 6;
1022                         }
1023                         break;
1024                 }
1025         logic: /* OR, EOR, AND */
1026                 a = amode(op >> 3, op, s);
1027                 n = (op >> 9) & 7;
1028                 v = rmode(a, s);
1029                 switch(op >> 12){
1030                 case 8: v |= r[n]; break;
1031                 case 11: v ^= r[n]; break;
1032                 case 12: v &= r[n]; break;
1033                 }
1034                 if((op & 0x100) == 0)
1035                         a = ~n;
1036                 wmode(a, s, v);
1037                 nz(v, s);
1038                 dtime(op, s);
1039                 break;
1040         case 11:
1041                 if(s == 3){ /* CMPA */
1042                         s = (op >> 8 & 1) + 1;
1043                         a = amode(op >> 3, op, s);
1044                         rS |= FLAGZ;
1045                         sub(ra[n], rmode(a, s), 0, 2);
1046                         tim += 6;
1047                         break;
1048                 }
1049                 if((op & 0x138) == 0x108){ /* CMPM */
1050                         m = op & 7;
1051                         rS |= FLAGZ;
1052                         sub(rmode(amode(3, n, s), s), rmode(amode(3, m, s), s), 0, s);
1053                         tim += s == 2 ? 20 : 12;
1054                         break;
1055                 }
1056                 if((op & 0x100) == 0){ /* CMP */
1057                         a = amode(op >> 3, op, s);
1058                         rS |= FLAGZ;
1059                         sub(r[n], rmode(a, s), 0, s);
1060                         tim += s == 2 ? 6 : 4;
1061                         break;
1062                 }
1063                 goto logic;
1064         case 12:
1065                 if(s == 3){ /* MULU, MULS */
1066                         a = amode(op >> 3, op, 1);
1067                         v = rmode(a, 1);
1068                         if((op & 0x100) != 0)
1069                                 v *= (s16int)r[n];
1070                         else
1071                                 v = (u16int)v * (u16int)r[n];
1072                         r[n] = v;
1073                         nz(v, 1);
1074                         tim += 70;
1075                         break;
1076                 }
1077                 if((op & 0x1f0) == 0x100){ /* ABCD */
1078                         n = (op >> 9) & 7;
1079                         m = op & 7;
1080                         if((op & 8) != 0){
1081                                 a = amode(4, n, 0);
1082                                 v = rmode(a, 0);
1083                                 w = rmode(amode(4, m, 0), 0);
1084                                 v = addbcd(v, w);
1085                                 wmode(a, 0, v);
1086                                 tim += 18;
1087                         }else{
1088                                 r[n] = r[n] & 0xffffff00 | addbcd((u8int)r[n], (u8int)r[m]);
1089                                 tim += 6;
1090                         }
1091                         break;
1092                 
1093                 }
1094                 if((op & 0x130) == 0x100){ /* EXG */
1095                         m = op & 0xf;
1096                         if((op & 0xc8) == 0x48)
1097                                 n |= 8;
1098                         v = r[n];
1099                         r[n] = r[m];
1100                         r[m] = v;
1101                         tim += 6;
1102                         break;
1103                 }
1104                 goto logic;
1105         case 9:
1106         case 13:
1107                 if(s == 3){ /* ADDA, SUBA */
1108                         if((op & 0x100) != 0){
1109                                 s = 2;
1110                                 tim += 6;
1111                         }else{
1112                                 s = 1;
1113                                 tim += 8;
1114                         }
1115                         a = amode(op >> 3, op, s);
1116                         if((op >> 12) == 13)
1117                                 ra[n] += rmode(a, s);
1118                         else
1119                                 ra[n] -= rmode(a, s);
1120                         break;
1121                 }
1122                 if((op & 0x130) == 0x100){ /* ADDX, SUBX */
1123                         m = op & 7;
1124                         if((op & 8) != 0){
1125                                 a = ra[n] -= 1<<s;
1126                                 v = rmode(a, s);
1127                                 w = rmode(ra[m] -= 1<<s, s);
1128                                 tim += s == 2 ? 30 : 18;
1129                         }else{
1130                                 v = r[n];
1131                                 w = r[m];
1132                                 a = ~n;
1133                                 tim += s == 2 ? 8 : 4;
1134                         }
1135                         if((op >> 12) == 13)
1136                                 v = add(v, w, (rS & FLAGX) != 0, s);
1137                         else
1138                                 v = sub(v, w, (rS & FLAGX) != 0, s);
1139                         wmode(a, s, v);
1140                         rS = rS & ~FLAGX | rS << 4 & FLAGX;
1141                         break;
1142                 } /* ADD, SUB */
1143                 a = amode(op >> 3, op, s);
1144                 rS |= FLAGZ;
1145                 d = (op & 0x100) == 0;
1146                 v = rmode(a, s);
1147                 if((op >> 12) == 13)
1148                         v = add(v, r[n], 0, s);
1149                 else
1150                         v = sub(d ? r[n] : v, d ? v : r[n], 0, s);
1151                 rS = rS & ~FLAGX | rS << 4 & FLAGX;
1152                 if(d)
1153                         a = ~n;
1154                 wmode(a, s, v);
1155                 dtime(op, s);
1156                 break;
1157         case 14: /* shifts */
1158                 if(s == 3){
1159                         m = op >> 8 & 7;
1160                         n = 1;
1161                         s = 1;
1162                         a = amode(op >> 3, op, s);
1163                 }else{
1164                         a = ~(uvlong)(op & 7);
1165                         m = op >> 2 & 6 | op >> 8 & 1;
1166                         n = (op >> 9) & 7;
1167                         if((op & 0x20) != 0)
1168                                 n = r[n] & 63;
1169                         else if(n == 0)
1170                                 n = 8;
1171                 }
1172                 wmode(a, s, rot(rmode(a, s), m, n, s));
1173                 break;
1174         case 10:
1175                 trap(10, curpc);
1176                 break;
1177         case 15:
1178                 trap(11, curpc);
1179                 break;
1180         default:
1181                 undef();
1182         }
1183         return tim;
1184 }