xref: /inferno-os/utils/kl/asm.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include	"l.h"
2 
3 #define	LPUT(c)\
4 	{\
5 		cbp[0] = (c)>>24;\
6 		cbp[1] = (c)>>16;\
7 		cbp[2] = (c)>>8;\
8 		cbp[3] = (c);\
9 		cbp += 4;\
10 		cbc -= 4;\
11 		if(cbc <= 0)\
12 			cflush();\
13 	}
14 
15 #define	CPUT(c)\
16 	{\
17 		cbp[0] = (c);\
18 		cbp++;\
19 		cbc--;\
20 		if(cbc <= 0)\
21 			cflush();\
22 	}
23 
24 long
25 entryvalue(void)
26 {
27 	char *a;
28 	Sym *s;
29 
30 	a = INITENTRY;
31 	if(*a >= '0' && *a <= '9')
32 		return atolwhex(a);
33 	s = lookup(a, 0);
34 	if(s->type == 0)
35 		return INITTEXT;
36 	if(s->type != STEXT && s->type != SLEAF)
37 		diag("entry not text: %s", s->name);
38 	return s->value;
39 }
40 
41 void
42 asmb(void)
43 {
44 	Prog *p;
45 	long t;
46 	Optab *o;
47 
48 	if(debug['v'])
49 		Bprint(&bso, "%5.2f asm\n", cputime());
50 	Bflush(&bso);
51 	seek(cout, HEADR, 0);
52 	pc = INITTEXT;
53 	for(p = firstp; p != P; p = p->link) {
54 		if(p->as == ATEXT) {
55 			curtext = p;
56 			autosize = p->to.offset + 4;
57 		}
58 		if(p->pc != pc) {
59 			diag("phase error %lux sb %lux",
60 				p->pc, pc);
61 			if(!debug['a'])
62 				prasm(curp);
63 			pc = p->pc;
64 		}
65 		curp = p;
66 		o = oplook(p);	/* could probably avoid this call */
67 		if(asmout(p, o, 0)) {
68 			p = p->link;
69 			pc += 4;
70 		}
71 		pc += o->size;
72 	}
73 	if(debug['a'])
74 		Bprint(&bso, "\n");
75 	Bflush(&bso);
76 	cflush();
77 
78 	curtext = P;
79 	switch(HEADTYPE) {
80 	case 0:
81 	case 3:
82 		seek(cout, HEADR+textsize, 0);
83 		break;
84 	case 1:
85 	case 2:
86 		seek(cout, HEADR+textsize, 0);
87 		break;
88 	}
89 	for(t = 0; t < datsize; t += sizeof(buf)-100) {
90 		if(datsize-t > sizeof(buf)-100)
91 			datblk(t, sizeof(buf)-100);
92 		else
93 			datblk(t, datsize-t);
94 	}
95 
96 	symsize = 0;
97 	lcsize = 0;
98 	if(!debug['s']) {
99 		if(debug['v'])
100 			Bprint(&bso, "%5.2f sym\n", cputime());
101 		Bflush(&bso);
102 		switch(HEADTYPE) {
103 		case 0:
104 		case 3:
105 			seek(cout, HEADR+textsize+datsize, 0);
106 			break;
107 		case 2:
108 		case 1:
109 			seek(cout, HEADR+textsize+datsize, 0);
110 			break;
111 		}
112 		if(!debug['s'])
113 			asmsym();
114 		if(debug['v'])
115 			Bprint(&bso, "%5.2f sp\n", cputime());
116 		Bflush(&bso);
117 		if(!debug['s'])
118 			asmlc();
119 		 /* round up file length for boot image */
120 		if(HEADTYPE == 0 || HEADTYPE == 3)
121 			if((symsize+lcsize) & 1)
122 				CPUT(0);
123 		cflush();
124 	}
125 
126 	seek(cout, 0L, 0);
127 	switch(HEADTYPE) {
128 	case 0:
129 		lput(0x1030107);		/* magic and sections */
130 		lput(textsize);			/* sizes */
131 		lput(datsize);
132 		lput(bsssize);
133 		lput(symsize);			/* nsyms */
134 		lput(entryvalue());		/* va of entry */
135 		lput(0L);
136 		lput(lcsize);
137 		break;
138 	case 1:
139 		break;
140 	case 2:
141 		lput(4*13*13+7);		/* magic */
142 		lput(textsize);			/* sizes */
143 		lput(datsize);
144 		lput(bsssize);
145 		lput(symsize);			/* nsyms */
146 		lput(entryvalue());		/* va of entry */
147 		lput(0L);
148 		lput(lcsize);
149 		break;
150 	case 3:
151 		lput(0x1030107);		/* magic and sections */
152 		lput(0x90100000);
153 #define SPARC_NOOP 0x01000000
154 		lput(SPARC_NOOP);
155 		lput(SPARC_NOOP);
156 		lput(SPARC_NOOP);
157 		lput(SPARC_NOOP);
158 		lput(SPARC_NOOP);
159 		lput(SPARC_NOOP);
160 		break;
161 	}
162 	cflush();
163 }
164 
165 void
166 lput(long l)
167 {
168 
169 	LPUT(l);
170 }
171 
172 void
173 cflush(void)
174 {
175 	int n;
176 
177 	n = sizeof(buf.cbuf) - cbc;
178 	if(n)
179 		write(cout, buf.cbuf, n);
180 	cbp = buf.cbuf;
181 	cbc = sizeof(buf.cbuf);
182 }
183 
184 void
185 asmsym(void)
186 {
187 	Prog *p;
188 	Auto *a;
189 	Sym *s;
190 	int h;
191 
192 	s = lookup("etext", 0);
193 	if(s->type == STEXT)
194 		putsymb(s->name, 'T', s->value, s->version);
195 
196 	for(h=0; h<NHASH; h++)
197 		for(s=hash[h]; s!=S; s=s->link)
198 			switch(s->type) {
199 			case SCONST:
200 				putsymb(s->name, 'D', s->value, s->version);
201 				continue;
202 
203 			case SDATA:
204 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
205 				continue;
206 
207 			case SBSS:
208 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
209 				continue;
210 
211 			case SFILE:
212 				putsymb(s->name, 'f', s->value, s->version);
213 				continue;
214 			}
215 
216 	for(p=textp; p!=P; p=p->cond) {
217 		s = p->from.sym;
218 		if(s->type != STEXT && s->type != SLEAF)
219 			continue;
220 
221 		/* filenames first */
222 		for(a=p->to.autom; a; a=a->link)
223 			if(a->type == D_FILE)
224 				putsymb(a->asym->name, 'z', a->aoffset, 0);
225 			else
226 			if(a->type == D_FILE1)
227 				putsymb(a->asym->name, 'Z', a->aoffset, 0);
228 
229 		if(s->type == STEXT)
230 			putsymb(s->name, 'T', s->value, s->version);
231 		else
232 			putsymb(s->name, 'L', s->value, s->version);
233 
234 		/* frame, auto and param after */
235 		putsymb(".frame", 'm', p->to.offset+4, 0);
236 		for(a=p->to.autom; a; a=a->link)
237 			if(a->type == D_AUTO)
238 				putsymb(a->asym->name, 'a', -a->aoffset, 0);
239 			else
240 			if(a->type == D_PARAM)
241 				putsymb(a->asym->name, 'p', a->aoffset, 0);
242 	}
243 	if(debug['v'] || debug['n'])
244 		Bprint(&bso, "symsize = %lud\n", symsize);
245 	Bflush(&bso);
246 }
247 
248 void
249 putsymb(char *s, int t, long v, int ver)
250 {
251 	int i, f;
252 
253 	if(t == 'f')
254 		s++;
255 	LPUT(v);
256 	if(ver)
257 		t += 'a' - 'A';
258 	CPUT(t+0x80);			/* 0x80 is variable length */
259 
260 	if(t == 'Z' || t == 'z') {
261 		CPUT(s[0]);
262 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
263 			CPUT(s[i]);
264 			CPUT(s[i+1]);
265 		}
266 		CPUT(0);
267 		CPUT(0);
268 		i++;
269 	}
270 	else {
271 		for(i=0; s[i]; i++)
272 			CPUT(s[i]);
273 		CPUT(0);
274 	}
275 	symsize += 4 + 1 + i + 1;
276 
277 	if(debug['n']) {
278 		if(t == 'z' || t == 'Z') {
279 			Bprint(&bso, "%c %.8lux ", t, v);
280 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
281 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
282 				Bprint(&bso, "/%x", f);
283 			}
284 			Bprint(&bso, "\n");
285 			return;
286 		}
287 		if(ver)
288 			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
289 		else
290 			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
291 	}
292 }
293 
294 #define	MINLC	4
295 void
296 asmlc(void)
297 {
298 	long oldpc, oldlc;
299 	Prog *p;
300 	long v, s;
301 
302 	oldpc = INITTEXT;
303 	oldlc = 0;
304 	for(p = firstp; p != P; p = p->link) {
305 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
306 			if(p->as == ATEXT)
307 				curtext = p;
308 			if(debug['L'])
309 				Bprint(&bso, "%6lux %P\n",
310 					p->pc, p);
311 			continue;
312 		}
313 		if(debug['L'])
314 			Bprint(&bso, "\t\t%6ld", lcsize);
315 		v = (p->pc - oldpc) / MINLC;
316 		while(v) {
317 			s = 127;
318 			if(v < 127)
319 				s = v;
320 			CPUT(s+128);	/* 129-255 +pc */
321 			if(debug['L'])
322 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
323 			v -= s;
324 			lcsize++;
325 		}
326 		s = p->line - oldlc;
327 		oldlc = p->line;
328 		oldpc = p->pc + MINLC;
329 		if(s > 64 || s < -64) {
330 			CPUT(0);	/* 0 vv +lc */
331 			CPUT(s>>24);
332 			CPUT(s>>16);
333 			CPUT(s>>8);
334 			CPUT(s);
335 			if(debug['L']) {
336 				if(s > 0)
337 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
338 						s, 0, s);
339 				else
340 					Bprint(&bso, " lc%ld(%d,%ld)\n",
341 						s, 0, s);
342 				Bprint(&bso, "%6lux %P\n",
343 					p->pc, p);
344 			}
345 			lcsize += 5;
346 			continue;
347 		}
348 		if(s > 0) {
349 			CPUT(0+s);	/* 1-64 +lc */
350 			if(debug['L']) {
351 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
352 				Bprint(&bso, "%6lux %P\n",
353 					p->pc, p);
354 			}
355 		} else {
356 			CPUT(64-s);	/* 65-128 -lc */
357 			if(debug['L']) {
358 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
359 				Bprint(&bso, "%6lux %P\n",
360 					p->pc, p);
361 			}
362 		}
363 		lcsize++;
364 	}
365 	while(lcsize & 1) {
366 		s = 129;
367 		CPUT(s);
368 		lcsize++;
369 	}
370 	if(debug['v'] || debug['L'])
371 		Bprint(&bso, "lcsize = %ld\n", lcsize);
372 	Bflush(&bso);
373 }
374 
375 void
376 datblk(long s, long n)
377 {
378 	Prog *p;
379 	char *cast;
380 	long l, fl, j, d;
381 	int i, c;
382 
383 	memset(buf.dbuf, 0, n+100);
384 	for(p = datap; p != P; p = p->link) {
385 		curp = p;
386 		l = p->from.sym->value + p->from.offset - s;
387 		c = p->reg;
388 		i = 0;
389 		if(l < 0) {
390 			if(l+c <= 0)
391 				continue;
392 			while(l < 0) {
393 				l++;
394 				i++;
395 			}
396 		}
397 		if(l >= n)
398 			continue;
399 		if(p->as != AINIT && p->as != ADYNT) {
400 			for(j=l+(c-i)-1; j>=l; j--)
401 				if(buf.dbuf[j]) {
402 					print("%P\n", p);
403 					diag("multiple initialization");
404 					break;
405 				}
406 		}
407 		switch(p->to.type) {
408 		default:
409 			diag("unknown mode in initialization\n%P", p);
410 			break;
411 
412 		case D_FCONST:
413 			switch(c) {
414 			default:
415 			case 4:
416 				fl = ieeedtof(&p->to.ieee);
417 				cast = (char*)&fl;
418 				for(; i<c; i++) {
419 					buf.dbuf[l] = cast[fnuxi8[i+4]];
420 					l++;
421 				}
422 				break;
423 			case 8:
424 				cast = (char*)&p->to.ieee;
425 				for(; i<c; i++) {
426 					buf.dbuf[l] = cast[fnuxi8[i]];
427 					l++;
428 				}
429 				break;
430 			}
431 			break;
432 
433 		case D_SCONST:
434 			for(; i<c; i++) {
435 				buf.dbuf[l] = p->to.sval[i];
436 				l++;
437 			}
438 			break;
439 
440 		case D_CONST:
441 			d = p->to.offset;
442 			if(p->to.sym) {
443 				if(p->to.sym->type == STEXT ||
444 				   p->to.sym->type == SLEAF)
445 					d += p->to.sym->value;
446 				if(p->to.sym->type == SDATA)
447 					d += p->to.sym->value + INITDAT;
448 				if(p->to.sym->type == SBSS)
449 					d += p->to.sym->value + INITDAT;
450 			}
451 			cast = (char*)&d;
452 			switch(c) {
453 			default:
454 				diag("bad nuxi %d %d\n%P", c, i, curp);
455 				break;
456 			case 1:
457 				for(; i<c; i++) {
458 					buf.dbuf[l] = cast[inuxi1[i]];
459 					l++;
460 				}
461 				break;
462 			case 2:
463 				for(; i<c; i++) {
464 					buf.dbuf[l] = cast[inuxi2[i]];
465 					l++;
466 				}
467 				break;
468 			case 4:
469 				for(; i<c; i++) {
470 					buf.dbuf[l] = cast[inuxi4[i]];
471 					l++;
472 				}
473 				break;
474 			}
475 			break;
476 		}
477 	}
478 	write(cout, buf.dbuf, n);
479 }
480 
481 #define	OP2(x)	(0x80000000|((x)<<19))
482 #define	OP3(x)	(0xc0000000|((x)<<19))
483 #define	OPB(x)	(0x00800000|((x)<<25))
484 #define	OPT(x)	(0x81d02000|((x)<<25))
485 #define	OPF1(x)	(0x81a00000|((x)<<5))
486 #define	OPF2(x)	(0x81a80000|((x)<<5))
487 #define	OPFB(x)	(0x01800000|((x)<<25))
488 
489 #define	OP_RRR(op,r1,r2,r3)\
490 	(0x00000000 | op |\
491 	(((r1)&31L)<<0) |\
492 	(((r2)&31L)<<14) |\
493 	(((r3)&31L)<<25))
494 #define	OP_IRR(op,i,r2,r3)\
495 	(0x00002000L | (op) |\
496 	(((i)&0x1fffL)<<0) |\
497 	(((r2)&31L)<<14) |\
498 	(((r3)&31L)<<25))
499 #define	OP_BRA(op,pc)\
500 	((op) |\
501 	(((pc)&0x3fffff)<<0))
502 
503 int
504 asmout(Prog *p, Optab *o, int aflag)
505 {
506 	long o1, o2, o3, o4, o5, v;
507 	Prog *ct;
508 	int r;
509 
510 	o1 = 0;
511 	o2 = 0;
512 	o3 = 0;
513 	o4 = 0;
514 	o5 = 0;
515 
516 	switch(o->type) {
517 	default:
518 		if(aflag)
519 			return 0;
520 		diag("unknown type %d", o->type);
521 		if(!debug['a'])
522 			prasm(p);
523 		break;
524 
525 	case 0:		/* pseudo ops */
526 		if(aflag) {
527 			if(p->link) {
528 				if(p->as == ATEXT) {
529 					ct = curtext;
530 					o2 = autosize;
531 					curtext = p;
532 					autosize = p->to.offset + 4;
533 					o1 = asmout(p->link, oplook(p->link), aflag);
534 					curtext = ct;
535 					autosize = o2;
536 				} else
537 					o1 = asmout(p->link, oplook(p->link), aflag);
538 			}
539 			return o1;
540 		}
541 		break;
542 
543 	case 1:		/* mov r1,r2 ==> OR r1,r0,r2 */
544 		o1 = OP_RRR(opcode(AOR), p->from.reg, REGZERO, p->to.reg);
545 		break;
546 
547 	case 2:		/* mov $c,r ==> add r1,r0,r2 */
548 		r = p->from.reg;
549 		if(r == NREG)
550 			r = o->param;
551 		v = regoff(&p->from);
552 		o1 = OP_IRR(opcode(AADD), v, r, p->to.reg);
553 		break;
554 
555 	case 3:		/* mov soreg, r */
556 		r = p->from.reg;
557 		if(r == NREG)
558 			r = o->param;
559 		v = regoff(&p->from);
560 		if(v == 0 && p->reg != NREG)
561 			o1 = OP_RRR(opcode(p->as), p->reg, r, p->to.reg);
562 		else
563 			o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
564 		break;
565 
566 	case 4:		/* mov r, soreg */
567 		r = p->to.reg;
568 		if(r == NREG)
569 			r = o->param;
570 		v = regoff(&p->to);
571 		if(v == 0 && p->reg != NREG)
572 			o1 = OP_RRR(opcode(p->as+AEND), p->reg, r, p->from.reg);
573 		else
574 			o1 = OP_IRR(opcode(p->as+AEND), v, r, p->from.reg);
575 		break;
576 
577 	case 5:		/* mov $lcon, reg => sethi, add */
578 		v = regoff(&p->from);
579 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
580 		o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
581 		break;
582 
583 	case 6:		/* mov asi, r[+r] */
584 		o1 = OP_RRR(opcode(p->as), p->reg, p->from.reg, p->to.reg);
585 		o1 |= (1<<23) | ((p->from.offset&0xff)<<5);
586 		break;
587 
588 	case 7:		/* mov [+r]r, asi */
589 		o1 = OP_RRR(opcode(p->as+AEND), p->reg, p->to.reg, p->from.reg);
590 		o1 |= (1<<23) | ((p->to.offset&0xff)<<5);
591 		break;
592 
593 	case 8:		/* mov r, preg and mov preg, r */
594 		if(p->to.type == D_PREG) {
595 			r = p->from.reg;
596 			switch(p->to.reg)
597 			{
598 			default:
599 				diag("unknown register P%d", p->to.reg);
600 			case D_Y:
601 				o1 = OP2(48);	/* wry */
602 				break;
603 			case D_PSR:
604 				o1 = OP2(49);	/* wrpsr */
605 				break;
606 			case D_WIM:
607 				o1 = OP2(50);	/* wrwim */
608 				break;
609 			case D_TBR:
610 				o1 = OP2(51);	/* wrtbr */
611 				break;
612 			}
613 			o1 = OP_IRR(o1, 0, r, 0);
614 			break;
615 		}
616 		if(p->from.type == D_PREG) {
617 			r = p->to.reg;
618 			switch(p->from.reg)
619 			{
620 			default:
621 				diag("unknown register P%d", p->to.reg);
622 			case D_Y:
623 				o1 = OP2(40);	/* rdy */
624 				break;
625 			case D_PSR:
626 				o1 = OP2(41);	/* rdpsr */
627 				break;
628 			case D_WIM:
629 				o1 = OP2(42);	/* rdwim */
630 				break;
631 			case D_TBR:
632 				o1 = OP2(43);	/* rdtbr */
633 				break;
634 			}
635 			o1 = OP_RRR(o1, 0, 0, r);
636 			break;
637 		}
638 		break;
639 
640 	case 9:		/* movb r,r */
641 		v = 24;
642 		if(p->as == AMOVH || p->as == AMOVHU)
643 			v = 16;
644 		r = ASRA;
645 		if(p->as == AMOVBU || p->as == AMOVHU)
646 			r = ASRL;
647 		o1 = OP_IRR(opcode(ASLL), v, p->from.reg, p->to.reg);
648 		o2 = OP_IRR(opcode(r), v, p->to.reg, p->to.reg);
649 		break;
650 
651 	case 10:	/* mov $loreg, reg */
652 		r = p->from.reg;
653 		if(r == NREG)
654 			r = o->param;
655 		v = regoff(&p->from);
656 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
657 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
658 		o3 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
659 		break;
660 
661 	case 11:	/* mov loreg, r */
662 		r = p->from.reg;
663 		if(r == NREG)
664 			r = o->param;
665 		v = regoff(&p->from);
666 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
667 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
668 		o3 = OP_IRR(opcode(p->as), (v&0x3ff), REGTMP, p->to.reg);
669 		break;
670 
671 	case 12:	/* mov r, loreg */
672 		r = p->to.reg;
673 		if(r == NREG)
674 			r = o->param;
675 		v = regoff(&p->to);
676 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
677 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
678 		o3 = OP_IRR(opcode(p->as+AEND), (v&0x3ff), REGTMP, p->from.reg);
679 		break;
680 
681 	case 13:	/* mov $ucon, r */
682 		v = regoff(&p->from);
683 		o1 = 0x1000000 | (p->to.reg<<25) | ((v>>10) & 0x3fffff);	/* sethi */
684 		break;
685 
686 	case 20:	/* op $scon,r */
687 		v = regoff(&p->from);
688 		r = p->reg;
689 		if(r == NREG)
690 			r = p->to.reg;
691 		o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
692 		break;
693 
694 	case 21:	/* op r1,r2 */
695 		r = p->reg;
696 		if(r == NREG)
697 			r = p->to.reg;
698 		o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
699 		break;
700 
701 	case 22:	/* op $lcon,r */
702 		v = regoff(&p->from);
703 		r = p->reg;
704 		if(r == NREG)
705 			r = p->to.reg;
706 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
707 		o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, REGTMP);
708 		o3 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
709 		break;
710 
711 	case 23:	/* cmp r,r */
712 		o1 = OP_RRR(opcode(ASUBCC), p->to.reg, p->from.reg, REGZERO);
713 		break;
714 
715 	case 24:	/* cmp r,$c */
716 		v = regoff(&p->to);
717 		o1 = OP_IRR(opcode(ASUBCC), v, p->from.reg, REGZERO);
718 		break;
719 
720 	case 25:	/* cmp $c,r BOTCH, fix compiler */
721 		v = regoff(&p->from);
722 		o1 = OP_IRR(opcode(AADD), v, NREG, REGTMP);
723 		o2 = OP_RRR(opcode(ASUBCC), p->to.reg, REGTMP, REGZERO);
724 		break;
725 
726 	case 26:	/* op $ucon,r */
727 		v = regoff(&p->from);
728 		r = p->reg;
729 		if(r == NREG)
730 			r = p->to.reg;
731 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
732 		o2 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
733 		break;
734 
735 	case 30:	/* jmp/jmpl soreg */
736 		if(aflag)
737 			return 0;
738 		v = regoff(&p->to);
739 		r = p->reg;
740 		if(r == NREG && p->as == AJMPL)
741 			r = 15;
742 		o1 = OP_IRR(opcode(AJMPL), v, p->to.reg, r);
743 		break;
744 
745 	case 31:	/* ba jmp */
746 		if(aflag)
747 			return 0;
748 		r = p->as;
749 		if(r == AJMP)
750 			r = ABA;
751 		v = 0;
752 		if(p->cond)
753 			v = p->cond->pc - p->pc;
754 		o1 = OP_BRA(opcode(r), v/4);
755 		if(r == ABA && p->link && p->cond && isnop(p->link)) {
756 			o2 = asmout(p->cond, oplook(p->cond), 1);
757 			if(o2) {
758 				o1 += 1;
759 				if(debug['a'])
760 					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
761 				LPUT(o1);
762 				LPUT(o2);
763 				return 1;
764 			}
765 			/* cant set annul here because pc has already been counted */
766 		}
767 		break;
768 
769 	case 32:	/* jmpl lbra */
770 		if(aflag)
771 			return 0;
772 		v = 0;
773 		if(p->cond)
774 			v = p->cond->pc - p->pc;
775 		r = p->reg;
776 		if(r != NREG && r != 15)
777 			diag("cant jmpl other than R15");
778 		o1 = 0x40000000 | ((v/4) & 0x3fffffffL);	/* call */
779 		if(p->link && p->cond && isnop(p->link)) {
780 			o2 = asmout(p->cond, oplook(p->cond), 1);
781 			if(o2) {
782 				o1 += 1;
783 				if(debug['a'])
784 					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
785 				LPUT(o1);
786 				LPUT(o2);
787 				return 1;
788 			}
789 		}
790 		break;
791 
792 	case 33:	/* trap r */
793 		if(aflag)
794 			return 0;
795 		o1 = opcode(p->as) | (p->from.reg<<14);
796 		break;
797 
798 	case 34:	/* rett r1,r2 -> jmpl (r1); rett (r2) */
799 		if(aflag)
800 			return 0;
801 		o1 = OP_IRR(opcode(AJMPL), 0, p->from.reg, REGZERO);
802 		o2 = OP_IRR(opcode(ARETT), 0, p->to.reg, REGZERO);
803 		break;
804 
805 	case 40:	/* ldfsr, stfsr, stdq */
806 		if(p->to.type == D_PREG) {
807 			r = p->from.reg;
808 			if(r == NREG)
809 				r = o->param;
810 			v = regoff(&p->from);
811 			if(p->to.reg == D_FSR) {
812 				o1 = OP_IRR(OP3(33), v, r, 0);
813 				break;
814 			}
815 			diag("unknown reg load %d", p->to.reg);
816 		} else {
817 			r = p->to.reg;
818 			if(r == NREG)
819 				r = o->param;
820 			v = regoff(&p->to);
821 			if(p->from.reg == D_FSR) {
822 				o1 = OP_IRR(OP3(37), v, r, 0);
823 				break;
824 			}
825 			if(p->as == AMOVD && p->from.reg == D_FPQ) {
826 				o1 = OP_IRR(OP3(38), v, r, 0);
827 				break;
828 			}
829 			diag("unknown reg store %d", p->from.reg);
830 		}
831 		break;
832 
833 	case 41:	/* ldf,ldd */
834 		r = p->from.reg;
835 		if(r == NREG)
836 			r = o->param;
837 		v = regoff(&p->from);
838 		if(p->as == AFMOVF || p->as == AMOVW) {
839 			o1 = OP_IRR(OP3(32), v, r, p->to.reg);
840 			break;
841 		}
842 		if(p->as == AMOVD || p->as == AFMOVD) {
843 			o1 = OP_IRR(OP3(35), v, r, p->to.reg);
844 			break;
845 		}
846 		diag("only MOVD and MOVW to FREG");
847 		break;
848 
849 	case 42:	/* ldd -> ldf,ldf */
850 		/* note should be ldd with proper allignment */
851 		r = p->from.reg;
852 		if(r == NREG)
853 			r = o->param;
854 		v = regoff(&p->from);
855 		o1 = OP_IRR(OP3(32), v, r, p->to.reg);
856 		o2 = OP_IRR(OP3(32), v+4, r, p->to.reg+1);
857 		break;
858 
859 	case 43:	/* stf */
860 		r = p->to.reg;
861 		if(r == NREG)
862 			r = o->param;
863 		v = regoff(&p->to);
864 		if(p->as == AFMOVF || p->as == AMOVW) {
865 			o1 = OP_IRR(OP3(36), v, r, p->from.reg);
866 			break;
867 		}
868 		if(p->as == AMOVD || p->as == AFMOVD) {
869 			o1 = OP_IRR(OP3(39), v, r, p->from.reg);
870 			break;
871 		}
872 		diag("only MOVD and MOVW from FREG");
873 		break;
874 
875 	case 44:	/* std -> stf,stf */
876 		/* note should be std with proper allignment */
877 		r = p->to.reg;
878 		if(r == NREG)
879 			r = o->param;
880 		v = regoff(&p->to);
881 		o1 = OP_IRR(OP3(36), v, r, p->from.reg);
882 		o2 = OP_IRR(OP3(36), v+4, r, p->from.reg+1);
883 		break;
884 
885 	case 45:	/* ldf lorg */
886 		r = p->from.reg;
887 		if(r == NREG)
888 			r = o->param;
889 		v = regoff(&p->from);
890 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
891 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
892 		o3 = OP_IRR(OP3(32), v&0x3ff, REGTMP, p->to.reg);
893 		break;
894 
895 	case 46:	/* ldd lorg -> ldf,ldf */
896 		/* note should be ldd with proper allignment */
897 		r = p->from.reg;
898 		if(r == NREG)
899 			r = o->param;
900 		v = regoff(&p->from);
901 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
902 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
903 		o3 = OP_IRR(OP3(32), (v&0x3ff), REGTMP, p->to.reg);
904 		o4 = OP_IRR(OP3(32), (v&0x3ff)+4, REGTMP, p->to.reg+1);
905 		break;
906 
907 	case 47:	/* stf lorg */
908 		r = p->to.reg;
909 		if(r == NREG)
910 			r = o->param;
911 		v = regoff(&p->to);
912 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
913 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
914 		o3 = OP_IRR(OP3(36), v&0x3ff, REGTMP, p->from.reg);
915 		break;
916 
917 	case 48:	/* std lorg -> stf,stf */
918 		/* note should be std with proper allignment */
919 		r = p->to.reg;
920 		if(r == NREG)
921 			r = o->param;
922 		v = regoff(&p->to);
923 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
924 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
925 		o3 = OP_IRR(OP3(36), (v&0x3ff), REGTMP, p->from.reg);
926 		o4 = OP_IRR(OP3(36), (v&0x3ff)+4, REGTMP, p->from.reg+1);
927 		break;
928 
929 	case 49:	/* fmovd -> fmovf,fmovf */
930 		o1 = OP_RRR(opcode(AFMOVF), p->from.reg, 0, p->to.reg);
931 		o2 = OP_RRR(opcode(AFMOVF), p->from.reg+1, 0, p->to.reg+1);
932 		break;
933 
934 	case 50:	/* fcmp */
935 		o1 = OP_RRR(opcode(p->as), p->to.reg, p->from.reg, 0);
936 		break;
937 
938 	case 51:	/* word */
939 		if(aflag)
940 			return 0;
941 		o1 = regoff(&p->from);
942 		break;
943 
944 	case 52:	/* div */
945 		r = p->reg;
946 		if(r == NREG)
947 			r = p->to.reg;
948 		o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
949 		o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
950 		o3 = OP_RRR(opcode(ADIV), p->from.reg, r, p->to.reg);
951 		break;
952 
953 	case 53:	/* divl */
954 		r = p->reg;
955 		if(r == NREG)
956 			r = p->to.reg;
957 		o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
958 		o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, p->to.reg);
959 		break;
960 
961 	case 54:	/* mod */
962 		r = p->reg;
963 		if(r == NREG)
964 			r = p->to.reg;
965 		o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
966 		o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
967 		o3 = OP_RRR(opcode(ADIV), p->from.reg, r, REGTMP);
968 		o4 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
969 		o5 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
970 		break;
971 
972 	case 55:	/* modl */
973 		r = p->reg;
974 		if(r == NREG)
975 			r = p->to.reg;
976 		o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
977 		o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, REGTMP);
978 		o3 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
979 		o4 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
980 		break;
981 
982 	case 56:	/* b(cc) -- annullable */
983 		if(aflag)
984 			return 0;
985 		r = p->as;
986 		v = 0;
987 		if(p->cond)
988 			v = p->cond->pc - p->pc;
989 		o1 = OP_BRA(opcode(r), v/4);
990 		if(p->link && p->cond && isnop(p->link))
991 		if(!debug['A']) {
992 			o2 = asmout(p->cond, oplook(p->cond), 2);
993 			if(o2) {
994 				o1 |= 1<<29;	/* annul */
995 				o1 += 1;
996 				if(debug['a'])
997 					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
998 				LPUT(o1);
999 				LPUT(o2);
1000 				return 1;
1001 			}
1002 		}
1003 		break;
1004 
1005 	case 57:	/* op r1,r2 with reserved rs1 */
1006 		r = 0;
1007 		o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
1008 		break;
1009 	}
1010 	if(aflag)
1011 		return o1;
1012 	v = p->pc;
1013 	switch(o->size) {
1014 	default:
1015 		if(debug['a'])
1016 			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
1017 		break;
1018 	case 4:
1019 		if(debug['a'])
1020 			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
1021 		LPUT(o1);
1022 		break;
1023 	case 8:
1024 		if(debug['a'])
1025 			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
1026 		LPUT(o1);
1027 		LPUT(o2);
1028 		break;
1029 	case 12:
1030 		if(debug['a'])
1031 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
1032 		LPUT(o1);
1033 		LPUT(o2);
1034 		LPUT(o3);
1035 		break;
1036 	case 16:
1037 		if(debug['a'])
1038 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
1039 				v, o1, o2, o3, o4, p);
1040 		LPUT(o1);
1041 		LPUT(o2);
1042 		LPUT(o3);
1043 		LPUT(o4);
1044 		break;
1045 	case 20:
1046 		if(debug['a'])
1047 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1048 				v, o1, o2, o3, o4, o5, p);
1049 		LPUT(o1);
1050 		LPUT(o2);
1051 		LPUT(o3);
1052 		LPUT(o4);
1053 		LPUT(o5);
1054 		break;
1055 	}
1056 	return 0;
1057 }
1058 
1059 int
1060 isnop(Prog *p)
1061 {
1062 	if(p->as != AORN)
1063 		return 0;
1064 	if(p->reg != REGZERO && p->reg != NREG)
1065 		return 0;
1066 	if(p->from.type != D_REG || p->from.reg != REGZERO)
1067 		return 0;
1068 	if(p->to.type != D_REG || p->to.reg != REGZERO)
1069 		return 0;
1070 	return 1;
1071 }
1072 
1073 long
1074 opcode(int a)
1075 {
1076 	switch(a) {
1077 	case AADD:	return OP2(0);
1078 	case AADDCC:	return OP2(16);
1079 	case AADDX:	return OP2(8);
1080 	case AADDXCC:	return OP2(24);
1081 
1082 	case AMUL:	return OP2(10);
1083 	case ADIV:	return OP2(15);
1084 	case ADIVL:	return OP2(14);
1085 
1086 	case ATADDCC:	return OP2(32);
1087 	case ATADDCCTV:	return OP2(34);
1088 
1089 	case ASUB:	return OP2(4);
1090 	case ASUBCC:	return OP2(20);
1091 	case ASUBX:	return OP2(12);
1092 	case ASUBXCC:	return OP2(28);
1093 
1094 	case ATSUBCC:	return OP2(33);
1095 	case ATSUBCCTV:	return OP2(35);
1096 
1097 	case AMULSCC:	return OP2(36);
1098 	case ASAVE:	return OP2(60);
1099 	case ARESTORE:	return OP2(61);
1100 
1101 	case AAND:	return OP2(1);
1102 	case AANDCC:	return OP2(17);
1103 	case AANDN:	return OP2(5);
1104 	case AANDNCC:	return OP2(21);
1105 
1106 	case AOR:	return OP2(2);
1107 	case AORCC:	return OP2(18);
1108 	case AORN:	return OP2(6);
1109 	case AORNCC:	return OP2(22);
1110 
1111 	case AXOR:	return OP2(3);
1112 	case AXORCC:	return OP2(19);
1113 	case AXNOR:	return OP2(7);
1114 	case AXNORCC:	return OP2(23);
1115 
1116 	case ASLL:	return OP2(37);
1117 	case ASRL:	return OP2(38);
1118 	case ASRA:	return OP2(39);
1119 
1120 	case AJMPL:
1121 	case AJMP:	return OP2(56);
1122 	case ARETT:	return OP2(57);
1123 
1124 	case AMOVBU:	return OP3(1);	/* ldub */
1125 	case AMOVB:	return OP3(9);	/* ldsb */
1126 	case AMOVHU:	return OP3(2);	/* lduh */
1127 	case AMOVH:	return OP3(10);	/* ldsh */
1128 	case AMOVW:	return OP3(0);	/* ld */
1129 	case AMOVD:	return OP3(3);	/* ldd */
1130 
1131 	case AMOVBU+AEND:
1132 	case AMOVB+AEND:return OP3(5);	/* stb */
1133 
1134 	case AMOVHU+AEND:
1135 	case AMOVH+AEND:return OP3(6);	/* sth */
1136 
1137 	case AMOVW+AEND:return OP3(4);	/* st */
1138 
1139 	case AMOVD+AEND:return OP3(7);	/* std */
1140 
1141 	case ASWAP:			/* swap is symmetric */
1142 	case ASWAP+AEND:return OP3(15);
1143 
1144 	case ATAS:	return OP3(13);	/* tas is really ldstub */
1145 
1146 	case ABN:	return OPB(0);
1147 	case ABE:	return OPB(1);
1148 	case ABLE:	return OPB(2);
1149 	case ABL:	return OPB(3);
1150 	case ABLEU:	return OPB(4);
1151 	case ABCS:	return OPB(5);
1152 	case ABNEG:	return OPB(6);
1153 	case ABVS:	return OPB(7);
1154 	case ABA:	return OPB(8);
1155 	case ABNE:	return OPB(9);
1156 	case ABG:	return OPB(10);
1157 	case ABGE:	return OPB(11);
1158 	case ABGU:	return OPB(12);
1159 	case ABCC:	return OPB(13);
1160 	case ABPOS:	return OPB(14);
1161 	case ABVC:	return OPB(15);
1162 
1163 	case AFBA:	return OPFB(8);
1164 	case AFBE:	return OPFB(9);
1165 	case AFBG:	return OPFB(6);
1166 	case AFBGE:	return OPFB(11);
1167 	case AFBL:	return OPFB(4);
1168 	case AFBLE:	return OPFB(13);
1169 	case AFBLG:	return OPFB(2);
1170 	case AFBN:	return OPFB(0);
1171 	case AFBNE:	return OPFB(1);
1172 	case AFBO:	return OPFB(15);
1173 	case AFBU:	return OPFB(7);
1174 	case AFBUE:	return OPFB(10);
1175 	case AFBUG:	return OPFB(5);
1176 	case AFBUGE:	return OPFB(12);
1177 	case AFBUL:	return OPFB(3);
1178 	case AFBULE:	return OPFB(14);
1179 
1180 	case ATN:	return OPT(0);
1181 	case ATE:	return OPT(1);
1182 	case ATLE:	return OPT(2);
1183 	case ATL:	return OPT(3);
1184 	case ATLEU:	return OPT(4);
1185 	case ATCS:	return OPT(5);
1186 	case ATNEG:	return OPT(6);
1187 	case ATVS:	return OPT(7);
1188 	case ATA:	return OPT(8);
1189 	case ATNE:	return OPT(9);
1190 	case ATG:	return OPT(10);
1191 	case ATGE:	return OPT(11);
1192 	case ATGU:	return OPT(12);
1193 	case ATCC:	return OPT(13);
1194 	case ATPOS:	return OPT(14);
1195 	case ATVC:	return OPT(15);
1196 
1197 	case AFADDF:	return OPF1(65);
1198 	case AFADDD:	return OPF1(66);
1199 	case AFADDX:	return OPF1(67);
1200 	case AFSUBF:	return OPF1(69);
1201 	case AFSUBD:	return OPF1(70);
1202 	case AFSUBX:	return OPF1(71);
1203 	case AFMULF:	return OPF1(73);
1204 	case AFMULD:	return OPF1(74);
1205 	case AFMULX:	return OPF1(75);
1206 	case AFDIVF:	return OPF1(77);
1207 	case AFDIVD:	return OPF1(78);
1208 	case AFDIVX:	return OPF1(79);
1209 
1210 	case AFMOVF:	return OPF1(1);
1211 	case AFNEGF:	return OPF1(5);
1212 	case AFABSF:	return OPF1(9);
1213 
1214 	case AFSQRTF:	return OPF1(41);
1215 	case AFSQRTD:	return OPF1(42);
1216 	case AFSQRTX:	return OPF1(43);
1217 
1218 	case AFMOVWF:	return OPF1(196);
1219 	case AFMOVWD:	return OPF1(200);
1220 	case AFMOVWX:	return OPF1(204);
1221 	case AFMOVFW:	return OPF1(209);
1222 	case AFMOVDW:	return OPF1(210);
1223 	case AFMOVXW:	return OPF1(211);
1224 	case AFMOVFD:	return OPF1(201);
1225 	case AFMOVFX:	return OPF1(205);
1226 	case AFMOVDF:	return OPF1(198);
1227 	case AFMOVDX:	return OPF1(206);
1228 	case AFMOVXF:	return OPF1(199);
1229 	case AFMOVXD:	return OPF1(203);
1230 
1231 	case AFCMPF:	return OPF2(81);
1232 	case AFCMPD:	return OPF2(82);
1233 	case AFCMPX:	return OPF2(83);
1234 	case AFCMPEF:	return OPF2(85);
1235 	case AFCMPED:	return OPF2(86);
1236 	case AFCMPEX:	return OPF2(87);
1237 
1238 	case AUNIMP:	return 0;
1239 	}
1240 	diag("bad opcode %A", a);
1241 	return 0;
1242 }
1243