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