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