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