]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vl/asm.c
9bootfat: rename open() to fileinit and make it static as its really a internal funct...
[plan9front.git] / sys / src / cmd / vl / asm.c
1 #include        "l.h"
2
3 long    OFFSET;
4 /*
5 long    BADOFFSET       =       -1;
6
7                 if(OFFSET <= BADOFFSET && OFFSET+4 > BADOFFSET)\
8                         abort();\
9                 OFFSET += 4;\
10
11                 if(OFFSET == BADOFFSET)\
12                         abort();\
13                 OFFSET++;\
14 */
15
16 #define LPUT(l) { \
17                 if (little) { \
18                         LLEPUT(l); \
19                 } else { \
20                         LBEPUT(l); \
21                 } \
22         }
23
24 #define LLEPUT(c)\
25         {\
26                 cbp[0] = (c);\
27                 cbp[1] = (c)>>8;\
28                 cbp[2] = (c)>>16;\
29                 cbp[3] = (c)>>24;\
30                 cbp += 4;\
31                 cbc -= 4;\
32                 if(cbc <= 0)\
33                         cflush();\
34         }
35
36 #define LBEPUT(c)\
37         {\
38                 cbp[0] = (c)>>24;\
39                 cbp[1] = (c)>>16;\
40                 cbp[2] = (c)>>8;\
41                 cbp[3] = (c);\
42                 cbp += 4;\
43                 cbc -= 4;\
44                 if(cbc <= 0)\
45                         cflush();\
46         }
47
48 #define HPUT(h) { \
49                 if (little) { \
50                         HLEPUT(h); \
51                 } else { \
52                         HBEPUT(h); \
53                 } \
54         }
55
56 #define HLEPUT(c)\
57         {\
58                 cbp[0] = (c);\
59                 cbp[1] = (c)>>8;\
60                 cbp += 2;\
61                 cbc -= 2;\
62                 if(cbc <= 0)\
63                         cflush();\
64         }
65
66 #define HBEPUT(c)\
67         {\
68                 cbp[0] = (c)>>8;\
69                 cbp[1] = (c);\
70                 cbp += 2;\
71                 cbc -= 2;\
72                 if(cbc <= 0)\
73                         cflush();\
74         }
75
76
77 #define CPUT(c)\
78         {\
79                 cbp[0] = (c);\
80                 cbp++;\
81                 cbc--;\
82                 if(cbc <= 0)\
83                         cflush();\
84         }
85
86 void
87 objput(long l)  /* emit long in byte order appropriate to object machine */
88 {
89         LPUT(l);
90 }
91
92 void
93 objhput(short s)
94 {
95         HPUT(s);
96 }
97
98 void
99 lput(long l)            /* emit long in big-endian byte order */
100 {
101         LBEPUT(l);
102 }
103
104 long
105 entryvalue(void)
106 {
107         char *a;
108         Sym *s;
109
110         a = INITENTRY;
111         if(*a >= '0' && *a <= '9')
112                 return atolwhex(a);
113         s = lookup(a, 0);
114         if(s->type == 0)
115                 return INITTEXT;
116         if(s->type != STEXT && s->type != SLEAF)
117                 diag("entry not text: %s", s->name);
118         return s->value;
119 }
120
121 void
122 asmb(void)
123 {
124         Prog *p;
125         long t, etext;
126         Optab *o;
127
128         if(debug['v'])
129                 Bprint(&bso, "%5.2f asm\n", cputime());
130         Bflush(&bso);
131         OFFSET = HEADR;
132         seek(cout, OFFSET, 0);
133         pc = INITTEXT;
134         for(p = firstp; p != P; p = p->link) {
135                 if(p->as == ATEXT) {
136                         curtext = p;
137                         autosize = p->to.offset + 4;
138                 }
139                 if(p->pc != pc) {
140                         diag("phase error %lux sb %lux",
141                                 p->pc, pc);
142                         if(!debug['a'])
143                                 prasm(curp);
144                         pc = p->pc;
145                 }
146                 curp = p;
147                 o = oplook(p);  /* could probably avoid this call */
148                 if(asmout(p, o, 0)) {
149                         p = p->link;
150                         pc += 4;
151                 }
152                 pc += o->size;
153         }
154         if(debug['a'])
155                 Bprint(&bso, "\n");
156         Bflush(&bso);
157         cflush();
158
159         etext = INITTEXT + textsize;
160         for(t = pc; t < etext; t += sizeof(buf)-100) {
161                 if(etext-t > sizeof(buf)-100)
162                         datblk(t, sizeof(buf)-100, 1);
163                 else
164                         datblk(t, etext-t, 1);
165         }
166
167         Bflush(&bso);
168         cflush();
169
170         curtext = P;
171         switch(HEADTYPE) {
172         case 0:
173         case 4:
174                 OFFSET = rnd(HEADR+textsize, 4096);
175                 seek(cout, OFFSET, 0);
176                 break;
177         case 1:
178         case 2:
179         case 3:
180         case 5:
181         case 6:
182                 OFFSET = HEADR+textsize;
183                 seek(cout, OFFSET, 0);
184                 break;
185         }
186         for(t = 0; t < datsize; t += sizeof(buf)-100) {
187                 if(datsize-t > sizeof(buf)-100)
188                         datblk(t, sizeof(buf)-100, 0);
189                 else
190                         datblk(t, datsize-t, 0);
191         }
192
193         symsize = 0;
194         lcsize = 0;
195         if(!debug['s']) {
196                 if(debug['v'])
197                         Bprint(&bso, "%5.2f sym\n", cputime());
198                 Bflush(&bso);
199                 switch(HEADTYPE) {
200                 case 0:
201                 case 4:
202                         OFFSET = rnd(HEADR+textsize, 4096)+datsize;
203                         seek(cout, OFFSET, 0);
204                         break;
205                 case 3:
206                 case 2:
207                 case 1:
208                 case 5:
209                 case 6:
210                         OFFSET = HEADR+textsize+datsize;
211                         seek(cout, OFFSET, 0);
212                         break;
213                 }
214                 if(!debug['s'])
215                         asmsym();
216                 if(debug['v'])
217                         Bprint(&bso, "%5.2f pc\n", cputime());
218                 Bflush(&bso);
219                 if(!debug['s'])
220                         asmlc();
221                 cflush();
222         }
223
224         if(debug['v'])
225                 Bprint(&bso, "%5.2f header\n", cputime());
226         Bflush(&bso);
227         OFFSET = 0;
228         seek(cout, OFFSET, 0);
229         switch(HEADTYPE) {
230         case 0:
231                 lput(0x160L<<16);               /* magic and sections */
232                 lput(0L);                       /* time and date */
233                 lput(rnd(HEADR+textsize, 4096)+datsize);
234                 lput(symsize);                  /* nsyms */
235                 lput((0x38L<<16)|7L);           /* size of optional hdr and flags */
236                 lput((0413<<16)|0437L);         /* magic and version */
237                 lput(rnd(HEADR+textsize, 4096));        /* sizes */
238                 lput(datsize);
239                 lput(bsssize);
240                 lput(entryvalue());             /* va of entry */
241                 lput(INITTEXT-HEADR);           /* va of base of text */
242                 lput(INITDAT);                  /* va of base of data */
243                 lput(INITDAT+datsize);          /* va of base of bss */
244                 lput(~0L);                      /* gp reg mask */
245                 lput(0L);
246                 lput(0L);
247                 lput(0L);
248                 lput(0L);
249                 lput(~0L);                      /* gp value ?? */
250                 break;
251         case 1:
252                 lput(0x160L<<16);               /* magic and sections */
253                 lput(0L);                       /* time and date */
254                 lput(HEADR+textsize+datsize);
255                 lput(symsize);                  /* nsyms */
256                 lput((0x38L<<16)|7L);           /* size of optional hdr and flags */
257
258                 lput((0407<<16)|0437L);         /* magic and version */
259                 lput(textsize);                 /* sizes */
260                 lput(datsize);
261                 lput(bsssize);
262                 lput(entryvalue());             /* va of entry */
263                 lput(INITTEXT);                 /* va of base of text */
264                 lput(INITDAT);                  /* va of base of data */
265                 lput(INITDAT+datsize);          /* va of base of bss */
266                 lput(~0L);                      /* gp reg mask */
267                 lput(lcsize);
268                 lput(0L);
269                 lput(0L);
270                 lput(0L);
271                 lput(~0L);                      /* gp value ?? */
272                 lput(0L);                       /* complete mystery */
273                 break;
274         case 2:
275                 if (little)
276                         t = 24;
277                 else
278                         t = 16;
279                 lput(((((4*t)+0)*t)+7));        /* magic */
280                 lput(textsize);                 /* sizes */
281                 lput(datsize);
282                 lput(bsssize);
283                 lput(symsize);                  /* nsyms */
284                 lput(entryvalue());             /* va of entry */
285                 lput(0L);
286                 lput(lcsize);
287                 break;
288         case 3:
289                 lput((0x160L<<16)|3L);          /* magic and sections */
290                 lput(time(0));                  /* time and date */
291                 lput(HEADR+textsize+datsize);
292                 lput(symsize);                  /* nsyms */
293                 lput((0x38L<<16)|7L);           /* size of optional hdr and flags */
294
295                 lput((0407<<16)|0437L);         /* magic and version */
296                 lput(textsize);                 /* sizes */
297                 lput(datsize);
298                 lput(bsssize);
299                 lput(entryvalue());             /* va of entry */
300                 lput(INITTEXT);                 /* va of base of text */
301                 lput(INITDAT);                  /* va of base of data */
302                 lput(INITDAT+datsize);          /* va of base of bss */
303                 lput(~0L);                      /* gp reg mask */
304                 lput(lcsize);
305                 lput(0L);
306                 lput(0L);
307                 lput(0L);
308                 lput(~0L);                      /* gp value ?? */
309
310                 strnput(".text", 8);            /* text segment */
311                 lput(INITTEXT);                 /* address */
312                 lput(INITTEXT);
313                 lput(textsize);
314                 lput(HEADR);
315                 lput(0L);
316                 lput(HEADR+textsize+datsize+symsize);
317                 lput(lcsize);                   /* line number size */
318                 lput(0x20L);                    /* flags */
319
320                 strnput(".data", 8);            /* data segment */
321                 lput(INITDAT);                  /* address */
322                 lput(INITDAT);
323                 lput(datsize);
324                 lput(HEADR+textsize);
325                 lput(0L);
326                 lput(0L);
327                 lput(0L);
328                 lput(0x40L);                    /* flags */
329
330                 strnput(".bss", 8);             /* bss segment */
331                 lput(INITDAT+datsize);          /* address */
332                 lput(INITDAT+datsize);
333                 lput(bsssize);
334                 lput(0L);
335                 lput(0L);
336                 lput(0L);
337                 lput(0L);
338                 lput(0x80L);                    /* flags */
339                 break;
340         case 4:
341
342                 lput((0x160L<<16)|3L);          /* magic and sections */
343                 lput(time(0));                  /* time and date */
344                 lput(rnd(HEADR+textsize, 4096)+datsize);
345                 lput(symsize);                  /* nsyms */
346                 lput((0x38L<<16)|7L);           /* size of optional hdr and flags */
347
348                 lput((0413<<16)|01012L);        /* magic and version */
349                 lput(textsize);                 /* sizes */
350                 lput(datsize);
351                 lput(bsssize);
352                 lput(entryvalue());             /* va of entry */
353                 lput(INITTEXT);                 /* va of base of text */
354                 lput(INITDAT);                  /* va of base of data */
355                 lput(INITDAT+datsize);          /* va of base of bss */
356                 lput(~0L);                      /* gp reg mask */
357                 lput(lcsize);
358                 lput(0L);
359                 lput(0L);
360                 lput(0L);
361                 lput(~0L);                      /* gp value ?? */
362
363                 strnput(".text", 8);            /* text segment */
364                 lput(INITTEXT);                 /* address */
365                 lput(INITTEXT);
366                 lput(textsize);
367                 lput(HEADR);
368                 lput(0L);
369                 lput(HEADR+textsize+datsize+symsize);
370                 lput(lcsize);                   /* line number size */
371                 lput(0x20L);                    /* flags */
372
373                 strnput(".data", 8);            /* data segment */
374                 lput(INITDAT);                  /* address */
375                 lput(INITDAT);
376                 lput(datsize);
377                 lput(rnd(HEADR+textsize, 4096));        /* sizes */
378                 lput(0L);
379                 lput(0L);
380                 lput(0L);
381                 lput(0x40L);                    /* flags */
382
383                 strnput(".bss", 8);             /* bss segment */
384                 lput(INITDAT+datsize);          /* address */
385                 lput(INITDAT+datsize);
386                 lput(bsssize);
387                 lput(0L);
388                 lput(0L);
389                 lput(0L);
390                 lput(0L);
391                 lput(0x80L);                    /* flags */
392                 break;
393         case 5:
394                 /* first part of ELF is byte-wide parts, thus no byte-order issues */
395                 strnput("\177ELF", 4);          /* e_ident */
396                 CPUT(1);                        /* class = 32 bit */
397                 CPUT(little? 1: 2);             /* data: 1 = LSB, 2 = MSB */
398                 CPUT(1);                        /* version = 1 */
399                 strnput("", 9);                 /* reserved for expansion */
400                 /* entire remainder of ELF file is in target byte order */
401
402                 /* file header part of ELF header */
403                 objhput(2);                     /* type = EXEC */
404                 objhput(8);                     /* machine = MIPS */
405                 objput(1L);                     /* version = CURRENT */
406                 objput(entryvalue());           /* entry vaddr */
407                 objput(52L);                    /* offset to first phdr */
408                 objput(0L);                     /* offset to first shdr */
409                 objput(0L);                     /* flags (no MIPS flags defined) */
410                 objhput(52);                    /* Ehdr size */
411                 objhput(32);                    /* Phdr size */
412                 objhput(3);                     /* # of Phdrs */
413                 objhput(0);                     /* Shdr size */
414                 objhput(0);                     /* # of Shdrs */
415                 objhput(0);                     /* Shdr string size */
416
417                 /* "Program headers" - one per chunk of file to load */
418
419                 /*
420                  * include ELF headers in text -- 8l doesn't,
421                  * but in theory it aids demand loading.
422                  */
423                 objput(1L);                     /* text: type = PT_LOAD */
424                 objput(0L);                     /* file offset */
425                 objput(INITTEXT-HEADR);         /* vaddr */
426                 objput(INITTEXT-HEADR);         /* paddr */
427                 objput(HEADR+textsize);         /* file size */
428                 objput(HEADR+textsize);         /* memory size */
429                 objput(0x05L);                  /* protections = RX */
430                 objput(0x1000L);                /* page-align text off's & vaddrs */
431
432                 objput(1L);                     /* data: type = PT_LOAD */
433                 objput(HEADR+textsize);         /* file offset */
434                 objput(INITDAT);                /* vaddr */
435                 objput(INITDAT);                /* paddr */
436                 objput(datsize);                /* file size */
437                 objput(datsize+bsssize);        /* memory size */
438                 objput(0x06L);                  /* protections = RW */
439                 if(INITDAT % 4096 == 0 && (HEADR + textsize) % 4096 == 0)
440                         objput(0x1000L);        /* page-align data off's & vaddrs */
441                 else
442                         objput(0L);             /* do not claim alignment */
443
444                 objput(0L);                     /* P9 symbols: type = PT_NULL */
445                 objput(HEADR+textsize+datsize); /* file offset */
446                 objput(0L);
447                 objput(0L);
448                 objput(symsize);                /* symbol table size */
449                 objput(lcsize);                 /* line number size */
450                 objput(0x04L);                  /* protections = R */
451                 objput(0L);                     /* do not claim alignment */
452                 break;
453         case 6:
454                 break;
455         }
456         cflush();
457 }
458
459 void
460 strnput(char *s, int n)
461 {
462         for(; *s; s++){
463                 CPUT(*s);
464                 n--;
465         }
466         for(; n > 0; n--)
467                 CPUT(0);
468 }
469
470 void
471 cflush(void)
472 {
473         int n;
474
475         n = sizeof(buf.cbuf) - cbc;
476         if(n)
477                 write(cout, buf.cbuf, n);
478         cbp = buf.cbuf;
479         cbc = sizeof(buf.cbuf);
480 }
481
482 void
483 nopstat(char *f, Count *c)
484 {
485         if(c->outof)
486         Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
487                 c->outof - c->count, c->outof,
488                 (double)(c->outof - c->count)/c->outof);
489 }
490
491 void
492 asmsym(void)
493 {
494         Prog *p;
495         Auto *a;
496         Sym *s;
497         int h;
498
499         s = lookup("etext", 0);
500         if(s->type == STEXT)
501                 putsymb(s->name, 'T', s->value, s->version);
502
503         for(h=0; h<NHASH; h++)
504                 for(s=hash[h]; s!=S; s=s->link)
505                         switch(s->type) {
506                         case SCONST:
507                                 putsymb(s->name, 'D', s->value, s->version);
508                                 continue;
509
510                         case SSTRING:
511                                 putsymb(s->name, 'T', s->value, s->version);
512                                 continue;
513
514                         case SDATA:
515                                 putsymb(s->name, 'D', s->value+INITDAT, s->version);
516                                 continue;
517
518                         case SBSS:
519                                 putsymb(s->name, 'B', s->value+INITDAT, s->version);
520                                 continue;
521
522                         case SFILE:
523                                 putsymb(s->name, 'f', s->value, s->version);
524                                 continue;
525                         }
526
527         for(p=textp; p!=P; p=p->cond) {
528                 s = p->from.sym;
529                 if(s->type != STEXT && s->type != SLEAF)
530                         continue;
531
532                 /* filenames first */
533                 for(a=p->to.autom; a; a=a->link)
534                         if(a->type == D_FILE)
535                                 putsymb(a->asym->name, 'z', a->aoffset, 0);
536                         else
537                         if(a->type == D_FILE1)
538                                 putsymb(a->asym->name, 'Z', a->aoffset, 0);
539
540                 if(s->type == STEXT)
541                         putsymb(s->name, 'T', s->value, s->version);
542                 else
543                         putsymb(s->name, 'L', s->value, s->version);
544
545                 /* frame, auto and param after */
546                 putsymb(".frame", 'm', p->to.offset+4, 0);
547                 for(a=p->to.autom; a; a=a->link)
548                         if(a->type == D_AUTO)
549                                 putsymb(a->asym->name, 'a', -a->aoffset, 0);
550                         else
551                         if(a->type == D_PARAM)
552                                 putsymb(a->asym->name, 'p', a->aoffset, 0);
553         }
554         if(debug['v'] || debug['n'])
555                 Bprint(&bso, "symsize = %lud\n", symsize);
556         Bflush(&bso);
557 }
558
559 void
560 putsymb(char *s, int t, long v, int ver)
561 {
562         int i, f;
563
564         if(t == 'f')
565                 s++;
566         LBEPUT(v);
567         if(ver)
568                 t += 'a' - 'A';
569         CPUT(t+0x80);                   /* 0x80 is variable length */
570
571         if(t == 'Z' || t == 'z') {
572                 CPUT(s[0]);
573                 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
574                         CPUT(s[i]);
575                         CPUT(s[i+1]);
576                 }
577                 CPUT(0);
578                 CPUT(0);
579                 i++;
580         }
581         else {
582                 for(i=0; s[i]; i++)
583                         CPUT(s[i]);
584                 CPUT(0);
585         }
586         symsize += 4 + 1 + i + 1;
587
588         if(debug['n']) {
589                 if(t == 'z' || t == 'Z') {
590                         Bprint(&bso, "%c %.8lux ", t, v);
591                         for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
592                                 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
593                                 Bprint(&bso, "/%x", f);
594                         }
595                         Bprint(&bso, "\n");
596                         return;
597                 }
598                 if(ver)
599                         Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
600                 else
601                         Bprint(&bso, "%c %.8lux %s\n", t, v, s);
602         }
603 }
604
605 #define MINLC   4
606 void
607 asmlc(void)
608 {
609         long oldpc, oldlc;
610         Prog *p;
611         long v, s;
612
613         oldpc = INITTEXT;
614         oldlc = 0;
615         for(p = firstp; p != P; p = p->link) {
616                 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
617                         if(p->as == ATEXT)
618                                 curtext = p;
619                         if(debug['L'])
620                                 Bprint(&bso, "%6lux %P\n",
621                                         p->pc, p);
622                         continue;
623                 }
624                 if(debug['L'])
625                         Bprint(&bso, "\t\t%6ld", lcsize);
626                 v = (p->pc - oldpc) / MINLC;
627                 while(v) {
628                         s = 127;
629                         if(v < 127)
630                                 s = v;
631                         CPUT(s+128);    /* 129-255 +pc */
632                         if(debug['L'])
633                                 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
634                         v -= s;
635                         lcsize++;
636                 }
637                 s = p->line - oldlc;
638                 oldlc = p->line;
639                 oldpc = p->pc + MINLC;
640                 if(s > 64 || s < -64) {
641                         CPUT(0);        /* 0 vv +lc */
642                         CPUT(s>>24);
643                         CPUT(s>>16);
644                         CPUT(s>>8);
645                         CPUT(s);
646                         if(debug['L']) {
647                                 if(s > 0)
648                                         Bprint(&bso, " lc+%ld(%d,%ld)\n",
649                                                 s, 0, s);
650                                 else
651                                         Bprint(&bso, " lc%ld(%d,%ld)\n",
652                                                 s, 0, s);
653                                 Bprint(&bso, "%6lux %P\n",
654                                         p->pc, p);
655                         }
656                         lcsize += 5;
657                         continue;
658                 }
659                 if(s > 0) {
660                         CPUT(0+s);      /* 1-64 +lc */
661                         if(debug['L']) {
662                                 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
663                                 Bprint(&bso, "%6lux %P\n",
664                                         p->pc, p);
665                         }
666                 } else {
667                         CPUT(64-s);     /* 65-128 -lc */
668                         if(debug['L']) {
669                                 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
670                                 Bprint(&bso, "%6lux %P\n",
671                                         p->pc, p);
672                         }
673                 }
674                 lcsize++;
675         }
676         while(lcsize & 1) {
677                 s = 129;
678                 CPUT(s);
679                 lcsize++;
680         }
681         if(debug['v'] || debug['L'])
682                 Bprint(&bso, "lcsize = %ld\n", lcsize);
683         Bflush(&bso);
684 }
685
686 void
687 datblk(long s, long n, int str)
688 {
689         Prog *p;
690         char *cast;
691         long l, fl, j, d;
692         int i, c;
693
694         memset(buf.dbuf, 0, n+100);
695         for(p = datap; p != P; p = p->link) {
696                 curp = p;
697                 if(str != (p->from.sym->type == SSTRING))
698                         continue;
699                 l = p->from.sym->value + p->from.offset - s;
700                 c = p->reg;
701                 i = 0;
702                 if(l < 0) {
703                         if(l+c <= 0)
704                                 continue;
705                         while(l < 0) {
706                                 l++;
707                                 i++;
708                         }
709                 }
710                 if(l >= n)
711                         continue;
712                 if(p->as != AINIT && p->as != ADYNT) {
713                         for(j=l+(c-i)-1; j>=l; j--)
714                                 if(buf.dbuf[j]) {
715                                         print("%P\n", p);
716                                         diag("multiple initialization");
717                                         break;
718                                 }
719                 }
720                 switch(p->to.type) {
721                 default:
722                         diag("unknown mode in initialization\n%P", p);
723                         break;
724
725                 case D_FCONST:
726                         switch(c) {
727                         default:
728                         case 4:
729                                 fl = ieeedtof(p->to.ieee);
730                                 cast = (char*)&fl;
731                                 for(; i<c; i++) {
732                                         buf.dbuf[l] = cast[fnuxi8[i+4]];
733                                         l++;
734                                 }
735                                 break;
736                         case 8:
737                                 cast = (char*)p->to.ieee;
738                                 for(; i<c; i++) {
739                                         buf.dbuf[l] = cast[fnuxi8[i]];
740                                         l++;
741                                 }
742                                 break;
743                         }
744                         break;
745
746                 case D_SCONST:
747                         for(; i<c; i++) {
748                                 buf.dbuf[l] = p->to.sval[i];
749                                 l++;
750                         }
751                         break;
752
753                 case D_CONST:
754                         d = p->to.offset;
755                         if(p->to.sym) {
756                                 switch(p->to.sym->type) {
757                                 case STEXT:
758                                 case SLEAF:
759                                 case SSTRING:
760                                         d += p->to.sym->value;
761                                         break;
762                                 case SDATA:
763                                 case SBSS:
764                                         d += p->to.sym->value + INITDAT;
765                                         break;
766                                 }
767                         }
768                         cast = (char*)&d;
769                         switch(c) {
770                         default:
771                                 diag("bad nuxi %d %d\n%P", c, i, curp);
772                                 break;
773                         case 1:
774                                 for(; i<c; i++) {
775                                         buf.dbuf[l] = cast[inuxi1[i]];
776                                         l++;
777                                 }
778                                 break;
779                         case 2:
780                                 for(; i<c; i++) {
781                                         buf.dbuf[l] = cast[inuxi2[i]];
782                                         l++;
783                                 }
784                                 break;
785                         case 4:
786                                 for(; i<c; i++) {
787                                         buf.dbuf[l] = cast[inuxi4[i]];
788                                         l++;
789                                 }
790                                 break;
791                         }
792                         break;
793                 }
794         }
795         write(cout, buf.dbuf, n);
796 }
797
798 #define OP_RRR(op,r1,r2,r3)\
799         (op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|(((r3)&31L)<<11))
800 #define OP_IRR(op,i,r2,r3)\
801         (op|((i)&0xffffL)|(((r2)&31L)<<21)|(((r3)&31L)<<16))
802 #define OP_SRR(op,s,r2,r3)\
803         (op|(((s)&31L)<<6)|(((r2)&31L)<<16)|(((r3)&31L)<<11))
804 #define OP_FRRR(op,r1,r2,r3)\
805         (op|(((r1)&31L)<<16)|(((r2)&31L)<<11)|(((r3)&31L)<<6))
806 #define OP_JMP(op,i)\
807                 ((op)|((i)&0x3ffffffL))
808
809 #define OP(x,y)\
810         (((x)<<3)|((y)<<0))
811 #define SP(x,y)\
812         (((x)<<29)|((y)<<26))
813 #define BCOND(x,y)\
814         (((x)<<19)|((y)<<16))
815 #define MMU(x,y)\
816         (SP(2,0)|(16<<21)|((x)<<3)|((y)<<0))
817 #define FPF(x,y)\
818         (SP(2,1)|(16<<21)|((x)<<3)|((y)<<0))
819 #define FPD(x,y)\
820         (SP(2,1)|(17<<21)|((x)<<3)|((y)<<0))
821 #define FPW(x,y)\
822         (SP(2,1)|(20<<21)|((x)<<3)|((y)<<0))
823
824 int vshift(int);
825
826 int
827 asmout(Prog *p, Optab *o, int aflag)
828 {
829         long o1, o2, o3, o4, o5, o6, o7, v;
830         Prog *ct;
831         int r, a;
832
833         o1 = 0;
834         o2 = 0;
835         o3 = 0;
836         o4 = 0;
837         o5 = 0;
838         o6 = 0;
839         o7 = 0;
840         switch(o->type) {
841         default:
842                 diag("unknown type %d", o->type);
843                 if(!debug['a'])
844                         prasm(p);
845                 break;
846
847         case 0:         /* pseudo ops */
848                 if(aflag) {
849                         if(p->link) {
850                                 if(p->as == ATEXT) {
851                                         ct = curtext;
852                                         o2 = autosize;
853                                         curtext = p;
854                                         autosize = p->to.offset + 4;
855                                         o1 = asmout(p->link, oplook(p->link), aflag);
856                                         curtext = ct;
857                                         autosize = o2;
858                                 } else
859                                         o1 = asmout(p->link, oplook(p->link), aflag);
860                         }
861                         return o1;
862                 }
863                 break;
864
865         case 1:         /* mov[v] r1,r2 ==> OR r1,r0,r2 */
866                 o1 = OP_RRR(oprrr(AOR), p->from.reg, REGZERO, p->to.reg);
867                 break;
868
869         case 2:         /* add/sub r1,[r2],r3 */
870                 r = p->reg;
871                 if(r == NREG)
872                         r = p->to.reg;
873                 o1 = OP_RRR(oprrr(p->as), p->from.reg, r, p->to.reg);
874                 break;
875
876         case 3:         /* mov $soreg, r ==> or/add $i,o,r */
877                 v = regoff(&p->from);
878                 r = p->from.reg;
879                 if(r == NREG)
880                         r = o->param;
881                 a = AADDU;
882                 if(o->a1 == C_ANDCON)
883                         a = AOR;
884                 o1 = OP_IRR(opirr(a), v, r, p->to.reg);
885                 break;
886
887         case 4:         /* add $scon,[r1],r2 */
888                 v = regoff(&p->from);
889                 r = p->reg;
890                 if(r == NREG)
891                         r = p->to.reg;
892                 o1 = OP_IRR(opirr(p->as), v, r, p->to.reg);
893                 break;
894
895         case 5:         /* syscall */
896                 if(aflag)
897                         return 0;
898                 o1 = oprrr(p->as);
899                 break;
900
901         case 6:         /* beq r1,[r2],sbra */
902                 if(aflag)
903                         return 0;
904                 if(p->cond == P)
905                         v = -4 >> 2;
906                 else
907                         v = (p->cond->pc - pc-4) >> 2;
908                 if(((v << 16) >> 16) != v)
909                         diag("short branch too far: %ld\n%P", v, p);
910                 o1 = OP_IRR(opirr(p->as), v, p->from.reg, p->reg);
911                 break;
912
913         case 7:         /* mov r, soreg ==> sw o(r) */
914                 r = p->to.reg;
915                 if(r == NREG)
916                         r = o->param;
917                 v = regoff(&p->to);
918                 o1 = OP_IRR(opirr(p->as), v, r, p->from.reg);
919                 break;
920
921         case 8:         /* mov soreg, r ==> lw o(r) */
922                 r = p->from.reg;
923                 if(r == NREG)
924                         r = o->param;
925                 v = regoff(&p->from);
926                 o1 = OP_IRR(opirr(p->as+ALAST), v, r, p->to.reg);
927                 break;
928
929         case 9:         /* asl r1,[r2],r3 */
930                 r = p->reg;
931                 if(r == NREG)
932                         r = p->to.reg;
933                 o1 = OP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg);
934                 break;
935
936         case 10:        /* add $con,[r1],r2 ==> mov $con,t; add t,[r1],r2 */
937                 v = regoff(&p->from);
938                 r = AOR;
939                 if(v < 0)
940                         r = AADDU;
941                 o1 = OP_IRR(opirr(r), v, 0, REGTMP);
942                 r = p->reg;
943                 if(r == NREG)
944                         r = p->to.reg;
945                 o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
946                 break;
947
948         case 11:        /* jmp lbra */
949                 if(aflag)
950                         return 0;
951                 if(p->cond == P)
952                         v = p->pc >> 2;
953                 else
954                         v = p->cond->pc >> 2;
955                 o1 = OP_JMP(opirr(p->as), v);
956                 if(!debug['Y'] && p->link && p->cond && isnop(p->link)) {
957                         nop.branch.count--;
958                         nop.branch.outof--;
959                         nop.jump.outof++;
960                         o2 = asmout(p->cond, oplook(p->cond), 1);
961                         if(o2) {
962                                 o1 += 1;
963                                 if(debug['a'])
964                                         Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n",
965                                                 p->pc, o1, o2, p);
966                                 LPUT(o1);
967                                 LPUT(o2);
968                                 return 1;
969                         }
970                 }
971                 break;
972
973         case 12:        /* movbs r,r */
974                 v = 16;
975                 if(p->as == AMOVB)
976                         v = 24;
977                 o1 = OP_SRR(opirr(ASLL), v, p->from.reg, p->to.reg);
978                 o2 = OP_SRR(opirr(ASRA), v, p->to.reg, p->to.reg);
979                 break;
980
981         case 13:        /* movbu r,r */
982                 if(p->as == AMOVBU)
983                         o1 = OP_IRR(opirr(AAND), 0xffL, p->from.reg, p->to.reg);
984                 else
985                         o1 = OP_IRR(opirr(AAND), 0xffffL, p->from.reg, p->to.reg);
986                 break;
987
988         case 16:        /* sll $c,[r1],r2 */
989                 v = regoff(&p->from);
990                 r = p->reg;
991                 if(r == NREG)
992                         r = p->to.reg;
993
994                 /* OP_SRR will use only the low 5 bits of the shift value */
995                 if(v >= 32 && vshift(p->as))
996                         o1 = OP_SRR(opirr(p->as+ALAST), v-32, r, p->to.reg);
997                 else 
998                         o1 = OP_SRR(opirr(p->as), v, r, p->to.reg);
999                 break;
1000
1001         case 18:        /* jmp [r1],0(r2) */
1002                 if(aflag)
1003                         return 0;
1004                 r = p->reg;
1005                 if(r == NREG)
1006                         r = o->param;
1007                 o1 = OP_RRR(oprrr(p->as), 0, p->to.reg, r);
1008                 break;
1009
1010         case 19:        /* mov $lcon,r ==> lu+or */
1011                 v = regoff(&p->from);
1012                 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
1013                 o2 = OP_IRR(opirr(AOR), v, p->to.reg, p->to.reg);
1014                 break;
1015
1016         case 20:        /* mov lohi,r */
1017                 r = OP(2,0);            /* mfhi */
1018                 if(p->from.type == D_LO)
1019                         r = OP(2,2);    /* mflo */
1020                 o1 = OP_RRR(r, REGZERO, REGZERO, p->to.reg);
1021                 break;
1022
1023         case 21:        /* mov r,lohi */
1024                 r = OP(2,1);            /* mthi */
1025                 if(p->to.type == D_LO)
1026                         r = OP(2,3);    /* mtlo */
1027                 o1 = OP_RRR(r, REGZERO, p->from.reg, REGZERO);
1028                 break;
1029
1030         case 22:        /* mul r1,r2 */
1031                 o1 = OP_RRR(oprrr(p->as), p->from.reg, p->reg, REGZERO);
1032                 break;
1033
1034         case 23:        /* add $lcon,r1,r2 ==> lu+or+add */
1035                 v = regoff(&p->from);
1036                 if(p->to.reg == REGTMP || p->reg == REGTMP)
1037                         diag("cant synthesize large constant\n%P", p);
1038                 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1039                 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1040                 r = p->reg;
1041                 if(r == NREG)
1042                         r = p->to.reg;
1043                 o3 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
1044                 break;
1045
1046         case 24:        /* mov $ucon,,r ==> lu r */
1047                 v = regoff(&p->from);
1048                 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
1049                 break;
1050
1051         case 25:        /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
1052                 v = regoff(&p->from);
1053                 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1054                 r = p->reg;
1055                 if(r == NREG)
1056                         r = p->to.reg;
1057                 o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
1058                 break;
1059
1060         case 26:        /* mov $lsext/auto/oreg,,r2 ==> lu+or+add */
1061                 v = regoff(&p->from);
1062                 if(p->to.reg == REGTMP)
1063                         diag("cant synthesize large constant\n%P", p);
1064                 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1065                 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1066                 r = p->from.reg;
1067                 if(r == NREG)
1068                         r = o->param;
1069                 o3 = OP_RRR(oprrr(AADDU), REGTMP, r, p->to.reg);
1070                 break;
1071
1072         case 27:                /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
1073                 r = p->from.reg;
1074                 if(r == NREG)
1075                         r = o->param;
1076                 v = regoff(&p->from);
1077                 switch(o->size) {
1078                 case 20:
1079                         o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1080                         o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1081                         o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1082                         o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg+1);
1083                         o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg);
1084                         break;
1085                 case 16:
1086                         o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1087                         o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1088                         o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1089                         o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg);
1090                         break;
1091                 case 8:
1092                         o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg+1);
1093                         o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg);
1094                         break;
1095                 case 4:
1096                         o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg);
1097                         break;
1098                 }
1099                 break;
1100
1101         case 28:                /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
1102                 r = p->to.reg;
1103                 if(r == NREG)
1104                         r = o->param;
1105                 v = regoff(&p->to);
1106                 switch(o->size) {
1107                 case 20:
1108                         if(r == REGTMP)
1109                                 diag("cant synthesize large constant\n%P", p);
1110                         o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1111                         o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1112                         o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1113                         o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg+1);
1114                         o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg);
1115                         break;
1116                 case 16:
1117                         if(r == REGTMP)
1118                                 diag("cant synthesize large constant\n%P", p);
1119                         o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1120                         o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1121                         o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1122                         o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg);
1123                         break;
1124                 case 8:
1125                         o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg+1);
1126                         o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg);
1127                         break;
1128                 case 4:
1129                         o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg);
1130                         break;
1131                 }
1132                 break;
1133
1134         case 30:        /* movw r,fr */
1135                 r = SP(2,1)|(4<<21);            /* mtc1 */
1136                 o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
1137                 break;
1138
1139         case 31:        /* movw fr,r */
1140                 r = SP(2,1)|(0<<21);            /* mfc1 */
1141                 o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
1142                 break;
1143
1144         case 32:        /* fadd fr1,[fr2],fr3 */
1145                 r = p->reg;
1146                 if(r == NREG)
1147                         o1 = OP_FRRR(oprrr(p->as), p->from.reg, p->to.reg, p->to.reg);
1148                 else
1149                         o1 = OP_FRRR(oprrr(p->as), p->from.reg, r, p->to.reg);
1150                 break;
1151
1152         case 33:        /* fabs fr1,fr3 */
1153                 o1 = OP_FRRR(oprrr(p->as), 0, p->from.reg, p->to.reg);
1154                 break;
1155
1156         case 34:        /* mov $con,fr ==> or/add $i,r,r2 */
1157                 v = regoff(&p->from);
1158                 r = AADDU;
1159                 if(o->a1 == C_ANDCON)
1160                         r = AOR;
1161                 o1 = OP_IRR(opirr(r), v, 0, REGTMP);
1162                 o2 = OP_RRR(SP(2,1)|(4<<21), REGTMP, 0, p->to.reg);     /* mtc1 */
1163                 break;
1164
1165         case 35:        /* mov r,lext/luto/oreg ==> sw o(r) */
1166                 /*
1167                  * the lowbits of the constant cannot
1168                  * be moved into the offset of the load
1169                  * because the mips 4000 in 64-bit mode
1170                  * does a 64-bit add and it will screw up.
1171                  */
1172                 v = regoff(&p->to);
1173                 r = p->to.reg;
1174                 if(r == NREG)
1175                         r = o->param;
1176                 if(r == REGTMP)
1177                         diag("cant synthesize large constant\n%P", p);
1178                 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1179                 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1180                 o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1181                 o4 = OP_IRR(opirr(p->as), 0, REGTMP, p->from.reg);
1182                 break;
1183
1184         case 36:        /* mov lext/lauto/lreg,r ==> lw o(r30) */
1185                 v = regoff(&p->from);
1186                 r = p->from.reg;
1187                 if(r == NREG)
1188                         r = o->param;
1189                 if(r == REGTMP)
1190                         diag("cant synthesize large constant\n%P", p);
1191                 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1192                 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1193                 o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1194                 o4 = OP_IRR(opirr(p->as+ALAST), 0, REGTMP, p->to.reg);
1195                 break;
1196
1197         case 37:        /* movw r,mr */
1198                 r = SP(2,0)|(4<<21);            /* mtc0 */
1199                 if(p->as == AMOVV)
1200                         r = SP(2,0)|(5<<21);    /* dmtc0 */
1201                 o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
1202                 break;
1203
1204         case 38:        /* movw mr,r */
1205                 r = SP(2,0)|(0<<21);            /* mfc0 */
1206                 if(p->as == AMOVV)
1207                         r = SP(2,0)|(1<<21);    /* dmfc0 */
1208                 o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
1209                 break;
1210
1211         case 39:        /* rfe ==> jmp+rfe */
1212                 if(aflag)
1213                         return 0;
1214                 o1 = OP_RRR(oprrr(AJMP), 0, p->to.reg, REGZERO);
1215                 o2 = oprrr(p->as);
1216                 break;
1217
1218         case 40:        /* word */
1219                 if(aflag)
1220                         return 0;
1221                 o1 = regoff(&p->to);
1222                 break;
1223
1224         case 41:        /* movw r,fcr */
1225                 o1 = OP_RRR(SP(2,1)|(2<<21), REGZERO, 0, p->to.reg);    /* mfcc1 */
1226                 o2 = OP_RRR(SP(2,1)|(6<<21), p->from.reg, 0, p->to.reg);/* mtcc1 */
1227                 break;
1228
1229         case 42:        /* movw fcr,r */
1230                 o1 = OP_RRR(SP(2,1)|(2<<21), p->to.reg, 0, p->from.reg);/* mfcc1 */
1231                 break;
1232
1233         case 45:        /* case r */
1234                 if(p->link == P)
1235                         v = p->pc+28;
1236                 else
1237                         v = p->link->pc;
1238                 if(v & (1<<15))
1239                         o1 = OP_IRR(opirr(ALAST), (v>>16)+1, REGZERO, REGTMP);
1240                 else
1241                         o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1242                 o2 = OP_SRR(opirr(ASLL), 2, p->from.reg, p->from.reg);
1243                 o3 = OP_RRR(oprrr(AADD), p->from.reg, REGTMP, REGTMP);
1244                 o4 = OP_IRR(opirr(AMOVW+ALAST), v, REGTMP, REGTMP);
1245                 o5 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
1246                 o6 = OP_RRR(oprrr(AJMP), 0, REGTMP, REGZERO);
1247                 o7 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
1248                 break;
1249
1250         case 46:        /* bcase $con,lbra */
1251                 if(p->cond == P)
1252                         v = p->pc;
1253                 else
1254                         v = p->cond->pc;
1255                 o1 = v;
1256                 break;
1257         }
1258         if(aflag)
1259                 return o1;
1260         v = p->pc;
1261         switch(o->size) {
1262         default:
1263                 if(debug['a'])
1264                         Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
1265                 break;
1266         case 4:
1267                 if(debug['a'])
1268                         Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
1269                 LPUT(o1);
1270                 break;
1271         case 8:
1272                 if(debug['a'])
1273                         Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
1274                 LPUT(o1);
1275                 LPUT(o2);
1276                 break;
1277         case 12:
1278                 if(debug['a'])
1279                         Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
1280                 LPUT(o1);
1281                 LPUT(o2);
1282                 LPUT(o3);
1283                 break;
1284         case 16:
1285                 if(debug['a'])
1286                         Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
1287                                 v, o1, o2, o3, o4, p);
1288                 LPUT(o1);
1289                 LPUT(o2);
1290                 LPUT(o3);
1291                 LPUT(o4);
1292                 break;
1293         case 20:
1294                 if(debug['a'])
1295                         Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1296                                 v, o1, o2, o3, o4, o5, p);
1297                 LPUT(o1);
1298                 LPUT(o2);
1299                 LPUT(o3);
1300                 LPUT(o4);
1301                 LPUT(o5);
1302                 break;
1303
1304         case 28:
1305                 if(debug['a'])
1306                         Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1307                                 v, o1, o2, o3, o4, o5, o6, o7, p);
1308                 LPUT(o1);
1309                 LPUT(o2);
1310                 LPUT(o3);
1311                 LPUT(o4);
1312                 LPUT(o5);
1313                 LPUT(o6);
1314                 LPUT(o7);
1315                 break;
1316         }
1317         return 0;
1318 }
1319
1320 int
1321 isnop(Prog *p)
1322 {
1323         if(p->as != ANOR)
1324                 return 0;
1325         if(p->reg != REGZERO && p->reg != NREG)
1326                 return 0;
1327         if(p->from.type != D_REG || p->from.reg != REGZERO)
1328                 return 0;
1329         if(p->to.type != D_REG || p->to.reg != REGZERO)
1330                 return 0;
1331         return 1;
1332 }
1333
1334 long
1335 oprrr(int a)
1336 {
1337         switch(a) {
1338         case AADD:      return OP(4,0);
1339         case AADDU:     return OP(4,1);
1340         case ASGT:      return OP(5,2);
1341         case ASGTU:     return OP(5,3);
1342         case AAND:      return OP(4,4);
1343         case AOR:       return OP(4,5);
1344         case AXOR:      return OP(4,6);
1345         case ASUB:      return OP(4,2);
1346         case ASUBU:     return OP(4,3);
1347         case ANOR:      return OP(4,7);
1348         case ASLL:      return OP(0,4);
1349         case ASRL:      return OP(0,6);
1350         case ASRA:      return OP(0,7);
1351
1352         case AREM:
1353         case ADIV:      return OP(3,2);
1354         case AREMU:
1355         case ADIVU:     return OP(3,3);
1356         case AMUL:      return OP(3,0);
1357         case AMULU:     return OP(3,1);
1358
1359         case AJMP:      return OP(1,0);
1360         case AJAL:      return OP(1,1);
1361
1362         case ABREAK:    return OP(1,5);
1363         case ASYSCALL:  return OP(1,4);
1364         case ATLBP:     return MMU(1,0);
1365         case ATLBR:     return MMU(0,1);
1366         case ATLBWI:    return MMU(0,2);
1367         case ATLBWR:    return MMU(0,6);
1368         case ARFE:      return MMU(2,0);
1369
1370         case ADIVF:     return FPF(0,3);
1371         case ADIVD:     return FPD(0,3);
1372         case AMULF:     return FPF(0,2);
1373         case AMULD:     return FPD(0,2);
1374         case ASUBF:     return FPF(0,1);
1375         case ASUBD:     return FPD(0,1);
1376         case AADDF:     return FPF(0,0);
1377         case AADDD:     return FPD(0,0);
1378
1379         case AMOVFW:    return FPF(4,4);
1380         case AMOVDW:    return FPD(4,4);
1381         case AMOVWF:    return FPW(4,0);
1382         case AMOVDF:    return FPD(4,0);
1383         case AMOVWD:    return FPW(4,1);
1384         case AMOVFD:    return FPF(4,1);
1385         case AABSF:     return FPF(0,5);
1386         case AABSD:     return FPD(0,5);
1387         case AMOVF:     return FPF(0,6);
1388         case AMOVD:     return FPD(0,6);
1389         case ANEGF:     return FPF(0,7);
1390         case ANEGD:     return FPD(0,7);
1391
1392         case ACMPEQF:   return FPF(6,2);
1393         case ACMPEQD:   return FPD(6,2);
1394         case ACMPGTF:   return FPF(7,4);
1395         case ACMPGTD:   return FPD(7,4);
1396         case ACMPGEF:   return FPF(7,6);
1397         case ACMPGED:   return FPD(7,6);
1398
1399         case ADIVV:     return OP(3,6);
1400         case ADIVVU:    return OP(3,7);
1401         case AADDV:     return OP(5,4);
1402         case AADDVU:    return OP(5,5);
1403         }
1404         diag("bad rrr %d", a);
1405         return 0;
1406 }
1407
1408 long
1409 opirr(int a)
1410 {
1411         switch(a) {
1412         case AADD:      return SP(1,0);
1413         case AADDU:     return SP(1,1);
1414         case ASGT:      return SP(1,2);
1415         case ASGTU:     return SP(1,3);
1416         case AAND:      return SP(1,4);
1417         case AOR:       return SP(1,5);
1418         case AXOR:      return SP(1,6);
1419         case ALAST:     return SP(1,7);
1420         case ASLL:      return OP(0,0);
1421         case ASRL:      return OP(0,2);
1422         case ASRA:      return OP(0,3);
1423
1424         case AJMP:      return SP(0,2);
1425         case AJAL:      return SP(0,3);
1426         case ABEQ:      return SP(0,4);
1427         case ABNE:      return SP(0,5);
1428
1429         case ABGEZ:     return SP(0,1)|BCOND(0,1);
1430         case ABGEZAL:   return SP(0,1)|BCOND(2,1);
1431         case ABGTZ:     return SP(0,7);
1432         case ABLEZ:     return SP(0,6);
1433         case ABLTZ:     return SP(0,1)|BCOND(0,0);
1434         case ABLTZAL:   return SP(0,1)|BCOND(2,0);
1435
1436         case ABFPT:     return SP(2,1)|(257<<16);
1437         case ABFPF:     return SP(2,1)|(256<<16);
1438
1439         case AMOVB:
1440         case AMOVBU:    return SP(5,0);
1441         case AMOVH:
1442         case AMOVHU:    return SP(5,1);
1443         case AMOVW:     return SP(5,3);
1444         case AMOVV:     return SP(7,7);
1445         case AMOVF:     return SP(7,1);
1446         case AMOVWL:    return SP(5,2);
1447         case AMOVWR:    return SP(5,6);
1448         case AMOVVL:    return SP(5,4);
1449         case AMOVVR:    return SP(5,5);
1450
1451         case ABREAK:    return SP(5,7);
1452
1453         case AMOVWL+ALAST:      return SP(4,2);
1454         case AMOVWR+ALAST:      return SP(4,6);
1455         case AMOVVL+ALAST:      return SP(3,2);
1456         case AMOVVR+ALAST:      return SP(3,3);
1457         case AMOVB+ALAST:       return SP(4,0);
1458         case AMOVBU+ALAST:      return SP(4,4);
1459         case AMOVH+ALAST:       return SP(4,1);
1460         case AMOVHU+ALAST:      return SP(4,5);
1461         case AMOVW+ALAST:       return SP(4,3);
1462         case AMOVV+ALAST:       return SP(6,7);
1463         case AMOVF+ALAST:       return SP(6,1);
1464
1465         case ASLLV:             return OP(7,0);
1466         case ASRLV:             return OP(7,2);
1467         case ASRAV:             return OP(7,3);
1468         case ASLLV+ALAST:       return OP(7,4);
1469         case ASRLV+ALAST:       return OP(7,6);
1470         case ASRAV+ALAST:       return OP(7,7);
1471
1472         case AADDV:             return SP(3,0);
1473         case AADDVU:            return SP(3,1);
1474         }
1475         diag("bad irr %d", a);
1476 abort();
1477         return 0;
1478 }
1479
1480 int
1481 vshift(int a)
1482 {
1483         switch(a){
1484         case ASLLV:             return 1;
1485         case ASRLV:             return 1;
1486         case ASRAV:             return 1;
1487         }
1488         return 0;
1489 }