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