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