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