xref: /plan9/sys/src/cmd/vl/pass.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include	"l.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier void
43e12c5d1SDavid du Colombier dodata(void)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	int i, t;
73e12c5d1SDavid du Colombier 	Sym *s;
83e12c5d1SDavid du Colombier 	Prog *p, *p1;
93e12c5d1SDavid du Colombier 	long orig, orig1, v;
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier 	if(debug['v'])
123e12c5d1SDavid du Colombier 		Bprint(&bso, "%5.2f dodata\n", cputime());
133e12c5d1SDavid du Colombier 	Bflush(&bso);
143e12c5d1SDavid du Colombier 	for(p = datap; p != P; p = p->link) {
153e12c5d1SDavid du Colombier 		s = p->from.sym;
16*219b2ee8SDavid du Colombier 		if(p->as == ADYNT || p->as == AINIT)
17*219b2ee8SDavid du Colombier 			s->value = dtype;
183e12c5d1SDavid du Colombier 		if(s->type == SBSS)
193e12c5d1SDavid du Colombier 			s->type = SDATA;
203e12c5d1SDavid du Colombier 		if(s->type != SDATA)
213e12c5d1SDavid du Colombier 			diag("initialize non-data (%d): %s\n%P\n",
223e12c5d1SDavid du Colombier 				s->type, s->name, p);
233e12c5d1SDavid du Colombier 		v = p->from.offset + p->reg;
243e12c5d1SDavid du Colombier 		if(v > s->value)
253e12c5d1SDavid du Colombier 			diag("initialize bounds (%ld): %s\n%P\n",
263e12c5d1SDavid du Colombier 				s->value, s->name, p);
273e12c5d1SDavid du Colombier 	}
283e12c5d1SDavid du Colombier 
293e12c5d1SDavid du Colombier 	/*
303e12c5d1SDavid du Colombier 	 * pass 1
313e12c5d1SDavid du Colombier 	 *	assign 'small' variables to data segment
323e12c5d1SDavid du Colombier 	 *	(rational is that data segment is more easily
333e12c5d1SDavid du Colombier 	 *	 addressed through offset on R30)
343e12c5d1SDavid du Colombier 	 */
353e12c5d1SDavid du Colombier 	orig = 0;
363e12c5d1SDavid du Colombier 	for(i=0; i<NHASH; i++)
373e12c5d1SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
383e12c5d1SDavid du Colombier 		t = s->type;
393e12c5d1SDavid du Colombier 		if(t != SDATA && t != SBSS)
403e12c5d1SDavid du Colombier 			continue;
413e12c5d1SDavid du Colombier 		v = s->value;
423e12c5d1SDavid du Colombier 		if(v == 0) {
433e12c5d1SDavid du Colombier 			diag("%s: no size\n", s->name);
443e12c5d1SDavid du Colombier 			v = 1;
453e12c5d1SDavid du Colombier 		}
463e12c5d1SDavid du Colombier 		while(v & 3)
473e12c5d1SDavid du Colombier 			v++;
483e12c5d1SDavid du Colombier 		s->value = v;
493e12c5d1SDavid du Colombier 		if(v > MINSIZ)
503e12c5d1SDavid du Colombier 			continue;
513e12c5d1SDavid du Colombier 		s->value = orig;
523e12c5d1SDavid du Colombier 		orig += v;
533e12c5d1SDavid du Colombier 		s->type = SDATA1;
543e12c5d1SDavid du Colombier 	}
553e12c5d1SDavid du Colombier 	orig1 = orig;
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier 	/*
583e12c5d1SDavid du Colombier 	 * pass 2
593e12c5d1SDavid du Colombier 	 *	assign 'data' variables to data segment
603e12c5d1SDavid du Colombier 	 */
613e12c5d1SDavid du Colombier 	for(i=0; i<NHASH; i++)
623e12c5d1SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
633e12c5d1SDavid du Colombier 		t = s->type;
643e12c5d1SDavid du Colombier 		if(t != SDATA) {
653e12c5d1SDavid du Colombier 			if(t == SDATA1)
663e12c5d1SDavid du Colombier 				s->type = SDATA;
673e12c5d1SDavid du Colombier 			continue;
683e12c5d1SDavid du Colombier 		}
693e12c5d1SDavid du Colombier 		v = s->value;
703e12c5d1SDavid du Colombier 		s->value = orig;
713e12c5d1SDavid du Colombier 		orig += v;
723e12c5d1SDavid du Colombier 		s->type = SDATA1;
733e12c5d1SDavid du Colombier 	}
743e12c5d1SDavid du Colombier 
753e12c5d1SDavid du Colombier 	while(orig & 7)
763e12c5d1SDavid du Colombier 		orig++;
773e12c5d1SDavid du Colombier 	datsize = orig;
783e12c5d1SDavid du Colombier 
793e12c5d1SDavid du Colombier 	/*
803e12c5d1SDavid du Colombier 	 * pass 3
813e12c5d1SDavid du Colombier 	 *	everything else to bss segment
823e12c5d1SDavid du Colombier 	 */
833e12c5d1SDavid du Colombier 	for(i=0; i<NHASH; i++)
843e12c5d1SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
853e12c5d1SDavid du Colombier 		if(s->type != SBSS)
863e12c5d1SDavid du Colombier 			continue;
873e12c5d1SDavid du Colombier 		v = s->value;
883e12c5d1SDavid du Colombier 		s->value = orig;
893e12c5d1SDavid du Colombier 		orig += v;
903e12c5d1SDavid du Colombier 	}
913e12c5d1SDavid du Colombier 	while(orig & 7)
923e12c5d1SDavid du Colombier 		orig++;
933e12c5d1SDavid du Colombier 	bsssize = orig-datsize;
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier 	/*
963e12c5d1SDavid du Colombier 	 * pass 4
973e12c5d1SDavid du Colombier 	 *	add literals to all large values.
983e12c5d1SDavid du Colombier 	 *	at this time:
993e12c5d1SDavid du Colombier 	 *		small data is allocated DATA
1003e12c5d1SDavid du Colombier 	 *		large data is allocated DATA1
1013e12c5d1SDavid du Colombier 	 *		large bss is allocated BSS
1023e12c5d1SDavid du Colombier 	 *	the new literals are loaded between
1033e12c5d1SDavid du Colombier 	 *	small data and large data.
1043e12c5d1SDavid du Colombier 	 */
1053e12c5d1SDavid du Colombier 	orig = 0;
1063e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
1073e12c5d1SDavid du Colombier 		if(p->as != AMOVW)
1083e12c5d1SDavid du Colombier 			continue;
1093e12c5d1SDavid du Colombier 		if(p->from.type != D_CONST)
1103e12c5d1SDavid du Colombier 			continue;
1113e12c5d1SDavid du Colombier 		if(s = p->from.sym) {
1123e12c5d1SDavid du Colombier 			t = s->type;
1133e12c5d1SDavid du Colombier 			if(t != SDATA && t != SDATA1 && t != SBSS)
1143e12c5d1SDavid du Colombier 				continue;
1153e12c5d1SDavid du Colombier 			t = p->from.name;
1163e12c5d1SDavid du Colombier 			if(t != D_EXTERN && t != D_STATIC)
1173e12c5d1SDavid du Colombier 				continue;
1183e12c5d1SDavid du Colombier 			v = s->value + p->from.offset;
1193e12c5d1SDavid du Colombier 			if(v >= 0 && v <= 0xffff)
1203e12c5d1SDavid du Colombier 				continue;
1213e12c5d1SDavid du Colombier 			if(!strcmp(s->name, "setR30"))
1223e12c5d1SDavid du Colombier 				continue;
1233e12c5d1SDavid du Colombier 			/* size should be 19 max */
124bd389b36SDavid du Colombier 			if(strlen(s->name) >= 10)	/* has loader address */
125bd389b36SDavid du Colombier 				sprint(literal, "$%lux.%lux", (long)s, p->from.offset);
126bd389b36SDavid du Colombier 			else
127bd389b36SDavid du Colombier 				sprint(literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
1283e12c5d1SDavid du Colombier 		} else {
1293e12c5d1SDavid du Colombier 			if(p->from.name != D_NONE)
1303e12c5d1SDavid du Colombier 				continue;
1313e12c5d1SDavid du Colombier 			if(p->from.reg != NREG)
1323e12c5d1SDavid du Colombier 				continue;
1333e12c5d1SDavid du Colombier 			v = p->from.offset;
1343e12c5d1SDavid du Colombier 			if(v >= -0x7fff && v <= 0xffff)
1353e12c5d1SDavid du Colombier 				continue;
1363e12c5d1SDavid du Colombier 			if(!(v & 0xffff))
1373e12c5d1SDavid du Colombier 				continue;
1383e12c5d1SDavid du Colombier 			/* size should be 9 max */
1393e12c5d1SDavid du Colombier 			sprint(literal, "$%lux", v);
1403e12c5d1SDavid du Colombier 		}
1413e12c5d1SDavid du Colombier 		s = lookup(literal, 0);
1423e12c5d1SDavid du Colombier 		if(s->type == 0) {
1433e12c5d1SDavid du Colombier 			s->type = SDATA;
1443e12c5d1SDavid du Colombier 			s->value = orig1+orig;
1453e12c5d1SDavid du Colombier 			orig += 4;
1463e12c5d1SDavid du Colombier 			p1 = prg();
1473e12c5d1SDavid du Colombier 			p1->line = p->line;
1483e12c5d1SDavid du Colombier 			p1->as = ADATA;
1493e12c5d1SDavid du Colombier 			p1->from.type = D_OREG;
1503e12c5d1SDavid du Colombier 			p1->from.sym = s;
1513e12c5d1SDavid du Colombier 			p1->from.name = D_EXTERN;
1523e12c5d1SDavid du Colombier 			p1->reg = 4;
1533e12c5d1SDavid du Colombier 			p1->to = p->from;
1543e12c5d1SDavid du Colombier 			p1->link = datap;
1553e12c5d1SDavid du Colombier 			datap = p1;
1563e12c5d1SDavid du Colombier 		}
1573e12c5d1SDavid du Colombier 		if(s->type != SDATA)
1583e12c5d1SDavid du Colombier 			diag("literal not data: %s", s->name);
1593e12c5d1SDavid du Colombier 		p->from.type = D_OREG;
1603e12c5d1SDavid du Colombier 		p->from.sym = s;
1613e12c5d1SDavid du Colombier 		p->from.name = D_EXTERN;
1623e12c5d1SDavid du Colombier 		p->from.offset = 0;
163*219b2ee8SDavid du Colombier 		nocache(p);
1643e12c5d1SDavid du Colombier 		continue;
1653e12c5d1SDavid du Colombier 	}
1663e12c5d1SDavid du Colombier 	while(orig & 7)
1673e12c5d1SDavid du Colombier 		orig++;
1683e12c5d1SDavid du Colombier 	/*
1693e12c5d1SDavid du Colombier 	 * pass 5
1703e12c5d1SDavid du Colombier 	 *	re-adjust offsets
1713e12c5d1SDavid du Colombier 	 */
1723e12c5d1SDavid du Colombier 	for(i=0; i<NHASH; i++)
1733e12c5d1SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
1743e12c5d1SDavid du Colombier 		t = s->type;
1753e12c5d1SDavid du Colombier 		if(t == SBSS) {
1763e12c5d1SDavid du Colombier 			s->value += orig;
1773e12c5d1SDavid du Colombier 			continue;
1783e12c5d1SDavid du Colombier 		}
1793e12c5d1SDavid du Colombier 		if(t == SDATA1) {
1803e12c5d1SDavid du Colombier 			s->type = SDATA;
1813e12c5d1SDavid du Colombier 			s->value += orig;
1823e12c5d1SDavid du Colombier 			continue;
1833e12c5d1SDavid du Colombier 		}
1843e12c5d1SDavid du Colombier 	}
1853e12c5d1SDavid du Colombier 	datsize += orig;
1863e12c5d1SDavid du Colombier 	xdefine("setR30", SDATA, 0L+BIG);
1873e12c5d1SDavid du Colombier 	xdefine("bdata", SDATA, 0L);
1883e12c5d1SDavid du Colombier 	xdefine("edata", SDATA, datsize);
1893e12c5d1SDavid du Colombier 	xdefine("end", SBSS, datsize+bsssize);
1903e12c5d1SDavid du Colombier 	xdefine("etext", STEXT, 0L);
1913e12c5d1SDavid du Colombier }
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier void
1943e12c5d1SDavid du Colombier undef(void)
1953e12c5d1SDavid du Colombier {
1963e12c5d1SDavid du Colombier 	int i;
1973e12c5d1SDavid du Colombier 	Sym *s;
1983e12c5d1SDavid du Colombier 
1993e12c5d1SDavid du Colombier 	for(i=0; i<NHASH; i++)
2003e12c5d1SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link)
2013e12c5d1SDavid du Colombier 		if(s->type == SXREF)
2023e12c5d1SDavid du Colombier 			diag("%s: not defined\n", s->name);
2033e12c5d1SDavid du Colombier }
2043e12c5d1SDavid du Colombier 
2053e12c5d1SDavid du Colombier void
2063e12c5d1SDavid du Colombier follow(void)
2073e12c5d1SDavid du Colombier {
2083e12c5d1SDavid du Colombier 	if(debug['v'])
2093e12c5d1SDavid du Colombier 		Bprint(&bso, "%5.2f follow\n", cputime());
2103e12c5d1SDavid du Colombier 	Bflush(&bso);
2113e12c5d1SDavid du Colombier 
2123e12c5d1SDavid du Colombier 	firstp = prg();
2133e12c5d1SDavid du Colombier 	lastp = firstp;
2143e12c5d1SDavid du Colombier 	xfol(textp);
2153e12c5d1SDavid du Colombier 
2163e12c5d1SDavid du Colombier 	firstp = firstp->link;
2173e12c5d1SDavid du Colombier 	lastp->link = P;
2183e12c5d1SDavid du Colombier }
2193e12c5d1SDavid du Colombier 
2203e12c5d1SDavid du Colombier void
2213e12c5d1SDavid du Colombier xfol(Prog *p)
2223e12c5d1SDavid du Colombier {
2233e12c5d1SDavid du Colombier 	Prog *q, *r;
2243e12c5d1SDavid du Colombier 	int a, i;
2253e12c5d1SDavid du Colombier 
2263e12c5d1SDavid du Colombier loop:
2273e12c5d1SDavid du Colombier 	if(p == P)
2283e12c5d1SDavid du Colombier 		return;
2293e12c5d1SDavid du Colombier 	a = p->as;
2303e12c5d1SDavid du Colombier 	if(a == ATEXT)
2313e12c5d1SDavid du Colombier 		curtext = p;
2323e12c5d1SDavid du Colombier 	if(a == AJMP) {
2333e12c5d1SDavid du Colombier 		q = p->cond;
234*219b2ee8SDavid du Colombier 		if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
235*219b2ee8SDavid du Colombier 			p->mark |= FOLL;
236*219b2ee8SDavid du Colombier 			lastp->link = p;
237*219b2ee8SDavid du Colombier 			lastp = p;
238*219b2ee8SDavid du Colombier 			p = p->link;
239*219b2ee8SDavid du Colombier 			xfol(p);
240*219b2ee8SDavid du Colombier 			p = q;
241*219b2ee8SDavid du Colombier 			if(p && !(p->mark & FOLL))
242*219b2ee8SDavid du Colombier 				goto loop;
243*219b2ee8SDavid du Colombier 			return;
244*219b2ee8SDavid du Colombier 		}
2453e12c5d1SDavid du Colombier 		if(q != P) {
246*219b2ee8SDavid du Colombier 			p->mark |= FOLL;
2473e12c5d1SDavid du Colombier 			p = q;
2483e12c5d1SDavid du Colombier 			if(!(p->mark & FOLL))
2493e12c5d1SDavid du Colombier 				goto loop;
2503e12c5d1SDavid du Colombier 		}
2513e12c5d1SDavid du Colombier 	}
2523e12c5d1SDavid du Colombier 	if(p->mark & FOLL) {
2533e12c5d1SDavid du Colombier 		for(i=0,q=p; i<4; i++,q=q->link) {
254*219b2ee8SDavid du Colombier 			if(q == lastp || (q->mark&NOSCHED))
2553e12c5d1SDavid du Colombier 				break;
2563e12c5d1SDavid du Colombier 			a = q->as;
2573e12c5d1SDavid du Colombier 			if(a == ANOP) {
2583e12c5d1SDavid du Colombier 				i--;
2593e12c5d1SDavid du Colombier 				continue;
2603e12c5d1SDavid du Colombier 			}
2613e12c5d1SDavid du Colombier 			if(a == AJMP || a == ARET || a == ARFE)
2623e12c5d1SDavid du Colombier 				goto copy;
2633e12c5d1SDavid du Colombier 			if(!q->cond || (q->cond->mark&FOLL))
2643e12c5d1SDavid du Colombier 				continue;
2653e12c5d1SDavid du Colombier 			if(a != ABEQ && a != ABNE)
2663e12c5d1SDavid du Colombier 				continue;
2673e12c5d1SDavid du Colombier 		copy:
2683e12c5d1SDavid du Colombier 			for(;;) {
2693e12c5d1SDavid du Colombier 				r = prg();
2703e12c5d1SDavid du Colombier 				*r = *p;
2713e12c5d1SDavid du Colombier 				if(!(r->mark&FOLL))
2723e12c5d1SDavid du Colombier 					print("cant happen 1\n");
273*219b2ee8SDavid du Colombier 				r->mark |= FOLL;
2743e12c5d1SDavid du Colombier 				if(p != q) {
2753e12c5d1SDavid du Colombier 					p = p->link;
2763e12c5d1SDavid du Colombier 					lastp->link = r;
2773e12c5d1SDavid du Colombier 					lastp = r;
2783e12c5d1SDavid du Colombier 					continue;
2793e12c5d1SDavid du Colombier 				}
2803e12c5d1SDavid du Colombier 				lastp->link = r;
2813e12c5d1SDavid du Colombier 				lastp = r;
2823e12c5d1SDavid du Colombier 				if(a == AJMP || a == ARET || a == ARFE)
2833e12c5d1SDavid du Colombier 					return;
2843e12c5d1SDavid du Colombier 				r->as = ABNE;
2853e12c5d1SDavid du Colombier 				if(a == ABNE)
2863e12c5d1SDavid du Colombier 					r->as = ABEQ;
2873e12c5d1SDavid du Colombier 				r->cond = p->link;
2883e12c5d1SDavid du Colombier 				r->link = p->cond;
2893e12c5d1SDavid du Colombier 				if(!(r->link->mark&FOLL))
2903e12c5d1SDavid du Colombier 					xfol(r->link);
2913e12c5d1SDavid du Colombier 				if(!(r->cond->mark&FOLL))
2923e12c5d1SDavid du Colombier 					print("cant happen 2\n");
2933e12c5d1SDavid du Colombier 				return;
2943e12c5d1SDavid du Colombier 			}
2953e12c5d1SDavid du Colombier 		}
2963e12c5d1SDavid du Colombier 		a = AJMP;
2973e12c5d1SDavid du Colombier 		q = prg();
2983e12c5d1SDavid du Colombier 		q->as = a;
2993e12c5d1SDavid du Colombier 		q->line = p->line;
3003e12c5d1SDavid du Colombier 		q->to.type = D_BRANCH;
3013e12c5d1SDavid du Colombier 		q->to.offset = p->pc;
3023e12c5d1SDavid du Colombier 		q->cond = p;
3033e12c5d1SDavid du Colombier 		p = q;
3043e12c5d1SDavid du Colombier 	}
305*219b2ee8SDavid du Colombier 	p->mark |= FOLL;
3063e12c5d1SDavid du Colombier 	lastp->link = p;
3073e12c5d1SDavid du Colombier 	lastp = p;
308*219b2ee8SDavid du Colombier 	if(a == AJMP || a == ARET || a == ARFE){
309*219b2ee8SDavid du Colombier 		if(p->mark & NOSCHED){
310*219b2ee8SDavid du Colombier 			p = p->link;
311*219b2ee8SDavid du Colombier 			goto loop;
312*219b2ee8SDavid du Colombier 		}
3133e12c5d1SDavid du Colombier 		return;
314*219b2ee8SDavid du Colombier 	}
3153e12c5d1SDavid du Colombier 	if(p->cond != P)
3163e12c5d1SDavid du Colombier 	if(a != AJAL && p->link != P) {
3173e12c5d1SDavid du Colombier 		xfol(p->link);
3183e12c5d1SDavid du Colombier 		p = p->cond;
3193e12c5d1SDavid du Colombier 		if(p == P || (p->mark&FOLL))
3203e12c5d1SDavid du Colombier 			return;
3213e12c5d1SDavid du Colombier 		goto loop;
3223e12c5d1SDavid du Colombier 	}
3233e12c5d1SDavid du Colombier 	p = p->link;
3243e12c5d1SDavid du Colombier 	goto loop;
3253e12c5d1SDavid du Colombier }
3263e12c5d1SDavid du Colombier 
3273e12c5d1SDavid du Colombier void
3283e12c5d1SDavid du Colombier patch(void)
3293e12c5d1SDavid du Colombier {
3303e12c5d1SDavid du Colombier 	long c, vexit;
3313e12c5d1SDavid du Colombier 	Prog *p, *q;
3323e12c5d1SDavid du Colombier 	Sym *s;
3333e12c5d1SDavid du Colombier 	int a;
3343e12c5d1SDavid du Colombier 
3353e12c5d1SDavid du Colombier 	if(debug['v'])
3363e12c5d1SDavid du Colombier 		Bprint(&bso, "%5.2f patch\n", cputime());
3373e12c5d1SDavid du Colombier 	Bflush(&bso);
3383e12c5d1SDavid du Colombier 	mkfwd();
3393e12c5d1SDavid du Colombier 	s = lookup("exit", 0);
3403e12c5d1SDavid du Colombier 	vexit = s->value;
3413e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
3423e12c5d1SDavid du Colombier 		a = p->as;
3433e12c5d1SDavid du Colombier 		if(a == ATEXT)
3443e12c5d1SDavid du Colombier 			curtext = p;
345*219b2ee8SDavid du Colombier 		if((a == AJAL || a == AJMP || a == ARET) &&
346*219b2ee8SDavid du Colombier 		   p->to.type != D_BRANCH && p->to.sym != S) {
3473e12c5d1SDavid du Colombier 			s = p->to.sym;
3483e12c5d1SDavid du Colombier 			if(s->type != STEXT) {
3493e12c5d1SDavid du Colombier 				diag("undefined: %s\n%P\n", s->name, p);
3503e12c5d1SDavid du Colombier 				s->type = STEXT;
3513e12c5d1SDavid du Colombier 				s->value = vexit;
3523e12c5d1SDavid du Colombier 			}
3533e12c5d1SDavid du Colombier 			p->to.offset = s->value;
3543e12c5d1SDavid du Colombier 			p->to.type = D_BRANCH;
3553e12c5d1SDavid du Colombier 		}
3563e12c5d1SDavid du Colombier 		if(p->to.type != D_BRANCH)
3573e12c5d1SDavid du Colombier 			continue;
3583e12c5d1SDavid du Colombier 		c = p->to.offset;
3593e12c5d1SDavid du Colombier 		for(q = firstp; q != P;) {
3603e12c5d1SDavid du Colombier 			if(q->forwd != P)
3613e12c5d1SDavid du Colombier 			if(c >= q->forwd->pc) {
3623e12c5d1SDavid du Colombier 				q = q->forwd;
3633e12c5d1SDavid du Colombier 				continue;
3643e12c5d1SDavid du Colombier 			}
3653e12c5d1SDavid du Colombier 			if(c == q->pc)
3663e12c5d1SDavid du Colombier 				break;
3673e12c5d1SDavid du Colombier 			q = q->link;
3683e12c5d1SDavid du Colombier 		}
3693e12c5d1SDavid du Colombier 		if(q == P) {
3703e12c5d1SDavid du Colombier 			diag("branch out of range %ld\n%P\n", c, p);
3713e12c5d1SDavid du Colombier 			p->to.type = D_NONE;
3723e12c5d1SDavid du Colombier 		}
3733e12c5d1SDavid du Colombier 		p->cond = q;
3743e12c5d1SDavid du Colombier 	}
3753e12c5d1SDavid du Colombier 
3763e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
3773e12c5d1SDavid du Colombier 		if(p->as == ATEXT)
3783e12c5d1SDavid du Colombier 			curtext = p;
3793e12c5d1SDavid du Colombier 		if(p->cond != P) {
3803e12c5d1SDavid du Colombier 			p->cond = brloop(p->cond);
3813e12c5d1SDavid du Colombier 			if(p->cond != P)
3823e12c5d1SDavid du Colombier 			if(p->to.type == D_BRANCH)
3833e12c5d1SDavid du Colombier 				p->to.offset = p->cond->pc;
3843e12c5d1SDavid du Colombier 		}
3853e12c5d1SDavid du Colombier 	}
3863e12c5d1SDavid du Colombier }
3873e12c5d1SDavid du Colombier 
3883e12c5d1SDavid du Colombier #define	LOG	5
3893e12c5d1SDavid du Colombier void
3903e12c5d1SDavid du Colombier mkfwd(void)
3913e12c5d1SDavid du Colombier {
3923e12c5d1SDavid du Colombier 	Prog *p;
3933e12c5d1SDavid du Colombier 	long dwn[LOG], cnt[LOG], i;
3943e12c5d1SDavid du Colombier 	Prog *lst[LOG];
3953e12c5d1SDavid du Colombier 
3963e12c5d1SDavid du Colombier 	for(i=0; i<LOG; i++) {
3973e12c5d1SDavid du Colombier 		if(i == 0)
3983e12c5d1SDavid du Colombier 			cnt[i] = 1; else
3993e12c5d1SDavid du Colombier 			cnt[i] = LOG * cnt[i-1];
4003e12c5d1SDavid du Colombier 		dwn[i] = 1;
4013e12c5d1SDavid du Colombier 		lst[i] = P;
4023e12c5d1SDavid du Colombier 	}
4033e12c5d1SDavid du Colombier 	i = 0;
4043e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
4053e12c5d1SDavid du Colombier 		if(p->as == ATEXT)
4063e12c5d1SDavid du Colombier 			curtext = p;
4073e12c5d1SDavid du Colombier 		i--;
4083e12c5d1SDavid du Colombier 		if(i < 0)
4093e12c5d1SDavid du Colombier 			i = LOG-1;
4103e12c5d1SDavid du Colombier 		p->forwd = P;
4113e12c5d1SDavid du Colombier 		dwn[i]--;
4123e12c5d1SDavid du Colombier 		if(dwn[i] <= 0) {
4133e12c5d1SDavid du Colombier 			dwn[i] = cnt[i];
4143e12c5d1SDavid du Colombier 			if(lst[i] != P)
4153e12c5d1SDavid du Colombier 				lst[i]->forwd = p;
4163e12c5d1SDavid du Colombier 			lst[i] = p;
4173e12c5d1SDavid du Colombier 		}
4183e12c5d1SDavid du Colombier 	}
4193e12c5d1SDavid du Colombier }
4203e12c5d1SDavid du Colombier 
4213e12c5d1SDavid du Colombier Prog*
4223e12c5d1SDavid du Colombier brloop(Prog *p)
4233e12c5d1SDavid du Colombier {
4243e12c5d1SDavid du Colombier 	Prog *q;
4253e12c5d1SDavid du Colombier 	int c;
4263e12c5d1SDavid du Colombier 
4273e12c5d1SDavid du Colombier 	for(c=0; p!=P;) {
428*219b2ee8SDavid du Colombier 		if(p->as != AJMP || (p->mark&NOSCHED))
4293e12c5d1SDavid du Colombier 			return p;
4303e12c5d1SDavid du Colombier 		q = p->cond;
4313e12c5d1SDavid du Colombier 		if(q <= p) {
4323e12c5d1SDavid du Colombier 			c++;
4333e12c5d1SDavid du Colombier 			if(q == p || c > 50)
4343e12c5d1SDavid du Colombier 				break;
4353e12c5d1SDavid du Colombier 		}
4363e12c5d1SDavid du Colombier 		p = q;
4373e12c5d1SDavid du Colombier 	}
4383e12c5d1SDavid du Colombier 	return P;
4393e12c5d1SDavid du Colombier }
4403e12c5d1SDavid du Colombier 
4413e12c5d1SDavid du Colombier long
4423e12c5d1SDavid du Colombier atolwhex(char *s)
4433e12c5d1SDavid du Colombier {
4443e12c5d1SDavid du Colombier 	long n;
4453e12c5d1SDavid du Colombier 	int f;
4463e12c5d1SDavid du Colombier 
4473e12c5d1SDavid du Colombier 	n = 0;
4483e12c5d1SDavid du Colombier 	f = 0;
4493e12c5d1SDavid du Colombier 	while(*s == ' ' || *s == '\t')
4503e12c5d1SDavid du Colombier 		s++;
4513e12c5d1SDavid du Colombier 	if(*s == '-' || *s == '+') {
4523e12c5d1SDavid du Colombier 		if(*s++ == '-')
4533e12c5d1SDavid du Colombier 			f = 1;
4543e12c5d1SDavid du Colombier 		while(*s == ' ' || *s == '\t')
4553e12c5d1SDavid du Colombier 			s++;
4563e12c5d1SDavid du Colombier 	}
4573e12c5d1SDavid du Colombier 	if(s[0]=='0' && s[1]){
4583e12c5d1SDavid du Colombier 		if(s[1]=='x' || s[1]=='X'){
4593e12c5d1SDavid du Colombier 			s += 2;
4603e12c5d1SDavid du Colombier 			for(;;){
4613e12c5d1SDavid du Colombier 				if(*s >= '0' && *s <= '9')
4623e12c5d1SDavid du Colombier 					n = n*16 + *s++ - '0';
4633e12c5d1SDavid du Colombier 				else if(*s >= 'a' && *s <= 'f')
4643e12c5d1SDavid du Colombier 					n = n*16 + *s++ - 'a' + 10;
4653e12c5d1SDavid du Colombier 				else if(*s >= 'A' && *s <= 'F')
4663e12c5d1SDavid du Colombier 					n = n*16 + *s++ - 'A' + 10;
4673e12c5d1SDavid du Colombier 				else
4683e12c5d1SDavid du Colombier 					break;
4693e12c5d1SDavid du Colombier 			}
4703e12c5d1SDavid du Colombier 		} else
4713e12c5d1SDavid du Colombier 			while(*s >= '0' && *s <= '7')
4723e12c5d1SDavid du Colombier 				n = n*8 + *s++ - '0';
4733e12c5d1SDavid du Colombier 	} else
4743e12c5d1SDavid du Colombier 		while(*s >= '0' && *s <= '9')
4753e12c5d1SDavid du Colombier 			n = n*10 + *s++ - '0';
4763e12c5d1SDavid du Colombier 	if(f)
4773e12c5d1SDavid du Colombier 		n = -n;
4783e12c5d1SDavid du Colombier 	return n;
4793e12c5d1SDavid du Colombier }
4803e12c5d1SDavid du Colombier 
4813e12c5d1SDavid du Colombier long
4823e12c5d1SDavid du Colombier rnd(long v, long r)
4833e12c5d1SDavid du Colombier {
4843e12c5d1SDavid du Colombier 	long c;
4853e12c5d1SDavid du Colombier 
4863e12c5d1SDavid du Colombier 	if(r <= 0)
4873e12c5d1SDavid du Colombier 		return v;
4883e12c5d1SDavid du Colombier 	v += r - 1;
4893e12c5d1SDavid du Colombier 	c = v % r;
4903e12c5d1SDavid du Colombier 	if(c < 0)
4913e12c5d1SDavid du Colombier 		c += r;
4923e12c5d1SDavid du Colombier 	v -= c;
4933e12c5d1SDavid du Colombier 	return v;
4943e12c5d1SDavid du Colombier }
495