]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/mix/mix.c
ape/lib9: sync arm getfcr.s implementation
[plan9front.git] / sys / src / games / mix / mix.c
1 #include <u.h>
2 #include <libc.h>
3 #include <ctype.h>
4 #include <bio.h>
5 #include <avl.h>
6 #include "mix.h"
7 #include "y.tab.h"
8
9 struct Resvd {
10         char *name;
11         long lex;
12         int c;
13         int f;
14 } res[] = {
15         { "NOP",        LOP,    0,      F(0, 5) },
16         { "ADD",        LOP,    1,      F(0, 5) },
17         { "FADD",       LOP,    1,      6 },
18         { "SUB",        LOP,    2,      F(0, 5) },
19         { "FSUB",       LOP,    2,      6 },
20         { "MUL",        LOP,    3,      F(0, 5) },
21         { "FMUL",       LOP,    3,      6 },
22         { "DIV",        LOP,    4,      F(0, 5) },
23         { "FDIV",       LOP,    4,      6 },
24         { "NUM",        LOP,    5,      0 },
25         { "CHAR",       LOP,    5,      1 },
26         { "HLT",        LOP,    5,      2 },
27         { "SLA",        LOP,    6,      0 },
28         { "SRA",        LOP,    6,      1 },
29         { "SLAX",       LOP,    6,      2 },
30         { "SRAX",       LOP,    6,      3 },
31         { "SLC",        LOP,    6,      4 },
32         { "SRC",        LOP,    6,      5 },
33         { "MOVE",       LOP,    7,      1 },
34         { "LDA",        LOP,    8,      F(0, 5) },
35         { "LD1",        LOP,    9,      F(0, 5) },
36         { "LD2",        LOP,    10,     F(0, 5) },
37         { "LD3",        LOP,    11,     F(0, 5) },
38         { "LD4",        LOP,    12,     F(0, 5) },
39         { "LD5",        LOP,    13,     F(0, 5) },
40         { "LD6",        LOP,    14,     F(0, 5) },
41         { "LDX",        LOP,    15,     F(0, 5) },
42         { "LDAN",       LOP,    16,     F(0, 5) },
43         { "LD1N",       LOP,    17,     F(0, 5) },
44         { "LD2N",       LOP,    18,     F(0, 5) },
45         { "LD3N",       LOP,    19,     F(0, 5) },
46         { "LD4N",       LOP,    20,     F(0, 5) },
47         { "LD5N",       LOP,    21,     F(0, 5) },
48         { "LD6N",       LOP,    22,     F(0, 5) },
49         { "LDXN",       LOP,    23,     F(0, 5) },
50         { "STA",        LOP,    24,     F(0, 5) },
51         { "ST1",        LOP,    25,     F(0, 5) },
52         { "ST2",        LOP,    26,     F(0, 5) },
53         { "ST3",        LOP,    27,     F(0, 5) },
54         { "ST4",        LOP,    28,     F(0, 5) },
55         { "ST5",        LOP,    29,     F(0, 5) },
56         { "ST6",        LOP,    30,     F(0, 5) },
57         { "STX",        LOP,    31,     F(0, 5) },
58         { "STJ",        LOP,    32,     F(0, 2) },
59         { "STZ",        LOP,    33,     F(0, 5) },
60         { "JBUS",       LOP,    34, 0 },
61         { "IOC",        LOP,    35, 0 },
62         { "IN", LOP,    36,     0 },
63         { "OUT",        LOP,    37,     0 },
64         { "JRED",       LOP,    38,     0 },
65         { "JMP",        LOP,    39, 0 },
66         { "JSJ",        LOP,    39, 1 },
67         { "JOV",        LOP,    39, 2 },
68         { "JNOV",       LOP,    39, 3 },
69         { "JL", LOP,    39,     4 },
70         { "JE", LOP,    39,     5 },
71         { "JG", LOP,    39,     6 },
72         { "JGE",        LOP,    39,     7 },
73         { "JNE",        LOP,    39,     8 },
74         { "JLE",        LOP,    39,     9 },
75         { "JAN",        LOP,    40,     0 },
76         { "JAZ",        LOP,    40,     1 },
77         { "JAP",        LOP,    40,     2 },
78         { "JANN",       LOP,    40,     3 },
79         { "JANZ",       LOP,    40,     4 },
80         { "JANP",       LOP,    40,     5 },
81         { "J1N",        LOP,    41,     0 },
82         { "J1Z",        LOP,    41,     1 },
83         { "J1P",        LOP,    41,     2 },
84         { "J1NN",       LOP,    41,     3 },
85         { "J1NZ",       LOP,    41,     4 },
86         { "J1NP",       LOP,    41,     5 },
87         { "J2N",        LOP,    42,     0 },
88         { "J2Z",        LOP,    42,     1 },
89         { "J2P",        LOP,    42,     2 },
90         { "J2NN",       LOP,    42,     3 },
91         { "J2NZ",       LOP,    42,     4 },
92         { "J2NP",       LOP,    42,     5 },
93         { "J3N",        LOP,    43,     0 },
94         { "J3Z",        LOP,    43,     1 },
95         { "J3P",        LOP,    43,     2 },
96         { "J3NN",       LOP,    43,     3 },
97         { "J3NZ",       LOP,    43,     4 },
98         { "J3NP",       LOP,    43,     5 },
99         { "J4N",        LOP,    44,     0 },
100         { "J4Z",        LOP,    44,     1 },
101         { "J4P",        LOP,    44,     2 },
102         { "J4NN",       LOP,    44,     3 },
103         { "J4NZ",       LOP,    44,     4 },
104         { "J4NP",       LOP,    44,     5 },
105         { "J5N",        LOP,    45,     0 },
106         { "J5Z",        LOP,    45,     1 },
107         { "J5P",        LOP,    45,     2 },
108         { "J5NN",       LOP,    45,     3 },
109         { "J5NZ",       LOP,    45,     4 },
110         { "J5NP",       LOP,    45,     5 },
111         { "J6N",        LOP,    46,     0 },
112         { "J6Z",        LOP,    46,     1 },
113         { "J6P",        LOP,    46,     2 },
114         { "J6NN",       LOP,    46,     3 },
115         { "J6NZ",       LOP,    46,     4 },
116         { "J6NP",       LOP,    46,     5 },
117         { "JXN",        LOP,    47,     0 },
118         { "JXZ",        LOP,    47,     1 },
119         { "JXP",        LOP,    47,     2 },
120         { "JXNN",       LOP,    47,     3 },
121         { "JXNZ",       LOP,    47,     4 },
122         { "JXNP",       LOP,    47,     5 },
123         { "INCA",       LOP,    48,     0 },
124         { "DECA",       LOP,    48,     1 },
125         { "ENTA",       LOP,    48,     2 },
126         { "ENNA",       LOP,    48,     3 },
127         { "INC1",       LOP,    49,     0 },
128         { "DEC1",       LOP,    49,     1 },
129         { "ENT1",       LOP,    49,     2 },
130         { "ENN1",       LOP,    49,     3 },
131         { "INC2",       LOP,    50,     0 },
132         { "DEC2",       LOP,    50,     1 },
133         { "ENT2",       LOP,    50,     2 },
134         { "ENN2",       LOP,    50,     3 },
135         { "INC3",       LOP,    51,     0 },
136         { "DEC3",       LOP,    51,     1 },
137         { "ENT3",       LOP,    51,     2 },
138         { "ENN3",       LOP,    51,     3 },
139         { "INC4",       LOP,    52,     0 },
140         { "DEC4",       LOP,    52,     1 },
141         { "ENT4",       LOP,    52,     2 },
142         { "ENN4",       LOP,    52,     3 },
143         { "INC5",       LOP,    53,     0 },
144         { "DEC5",       LOP,    53,     1 },
145         { "ENT5",       LOP,    53,     2 },
146         { "ENN5",       LOP,    53,     3 },
147         { "INC6",       LOP,    54,     0 },
148         { "DEC6",       LOP,    54,     1 },
149         { "ENT6",       LOP,    54,     2 },
150         { "ENN6",       LOP,    54,     3 },
151         { "INCX",       LOP,    55,     0 },
152         { "DECX",       LOP,    55,     1 },
153         { "ENTX",       LOP,    55,     2 },
154         { "ENNX",       LOP,    55,     3 },
155         { "CMPA",       LOP,    56,     F(0, 5) },
156         { "FCMP",       LOP,    56,     6 },
157         { "CMP1",       LOP,    57,     F(0, 5) },
158         { "CMP2",       LOP,    58,     F(0, 5) },
159         { "CMP3",       LOP,    59,     F(0, 5) },
160         { "CMP4",       LOP,    60,     F(0, 5) },
161         { "CMP5",       LOP,    61,     F(0, 5) },
162         { "CMP6",       LOP,    62,     F(0, 5) },
163         { "CMPX",       LOP,    63,     F(0, 5) },
164         { "EQU",        LEQU,   -1,     -1 },
165         { "ORIG",       LORIG,  -1,     -1 },
166         { "CON",        LCON,   -1,     -1 },
167         { "ALF",        LALF,   -1,     -1 },
168         { "END",        LEND,   -1,     -1 },
169         { "0H", LHERE,  0,      -1 },
170         { "1H", LHERE,  1,      -1 },
171         { "2H", LHERE,  2,      -1 },
172         { "3H", LHERE,  3,      -1 },
173         { "4H", LHERE,  4,      -1 },
174         { "5H", LHERE,  5,      -1 },
175         { "6H", LHERE,  6,      -1 },
176         { "7H", LHERE,  7,      -1 },
177         { "8H", LHERE,  8,      -1 },
178         { "9H", LHERE,  9,      -1 },
179         { "0B", LBACK,  0,      -1 },
180         { "1B", LBACK,  1,      -1 },
181         { "2B", LBACK,  2,      -1 },
182         { "3B", LBACK,  3,      -1 },
183         { "4B", LBACK,  4,      -1 },
184         { "5B", LBACK,  5,      -1 },
185         { "6B", LBACK,  6,      -1 },
186         { "7B", LBACK,  7,      -1 },
187         { "8B", LBACK,  8,      -1 },
188         { "9B", LBACK,  9,      -1 },
189         { "0F", LFORW,  0,      -1 },
190         { "1F", LFORW,  1,      -1 },
191         { "2F", LFORW,  2,      -1 },
192         { "3F", LFORW,  3,      -1 },
193         { "4F", LFORW,  4,      -1 },
194         { "5F", LFORW,  5,      -1 },
195         { "6F", LFORW,  6,      -1 },
196         { "7F", LFORW,  7,      -1 },
197         { "8F", LFORW,  8,      -1 },
198         { "9F", LFORW,  9,      -1 },
199 };
200
201 int mask[] = {
202         MASK1,
203         MASK2,
204         MASK3,
205         MASK4,
206         MASK5
207 };
208
209 int symcmp(Avl*, Avl*);
210 Sym *sym(char*);
211
212 void
213 main(int argc, char **argv)
214 {
215         int go;
216         char **ap;
217
218         go = 0;
219         ARGBEGIN {
220         case 'g': go++; break;
221         } ARGEND
222
223         cinit();
224         sinit();
225         fmtinstall('I', Ifmt);
226         vmstart = -1;
227         for(ap = argv; ap < argv+argc; ap++)
228                 asmfile(*ap);
229         repl(go);
230         exits(nil);
231 }
232
233 void
234 sinit(void)
235 {
236         struct Resvd *r;
237         Sym *s;
238
239         syms = avlcreate(symcmp);
240         for(r = res; r < res + nelem(res); r++) {
241                 s = sym(r->name);
242                 s->lex = r->lex;
243                 s->opc = r->c;
244                 s->f = r->f;
245                 avlinsert(syms, s);
246         }
247 }
248
249 int
250 asmfile(char *file)
251 {
252         int fd;
253
254         if((fd = open(file, OREAD)) == -1)
255                 return -1;
256         Binit(&bin, fd, OREAD);
257         line = 1;
258         filename = file;
259         if(setjmp(errjmp) == 0)
260                 yyparse();
261         Bterm(&bin);
262         close(fd);
263         return 0;
264 }
265
266 int
267 unpack(u32int inst, int *apart, int *ipart, int *fpart)
268 {
269         int opc;
270
271         opc = V(inst, F(5, 5));
272         *fpart = V(inst, F(4, 4));
273         *ipart = V(inst, F(3, 3));
274         *apart = V(inst, F(0, 2));
275         return opc;
276 }
277
278 int
279 Ifmt(Fmt *f)
280 {
281         u32int inst;
282         int i, apart, ipart, fpart, opc, a, b;
283
284         inst = va_arg(f->args, u32int);
285         opc = unpack(inst, &apart, &ipart, &fpart);
286         for(i = 0; i < nelem(res); i++) {
287                 if(res[i].c == opc)
288                         break;
289         }
290         UNF(a, b, fpart);
291         if(res[i+1].c != opc || opc == 56)
292                 return fmtprint(f, "%s\t%d,%d(%d | %d:%d)", res[i].name, apart, ipart, fpart, a, b);
293         while(res[i].c == opc && i < nelem(res)) {
294                 if(res[i].f == fpart)
295                         return fmtprint(f, "%s\t%d,%d(%d | %d:%d)", res[i].name, apart, ipart, fpart, a, b);
296                 i++;
297         }
298         return fmtprint(f, "%d\t%d,%d(%d | %d:%d)", opc, apart, ipart, fpart, a, b);
299 }
300
301 Rune
302 getr(void)
303 {
304         static int bol = 1;
305         Rune r;
306
307         r = Bgetrune(&bin);
308         switch(r) {
309         case '*':
310                 if(!bol)
311                         break;
312         case '#':
313                 skipto('\n');
314         case '\n':
315                 line++;
316                 bol = 1;
317                 return '\n';
318         }
319         bol = 0;
320         return r;
321 }
322
323 void
324 ungetr(Rune r)
325 {
326         if(r == '\n')
327                 line--;
328         Bungetrune(&bin);
329 }
330
331 long
332 yylex(void)
333 {
334         static Rune buf[11];
335         Rune r, *bp, *ep;
336         static char cbuf[100];
337         int isnum;
338
339         if(yydone)
340                 return -1;
341
342 Loop:
343         r = getr();
344         switch(r) {
345         case Beof:
346                 return -1;
347         case '\t':
348         case ' ':
349                 goto Loop;
350         case '\n': case '*': case '+':
351         case '-': case ':': case ',':
352         case '(': case ')': case '=':
353                 return r;
354         case '/':
355                 r = getr();
356                 if(r == '/')
357                         return LSS;
358                 else
359                         ungetr(r);
360                 return '/';
361         case '"':
362                 for(bp = buf; bp < buf+5; bp++) {
363                         *bp = getr();
364                 }
365                 if(getr() != '"')
366                         yyerror("Bad string literal\n");
367                 yylval.rbuf = buf;
368                 return LSTR;
369         }
370         bp = buf;
371         ep = buf+nelem(buf)-1;
372         isnum = 1;
373         for(;;) {
374                 if(runetomix(r) == -1)
375                         yyerror("Invalid character %C", r);
376                 if(bp == ep)
377                         yyerror("Symbol or number too long");
378                 *bp++ = r;
379                 if(isnum && (r >= Runeself || !isdigit(r)))
380                         isnum = 0;
381                 switch(r = getr()) {
382                 case Beof: case '\t': case '\n':
383                 case '+': case '-': case '*':
384                 case ':': case ',': case '(':
385                 case ')': case '=': case ' ':
386                 case '/': case '#':
387                         ungetr(r);
388                         *bp = '\0';
389                         goto End;
390                 }
391         }
392 End:
393         seprint(cbuf, cbuf+100, "%S", buf);
394         if(isnum) {
395                 yylval.lval = strtol(cbuf, nil, 10);
396                 return LNUM;
397         }
398         yylval.sym = sym(cbuf);
399         return yylval.sym->lex;
400 }
401
402 Sym*
403 getsym(char *name)
404 {
405         Sym *s;
406
407         s = emallocz(sizeof(*s) + strlen(name));
408         strcpy(s->nbuf, name);
409         s->name = s->nbuf;
410         s->lex = LSYMREF;
411         return s;
412 }
413
414 Sym*
415 sym(char *name)
416 {
417         Sym *s, l;
418
419         l.name = name;
420         s = (Sym*)avllookup(syms, &l, 0);
421         if(s != nil)
422                 return s;
423         s = getsym(name);
424         avlinsert(syms, s);
425         return s;
426 }
427
428 int
429 symcmp(Avl *a, Avl *b)
430 {
431         Sym *sa, *sb;
432
433         sa = (Sym*)a;
434         sb = (Sym*)b;
435         return strcmp(sa->name, sb->name);
436 }
437
438 void
439 skipto(char c)
440 {
441         Rune r;
442
443         for(;;) {
444                 r = Bgetrune(&bin);
445                 if(r != c && r != Beof)
446                         continue;
447                 return;
448         }
449 }
450
451 int
452 mval(u32int a, int s, u32int m)
453 {
454         int sign, val;
455
456         sign = a >> 31;
457         val = a>>s*BITS & m;
458         if(sign)
459                 return -val;
460         return val;
461 }
462
463 int
464 V(u32int w, int f)
465 {
466         int a, b, d;
467
468         if(f == 0)
469                 return 0;
470
471         UNF(a, b, f);
472         if(a > 0)
473                 w &= ~SIGNB;
474         else
475                 a++;
476
477         d = b - a;
478         if(a > 5 || b > 5 || d < 0 || d > 4)
479                 vmerror("Invalid fpart %d", f);
480
481         return mval(w, 5-b, mask[d]);
482 }
483
484 int
485 M(int a, int i)
486 {
487         int off, r;
488
489         r = ri[i] & ~(MASK3<<2*BITS);
490         off = i == 0 ? 0 : mval(r, 0, MASK2);
491         return a + off;
492 }
493
494 void mixfadd(int){}
495
496 void
497 mixadd(int m, int f)
498 {
499         int rval;
500         
501         rval = mval(ra, 0, MASK5);
502         rval += V(cells[m], f);
503         ra = rval < 0 ? -rval|SIGNB : rval;
504         if(ra & OVERB) {
505                 ra &= ~OVERB;
506                 ot = 1;
507         }
508 }
509
510 void mixfsub(int){}
511
512 void
513 mixsub(int m, int f)
514 {
515         int rval;
516
517         rval = mval(ra, 0, MASK5);
518         rval -= V(cells[m], f);
519         ra = rval < 0 ? -rval|SIGNB : rval;
520         if(ra & OVERB) {
521                 ra &= ~OVERB;
522                 ot = 1;
523         }
524 }
525
526 void mixfmul(int){}
527
528 void
529 mixmul(int m, int f)
530 {
531         vlong rval;
532         int signb;
533
534         rval = mval(ra, 0, MASK5);
535         rval *= V(cells[m], f);
536
537         if(rval < 0) {
538                 rval = -rval;
539                 signb = SIGNB;
540         } else
541                 signb = 0;
542
543         ra = rval>>5*BITS & MASK5 | signb;
544         rx = rval & MASK5 | signb;
545 }
546
547 void mixfdiv(int){}
548
549 void
550 mixdiv(int m, int f)
551 {
552         vlong rax, quot;
553         u32int xsignb, asignb;
554         int rem, v;
555
556         v = V(cells[m], f);
557         if(v == 0) {
558                 ot = 1;
559                 return;
560         }
561         rax = ra & MASK5;
562         rax <<= 5 * BITS;
563         rax |= rx & MASK5;
564         if(ra >> 31)
565                 rax = -rax;
566
567         quot = rax / v;
568         rem = rax % v;
569
570         if(quot < 0) {
571                 quot = -quot;
572                 asignb = SIGNB;
573         } else
574                 asignb = 0;
575
576         if(rem < 0) {
577                 rem = -rem;
578                 xsignb = SIGNB;
579         } else
580                 xsignb = 0;
581
582         if(quot & ~MASK5)
583                 ot = 1;
584
585         ra = quot & MASK5 | asignb;
586         rx = rem & MASK5 | xsignb;
587 }
588
589 void
590 mixnum(void)
591 {
592         int i, b;
593         u32int n;
594
595         n = 0;
596         for(i = 0; i < 5; i++) {
597                 b = ra>>(4-i)*BITS & MASK1;
598                 b %= 10;
599                 n = 10*n + b;
600         }
601         for(i = 0; i < 5; i++) {
602                 b = rx>>(4-i)*BITS & MASK1;
603                 b %= 10;
604                 n = 10*n + b;
605         }
606         ra &= ~MASK5;
607         ra |= n & MASK5;
608 }
609
610 void
611 mixchar(void)
612 {
613         int i;
614         u32int a, val;
615
616         val = ra & ~SIGNB;
617         for(i = 0; i < 5; i++) {
618                 a = val % 10;
619                 a += 30;
620                 rx &= ~(MASK1 << i*BITS);
621                 rx |= a << i*BITS;
622                 val /= 10;
623         }
624         for(i = 0; i < 5; i++) {
625                 a = val % 10;
626                 a += 30;
627                 ra &= ~(MASK1 << i*BITS);
628                 ra |= a << i*BITS;
629                 val /= 10;
630         }
631 }
632
633 void
634 mixslra(int m, int left)
635 {
636         u32int val;
637
638         if(m < 0)
639                 vmerror("Bad shift A %d", m);
640         if(m > 4) {
641                 ra &= ~MASK5;
642                 return;
643         }
644         val = ra & MASK5;
645         ra &= ~MASK5;
646         if(left)
647                 val <<= m * BITS;
648         else
649                 val >>= m * BITS;
650         ra |= val & MASK5;
651 }
652
653 void
654 mixslrax(int m, int left)
655 {
656         u64int rax;
657
658         if(m < 0)
659                 vmerror("Bad shift AX %d", m);
660         if(m > 9) {
661                 ra &= ~MASK5;
662                 rx &= ~MASK5;
663                 return;
664         }
665         rax = ra & MASK5;
666         ra &= ~MASK5;
667         rax <<= 5 * BITS;
668         rax |= rx & MASK5;
669         rx &= ~MASK5;
670         if(left)
671                 rax <<= m*BITS;
672         else
673                 rax >>= m*BITS;
674         rx |= rax & MASK5;
675         ra |= rax>>5*BITS & MASK5;
676 }
677
678 void
679 mixslc(int m)
680 {
681         u64int rax, s;
682
683         if(m < 0)
684                 vmerror("Bad shift SLC %d", m);
685
686         m %= 10;
687
688         rax = ra & MASK5;
689         ra &= ~MASK5;
690         rax <<= 5 * BITS;
691         rax |= rx & MASK5;
692         rx &= ~MASK5;
693
694         s = rax & mask[m]<<10-m;
695         rax <<= m;
696         rax &= ~mask[m];
697         rax |= s;
698
699         rx |= rax & MASK5;
700         ra |= rax>>5*BITS & MASK5;
701 }
702
703 void
704 mixsrc(int m)
705 {
706         u64int rax, s;
707
708         if(m < 0)
709                 vmerror("Bad shift SRC %d", m);
710
711         m %= 10;
712
713         rax = ra & MASK5;
714         ra &= ~MASK5;
715         rax <<= 5 * BITS;
716         rax |= rx & MASK5;
717         rx &= ~MASK5;
718
719         s = rax & mask[m];
720         rax >>= m;
721         rax &= ~mask[m] << 10-m;
722         rax |= s<<10-m;
723
724         rx |= rax & MASK5;
725         ra |= rax>>5*BITS & MASK5;
726 }
727
728 void
729 mixmove(int s, int f)
730 {
731         int d;
732         u32int *p, *q, *pe;
733
734         if(f == 0)
735                 return;
736         if(s < 0 || s >= 4000 || s+f < 0 || s+f > 4000)
737                 vmerror("Bad src range MOVE %d:%d", s, s+f-1);
738         d = mval(ri[1], 0, MASK2);
739         if(d < 0 || d >= 4000 || d+f < 0 || d+f > 4000)
740                 vmerror("Bad dst range MOVE %d:%d", d, d+f-1);
741         p = cells+d;
742         q = cells+s;
743         pe = p+f;
744         while(p < pe)
745                 *p++ = *q++;
746         d += f;
747         d &= MASK2;
748         ri[1] = d < 0 ? -d|SIGNB : d;
749 }
750
751 u32int
752 mixld(u32int v, int f)
753 {
754         u32int w;
755         int a, b, d;
756
757         if(f == 5)
758                 return v;
759
760         UNF(a, b, f);
761         w = 0;
762         if(a == 0) {
763                 if(v >> 31)
764                         w = SIGNB;
765                 if(b == 0)
766                         return w;
767                 a++;
768         }
769
770         d = b - a;
771         if(a > 5 || b > 5 || d < 0 || d > 4)
772                 vmerror("Bad fpart (%d:%d)", a, b);
773         v &= mask[d] << (5-b) * BITS;
774         v >>= (5-b) * BITS;
775         return w | v;
776 }
777
778 u32int
779 mixst(u32int w, u32int v, int f)
780 {
781         int a, b, d;
782
783         if(f == 5)
784                 return v;
785
786         UNF(a, b, f);
787         if(a == 0) {
788                 w = v>>31 ? w|SIGNB : w&~SIGNB;
789                 if(b == 0)
790                         return w;
791                 a++;
792         }
793
794         d = b - a;
795         if(a > 5 || b > 5 || d < 0 || d > 4)
796                 vmerror("Bad fpart (%d:%d)", a, b);
797         v &= mask[d];
798         v <<= (5-b) * BITS;
799         w &= ~(mask[d] << (5-b)*BITS);
800         return w | v;
801 }
802
803 int
804 mixjbus(int /*m*/, int /*f*/, int ip)
805 {
806         return ip+1;
807 }
808
809 void
810 mixioc(int, int f)
811 {
812         switch(f) {
813         case 18:
814         case 19:
815                 print("\n");
816                 break;
817         }
818 }
819
820 void mixin(int, int){}
821
822 void
823 mixout(int m, int f)
824 {
825         switch(f) {
826         case 18:
827                 mixprint(m, 24);
828                 break;
829         case 19:
830                 mixprint(m, 14);
831                 break;
832         }
833 }
834
835 int
836 mixjred(int m, int /*f*/, int /*ip*/)
837 {
838         return m;
839 }
840
841 int
842 mixjmp(int m, int ip)
843 {
844         ri[0] = ip+1 & MASK2;
845         return m;
846 }
847
848 int
849 mixjov(int m, int ip)
850 {
851         if(ot) {
852                 ot = 0;
853                 ri[0] = ip+1 & MASK2;
854                 return m;
855         }
856         return ip + 1;
857 }
858
859 int
860 mixjnov(int m, int ip)
861 {
862         if(ot) {
863                 ot = 0;
864                 return ip + 1;
865         }
866         ri[0] = ip+1 & MASK2;
867         return m;
868 }
869
870 int
871 mixjc(int m, int ip, int c1, int c2)
872 {
873         if(c1 || c2) {
874                 ri[0] = ip+1 & MASK2;
875                 return m;
876         }
877         return ip + 1;
878 }
879
880 int
881 mixjaxic(int m, int ip, u32int r, u32int msk, int f)
882 {
883         int v, c;
884
885         v = mval(r, 0, msk);
886         switch(f) {
887         default:        vmerror("Bad instruction JA condition: %d", f);
888         case 0: c = v < 0;      break;
889         case 1: c = v == 0;     break;
890         case 2: c = v > 0;      break;
891         case 3: c = v >= 0;     break;
892         case 4: c = v != 0;     break;
893         case 5: c = v <= 0;     break;
894         }
895
896         if(c) {
897                 ri[0] = ip+1 & MASK2;
898                 return m;
899         }
900         return ip + 1;
901 }
902
903 void
904 mixinc(int m, u32int *r)
905 {
906         int v;
907
908         v = mval(*r, 0, MASK5);
909         v += m;
910         *r = v < 0 ? -v|SIGNB : v;
911 }
912
913 void mixfcmp(void){}
914
915 void
916 mixcmp(int m, int f, u32int r)
917 {
918         int v1, v2;
919
920         ce = cg = cl = 0;
921
922         v1 = V(r, f);
923         v2 = V(cells[m], f);
924         if(v1 < v2)
925                 cl = 1;
926         else if(v1 > v2)
927                 cg = 1;
928         else
929                 ce = 1;
930 }
931
932 int
933 mixvm(int ip, int once)
934 {
935         u32int r;
936         int a, i, f, c, m, inst;
937
938         curpc = ip;
939         for (;;) {
940                 if(curpc < 0 || curpc > 4000)
941                         vmerror("Bad PC %d", curpc);
942                 if(bp[curpc] && !once)
943                         return curpc;
944                 inst = cells[curpc];
945                 a = V(inst, F(0, 2));
946                 i = V(inst, F(3, 3));
947                 f = V(inst, F(4, 4));
948                 c = V(inst, F(5, 5));
949                 m = M(a, i);
950                 switch(c) {
951                 default:
952                         fprint(2, "Bad op!\n");
953                         exits("error");
954                 case 0:
955                         break;
956                 case 1:
957                         if(f == 6)
958                                 mixfadd(inst);
959                         else
960                                 mixadd(m, f);
961                         break;
962                 case 2:
963                         if(f == 6)
964                                 mixfsub(inst);
965                         else
966                                 mixsub(m, f);
967                         break;
968                 case 3:
969                         if(f == 6)
970                                 mixfmul(inst);
971                         else
972                                 mixmul(m, f);
973                         break;
974                 case 4:
975                         if(f == 6)
976                                 mixfdiv(inst);
977                         else
978                                 mixdiv(m, f);
979                         break;
980                 case 5:
981                         switch(f) {
982                         default:
983                                 vmerror("Bad instruction NUM or CHAR: %d", f);
984                         case 0:
985                                 mixnum();
986                                 break;
987                         case 1:
988                                 mixchar();
989                                 break;
990                         case 2:
991                                 return -1;      /* HLT */
992                         }
993                         break;
994                 case 6:
995                         switch(f) {
996                         default: vmerror("Bad instruction shift: %d", f);
997                         case 0: mixslra(m, 1);  break;
998                         case 1: mixslra(m, 0);  break;
999                         case 2: mixslrax(m, 1); break;
1000                         case 3: mixslrax(m, 0); break;
1001                         case 4: mixslc(m);      break;
1002                         case 5: mixsrc(m);      break;
1003                         }
1004                         break;
1005                 case 7:
1006                         mixmove(m, f);
1007                         break;
1008                 case 8:
1009                         ra = mixld(cells[m], f);
1010                         break;
1011                 case 9: case 10: case 11:
1012                 case 12: case 13: case 14:
1013                         ri[c-8] = mixld(cells[m], f);
1014                         break;
1015                 case 15:
1016                         rx = mixld(cells[m], f);
1017                         break;
1018                 case 16:
1019                         ra = mixld(cells[m], f) ^ SIGNB;
1020                         break;
1021                 case 17: case 18: case 19:
1022                 case 20: case 21: case 22:
1023                         ri[c-16] = mixld(cells[m], f) ^ SIGNB;
1024                         break;
1025                 case 23:
1026                         rx = mixld(cells[m], f) ^ SIGNB;
1027                         break;
1028                 case 24:
1029                         cells[m] = mixst(cells[m], ra, f);
1030                         break;
1031                 case 25: case 26: case 27:
1032                 case 28: case 29: case 30:
1033                         r = ri[c-24] & ~(MASK3 << 2*BITS);
1034                         cells[m] = mixst(cells[m], r, f);
1035                         break;
1036                 case 31:
1037                         cells[m] = mixst(cells[m], rx, f);
1038                         break;
1039                 case 32:
1040                         r = ri[0] & ~(MASK3 << 2*BITS);
1041                         cells[m] = mixst(cells[m], r, f);
1042                         break;
1043                 case 33:
1044                         cells[m] = mixst(cells[m], 0, f);
1045                         break;
1046                 case 34:
1047                         curpc = mixjbus(m, f, curpc);
1048                         goto Again;
1049                 case 35:
1050                         mixioc(m, f);
1051                         break;
1052                 case 36:
1053                         mixin(m, f);
1054                         break;
1055                 case 37:
1056                         mixout(m, f);
1057                         break;
1058                 case 38:
1059                         curpc = mixjred(m, f, curpc);
1060                         break;
1061                 case 39:
1062                         switch(f) {
1063                         default: vmerror("Bad jmp instruction: %d", f);
1064                         case 0: curpc = mixjmp(m, curpc);       break;
1065                         case 1: curpc = m;      break;  /* JSJ */
1066                         case 2: curpc = mixjov(m, curpc);       break;
1067                         case 3: curpc = mixjnov(m, curpc);      break;
1068                         case 4: curpc = mixjc(m, curpc, cl, 0); break;
1069                         case 5: curpc = mixjc(m, curpc, ce, 0); break;
1070                         case 6: curpc = mixjc(m, curpc, cg, 0); break;
1071                         case 7: curpc = mixjc(m, curpc, cg, ce);        break;
1072                         case 8: curpc = mixjc(m, curpc, cl, cg);        break;
1073                         case 9: curpc = mixjc(m, curpc, cl, ce);        break;
1074                         }
1075                         goto Again;
1076                 case 40:
1077                         curpc = mixjaxic(m, curpc, ra, MASK5, f);
1078                         goto Again;
1079                 case 41: case 42: case 43:
1080                 case 44: case 45: case 46:
1081                         curpc = mixjaxic(m, curpc, ri[c-40], MASK2, f);
1082                         goto Again;
1083                 case 47:
1084                         curpc = mixjaxic(m, curpc, rx, MASK5, f);
1085                         goto Again;
1086                 case 48:
1087                         switch(f) {
1088                         case 0: mixinc(m, &ra); break;
1089                         case 1: mixinc(-m, &ra);        break;
1090                         case 2:
1091                                 ra = m == 0
1092                                         ? inst & SIGNB
1093                                         : m < 0 ? -m|SIGNB : m;
1094                                 break;  /* ENTA */
1095                         case 3:
1096                                 ra = m == 0
1097                                         ? ~inst & SIGNB
1098                                         : m > 0 ? m|SIGNB : -m;
1099                                 break;  /* ENNA */
1100                         }
1101                         break;
1102                 case 49: case 50: case 51:
1103                 case 52: case 53: case 54:
1104                         switch(f) {
1105                         case 0: mixinc(m, ri+(c-48));   break;
1106                         case 1: mixinc(-m, ri+(c-48));  break;
1107                         case 2:
1108                                 ri[c-48] = m == 0
1109                                         ? inst & SIGNB
1110                                         : m < 0 ? -m|SIGNB : m;
1111                                 break;  /* ENT[1-6] */
1112                         case 3:
1113                                 ri[c-48] = m == 0
1114                                         ? ~inst & SIGNB
1115                                         : m > 0 ? m|SIGNB : -m;
1116                                 break;  /* ENN[1-6] */
1117                         }
1118                         break;
1119                 case 55:
1120                         switch(f) {
1121                         case 0: mixinc(m, &rx); break;
1122                         case 1: mixinc(-m, &rx);        break;
1123                         case 2: rx = m == 0
1124                                         ? inst & SIGNB
1125                                         : m < 0 ? -m|SIGNB : m;
1126                                 break;  /* ENTX */
1127                         case 3: rx = m == 0
1128                                         ? ~inst & SIGNB
1129                                         : m > 0 ? m|SIGNB : -m;
1130                                 break;  /* ENNX */
1131                         }
1132                         break;
1133                 case 56:
1134                         if(f == 6)
1135                                 mixfcmp();
1136                         else
1137                                 mixcmp(m, f, ra);
1138                         break;
1139                 case 57: case 58: case 59:
1140                 case 60: case 61: case 62:
1141                         mixcmp(m, f, ri[c-56] & ~(MASK3<<2*BITS));
1142                         break;
1143                 case 63:
1144                         mixcmp(m, f, rx);
1145                         break;
1146                 }
1147                 curpc++;
1148 Again:
1149                 if(once)
1150                         return curpc;
1151         }
1152 }