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