xref: /plan9/sys/src/cmd/vl/asm.c (revision 5482313dd45cf2be65aac405a2f0426da9f89875)
13e12c5d1SDavid du Colombier #include	"l.h"
23e12c5d1SDavid du Colombier 
33305c317SDavid du Colombier /* can't include a.out.h due to name clashes, but these are taken from it */
43305c317SDavid du Colombier #define	_MAGIC(f, b)	((f)|((((4*(b))+0)*(b))+7))
53305c317SDavid du Colombier #define	V_MAGIC		_MAGIC(0, 16)		/* mips 3000 BE */
63305c317SDavid du Colombier #define	M_MAGIC		_MAGIC(0, 18)		/* mips 4000 BE */
73305c317SDavid du Colombier #define	N_MAGIC		_MAGIC(0, 22)		/* mips 4000 LE */
83305c317SDavid du Colombier #define	P_MAGIC		_MAGIC(0, 24)		/* mips 3000 LE */
93305c317SDavid du Colombier 
10bd389b36SDavid du Colombier long	OFFSET;
11bd389b36SDavid du Colombier /*
12bd389b36SDavid du Colombier long	BADOFFSET	=	-1;
13bd389b36SDavid du Colombier 
14bd389b36SDavid du Colombier 		if(OFFSET <= BADOFFSET && OFFSET+4 > BADOFFSET)\
15bd389b36SDavid du Colombier 			abort();\
16bd389b36SDavid du Colombier 		OFFSET += 4;\
17bd389b36SDavid du Colombier 
18bd389b36SDavid du Colombier 		if(OFFSET == BADOFFSET)\
19bd389b36SDavid du Colombier 			abort();\
20bd389b36SDavid du Colombier 		OFFSET++;\
21bd389b36SDavid du Colombier */
22bd389b36SDavid du Colombier 
2391178603SDavid du Colombier #define LPUT(l) { \
2491178603SDavid du Colombier 		if (little) { \
2591178603SDavid du Colombier 			LLEPUT(l); \
2691178603SDavid du Colombier 		} else { \
2791178603SDavid du Colombier 			LBEPUT(l); \
2891178603SDavid du Colombier 		} \
2991178603SDavid du Colombier 	}
3091178603SDavid du Colombier 
3191178603SDavid du Colombier #define	LLEPUT(c)\
3291178603SDavid du Colombier 	{\
3391178603SDavid du Colombier 		cbp[0] = (c);\
3491178603SDavid du Colombier 		cbp[1] = (c)>>8;\
3591178603SDavid du Colombier 		cbp[2] = (c)>>16;\
3691178603SDavid du Colombier 		cbp[3] = (c)>>24;\
3791178603SDavid du Colombier 		cbp += 4;\
3891178603SDavid du Colombier 		cbc -= 4;\
3991178603SDavid du Colombier 		if(cbc <= 0)\
4091178603SDavid du Colombier 			cflush();\
4191178603SDavid du Colombier 	}
4291178603SDavid du Colombier 
4391178603SDavid du Colombier #define	LBEPUT(c)\
443e12c5d1SDavid du Colombier 	{\
453e12c5d1SDavid du Colombier 		cbp[0] = (c)>>24;\
463e12c5d1SDavid du Colombier 		cbp[1] = (c)>>16;\
473e12c5d1SDavid du Colombier 		cbp[2] = (c)>>8;\
483e12c5d1SDavid du Colombier 		cbp[3] = (c);\
493e12c5d1SDavid du Colombier 		cbp += 4;\
503e12c5d1SDavid du Colombier 		cbc -= 4;\
513e12c5d1SDavid du Colombier 		if(cbc <= 0)\
523e12c5d1SDavid du Colombier 			cflush();\
533e12c5d1SDavid du Colombier 	}
543e12c5d1SDavid du Colombier 
55bfb6eab9SDavid du Colombier #define HPUT(h) { \
56bfb6eab9SDavid du Colombier 		if (little) { \
57bfb6eab9SDavid du Colombier 			HLEPUT(h); \
58bfb6eab9SDavid du Colombier 		} else { \
59bfb6eab9SDavid du Colombier 			HBEPUT(h); \
60bfb6eab9SDavid du Colombier 		} \
61bfb6eab9SDavid du Colombier 	}
62bfb6eab9SDavid du Colombier 
63bfb6eab9SDavid du Colombier #define	HLEPUT(c)\
64bfb6eab9SDavid du Colombier 	{\
65bfb6eab9SDavid du Colombier 		cbp[0] = (c);\
66bfb6eab9SDavid du Colombier 		cbp[1] = (c)>>8;\
67bfb6eab9SDavid du Colombier 		cbp += 2;\
68bfb6eab9SDavid du Colombier 		cbc -= 2;\
69bfb6eab9SDavid du Colombier 		if(cbc <= 0)\
70bfb6eab9SDavid du Colombier 			cflush();\
71bfb6eab9SDavid du Colombier 	}
72bfb6eab9SDavid du Colombier 
73bfb6eab9SDavid du Colombier #define	HBEPUT(c)\
74bfb6eab9SDavid du Colombier 	{\
75bfb6eab9SDavid du Colombier 		cbp[0] = (c)>>8;\
76bfb6eab9SDavid du Colombier 		cbp[1] = (c);\
77bfb6eab9SDavid du Colombier 		cbp += 2;\
78bfb6eab9SDavid du Colombier 		cbc -= 2;\
79bfb6eab9SDavid du Colombier 		if(cbc <= 0)\
80bfb6eab9SDavid du Colombier 			cflush();\
81bfb6eab9SDavid du Colombier 	}
82bfb6eab9SDavid du Colombier 
8391178603SDavid du Colombier 
843e12c5d1SDavid du Colombier #define	CPUT(c)\
853e12c5d1SDavid du Colombier 	{\
863e12c5d1SDavid du Colombier 		cbp[0] = (c);\
873e12c5d1SDavid du Colombier 		cbp++;\
883e12c5d1SDavid du Colombier 		cbc--;\
893e12c5d1SDavid du Colombier 		if(cbc <= 0)\
903e12c5d1SDavid du Colombier 			cflush();\
913e12c5d1SDavid du Colombier 	}
923e12c5d1SDavid du Colombier 
9391178603SDavid du Colombier void
948153b942SDavid du Colombier cput(long l)
958153b942SDavid du Colombier {
968153b942SDavid du Colombier 	CPUT(l);
978153b942SDavid du Colombier }
988153b942SDavid du Colombier 
998153b942SDavid du Colombier void
10091178603SDavid du Colombier objput(long l)	/* emit long in byte order appropriate to object machine */
10191178603SDavid du Colombier {
10291178603SDavid du Colombier 	LPUT(l);
10391178603SDavid du Colombier }
10491178603SDavid du Colombier 
10591178603SDavid du Colombier void
106bfb6eab9SDavid du Colombier objhput(short s)
107bfb6eab9SDavid du Colombier {
108bfb6eab9SDavid du Colombier 	HPUT(s);
109bfb6eab9SDavid du Colombier }
110bfb6eab9SDavid du Colombier 
111bfb6eab9SDavid du Colombier void
1128153b942SDavid du Colombier wput(long l)
1138153b942SDavid du Colombier {
1148153b942SDavid du Colombier 
1158153b942SDavid du Colombier 	cbp[0] = l>>8;
1168153b942SDavid du Colombier 	cbp[1] = l;
1178153b942SDavid du Colombier 	cbp += 2;
1188153b942SDavid du Colombier 	cbc -= 2;
1198153b942SDavid du Colombier 	if(cbc <= 0)
1208153b942SDavid du Colombier 		cflush();
1218153b942SDavid du Colombier }
1228153b942SDavid du Colombier 
1238153b942SDavid du Colombier void
1248153b942SDavid du Colombier wputl(long l)
1258153b942SDavid du Colombier {
1268153b942SDavid du Colombier 
1278153b942SDavid du Colombier 	cbp[0] = l;
1288153b942SDavid du Colombier 	cbp[1] = l>>8;
1298153b942SDavid du Colombier 	cbp += 2;
1308153b942SDavid du Colombier 	cbc -= 2;
1318153b942SDavid du Colombier 	if(cbc <= 0)
1328153b942SDavid du Colombier 		cflush();
1338153b942SDavid du Colombier }
1348153b942SDavid du Colombier 
1358153b942SDavid du Colombier void
13691178603SDavid du Colombier lput(long l)		/* emit long in big-endian byte order */
13791178603SDavid du Colombier {
13891178603SDavid du Colombier 	LBEPUT(l);
13991178603SDavid du Colombier }
14091178603SDavid du Colombier 
1418153b942SDavid du Colombier void
1428153b942SDavid du Colombier lputl(long l)		/* emit long in big-endian byte order */
1438153b942SDavid du Colombier {
1448153b942SDavid du Colombier 	LLEPUT(l);
1458153b942SDavid du Colombier }
1468153b942SDavid du Colombier 
1478153b942SDavid du Colombier void
1488153b942SDavid du Colombier llput(vlong v)
1498153b942SDavid du Colombier {
1508153b942SDavid du Colombier 	lput(v>>32);
1518153b942SDavid du Colombier 	lput(v);
1528153b942SDavid du Colombier }
1538153b942SDavid du Colombier 
1548153b942SDavid du Colombier void
1558153b942SDavid du Colombier llputl(vlong v)
1568153b942SDavid du Colombier {
1578153b942SDavid du Colombier 	lputl(v);
1588153b942SDavid du Colombier 	lputl(v>>32);
1598153b942SDavid du Colombier }
1608153b942SDavid du Colombier 
1613e12c5d1SDavid du Colombier long
1623e12c5d1SDavid du Colombier entryvalue(void)
1633e12c5d1SDavid du Colombier {
1643e12c5d1SDavid du Colombier 	char *a;
1653e12c5d1SDavid du Colombier 	Sym *s;
1663e12c5d1SDavid du Colombier 
1673e12c5d1SDavid du Colombier 	a = INITENTRY;
1683e12c5d1SDavid du Colombier 	if(*a >= '0' && *a <= '9')
1693e12c5d1SDavid du Colombier 		return atolwhex(a);
1703e12c5d1SDavid du Colombier 	s = lookup(a, 0);
1713e12c5d1SDavid du Colombier 	if(s->type == 0)
1723e12c5d1SDavid du Colombier 		return INITTEXT;
1733e12c5d1SDavid du Colombier 	if(s->type != STEXT && s->type != SLEAF)
1743e12c5d1SDavid du Colombier 		diag("entry not text: %s", s->name);
1753e12c5d1SDavid du Colombier 	return s->value;
1763e12c5d1SDavid du Colombier }
1773e12c5d1SDavid du Colombier 
178*5482313dSDavid du Colombier static void
179*5482313dSDavid du Colombier plan9bootimage(ulong sects, ulong submagicvers, ulong tm,
180*5482313dSDavid du Colombier 	ulong hdrtxtsz, ulong textsz, ulong textva, ulong lcsize)
181*5482313dSDavid du Colombier {
182*5482313dSDavid du Colombier 	lput(0x160L<<16|sects);		/* magic and sections */
183*5482313dSDavid du Colombier 	lput(tm);			/* time and date */
184*5482313dSDavid du Colombier 	lput(hdrtxtsz+datsize);		/* offset to symbol table */
185*5482313dSDavid du Colombier 	lput(symsize);			/* size of symbol table */
186*5482313dSDavid du Colombier 	lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
187*5482313dSDavid du Colombier 	lput(submagicvers);		/* magic and version */
188*5482313dSDavid du Colombier 
189*5482313dSDavid du Colombier 	lput(textsz);			/* segment sizes */
190*5482313dSDavid du Colombier 	lput(datsize);
191*5482313dSDavid du Colombier 	lput(bsssize);
192*5482313dSDavid du Colombier 
193*5482313dSDavid du Colombier 	lput(entryvalue());		/* va of entry */
194*5482313dSDavid du Colombier 	lput(textva);			/* va of base of text */
195*5482313dSDavid du Colombier 	lput(INITDAT);			/* va of base of data */
196*5482313dSDavid du Colombier 	lput(INITDAT+datsize);		/* va of base of bss */
197*5482313dSDavid du Colombier 
198*5482313dSDavid du Colombier 	lput(~0);			/* gp reg mask */
199*5482313dSDavid du Colombier 	lput(lcsize);			/* pcsize / cprmask[0] */
200*5482313dSDavid du Colombier 	lput(0);			/* coproc reg masks[1⋯3] */
201*5482313dSDavid du Colombier 	lput(0);
202*5482313dSDavid du Colombier 	lput(0);
203*5482313dSDavid du Colombier 	lput(~0);			/* gp value ?? */
204*5482313dSDavid du Colombier }
205*5482313dSDavid du Colombier 
206*5482313dSDavid du Colombier static void
207*5482313dSDavid du Colombier symhdrs(ulong hdrtxtsz)
208*5482313dSDavid du Colombier {
209*5482313dSDavid du Colombier 	strnput(".text", 8);		/* text segment */
210*5482313dSDavid du Colombier 	lput(INITTEXT);			/* address */
211*5482313dSDavid du Colombier 	lput(INITTEXT);
212*5482313dSDavid du Colombier 	lput(textsize);
213*5482313dSDavid du Colombier 	lput(HEADR);
214*5482313dSDavid du Colombier 	lput(0);
215*5482313dSDavid du Colombier 	lput(HEADR+textsize+datsize+symsize);
216*5482313dSDavid du Colombier 	lput(lcsize);			/* line number size */
217*5482313dSDavid du Colombier 	lput(0x20);			/* flags */
218*5482313dSDavid du Colombier 
219*5482313dSDavid du Colombier 	strnput(".data", 8);		/* data segment */
220*5482313dSDavid du Colombier 	lput(INITDAT);			/* address */
221*5482313dSDavid du Colombier 	lput(INITDAT);
222*5482313dSDavid du Colombier 	lput(datsize);
223*5482313dSDavid du Colombier 	lput(hdrtxtsz);
224*5482313dSDavid du Colombier 	lput(0);
225*5482313dSDavid du Colombier 	lput(0);
226*5482313dSDavid du Colombier 	lput(0);
227*5482313dSDavid du Colombier 	lput(0x40);			/* flags */
228*5482313dSDavid du Colombier 
229*5482313dSDavid du Colombier 	strnput(".bss", 8);		/* bss segment */
230*5482313dSDavid du Colombier 	lput(INITDAT+datsize);		/* address */
231*5482313dSDavid du Colombier 	lput(INITDAT+datsize);
232*5482313dSDavid du Colombier 	lput(bsssize);
233*5482313dSDavid du Colombier 	lput(0);
234*5482313dSDavid du Colombier 	lput(0);
235*5482313dSDavid du Colombier 	lput(0);
236*5482313dSDavid du Colombier 	lput(0);
237*5482313dSDavid du Colombier 	lput(0x80);			/* flags */
238*5482313dSDavid du Colombier }
239*5482313dSDavid du Colombier 
2403e12c5d1SDavid du Colombier void
2413e12c5d1SDavid du Colombier asmb(void)
2423e12c5d1SDavid du Colombier {
2433e12c5d1SDavid du Colombier 	Prog *p;
244*5482313dSDavid du Colombier 	long tm;
245*5482313dSDavid du Colombier 	ulong rndtxtsz;
246a587111cSDavid du Colombier 	vlong t, etext;
2473e12c5d1SDavid du Colombier 	Optab *o;
2483e12c5d1SDavid du Colombier 
2493e12c5d1SDavid du Colombier 	if(debug['v'])
2503e12c5d1SDavid du Colombier 		Bprint(&bso, "%5.2f asm\n", cputime());
2513e12c5d1SDavid du Colombier 	Bflush(&bso);
252bd389b36SDavid du Colombier 	OFFSET = HEADR;
253bd389b36SDavid du Colombier 	seek(cout, OFFSET, 0);
2543e12c5d1SDavid du Colombier 	pc = INITTEXT;
2553e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
2563e12c5d1SDavid du Colombier 		if(p->as == ATEXT) {
2573e12c5d1SDavid du Colombier 			curtext = p;
2583e12c5d1SDavid du Colombier 			autosize = p->to.offset + 4;
2593e12c5d1SDavid du Colombier 		}
2603e12c5d1SDavid du Colombier 		if(p->pc != pc) {
261a587111cSDavid du Colombier 			diag("phase error %llux sb %llux", p->pc, pc);
2623e12c5d1SDavid du Colombier 			if(!debug['a'])
2633e12c5d1SDavid du Colombier 				prasm(curp);
2643e12c5d1SDavid du Colombier 			pc = p->pc;
2653e12c5d1SDavid du Colombier 		}
2663e12c5d1SDavid du Colombier 		curp = p;
2673e12c5d1SDavid du Colombier 		o = oplook(p);	/* could probably avoid this call */
2683e12c5d1SDavid du Colombier 		if(asmout(p, o, 0)) {
2693e12c5d1SDavid du Colombier 			p = p->link;
2703e12c5d1SDavid du Colombier 			pc += 4;
2713e12c5d1SDavid du Colombier 		}
2723e12c5d1SDavid du Colombier 		pc += o->size;
2733e12c5d1SDavid du Colombier 	}
2743e12c5d1SDavid du Colombier 	if(debug['a'])
2753e12c5d1SDavid du Colombier 		Bprint(&bso, "\n");
2763e12c5d1SDavid du Colombier 	Bflush(&bso);
2773e12c5d1SDavid du Colombier 	cflush();
2783e12c5d1SDavid du Colombier 
2799a747e4fSDavid du Colombier 	etext = INITTEXT + textsize;
2809a747e4fSDavid du Colombier 	for(t = pc; t < etext; t += sizeof(buf)-100) {
2819a747e4fSDavid du Colombier 		if(etext-t > sizeof(buf)-100)
2829a747e4fSDavid du Colombier 			datblk(t, sizeof(buf)-100, 1);
2839a747e4fSDavid du Colombier 		else
2849a747e4fSDavid du Colombier 			datblk(t, etext-t, 1);
2859a747e4fSDavid du Colombier 	}
2869a747e4fSDavid du Colombier 
2879a747e4fSDavid du Colombier 	Bflush(&bso);
2889a747e4fSDavid du Colombier 	cflush();
2899a747e4fSDavid du Colombier 
2903e12c5d1SDavid du Colombier 	curtext = P;
2913e12c5d1SDavid du Colombier 	switch(HEADTYPE) {
2923e12c5d1SDavid du Colombier 	case 0:
293219b2ee8SDavid du Colombier 	case 4:
294bd389b36SDavid du Colombier 		OFFSET = rnd(HEADR+textsize, 4096);
295bd389b36SDavid du Colombier 		seek(cout, OFFSET, 0);
2963e12c5d1SDavid du Colombier 		break;
2973e12c5d1SDavid du Colombier 	case 1:
2983e12c5d1SDavid du Colombier 	case 2:
299219b2ee8SDavid du Colombier 	case 3:
300219b2ee8SDavid du Colombier 	case 5:
30191178603SDavid du Colombier 	case 6:
302bd389b36SDavid du Colombier 		OFFSET = HEADR+textsize;
303bd389b36SDavid du Colombier 		seek(cout, OFFSET, 0);
3043e12c5d1SDavid du Colombier 		break;
3053e12c5d1SDavid du Colombier 	}
3063e12c5d1SDavid du Colombier 	for(t = 0; t < datsize; t += sizeof(buf)-100) {
3073e12c5d1SDavid du Colombier 		if(datsize-t > sizeof(buf)-100)
3089a747e4fSDavid du Colombier 			datblk(t, sizeof(buf)-100, 0);
3093e12c5d1SDavid du Colombier 		else
3109a747e4fSDavid du Colombier 			datblk(t, datsize-t, 0);
3113e12c5d1SDavid du Colombier 	}
3123e12c5d1SDavid du Colombier 
3133e12c5d1SDavid du Colombier 	symsize = 0;
3143e12c5d1SDavid du Colombier 	lcsize = 0;
3153e12c5d1SDavid du Colombier 	if(!debug['s']) {
3163e12c5d1SDavid du Colombier 		if(debug['v'])
3173e12c5d1SDavid du Colombier 			Bprint(&bso, "%5.2f sym\n", cputime());
3183e12c5d1SDavid du Colombier 		Bflush(&bso);
3193e12c5d1SDavid du Colombier 		switch(HEADTYPE) {
3203e12c5d1SDavid du Colombier 		case 0:
321219b2ee8SDavid du Colombier 		case 4:
322bd389b36SDavid du Colombier 			OFFSET = rnd(HEADR+textsize, 4096)+datsize;
323bd389b36SDavid du Colombier 			seek(cout, OFFSET, 0);
3243e12c5d1SDavid du Colombier 			break;
325219b2ee8SDavid du Colombier 		case 3:
3263e12c5d1SDavid du Colombier 		case 2:
3273e12c5d1SDavid du Colombier 		case 1:
328219b2ee8SDavid du Colombier 		case 5:
32991178603SDavid du Colombier 		case 6:
330bd389b36SDavid du Colombier 			OFFSET = HEADR+textsize+datsize;
331bd389b36SDavid du Colombier 			seek(cout, OFFSET, 0);
3323e12c5d1SDavid du Colombier 			break;
3333e12c5d1SDavid du Colombier 		}
3343e12c5d1SDavid du Colombier 		if(!debug['s'])
3353e12c5d1SDavid du Colombier 			asmsym();
3363e12c5d1SDavid du Colombier 		if(debug['v'])
3373e12c5d1SDavid du Colombier 			Bprint(&bso, "%5.2f pc\n", cputime());
3383e12c5d1SDavid du Colombier 		Bflush(&bso);
3393e12c5d1SDavid du Colombier 		if(!debug['s'])
3403e12c5d1SDavid du Colombier 			asmlc();
3413e12c5d1SDavid du Colombier 		cflush();
3423e12c5d1SDavid du Colombier 	}
3433e12c5d1SDavid du Colombier 
3443e12c5d1SDavid du Colombier 	if(debug['v'])
3453e12c5d1SDavid du Colombier 		Bprint(&bso, "%5.2f header\n", cputime());
3463e12c5d1SDavid du Colombier 	Bflush(&bso);
347bd389b36SDavid du Colombier 	OFFSET = 0;
348bd389b36SDavid du Colombier 	seek(cout, OFFSET, 0);
349*5482313dSDavid du Colombier 
350*5482313dSDavid du Colombier 	rndtxtsz = rnd(HEADR+textsize, (INITRND > 0? INITRND: 4096));
351*5482313dSDavid du Colombier 	tm = time(0);
3523e12c5d1SDavid du Colombier 	switch(HEADTYPE) {
3533e12c5d1SDavid du Colombier 	case 0:
354*5482313dSDavid du Colombier 		/* 0413: plan 9 boot image, text segment rounded (to 4KB) */
355*5482313dSDavid du Colombier 		plan9bootimage(0, 0413<<16|0437, 0, rndtxtsz, rndtxtsz,
356*5482313dSDavid du Colombier 			INITTEXT-HEADR, 0);
3573e12c5d1SDavid du Colombier 		break;
3583e12c5d1SDavid du Colombier 	case 1:
359*5482313dSDavid du Colombier 		/* 0407: plan 9 boot image, extra word */
360*5482313dSDavid du Colombier 		plan9bootimage(0, 0407<<16|0437, 0, HEADR+textsize, textsize,
361*5482313dSDavid du Colombier 			INITTEXT, lcsize);
362*5482313dSDavid du Colombier 		lput(0);			/* extra; complete mystery */
3633e12c5d1SDavid du Colombier 		break;
3643305c317SDavid du Colombier 	case 2:					/* plan 9 format */
36591178603SDavid du Colombier 		if (little)
3663305c317SDavid du Colombier 			lput(P_MAGIC);		/* mips 3000 LE */
36791178603SDavid du Colombier 		else
3683305c317SDavid du Colombier 			lput(V_MAGIC);		/* mips 3000 BE */
3693e12c5d1SDavid du Colombier 		lput(textsize);			/* sizes */
3703e12c5d1SDavid du Colombier 		lput(datsize);
3713e12c5d1SDavid du Colombier 		lput(bsssize);
3723e12c5d1SDavid du Colombier 		lput(symsize);			/* nsyms */
3733e12c5d1SDavid du Colombier 		lput(entryvalue());		/* va of entry */
3743e12c5d1SDavid du Colombier 		lput(0L);
3753e12c5d1SDavid du Colombier 		lput(lcsize);
3763e12c5d1SDavid du Colombier 		break;
377219b2ee8SDavid du Colombier 	case 3:
378*5482313dSDavid du Colombier 		/* 0407: plan 9 mips 4k boot image with symbols */
379*5482313dSDavid du Colombier 		plan9bootimage(3, 0407<<16|0437, tm, HEADR+textsize, textsize,
380*5482313dSDavid du Colombier 			INITTEXT, lcsize);
381*5482313dSDavid du Colombier 		symhdrs(HEADR+textsize);
382219b2ee8SDavid du Colombier 		break;
383219b2ee8SDavid du Colombier 	case 4:
384*5482313dSDavid du Colombier 		/* 0413: plan 9 mips 4k boot image with symbols */
385*5482313dSDavid du Colombier 		plan9bootimage(3, 0413<<16|01012, tm, rndtxtsz, textsize,
386*5482313dSDavid du Colombier 			INITTEXT, lcsize);
387*5482313dSDavid du Colombier 		symhdrs(rndtxtsz);
388219b2ee8SDavid du Colombier 		break;
389219b2ee8SDavid du Colombier 	case 5:
3908153b942SDavid du Colombier 		elf32(MIPS, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
39191178603SDavid du Colombier 		break;
39291178603SDavid du Colombier 	case 6:
39391178603SDavid du Colombier 		break;
394a587111cSDavid du Colombier 	case 7:
395a587111cSDavid du Colombier 		elf64(MIPSR4K, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
396a587111cSDavid du Colombier 		break;
3973e12c5d1SDavid du Colombier 	}
3983e12c5d1SDavid du Colombier 	cflush();
3993e12c5d1SDavid du Colombier }
4003e12c5d1SDavid du Colombier 
4013e12c5d1SDavid du Colombier void
402219b2ee8SDavid du Colombier strnput(char *s, int n)
403219b2ee8SDavid du Colombier {
404219b2ee8SDavid du Colombier 	for(; *s; s++){
405219b2ee8SDavid du Colombier 		CPUT(*s);
406219b2ee8SDavid du Colombier 		n--;
407219b2ee8SDavid du Colombier 	}
408219b2ee8SDavid du Colombier 	for(; n > 0; n--)
409219b2ee8SDavid du Colombier 		CPUT(0);
410219b2ee8SDavid du Colombier }
411219b2ee8SDavid du Colombier 
412219b2ee8SDavid du Colombier void
4133e12c5d1SDavid du Colombier cflush(void)
4143e12c5d1SDavid du Colombier {
4153e12c5d1SDavid du Colombier 	int n;
4163e12c5d1SDavid du Colombier 
4173e12c5d1SDavid du Colombier 	n = sizeof(buf.cbuf) - cbc;
4183e12c5d1SDavid du Colombier 	if(n)
4193e12c5d1SDavid du Colombier 		write(cout, buf.cbuf, n);
4203e12c5d1SDavid du Colombier 	cbp = buf.cbuf;
4213e12c5d1SDavid du Colombier 	cbc = sizeof(buf.cbuf);
4223e12c5d1SDavid du Colombier }
4233e12c5d1SDavid du Colombier 
4243e12c5d1SDavid du Colombier void
425219b2ee8SDavid du Colombier nopstat(char *f, Count *c)
426219b2ee8SDavid du Colombier {
427219b2ee8SDavid du Colombier 	if(c->outof)
428219b2ee8SDavid du Colombier 	Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
429219b2ee8SDavid du Colombier 		c->outof - c->count, c->outof,
430219b2ee8SDavid du Colombier 		(double)(c->outof - c->count)/c->outof);
431219b2ee8SDavid du Colombier }
432219b2ee8SDavid du Colombier 
433219b2ee8SDavid du Colombier void
4343e12c5d1SDavid du Colombier asmsym(void)
4353e12c5d1SDavid du Colombier {
4363e12c5d1SDavid du Colombier 	Prog *p;
4373e12c5d1SDavid du Colombier 	Auto *a;
4383e12c5d1SDavid du Colombier 	Sym *s;
4393e12c5d1SDavid du Colombier 	int h;
4403e12c5d1SDavid du Colombier 
4413e12c5d1SDavid du Colombier 	s = lookup("etext", 0);
4423e12c5d1SDavid du Colombier 	if(s->type == STEXT)
4433e12c5d1SDavid du Colombier 		putsymb(s->name, 'T', s->value, s->version);
4443e12c5d1SDavid du Colombier 
4453e12c5d1SDavid du Colombier 	for(h=0; h<NHASH; h++)
4463e12c5d1SDavid du Colombier 		for(s=hash[h]; s!=S; s=s->link)
4473e12c5d1SDavid du Colombier 			switch(s->type) {
448219b2ee8SDavid du Colombier 			case SCONST:
449219b2ee8SDavid du Colombier 				putsymb(s->name, 'D', s->value, s->version);
450219b2ee8SDavid du Colombier 				continue;
451219b2ee8SDavid du Colombier 
4529a747e4fSDavid du Colombier 			case SSTRING:
4539a747e4fSDavid du Colombier 				putsymb(s->name, 'T', s->value, s->version);
4549a747e4fSDavid du Colombier 				continue;
4559a747e4fSDavid du Colombier 
4563e12c5d1SDavid du Colombier 			case SDATA:
4573e12c5d1SDavid du Colombier 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
4583e12c5d1SDavid du Colombier 				continue;
4593e12c5d1SDavid du Colombier 
4603e12c5d1SDavid du Colombier 			case SBSS:
4613e12c5d1SDavid du Colombier 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
4623e12c5d1SDavid du Colombier 				continue;
4633e12c5d1SDavid du Colombier 
4643e12c5d1SDavid du Colombier 			case SFILE:
4653e12c5d1SDavid du Colombier 				putsymb(s->name, 'f', s->value, s->version);
4663e12c5d1SDavid du Colombier 				continue;
4673e12c5d1SDavid du Colombier 			}
4683e12c5d1SDavid du Colombier 
4693e12c5d1SDavid du Colombier 	for(p=textp; p!=P; p=p->cond) {
4703e12c5d1SDavid du Colombier 		s = p->from.sym;
4713e12c5d1SDavid du Colombier 		if(s->type != STEXT && s->type != SLEAF)
4723e12c5d1SDavid du Colombier 			continue;
4733e12c5d1SDavid du Colombier 
4743e12c5d1SDavid du Colombier 		/* filenames first */
4753e12c5d1SDavid du Colombier 		for(a=p->to.autom; a; a=a->link)
4763e12c5d1SDavid du Colombier 			if(a->type == D_FILE)
4777dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'z', a->aoffset, 0);
4783e12c5d1SDavid du Colombier 			else
479219b2ee8SDavid du Colombier 			if(a->type == D_FILE1)
4807dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'Z', a->aoffset, 0);
4813e12c5d1SDavid du Colombier 
4823e12c5d1SDavid du Colombier 		if(s->type == STEXT)
4833e12c5d1SDavid du Colombier 			putsymb(s->name, 'T', s->value, s->version);
4843e12c5d1SDavid du Colombier 		else
4853e12c5d1SDavid du Colombier 			putsymb(s->name, 'L', s->value, s->version);
4863e12c5d1SDavid du Colombier 
4873e12c5d1SDavid du Colombier 		/* frame, auto and param after */
488219b2ee8SDavid du Colombier 		putsymb(".frame", 'm', p->to.offset+4, 0);
4893e12c5d1SDavid du Colombier 		for(a=p->to.autom; a; a=a->link)
4903e12c5d1SDavid du Colombier 			if(a->type == D_AUTO)
4917dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'a', -a->aoffset, 0);
4923e12c5d1SDavid du Colombier 			else
4933e12c5d1SDavid du Colombier 			if(a->type == D_PARAM)
4947dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'p', a->aoffset, 0);
4953e12c5d1SDavid du Colombier 	}
4963e12c5d1SDavid du Colombier 	if(debug['v'] || debug['n'])
4973e12c5d1SDavid du Colombier 		Bprint(&bso, "symsize = %lud\n", symsize);
4983e12c5d1SDavid du Colombier 	Bflush(&bso);
4993e12c5d1SDavid du Colombier }
5003e12c5d1SDavid du Colombier 
5013e12c5d1SDavid du Colombier void
5023e12c5d1SDavid du Colombier putsymb(char *s, int t, long v, int ver)
5033e12c5d1SDavid du Colombier {
5043e12c5d1SDavid du Colombier 	int i, f;
5053e12c5d1SDavid du Colombier 
5063e12c5d1SDavid du Colombier 	if(t == 'f')
5073e12c5d1SDavid du Colombier 		s++;
50891178603SDavid du Colombier 	LBEPUT(v);
5093e12c5d1SDavid du Colombier 	if(ver)
5103e12c5d1SDavid du Colombier 		t += 'a' - 'A';
511219b2ee8SDavid du Colombier 	CPUT(t+0x80);			/* 0x80 is variable length */
512219b2ee8SDavid du Colombier 
513219b2ee8SDavid du Colombier 	if(t == 'Z' || t == 'z') {
514219b2ee8SDavid du Colombier 		CPUT(s[0]);
515219b2ee8SDavid du Colombier 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
516219b2ee8SDavid du Colombier 			CPUT(s[i]);
517219b2ee8SDavid du Colombier 			CPUT(s[i+1]);
518219b2ee8SDavid du Colombier 		}
519219b2ee8SDavid du Colombier 		CPUT(0);
520219b2ee8SDavid du Colombier 		CPUT(0);
521219b2ee8SDavid du Colombier 		i++;
522219b2ee8SDavid du Colombier 	}
523219b2ee8SDavid du Colombier 	else {
524219b2ee8SDavid du Colombier 		for(i=0; s[i]; i++)
5253e12c5d1SDavid du Colombier 			CPUT(s[i]);
5263e12c5d1SDavid du Colombier 		CPUT(0);
527219b2ee8SDavid du Colombier 	}
528219b2ee8SDavid du Colombier 	symsize += 4 + 1 + i + 1;
529219b2ee8SDavid du Colombier 
5303e12c5d1SDavid du Colombier 	if(debug['n']) {
5313e12c5d1SDavid du Colombier 		if(t == 'z' || t == 'Z') {
532219b2ee8SDavid du Colombier 			Bprint(&bso, "%c %.8lux ", t, v);
533219b2ee8SDavid du Colombier 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
5343e12c5d1SDavid du Colombier 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
535219b2ee8SDavid du Colombier 				Bprint(&bso, "/%x", f);
5363e12c5d1SDavid du Colombier 			}
537219b2ee8SDavid du Colombier 			Bprint(&bso, "\n");
5383e12c5d1SDavid du Colombier 			return;
5393e12c5d1SDavid du Colombier 		}
5403e12c5d1SDavid du Colombier 		if(ver)
5413e12c5d1SDavid du Colombier 			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
5423e12c5d1SDavid du Colombier 		else
5433e12c5d1SDavid du Colombier 			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
5443e12c5d1SDavid du Colombier 	}
5453e12c5d1SDavid du Colombier }
5463e12c5d1SDavid du Colombier 
5473e12c5d1SDavid du Colombier #define	MINLC	4
5483e12c5d1SDavid du Colombier void
5493e12c5d1SDavid du Colombier asmlc(void)
5503e12c5d1SDavid du Colombier {
551a587111cSDavid du Colombier 	long oldlc, v, s;
552a587111cSDavid du Colombier 	vlong oldpc;
5533e12c5d1SDavid du Colombier 	Prog *p;
5543e12c5d1SDavid du Colombier 
5553e12c5d1SDavid du Colombier 	oldpc = INITTEXT;
5563e12c5d1SDavid du Colombier 	oldlc = 0;
5573e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
5583e12c5d1SDavid du Colombier 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
5593e12c5d1SDavid du Colombier 			if(p->as == ATEXT)
5603e12c5d1SDavid du Colombier 				curtext = p;
561b87cd620SDavid du Colombier 			if(debug['V'])
562a587111cSDavid du Colombier 				Bprint(&bso, "%6llux %P\n", p->pc, p);
5633e12c5d1SDavid du Colombier 			continue;
5643e12c5d1SDavid du Colombier 		}
565b87cd620SDavid du Colombier 		if(debug['V'])
5663e12c5d1SDavid du Colombier 			Bprint(&bso, "\t\t%6ld", lcsize);
5673e12c5d1SDavid du Colombier 		v = (p->pc - oldpc) / MINLC;
5683e12c5d1SDavid du Colombier 		while(v) {
5693e12c5d1SDavid du Colombier 			s = 127;
5703e12c5d1SDavid du Colombier 			if(v < 127)
5713e12c5d1SDavid du Colombier 				s = v;
5723e12c5d1SDavid du Colombier 			CPUT(s+128);	/* 129-255 +pc */
573b87cd620SDavid du Colombier 			if(debug['V'])
5743e12c5d1SDavid du Colombier 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
5753e12c5d1SDavid du Colombier 			v -= s;
5763e12c5d1SDavid du Colombier 			lcsize++;
5773e12c5d1SDavid du Colombier 		}
5783e12c5d1SDavid du Colombier 		s = p->line - oldlc;
5793e12c5d1SDavid du Colombier 		oldlc = p->line;
5803e12c5d1SDavid du Colombier 		oldpc = p->pc + MINLC;
5813e12c5d1SDavid du Colombier 		if(s > 64 || s < -64) {
5823e12c5d1SDavid du Colombier 			CPUT(0);	/* 0 vv +lc */
5833e12c5d1SDavid du Colombier 			CPUT(s>>24);
5843e12c5d1SDavid du Colombier 			CPUT(s>>16);
5853e12c5d1SDavid du Colombier 			CPUT(s>>8);
5863e12c5d1SDavid du Colombier 			CPUT(s);
587b87cd620SDavid du Colombier 			if(debug['V']) {
5883e12c5d1SDavid du Colombier 				if(s > 0)
5893e12c5d1SDavid du Colombier 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
5903e12c5d1SDavid du Colombier 						s, 0, s);
5913e12c5d1SDavid du Colombier 				else
5923e12c5d1SDavid du Colombier 					Bprint(&bso, " lc%ld(%d,%ld)\n",
5933e12c5d1SDavid du Colombier 						s, 0, s);
594a587111cSDavid du Colombier 				Bprint(&bso, "%6llux %P\n", p->pc, p);
5953e12c5d1SDavid du Colombier 			}
5963e12c5d1SDavid du Colombier 			lcsize += 5;
5973e12c5d1SDavid du Colombier 			continue;
5983e12c5d1SDavid du Colombier 		}
5993e12c5d1SDavid du Colombier 		if(s > 0) {
6003e12c5d1SDavid du Colombier 			CPUT(0+s);	/* 1-64 +lc */
601b87cd620SDavid du Colombier 			if(debug['V']) {
6023e12c5d1SDavid du Colombier 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
603a587111cSDavid du Colombier 				Bprint(&bso, "%6llux %P\n", p->pc, p);
6043e12c5d1SDavid du Colombier 			}
6053e12c5d1SDavid du Colombier 		} else {
6063e12c5d1SDavid du Colombier 			CPUT(64-s);	/* 65-128 -lc */
607b87cd620SDavid du Colombier 			if(debug['V']) {
6083e12c5d1SDavid du Colombier 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
609a587111cSDavid du Colombier 				Bprint(&bso, "%6llux %P\n", p->pc, p);
6103e12c5d1SDavid du Colombier 			}
6113e12c5d1SDavid du Colombier 		}
6123e12c5d1SDavid du Colombier 		lcsize++;
6133e12c5d1SDavid du Colombier 	}
6143e12c5d1SDavid du Colombier 	while(lcsize & 1) {
6153e12c5d1SDavid du Colombier 		s = 129;
6163e12c5d1SDavid du Colombier 		CPUT(s);
6173e12c5d1SDavid du Colombier 		lcsize++;
6183e12c5d1SDavid du Colombier 	}
619b87cd620SDavid du Colombier 	if(debug['v'] || debug['V'])
6203e12c5d1SDavid du Colombier 		Bprint(&bso, "lcsize = %ld\n", lcsize);
6213e12c5d1SDavid du Colombier 	Bflush(&bso);
6223e12c5d1SDavid du Colombier }
6233e12c5d1SDavid du Colombier 
6243e12c5d1SDavid du Colombier void
6259a747e4fSDavid du Colombier datblk(long s, long n, int str)
6263e12c5d1SDavid du Colombier {
6273e12c5d1SDavid du Colombier 	Prog *p;
6283e12c5d1SDavid du Colombier 	char *cast;
6293e12c5d1SDavid du Colombier 	long l, fl, j, d;
6303e12c5d1SDavid du Colombier 	int i, c;
6313e12c5d1SDavid du Colombier 
6323e12c5d1SDavid du Colombier 	memset(buf.dbuf, 0, n+100);
6333e12c5d1SDavid du Colombier 	for(p = datap; p != P; p = p->link) {
6343e12c5d1SDavid du Colombier 		curp = p;
6359a747e4fSDavid du Colombier 		if(str != (p->from.sym->type == SSTRING))
6369a747e4fSDavid du Colombier 			continue;
6373e12c5d1SDavid du Colombier 		l = p->from.sym->value + p->from.offset - s;
6383e12c5d1SDavid du Colombier 		c = p->reg;
6393e12c5d1SDavid du Colombier 		i = 0;
6403e12c5d1SDavid du Colombier 		if(l < 0) {
6413e12c5d1SDavid du Colombier 			if(l+c <= 0)
6423e12c5d1SDavid du Colombier 				continue;
6433e12c5d1SDavid du Colombier 			while(l < 0) {
6443e12c5d1SDavid du Colombier 				l++;
6453e12c5d1SDavid du Colombier 				i++;
6463e12c5d1SDavid du Colombier 			}
6473e12c5d1SDavid du Colombier 		}
6483e12c5d1SDavid du Colombier 		if(l >= n)
6493e12c5d1SDavid du Colombier 			continue;
650219b2ee8SDavid du Colombier 		if(p->as != AINIT && p->as != ADYNT) {
6513e12c5d1SDavid du Colombier 			for(j=l+(c-i)-1; j>=l; j--)
6523e12c5d1SDavid du Colombier 				if(buf.dbuf[j]) {
6533e12c5d1SDavid du Colombier 					print("%P\n", p);
6546b6b9ac8SDavid du Colombier 					diag("multiple initialization");
6553e12c5d1SDavid du Colombier 					break;
6563e12c5d1SDavid du Colombier 				}
657219b2ee8SDavid du Colombier 		}
6583e12c5d1SDavid du Colombier 		switch(p->to.type) {
6593e12c5d1SDavid du Colombier 		default:
6606b6b9ac8SDavid du Colombier 			diag("unknown mode in initialization\n%P", p);
6613e12c5d1SDavid du Colombier 			break;
6623e12c5d1SDavid du Colombier 
6633e12c5d1SDavid du Colombier 		case D_FCONST:
6643e12c5d1SDavid du Colombier 			switch(c) {
6653e12c5d1SDavid du Colombier 			default:
6663e12c5d1SDavid du Colombier 			case 4:
6673e12c5d1SDavid du Colombier 				fl = ieeedtof(p->to.ieee);
6683e12c5d1SDavid du Colombier 				cast = (char*)&fl;
6693e12c5d1SDavid du Colombier 				for(; i<c; i++) {
6703e12c5d1SDavid du Colombier 					buf.dbuf[l] = cast[fnuxi8[i+4]];
6713e12c5d1SDavid du Colombier 					l++;
6723e12c5d1SDavid du Colombier 				}
6733e12c5d1SDavid du Colombier 				break;
6743e12c5d1SDavid du Colombier 			case 8:
6753e12c5d1SDavid du Colombier 				cast = (char*)p->to.ieee;
6763e12c5d1SDavid du Colombier 				for(; i<c; i++) {
6773e12c5d1SDavid du Colombier 					buf.dbuf[l] = cast[fnuxi8[i]];
6783e12c5d1SDavid du Colombier 					l++;
6793e12c5d1SDavid du Colombier 				}
6803e12c5d1SDavid du Colombier 				break;
6813e12c5d1SDavid du Colombier 			}
6823e12c5d1SDavid du Colombier 			break;
6833e12c5d1SDavid du Colombier 
6843e12c5d1SDavid du Colombier 		case D_SCONST:
6853e12c5d1SDavid du Colombier 			for(; i<c; i++) {
6863e12c5d1SDavid du Colombier 				buf.dbuf[l] = p->to.sval[i];
6873e12c5d1SDavid du Colombier 				l++;
6883e12c5d1SDavid du Colombier 			}
6893e12c5d1SDavid du Colombier 			break;
6903e12c5d1SDavid du Colombier 
6913e12c5d1SDavid du Colombier 		case D_CONST:
6923e12c5d1SDavid du Colombier 			d = p->to.offset;
6933e12c5d1SDavid du Colombier 			if(p->to.sym) {
6949a747e4fSDavid du Colombier 				switch(p->to.sym->type) {
6959a747e4fSDavid du Colombier 				case STEXT:
6969a747e4fSDavid du Colombier 				case SLEAF:
6979a747e4fSDavid du Colombier 				case SSTRING:
6983e12c5d1SDavid du Colombier 					d += p->to.sym->value;
6999a747e4fSDavid du Colombier 					break;
7009a747e4fSDavid du Colombier 				case SDATA:
7019a747e4fSDavid du Colombier 				case SBSS:
7023e12c5d1SDavid du Colombier 					d += p->to.sym->value + INITDAT;
7039a747e4fSDavid du Colombier 					break;
7049a747e4fSDavid du Colombier 				}
7053e12c5d1SDavid du Colombier 			}
7063e12c5d1SDavid du Colombier 			cast = (char*)&d;
7073e12c5d1SDavid du Colombier 			switch(c) {
7083e12c5d1SDavid du Colombier 			default:
7096b6b9ac8SDavid du Colombier 				diag("bad nuxi %d %d\n%P", c, i, curp);
7103e12c5d1SDavid du Colombier 				break;
7113e12c5d1SDavid du Colombier 			case 1:
7123e12c5d1SDavid du Colombier 				for(; i<c; i++) {
7133e12c5d1SDavid du Colombier 					buf.dbuf[l] = cast[inuxi1[i]];
7143e12c5d1SDavid du Colombier 					l++;
7153e12c5d1SDavid du Colombier 				}
7163e12c5d1SDavid du Colombier 				break;
7173e12c5d1SDavid du Colombier 			case 2:
7183e12c5d1SDavid du Colombier 				for(; i<c; i++) {
7193e12c5d1SDavid du Colombier 					buf.dbuf[l] = cast[inuxi2[i]];
7203e12c5d1SDavid du Colombier 					l++;
7213e12c5d1SDavid du Colombier 				}
7223e12c5d1SDavid du Colombier 				break;
7233e12c5d1SDavid du Colombier 			case 4:
7243e12c5d1SDavid du Colombier 				for(; i<c; i++) {
7253e12c5d1SDavid du Colombier 					buf.dbuf[l] = cast[inuxi4[i]];
7263e12c5d1SDavid du Colombier 					l++;
7273e12c5d1SDavid du Colombier 				}
7283e12c5d1SDavid du Colombier 				break;
7293e12c5d1SDavid du Colombier 			}
7303e12c5d1SDavid du Colombier 			break;
7313e12c5d1SDavid du Colombier 		}
7323e12c5d1SDavid du Colombier 	}
7333e12c5d1SDavid du Colombier 	write(cout, buf.dbuf, n);
7343e12c5d1SDavid du Colombier }
7353e12c5d1SDavid du Colombier 
7363e12c5d1SDavid du Colombier #define	OP_RRR(op,r1,r2,r3)\
7373e12c5d1SDavid du Colombier 	(op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|(((r3)&31L)<<11))
7383e12c5d1SDavid du Colombier #define	OP_IRR(op,i,r2,r3)\
7393e12c5d1SDavid du Colombier 	(op|((i)&0xffffL)|(((r2)&31L)<<21)|(((r3)&31L)<<16))
7403e12c5d1SDavid du Colombier #define	OP_SRR(op,s,r2,r3)\
7413e12c5d1SDavid du Colombier 	(op|(((s)&31L)<<6)|(((r2)&31L)<<16)|(((r3)&31L)<<11))
7423e12c5d1SDavid du Colombier #define	OP_FRRR(op,r1,r2,r3)\
7433e12c5d1SDavid du Colombier 	(op|(((r1)&31L)<<16)|(((r2)&31L)<<11)|(((r3)&31L)<<6))
7443e12c5d1SDavid du Colombier #define	OP_JMP(op,i)\
7453e12c5d1SDavid du Colombier 		((op)|((i)&0x3ffffffL))
7463e12c5d1SDavid du Colombier 
747219b2ee8SDavid du Colombier #define	OP(x,y)\
748219b2ee8SDavid du Colombier 	(((x)<<3)|((y)<<0))
749219b2ee8SDavid du Colombier #define	SP(x,y)\
750219b2ee8SDavid du Colombier 	(((x)<<29)|((y)<<26))
751219b2ee8SDavid du Colombier #define	BCOND(x,y)\
752219b2ee8SDavid du Colombier 	(((x)<<19)|((y)<<16))
753219b2ee8SDavid du Colombier #define	MMU(x,y)\
754219b2ee8SDavid du Colombier 	(SP(2,0)|(16<<21)|((x)<<3)|((y)<<0))
755219b2ee8SDavid du Colombier #define	FPF(x,y)\
756219b2ee8SDavid du Colombier 	(SP(2,1)|(16<<21)|((x)<<3)|((y)<<0))
757219b2ee8SDavid du Colombier #define	FPD(x,y)\
758219b2ee8SDavid du Colombier 	(SP(2,1)|(17<<21)|((x)<<3)|((y)<<0))
759219b2ee8SDavid du Colombier #define	FPW(x,y)\
760219b2ee8SDavid du Colombier 	(SP(2,1)|(20<<21)|((x)<<3)|((y)<<0))
761219b2ee8SDavid du Colombier 
762dc5a79c1SDavid du Colombier int vshift(int);
763dc5a79c1SDavid du Colombier 
7643e12c5d1SDavid du Colombier int
7653e12c5d1SDavid du Colombier asmout(Prog *p, Optab *o, int aflag)
7663e12c5d1SDavid du Colombier {
7677dd7cddfSDavid du Colombier 	long o1, o2, o3, o4, o5, o6, o7, v;
7683e12c5d1SDavid du Colombier 	Prog *ct;
7693e12c5d1SDavid du Colombier 	int r, a;
7703e12c5d1SDavid du Colombier 
7713e12c5d1SDavid du Colombier 	o1 = 0;
7723e12c5d1SDavid du Colombier 	o2 = 0;
7733e12c5d1SDavid du Colombier 	o3 = 0;
7743e12c5d1SDavid du Colombier 	o4 = 0;
775219b2ee8SDavid du Colombier 	o5 = 0;
7767dd7cddfSDavid du Colombier 	o6 = 0;
7777dd7cddfSDavid du Colombier 	o7 = 0;
7783e12c5d1SDavid du Colombier 	switch(o->type) {
7793e12c5d1SDavid du Colombier 	default:
7806b6b9ac8SDavid du Colombier 		diag("unknown type %d", o->type);
7813e12c5d1SDavid du Colombier 		if(!debug['a'])
7823e12c5d1SDavid du Colombier 			prasm(p);
7833e12c5d1SDavid du Colombier 		break;
7843e12c5d1SDavid du Colombier 
7853e12c5d1SDavid du Colombier 	case 0:		/* pseudo ops */
7863e12c5d1SDavid du Colombier 		if(aflag) {
7873e12c5d1SDavid du Colombier 			if(p->link) {
7883e12c5d1SDavid du Colombier 				if(p->as == ATEXT) {
7893e12c5d1SDavid du Colombier 					ct = curtext;
7903e12c5d1SDavid du Colombier 					o2 = autosize;
7913e12c5d1SDavid du Colombier 					curtext = p;
7923e12c5d1SDavid du Colombier 					autosize = p->to.offset + 4;
7933e12c5d1SDavid du Colombier 					o1 = asmout(p->link, oplook(p->link), aflag);
7943e12c5d1SDavid du Colombier 					curtext = ct;
7953e12c5d1SDavid du Colombier 					autosize = o2;
7963e12c5d1SDavid du Colombier 				} else
7973e12c5d1SDavid du Colombier 					o1 = asmout(p->link, oplook(p->link), aflag);
7983e12c5d1SDavid du Colombier 			}
7993e12c5d1SDavid du Colombier 			return o1;
8003e12c5d1SDavid du Colombier 		}
8013e12c5d1SDavid du Colombier 		break;
8023e12c5d1SDavid du Colombier 
803219b2ee8SDavid du Colombier 	case 1:		/* mov[v] r1,r2 ==> OR r1,r0,r2 */
8043e12c5d1SDavid du Colombier 		o1 = OP_RRR(oprrr(AOR), p->from.reg, REGZERO, p->to.reg);
8053e12c5d1SDavid du Colombier 		break;
8063e12c5d1SDavid du Colombier 
8073e12c5d1SDavid du Colombier 	case 2:		/* add/sub r1,[r2],r3 */
8083e12c5d1SDavid du Colombier 		r = p->reg;
8093e12c5d1SDavid du Colombier 		if(r == NREG)
8103e12c5d1SDavid du Colombier 			r = p->to.reg;
8113e12c5d1SDavid du Colombier 		o1 = OP_RRR(oprrr(p->as), p->from.reg, r, p->to.reg);
8123e12c5d1SDavid du Colombier 		break;
8133e12c5d1SDavid du Colombier 
8143e12c5d1SDavid du Colombier 	case 3:		/* mov $soreg, r ==> or/add $i,o,r */
8153e12c5d1SDavid du Colombier 		v = regoff(&p->from);
8163e12c5d1SDavid du Colombier 		r = p->from.reg;
8173e12c5d1SDavid du Colombier 		if(r == NREG)
8183e12c5d1SDavid du Colombier 			r = o->param;
819219b2ee8SDavid du Colombier 		a = AADDU;
8203e12c5d1SDavid du Colombier 		if(o->a1 == C_ANDCON)
8213e12c5d1SDavid du Colombier 			a = AOR;
8223e12c5d1SDavid du Colombier 		o1 = OP_IRR(opirr(a), v, r, p->to.reg);
8233e12c5d1SDavid du Colombier 		break;
8243e12c5d1SDavid du Colombier 
8253e12c5d1SDavid du Colombier 	case 4:		/* add $scon,[r1],r2 */
8263e12c5d1SDavid du Colombier 		v = regoff(&p->from);
8273e12c5d1SDavid du Colombier 		r = p->reg;
8283e12c5d1SDavid du Colombier 		if(r == NREG)
8293e12c5d1SDavid du Colombier 			r = p->to.reg;
8303e12c5d1SDavid du Colombier 		o1 = OP_IRR(opirr(p->as), v, r, p->to.reg);
8313e12c5d1SDavid du Colombier 		break;
8323e12c5d1SDavid du Colombier 
8333e12c5d1SDavid du Colombier 	case 5:		/* syscall */
8343e12c5d1SDavid du Colombier 		if(aflag)
8353e12c5d1SDavid du Colombier 			return 0;
8363e12c5d1SDavid du Colombier 		o1 = oprrr(p->as);
8373e12c5d1SDavid du Colombier 		break;
8383e12c5d1SDavid du Colombier 
8393e12c5d1SDavid du Colombier 	case 6:		/* beq r1,[r2],sbra */
8403e12c5d1SDavid du Colombier 		if(aflag)
8413e12c5d1SDavid du Colombier 			return 0;
8423e12c5d1SDavid du Colombier 		if(p->cond == P)
8433e12c5d1SDavid du Colombier 			v = -4 >> 2;
8443e12c5d1SDavid du Colombier 		else
8453e12c5d1SDavid du Colombier 			v = (p->cond->pc - pc-4) >> 2;
8467dd7cddfSDavid du Colombier 		if(((v << 16) >> 16) != v)
847406758d9SDavid du Colombier 			diag("short branch too far: %ld\n%P", v, p);
8483e12c5d1SDavid du Colombier 		o1 = OP_IRR(opirr(p->as), v, p->from.reg, p->reg);
8493e12c5d1SDavid du Colombier 		break;
8503e12c5d1SDavid du Colombier 
8513e12c5d1SDavid du Colombier 	case 7:		/* mov r, soreg ==> sw o(r) */
8523e12c5d1SDavid du Colombier 		r = p->to.reg;
8533e12c5d1SDavid du Colombier 		if(r == NREG)
8543e12c5d1SDavid du Colombier 			r = o->param;
8553e12c5d1SDavid du Colombier 		v = regoff(&p->to);
8563e12c5d1SDavid du Colombier 		o1 = OP_IRR(opirr(p->as), v, r, p->from.reg);
8573e12c5d1SDavid du Colombier 		break;
8583e12c5d1SDavid du Colombier 
8593e12c5d1SDavid du Colombier 	case 8:		/* mov soreg, r ==> lw o(r) */
8603e12c5d1SDavid du Colombier 		r = p->from.reg;
8613e12c5d1SDavid du Colombier 		if(r == NREG)
8623e12c5d1SDavid du Colombier 			r = o->param;
8633e12c5d1SDavid du Colombier 		v = regoff(&p->from);
864219b2ee8SDavid du Colombier 		o1 = OP_IRR(opirr(p->as+ALAST), v, r, p->to.reg);
8653e12c5d1SDavid du Colombier 		break;
8663e12c5d1SDavid du Colombier 
8673e12c5d1SDavid du Colombier 	case 9:		/* asl r1,[r2],r3 */
8683e12c5d1SDavid du Colombier 		r = p->reg;
8693e12c5d1SDavid du Colombier 		if(r == NREG)
8703e12c5d1SDavid du Colombier 			r = p->to.reg;
8713e12c5d1SDavid du Colombier 		o1 = OP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg);
8723e12c5d1SDavid du Colombier 		break;
8733e12c5d1SDavid du Colombier 
8743e12c5d1SDavid du Colombier 	case 10:	/* add $con,[r1],r2 ==> mov $con,t; add t,[r1],r2 */
8753e12c5d1SDavid du Colombier 		v = regoff(&p->from);
8763e12c5d1SDavid du Colombier 		r = AOR;
8773e12c5d1SDavid du Colombier 		if(v < 0)
878219b2ee8SDavid du Colombier 			r = AADDU;
8793e12c5d1SDavid du Colombier 		o1 = OP_IRR(opirr(r), v, 0, REGTMP);
8803e12c5d1SDavid du Colombier 		r = p->reg;
8813e12c5d1SDavid du Colombier 		if(r == NREG)
8823e12c5d1SDavid du Colombier 			r = p->to.reg;
8833e12c5d1SDavid du Colombier 		o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
8843e12c5d1SDavid du Colombier 		break;
8853e12c5d1SDavid du Colombier 
8863e12c5d1SDavid du Colombier 	case 11:	/* jmp lbra */
8873e12c5d1SDavid du Colombier 		if(aflag)
8883e12c5d1SDavid du Colombier 			return 0;
8893e12c5d1SDavid du Colombier 		if(p->cond == P)
8903e12c5d1SDavid du Colombier 			v = p->pc >> 2;
8913e12c5d1SDavid du Colombier 		else
8923e12c5d1SDavid du Colombier 			v = p->cond->pc >> 2;
8933e12c5d1SDavid du Colombier 		o1 = OP_JMP(opirr(p->as), v);
894219b2ee8SDavid du Colombier 		if(!debug['Y'] && p->link && p->cond && isnop(p->link)) {
895219b2ee8SDavid du Colombier 			nop.branch.count--;
896219b2ee8SDavid du Colombier 			nop.branch.outof--;
897219b2ee8SDavid du Colombier 			nop.jump.outof++;
8983e12c5d1SDavid du Colombier 			o2 = asmout(p->cond, oplook(p->cond), 1);
8993e12c5d1SDavid du Colombier 			if(o2) {
9003e12c5d1SDavid du Colombier 				o1 += 1;
9013e12c5d1SDavid du Colombier 				if(debug['a'])
902a587111cSDavid du Colombier 					Bprint(&bso, " %.8llux: %.8lux %.8lux%P\n",
903219b2ee8SDavid du Colombier 						p->pc, o1, o2, p);
9043e12c5d1SDavid du Colombier 				LPUT(o1);
9053e12c5d1SDavid du Colombier 				LPUT(o2);
9063e12c5d1SDavid du Colombier 				return 1;
9073e12c5d1SDavid du Colombier 			}
9083e12c5d1SDavid du Colombier 		}
9093e12c5d1SDavid du Colombier 		break;
9103e12c5d1SDavid du Colombier 
9113e12c5d1SDavid du Colombier 	case 12:	/* movbs r,r */
9123e12c5d1SDavid du Colombier 		v = 16;
9133e12c5d1SDavid du Colombier 		if(p->as == AMOVB)
9143e12c5d1SDavid du Colombier 			v = 24;
9153e12c5d1SDavid du Colombier 		o1 = OP_SRR(opirr(ASLL), v, p->from.reg, p->to.reg);
9163e12c5d1SDavid du Colombier 		o2 = OP_SRR(opirr(ASRA), v, p->to.reg, p->to.reg);
9173e12c5d1SDavid du Colombier 		break;
9183e12c5d1SDavid du Colombier 
9193e12c5d1SDavid du Colombier 	case 13:	/* movbu r,r */
9203e12c5d1SDavid du Colombier 		if(p->as == AMOVBU)
9213e12c5d1SDavid du Colombier 			o1 = OP_IRR(opirr(AAND), 0xffL, p->from.reg, p->to.reg);
9223e12c5d1SDavid du Colombier 		else
9233e12c5d1SDavid du Colombier 			o1 = OP_IRR(opirr(AAND), 0xffffL, p->from.reg, p->to.reg);
9243e12c5d1SDavid du Colombier 		break;
9253e12c5d1SDavid du Colombier 
9263e12c5d1SDavid du Colombier 	case 16:	/* sll $c,[r1],r2 */
9273e12c5d1SDavid du Colombier 		v = regoff(&p->from);
9283e12c5d1SDavid du Colombier 		r = p->reg;
9293e12c5d1SDavid du Colombier 		if(r == NREG)
9303e12c5d1SDavid du Colombier 			r = p->to.reg;
931dc5a79c1SDavid du Colombier 
932dc5a79c1SDavid du Colombier 		/* OP_SRR will use only the low 5 bits of the shift value */
933dc5a79c1SDavid du Colombier 		if(v >= 32 && vshift(p->as))
934219b2ee8SDavid du Colombier 			o1 = OP_SRR(opirr(p->as+ALAST), v-32, r, p->to.reg);
935219b2ee8SDavid du Colombier 		else
9363e12c5d1SDavid du Colombier 			o1 = OP_SRR(opirr(p->as), v, r, p->to.reg);
9373e12c5d1SDavid du Colombier 		break;
9383e12c5d1SDavid du Colombier 
9393e12c5d1SDavid du Colombier 	case 18:	/* jmp [r1],0(r2) */
9403e12c5d1SDavid du Colombier 		if(aflag)
9413e12c5d1SDavid du Colombier 			return 0;
9423e12c5d1SDavid du Colombier 		r = p->reg;
9433e12c5d1SDavid du Colombier 		if(r == NREG)
9443e12c5d1SDavid du Colombier 			r = o->param;
9453e12c5d1SDavid du Colombier 		o1 = OP_RRR(oprrr(p->as), 0, p->to.reg, r);
9463e12c5d1SDavid du Colombier 		break;
9473e12c5d1SDavid du Colombier 
9483e12c5d1SDavid du Colombier 	case 19:	/* mov $lcon,r ==> lu+or */
9493e12c5d1SDavid du Colombier 		v = regoff(&p->from);
950219b2ee8SDavid du Colombier 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
9513e12c5d1SDavid du Colombier 		o2 = OP_IRR(opirr(AOR), v, p->to.reg, p->to.reg);
9523e12c5d1SDavid du Colombier 		break;
9533e12c5d1SDavid du Colombier 
954219b2ee8SDavid du Colombier 	case 20:	/* mov lohi,r */
955219b2ee8SDavid du Colombier 		r = OP(2,0);		/* mfhi */
9563e12c5d1SDavid du Colombier 		if(p->from.type == D_LO)
957219b2ee8SDavid du Colombier 			r = OP(2,2);	/* mflo */
958219b2ee8SDavid du Colombier 		o1 = OP_RRR(r, REGZERO, REGZERO, p->to.reg);
9593e12c5d1SDavid du Colombier 		break;
9603e12c5d1SDavid du Colombier 
961219b2ee8SDavid du Colombier 	case 21:	/* mov r,lohi */
962219b2ee8SDavid du Colombier 		r = OP(2,1);		/* mthi */
9633e12c5d1SDavid du Colombier 		if(p->to.type == D_LO)
964219b2ee8SDavid du Colombier 			r = OP(2,3);	/* mtlo */
965219b2ee8SDavid du Colombier 		o1 = OP_RRR(r, REGZERO, p->from.reg, REGZERO);
9663e12c5d1SDavid du Colombier 		break;
9673e12c5d1SDavid du Colombier 
9683e12c5d1SDavid du Colombier 	case 22:	/* mul r1,r2 */
9693e12c5d1SDavid du Colombier 		o1 = OP_RRR(oprrr(p->as), p->from.reg, p->reg, REGZERO);
9703e12c5d1SDavid du Colombier 		break;
9713e12c5d1SDavid du Colombier 
9723e12c5d1SDavid du Colombier 	case 23:	/* add $lcon,r1,r2 ==> lu+or+add */
9733e12c5d1SDavid du Colombier 		v = regoff(&p->from);
9743e12c5d1SDavid du Colombier 		if(p->to.reg == REGTMP || p->reg == REGTMP)
9756b6b9ac8SDavid du Colombier 			diag("cant synthesize large constant\n%P", p);
976219b2ee8SDavid du Colombier 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
9773e12c5d1SDavid du Colombier 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
9783e12c5d1SDavid du Colombier 		r = p->reg;
9793e12c5d1SDavid du Colombier 		if(r == NREG)
9803e12c5d1SDavid du Colombier 			r = p->to.reg;
9813e12c5d1SDavid du Colombier 		o3 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
9823e12c5d1SDavid du Colombier 		break;
9833e12c5d1SDavid du Colombier 
9843e12c5d1SDavid du Colombier 	case 24:	/* mov $ucon,,r ==> lu r */
9853e12c5d1SDavid du Colombier 		v = regoff(&p->from);
986219b2ee8SDavid du Colombier 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
9873e12c5d1SDavid du Colombier 		break;
9883e12c5d1SDavid du Colombier 
9893e12c5d1SDavid du Colombier 	case 25:	/* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
9903e12c5d1SDavid du Colombier 		v = regoff(&p->from);
991219b2ee8SDavid du Colombier 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
9923e12c5d1SDavid du Colombier 		r = p->reg;
9933e12c5d1SDavid du Colombier 		if(r == NREG)
9943e12c5d1SDavid du Colombier 			r = p->to.reg;
9953e12c5d1SDavid du Colombier 		o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
9963e12c5d1SDavid du Colombier 		break;
9973e12c5d1SDavid du Colombier 
9983e12c5d1SDavid du Colombier 	case 26:	/* mov $lsext/auto/oreg,,r2 ==> lu+or+add */
9993e12c5d1SDavid du Colombier 		v = regoff(&p->from);
10003e12c5d1SDavid du Colombier 		if(p->to.reg == REGTMP)
10016b6b9ac8SDavid du Colombier 			diag("cant synthesize large constant\n%P", p);
1002219b2ee8SDavid du Colombier 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
10033e12c5d1SDavid du Colombier 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
10043e12c5d1SDavid du Colombier 		r = p->from.reg;
10053e12c5d1SDavid du Colombier 		if(r == NREG)
10063e12c5d1SDavid du Colombier 			r = o->param;
1007219b2ee8SDavid du Colombier 		o3 = OP_RRR(oprrr(AADDU), REGTMP, r, p->to.reg);
10083e12c5d1SDavid du Colombier 		break;
10093e12c5d1SDavid du Colombier 
10103e12c5d1SDavid du Colombier 	case 27:		/* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
10113e12c5d1SDavid du Colombier 		r = p->from.reg;
10123e12c5d1SDavid du Colombier 		if(r == NREG)
10133e12c5d1SDavid du Colombier 			r = o->param;
10143e12c5d1SDavid du Colombier 		v = regoff(&p->from);
10153e12c5d1SDavid du Colombier 		switch(o->size) {
1016219b2ee8SDavid du Colombier 		case 20:
1017219b2ee8SDavid du Colombier 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1018219b2ee8SDavid du Colombier 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1019219b2ee8SDavid du Colombier 			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1020219b2ee8SDavid du Colombier 			o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg+1);
1021219b2ee8SDavid du Colombier 			o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg);
10223e12c5d1SDavid du Colombier 			break;
1023219b2ee8SDavid du Colombier 		case 16:
1024219b2ee8SDavid du Colombier 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1025219b2ee8SDavid du Colombier 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1026219b2ee8SDavid du Colombier 			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1027219b2ee8SDavid du Colombier 			o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg);
10283e12c5d1SDavid du Colombier 			break;
10293e12c5d1SDavid du Colombier 		case 8:
1030219b2ee8SDavid du Colombier 			o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg+1);
1031219b2ee8SDavid du Colombier 			o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg);
10323e12c5d1SDavid du Colombier 			break;
10333e12c5d1SDavid du Colombier 		case 4:
1034219b2ee8SDavid du Colombier 			o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg);
10353e12c5d1SDavid du Colombier 			break;
10363e12c5d1SDavid du Colombier 		}
10373e12c5d1SDavid du Colombier 		break;
10383e12c5d1SDavid du Colombier 
10393e12c5d1SDavid du Colombier 	case 28:		/* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
10403e12c5d1SDavid du Colombier 		r = p->to.reg;
10413e12c5d1SDavid du Colombier 		if(r == NREG)
10423e12c5d1SDavid du Colombier 			r = o->param;
10433e12c5d1SDavid du Colombier 		v = regoff(&p->to);
10443e12c5d1SDavid du Colombier 		switch(o->size) {
1045219b2ee8SDavid du Colombier 		case 20:
1046219b2ee8SDavid du Colombier 			if(r == REGTMP)
10476b6b9ac8SDavid du Colombier 				diag("cant synthesize large constant\n%P", p);
1048219b2ee8SDavid du Colombier 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1049219b2ee8SDavid du Colombier 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1050219b2ee8SDavid du Colombier 			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1051219b2ee8SDavid du Colombier 			o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg+1);
1052219b2ee8SDavid du Colombier 			o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg);
10533e12c5d1SDavid du Colombier 			break;
1054219b2ee8SDavid du Colombier 		case 16:
1055219b2ee8SDavid du Colombier 			if(r == REGTMP)
10566b6b9ac8SDavid du Colombier 				diag("cant synthesize large constant\n%P", p);
1057219b2ee8SDavid du Colombier 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1058219b2ee8SDavid du Colombier 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1059219b2ee8SDavid du Colombier 			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1060219b2ee8SDavid du Colombier 			o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg);
10613e12c5d1SDavid du Colombier 			break;
10623e12c5d1SDavid du Colombier 		case 8:
10633e12c5d1SDavid du Colombier 			o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg+1);
10643e12c5d1SDavid du Colombier 			o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg);
10653e12c5d1SDavid du Colombier 			break;
10663e12c5d1SDavid du Colombier 		case 4:
10673e12c5d1SDavid du Colombier 			o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg);
10683e12c5d1SDavid du Colombier 			break;
10693e12c5d1SDavid du Colombier 		}
10703e12c5d1SDavid du Colombier 		break;
10713e12c5d1SDavid du Colombier 
10723e12c5d1SDavid du Colombier 	case 30:	/* movw r,fr */
1073219b2ee8SDavid du Colombier 		r = SP(2,1)|(4<<21);		/* mtc1 */
1074219b2ee8SDavid du Colombier 		o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
10753e12c5d1SDavid du Colombier 		break;
10763e12c5d1SDavid du Colombier 
10773e12c5d1SDavid du Colombier 	case 31:	/* movw fr,r */
1078219b2ee8SDavid du Colombier 		r = SP(2,1)|(0<<21);		/* mfc1 */
1079219b2ee8SDavid du Colombier 		o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
10803e12c5d1SDavid du Colombier 		break;
10813e12c5d1SDavid du Colombier 
10823e12c5d1SDavid du Colombier 	case 32:	/* fadd fr1,[fr2],fr3 */
10833e12c5d1SDavid du Colombier 		r = p->reg;
10843e12c5d1SDavid du Colombier 		if(r == NREG)
10853e12c5d1SDavid du Colombier 			o1 = OP_FRRR(oprrr(p->as), p->from.reg, p->to.reg, p->to.reg);
10863e12c5d1SDavid du Colombier 		else
10873e12c5d1SDavid du Colombier 			o1 = OP_FRRR(oprrr(p->as), p->from.reg, r, p->to.reg);
10883e12c5d1SDavid du Colombier 		break;
10893e12c5d1SDavid du Colombier 
10903e12c5d1SDavid du Colombier 	case 33:	/* fabs fr1,fr3 */
10913e12c5d1SDavid du Colombier 		o1 = OP_FRRR(oprrr(p->as), 0, p->from.reg, p->to.reg);
10923e12c5d1SDavid du Colombier 		break;
10933e12c5d1SDavid du Colombier 
10943e12c5d1SDavid du Colombier 	case 34:	/* mov $con,fr ==> or/add $i,r,r2 */
10953e12c5d1SDavid du Colombier 		v = regoff(&p->from);
1096219b2ee8SDavid du Colombier 		r = AADDU;
10973e12c5d1SDavid du Colombier 		if(o->a1 == C_ANDCON)
10983e12c5d1SDavid du Colombier 			r = AOR;
10993e12c5d1SDavid du Colombier 		o1 = OP_IRR(opirr(r), v, 0, REGTMP);
1100219b2ee8SDavid du Colombier 		o2 = OP_RRR(SP(2,1)|(4<<21), REGTMP, 0, p->to.reg);	/* mtc1 */
11013e12c5d1SDavid du Colombier 		break;
11023e12c5d1SDavid du Colombier 
11033e12c5d1SDavid du Colombier 	case 35:	/* mov r,lext/luto/oreg ==> sw o(r) */
1104219b2ee8SDavid du Colombier 		/*
1105219b2ee8SDavid du Colombier 		 * the lowbits of the constant cannot
1106219b2ee8SDavid du Colombier 		 * be moved into the offset of the load
1107219b2ee8SDavid du Colombier 		 * because the mips 4000 in 64-bit mode
1108219b2ee8SDavid du Colombier 		 * does a 64-bit add and it will screw up.
1109219b2ee8SDavid du Colombier 		 */
11103e12c5d1SDavid du Colombier 		v = regoff(&p->to);
11113e12c5d1SDavid du Colombier 		r = p->to.reg;
11123e12c5d1SDavid du Colombier 		if(r == NREG)
11133e12c5d1SDavid du Colombier 			r = o->param;
1114219b2ee8SDavid du Colombier 		if(r == REGTMP)
11156b6b9ac8SDavid du Colombier 			diag("cant synthesize large constant\n%P", p);
1116219b2ee8SDavid du Colombier 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1117219b2ee8SDavid du Colombier 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1118219b2ee8SDavid du Colombier 		o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1119219b2ee8SDavid du Colombier 		o4 = OP_IRR(opirr(p->as), 0, REGTMP, p->from.reg);
11203e12c5d1SDavid du Colombier 		break;
11213e12c5d1SDavid du Colombier 
11223e12c5d1SDavid du Colombier 	case 36:	/* mov lext/lauto/lreg,r ==> lw o(r30) */
11233e12c5d1SDavid du Colombier 		v = regoff(&p->from);
11243e12c5d1SDavid du Colombier 		r = p->from.reg;
11253e12c5d1SDavid du Colombier 		if(r == NREG)
11263e12c5d1SDavid du Colombier 			r = o->param;
1127219b2ee8SDavid du Colombier 		if(r == REGTMP)
11286b6b9ac8SDavid du Colombier 			diag("cant synthesize large constant\n%P", p);
1129219b2ee8SDavid du Colombier 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1130219b2ee8SDavid du Colombier 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1131219b2ee8SDavid du Colombier 		o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1132219b2ee8SDavid du Colombier 		o4 = OP_IRR(opirr(p->as+ALAST), 0, REGTMP, p->to.reg);
11333e12c5d1SDavid du Colombier 		break;
11343e12c5d1SDavid du Colombier 
11353e12c5d1SDavid du Colombier 	case 37:	/* movw r,mr */
1136219b2ee8SDavid du Colombier 		r = SP(2,0)|(4<<21);		/* mtc0 */
1137219b2ee8SDavid du Colombier 		if(p->as == AMOVV)
1138219b2ee8SDavid du Colombier 			r = SP(2,0)|(5<<21);	/* dmtc0 */
1139219b2ee8SDavid du Colombier 		o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
11403e12c5d1SDavid du Colombier 		break;
11413e12c5d1SDavid du Colombier 
11423e12c5d1SDavid du Colombier 	case 38:	/* movw mr,r */
1143219b2ee8SDavid du Colombier 		r = SP(2,0)|(0<<21);		/* mfc0 */
1144219b2ee8SDavid du Colombier 		if(p->as == AMOVV)
1145219b2ee8SDavid du Colombier 			r = SP(2,0)|(1<<21);	/* dmfc0 */
1146219b2ee8SDavid du Colombier 		o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
11473e12c5d1SDavid du Colombier 		break;
11483e12c5d1SDavid du Colombier 
11493e12c5d1SDavid du Colombier 	case 39:	/* rfe ==> jmp+rfe */
11503e12c5d1SDavid du Colombier 		if(aflag)
11513e12c5d1SDavid du Colombier 			return 0;
11523e12c5d1SDavid du Colombier 		o1 = OP_RRR(oprrr(AJMP), 0, p->to.reg, REGZERO);
11533e12c5d1SDavid du Colombier 		o2 = oprrr(p->as);
11543e12c5d1SDavid du Colombier 		break;
11553e12c5d1SDavid du Colombier 
11563e12c5d1SDavid du Colombier 	case 40:	/* word */
11573e12c5d1SDavid du Colombier 		if(aflag)
11583e12c5d1SDavid du Colombier 			return 0;
11593e12c5d1SDavid du Colombier 		o1 = regoff(&p->to);
11603e12c5d1SDavid du Colombier 		break;
11613e12c5d1SDavid du Colombier 
11623e12c5d1SDavid du Colombier 	case 41:	/* movw r,fcr */
1163219b2ee8SDavid du Colombier 		o1 = OP_RRR(SP(2,1)|(2<<21), REGZERO, 0, p->to.reg); 	/* mfcc1 */
1164219b2ee8SDavid du Colombier 		o2 = OP_RRR(SP(2,1)|(6<<21), p->from.reg, 0, p->to.reg);/* mtcc1 */
11653e12c5d1SDavid du Colombier 		break;
11663e12c5d1SDavid du Colombier 
11673e12c5d1SDavid du Colombier 	case 42:	/* movw fcr,r */
1168219b2ee8SDavid du Colombier 		o1 = OP_RRR(SP(2,1)|(2<<21), p->to.reg, 0, p->from.reg);/* mfcc1 */
11693e12c5d1SDavid du Colombier 		break;
11707dd7cddfSDavid du Colombier 
11717dd7cddfSDavid du Colombier 	case 45:	/* case r */
11727dd7cddfSDavid du Colombier 		if(p->link == P)
11737dd7cddfSDavid du Colombier 			v = p->pc+28;
11747dd7cddfSDavid du Colombier 		else
11757dd7cddfSDavid du Colombier 			v = p->link->pc;
11767dd7cddfSDavid du Colombier 		if(v & (1<<15))
11777dd7cddfSDavid du Colombier 			o1 = OP_IRR(opirr(ALAST), (v>>16)+1, REGZERO, REGTMP);
11787dd7cddfSDavid du Colombier 		else
11797dd7cddfSDavid du Colombier 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
11807dd7cddfSDavid du Colombier 		o2 = OP_SRR(opirr(ASLL), 2, p->from.reg, p->from.reg);
11817dd7cddfSDavid du Colombier 		o3 = OP_RRR(oprrr(AADD), p->from.reg, REGTMP, REGTMP);
11827dd7cddfSDavid du Colombier 		o4 = OP_IRR(opirr(AMOVW+ALAST), v, REGTMP, REGTMP);
11837dd7cddfSDavid du Colombier 		o5 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
11847dd7cddfSDavid du Colombier 		o6 = OP_RRR(oprrr(AJMP), 0, REGTMP, REGZERO);
11857dd7cddfSDavid du Colombier 		o7 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
11867dd7cddfSDavid du Colombier 		break;
11877dd7cddfSDavid du Colombier 
11887dd7cddfSDavid du Colombier 	case 46:	/* bcase $con,lbra */
11897dd7cddfSDavid du Colombier 		if(p->cond == P)
11907dd7cddfSDavid du Colombier 			v = p->pc;
11917dd7cddfSDavid du Colombier 		else
11927dd7cddfSDavid du Colombier 			v = p->cond->pc;
11937dd7cddfSDavid du Colombier 		o1 = v;
11947dd7cddfSDavid du Colombier 		break;
11953e12c5d1SDavid du Colombier 	}
11963e12c5d1SDavid du Colombier 	if(aflag)
11973e12c5d1SDavid du Colombier 		return o1;
11983e12c5d1SDavid du Colombier 	v = p->pc;
11993e12c5d1SDavid du Colombier 	switch(o->size) {
12003e12c5d1SDavid du Colombier 	default:
12013e12c5d1SDavid du Colombier 		if(debug['a'])
12023e12c5d1SDavid du Colombier 			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
12033e12c5d1SDavid du Colombier 		break;
12043e12c5d1SDavid du Colombier 	case 4:
12053e12c5d1SDavid du Colombier 		if(debug['a'])
12063e12c5d1SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
12073e12c5d1SDavid du Colombier 		LPUT(o1);
12083e12c5d1SDavid du Colombier 		break;
12093e12c5d1SDavid du Colombier 	case 8:
12103e12c5d1SDavid du Colombier 		if(debug['a'])
12113e12c5d1SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
12123e12c5d1SDavid du Colombier 		LPUT(o1);
12133e12c5d1SDavid du Colombier 		LPUT(o2);
12143e12c5d1SDavid du Colombier 		break;
12153e12c5d1SDavid du Colombier 	case 12:
12163e12c5d1SDavid du Colombier 		if(debug['a'])
12173e12c5d1SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
12183e12c5d1SDavid du Colombier 		LPUT(o1);
12193e12c5d1SDavid du Colombier 		LPUT(o2);
12203e12c5d1SDavid du Colombier 		LPUT(o3);
12213e12c5d1SDavid du Colombier 		break;
12223e12c5d1SDavid du Colombier 	case 16:
12233e12c5d1SDavid du Colombier 		if(debug['a'])
12243e12c5d1SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
12253e12c5d1SDavid du Colombier 				v, o1, o2, o3, o4, p);
12263e12c5d1SDavid du Colombier 		LPUT(o1);
12273e12c5d1SDavid du Colombier 		LPUT(o2);
12283e12c5d1SDavid du Colombier 		LPUT(o3);
12293e12c5d1SDavid du Colombier 		LPUT(o4);
12303e12c5d1SDavid du Colombier 		break;
1231219b2ee8SDavid du Colombier 	case 20:
1232219b2ee8SDavid du Colombier 		if(debug['a'])
1233219b2ee8SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1234219b2ee8SDavid du Colombier 				v, o1, o2, o3, o4, o5, p);
1235219b2ee8SDavid du Colombier 		LPUT(o1);
1236219b2ee8SDavid du Colombier 		LPUT(o2);
1237219b2ee8SDavid du Colombier 		LPUT(o3);
1238219b2ee8SDavid du Colombier 		LPUT(o4);
1239219b2ee8SDavid du Colombier 		LPUT(o5);
1240219b2ee8SDavid du Colombier 		break;
12417dd7cddfSDavid du Colombier 
12427dd7cddfSDavid du Colombier 	case 28:
12437dd7cddfSDavid du Colombier 		if(debug['a'])
12447dd7cddfSDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
12457dd7cddfSDavid du Colombier 				v, o1, o2, o3, o4, o5, o6, o7, p);
12467dd7cddfSDavid du Colombier 		LPUT(o1);
12477dd7cddfSDavid du Colombier 		LPUT(o2);
12487dd7cddfSDavid du Colombier 		LPUT(o3);
12497dd7cddfSDavid du Colombier 		LPUT(o4);
12507dd7cddfSDavid du Colombier 		LPUT(o5);
12517dd7cddfSDavid du Colombier 		LPUT(o6);
12527dd7cddfSDavid du Colombier 		LPUT(o7);
12537dd7cddfSDavid du Colombier 		break;
12543e12c5d1SDavid du Colombier 	}
12553e12c5d1SDavid du Colombier 	return 0;
12563e12c5d1SDavid du Colombier }
12573e12c5d1SDavid du Colombier 
1258219b2ee8SDavid du Colombier int
1259219b2ee8SDavid du Colombier isnop(Prog *p)
1260219b2ee8SDavid du Colombier {
1261219b2ee8SDavid du Colombier 	if(p->as != ANOR)
1262219b2ee8SDavid du Colombier 		return 0;
1263219b2ee8SDavid du Colombier 	if(p->reg != REGZERO && p->reg != NREG)
1264219b2ee8SDavid du Colombier 		return 0;
1265219b2ee8SDavid du Colombier 	if(p->from.type != D_REG || p->from.reg != REGZERO)
1266219b2ee8SDavid du Colombier 		return 0;
1267219b2ee8SDavid du Colombier 	if(p->to.type != D_REG || p->to.reg != REGZERO)
1268219b2ee8SDavid du Colombier 		return 0;
1269219b2ee8SDavid du Colombier 	return 1;
1270219b2ee8SDavid du Colombier }
12713e12c5d1SDavid du Colombier 
12723e12c5d1SDavid du Colombier long
12733e12c5d1SDavid du Colombier oprrr(int a)
12743e12c5d1SDavid du Colombier {
12753e12c5d1SDavid du Colombier 	switch(a) {
12763e12c5d1SDavid du Colombier 	case AADD:	return OP(4,0);
12773e12c5d1SDavid du Colombier 	case AADDU:	return OP(4,1);
12783e12c5d1SDavid du Colombier 	case ASGT:	return OP(5,2);
12793e12c5d1SDavid du Colombier 	case ASGTU:	return OP(5,3);
12803e12c5d1SDavid du Colombier 	case AAND:	return OP(4,4);
12813e12c5d1SDavid du Colombier 	case AOR:	return OP(4,5);
12823e12c5d1SDavid du Colombier 	case AXOR:	return OP(4,6);
12833e12c5d1SDavid du Colombier 	case ASUB:	return OP(4,2);
12843e12c5d1SDavid du Colombier 	case ASUBU:	return OP(4,3);
12853e12c5d1SDavid du Colombier 	case ANOR:	return OP(4,7);
12863e12c5d1SDavid du Colombier 	case ASLL:	return OP(0,4);
12873e12c5d1SDavid du Colombier 	case ASRL:	return OP(0,6);
12883e12c5d1SDavid du Colombier 	case ASRA:	return OP(0,7);
12893e12c5d1SDavid du Colombier 
12903e12c5d1SDavid du Colombier 	case AREM:
12913e12c5d1SDavid du Colombier 	case ADIV:	return OP(3,2);
12923e12c5d1SDavid du Colombier 	case AREMU:
12933e12c5d1SDavid du Colombier 	case ADIVU:	return OP(3,3);
12943e12c5d1SDavid du Colombier 	case AMUL:	return OP(3,0);
12953e12c5d1SDavid du Colombier 	case AMULU:	return OP(3,1);
12963e12c5d1SDavid du Colombier 
12973e12c5d1SDavid du Colombier 	case AJMP:	return OP(1,0);
12983e12c5d1SDavid du Colombier 	case AJAL:	return OP(1,1);
12993e12c5d1SDavid du Colombier 
13003e12c5d1SDavid du Colombier 	case ABREAK:	return OP(1,5);
13013e12c5d1SDavid du Colombier 	case ASYSCALL:	return OP(1,4);
13023e12c5d1SDavid du Colombier 	case ATLBP:	return MMU(1,0);
13033e12c5d1SDavid du Colombier 	case ATLBR:	return MMU(0,1);
13043e12c5d1SDavid du Colombier 	case ATLBWI:	return MMU(0,2);
13053e12c5d1SDavid du Colombier 	case ATLBWR:	return MMU(0,6);
13063e12c5d1SDavid du Colombier 	case ARFE:	return MMU(2,0);
13073e12c5d1SDavid du Colombier 
13083e12c5d1SDavid du Colombier 	case ADIVF:	return FPF(0,3);
13093e12c5d1SDavid du Colombier 	case ADIVD:	return FPD(0,3);
13103e12c5d1SDavid du Colombier 	case AMULF:	return FPF(0,2);
13113e12c5d1SDavid du Colombier 	case AMULD:	return FPD(0,2);
13123e12c5d1SDavid du Colombier 	case ASUBF:	return FPF(0,1);
13133e12c5d1SDavid du Colombier 	case ASUBD:	return FPD(0,1);
13143e12c5d1SDavid du Colombier 	case AADDF:	return FPF(0,0);
13153e12c5d1SDavid du Colombier 	case AADDD:	return FPD(0,0);
13163e12c5d1SDavid du Colombier 
13173e12c5d1SDavid du Colombier 	case AMOVFW:	return FPF(4,4);
13183e12c5d1SDavid du Colombier 	case AMOVDW:	return FPD(4,4);
13193e12c5d1SDavid du Colombier 	case AMOVWF:	return FPW(4,0);
13203e12c5d1SDavid du Colombier 	case AMOVDF:	return FPD(4,0);
13213e12c5d1SDavid du Colombier 	case AMOVWD:	return FPW(4,1);
13223e12c5d1SDavid du Colombier 	case AMOVFD:	return FPF(4,1);
13233e12c5d1SDavid du Colombier 	case AABSF:	return FPF(0,5);
13243e12c5d1SDavid du Colombier 	case AABSD:	return FPD(0,5);
13253e12c5d1SDavid du Colombier 	case AMOVF:	return FPF(0,6);
13263e12c5d1SDavid du Colombier 	case AMOVD:	return FPD(0,6);
13273e12c5d1SDavid du Colombier 	case ANEGF:	return FPF(0,7);
13283e12c5d1SDavid du Colombier 	case ANEGD:	return FPD(0,7);
13293e12c5d1SDavid du Colombier 
13303e12c5d1SDavid du Colombier 	case ACMPEQF:	return FPF(6,2);
13313e12c5d1SDavid du Colombier 	case ACMPEQD:	return FPD(6,2);
13323e12c5d1SDavid du Colombier 	case ACMPGTF:	return FPF(7,4);
13333e12c5d1SDavid du Colombier 	case ACMPGTD:	return FPD(7,4);
13343e12c5d1SDavid du Colombier 	case ACMPGEF:	return FPF(7,6);
13353e12c5d1SDavid du Colombier 	case ACMPGED:	return FPD(7,6);
13367dd7cddfSDavid du Colombier 
13377dd7cddfSDavid du Colombier 	case ADIVV:	return OP(3,6);
13387dd7cddfSDavid du Colombier 	case ADIVVU:	return OP(3,7);
13397dd7cddfSDavid du Colombier 	case AADDV:	return OP(5,4);
13407dd7cddfSDavid du Colombier 	case AADDVU:	return OP(5,5);
13413e12c5d1SDavid du Colombier 	}
13426b6b9ac8SDavid du Colombier 	diag("bad rrr %d", a);
13433e12c5d1SDavid du Colombier 	return 0;
13443e12c5d1SDavid du Colombier }
13453e12c5d1SDavid du Colombier 
13463e12c5d1SDavid du Colombier long
13473e12c5d1SDavid du Colombier opirr(int a)
13483e12c5d1SDavid du Colombier {
13493e12c5d1SDavid du Colombier 	switch(a) {
13503e12c5d1SDavid du Colombier 	case AADD:	return SP(1,0);
13513e12c5d1SDavid du Colombier 	case AADDU:	return SP(1,1);
13523e12c5d1SDavid du Colombier 	case ASGT:	return SP(1,2);
13533e12c5d1SDavid du Colombier 	case ASGTU:	return SP(1,3);
13543e12c5d1SDavid du Colombier 	case AAND:	return SP(1,4);
13553e12c5d1SDavid du Colombier 	case AOR:	return SP(1,5);
13563e12c5d1SDavid du Colombier 	case AXOR:	return SP(1,6);
1357219b2ee8SDavid du Colombier 	case ALAST:	return SP(1,7);
13583e12c5d1SDavid du Colombier 	case ASLL:	return OP(0,0);
13593e12c5d1SDavid du Colombier 	case ASRL:	return OP(0,2);
13603e12c5d1SDavid du Colombier 	case ASRA:	return OP(0,3);
13613e12c5d1SDavid du Colombier 
13623e12c5d1SDavid du Colombier 	case AJMP:	return SP(0,2);
13633e12c5d1SDavid du Colombier 	case AJAL:	return SP(0,3);
13643e12c5d1SDavid du Colombier 	case ABEQ:	return SP(0,4);
13653e12c5d1SDavid du Colombier 	case ABNE:	return SP(0,5);
13663e12c5d1SDavid du Colombier 
13673e12c5d1SDavid du Colombier 	case ABGEZ:	return SP(0,1)|BCOND(0,1);
13683e12c5d1SDavid du Colombier 	case ABGEZAL:	return SP(0,1)|BCOND(2,1);
13693e12c5d1SDavid du Colombier 	case ABGTZ:	return SP(0,7);
13703e12c5d1SDavid du Colombier 	case ABLEZ:	return SP(0,6);
13713e12c5d1SDavid du Colombier 	case ABLTZ:	return SP(0,1)|BCOND(0,0);
13723e12c5d1SDavid du Colombier 	case ABLTZAL:	return SP(0,1)|BCOND(2,0);
13733e12c5d1SDavid du Colombier 
13743e12c5d1SDavid du Colombier 	case ABFPT:	return SP(2,1)|(257<<16);
13753e12c5d1SDavid du Colombier 	case ABFPF:	return SP(2,1)|(256<<16);
13763e12c5d1SDavid du Colombier 
13773e12c5d1SDavid du Colombier 	case AMOVB:
13783e12c5d1SDavid du Colombier 	case AMOVBU:	return SP(5,0);
13793e12c5d1SDavid du Colombier 	case AMOVH:
13803e12c5d1SDavid du Colombier 	case AMOVHU:	return SP(5,1);
13813e12c5d1SDavid du Colombier 	case AMOVW:	return SP(5,3);
1382219b2ee8SDavid du Colombier 	case AMOVV:	return SP(7,7);
13833e12c5d1SDavid du Colombier 	case AMOVF:	return SP(7,1);
13843e12c5d1SDavid du Colombier 	case AMOVWL:	return SP(5,2);
13853e12c5d1SDavid du Colombier 	case AMOVWR:	return SP(5,6);
1386219b2ee8SDavid du Colombier 	case AMOVVL:	return SP(5,4);
1387219b2ee8SDavid du Colombier 	case AMOVVR:	return SP(5,5);
13883e12c5d1SDavid du Colombier 
1389bd389b36SDavid du Colombier 	case ABREAK:	return SP(5,7);
1390bd389b36SDavid du Colombier 
1391219b2ee8SDavid du Colombier 	case AMOVWL+ALAST:	return SP(4,2);
1392219b2ee8SDavid du Colombier 	case AMOVWR+ALAST:	return SP(4,6);
1393219b2ee8SDavid du Colombier 	case AMOVVL+ALAST:	return SP(3,2);
1394219b2ee8SDavid du Colombier 	case AMOVVR+ALAST:	return SP(3,3);
1395219b2ee8SDavid du Colombier 	case AMOVB+ALAST:	return SP(4,0);
1396219b2ee8SDavid du Colombier 	case AMOVBU+ALAST:	return SP(4,4);
1397219b2ee8SDavid du Colombier 	case AMOVH+ALAST:	return SP(4,1);
1398219b2ee8SDavid du Colombier 	case AMOVHU+ALAST:	return SP(4,5);
1399219b2ee8SDavid du Colombier 	case AMOVW+ALAST:	return SP(4,3);
1400219b2ee8SDavid du Colombier 	case AMOVV+ALAST:	return SP(6,7);
1401219b2ee8SDavid du Colombier 	case AMOVF+ALAST:	return SP(6,1);
14023e12c5d1SDavid du Colombier 
1403219b2ee8SDavid du Colombier 	case ASLLV:		return OP(7,0);
1404219b2ee8SDavid du Colombier 	case ASRLV:		return OP(7,2);
1405219b2ee8SDavid du Colombier 	case ASRAV:		return OP(7,3);
1406219b2ee8SDavid du Colombier 	case ASLLV+ALAST:	return OP(7,4);
1407219b2ee8SDavid du Colombier 	case ASRLV+ALAST:	return OP(7,6);
1408219b2ee8SDavid du Colombier 	case ASRAV+ALAST:	return OP(7,7);
14097dd7cddfSDavid du Colombier 
14107dd7cddfSDavid du Colombier 	case AADDV:		return SP(3,0);
14117dd7cddfSDavid du Colombier 	case AADDVU:		return SP(3,1);
14123e12c5d1SDavid du Colombier 	}
14136b6b9ac8SDavid du Colombier 	diag("bad irr %d", a);
1414dc5a79c1SDavid du Colombier abort();
1415dc5a79c1SDavid du Colombier 	return 0;
1416dc5a79c1SDavid du Colombier }
1417dc5a79c1SDavid du Colombier 
1418dc5a79c1SDavid du Colombier int
1419dc5a79c1SDavid du Colombier vshift(int a)
1420dc5a79c1SDavid du Colombier {
1421dc5a79c1SDavid du Colombier 	switch(a){
1422dc5a79c1SDavid du Colombier 	case ASLLV:		return 1;
1423dc5a79c1SDavid du Colombier 	case ASRLV:		return 1;
1424dc5a79c1SDavid du Colombier 	case ASRAV:		return 1;
1425dc5a79c1SDavid du Colombier 	}
14263e12c5d1SDavid du Colombier 	return 0;
14273e12c5d1SDavid du Colombier }
1428