xref: /plan9-contrib/sys/src/cmd/4l/pass.c (revision f8bc6aaf8056e137bcdfb6117a990ac3eff62cc9)
17edc7532SDavid du Colombier #include	"l.h"
27edc7532SDavid du Colombier 
37edc7532SDavid du Colombier void
dodata(void)47edc7532SDavid du Colombier dodata(void)
57edc7532SDavid du Colombier {
67edc7532SDavid du Colombier 	int i, t;
77edc7532SDavid du Colombier 	Sym *s;
87edc7532SDavid du Colombier 	Prog *p, *p1;
97edc7532SDavid du Colombier 	vlong orig, orig1, v;
107edc7532SDavid du Colombier 
117edc7532SDavid du Colombier 	if(debug['v'])
127edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f dodata\n", cputime());
137edc7532SDavid du Colombier 	Bflush(&bso);
147edc7532SDavid du Colombier 	for(p = datap; p != P; p = p->link) {
157edc7532SDavid du Colombier 		s = p->from.sym;
167edc7532SDavid du Colombier 		if(p->as == ADYNT || p->as == AINIT)
177edc7532SDavid du Colombier 			s->value = dtype;
187edc7532SDavid du Colombier 		if(s->type == SBSS)
197edc7532SDavid du Colombier 			s->type = SDATA;
207edc7532SDavid du Colombier 		if(s->type != SDATA)
217edc7532SDavid du Colombier 			diag("initialize non-data (%d): %s\n%P",
227edc7532SDavid du Colombier 				s->type, s->name, p);
237edc7532SDavid du Colombier 		v = p->from.offset + p->reg;
247edc7532SDavid du Colombier 		if(v > s->value)
257edc7532SDavid du Colombier 			diag("initialize bounds (%lld): %s\n%P",
267edc7532SDavid du Colombier 				s->value, s->name, p);
277edc7532SDavid du Colombier 	}
287edc7532SDavid du Colombier 
29*f8bc6aafSDavid du Colombier 	if(debug['t']) {
30*f8bc6aafSDavid du Colombier 		/*
31*f8bc6aafSDavid du Colombier 		 * pull out string constants
32*f8bc6aafSDavid du Colombier 		 */
33*f8bc6aafSDavid du Colombier 		for(p = datap; p != P; p = p->link) {
34*f8bc6aafSDavid du Colombier 			s = p->from.sym;
35*f8bc6aafSDavid du Colombier 			if(p->to.type == D_SCONST)
36*f8bc6aafSDavid du Colombier 				s->type = SSTRING;
37*f8bc6aafSDavid du Colombier 		}
38*f8bc6aafSDavid du Colombier 	}
39*f8bc6aafSDavid du Colombier 
407edc7532SDavid du Colombier 	/*
417edc7532SDavid du Colombier 	 * pass 1
427edc7532SDavid du Colombier 	 *	assign 'small' variables to data segment
437edc7532SDavid du Colombier 	 *	(rational is that data segment is more easily
447edc7532SDavid du Colombier 	 *	 addressed through offset on R30)
457edc7532SDavid du Colombier 	 */
467edc7532SDavid du Colombier 	orig = 0;
477edc7532SDavid du Colombier 	for(i=0; i<NHASH; i++)
487edc7532SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
497edc7532SDavid du Colombier 		t = s->type;
507edc7532SDavid du Colombier 		if(t != SDATA && t != SBSS)
517edc7532SDavid du Colombier 			continue;
527edc7532SDavid du Colombier 		v = s->value;
537edc7532SDavid du Colombier 		if(v == 0) {
547edc7532SDavid du Colombier 			diag("%s: no size", s->name);
557edc7532SDavid du Colombier 			v = 1;
567edc7532SDavid du Colombier 		}
577edc7532SDavid du Colombier 		while(v & 7)
587edc7532SDavid du Colombier 			v++;
597edc7532SDavid du Colombier 		s->value = v;
607edc7532SDavid du Colombier 		if(v > MINSIZ)
617edc7532SDavid du Colombier 			continue;
627edc7532SDavid du Colombier 		s->value = orig;
637edc7532SDavid du Colombier 		orig += v;
647edc7532SDavid du Colombier 		s->type = SDATA1;
657edc7532SDavid du Colombier 	}
667edc7532SDavid du Colombier 	orig1 = orig;
677edc7532SDavid du Colombier 
687edc7532SDavid du Colombier 	/*
697edc7532SDavid du Colombier 	 * pass 2
707edc7532SDavid du Colombier 	 *	assign 'data' variables to data segment
717edc7532SDavid du Colombier 	 */
727edc7532SDavid du Colombier 	for(i=0; i<NHASH; i++)
737edc7532SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
747edc7532SDavid du Colombier 		t = s->type;
757edc7532SDavid du Colombier 		if(t != SDATA) {
767edc7532SDavid du Colombier 			if(t == SDATA1)
777edc7532SDavid du Colombier 				s->type = SDATA;
787edc7532SDavid du Colombier 			continue;
797edc7532SDavid du Colombier 		}
807edc7532SDavid du Colombier 		v = s->value;
817edc7532SDavid du Colombier 		while(v & 7)
827edc7532SDavid du Colombier 			v++;
837edc7532SDavid du Colombier 		s->value = orig;
847edc7532SDavid du Colombier 		orig += v;
857edc7532SDavid du Colombier 		s->type = SDATA1;
867edc7532SDavid du Colombier 	}
877edc7532SDavid du Colombier 
887edc7532SDavid du Colombier 	while(orig & 7)
897edc7532SDavid du Colombier 		orig++;
907edc7532SDavid du Colombier 	datsize = orig;
917edc7532SDavid du Colombier 
927edc7532SDavid du Colombier 	/*
937edc7532SDavid du Colombier 	 * pass 3
947edc7532SDavid du Colombier 	 *	everything else to bss segment
957edc7532SDavid du Colombier 	 */
967edc7532SDavid du Colombier 	for(i=0; i<NHASH; i++)
977edc7532SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
987edc7532SDavid du Colombier 		if(s->type != SBSS)
997edc7532SDavid du Colombier 			continue;
1007edc7532SDavid du Colombier 		v = s->value;
1017edc7532SDavid du Colombier 		while(v & 7)
1027edc7532SDavid du Colombier 			v++;
1037edc7532SDavid du Colombier 		s->value = orig;
1047edc7532SDavid du Colombier 		orig += v;
1057edc7532SDavid du Colombier 	}
1067edc7532SDavid du Colombier 	while(orig & 7)
1077edc7532SDavid du Colombier 		orig++;
1087edc7532SDavid du Colombier 	bsssize = orig-datsize;
1097edc7532SDavid du Colombier 
1107edc7532SDavid du Colombier 	/*
1117edc7532SDavid du Colombier 	 * pass 4
1127edc7532SDavid du Colombier 	 *	add literals to all large values.
1137edc7532SDavid du Colombier 	 *	at this time:
1147edc7532SDavid du Colombier 	 *		small data is allocated DATA
1157edc7532SDavid du Colombier 	 *		large data is allocated DATA1
1167edc7532SDavid du Colombier 	 *		large bss is allocated BSS
1177edc7532SDavid du Colombier 	 *	the new literals are loaded between
1187edc7532SDavid du Colombier 	 *	small data and large data.
1197edc7532SDavid du Colombier 	 */
1207edc7532SDavid du Colombier 	orig = 0;
1217edc7532SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
1227edc7532SDavid du Colombier 		if(p->as != AMOVW)
1237edc7532SDavid du Colombier 			continue;
1247edc7532SDavid du Colombier 		if(p->from.type != D_CONST)
1257edc7532SDavid du Colombier 			continue;
1267edc7532SDavid du Colombier 		if(s = p->from.sym) {
1277edc7532SDavid du Colombier 			t = s->type;
1287edc7532SDavid du Colombier 			if(t != SDATA && t != SDATA1 && t != SBSS)
1297edc7532SDavid du Colombier 				continue;
1307edc7532SDavid du Colombier 			t = p->from.name;
1317edc7532SDavid du Colombier 			if(t != D_EXTERN && t != D_STATIC)
1327edc7532SDavid du Colombier 				continue;
1337edc7532SDavid du Colombier 			v = s->value + p->from.offset;
1347edc7532SDavid du Colombier 			if(v >= 0 && v <= 0xffff)
1357edc7532SDavid du Colombier 				continue;
1367edc7532SDavid du Colombier 			if(!strcmp(s->name, "setR30"))
1377edc7532SDavid du Colombier 				continue;
1387edc7532SDavid du Colombier 			/* size should be 19 max */
1397edc7532SDavid du Colombier 			if(strlen(s->name) >= 10)	/* has loader address */
140*f8bc6aafSDavid du Colombier 				sprint(literal, "$%p.%llux", s, p->from.offset);
1417edc7532SDavid du Colombier 			else
142*f8bc6aafSDavid du Colombier 				sprint(literal, "$%s.%d.%llux", s->name,
143*f8bc6aafSDavid du Colombier 					s->version, p->from.offset);
1447edc7532SDavid du Colombier 		} else {
1457edc7532SDavid du Colombier 			if(p->from.name != D_NONE)
1467edc7532SDavid du Colombier 				continue;
1477edc7532SDavid du Colombier 			if(p->from.reg != NREG)
1487edc7532SDavid du Colombier 				continue;
1497edc7532SDavid du Colombier 			v = p->from.offset;
1507edc7532SDavid du Colombier 			if(v >= -0x7fff && v <= 0xffff)
1517edc7532SDavid du Colombier 				continue;
1527edc7532SDavid du Colombier 			if(!(v & 0xffff))
1537edc7532SDavid du Colombier 				continue;
1547edc7532SDavid du Colombier 			/* size should be 9 max */
1557edc7532SDavid du Colombier 			sprint(literal, "$%llux", v);
1567edc7532SDavid du Colombier 		}
1577edc7532SDavid du Colombier 		s = lookup(literal, 0);
1587edc7532SDavid du Colombier 		if(s->type == 0) {
1597edc7532SDavid du Colombier 			s->type = SDATA;
1607edc7532SDavid du Colombier 			s->value = orig1+orig;
1617edc7532SDavid du Colombier 			orig += 8;
1627edc7532SDavid du Colombier 			p1 = prg();
1637edc7532SDavid du Colombier 			p1->line = p->line;
1647edc7532SDavid du Colombier 			p1->as = ADATA;
1657edc7532SDavid du Colombier 			p1->from.type = D_OREG;
1667edc7532SDavid du Colombier 			p1->from.sym = s;
1677edc7532SDavid du Colombier 			p1->from.name = D_EXTERN;
1687edc7532SDavid du Colombier 			p1->reg = 4;
1697edc7532SDavid du Colombier 			p1->to = p->from;
1707edc7532SDavid du Colombier 			p1->link = datap;
1717edc7532SDavid du Colombier 			datap = p1;
1727edc7532SDavid du Colombier 		}
1737edc7532SDavid du Colombier 		if(s->type != SDATA)
1747edc7532SDavid du Colombier 			diag("literal not data: %s", s->name);
1757edc7532SDavid du Colombier 		p->from.type = D_OREG;
1767edc7532SDavid du Colombier 		p->from.sym = s;
1777edc7532SDavid du Colombier 		p->from.name = D_EXTERN;
1787edc7532SDavid du Colombier 		p->from.offset = 0;
1797edc7532SDavid du Colombier 		nocache(p);
1807edc7532SDavid du Colombier 		continue;
1817edc7532SDavid du Colombier 	}
1827edc7532SDavid du Colombier 	while(orig & 7)
1837edc7532SDavid du Colombier 		orig++;
1847edc7532SDavid du Colombier 	/*
1857edc7532SDavid du Colombier 	 * pass 5
1867edc7532SDavid du Colombier 	 *	re-adjust offsets
1877edc7532SDavid du Colombier 	 */
1887edc7532SDavid du Colombier 	for(i=0; i<NHASH; i++)
1897edc7532SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
1907edc7532SDavid du Colombier 		t = s->type;
1917edc7532SDavid du Colombier 		if(t == SBSS) {
1927edc7532SDavid du Colombier 			s->value += orig;
1937edc7532SDavid du Colombier 			continue;
1947edc7532SDavid du Colombier 		}
1957edc7532SDavid du Colombier 		if(t == SDATA1) {
1967edc7532SDavid du Colombier 			s->type = SDATA;
1977edc7532SDavid du Colombier 			s->value += orig;
1987edc7532SDavid du Colombier 			continue;
1997edc7532SDavid du Colombier 		}
2007edc7532SDavid du Colombier 	}
2017edc7532SDavid du Colombier 	datsize += orig;
2027edc7532SDavid du Colombier 	xdefine("setR30", SDATA, 0L+BIG);
2037edc7532SDavid du Colombier 	xdefine("bdata", SDATA, 0L);
2047edc7532SDavid du Colombier 	xdefine("edata", SDATA, datsize);
2057edc7532SDavid du Colombier 	xdefine("end", SBSS, datsize+bsssize);
2067edc7532SDavid du Colombier 	xdefine("etext", STEXT, 0L);
2077edc7532SDavid du Colombier }
2087edc7532SDavid du Colombier 
2097edc7532SDavid du Colombier void
undef(void)2107edc7532SDavid du Colombier undef(void)
2117edc7532SDavid du Colombier {
2127edc7532SDavid du Colombier 	int i;
2137edc7532SDavid du Colombier 	Sym *s;
2147edc7532SDavid du Colombier 
2157edc7532SDavid du Colombier 	for(i=0; i<NHASH; i++)
2167edc7532SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link)
2177edc7532SDavid du Colombier 		if(s->type == SXREF)
2187edc7532SDavid du Colombier 			diag("%s: not defined", s->name);
2197edc7532SDavid du Colombier }
2207edc7532SDavid du Colombier 
2217edc7532SDavid du Colombier void
follow(void)2227edc7532SDavid du Colombier follow(void)
2237edc7532SDavid du Colombier {
2247edc7532SDavid du Colombier 	if(debug['v'])
2257edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f follow\n", cputime());
2267edc7532SDavid du Colombier 	Bflush(&bso);
2277edc7532SDavid du Colombier 
2287edc7532SDavid du Colombier 	firstp = prg();
2297edc7532SDavid du Colombier 	lastp = firstp;
2307edc7532SDavid du Colombier 	xfol(textp);
2317edc7532SDavid du Colombier 
2327edc7532SDavid du Colombier 	firstp = firstp->link;
2337edc7532SDavid du Colombier 	lastp->link = P;
2347edc7532SDavid du Colombier }
2357edc7532SDavid du Colombier 
2367edc7532SDavid du Colombier void
xfol(Prog * p)2377edc7532SDavid du Colombier xfol(Prog *p)
2387edc7532SDavid du Colombier {
2397edc7532SDavid du Colombier 	Prog *q, *r;
2407edc7532SDavid du Colombier 	int a, i;
2417edc7532SDavid du Colombier 
2427edc7532SDavid du Colombier loop:
2437edc7532SDavid du Colombier 	if(p == P)
2447edc7532SDavid du Colombier 		return;
2457edc7532SDavid du Colombier 	a = p->as;
2467edc7532SDavid du Colombier 	if(a == ATEXT)
2477edc7532SDavid du Colombier 		curtext = p;
2487edc7532SDavid du Colombier 	if(a == AJMP) {
2497edc7532SDavid du Colombier 		q = p->cond;
2507edc7532SDavid du Colombier 		if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
2517edc7532SDavid du Colombier 			p->mark |= FOLL;
2527edc7532SDavid du Colombier 			lastp->link = p;
2537edc7532SDavid du Colombier 			lastp = p;
2547edc7532SDavid du Colombier 			p = p->link;
2557edc7532SDavid du Colombier 			xfol(p);
2567edc7532SDavid du Colombier 			p = q;
2577edc7532SDavid du Colombier 			if(p && !(p->mark & FOLL))
2587edc7532SDavid du Colombier 				goto loop;
2597edc7532SDavid du Colombier 			return;
2607edc7532SDavid du Colombier 		}
2617edc7532SDavid du Colombier 		if(q != P) {
2627edc7532SDavid du Colombier 			p->mark |= FOLL;
2637edc7532SDavid du Colombier 			p = q;
2647edc7532SDavid du Colombier 			if(!(p->mark & FOLL))
2657edc7532SDavid du Colombier 				goto loop;
2667edc7532SDavid du Colombier 		}
2677edc7532SDavid du Colombier 	}
2687edc7532SDavid du Colombier 	if(p->mark & FOLL) {
2697edc7532SDavid du Colombier 		for(i=0,q=p; i<4; i++,q=q->link) {
2707edc7532SDavid du Colombier 			if(q == lastp || (q->mark&NOSCHED))
2717edc7532SDavid du Colombier 				break;
2727edc7532SDavid du Colombier 			a = q->as;
2737edc7532SDavid du Colombier 			if(a == ANOP) {
2747edc7532SDavid du Colombier 				i--;
2757edc7532SDavid du Colombier 				continue;
2767edc7532SDavid du Colombier 			}
2777edc7532SDavid du Colombier 			if(a == AJMP || a == ARET || a == ARFE)
2787edc7532SDavid du Colombier 				goto copy;
2797edc7532SDavid du Colombier 			if(!q->cond || (q->cond->mark&FOLL))
2807edc7532SDavid du Colombier 				continue;
2817edc7532SDavid du Colombier 			if(a != ABEQ && a != ABNE)
2827edc7532SDavid du Colombier 				continue;
2837edc7532SDavid du Colombier 		copy:
2847edc7532SDavid du Colombier 			for(;;) {
2857edc7532SDavid du Colombier 				r = prg();
2867edc7532SDavid du Colombier 				*r = *p;
2877edc7532SDavid du Colombier 				if(!(r->mark&FOLL))
2887edc7532SDavid du Colombier 					print("cant happen 1\n");
2897edc7532SDavid du Colombier 				r->mark |= FOLL;
2907edc7532SDavid du Colombier 				if(p != q) {
2917edc7532SDavid du Colombier 					p = p->link;
2927edc7532SDavid du Colombier 					lastp->link = r;
2937edc7532SDavid du Colombier 					lastp = r;
2947edc7532SDavid du Colombier 					continue;
2957edc7532SDavid du Colombier 				}
2967edc7532SDavid du Colombier 				lastp->link = r;
2977edc7532SDavid du Colombier 				lastp = r;
2987edc7532SDavid du Colombier 				if(a == AJMP || a == ARET || a == ARFE)
2997edc7532SDavid du Colombier 					return;
3007edc7532SDavid du Colombier 				r->as = ABNE;
3017edc7532SDavid du Colombier 				if(a == ABNE)
3027edc7532SDavid du Colombier 					r->as = ABEQ;
3037edc7532SDavid du Colombier 				r->cond = p->link;
3047edc7532SDavid du Colombier 				r->link = p->cond;
3057edc7532SDavid du Colombier 				if(!(r->link->mark&FOLL))
3067edc7532SDavid du Colombier 					xfol(r->link);
3077edc7532SDavid du Colombier 				if(!(r->cond->mark&FOLL))
3087edc7532SDavid du Colombier 					print("cant happen 2\n");
3097edc7532SDavid du Colombier 				return;
3107edc7532SDavid du Colombier 			}
3117edc7532SDavid du Colombier 		}
3127edc7532SDavid du Colombier 		a = AJMP;
3137edc7532SDavid du Colombier 		q = prg();
3147edc7532SDavid du Colombier 		q->as = a;
3157edc7532SDavid du Colombier 		q->line = p->line;
3167edc7532SDavid du Colombier 		q->to.type = D_BRANCH;
3177edc7532SDavid du Colombier 		q->to.offset = p->pc;
3187edc7532SDavid du Colombier 		q->cond = p;
3197edc7532SDavid du Colombier 		p = q;
3207edc7532SDavid du Colombier 	}
3217edc7532SDavid du Colombier 	p->mark |= FOLL;
3227edc7532SDavid du Colombier 	lastp->link = p;
3237edc7532SDavid du Colombier 	lastp = p;
3247edc7532SDavid du Colombier 	if(a == AJMP || a == ARET || a == ARFE){
3257edc7532SDavid du Colombier 		if(p->mark & NOSCHED){
3267edc7532SDavid du Colombier 			p = p->link;
3277edc7532SDavid du Colombier 			goto loop;
3287edc7532SDavid du Colombier 		}
3297edc7532SDavid du Colombier 		return;
3307edc7532SDavid du Colombier 	}
3317edc7532SDavid du Colombier 	if(p->cond != P)
3327edc7532SDavid du Colombier 	if(a != AJAL && p->link != P) {
3337edc7532SDavid du Colombier 		xfol(p->link);
3347edc7532SDavid du Colombier 		p = p->cond;
3357edc7532SDavid du Colombier 		if(p == P || (p->mark&FOLL))
3367edc7532SDavid du Colombier 			return;
3377edc7532SDavid du Colombier 		goto loop;
3387edc7532SDavid du Colombier 	}
3397edc7532SDavid du Colombier 	p = p->link;
3407edc7532SDavid du Colombier 	goto loop;
3417edc7532SDavid du Colombier }
3427edc7532SDavid du Colombier 
3437edc7532SDavid du Colombier void
patch(void)3447edc7532SDavid du Colombier patch(void)
3457edc7532SDavid du Colombier {
3467edc7532SDavid du Colombier 	vlong c, vexit;
3477edc7532SDavid du Colombier 	Prog *p, *q;
3487edc7532SDavid du Colombier 	Sym *s;
3497edc7532SDavid du Colombier 	int a;
3507edc7532SDavid du Colombier 
3517edc7532SDavid du Colombier 	if(debug['v'])
3527edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f patch\n", cputime());
3537edc7532SDavid du Colombier 	Bflush(&bso);
3547edc7532SDavid du Colombier 	mkfwd();
3557edc7532SDavid du Colombier 	s = lookup("exit", 0);
3567edc7532SDavid du Colombier 	vexit = s->value;
3577edc7532SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
3587edc7532SDavid du Colombier 		a = p->as;
3597edc7532SDavid du Colombier 		if(a == ATEXT)
3607edc7532SDavid du Colombier 			curtext = p;
3617edc7532SDavid du Colombier 		if((a == AJAL || a == AJMP || a == ARET) &&
3627edc7532SDavid du Colombier 		   p->to.type != D_BRANCH && p->to.sym != S) {
3637edc7532SDavid du Colombier 			s = p->to.sym;
3647edc7532SDavid du Colombier 			if(s->type != STEXT) {
3657edc7532SDavid du Colombier 				diag("undefined: %s\n%P", s->name, p);
3667edc7532SDavid du Colombier 				s->type = STEXT;
3677edc7532SDavid du Colombier 				s->value = vexit;
3687edc7532SDavid du Colombier 			}
3697edc7532SDavid du Colombier 			p->to.offset = s->value;
3707edc7532SDavid du Colombier 			p->to.type = D_BRANCH;
3717edc7532SDavid du Colombier 		}
3727edc7532SDavid du Colombier 		if(p->to.type != D_BRANCH)
3737edc7532SDavid du Colombier 			continue;
3747edc7532SDavid du Colombier 		c = p->to.offset;
3757edc7532SDavid du Colombier 		for(q = firstp; q != P;) {
3767edc7532SDavid du Colombier 			if(q->forwd != P)
3777edc7532SDavid du Colombier 			if(c >= q->forwd->pc) {
3787edc7532SDavid du Colombier 				q = q->forwd;
3797edc7532SDavid du Colombier 				continue;
3807edc7532SDavid du Colombier 			}
3817edc7532SDavid du Colombier 			if(c == q->pc)
3827edc7532SDavid du Colombier 				break;
3837edc7532SDavid du Colombier 			q = q->link;
3847edc7532SDavid du Colombier 		}
3857edc7532SDavid du Colombier 		if(q == P) {
386*f8bc6aafSDavid du Colombier 			diag("branch out of range %lld\n%P", c, p);
3877edc7532SDavid du Colombier 			p->to.type = D_NONE;
3887edc7532SDavid du Colombier 		}
3897edc7532SDavid du Colombier 		p->cond = q;
3907edc7532SDavid du Colombier 	}
3917edc7532SDavid du Colombier 
3927edc7532SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
3937edc7532SDavid du Colombier 		if(p->as == ATEXT)
3947edc7532SDavid du Colombier 			curtext = p;
3957edc7532SDavid du Colombier 		if(p->cond != P) {
3967edc7532SDavid du Colombier 			p->cond = brloop(p->cond);
3977edc7532SDavid du Colombier 			if(p->cond != P)
3987edc7532SDavid du Colombier 			if(p->to.type == D_BRANCH)
3997edc7532SDavid du Colombier 				p->to.offset = p->cond->pc;
4007edc7532SDavid du Colombier 		}
4017edc7532SDavid du Colombier 	}
4027edc7532SDavid du Colombier }
4037edc7532SDavid du Colombier 
4047edc7532SDavid du Colombier #define	LOG	5
4057edc7532SDavid du Colombier void
mkfwd(void)4067edc7532SDavid du Colombier mkfwd(void)
4077edc7532SDavid du Colombier {
4087edc7532SDavid du Colombier 	Prog *p;
4097edc7532SDavid du Colombier 	long dwn[LOG], cnt[LOG], i;
4107edc7532SDavid du Colombier 	Prog *lst[LOG];
4117edc7532SDavid du Colombier 
4127edc7532SDavid du Colombier 	for(i=0; i<LOG; i++) {
4137edc7532SDavid du Colombier 		if(i == 0)
4147edc7532SDavid du Colombier 			cnt[i] = 1; else
4157edc7532SDavid du Colombier 			cnt[i] = LOG * cnt[i-1];
4167edc7532SDavid du Colombier 		dwn[i] = 1;
4177edc7532SDavid du Colombier 		lst[i] = P;
4187edc7532SDavid du Colombier 	}
4197edc7532SDavid du Colombier 	i = 0;
4207edc7532SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
4217edc7532SDavid du Colombier 		if(p->as == ATEXT)
4227edc7532SDavid du Colombier 			curtext = p;
4237edc7532SDavid du Colombier 		i--;
4247edc7532SDavid du Colombier 		if(i < 0)
4257edc7532SDavid du Colombier 			i = LOG-1;
4267edc7532SDavid du Colombier 		p->forwd = P;
4277edc7532SDavid du Colombier 		dwn[i]--;
4287edc7532SDavid du Colombier 		if(dwn[i] <= 0) {
4297edc7532SDavid du Colombier 			dwn[i] = cnt[i];
4307edc7532SDavid du Colombier 			if(lst[i] != P)
4317edc7532SDavid du Colombier 				lst[i]->forwd = p;
4327edc7532SDavid du Colombier 			lst[i] = p;
4337edc7532SDavid du Colombier 		}
4347edc7532SDavid du Colombier 	}
4357edc7532SDavid du Colombier }
4367edc7532SDavid du Colombier 
4377edc7532SDavid du Colombier Prog*
brloop(Prog * p)4387edc7532SDavid du Colombier brloop(Prog *p)
4397edc7532SDavid du Colombier {
4407edc7532SDavid du Colombier 	Prog *q;
4417edc7532SDavid du Colombier 	int c;
4427edc7532SDavid du Colombier 
4437edc7532SDavid du Colombier 	for(c=0; p!=P;) {
4447edc7532SDavid du Colombier 		if(p->as != AJMP || (p->mark&NOSCHED))
4457edc7532SDavid du Colombier 			return p;
4467edc7532SDavid du Colombier 		q = p->cond;
4477edc7532SDavid du Colombier 		if(q <= p) {
4487edc7532SDavid du Colombier 			c++;
4497edc7532SDavid du Colombier 			if(q == p || c > 5000)
4507edc7532SDavid du Colombier 				break;
4517edc7532SDavid du Colombier 		}
4527edc7532SDavid du Colombier 		p = q;
4537edc7532SDavid du Colombier 	}
4547edc7532SDavid du Colombier 	return P;
4557edc7532SDavid du Colombier }
4567edc7532SDavid du Colombier 
457*f8bc6aafSDavid du Colombier vlong
atolwhex(char * s)4587edc7532SDavid du Colombier atolwhex(char *s)
4597edc7532SDavid du Colombier {
460*f8bc6aafSDavid du Colombier 	vlong n;
4617edc7532SDavid du Colombier 	int f;
4627edc7532SDavid du Colombier 
4637edc7532SDavid du Colombier 	n = 0;
4647edc7532SDavid du Colombier 	f = 0;
4657edc7532SDavid du Colombier 	while(*s == ' ' || *s == '\t')
4667edc7532SDavid du Colombier 		s++;
4677edc7532SDavid du Colombier 	if(*s == '-' || *s == '+') {
4687edc7532SDavid du Colombier 		if(*s++ == '-')
4697edc7532SDavid du Colombier 			f = 1;
4707edc7532SDavid du Colombier 		while(*s == ' ' || *s == '\t')
4717edc7532SDavid du Colombier 			s++;
4727edc7532SDavid du Colombier 	}
4737edc7532SDavid du Colombier 	if(s[0]=='0' && s[1]){
4747edc7532SDavid du Colombier 		if(s[1]=='x' || s[1]=='X'){
4757edc7532SDavid du Colombier 			s += 2;
4767edc7532SDavid du Colombier 			for(;;){
4777edc7532SDavid du Colombier 				if(*s >= '0' && *s <= '9')
4787edc7532SDavid du Colombier 					n = n*16 + *s++ - '0';
4797edc7532SDavid du Colombier 				else if(*s >= 'a' && *s <= 'f')
4807edc7532SDavid du Colombier 					n = n*16 + *s++ - 'a' + 10;
4817edc7532SDavid du Colombier 				else if(*s >= 'A' && *s <= 'F')
4827edc7532SDavid du Colombier 					n = n*16 + *s++ - 'A' + 10;
4837edc7532SDavid du Colombier 				else
4847edc7532SDavid du Colombier 					break;
4857edc7532SDavid du Colombier 			}
4867edc7532SDavid du Colombier 		} else
4877edc7532SDavid du Colombier 			while(*s >= '0' && *s <= '7')
4887edc7532SDavid du Colombier 				n = n*8 + *s++ - '0';
4897edc7532SDavid du Colombier 	} else
4907edc7532SDavid du Colombier 		while(*s >= '0' && *s <= '9')
4917edc7532SDavid du Colombier 			n = n*10 + *s++ - '0';
4927edc7532SDavid du Colombier 	if(f)
4937edc7532SDavid du Colombier 		n = -n;
4947edc7532SDavid du Colombier 	return n;
4957edc7532SDavid du Colombier }
4967edc7532SDavid du Colombier 
4977edc7532SDavid du Colombier vlong
atovlwhex(char * s)4987edc7532SDavid du Colombier atovlwhex(char *s)
4997edc7532SDavid du Colombier {
5007edc7532SDavid du Colombier 	vlong n;
5017edc7532SDavid du Colombier 	int f;
5027edc7532SDavid du Colombier 
5037edc7532SDavid du Colombier 	n = 0;
5047edc7532SDavid du Colombier 	f = 0;
5057edc7532SDavid du Colombier 	while(*s == ' ' || *s == '\t')
5067edc7532SDavid du Colombier 		s++;
5077edc7532SDavid du Colombier 	if(*s == '-' || *s == '+') {
5087edc7532SDavid du Colombier 		if(*s++ == '-')
5097edc7532SDavid du Colombier 			f = 1;
5107edc7532SDavid du Colombier 		while(*s == ' ' || *s == '\t')
5117edc7532SDavid du Colombier 			s++;
5127edc7532SDavid du Colombier 	}
5137edc7532SDavid du Colombier 	if(s[0]=='0' && s[1]){
5147edc7532SDavid du Colombier 		if(s[1]=='x' || s[1]=='X'){
5157edc7532SDavid du Colombier 			s += 2;
5167edc7532SDavid du Colombier 			for(;;){
5177edc7532SDavid du Colombier 				if(*s >= '0' && *s <= '9')
5187edc7532SDavid du Colombier 					n = n*16 + *s++ - '0';
5197edc7532SDavid du Colombier 				else if(*s >= 'a' && *s <= 'f')
5207edc7532SDavid du Colombier 					n = n*16 + *s++ - 'a' + 10;
5217edc7532SDavid du Colombier 				else if(*s >= 'A' && *s <= 'F')
5227edc7532SDavid du Colombier 					n = n*16 + *s++ - 'A' + 10;
5237edc7532SDavid du Colombier 				else
5247edc7532SDavid du Colombier 					break;
5257edc7532SDavid du Colombier 			}
5267edc7532SDavid du Colombier 		} else
5277edc7532SDavid du Colombier 			while(*s >= '0' && *s <= '7')
5287edc7532SDavid du Colombier 				n = n*8 + *s++ - '0';
5297edc7532SDavid du Colombier 	} else
5307edc7532SDavid du Colombier 		while(*s >= '0' && *s <= '9')
5317edc7532SDavid du Colombier 			n = n*10 + *s++ - '0';
5327edc7532SDavid du Colombier 	if(f)
5337edc7532SDavid du Colombier 		n = -n;
5347edc7532SDavid du Colombier 	return n;
5357edc7532SDavid du Colombier }
5367edc7532SDavid du Colombier 
5377edc7532SDavid du Colombier vlong
rnd(vlong v,long r)538*f8bc6aafSDavid du Colombier rnd(vlong v, long r)
5397edc7532SDavid du Colombier {
540*f8bc6aafSDavid du Colombier 	long c;
5417edc7532SDavid du Colombier 
5427edc7532SDavid du Colombier 	if(r <= 0)
5437edc7532SDavid du Colombier 		return v;
5447edc7532SDavid du Colombier 	v += r - 1;
5457edc7532SDavid du Colombier 	c = v % r;
5467edc7532SDavid du Colombier 	if(c < 0)
5477edc7532SDavid du Colombier 		c += r;
5487edc7532SDavid du Colombier 	v -= c;
5497edc7532SDavid du Colombier 	return v;
5507edc7532SDavid du Colombier }
551