xref: /inferno-os/utils/vl/asm.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth #include	"l.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth long	OFFSET;
474a4d8c2SCharles.Forsyth /*
574a4d8c2SCharles.Forsyth long	BADOFFSET	=	-1;
674a4d8c2SCharles.Forsyth 
774a4d8c2SCharles.Forsyth 		if(OFFSET <= BADOFFSET && OFFSET+4 > BADOFFSET)\
874a4d8c2SCharles.Forsyth 			abort();\
974a4d8c2SCharles.Forsyth 		OFFSET += 4;\
1074a4d8c2SCharles.Forsyth 
1174a4d8c2SCharles.Forsyth 		if(OFFSET == BADOFFSET)\
1274a4d8c2SCharles.Forsyth 			abort();\
1374a4d8c2SCharles.Forsyth 		OFFSET++;\
1474a4d8c2SCharles.Forsyth */
1574a4d8c2SCharles.Forsyth 
164206ee1aSforsyth #define LPUT(l) { \
174206ee1aSforsyth 		if (little) { \
184206ee1aSforsyth 			LLEPUT(l); \
194206ee1aSforsyth 		} else { \
204206ee1aSforsyth 			LBEPUT(l); \
214206ee1aSforsyth 		} \
224206ee1aSforsyth 	}
234206ee1aSforsyth 
244206ee1aSforsyth #define	LLEPUT(c)\
254206ee1aSforsyth 	{\
264206ee1aSforsyth 		cbp[0] = (c);\
274206ee1aSforsyth 		cbp[1] = (c)>>8;\
284206ee1aSforsyth 		cbp[2] = (c)>>16;\
294206ee1aSforsyth 		cbp[3] = (c)>>24;\
304206ee1aSforsyth 		cbp += 4;\
314206ee1aSforsyth 		cbc -= 4;\
324206ee1aSforsyth 		if(cbc <= 0)\
334206ee1aSforsyth 			cflush();\
344206ee1aSforsyth 	}
354206ee1aSforsyth 
364206ee1aSforsyth #define	LBEPUT(c)\
3774a4d8c2SCharles.Forsyth 	{\
3874a4d8c2SCharles.Forsyth 		cbp[0] = (c)>>24;\
3974a4d8c2SCharles.Forsyth 		cbp[1] = (c)>>16;\
4074a4d8c2SCharles.Forsyth 		cbp[2] = (c)>>8;\
4174a4d8c2SCharles.Forsyth 		cbp[3] = (c);\
4274a4d8c2SCharles.Forsyth 		cbp += 4;\
4374a4d8c2SCharles.Forsyth 		cbc -= 4;\
4474a4d8c2SCharles.Forsyth 		if(cbc <= 0)\
4574a4d8c2SCharles.Forsyth 			cflush();\
4674a4d8c2SCharles.Forsyth 	}
4774a4d8c2SCharles.Forsyth 
484206ee1aSforsyth #define HPUT(h) { \
494206ee1aSforsyth 		if (little) { \
504206ee1aSforsyth 			HLEPUT(h); \
514206ee1aSforsyth 		} else { \
524206ee1aSforsyth 			HBEPUT(h); \
534206ee1aSforsyth 		} \
544206ee1aSforsyth 	}
554206ee1aSforsyth 
564206ee1aSforsyth #define	HLEPUT(c)\
574206ee1aSforsyth 	{\
584206ee1aSforsyth 		cbp[0] = (c);\
594206ee1aSforsyth 		cbp[1] = (c)>>8;\
604206ee1aSforsyth 		cbp += 2;\
614206ee1aSforsyth 		cbc -= 2;\
624206ee1aSforsyth 		if(cbc <= 0)\
634206ee1aSforsyth 			cflush();\
644206ee1aSforsyth 	}
654206ee1aSforsyth 
664206ee1aSforsyth #define	HBEPUT(c)\
674206ee1aSforsyth 	{\
684206ee1aSforsyth 		cbp[0] = (c)>>8;\
694206ee1aSforsyth 		cbp[1] = (c);\
704206ee1aSforsyth 		cbp += 2;\
714206ee1aSforsyth 		cbc -= 2;\
724206ee1aSforsyth 		if(cbc <= 0)\
734206ee1aSforsyth 			cflush();\
744206ee1aSforsyth 	}
754206ee1aSforsyth 
764206ee1aSforsyth 
7774a4d8c2SCharles.Forsyth #define	CPUT(c)\
7874a4d8c2SCharles.Forsyth 	{\
7974a4d8c2SCharles.Forsyth 		cbp[0] = (c);\
8074a4d8c2SCharles.Forsyth 		cbp++;\
8174a4d8c2SCharles.Forsyth 		cbc--;\
8274a4d8c2SCharles.Forsyth 		if(cbc <= 0)\
8374a4d8c2SCharles.Forsyth 			cflush();\
8474a4d8c2SCharles.Forsyth 	}
8574a4d8c2SCharles.Forsyth 
864206ee1aSforsyth void
cput(long l)87*45a20ab7Sforsyth cput(long l)
88*45a20ab7Sforsyth {
89*45a20ab7Sforsyth 	CPUT(l);
90*45a20ab7Sforsyth }
91*45a20ab7Sforsyth 
92*45a20ab7Sforsyth void
objput(long l)934206ee1aSforsyth objput(long l)	/* emit long in byte order appropriate to object machine */
944206ee1aSforsyth {
954206ee1aSforsyth 	LPUT(l);
964206ee1aSforsyth }
974206ee1aSforsyth 
984206ee1aSforsyth void
objhput(short s)994206ee1aSforsyth objhput(short s)
1004206ee1aSforsyth {
1014206ee1aSforsyth 	HPUT(s);
1024206ee1aSforsyth }
1034206ee1aSforsyth 
1044206ee1aSforsyth void
wput(long l)105*45a20ab7Sforsyth wput(long l)
106*45a20ab7Sforsyth {
107*45a20ab7Sforsyth 
108*45a20ab7Sforsyth 	cbp[0] = l>>8;
109*45a20ab7Sforsyth 	cbp[1] = l;
110*45a20ab7Sforsyth 	cbp += 2;
111*45a20ab7Sforsyth 	cbc -= 2;
112*45a20ab7Sforsyth 	if(cbc <= 0)
113*45a20ab7Sforsyth 		cflush();
114*45a20ab7Sforsyth }
115*45a20ab7Sforsyth 
116*45a20ab7Sforsyth void
wputl(long l)117*45a20ab7Sforsyth wputl(long l)
118*45a20ab7Sforsyth {
119*45a20ab7Sforsyth 
120*45a20ab7Sforsyth 	cbp[0] = l;
121*45a20ab7Sforsyth 	cbp[1] = l>>8;
122*45a20ab7Sforsyth 	cbp += 2;
123*45a20ab7Sforsyth 	cbc -= 2;
124*45a20ab7Sforsyth 	if(cbc <= 0)
125*45a20ab7Sforsyth 		cflush();
126*45a20ab7Sforsyth }
127*45a20ab7Sforsyth 
128*45a20ab7Sforsyth void
lput(long l)1294206ee1aSforsyth lput(long l)		/* emit long in big-endian byte order */
1304206ee1aSforsyth {
1314206ee1aSforsyth 	LBEPUT(l);
1324206ee1aSforsyth }
1334206ee1aSforsyth 
134*45a20ab7Sforsyth void
lputl(long l)135*45a20ab7Sforsyth lputl(long l)		/* emit long in big-endian byte order */
136*45a20ab7Sforsyth {
137*45a20ab7Sforsyth 	LLEPUT(l);
138*45a20ab7Sforsyth }
139*45a20ab7Sforsyth 
140*45a20ab7Sforsyth void
llput(vlong v)141*45a20ab7Sforsyth llput(vlong v)
142*45a20ab7Sforsyth {
143*45a20ab7Sforsyth 	lput(v>>32);
144*45a20ab7Sforsyth 	lput(v);
145*45a20ab7Sforsyth }
146*45a20ab7Sforsyth 
147*45a20ab7Sforsyth void
llputl(vlong v)148*45a20ab7Sforsyth llputl(vlong v)
149*45a20ab7Sforsyth {
150*45a20ab7Sforsyth 	lputl(v);
151*45a20ab7Sforsyth 	lputl(v>>32);
152*45a20ab7Sforsyth }
153*45a20ab7Sforsyth 
15474a4d8c2SCharles.Forsyth long
entryvalue(void)15574a4d8c2SCharles.Forsyth entryvalue(void)
15674a4d8c2SCharles.Forsyth {
15774a4d8c2SCharles.Forsyth 	char *a;
15874a4d8c2SCharles.Forsyth 	Sym *s;
15974a4d8c2SCharles.Forsyth 
16074a4d8c2SCharles.Forsyth 	a = INITENTRY;
16174a4d8c2SCharles.Forsyth 	if(*a >= '0' && *a <= '9')
16274a4d8c2SCharles.Forsyth 		return atolwhex(a);
16374a4d8c2SCharles.Forsyth 	s = lookup(a, 0);
16474a4d8c2SCharles.Forsyth 	if(s->type == 0)
16574a4d8c2SCharles.Forsyth 		return INITTEXT;
16674a4d8c2SCharles.Forsyth 	if(s->type != STEXT && s->type != SLEAF)
16774a4d8c2SCharles.Forsyth 		diag("entry not text: %s", s->name);
16874a4d8c2SCharles.Forsyth 	return s->value;
16974a4d8c2SCharles.Forsyth }
17074a4d8c2SCharles.Forsyth 
17174a4d8c2SCharles.Forsyth void
asmb(void)17274a4d8c2SCharles.Forsyth asmb(void)
17374a4d8c2SCharles.Forsyth {
17474a4d8c2SCharles.Forsyth 	Prog *p;
17574a4d8c2SCharles.Forsyth 	long t, etext;
17674a4d8c2SCharles.Forsyth 	Optab *o;
17774a4d8c2SCharles.Forsyth 
17874a4d8c2SCharles.Forsyth 	if(debug['v'])
17974a4d8c2SCharles.Forsyth 		Bprint(&bso, "%5.2f asm\n", cputime());
18074a4d8c2SCharles.Forsyth 	Bflush(&bso);
18174a4d8c2SCharles.Forsyth 	OFFSET = HEADR;
18274a4d8c2SCharles.Forsyth 	seek(cout, OFFSET, 0);
18374a4d8c2SCharles.Forsyth 	pc = INITTEXT;
18474a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
18574a4d8c2SCharles.Forsyth 		if(p->as == ATEXT) {
18674a4d8c2SCharles.Forsyth 			curtext = p;
18774a4d8c2SCharles.Forsyth 			autosize = p->to.offset + 4;
18874a4d8c2SCharles.Forsyth 		}
18974a4d8c2SCharles.Forsyth 		if(p->pc != pc) {
19074a4d8c2SCharles.Forsyth 			diag("phase error %lux sb %lux",
19174a4d8c2SCharles.Forsyth 				p->pc, pc);
19274a4d8c2SCharles.Forsyth 			if(!debug['a'])
19374a4d8c2SCharles.Forsyth 				prasm(curp);
19474a4d8c2SCharles.Forsyth 			pc = p->pc;
19574a4d8c2SCharles.Forsyth 		}
19674a4d8c2SCharles.Forsyth 		curp = p;
19774a4d8c2SCharles.Forsyth 		o = oplook(p);	/* could probably avoid this call */
19874a4d8c2SCharles.Forsyth 		if(asmout(p, o, 0)) {
19974a4d8c2SCharles.Forsyth 			p = p->link;
20074a4d8c2SCharles.Forsyth 			pc += 4;
20174a4d8c2SCharles.Forsyth 		}
20274a4d8c2SCharles.Forsyth 		pc += o->size;
20374a4d8c2SCharles.Forsyth 	}
20474a4d8c2SCharles.Forsyth 	if(debug['a'])
20574a4d8c2SCharles.Forsyth 		Bprint(&bso, "\n");
20674a4d8c2SCharles.Forsyth 	Bflush(&bso);
20774a4d8c2SCharles.Forsyth 	cflush();
20874a4d8c2SCharles.Forsyth 
20974a4d8c2SCharles.Forsyth 	etext = INITTEXT + textsize;
21074a4d8c2SCharles.Forsyth 	for(t = pc; t < etext; t += sizeof(buf)-100) {
21174a4d8c2SCharles.Forsyth 		if(etext-t > sizeof(buf)-100)
21274a4d8c2SCharles.Forsyth 			datblk(t, sizeof(buf)-100, 1);
21374a4d8c2SCharles.Forsyth 		else
21474a4d8c2SCharles.Forsyth 			datblk(t, etext-t, 1);
21574a4d8c2SCharles.Forsyth 	}
21674a4d8c2SCharles.Forsyth 
21774a4d8c2SCharles.Forsyth 	Bflush(&bso);
21874a4d8c2SCharles.Forsyth 	cflush();
21974a4d8c2SCharles.Forsyth 
22074a4d8c2SCharles.Forsyth 	curtext = P;
22174a4d8c2SCharles.Forsyth 	switch(HEADTYPE) {
22274a4d8c2SCharles.Forsyth 	case 0:
22374a4d8c2SCharles.Forsyth 	case 4:
22474a4d8c2SCharles.Forsyth 		OFFSET = rnd(HEADR+textsize, 4096);
22574a4d8c2SCharles.Forsyth 		seek(cout, OFFSET, 0);
22674a4d8c2SCharles.Forsyth 		break;
22774a4d8c2SCharles.Forsyth 	case 1:
22874a4d8c2SCharles.Forsyth 	case 2:
22974a4d8c2SCharles.Forsyth 	case 3:
23074a4d8c2SCharles.Forsyth 	case 5:
2314206ee1aSforsyth 	case 6:
23274a4d8c2SCharles.Forsyth 		OFFSET = HEADR+textsize;
23374a4d8c2SCharles.Forsyth 		seek(cout, OFFSET, 0);
23474a4d8c2SCharles.Forsyth 		break;
23574a4d8c2SCharles.Forsyth 	}
23674a4d8c2SCharles.Forsyth 	for(t = 0; t < datsize; t += sizeof(buf)-100) {
23774a4d8c2SCharles.Forsyth 		if(datsize-t > sizeof(buf)-100)
23874a4d8c2SCharles.Forsyth 			datblk(t, sizeof(buf)-100, 0);
23974a4d8c2SCharles.Forsyth 		else
24074a4d8c2SCharles.Forsyth 			datblk(t, datsize-t, 0);
24174a4d8c2SCharles.Forsyth 	}
24274a4d8c2SCharles.Forsyth 
24374a4d8c2SCharles.Forsyth 	symsize = 0;
24474a4d8c2SCharles.Forsyth 	lcsize = 0;
24574a4d8c2SCharles.Forsyth 	if(!debug['s']) {
24674a4d8c2SCharles.Forsyth 		if(debug['v'])
24774a4d8c2SCharles.Forsyth 			Bprint(&bso, "%5.2f sym\n", cputime());
24874a4d8c2SCharles.Forsyth 		Bflush(&bso);
24974a4d8c2SCharles.Forsyth 		switch(HEADTYPE) {
25074a4d8c2SCharles.Forsyth 		case 0:
25174a4d8c2SCharles.Forsyth 		case 4:
25274a4d8c2SCharles.Forsyth 			OFFSET = rnd(HEADR+textsize, 4096)+datsize;
25374a4d8c2SCharles.Forsyth 			seek(cout, OFFSET, 0);
25474a4d8c2SCharles.Forsyth 			break;
25574a4d8c2SCharles.Forsyth 		case 3:
25674a4d8c2SCharles.Forsyth 		case 2:
25774a4d8c2SCharles.Forsyth 		case 1:
25874a4d8c2SCharles.Forsyth 		case 5:
2594206ee1aSforsyth 		case 6:
26074a4d8c2SCharles.Forsyth 			OFFSET = HEADR+textsize+datsize;
26174a4d8c2SCharles.Forsyth 			seek(cout, OFFSET, 0);
26274a4d8c2SCharles.Forsyth 			break;
26374a4d8c2SCharles.Forsyth 		}
26474a4d8c2SCharles.Forsyth 		if(!debug['s'])
26574a4d8c2SCharles.Forsyth 			asmsym();
26674a4d8c2SCharles.Forsyth 		if(debug['v'])
26774a4d8c2SCharles.Forsyth 			Bprint(&bso, "%5.2f pc\n", cputime());
26874a4d8c2SCharles.Forsyth 		Bflush(&bso);
26974a4d8c2SCharles.Forsyth 		if(!debug['s'])
27074a4d8c2SCharles.Forsyth 			asmlc();
27174a4d8c2SCharles.Forsyth 		cflush();
27274a4d8c2SCharles.Forsyth 	}
27374a4d8c2SCharles.Forsyth 
27474a4d8c2SCharles.Forsyth 	if(debug['v'])
27574a4d8c2SCharles.Forsyth 		Bprint(&bso, "%5.2f header\n", cputime());
27674a4d8c2SCharles.Forsyth 	Bflush(&bso);
27774a4d8c2SCharles.Forsyth 	OFFSET = 0;
27874a4d8c2SCharles.Forsyth 	seek(cout, OFFSET, 0);
27974a4d8c2SCharles.Forsyth 	switch(HEADTYPE) {
28074a4d8c2SCharles.Forsyth 	case 0:
28174a4d8c2SCharles.Forsyth 		lput(0x160L<<16);		/* magic and sections */
28274a4d8c2SCharles.Forsyth 		lput(0L);			/* time and date */
28374a4d8c2SCharles.Forsyth 		lput(rnd(HEADR+textsize, 4096)+datsize);
28474a4d8c2SCharles.Forsyth 		lput(symsize);			/* nsyms */
28574a4d8c2SCharles.Forsyth 		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
28674a4d8c2SCharles.Forsyth 		lput((0413<<16)|0437L);		/* magic and version */
28774a4d8c2SCharles.Forsyth 		lput(rnd(HEADR+textsize, 4096));	/* sizes */
28874a4d8c2SCharles.Forsyth 		lput(datsize);
28974a4d8c2SCharles.Forsyth 		lput(bsssize);
29074a4d8c2SCharles.Forsyth 		lput(entryvalue());		/* va of entry */
29174a4d8c2SCharles.Forsyth 		lput(INITTEXT-HEADR);		/* va of base of text */
29274a4d8c2SCharles.Forsyth 		lput(INITDAT);			/* va of base of data */
29374a4d8c2SCharles.Forsyth 		lput(INITDAT+datsize);		/* va of base of bss */
29474a4d8c2SCharles.Forsyth 		lput(~0L);			/* gp reg mask */
29574a4d8c2SCharles.Forsyth 		lput(0L);
29674a4d8c2SCharles.Forsyth 		lput(0L);
29774a4d8c2SCharles.Forsyth 		lput(0L);
29874a4d8c2SCharles.Forsyth 		lput(0L);
29974a4d8c2SCharles.Forsyth 		lput(~0L);			/* gp value ?? */
30074a4d8c2SCharles.Forsyth 		break;
30174a4d8c2SCharles.Forsyth 	case 1:
30274a4d8c2SCharles.Forsyth 		lput(0x160L<<16);		/* magic and sections */
30374a4d8c2SCharles.Forsyth 		lput(0L);			/* time and date */
30474a4d8c2SCharles.Forsyth 		lput(HEADR+textsize+datsize);
30574a4d8c2SCharles.Forsyth 		lput(symsize);			/* nsyms */
30674a4d8c2SCharles.Forsyth 		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
30774a4d8c2SCharles.Forsyth 
30874a4d8c2SCharles.Forsyth 		lput((0407<<16)|0437L);		/* magic and version */
30974a4d8c2SCharles.Forsyth 		lput(textsize);			/* sizes */
31074a4d8c2SCharles.Forsyth 		lput(datsize);
31174a4d8c2SCharles.Forsyth 		lput(bsssize);
31274a4d8c2SCharles.Forsyth 		lput(entryvalue());		/* va of entry */
31374a4d8c2SCharles.Forsyth 		lput(INITTEXT);			/* va of base of text */
31474a4d8c2SCharles.Forsyth 		lput(INITDAT);			/* va of base of data */
31574a4d8c2SCharles.Forsyth 		lput(INITDAT+datsize);		/* va of base of bss */
31674a4d8c2SCharles.Forsyth 		lput(~0L);			/* gp reg mask */
31774a4d8c2SCharles.Forsyth 		lput(lcsize);
31874a4d8c2SCharles.Forsyth 		lput(0L);
31974a4d8c2SCharles.Forsyth 		lput(0L);
32074a4d8c2SCharles.Forsyth 		lput(0L);
32174a4d8c2SCharles.Forsyth 		lput(~0L);			/* gp value ?? */
32274a4d8c2SCharles.Forsyth 		lput(0L);			/* complete mystery */
32374a4d8c2SCharles.Forsyth 		break;
32474a4d8c2SCharles.Forsyth 	case 2:
3254206ee1aSforsyth 		if (little)
3264206ee1aSforsyth 			t = 24;
3274206ee1aSforsyth 		else
3284206ee1aSforsyth 			t = 16;
3294206ee1aSforsyth 		lput(((((4*t)+0)*t)+7));	/* magic */
33074a4d8c2SCharles.Forsyth 		lput(textsize);			/* sizes */
33174a4d8c2SCharles.Forsyth 		lput(datsize);
33274a4d8c2SCharles.Forsyth 		lput(bsssize);
33374a4d8c2SCharles.Forsyth 		lput(symsize);			/* nsyms */
33474a4d8c2SCharles.Forsyth 		lput(entryvalue());		/* va of entry */
33574a4d8c2SCharles.Forsyth 		lput(0L);
33674a4d8c2SCharles.Forsyth 		lput(lcsize);
33774a4d8c2SCharles.Forsyth 		break;
33874a4d8c2SCharles.Forsyth 	case 3:
33974a4d8c2SCharles.Forsyth 		lput((0x160L<<16)|3L);		/* magic and sections */
34074a4d8c2SCharles.Forsyth 		lput(time(0));			/* time and date */
34174a4d8c2SCharles.Forsyth 		lput(HEADR+textsize+datsize);
34274a4d8c2SCharles.Forsyth 		lput(symsize);			/* nsyms */
34374a4d8c2SCharles.Forsyth 		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
34474a4d8c2SCharles.Forsyth 
34574a4d8c2SCharles.Forsyth 		lput((0407<<16)|0437L);		/* magic and version */
34674a4d8c2SCharles.Forsyth 		lput(textsize);			/* sizes */
34774a4d8c2SCharles.Forsyth 		lput(datsize);
34874a4d8c2SCharles.Forsyth 		lput(bsssize);
34974a4d8c2SCharles.Forsyth 		lput(entryvalue());		/* va of entry */
35074a4d8c2SCharles.Forsyth 		lput(INITTEXT);			/* va of base of text */
35174a4d8c2SCharles.Forsyth 		lput(INITDAT);			/* va of base of data */
35274a4d8c2SCharles.Forsyth 		lput(INITDAT+datsize);		/* va of base of bss */
35374a4d8c2SCharles.Forsyth 		lput(~0L);			/* gp reg mask */
35474a4d8c2SCharles.Forsyth 		lput(lcsize);
35574a4d8c2SCharles.Forsyth 		lput(0L);
35674a4d8c2SCharles.Forsyth 		lput(0L);
35774a4d8c2SCharles.Forsyth 		lput(0L);
35874a4d8c2SCharles.Forsyth 		lput(~0L);			/* gp value ?? */
35974a4d8c2SCharles.Forsyth 
36074a4d8c2SCharles.Forsyth 		strnput(".text", 8);		/* text segment */
36174a4d8c2SCharles.Forsyth 		lput(INITTEXT);			/* address */
36274a4d8c2SCharles.Forsyth 		lput(INITTEXT);
36374a4d8c2SCharles.Forsyth 		lput(textsize);
36474a4d8c2SCharles.Forsyth 		lput(HEADR);
36574a4d8c2SCharles.Forsyth 		lput(0L);
36674a4d8c2SCharles.Forsyth 		lput(HEADR+textsize+datsize+symsize);
36774a4d8c2SCharles.Forsyth 		lput(lcsize);			/* line number size */
36874a4d8c2SCharles.Forsyth 		lput(0x20L);			/* flags */
36974a4d8c2SCharles.Forsyth 
37074a4d8c2SCharles.Forsyth 		strnput(".data", 8);		/* data segment */
37174a4d8c2SCharles.Forsyth 		lput(INITDAT);			/* address */
37274a4d8c2SCharles.Forsyth 		lput(INITDAT);
37374a4d8c2SCharles.Forsyth 		lput(datsize);
37474a4d8c2SCharles.Forsyth 		lput(HEADR+textsize);
37574a4d8c2SCharles.Forsyth 		lput(0L);
37674a4d8c2SCharles.Forsyth 		lput(0L);
37774a4d8c2SCharles.Forsyth 		lput(0L);
37874a4d8c2SCharles.Forsyth 		lput(0x40L);			/* flags */
37974a4d8c2SCharles.Forsyth 
38074a4d8c2SCharles.Forsyth 		strnput(".bss", 8);		/* bss segment */
38174a4d8c2SCharles.Forsyth 		lput(INITDAT+datsize);		/* address */
38274a4d8c2SCharles.Forsyth 		lput(INITDAT+datsize);
38374a4d8c2SCharles.Forsyth 		lput(bsssize);
38474a4d8c2SCharles.Forsyth 		lput(0L);
38574a4d8c2SCharles.Forsyth 		lput(0L);
38674a4d8c2SCharles.Forsyth 		lput(0L);
38774a4d8c2SCharles.Forsyth 		lput(0L);
38874a4d8c2SCharles.Forsyth 		lput(0x80L);			/* flags */
38974a4d8c2SCharles.Forsyth 		break;
39074a4d8c2SCharles.Forsyth 	case 4:
39174a4d8c2SCharles.Forsyth 
39274a4d8c2SCharles.Forsyth 		lput((0x160L<<16)|3L);		/* magic and sections */
39374a4d8c2SCharles.Forsyth 		lput(time(0));			/* time and date */
39474a4d8c2SCharles.Forsyth 		lput(rnd(HEADR+textsize, 4096)+datsize);
39574a4d8c2SCharles.Forsyth 		lput(symsize);			/* nsyms */
39674a4d8c2SCharles.Forsyth 		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
39774a4d8c2SCharles.Forsyth 
39874a4d8c2SCharles.Forsyth 		lput((0413<<16)|01012L);	/* magic and version */
39974a4d8c2SCharles.Forsyth 		lput(textsize);			/* sizes */
40074a4d8c2SCharles.Forsyth 		lput(datsize);
40174a4d8c2SCharles.Forsyth 		lput(bsssize);
40274a4d8c2SCharles.Forsyth 		lput(entryvalue());		/* va of entry */
40374a4d8c2SCharles.Forsyth 		lput(INITTEXT);			/* va of base of text */
40474a4d8c2SCharles.Forsyth 		lput(INITDAT);			/* va of base of data */
40574a4d8c2SCharles.Forsyth 		lput(INITDAT+datsize);		/* va of base of bss */
40674a4d8c2SCharles.Forsyth 		lput(~0L);			/* gp reg mask */
40774a4d8c2SCharles.Forsyth 		lput(lcsize);
40874a4d8c2SCharles.Forsyth 		lput(0L);
40974a4d8c2SCharles.Forsyth 		lput(0L);
41074a4d8c2SCharles.Forsyth 		lput(0L);
41174a4d8c2SCharles.Forsyth 		lput(~0L);			/* gp value ?? */
41274a4d8c2SCharles.Forsyth 
41374a4d8c2SCharles.Forsyth 		strnput(".text", 8);		/* text segment */
41474a4d8c2SCharles.Forsyth 		lput(INITTEXT);			/* address */
41574a4d8c2SCharles.Forsyth 		lput(INITTEXT);
41674a4d8c2SCharles.Forsyth 		lput(textsize);
41774a4d8c2SCharles.Forsyth 		lput(HEADR);
41874a4d8c2SCharles.Forsyth 		lput(0L);
41974a4d8c2SCharles.Forsyth 		lput(HEADR+textsize+datsize+symsize);
42074a4d8c2SCharles.Forsyth 		lput(lcsize);			/* line number size */
42174a4d8c2SCharles.Forsyth 		lput(0x20L);			/* flags */
42274a4d8c2SCharles.Forsyth 
42374a4d8c2SCharles.Forsyth 		strnput(".data", 8);		/* data segment */
42474a4d8c2SCharles.Forsyth 		lput(INITDAT);			/* address */
42574a4d8c2SCharles.Forsyth 		lput(INITDAT);
42674a4d8c2SCharles.Forsyth 		lput(datsize);
42774a4d8c2SCharles.Forsyth 		lput(rnd(HEADR+textsize, 4096));	/* sizes */
42874a4d8c2SCharles.Forsyth 		lput(0L);
42974a4d8c2SCharles.Forsyth 		lput(0L);
43074a4d8c2SCharles.Forsyth 		lput(0L);
43174a4d8c2SCharles.Forsyth 		lput(0x40L);			/* flags */
43274a4d8c2SCharles.Forsyth 
43374a4d8c2SCharles.Forsyth 		strnput(".bss", 8);		/* bss segment */
43474a4d8c2SCharles.Forsyth 		lput(INITDAT+datsize);		/* address */
43574a4d8c2SCharles.Forsyth 		lput(INITDAT+datsize);
43674a4d8c2SCharles.Forsyth 		lput(bsssize);
43774a4d8c2SCharles.Forsyth 		lput(0L);
43874a4d8c2SCharles.Forsyth 		lput(0L);
43974a4d8c2SCharles.Forsyth 		lput(0L);
44074a4d8c2SCharles.Forsyth 		lput(0L);
44174a4d8c2SCharles.Forsyth 		lput(0x80L);			/* flags */
44274a4d8c2SCharles.Forsyth 		break;
44374a4d8c2SCharles.Forsyth 	case 5:
444*45a20ab7Sforsyth 		elf32(MIPS, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
4454206ee1aSforsyth 		break;
4464206ee1aSforsyth 	case 6:
4474206ee1aSforsyth 		break;
44874a4d8c2SCharles.Forsyth 	}
44974a4d8c2SCharles.Forsyth 	cflush();
45074a4d8c2SCharles.Forsyth }
45174a4d8c2SCharles.Forsyth 
45274a4d8c2SCharles.Forsyth void
strnput(char * s,int n)45374a4d8c2SCharles.Forsyth strnput(char *s, int n)
45474a4d8c2SCharles.Forsyth {
45574a4d8c2SCharles.Forsyth 	for(; *s; s++){
45674a4d8c2SCharles.Forsyth 		CPUT(*s);
45774a4d8c2SCharles.Forsyth 		n--;
45874a4d8c2SCharles.Forsyth 	}
45974a4d8c2SCharles.Forsyth 	for(; n > 0; n--)
46074a4d8c2SCharles.Forsyth 		CPUT(0);
46174a4d8c2SCharles.Forsyth }
46274a4d8c2SCharles.Forsyth 
46374a4d8c2SCharles.Forsyth void
cflush(void)46474a4d8c2SCharles.Forsyth cflush(void)
46574a4d8c2SCharles.Forsyth {
46674a4d8c2SCharles.Forsyth 	int n;
46774a4d8c2SCharles.Forsyth 
46874a4d8c2SCharles.Forsyth 	n = sizeof(buf.cbuf) - cbc;
46974a4d8c2SCharles.Forsyth 	if(n)
47074a4d8c2SCharles.Forsyth 		write(cout, buf.cbuf, n);
47174a4d8c2SCharles.Forsyth 	cbp = buf.cbuf;
47274a4d8c2SCharles.Forsyth 	cbc = sizeof(buf.cbuf);
47374a4d8c2SCharles.Forsyth }
47474a4d8c2SCharles.Forsyth 
47574a4d8c2SCharles.Forsyth void
nopstat(char * f,Count * c)47674a4d8c2SCharles.Forsyth nopstat(char *f, Count *c)
47774a4d8c2SCharles.Forsyth {
47874a4d8c2SCharles.Forsyth 	if(c->outof)
47974a4d8c2SCharles.Forsyth 	Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
48074a4d8c2SCharles.Forsyth 		c->outof - c->count, c->outof,
48174a4d8c2SCharles.Forsyth 		(double)(c->outof - c->count)/c->outof);
48274a4d8c2SCharles.Forsyth }
48374a4d8c2SCharles.Forsyth 
48474a4d8c2SCharles.Forsyth void
asmsym(void)48574a4d8c2SCharles.Forsyth asmsym(void)
48674a4d8c2SCharles.Forsyth {
48774a4d8c2SCharles.Forsyth 	Prog *p;
48874a4d8c2SCharles.Forsyth 	Auto *a;
48974a4d8c2SCharles.Forsyth 	Sym *s;
49074a4d8c2SCharles.Forsyth 	int h;
49174a4d8c2SCharles.Forsyth 
49274a4d8c2SCharles.Forsyth 	s = lookup("etext", 0);
49374a4d8c2SCharles.Forsyth 	if(s->type == STEXT)
49474a4d8c2SCharles.Forsyth 		putsymb(s->name, 'T', s->value, s->version);
49574a4d8c2SCharles.Forsyth 
49674a4d8c2SCharles.Forsyth 	for(h=0; h<NHASH; h++)
49774a4d8c2SCharles.Forsyth 		for(s=hash[h]; s!=S; s=s->link)
49874a4d8c2SCharles.Forsyth 			switch(s->type) {
49974a4d8c2SCharles.Forsyth 			case SCONST:
50074a4d8c2SCharles.Forsyth 				putsymb(s->name, 'D', s->value, s->version);
50174a4d8c2SCharles.Forsyth 				continue;
50274a4d8c2SCharles.Forsyth 
50374a4d8c2SCharles.Forsyth 			case SSTRING:
50474a4d8c2SCharles.Forsyth 				putsymb(s->name, 'T', s->value, s->version);
50574a4d8c2SCharles.Forsyth 				continue;
50674a4d8c2SCharles.Forsyth 
50774a4d8c2SCharles.Forsyth 			case SDATA:
50874a4d8c2SCharles.Forsyth 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
50974a4d8c2SCharles.Forsyth 				continue;
51074a4d8c2SCharles.Forsyth 
51174a4d8c2SCharles.Forsyth 			case SBSS:
51274a4d8c2SCharles.Forsyth 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
51374a4d8c2SCharles.Forsyth 				continue;
51474a4d8c2SCharles.Forsyth 
51574a4d8c2SCharles.Forsyth 			case SFILE:
51674a4d8c2SCharles.Forsyth 				putsymb(s->name, 'f', s->value, s->version);
51774a4d8c2SCharles.Forsyth 				continue;
51874a4d8c2SCharles.Forsyth 			}
51974a4d8c2SCharles.Forsyth 
52074a4d8c2SCharles.Forsyth 	for(p=textp; p!=P; p=p->cond) {
52174a4d8c2SCharles.Forsyth 		s = p->from.sym;
52274a4d8c2SCharles.Forsyth 		if(s->type != STEXT && s->type != SLEAF)
52374a4d8c2SCharles.Forsyth 			continue;
52474a4d8c2SCharles.Forsyth 
52574a4d8c2SCharles.Forsyth 		/* filenames first */
52674a4d8c2SCharles.Forsyth 		for(a=p->to.autom; a; a=a->link)
52774a4d8c2SCharles.Forsyth 			if(a->type == D_FILE)
52874a4d8c2SCharles.Forsyth 				putsymb(a->asym->name, 'z', a->aoffset, 0);
52974a4d8c2SCharles.Forsyth 			else
53074a4d8c2SCharles.Forsyth 			if(a->type == D_FILE1)
53174a4d8c2SCharles.Forsyth 				putsymb(a->asym->name, 'Z', a->aoffset, 0);
53274a4d8c2SCharles.Forsyth 
53374a4d8c2SCharles.Forsyth 		if(s->type == STEXT)
53474a4d8c2SCharles.Forsyth 			putsymb(s->name, 'T', s->value, s->version);
53574a4d8c2SCharles.Forsyth 		else
53674a4d8c2SCharles.Forsyth 			putsymb(s->name, 'L', s->value, s->version);
53774a4d8c2SCharles.Forsyth 
53874a4d8c2SCharles.Forsyth 		/* frame, auto and param after */
53974a4d8c2SCharles.Forsyth 		putsymb(".frame", 'm', p->to.offset+4, 0);
54074a4d8c2SCharles.Forsyth 		for(a=p->to.autom; a; a=a->link)
54174a4d8c2SCharles.Forsyth 			if(a->type == D_AUTO)
54274a4d8c2SCharles.Forsyth 				putsymb(a->asym->name, 'a', -a->aoffset, 0);
54374a4d8c2SCharles.Forsyth 			else
54474a4d8c2SCharles.Forsyth 			if(a->type == D_PARAM)
54574a4d8c2SCharles.Forsyth 				putsymb(a->asym->name, 'p', a->aoffset, 0);
54674a4d8c2SCharles.Forsyth 	}
54774a4d8c2SCharles.Forsyth 	if(debug['v'] || debug['n'])
54874a4d8c2SCharles.Forsyth 		Bprint(&bso, "symsize = %lud\n", symsize);
54974a4d8c2SCharles.Forsyth 	Bflush(&bso);
55074a4d8c2SCharles.Forsyth }
55174a4d8c2SCharles.Forsyth 
55274a4d8c2SCharles.Forsyth void
putsymb(char * s,int t,long v,int ver)55374a4d8c2SCharles.Forsyth putsymb(char *s, int t, long v, int ver)
55474a4d8c2SCharles.Forsyth {
55574a4d8c2SCharles.Forsyth 	int i, f;
55674a4d8c2SCharles.Forsyth 
55774a4d8c2SCharles.Forsyth 	if(t == 'f')
55874a4d8c2SCharles.Forsyth 		s++;
5594206ee1aSforsyth 	LBEPUT(v);
56074a4d8c2SCharles.Forsyth 	if(ver)
56174a4d8c2SCharles.Forsyth 		t += 'a' - 'A';
56274a4d8c2SCharles.Forsyth 	CPUT(t+0x80);			/* 0x80 is variable length */
56374a4d8c2SCharles.Forsyth 
56474a4d8c2SCharles.Forsyth 	if(t == 'Z' || t == 'z') {
56574a4d8c2SCharles.Forsyth 		CPUT(s[0]);
56674a4d8c2SCharles.Forsyth 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
56774a4d8c2SCharles.Forsyth 			CPUT(s[i]);
56874a4d8c2SCharles.Forsyth 			CPUT(s[i+1]);
56974a4d8c2SCharles.Forsyth 		}
57074a4d8c2SCharles.Forsyth 		CPUT(0);
57174a4d8c2SCharles.Forsyth 		CPUT(0);
57274a4d8c2SCharles.Forsyth 		i++;
57374a4d8c2SCharles.Forsyth 	}
57474a4d8c2SCharles.Forsyth 	else {
57574a4d8c2SCharles.Forsyth 		for(i=0; s[i]; i++)
57674a4d8c2SCharles.Forsyth 			CPUT(s[i]);
57774a4d8c2SCharles.Forsyth 		CPUT(0);
57874a4d8c2SCharles.Forsyth 	}
57974a4d8c2SCharles.Forsyth 	symsize += 4 + 1 + i + 1;
58074a4d8c2SCharles.Forsyth 
58174a4d8c2SCharles.Forsyth 	if(debug['n']) {
58274a4d8c2SCharles.Forsyth 		if(t == 'z' || t == 'Z') {
58374a4d8c2SCharles.Forsyth 			Bprint(&bso, "%c %.8lux ", t, v);
58474a4d8c2SCharles.Forsyth 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
58574a4d8c2SCharles.Forsyth 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
58674a4d8c2SCharles.Forsyth 				Bprint(&bso, "/%x", f);
58774a4d8c2SCharles.Forsyth 			}
58874a4d8c2SCharles.Forsyth 			Bprint(&bso, "\n");
58974a4d8c2SCharles.Forsyth 			return;
59074a4d8c2SCharles.Forsyth 		}
59174a4d8c2SCharles.Forsyth 		if(ver)
59274a4d8c2SCharles.Forsyth 			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
59374a4d8c2SCharles.Forsyth 		else
59474a4d8c2SCharles.Forsyth 			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
59574a4d8c2SCharles.Forsyth 	}
59674a4d8c2SCharles.Forsyth }
59774a4d8c2SCharles.Forsyth 
59874a4d8c2SCharles.Forsyth #define	MINLC	4
59974a4d8c2SCharles.Forsyth void
asmlc(void)60074a4d8c2SCharles.Forsyth asmlc(void)
60174a4d8c2SCharles.Forsyth {
60274a4d8c2SCharles.Forsyth 	long oldpc, oldlc;
60374a4d8c2SCharles.Forsyth 	Prog *p;
60474a4d8c2SCharles.Forsyth 	long v, s;
60574a4d8c2SCharles.Forsyth 
60674a4d8c2SCharles.Forsyth 	oldpc = INITTEXT;
60774a4d8c2SCharles.Forsyth 	oldlc = 0;
60874a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
60974a4d8c2SCharles.Forsyth 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
61074a4d8c2SCharles.Forsyth 			if(p->as == ATEXT)
61174a4d8c2SCharles.Forsyth 				curtext = p;
612*45a20ab7Sforsyth 			if(debug['V'])
61374a4d8c2SCharles.Forsyth 				Bprint(&bso, "%6lux %P\n",
61474a4d8c2SCharles.Forsyth 					p->pc, p);
61574a4d8c2SCharles.Forsyth 			continue;
61674a4d8c2SCharles.Forsyth 		}
617*45a20ab7Sforsyth 		if(debug['V'])
61874a4d8c2SCharles.Forsyth 			Bprint(&bso, "\t\t%6ld", lcsize);
61974a4d8c2SCharles.Forsyth 		v = (p->pc - oldpc) / MINLC;
62074a4d8c2SCharles.Forsyth 		while(v) {
62174a4d8c2SCharles.Forsyth 			s = 127;
62274a4d8c2SCharles.Forsyth 			if(v < 127)
62374a4d8c2SCharles.Forsyth 				s = v;
62474a4d8c2SCharles.Forsyth 			CPUT(s+128);	/* 129-255 +pc */
625*45a20ab7Sforsyth 			if(debug['V'])
62674a4d8c2SCharles.Forsyth 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
62774a4d8c2SCharles.Forsyth 			v -= s;
62874a4d8c2SCharles.Forsyth 			lcsize++;
62974a4d8c2SCharles.Forsyth 		}
63074a4d8c2SCharles.Forsyth 		s = p->line - oldlc;
63174a4d8c2SCharles.Forsyth 		oldlc = p->line;
63274a4d8c2SCharles.Forsyth 		oldpc = p->pc + MINLC;
63374a4d8c2SCharles.Forsyth 		if(s > 64 || s < -64) {
63474a4d8c2SCharles.Forsyth 			CPUT(0);	/* 0 vv +lc */
63574a4d8c2SCharles.Forsyth 			CPUT(s>>24);
63674a4d8c2SCharles.Forsyth 			CPUT(s>>16);
63774a4d8c2SCharles.Forsyth 			CPUT(s>>8);
63874a4d8c2SCharles.Forsyth 			CPUT(s);
639*45a20ab7Sforsyth 			if(debug['V']) {
64074a4d8c2SCharles.Forsyth 				if(s > 0)
64174a4d8c2SCharles.Forsyth 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
64274a4d8c2SCharles.Forsyth 						s, 0, s);
64374a4d8c2SCharles.Forsyth 				else
64474a4d8c2SCharles.Forsyth 					Bprint(&bso, " lc%ld(%d,%ld)\n",
64574a4d8c2SCharles.Forsyth 						s, 0, s);
64674a4d8c2SCharles.Forsyth 				Bprint(&bso, "%6lux %P\n",
64774a4d8c2SCharles.Forsyth 					p->pc, p);
64874a4d8c2SCharles.Forsyth 			}
64974a4d8c2SCharles.Forsyth 			lcsize += 5;
65074a4d8c2SCharles.Forsyth 			continue;
65174a4d8c2SCharles.Forsyth 		}
65274a4d8c2SCharles.Forsyth 		if(s > 0) {
65374a4d8c2SCharles.Forsyth 			CPUT(0+s);	/* 1-64 +lc */
654*45a20ab7Sforsyth 			if(debug['V']) {
65574a4d8c2SCharles.Forsyth 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
65674a4d8c2SCharles.Forsyth 				Bprint(&bso, "%6lux %P\n",
65774a4d8c2SCharles.Forsyth 					p->pc, p);
65874a4d8c2SCharles.Forsyth 			}
65974a4d8c2SCharles.Forsyth 		} else {
66074a4d8c2SCharles.Forsyth 			CPUT(64-s);	/* 65-128 -lc */
661*45a20ab7Sforsyth 			if(debug['V']) {
66274a4d8c2SCharles.Forsyth 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
66374a4d8c2SCharles.Forsyth 				Bprint(&bso, "%6lux %P\n",
66474a4d8c2SCharles.Forsyth 					p->pc, p);
66574a4d8c2SCharles.Forsyth 			}
66674a4d8c2SCharles.Forsyth 		}
66774a4d8c2SCharles.Forsyth 		lcsize++;
66874a4d8c2SCharles.Forsyth 	}
66974a4d8c2SCharles.Forsyth 	while(lcsize & 1) {
67074a4d8c2SCharles.Forsyth 		s = 129;
67174a4d8c2SCharles.Forsyth 		CPUT(s);
67274a4d8c2SCharles.Forsyth 		lcsize++;
67374a4d8c2SCharles.Forsyth 	}
674*45a20ab7Sforsyth 	if(debug['v'] || debug['V'])
67574a4d8c2SCharles.Forsyth 		Bprint(&bso, "lcsize = %ld\n", lcsize);
67674a4d8c2SCharles.Forsyth 	Bflush(&bso);
67774a4d8c2SCharles.Forsyth }
67874a4d8c2SCharles.Forsyth 
67974a4d8c2SCharles.Forsyth void
datblk(long s,long n,int str)68074a4d8c2SCharles.Forsyth datblk(long s, long n, int str)
68174a4d8c2SCharles.Forsyth {
68274a4d8c2SCharles.Forsyth 	Prog *p;
68374a4d8c2SCharles.Forsyth 	char *cast;
68474a4d8c2SCharles.Forsyth 	long l, fl, j, d;
68574a4d8c2SCharles.Forsyth 	int i, c;
68674a4d8c2SCharles.Forsyth 
68774a4d8c2SCharles.Forsyth 	memset(buf.dbuf, 0, n+100);
68874a4d8c2SCharles.Forsyth 	for(p = datap; p != P; p = p->link) {
68974a4d8c2SCharles.Forsyth 		curp = p;
69074a4d8c2SCharles.Forsyth 		if(str != (p->from.sym->type == SSTRING))
69174a4d8c2SCharles.Forsyth 			continue;
69274a4d8c2SCharles.Forsyth 		l = p->from.sym->value + p->from.offset - s;
69374a4d8c2SCharles.Forsyth 		c = p->reg;
69474a4d8c2SCharles.Forsyth 		i = 0;
69574a4d8c2SCharles.Forsyth 		if(l < 0) {
69674a4d8c2SCharles.Forsyth 			if(l+c <= 0)
69774a4d8c2SCharles.Forsyth 				continue;
69874a4d8c2SCharles.Forsyth 			while(l < 0) {
69974a4d8c2SCharles.Forsyth 				l++;
70074a4d8c2SCharles.Forsyth 				i++;
70174a4d8c2SCharles.Forsyth 			}
70274a4d8c2SCharles.Forsyth 		}
70374a4d8c2SCharles.Forsyth 		if(l >= n)
70474a4d8c2SCharles.Forsyth 			continue;
70574a4d8c2SCharles.Forsyth 		if(p->as != AINIT && p->as != ADYNT) {
70674a4d8c2SCharles.Forsyth 			for(j=l+(c-i)-1; j>=l; j--)
70774a4d8c2SCharles.Forsyth 				if(buf.dbuf[j]) {
70874a4d8c2SCharles.Forsyth 					print("%P\n", p);
70974a4d8c2SCharles.Forsyth 					diag("multiple initialization");
71074a4d8c2SCharles.Forsyth 					break;
71174a4d8c2SCharles.Forsyth 				}
71274a4d8c2SCharles.Forsyth 		}
71374a4d8c2SCharles.Forsyth 		switch(p->to.type) {
71474a4d8c2SCharles.Forsyth 		default:
71574a4d8c2SCharles.Forsyth 			diag("unknown mode in initialization\n%P", p);
71674a4d8c2SCharles.Forsyth 			break;
71774a4d8c2SCharles.Forsyth 
71874a4d8c2SCharles.Forsyth 		case D_FCONST:
71974a4d8c2SCharles.Forsyth 			switch(c) {
72074a4d8c2SCharles.Forsyth 			default:
72174a4d8c2SCharles.Forsyth 			case 4:
72274a4d8c2SCharles.Forsyth 				fl = ieeedtof(p->to.ieee);
72374a4d8c2SCharles.Forsyth 				cast = (char*)&fl;
72474a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
72574a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[fnuxi8[i+4]];
72674a4d8c2SCharles.Forsyth 					l++;
72774a4d8c2SCharles.Forsyth 				}
72874a4d8c2SCharles.Forsyth 				break;
72974a4d8c2SCharles.Forsyth 			case 8:
73074a4d8c2SCharles.Forsyth 				cast = (char*)p->to.ieee;
73174a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
73274a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[fnuxi8[i]];
73374a4d8c2SCharles.Forsyth 					l++;
73474a4d8c2SCharles.Forsyth 				}
73574a4d8c2SCharles.Forsyth 				break;
73674a4d8c2SCharles.Forsyth 			}
73774a4d8c2SCharles.Forsyth 			break;
73874a4d8c2SCharles.Forsyth 
73974a4d8c2SCharles.Forsyth 		case D_SCONST:
74074a4d8c2SCharles.Forsyth 			for(; i<c; i++) {
74174a4d8c2SCharles.Forsyth 				buf.dbuf[l] = p->to.sval[i];
74274a4d8c2SCharles.Forsyth 				l++;
74374a4d8c2SCharles.Forsyth 			}
74474a4d8c2SCharles.Forsyth 			break;
74574a4d8c2SCharles.Forsyth 
74674a4d8c2SCharles.Forsyth 		case D_CONST:
74774a4d8c2SCharles.Forsyth 			d = p->to.offset;
74874a4d8c2SCharles.Forsyth 			if(p->to.sym) {
74974a4d8c2SCharles.Forsyth 				switch(p->to.sym->type) {
75074a4d8c2SCharles.Forsyth 				case STEXT:
75174a4d8c2SCharles.Forsyth 				case SLEAF:
75274a4d8c2SCharles.Forsyth 				case SSTRING:
75374a4d8c2SCharles.Forsyth 					d += p->to.sym->value;
75474a4d8c2SCharles.Forsyth 					break;
75574a4d8c2SCharles.Forsyth 				case SDATA:
75674a4d8c2SCharles.Forsyth 				case SBSS:
75774a4d8c2SCharles.Forsyth 					d += p->to.sym->value + INITDAT;
75874a4d8c2SCharles.Forsyth 					break;
75974a4d8c2SCharles.Forsyth 				}
76074a4d8c2SCharles.Forsyth 			}
76174a4d8c2SCharles.Forsyth 			cast = (char*)&d;
76274a4d8c2SCharles.Forsyth 			switch(c) {
76374a4d8c2SCharles.Forsyth 			default:
76474a4d8c2SCharles.Forsyth 				diag("bad nuxi %d %d\n%P", c, i, curp);
76574a4d8c2SCharles.Forsyth 				break;
76674a4d8c2SCharles.Forsyth 			case 1:
76774a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
76874a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[inuxi1[i]];
76974a4d8c2SCharles.Forsyth 					l++;
77074a4d8c2SCharles.Forsyth 				}
77174a4d8c2SCharles.Forsyth 				break;
77274a4d8c2SCharles.Forsyth 			case 2:
77374a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
77474a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[inuxi2[i]];
77574a4d8c2SCharles.Forsyth 					l++;
77674a4d8c2SCharles.Forsyth 				}
77774a4d8c2SCharles.Forsyth 				break;
77874a4d8c2SCharles.Forsyth 			case 4:
77974a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
78074a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[inuxi4[i]];
78174a4d8c2SCharles.Forsyth 					l++;
78274a4d8c2SCharles.Forsyth 				}
78374a4d8c2SCharles.Forsyth 				break;
78474a4d8c2SCharles.Forsyth 			}
78574a4d8c2SCharles.Forsyth 			break;
78674a4d8c2SCharles.Forsyth 		}
78774a4d8c2SCharles.Forsyth 	}
78874a4d8c2SCharles.Forsyth 	write(cout, buf.dbuf, n);
78974a4d8c2SCharles.Forsyth }
79074a4d8c2SCharles.Forsyth 
79174a4d8c2SCharles.Forsyth #define	OP_RRR(op,r1,r2,r3)\
79274a4d8c2SCharles.Forsyth 	(op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|(((r3)&31L)<<11))
79374a4d8c2SCharles.Forsyth #define	OP_IRR(op,i,r2,r3)\
79474a4d8c2SCharles.Forsyth 	(op|((i)&0xffffL)|(((r2)&31L)<<21)|(((r3)&31L)<<16))
79574a4d8c2SCharles.Forsyth #define	OP_SRR(op,s,r2,r3)\
79674a4d8c2SCharles.Forsyth 	(op|(((s)&31L)<<6)|(((r2)&31L)<<16)|(((r3)&31L)<<11))
79774a4d8c2SCharles.Forsyth #define	OP_FRRR(op,r1,r2,r3)\
79874a4d8c2SCharles.Forsyth 	(op|(((r1)&31L)<<16)|(((r2)&31L)<<11)|(((r3)&31L)<<6))
79974a4d8c2SCharles.Forsyth #define	OP_JMP(op,i)\
80074a4d8c2SCharles.Forsyth 		((op)|((i)&0x3ffffffL))
80174a4d8c2SCharles.Forsyth 
80274a4d8c2SCharles.Forsyth #define	OP(x,y)\
80374a4d8c2SCharles.Forsyth 	(((x)<<3)|((y)<<0))
80474a4d8c2SCharles.Forsyth #define	SP(x,y)\
80574a4d8c2SCharles.Forsyth 	(((x)<<29)|((y)<<26))
80674a4d8c2SCharles.Forsyth #define	BCOND(x,y)\
80774a4d8c2SCharles.Forsyth 	(((x)<<19)|((y)<<16))
80874a4d8c2SCharles.Forsyth #define	MMU(x,y)\
80974a4d8c2SCharles.Forsyth 	(SP(2,0)|(16<<21)|((x)<<3)|((y)<<0))
81074a4d8c2SCharles.Forsyth #define	FPF(x,y)\
81174a4d8c2SCharles.Forsyth 	(SP(2,1)|(16<<21)|((x)<<3)|((y)<<0))
81274a4d8c2SCharles.Forsyth #define	FPD(x,y)\
81374a4d8c2SCharles.Forsyth 	(SP(2,1)|(17<<21)|((x)<<3)|((y)<<0))
81474a4d8c2SCharles.Forsyth #define	FPW(x,y)\
81574a4d8c2SCharles.Forsyth 	(SP(2,1)|(20<<21)|((x)<<3)|((y)<<0))
81674a4d8c2SCharles.Forsyth 
81774a4d8c2SCharles.Forsyth int vshift(int);
81874a4d8c2SCharles.Forsyth 
81974a4d8c2SCharles.Forsyth int
asmout(Prog * p,Optab * o,int aflag)82074a4d8c2SCharles.Forsyth asmout(Prog *p, Optab *o, int aflag)
82174a4d8c2SCharles.Forsyth {
82274a4d8c2SCharles.Forsyth 	long o1, o2, o3, o4, o5, o6, o7, v;
82374a4d8c2SCharles.Forsyth 	Prog *ct;
82474a4d8c2SCharles.Forsyth 	int r, a;
82574a4d8c2SCharles.Forsyth 
82674a4d8c2SCharles.Forsyth 	o1 = 0;
82774a4d8c2SCharles.Forsyth 	o2 = 0;
82874a4d8c2SCharles.Forsyth 	o3 = 0;
82974a4d8c2SCharles.Forsyth 	o4 = 0;
83074a4d8c2SCharles.Forsyth 	o5 = 0;
83174a4d8c2SCharles.Forsyth 	o6 = 0;
83274a4d8c2SCharles.Forsyth 	o7 = 0;
83374a4d8c2SCharles.Forsyth 	switch(o->type) {
83474a4d8c2SCharles.Forsyth 	default:
83574a4d8c2SCharles.Forsyth 		diag("unknown type %d", o->type);
83674a4d8c2SCharles.Forsyth 		if(!debug['a'])
83774a4d8c2SCharles.Forsyth 			prasm(p);
83874a4d8c2SCharles.Forsyth 		break;
83974a4d8c2SCharles.Forsyth 
84074a4d8c2SCharles.Forsyth 	case 0:		/* pseudo ops */
84174a4d8c2SCharles.Forsyth 		if(aflag) {
84274a4d8c2SCharles.Forsyth 			if(p->link) {
84374a4d8c2SCharles.Forsyth 				if(p->as == ATEXT) {
84474a4d8c2SCharles.Forsyth 					ct = curtext;
84574a4d8c2SCharles.Forsyth 					o2 = autosize;
84674a4d8c2SCharles.Forsyth 					curtext = p;
84774a4d8c2SCharles.Forsyth 					autosize = p->to.offset + 4;
84874a4d8c2SCharles.Forsyth 					o1 = asmout(p->link, oplook(p->link), aflag);
84974a4d8c2SCharles.Forsyth 					curtext = ct;
85074a4d8c2SCharles.Forsyth 					autosize = o2;
85174a4d8c2SCharles.Forsyth 				} else
85274a4d8c2SCharles.Forsyth 					o1 = asmout(p->link, oplook(p->link), aflag);
85374a4d8c2SCharles.Forsyth 			}
85474a4d8c2SCharles.Forsyth 			return o1;
85574a4d8c2SCharles.Forsyth 		}
85674a4d8c2SCharles.Forsyth 		break;
85774a4d8c2SCharles.Forsyth 
85874a4d8c2SCharles.Forsyth 	case 1:		/* mov[v] r1,r2 ==> OR r1,r0,r2 */
85974a4d8c2SCharles.Forsyth 		o1 = OP_RRR(oprrr(AOR), p->from.reg, REGZERO, p->to.reg);
86074a4d8c2SCharles.Forsyth 		break;
86174a4d8c2SCharles.Forsyth 
86274a4d8c2SCharles.Forsyth 	case 2:		/* add/sub r1,[r2],r3 */
86374a4d8c2SCharles.Forsyth 		r = p->reg;
86474a4d8c2SCharles.Forsyth 		if(r == NREG)
86574a4d8c2SCharles.Forsyth 			r = p->to.reg;
86674a4d8c2SCharles.Forsyth 		o1 = OP_RRR(oprrr(p->as), p->from.reg, r, p->to.reg);
86774a4d8c2SCharles.Forsyth 		break;
86874a4d8c2SCharles.Forsyth 
86974a4d8c2SCharles.Forsyth 	case 3:		/* mov $soreg, r ==> or/add $i,o,r */
87074a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
87174a4d8c2SCharles.Forsyth 		r = p->from.reg;
87274a4d8c2SCharles.Forsyth 		if(r == NREG)
87374a4d8c2SCharles.Forsyth 			r = o->param;
87474a4d8c2SCharles.Forsyth 		a = AADDU;
87574a4d8c2SCharles.Forsyth 		if(o->a1 == C_ANDCON)
87674a4d8c2SCharles.Forsyth 			a = AOR;
87774a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(a), v, r, p->to.reg);
87874a4d8c2SCharles.Forsyth 		break;
87974a4d8c2SCharles.Forsyth 
88074a4d8c2SCharles.Forsyth 	case 4:		/* add $scon,[r1],r2 */
88174a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
88274a4d8c2SCharles.Forsyth 		r = p->reg;
88374a4d8c2SCharles.Forsyth 		if(r == NREG)
88474a4d8c2SCharles.Forsyth 			r = p->to.reg;
88574a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(p->as), v, r, p->to.reg);
88674a4d8c2SCharles.Forsyth 		break;
88774a4d8c2SCharles.Forsyth 
88874a4d8c2SCharles.Forsyth 	case 5:		/* syscall */
88974a4d8c2SCharles.Forsyth 		if(aflag)
89074a4d8c2SCharles.Forsyth 			return 0;
89174a4d8c2SCharles.Forsyth 		o1 = oprrr(p->as);
89274a4d8c2SCharles.Forsyth 		break;
89374a4d8c2SCharles.Forsyth 
89474a4d8c2SCharles.Forsyth 	case 6:		/* beq r1,[r2],sbra */
89574a4d8c2SCharles.Forsyth 		if(aflag)
89674a4d8c2SCharles.Forsyth 			return 0;
89774a4d8c2SCharles.Forsyth 		if(p->cond == P)
89874a4d8c2SCharles.Forsyth 			v = -4 >> 2;
89974a4d8c2SCharles.Forsyth 		else
90074a4d8c2SCharles.Forsyth 			v = (p->cond->pc - pc-4) >> 2;
90174a4d8c2SCharles.Forsyth 		if(((v << 16) >> 16) != v)
9024206ee1aSforsyth 			diag("short branch too far: %ld\n%P", v, p);
90374a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(p->as), v, p->from.reg, p->reg);
90474a4d8c2SCharles.Forsyth 		break;
90574a4d8c2SCharles.Forsyth 
90674a4d8c2SCharles.Forsyth 	case 7:		/* mov r, soreg ==> sw o(r) */
90774a4d8c2SCharles.Forsyth 		r = p->to.reg;
90874a4d8c2SCharles.Forsyth 		if(r == NREG)
90974a4d8c2SCharles.Forsyth 			r = o->param;
91074a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
91174a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(p->as), v, r, p->from.reg);
91274a4d8c2SCharles.Forsyth 		break;
91374a4d8c2SCharles.Forsyth 
91474a4d8c2SCharles.Forsyth 	case 8:		/* mov soreg, r ==> lw o(r) */
91574a4d8c2SCharles.Forsyth 		r = p->from.reg;
91674a4d8c2SCharles.Forsyth 		if(r == NREG)
91774a4d8c2SCharles.Forsyth 			r = o->param;
91874a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
91974a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(p->as+ALAST), v, r, p->to.reg);
92074a4d8c2SCharles.Forsyth 		break;
92174a4d8c2SCharles.Forsyth 
92274a4d8c2SCharles.Forsyth 	case 9:		/* asl r1,[r2],r3 */
92374a4d8c2SCharles.Forsyth 		r = p->reg;
92474a4d8c2SCharles.Forsyth 		if(r == NREG)
92574a4d8c2SCharles.Forsyth 			r = p->to.reg;
92674a4d8c2SCharles.Forsyth 		o1 = OP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg);
92774a4d8c2SCharles.Forsyth 		break;
92874a4d8c2SCharles.Forsyth 
92974a4d8c2SCharles.Forsyth 	case 10:	/* add $con,[r1],r2 ==> mov $con,t; add t,[r1],r2 */
93074a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
93174a4d8c2SCharles.Forsyth 		r = AOR;
93274a4d8c2SCharles.Forsyth 		if(v < 0)
93374a4d8c2SCharles.Forsyth 			r = AADDU;
93474a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(r), v, 0, REGTMP);
93574a4d8c2SCharles.Forsyth 		r = p->reg;
93674a4d8c2SCharles.Forsyth 		if(r == NREG)
93774a4d8c2SCharles.Forsyth 			r = p->to.reg;
93874a4d8c2SCharles.Forsyth 		o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
93974a4d8c2SCharles.Forsyth 		break;
94074a4d8c2SCharles.Forsyth 
94174a4d8c2SCharles.Forsyth 	case 11:	/* jmp lbra */
94274a4d8c2SCharles.Forsyth 		if(aflag)
94374a4d8c2SCharles.Forsyth 			return 0;
94474a4d8c2SCharles.Forsyth 		if(p->cond == P)
94574a4d8c2SCharles.Forsyth 			v = p->pc >> 2;
94674a4d8c2SCharles.Forsyth 		else
94774a4d8c2SCharles.Forsyth 			v = p->cond->pc >> 2;
94874a4d8c2SCharles.Forsyth 		o1 = OP_JMP(opirr(p->as), v);
94974a4d8c2SCharles.Forsyth 		if(!debug['Y'] && p->link && p->cond && isnop(p->link)) {
95074a4d8c2SCharles.Forsyth 			nop.branch.count--;
95174a4d8c2SCharles.Forsyth 			nop.branch.outof--;
95274a4d8c2SCharles.Forsyth 			nop.jump.outof++;
95374a4d8c2SCharles.Forsyth 			o2 = asmout(p->cond, oplook(p->cond), 1);
95474a4d8c2SCharles.Forsyth 			if(o2) {
95574a4d8c2SCharles.Forsyth 				o1 += 1;
95674a4d8c2SCharles.Forsyth 				if(debug['a'])
95774a4d8c2SCharles.Forsyth 					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n",
95874a4d8c2SCharles.Forsyth 						p->pc, o1, o2, p);
95974a4d8c2SCharles.Forsyth 				LPUT(o1);
96074a4d8c2SCharles.Forsyth 				LPUT(o2);
96174a4d8c2SCharles.Forsyth 				return 1;
96274a4d8c2SCharles.Forsyth 			}
96374a4d8c2SCharles.Forsyth 		}
96474a4d8c2SCharles.Forsyth 		break;
96574a4d8c2SCharles.Forsyth 
96674a4d8c2SCharles.Forsyth 	case 12:	/* movbs r,r */
96774a4d8c2SCharles.Forsyth 		v = 16;
96874a4d8c2SCharles.Forsyth 		if(p->as == AMOVB)
96974a4d8c2SCharles.Forsyth 			v = 24;
97074a4d8c2SCharles.Forsyth 		o1 = OP_SRR(opirr(ASLL), v, p->from.reg, p->to.reg);
97174a4d8c2SCharles.Forsyth 		o2 = OP_SRR(opirr(ASRA), v, p->to.reg, p->to.reg);
97274a4d8c2SCharles.Forsyth 		break;
97374a4d8c2SCharles.Forsyth 
97474a4d8c2SCharles.Forsyth 	case 13:	/* movbu r,r */
97574a4d8c2SCharles.Forsyth 		if(p->as == AMOVBU)
97674a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(AAND), 0xffL, p->from.reg, p->to.reg);
97774a4d8c2SCharles.Forsyth 		else
97874a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(AAND), 0xffffL, p->from.reg, p->to.reg);
97974a4d8c2SCharles.Forsyth 		break;
98074a4d8c2SCharles.Forsyth 
98174a4d8c2SCharles.Forsyth 	case 16:	/* sll $c,[r1],r2 */
98274a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
98374a4d8c2SCharles.Forsyth 		r = p->reg;
98474a4d8c2SCharles.Forsyth 		if(r == NREG)
98574a4d8c2SCharles.Forsyth 			r = p->to.reg;
98674a4d8c2SCharles.Forsyth 
98774a4d8c2SCharles.Forsyth 		/* OP_SRR will use only the low 5 bits of the shift value */
98874a4d8c2SCharles.Forsyth 		if(v >= 32 && vshift(p->as))
98974a4d8c2SCharles.Forsyth 			o1 = OP_SRR(opirr(p->as+ALAST), v-32, r, p->to.reg);
99074a4d8c2SCharles.Forsyth 		else
99174a4d8c2SCharles.Forsyth 			o1 = OP_SRR(opirr(p->as), v, r, p->to.reg);
99274a4d8c2SCharles.Forsyth 		break;
99374a4d8c2SCharles.Forsyth 
99474a4d8c2SCharles.Forsyth 	case 18:	/* jmp [r1],0(r2) */
99574a4d8c2SCharles.Forsyth 		if(aflag)
99674a4d8c2SCharles.Forsyth 			return 0;
99774a4d8c2SCharles.Forsyth 		r = p->reg;
99874a4d8c2SCharles.Forsyth 		if(r == NREG)
99974a4d8c2SCharles.Forsyth 			r = o->param;
100074a4d8c2SCharles.Forsyth 		o1 = OP_RRR(oprrr(p->as), 0, p->to.reg, r);
100174a4d8c2SCharles.Forsyth 		break;
100274a4d8c2SCharles.Forsyth 
100374a4d8c2SCharles.Forsyth 	case 19:	/* mov $lcon,r ==> lu+or */
100474a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
100574a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
100674a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opirr(AOR), v, p->to.reg, p->to.reg);
100774a4d8c2SCharles.Forsyth 		break;
100874a4d8c2SCharles.Forsyth 
100974a4d8c2SCharles.Forsyth 	case 20:	/* mov lohi,r */
101074a4d8c2SCharles.Forsyth 		r = OP(2,0);		/* mfhi */
101174a4d8c2SCharles.Forsyth 		if(p->from.type == D_LO)
101274a4d8c2SCharles.Forsyth 			r = OP(2,2);	/* mflo */
101374a4d8c2SCharles.Forsyth 		o1 = OP_RRR(r, REGZERO, REGZERO, p->to.reg);
101474a4d8c2SCharles.Forsyth 		break;
101574a4d8c2SCharles.Forsyth 
101674a4d8c2SCharles.Forsyth 	case 21:	/* mov r,lohi */
101774a4d8c2SCharles.Forsyth 		r = OP(2,1);		/* mthi */
101874a4d8c2SCharles.Forsyth 		if(p->to.type == D_LO)
101974a4d8c2SCharles.Forsyth 			r = OP(2,3);	/* mtlo */
102074a4d8c2SCharles.Forsyth 		o1 = OP_RRR(r, REGZERO, p->from.reg, REGZERO);
102174a4d8c2SCharles.Forsyth 		break;
102274a4d8c2SCharles.Forsyth 
102374a4d8c2SCharles.Forsyth 	case 22:	/* mul r1,r2 */
102474a4d8c2SCharles.Forsyth 		o1 = OP_RRR(oprrr(p->as), p->from.reg, p->reg, REGZERO);
102574a4d8c2SCharles.Forsyth 		break;
102674a4d8c2SCharles.Forsyth 
102774a4d8c2SCharles.Forsyth 	case 23:	/* add $lcon,r1,r2 ==> lu+or+add */
102874a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
102974a4d8c2SCharles.Forsyth 		if(p->to.reg == REGTMP || p->reg == REGTMP)
103074a4d8c2SCharles.Forsyth 			diag("cant synthesize large constant\n%P", p);
103174a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
103274a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
103374a4d8c2SCharles.Forsyth 		r = p->reg;
103474a4d8c2SCharles.Forsyth 		if(r == NREG)
103574a4d8c2SCharles.Forsyth 			r = p->to.reg;
103674a4d8c2SCharles.Forsyth 		o3 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
103774a4d8c2SCharles.Forsyth 		break;
103874a4d8c2SCharles.Forsyth 
103974a4d8c2SCharles.Forsyth 	case 24:	/* mov $ucon,,r ==> lu r */
104074a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
104174a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
104274a4d8c2SCharles.Forsyth 		break;
104374a4d8c2SCharles.Forsyth 
104474a4d8c2SCharles.Forsyth 	case 25:	/* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
104574a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
104674a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
104774a4d8c2SCharles.Forsyth 		r = p->reg;
104874a4d8c2SCharles.Forsyth 		if(r == NREG)
104974a4d8c2SCharles.Forsyth 			r = p->to.reg;
105074a4d8c2SCharles.Forsyth 		o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
105174a4d8c2SCharles.Forsyth 		break;
105274a4d8c2SCharles.Forsyth 
105374a4d8c2SCharles.Forsyth 	case 26:	/* mov $lsext/auto/oreg,,r2 ==> lu+or+add */
105474a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
105574a4d8c2SCharles.Forsyth 		if(p->to.reg == REGTMP)
105674a4d8c2SCharles.Forsyth 			diag("cant synthesize large constant\n%P", p);
105774a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
105874a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
105974a4d8c2SCharles.Forsyth 		r = p->from.reg;
106074a4d8c2SCharles.Forsyth 		if(r == NREG)
106174a4d8c2SCharles.Forsyth 			r = o->param;
106274a4d8c2SCharles.Forsyth 		o3 = OP_RRR(oprrr(AADDU), REGTMP, r, p->to.reg);
106374a4d8c2SCharles.Forsyth 		break;
106474a4d8c2SCharles.Forsyth 
106574a4d8c2SCharles.Forsyth 	case 27:		/* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
106674a4d8c2SCharles.Forsyth 		r = p->from.reg;
106774a4d8c2SCharles.Forsyth 		if(r == NREG)
106874a4d8c2SCharles.Forsyth 			r = o->param;
106974a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
107074a4d8c2SCharles.Forsyth 		switch(o->size) {
107174a4d8c2SCharles.Forsyth 		case 20:
107274a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
107374a4d8c2SCharles.Forsyth 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
107474a4d8c2SCharles.Forsyth 			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
107574a4d8c2SCharles.Forsyth 			o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg+1);
107674a4d8c2SCharles.Forsyth 			o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg);
107774a4d8c2SCharles.Forsyth 			break;
107874a4d8c2SCharles.Forsyth 		case 16:
107974a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
108074a4d8c2SCharles.Forsyth 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
108174a4d8c2SCharles.Forsyth 			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
108274a4d8c2SCharles.Forsyth 			o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg);
108374a4d8c2SCharles.Forsyth 			break;
108474a4d8c2SCharles.Forsyth 		case 8:
108574a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg+1);
108674a4d8c2SCharles.Forsyth 			o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg);
108774a4d8c2SCharles.Forsyth 			break;
108874a4d8c2SCharles.Forsyth 		case 4:
108974a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg);
109074a4d8c2SCharles.Forsyth 			break;
109174a4d8c2SCharles.Forsyth 		}
109274a4d8c2SCharles.Forsyth 		break;
109374a4d8c2SCharles.Forsyth 
109474a4d8c2SCharles.Forsyth 	case 28:		/* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
109574a4d8c2SCharles.Forsyth 		r = p->to.reg;
109674a4d8c2SCharles.Forsyth 		if(r == NREG)
109774a4d8c2SCharles.Forsyth 			r = o->param;
109874a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
109974a4d8c2SCharles.Forsyth 		switch(o->size) {
110074a4d8c2SCharles.Forsyth 		case 20:
110174a4d8c2SCharles.Forsyth 			if(r == REGTMP)
110274a4d8c2SCharles.Forsyth 				diag("cant synthesize large constant\n%P", p);
110374a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
110474a4d8c2SCharles.Forsyth 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
110574a4d8c2SCharles.Forsyth 			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
110674a4d8c2SCharles.Forsyth 			o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg+1);
110774a4d8c2SCharles.Forsyth 			o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg);
110874a4d8c2SCharles.Forsyth 			break;
110974a4d8c2SCharles.Forsyth 		case 16:
111074a4d8c2SCharles.Forsyth 			if(r == REGTMP)
111174a4d8c2SCharles.Forsyth 				diag("cant synthesize large constant\n%P", p);
111274a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
111374a4d8c2SCharles.Forsyth 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
111474a4d8c2SCharles.Forsyth 			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
111574a4d8c2SCharles.Forsyth 			o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg);
111674a4d8c2SCharles.Forsyth 			break;
111774a4d8c2SCharles.Forsyth 		case 8:
111874a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg+1);
111974a4d8c2SCharles.Forsyth 			o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg);
112074a4d8c2SCharles.Forsyth 			break;
112174a4d8c2SCharles.Forsyth 		case 4:
112274a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg);
112374a4d8c2SCharles.Forsyth 			break;
112474a4d8c2SCharles.Forsyth 		}
112574a4d8c2SCharles.Forsyth 		break;
112674a4d8c2SCharles.Forsyth 
112774a4d8c2SCharles.Forsyth 	case 30:	/* movw r,fr */
112874a4d8c2SCharles.Forsyth 		r = SP(2,1)|(4<<21);		/* mtc1 */
112974a4d8c2SCharles.Forsyth 		o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
113074a4d8c2SCharles.Forsyth 		break;
113174a4d8c2SCharles.Forsyth 
113274a4d8c2SCharles.Forsyth 	case 31:	/* movw fr,r */
113374a4d8c2SCharles.Forsyth 		r = SP(2,1)|(0<<21);		/* mfc1 */
113474a4d8c2SCharles.Forsyth 		o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
113574a4d8c2SCharles.Forsyth 		break;
113674a4d8c2SCharles.Forsyth 
113774a4d8c2SCharles.Forsyth 	case 32:	/* fadd fr1,[fr2],fr3 */
113874a4d8c2SCharles.Forsyth 		r = p->reg;
113974a4d8c2SCharles.Forsyth 		if(r == NREG)
114074a4d8c2SCharles.Forsyth 			o1 = OP_FRRR(oprrr(p->as), p->from.reg, p->to.reg, p->to.reg);
114174a4d8c2SCharles.Forsyth 		else
114274a4d8c2SCharles.Forsyth 			o1 = OP_FRRR(oprrr(p->as), p->from.reg, r, p->to.reg);
114374a4d8c2SCharles.Forsyth 		break;
114474a4d8c2SCharles.Forsyth 
114574a4d8c2SCharles.Forsyth 	case 33:	/* fabs fr1,fr3 */
114674a4d8c2SCharles.Forsyth 		o1 = OP_FRRR(oprrr(p->as), 0, p->from.reg, p->to.reg);
114774a4d8c2SCharles.Forsyth 		break;
114874a4d8c2SCharles.Forsyth 
114974a4d8c2SCharles.Forsyth 	case 34:	/* mov $con,fr ==> or/add $i,r,r2 */
115074a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
115174a4d8c2SCharles.Forsyth 		r = AADDU;
115274a4d8c2SCharles.Forsyth 		if(o->a1 == C_ANDCON)
115374a4d8c2SCharles.Forsyth 			r = AOR;
115474a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(r), v, 0, REGTMP);
115574a4d8c2SCharles.Forsyth 		o2 = OP_RRR(SP(2,1)|(4<<21), REGTMP, 0, p->to.reg);	/* mtc1 */
115674a4d8c2SCharles.Forsyth 		break;
115774a4d8c2SCharles.Forsyth 
115874a4d8c2SCharles.Forsyth 	case 35:	/* mov r,lext/luto/oreg ==> sw o(r) */
115974a4d8c2SCharles.Forsyth 		/*
116074a4d8c2SCharles.Forsyth 		 * the lowbits of the constant cannot
116174a4d8c2SCharles.Forsyth 		 * be moved into the offset of the load
116274a4d8c2SCharles.Forsyth 		 * because the mips 4000 in 64-bit mode
116374a4d8c2SCharles.Forsyth 		 * does a 64-bit add and it will screw up.
116474a4d8c2SCharles.Forsyth 		 */
116574a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
116674a4d8c2SCharles.Forsyth 		r = p->to.reg;
116774a4d8c2SCharles.Forsyth 		if(r == NREG)
116874a4d8c2SCharles.Forsyth 			r = o->param;
116974a4d8c2SCharles.Forsyth 		if(r == REGTMP)
117074a4d8c2SCharles.Forsyth 			diag("cant synthesize large constant\n%P", p);
117174a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
117274a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
117374a4d8c2SCharles.Forsyth 		o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
117474a4d8c2SCharles.Forsyth 		o4 = OP_IRR(opirr(p->as), 0, REGTMP, p->from.reg);
117574a4d8c2SCharles.Forsyth 		break;
117674a4d8c2SCharles.Forsyth 
117774a4d8c2SCharles.Forsyth 	case 36:	/* mov lext/lauto/lreg,r ==> lw o(r30) */
117874a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
117974a4d8c2SCharles.Forsyth 		r = p->from.reg;
118074a4d8c2SCharles.Forsyth 		if(r == NREG)
118174a4d8c2SCharles.Forsyth 			r = o->param;
118274a4d8c2SCharles.Forsyth 		if(r == REGTMP)
118374a4d8c2SCharles.Forsyth 			diag("cant synthesize large constant\n%P", p);
118474a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
118574a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
118674a4d8c2SCharles.Forsyth 		o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
118774a4d8c2SCharles.Forsyth 		o4 = OP_IRR(opirr(p->as+ALAST), 0, REGTMP, p->to.reg);
118874a4d8c2SCharles.Forsyth 		break;
118974a4d8c2SCharles.Forsyth 
119074a4d8c2SCharles.Forsyth 	case 37:	/* movw r,mr */
119174a4d8c2SCharles.Forsyth 		r = SP(2,0)|(4<<21);		/* mtc0 */
119274a4d8c2SCharles.Forsyth 		if(p->as == AMOVV)
119374a4d8c2SCharles.Forsyth 			r = SP(2,0)|(5<<21);	/* dmtc0 */
119474a4d8c2SCharles.Forsyth 		o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
119574a4d8c2SCharles.Forsyth 		break;
119674a4d8c2SCharles.Forsyth 
119774a4d8c2SCharles.Forsyth 	case 38:	/* movw mr,r */
119874a4d8c2SCharles.Forsyth 		r = SP(2,0)|(0<<21);		/* mfc0 */
119974a4d8c2SCharles.Forsyth 		if(p->as == AMOVV)
120074a4d8c2SCharles.Forsyth 			r = SP(2,0)|(1<<21);	/* dmfc0 */
120174a4d8c2SCharles.Forsyth 		o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
120274a4d8c2SCharles.Forsyth 		break;
120374a4d8c2SCharles.Forsyth 
120474a4d8c2SCharles.Forsyth 	case 39:	/* rfe ==> jmp+rfe */
120574a4d8c2SCharles.Forsyth 		if(aflag)
120674a4d8c2SCharles.Forsyth 			return 0;
120774a4d8c2SCharles.Forsyth 		o1 = OP_RRR(oprrr(AJMP), 0, p->to.reg, REGZERO);
120874a4d8c2SCharles.Forsyth 		o2 = oprrr(p->as);
120974a4d8c2SCharles.Forsyth 		break;
121074a4d8c2SCharles.Forsyth 
121174a4d8c2SCharles.Forsyth 	case 40:	/* word */
121274a4d8c2SCharles.Forsyth 		if(aflag)
121374a4d8c2SCharles.Forsyth 			return 0;
121474a4d8c2SCharles.Forsyth 		o1 = regoff(&p->to);
121574a4d8c2SCharles.Forsyth 		break;
121674a4d8c2SCharles.Forsyth 
121774a4d8c2SCharles.Forsyth 	case 41:	/* movw r,fcr */
121874a4d8c2SCharles.Forsyth 		o1 = OP_RRR(SP(2,1)|(2<<21), REGZERO, 0, p->to.reg); 	/* mfcc1 */
121974a4d8c2SCharles.Forsyth 		o2 = OP_RRR(SP(2,1)|(6<<21), p->from.reg, 0, p->to.reg);/* mtcc1 */
122074a4d8c2SCharles.Forsyth 		break;
122174a4d8c2SCharles.Forsyth 
122274a4d8c2SCharles.Forsyth 	case 42:	/* movw fcr,r */
122374a4d8c2SCharles.Forsyth 		o1 = OP_RRR(SP(2,1)|(2<<21), p->to.reg, 0, p->from.reg);/* mfcc1 */
122474a4d8c2SCharles.Forsyth 		break;
122574a4d8c2SCharles.Forsyth 
122674a4d8c2SCharles.Forsyth 	case 45:	/* case r */
122774a4d8c2SCharles.Forsyth 		if(p->link == P)
122874a4d8c2SCharles.Forsyth 			v = p->pc+28;
122974a4d8c2SCharles.Forsyth 		else
123074a4d8c2SCharles.Forsyth 			v = p->link->pc;
123174a4d8c2SCharles.Forsyth 		if(v & (1<<15))
123274a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(ALAST), (v>>16)+1, REGZERO, REGTMP);
123374a4d8c2SCharles.Forsyth 		else
123474a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
123574a4d8c2SCharles.Forsyth 		o2 = OP_SRR(opirr(ASLL), 2, p->from.reg, p->from.reg);
123674a4d8c2SCharles.Forsyth 		o3 = OP_RRR(oprrr(AADD), p->from.reg, REGTMP, REGTMP);
123774a4d8c2SCharles.Forsyth 		o4 = OP_IRR(opirr(AMOVW+ALAST), v, REGTMP, REGTMP);
123874a4d8c2SCharles.Forsyth 		o5 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
123974a4d8c2SCharles.Forsyth 		o6 = OP_RRR(oprrr(AJMP), 0, REGTMP, REGZERO);
124074a4d8c2SCharles.Forsyth 		o7 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
124174a4d8c2SCharles.Forsyth 		break;
124274a4d8c2SCharles.Forsyth 
124374a4d8c2SCharles.Forsyth 	case 46:	/* bcase $con,lbra */
124474a4d8c2SCharles.Forsyth 		if(p->cond == P)
124574a4d8c2SCharles.Forsyth 			v = p->pc;
124674a4d8c2SCharles.Forsyth 		else
124774a4d8c2SCharles.Forsyth 			v = p->cond->pc;
124874a4d8c2SCharles.Forsyth 		o1 = v;
124974a4d8c2SCharles.Forsyth 		break;
125074a4d8c2SCharles.Forsyth 	}
125174a4d8c2SCharles.Forsyth 	if(aflag)
125274a4d8c2SCharles.Forsyth 		return o1;
125374a4d8c2SCharles.Forsyth 	v = p->pc;
125474a4d8c2SCharles.Forsyth 	switch(o->size) {
125574a4d8c2SCharles.Forsyth 	default:
125674a4d8c2SCharles.Forsyth 		if(debug['a'])
125774a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
125874a4d8c2SCharles.Forsyth 		break;
125974a4d8c2SCharles.Forsyth 	case 4:
126074a4d8c2SCharles.Forsyth 		if(debug['a'])
126174a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
126274a4d8c2SCharles.Forsyth 		LPUT(o1);
126374a4d8c2SCharles.Forsyth 		break;
126474a4d8c2SCharles.Forsyth 	case 8:
126574a4d8c2SCharles.Forsyth 		if(debug['a'])
126674a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
126774a4d8c2SCharles.Forsyth 		LPUT(o1);
126874a4d8c2SCharles.Forsyth 		LPUT(o2);
126974a4d8c2SCharles.Forsyth 		break;
127074a4d8c2SCharles.Forsyth 	case 12:
127174a4d8c2SCharles.Forsyth 		if(debug['a'])
127274a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
127374a4d8c2SCharles.Forsyth 		LPUT(o1);
127474a4d8c2SCharles.Forsyth 		LPUT(o2);
127574a4d8c2SCharles.Forsyth 		LPUT(o3);
127674a4d8c2SCharles.Forsyth 		break;
127774a4d8c2SCharles.Forsyth 	case 16:
127874a4d8c2SCharles.Forsyth 		if(debug['a'])
127974a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
128074a4d8c2SCharles.Forsyth 				v, o1, o2, o3, o4, p);
128174a4d8c2SCharles.Forsyth 		LPUT(o1);
128274a4d8c2SCharles.Forsyth 		LPUT(o2);
128374a4d8c2SCharles.Forsyth 		LPUT(o3);
128474a4d8c2SCharles.Forsyth 		LPUT(o4);
128574a4d8c2SCharles.Forsyth 		break;
128674a4d8c2SCharles.Forsyth 	case 20:
128774a4d8c2SCharles.Forsyth 		if(debug['a'])
128874a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
128974a4d8c2SCharles.Forsyth 				v, o1, o2, o3, o4, o5, p);
129074a4d8c2SCharles.Forsyth 		LPUT(o1);
129174a4d8c2SCharles.Forsyth 		LPUT(o2);
129274a4d8c2SCharles.Forsyth 		LPUT(o3);
129374a4d8c2SCharles.Forsyth 		LPUT(o4);
129474a4d8c2SCharles.Forsyth 		LPUT(o5);
129574a4d8c2SCharles.Forsyth 		break;
129674a4d8c2SCharles.Forsyth 
129774a4d8c2SCharles.Forsyth 	case 28:
129874a4d8c2SCharles.Forsyth 		if(debug['a'])
129974a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
130074a4d8c2SCharles.Forsyth 				v, o1, o2, o3, o4, o5, o6, o7, p);
130174a4d8c2SCharles.Forsyth 		LPUT(o1);
130274a4d8c2SCharles.Forsyth 		LPUT(o2);
130374a4d8c2SCharles.Forsyth 		LPUT(o3);
130474a4d8c2SCharles.Forsyth 		LPUT(o4);
130574a4d8c2SCharles.Forsyth 		LPUT(o5);
130674a4d8c2SCharles.Forsyth 		LPUT(o6);
130774a4d8c2SCharles.Forsyth 		LPUT(o7);
130874a4d8c2SCharles.Forsyth 		break;
130974a4d8c2SCharles.Forsyth 	}
131074a4d8c2SCharles.Forsyth 	return 0;
131174a4d8c2SCharles.Forsyth }
131274a4d8c2SCharles.Forsyth 
131374a4d8c2SCharles.Forsyth int
isnop(Prog * p)131474a4d8c2SCharles.Forsyth isnop(Prog *p)
131574a4d8c2SCharles.Forsyth {
131674a4d8c2SCharles.Forsyth 	if(p->as != ANOR)
131774a4d8c2SCharles.Forsyth 		return 0;
131874a4d8c2SCharles.Forsyth 	if(p->reg != REGZERO && p->reg != NREG)
131974a4d8c2SCharles.Forsyth 		return 0;
132074a4d8c2SCharles.Forsyth 	if(p->from.type != D_REG || p->from.reg != REGZERO)
132174a4d8c2SCharles.Forsyth 		return 0;
132274a4d8c2SCharles.Forsyth 	if(p->to.type != D_REG || p->to.reg != REGZERO)
132374a4d8c2SCharles.Forsyth 		return 0;
132474a4d8c2SCharles.Forsyth 	return 1;
132574a4d8c2SCharles.Forsyth }
132674a4d8c2SCharles.Forsyth 
132774a4d8c2SCharles.Forsyth long
oprrr(int a)132874a4d8c2SCharles.Forsyth oprrr(int a)
132974a4d8c2SCharles.Forsyth {
133074a4d8c2SCharles.Forsyth 	switch(a) {
133174a4d8c2SCharles.Forsyth 	case AADD:	return OP(4,0);
133274a4d8c2SCharles.Forsyth 	case AADDU:	return OP(4,1);
133374a4d8c2SCharles.Forsyth 	case ASGT:	return OP(5,2);
133474a4d8c2SCharles.Forsyth 	case ASGTU:	return OP(5,3);
133574a4d8c2SCharles.Forsyth 	case AAND:	return OP(4,4);
133674a4d8c2SCharles.Forsyth 	case AOR:	return OP(4,5);
133774a4d8c2SCharles.Forsyth 	case AXOR:	return OP(4,6);
133874a4d8c2SCharles.Forsyth 	case ASUB:	return OP(4,2);
133974a4d8c2SCharles.Forsyth 	case ASUBU:	return OP(4,3);
134074a4d8c2SCharles.Forsyth 	case ANOR:	return OP(4,7);
134174a4d8c2SCharles.Forsyth 	case ASLL:	return OP(0,4);
134274a4d8c2SCharles.Forsyth 	case ASRL:	return OP(0,6);
134374a4d8c2SCharles.Forsyth 	case ASRA:	return OP(0,7);
134474a4d8c2SCharles.Forsyth 
134574a4d8c2SCharles.Forsyth 	case AREM:
134674a4d8c2SCharles.Forsyth 	case ADIV:	return OP(3,2);
134774a4d8c2SCharles.Forsyth 	case AREMU:
134874a4d8c2SCharles.Forsyth 	case ADIVU:	return OP(3,3);
134974a4d8c2SCharles.Forsyth 	case AMUL:	return OP(3,0);
135074a4d8c2SCharles.Forsyth 	case AMULU:	return OP(3,1);
135174a4d8c2SCharles.Forsyth 
135274a4d8c2SCharles.Forsyth 	case AJMP:	return OP(1,0);
135374a4d8c2SCharles.Forsyth 	case AJAL:	return OP(1,1);
135474a4d8c2SCharles.Forsyth 
135574a4d8c2SCharles.Forsyth 	case ABREAK:	return OP(1,5);
135674a4d8c2SCharles.Forsyth 	case ASYSCALL:	return OP(1,4);
135774a4d8c2SCharles.Forsyth 	case ATLBP:	return MMU(1,0);
135874a4d8c2SCharles.Forsyth 	case ATLBR:	return MMU(0,1);
135974a4d8c2SCharles.Forsyth 	case ATLBWI:	return MMU(0,2);
136074a4d8c2SCharles.Forsyth 	case ATLBWR:	return MMU(0,6);
136174a4d8c2SCharles.Forsyth 	case ARFE:	return MMU(2,0);
136274a4d8c2SCharles.Forsyth 
136374a4d8c2SCharles.Forsyth 	case ADIVF:	return FPF(0,3);
136474a4d8c2SCharles.Forsyth 	case ADIVD:	return FPD(0,3);
136574a4d8c2SCharles.Forsyth 	case AMULF:	return FPF(0,2);
136674a4d8c2SCharles.Forsyth 	case AMULD:	return FPD(0,2);
136774a4d8c2SCharles.Forsyth 	case ASUBF:	return FPF(0,1);
136874a4d8c2SCharles.Forsyth 	case ASUBD:	return FPD(0,1);
136974a4d8c2SCharles.Forsyth 	case AADDF:	return FPF(0,0);
137074a4d8c2SCharles.Forsyth 	case AADDD:	return FPD(0,0);
137174a4d8c2SCharles.Forsyth 
137274a4d8c2SCharles.Forsyth 	case AMOVFW:	return FPF(4,4);
137374a4d8c2SCharles.Forsyth 	case AMOVDW:	return FPD(4,4);
137474a4d8c2SCharles.Forsyth 	case AMOVWF:	return FPW(4,0);
137574a4d8c2SCharles.Forsyth 	case AMOVDF:	return FPD(4,0);
137674a4d8c2SCharles.Forsyth 	case AMOVWD:	return FPW(4,1);
137774a4d8c2SCharles.Forsyth 	case AMOVFD:	return FPF(4,1);
137874a4d8c2SCharles.Forsyth 	case AABSF:	return FPF(0,5);
137974a4d8c2SCharles.Forsyth 	case AABSD:	return FPD(0,5);
138074a4d8c2SCharles.Forsyth 	case AMOVF:	return FPF(0,6);
138174a4d8c2SCharles.Forsyth 	case AMOVD:	return FPD(0,6);
138274a4d8c2SCharles.Forsyth 	case ANEGF:	return FPF(0,7);
138374a4d8c2SCharles.Forsyth 	case ANEGD:	return FPD(0,7);
138474a4d8c2SCharles.Forsyth 
138574a4d8c2SCharles.Forsyth 	case ACMPEQF:	return FPF(6,2);
138674a4d8c2SCharles.Forsyth 	case ACMPEQD:	return FPD(6,2);
138774a4d8c2SCharles.Forsyth 	case ACMPGTF:	return FPF(7,4);
138874a4d8c2SCharles.Forsyth 	case ACMPGTD:	return FPD(7,4);
138974a4d8c2SCharles.Forsyth 	case ACMPGEF:	return FPF(7,6);
139074a4d8c2SCharles.Forsyth 	case ACMPGED:	return FPD(7,6);
139174a4d8c2SCharles.Forsyth 
139274a4d8c2SCharles.Forsyth 	case ADIVV:	return OP(3,6);
139374a4d8c2SCharles.Forsyth 	case ADIVVU:	return OP(3,7);
139474a4d8c2SCharles.Forsyth 	case AADDV:	return OP(5,4);
139574a4d8c2SCharles.Forsyth 	case AADDVU:	return OP(5,5);
139674a4d8c2SCharles.Forsyth 	}
139774a4d8c2SCharles.Forsyth 	diag("bad rrr %d", a);
139874a4d8c2SCharles.Forsyth 	return 0;
139974a4d8c2SCharles.Forsyth }
140074a4d8c2SCharles.Forsyth 
140174a4d8c2SCharles.Forsyth long
opirr(int a)140274a4d8c2SCharles.Forsyth opirr(int a)
140374a4d8c2SCharles.Forsyth {
140474a4d8c2SCharles.Forsyth 	switch(a) {
140574a4d8c2SCharles.Forsyth 	case AADD:	return SP(1,0);
140674a4d8c2SCharles.Forsyth 	case AADDU:	return SP(1,1);
140774a4d8c2SCharles.Forsyth 	case ASGT:	return SP(1,2);
140874a4d8c2SCharles.Forsyth 	case ASGTU:	return SP(1,3);
140974a4d8c2SCharles.Forsyth 	case AAND:	return SP(1,4);
141074a4d8c2SCharles.Forsyth 	case AOR:	return SP(1,5);
141174a4d8c2SCharles.Forsyth 	case AXOR:	return SP(1,6);
141274a4d8c2SCharles.Forsyth 	case ALAST:	return SP(1,7);
141374a4d8c2SCharles.Forsyth 	case ASLL:	return OP(0,0);
141474a4d8c2SCharles.Forsyth 	case ASRL:	return OP(0,2);
141574a4d8c2SCharles.Forsyth 	case ASRA:	return OP(0,3);
141674a4d8c2SCharles.Forsyth 
141774a4d8c2SCharles.Forsyth 	case AJMP:	return SP(0,2);
141874a4d8c2SCharles.Forsyth 	case AJAL:	return SP(0,3);
141974a4d8c2SCharles.Forsyth 	case ABEQ:	return SP(0,4);
142074a4d8c2SCharles.Forsyth 	case ABNE:	return SP(0,5);
142174a4d8c2SCharles.Forsyth 
142274a4d8c2SCharles.Forsyth 	case ABGEZ:	return SP(0,1)|BCOND(0,1);
142374a4d8c2SCharles.Forsyth 	case ABGEZAL:	return SP(0,1)|BCOND(2,1);
142474a4d8c2SCharles.Forsyth 	case ABGTZ:	return SP(0,7);
142574a4d8c2SCharles.Forsyth 	case ABLEZ:	return SP(0,6);
142674a4d8c2SCharles.Forsyth 	case ABLTZ:	return SP(0,1)|BCOND(0,0);
142774a4d8c2SCharles.Forsyth 	case ABLTZAL:	return SP(0,1)|BCOND(2,0);
142874a4d8c2SCharles.Forsyth 
142974a4d8c2SCharles.Forsyth 	case ABFPT:	return SP(2,1)|(257<<16);
143074a4d8c2SCharles.Forsyth 	case ABFPF:	return SP(2,1)|(256<<16);
143174a4d8c2SCharles.Forsyth 
143274a4d8c2SCharles.Forsyth 	case AMOVB:
143374a4d8c2SCharles.Forsyth 	case AMOVBU:	return SP(5,0);
143474a4d8c2SCharles.Forsyth 	case AMOVH:
143574a4d8c2SCharles.Forsyth 	case AMOVHU:	return SP(5,1);
143674a4d8c2SCharles.Forsyth 	case AMOVW:	return SP(5,3);
143774a4d8c2SCharles.Forsyth 	case AMOVV:	return SP(7,7);
143874a4d8c2SCharles.Forsyth 	case AMOVF:	return SP(7,1);
143974a4d8c2SCharles.Forsyth 	case AMOVWL:	return SP(5,2);
144074a4d8c2SCharles.Forsyth 	case AMOVWR:	return SP(5,6);
144174a4d8c2SCharles.Forsyth 	case AMOVVL:	return SP(5,4);
144274a4d8c2SCharles.Forsyth 	case AMOVVR:	return SP(5,5);
144374a4d8c2SCharles.Forsyth 
144474a4d8c2SCharles.Forsyth 	case ABREAK:	return SP(5,7);
144574a4d8c2SCharles.Forsyth 
144674a4d8c2SCharles.Forsyth 	case AMOVWL+ALAST:	return SP(4,2);
144774a4d8c2SCharles.Forsyth 	case AMOVWR+ALAST:	return SP(4,6);
144874a4d8c2SCharles.Forsyth 	case AMOVVL+ALAST:	return SP(3,2);
144974a4d8c2SCharles.Forsyth 	case AMOVVR+ALAST:	return SP(3,3);
145074a4d8c2SCharles.Forsyth 	case AMOVB+ALAST:	return SP(4,0);
145174a4d8c2SCharles.Forsyth 	case AMOVBU+ALAST:	return SP(4,4);
145274a4d8c2SCharles.Forsyth 	case AMOVH+ALAST:	return SP(4,1);
145374a4d8c2SCharles.Forsyth 	case AMOVHU+ALAST:	return SP(4,5);
145474a4d8c2SCharles.Forsyth 	case AMOVW+ALAST:	return SP(4,3);
145574a4d8c2SCharles.Forsyth 	case AMOVV+ALAST:	return SP(6,7);
145674a4d8c2SCharles.Forsyth 	case AMOVF+ALAST:	return SP(6,1);
145774a4d8c2SCharles.Forsyth 
145874a4d8c2SCharles.Forsyth 	case ASLLV:		return OP(7,0);
145974a4d8c2SCharles.Forsyth 	case ASRLV:		return OP(7,2);
146074a4d8c2SCharles.Forsyth 	case ASRAV:		return OP(7,3);
146174a4d8c2SCharles.Forsyth 	case ASLLV+ALAST:	return OP(7,4);
146274a4d8c2SCharles.Forsyth 	case ASRLV+ALAST:	return OP(7,6);
146374a4d8c2SCharles.Forsyth 	case ASRAV+ALAST:	return OP(7,7);
146474a4d8c2SCharles.Forsyth 
146574a4d8c2SCharles.Forsyth 	case AADDV:		return SP(3,0);
146674a4d8c2SCharles.Forsyth 	case AADDVU:		return SP(3,1);
146774a4d8c2SCharles.Forsyth 	}
146874a4d8c2SCharles.Forsyth 	diag("bad irr %d", a);
146974a4d8c2SCharles.Forsyth abort();
147074a4d8c2SCharles.Forsyth 	return 0;
147174a4d8c2SCharles.Forsyth }
147274a4d8c2SCharles.Forsyth 
147374a4d8c2SCharles.Forsyth int
vshift(int a)147474a4d8c2SCharles.Forsyth vshift(int a)
147574a4d8c2SCharles.Forsyth {
147674a4d8c2SCharles.Forsyth 	switch(a){
147774a4d8c2SCharles.Forsyth 	case ASLLV:		return 1;
147874a4d8c2SCharles.Forsyth 	case ASRLV:		return 1;
147974a4d8c2SCharles.Forsyth 	case ASRAV:		return 1;
148074a4d8c2SCharles.Forsyth 	}
148174a4d8c2SCharles.Forsyth 	return 0;
148274a4d8c2SCharles.Forsyth }
1483