xref: /plan9/sys/src/cmd/ql/pass.c (revision 73e742d79f6b0cfc24f3b01d7ade790955db63c2)
17dd7cddfSDavid du Colombier #include	"l.h"
27dd7cddfSDavid du Colombier 
37dd7cddfSDavid du Colombier void
dodata(void)47dd7cddfSDavid du Colombier dodata(void)
57dd7cddfSDavid du Colombier {
67dd7cddfSDavid du Colombier 	int i, t;
77dd7cddfSDavid du Colombier 	Sym *s;
87dd7cddfSDavid du Colombier 	Prog *p, *p1;
97dd7cddfSDavid du Colombier 	long orig, orig1, v;
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier 	if(debug['v'])
127dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f dodata\n", cputime());
137dd7cddfSDavid du Colombier 	Bflush(&bso);
147dd7cddfSDavid du Colombier 	for(p = datap; p != P; p = p->link) {
157dd7cddfSDavid du Colombier 		s = p->from.sym;
167dd7cddfSDavid du Colombier 		if(p->as == ADYNT || p->as == AINIT)
177dd7cddfSDavid du Colombier 			s->value = dtype;
187dd7cddfSDavid du Colombier 		if(s->type == SBSS)
197dd7cddfSDavid du Colombier 			s->type = SDATA;
207dd7cddfSDavid du Colombier 		if(s->type != SDATA)
216b6b9ac8SDavid du Colombier 			diag("initialize non-data (%d): %s\n%P",
227dd7cddfSDavid du Colombier 				s->type, s->name, p);
237dd7cddfSDavid du Colombier 		v = p->from.offset + p->reg;
247dd7cddfSDavid du Colombier 		if(v > s->value)
256b6b9ac8SDavid du Colombier 			diag("initialize bounds (%ld): %s\n%P",
267dd7cddfSDavid du Colombier 				s->value, s->name, p);
277dd7cddfSDavid du Colombier 	}
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier 	/*
307dd7cddfSDavid du Colombier 	 * pass 1
317dd7cddfSDavid du Colombier 	 *	assign 'small' variables to data segment
327dd7cddfSDavid du Colombier 	 *	(rational is that data segment is more easily
337dd7cddfSDavid du Colombier 	 *	 addressed through offset on REGSB)
347dd7cddfSDavid du Colombier 	 */
357dd7cddfSDavid du Colombier 	orig = 0;
367dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
377dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
387dd7cddfSDavid du Colombier 		t = s->type;
397dd7cddfSDavid du Colombier 		if(t != SDATA && t != SBSS)
407dd7cddfSDavid du Colombier 			continue;
417dd7cddfSDavid du Colombier 		v = s->value;
427dd7cddfSDavid du Colombier 		if(v == 0) {
436b6b9ac8SDavid du Colombier 			diag("%s: no size", s->name);
447dd7cddfSDavid du Colombier 			v = 1;
457dd7cddfSDavid du Colombier 		}
467dd7cddfSDavid du Colombier 		while(v & 3)
477dd7cddfSDavid du Colombier 			v++;
487dd7cddfSDavid du Colombier 		s->value = v;
497dd7cddfSDavid du Colombier 		if(v > MINSIZ)
507dd7cddfSDavid du Colombier 			continue;
517dd7cddfSDavid du Colombier 		if(v >= 8)
527dd7cddfSDavid du Colombier 			while(orig & 7)
537dd7cddfSDavid du Colombier 				orig++;
547dd7cddfSDavid du Colombier 		s->value = orig;
557dd7cddfSDavid du Colombier 		orig += v;
567dd7cddfSDavid du Colombier 		s->type = SDATA1;
577dd7cddfSDavid du Colombier 	}
587dd7cddfSDavid du Colombier 	orig1 = orig;
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier 	/*
617dd7cddfSDavid du Colombier 	 * pass 2
627dd7cddfSDavid du Colombier 	 *	assign 'data' variables to data segment
637dd7cddfSDavid du Colombier 	 */
647dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
657dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
667dd7cddfSDavid du Colombier 		t = s->type;
677dd7cddfSDavid du Colombier 		if(t != SDATA) {
687dd7cddfSDavid du Colombier 			if(t == SDATA1)
697dd7cddfSDavid du Colombier 				s->type = SDATA;
707dd7cddfSDavid du Colombier 			continue;
717dd7cddfSDavid du Colombier 		}
727dd7cddfSDavid du Colombier 		v = s->value;
737dd7cddfSDavid du Colombier 		if(v >= 8)
747dd7cddfSDavid du Colombier 			while(orig & 7)
757dd7cddfSDavid du Colombier 				orig++;
767dd7cddfSDavid du Colombier 		s->value = orig;
777dd7cddfSDavid du Colombier 		orig += v;
787dd7cddfSDavid du Colombier 		s->type = SDATA1;
797dd7cddfSDavid du Colombier 	}
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier 	while(orig & 7)
827dd7cddfSDavid du Colombier 		orig++;
837dd7cddfSDavid du Colombier 	datsize = orig;
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier 	/*
867dd7cddfSDavid du Colombier 	 * pass 3
877dd7cddfSDavid du Colombier 	 *	everything else to bss segment
887dd7cddfSDavid du Colombier 	 */
897dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
907dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
917dd7cddfSDavid du Colombier 		if(s->type != SBSS)
927dd7cddfSDavid du Colombier 			continue;
937dd7cddfSDavid du Colombier 		v = s->value;
947dd7cddfSDavid du Colombier 		if(v >= 8)
957dd7cddfSDavid du Colombier 			while(orig & 7)
967dd7cddfSDavid du Colombier 				orig++;
977dd7cddfSDavid du Colombier 		s->value = orig;
987dd7cddfSDavid du Colombier 		orig += v;
997dd7cddfSDavid du Colombier 	}
1007dd7cddfSDavid du Colombier 	while(orig & 7)
1017dd7cddfSDavid du Colombier 		orig++;
1027dd7cddfSDavid du Colombier 	bsssize = orig-datsize;
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier 	/*
1057dd7cddfSDavid du Colombier 	 * pass 4
1067dd7cddfSDavid du Colombier 	 *	add literals to all large values.
1077dd7cddfSDavid du Colombier 	 *	at this time:
1087dd7cddfSDavid du Colombier 	 *		small data is allocated DATA
1097dd7cddfSDavid du Colombier 	 *		large data is allocated DATA1
1107dd7cddfSDavid du Colombier 	 *		large bss is allocated BSS
1117dd7cddfSDavid du Colombier 	 *	the new literals are loaded between
1127dd7cddfSDavid du Colombier 	 *	small data and large data.
1137dd7cddfSDavid du Colombier 	 */
1147dd7cddfSDavid du Colombier 	orig = 0;
1157dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
1167dd7cddfSDavid du Colombier 		if(p->as != AMOVW)
1177dd7cddfSDavid du Colombier 			continue;
1187dd7cddfSDavid du Colombier 		if(p->from.type != D_CONST)
1197dd7cddfSDavid du Colombier 			continue;
1207dd7cddfSDavid du Colombier 		if(s = p->from.sym) {
1217dd7cddfSDavid du Colombier 			t = s->type;
1227dd7cddfSDavid du Colombier 			if(t != SDATA && t != SDATA1 && t != SBSS)
1237dd7cddfSDavid du Colombier 				continue;
1247dd7cddfSDavid du Colombier 			t = p->from.name;
1257dd7cddfSDavid du Colombier 			if(t != D_EXTERN && t != D_STATIC)
1267dd7cddfSDavid du Colombier 				continue;
1277dd7cddfSDavid du Colombier 			v = s->value + p->from.offset;
1287dd7cddfSDavid du Colombier 			if(v >= 0 && v <= 0xffff)
1297dd7cddfSDavid du Colombier 				continue;
1307dd7cddfSDavid du Colombier 			if(!strcmp(s->name, "setSB"))
1317dd7cddfSDavid du Colombier 				continue;
1327dd7cddfSDavid du Colombier 			/* size should be 19 max */
1337dd7cddfSDavid du Colombier 			if(strlen(s->name) >= 10)	/* has loader address */
134*73e742d7SDavid du Colombier 				sprint(literal, "$%p.%lux", s, p->from.offset);
1357dd7cddfSDavid du Colombier 			else
1367dd7cddfSDavid du Colombier 				sprint(literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
1377dd7cddfSDavid du Colombier 		} else {
1387dd7cddfSDavid du Colombier 			if(p->from.name != D_NONE)
1397dd7cddfSDavid du Colombier 				continue;
1407dd7cddfSDavid du Colombier 			if(p->from.reg != NREG)
1417dd7cddfSDavid du Colombier 				continue;
1427dd7cddfSDavid du Colombier 			v = p->from.offset;
1437dd7cddfSDavid du Colombier 			if(v >= -0x7fff-1 && v <= 0x7fff)
1447dd7cddfSDavid du Colombier 				continue;
1457dd7cddfSDavid du Colombier 			if(!(v & 0xffff))
1467dd7cddfSDavid du Colombier 				continue;
1477dd7cddfSDavid du Colombier 			if(v)
1487dd7cddfSDavid du Colombier 				continue;	/* quicker to build it than load it */
1497dd7cddfSDavid du Colombier 			/* size should be 9 max */
1507dd7cddfSDavid du Colombier 			sprint(literal, "$%lux", v);
1517dd7cddfSDavid du Colombier 		}
1527dd7cddfSDavid du Colombier 		s = lookup(literal, 0);
1537dd7cddfSDavid du Colombier 		if(s->type == 0) {
1547dd7cddfSDavid du Colombier 			s->type = SDATA;
1557dd7cddfSDavid du Colombier 			s->value = orig1+orig;
1567dd7cddfSDavid du Colombier 			orig += 4;
1577dd7cddfSDavid du Colombier 			p1 = prg();
1587dd7cddfSDavid du Colombier 			p1->as = ADATA;
1597dd7cddfSDavid du Colombier 			p1->line = p->line;
1607dd7cddfSDavid du Colombier 			p1->from.type = D_OREG;
1617dd7cddfSDavid du Colombier 			p1->from.sym = s;
1627dd7cddfSDavid du Colombier 			p1->from.name = D_EXTERN;
1637dd7cddfSDavid du Colombier 			p1->reg = 4;
1647dd7cddfSDavid du Colombier 			p1->to = p->from;
1657dd7cddfSDavid du Colombier 			p1->link = datap;
1667dd7cddfSDavid du Colombier 			datap = p1;
1677dd7cddfSDavid du Colombier 		}
1687dd7cddfSDavid du Colombier 		if(s->type != SDATA)
1697dd7cddfSDavid du Colombier 			diag("literal not data: %s", s->name);
1707dd7cddfSDavid du Colombier 		p->from.type = D_OREG;
1717dd7cddfSDavid du Colombier 		p->from.sym = s;
1727dd7cddfSDavid du Colombier 		p->from.name = D_EXTERN;
1737dd7cddfSDavid du Colombier 		p->from.offset = 0;
1747dd7cddfSDavid du Colombier 		continue;
1757dd7cddfSDavid du Colombier 	}
1767dd7cddfSDavid du Colombier 	while(orig & 7)
1777dd7cddfSDavid du Colombier 		orig++;
1787dd7cddfSDavid du Colombier 	/*
1797dd7cddfSDavid du Colombier 	 * pass 5
1807dd7cddfSDavid du Colombier 	 *	re-adjust offsets
1817dd7cddfSDavid du Colombier 	 */
1827dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
1837dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
1847dd7cddfSDavid du Colombier 		t = s->type;
1857dd7cddfSDavid du Colombier 		if(t == SBSS) {
1867dd7cddfSDavid du Colombier 			s->value += orig;
1877dd7cddfSDavid du Colombier 			continue;
1887dd7cddfSDavid du Colombier 		}
1897dd7cddfSDavid du Colombier 		if(t == SDATA1) {
1907dd7cddfSDavid du Colombier 			s->type = SDATA;
1917dd7cddfSDavid du Colombier 			s->value += orig;
1927dd7cddfSDavid du Colombier 			continue;
1937dd7cddfSDavid du Colombier 		}
1947dd7cddfSDavid du Colombier 	}
1957dd7cddfSDavid du Colombier 	datsize += orig;
1967dd7cddfSDavid du Colombier 	xdefine("setSB", SDATA, 0L+BIG);
1977dd7cddfSDavid du Colombier 	xdefine("bdata", SDATA, 0L);
1987dd7cddfSDavid du Colombier 	xdefine("edata", SDATA, datsize);
1997dd7cddfSDavid du Colombier 	xdefine("end", SBSS, datsize+bsssize);
2007dd7cddfSDavid du Colombier 	xdefine("etext", STEXT, 0L);
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier void
undef(void)2047dd7cddfSDavid du Colombier undef(void)
2057dd7cddfSDavid du Colombier {
2067dd7cddfSDavid du Colombier 	int i;
2077dd7cddfSDavid du Colombier 	Sym *s;
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
2107dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link)
2117dd7cddfSDavid du Colombier 		if(s->type == SXREF)
2126b6b9ac8SDavid du Colombier 			diag("%s: not defined", s->name);
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier int
relinv(int a)2167dd7cddfSDavid du Colombier relinv(int a)
2177dd7cddfSDavid du Colombier {
2187dd7cddfSDavid du Colombier 
2197dd7cddfSDavid du Colombier 	switch(a) {
2207dd7cddfSDavid du Colombier 	case ABEQ:	return ABNE;
2217dd7cddfSDavid du Colombier 	case ABNE:	return ABEQ;
2227dd7cddfSDavid du Colombier 
2237dd7cddfSDavid du Colombier 	case ABGE:	return ABLT;
2247dd7cddfSDavid du Colombier 	case ABLT:	return ABGE;
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier 	case ABGT:	return ABLE;
2277dd7cddfSDavid du Colombier 	case ABLE:	return ABGT;
2287dd7cddfSDavid du Colombier 
2297dd7cddfSDavid du Colombier 	case ABVC:	return ABVS;
2307dd7cddfSDavid du Colombier 	case ABVS:	return ABVC;
2317dd7cddfSDavid du Colombier 	}
2327dd7cddfSDavid du Colombier 	return 0;
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier 
2357dd7cddfSDavid du Colombier void
follow(void)2367dd7cddfSDavid du Colombier follow(void)
2377dd7cddfSDavid du Colombier {
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier 	if(debug['v'])
2407dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f follow\n", cputime());
2417dd7cddfSDavid du Colombier 	Bflush(&bso);
2427dd7cddfSDavid du Colombier 
2437dd7cddfSDavid du Colombier 	firstp = prg();
2447dd7cddfSDavid du Colombier 	lastp = firstp;
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier 	xfol(textp);
2477dd7cddfSDavid du Colombier 
2487dd7cddfSDavid du Colombier 	firstp = firstp->link;
2497dd7cddfSDavid du Colombier 	lastp->link = P;
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier 
2527dd7cddfSDavid du Colombier void
xfol(Prog * p)2537dd7cddfSDavid du Colombier xfol(Prog *p)
2547dd7cddfSDavid du Colombier {
2557dd7cddfSDavid du Colombier 	Prog *q, *r;
2567dd7cddfSDavid du Colombier 	int a, b, i;
2577dd7cddfSDavid du Colombier 
2587dd7cddfSDavid du Colombier loop:
2597dd7cddfSDavid du Colombier 	if(p == P)
2607dd7cddfSDavid du Colombier 		return;
2617dd7cddfSDavid du Colombier 	a = p->as;
2627dd7cddfSDavid du Colombier 	if(a == ATEXT)
2637dd7cddfSDavid du Colombier 		curtext = p;
2647dd7cddfSDavid du Colombier 	if(a == ABR) {
2657dd7cddfSDavid du Colombier 		q = p->cond;
2667dd7cddfSDavid du Colombier 		if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
2677dd7cddfSDavid du Colombier 			p->mark |= FOLL;
2687dd7cddfSDavid du Colombier 			lastp->link = p;
2697dd7cddfSDavid du Colombier 			lastp = p;
2707dd7cddfSDavid du Colombier 			p = p->link;
2717dd7cddfSDavid du Colombier 			xfol(p);
2727dd7cddfSDavid du Colombier 			p = q;
2737dd7cddfSDavid du Colombier 			if(p && !(p->mark & FOLL))
2747dd7cddfSDavid du Colombier 				goto loop;
2757dd7cddfSDavid du Colombier 			return;
2767dd7cddfSDavid du Colombier 		}
2777dd7cddfSDavid du Colombier 		if(q != P) {
2787dd7cddfSDavid du Colombier 			p->mark |= FOLL;
2797dd7cddfSDavid du Colombier 			p = q;
2807dd7cddfSDavid du Colombier 			if(!(p->mark & FOLL))
2817dd7cddfSDavid du Colombier 				goto loop;
2827dd7cddfSDavid du Colombier 		}
2837dd7cddfSDavid du Colombier 	}
2847dd7cddfSDavid du Colombier 	if(p->mark & FOLL) {
2857dd7cddfSDavid du Colombier 		for(i=0,q=p; i<4; i++,q=q->link) {
2867dd7cddfSDavid du Colombier 			if(q == lastp || (q->mark&NOSCHED))
2877dd7cddfSDavid du Colombier 				break;
2887dd7cddfSDavid du Colombier 			b = 0;		/* set */
2897dd7cddfSDavid du Colombier 			a = q->as;
2907dd7cddfSDavid du Colombier 			if(a == ANOP) {
2917dd7cddfSDavid du Colombier 				i--;
2927dd7cddfSDavid du Colombier 				continue;
2937dd7cddfSDavid du Colombier 			}
294375daca8SDavid du Colombier 			if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI)
2957dd7cddfSDavid du Colombier 				goto copy;
2967dd7cddfSDavid du Colombier 			if(!q->cond || (q->cond->mark&FOLL))
2977dd7cddfSDavid du Colombier 				continue;
2987dd7cddfSDavid du Colombier 			b = relinv(a);
2997dd7cddfSDavid du Colombier 			if(!b)
3007dd7cddfSDavid du Colombier 				continue;
3017dd7cddfSDavid du Colombier 		copy:
3027dd7cddfSDavid du Colombier 			for(;;) {
3037dd7cddfSDavid du Colombier 				r = prg();
3047dd7cddfSDavid du Colombier 				*r = *p;
3057dd7cddfSDavid du Colombier 				if(!(r->mark&FOLL))
3067dd7cddfSDavid du Colombier 					print("cant happen 1\n");
3077dd7cddfSDavid du Colombier 				r->mark |= FOLL;
3087dd7cddfSDavid du Colombier 				if(p != q) {
3097dd7cddfSDavid du Colombier 					p = p->link;
3107dd7cddfSDavid du Colombier 					lastp->link = r;
3117dd7cddfSDavid du Colombier 					lastp = r;
3127dd7cddfSDavid du Colombier 					continue;
3137dd7cddfSDavid du Colombier 				}
3147dd7cddfSDavid du Colombier 				lastp->link = r;
3157dd7cddfSDavid du Colombier 				lastp = r;
316375daca8SDavid du Colombier 				if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI)
3177dd7cddfSDavid du Colombier 					return;
3187dd7cddfSDavid du Colombier 				r->as = b;
3197dd7cddfSDavid du Colombier 				r->cond = p->link;
3207dd7cddfSDavid du Colombier 				r->link = p->cond;
3217dd7cddfSDavid du Colombier 				if(!(r->link->mark&FOLL))
3227dd7cddfSDavid du Colombier 					xfol(r->link);
3237dd7cddfSDavid du Colombier 				if(!(r->cond->mark&FOLL))
3247dd7cddfSDavid du Colombier 					print("cant happen 2\n");
3257dd7cddfSDavid du Colombier 				return;
3267dd7cddfSDavid du Colombier 			}
3277dd7cddfSDavid du Colombier 		}
3287dd7cddfSDavid du Colombier 
3297dd7cddfSDavid du Colombier 		a = ABR;
3307dd7cddfSDavid du Colombier 		q = prg();
3317dd7cddfSDavid du Colombier 		q->as = a;
3327dd7cddfSDavid du Colombier 		q->line = p->line;
3337dd7cddfSDavid du Colombier 		q->to.type = D_BRANCH;
3347dd7cddfSDavid du Colombier 		q->to.offset = p->pc;
3357dd7cddfSDavid du Colombier 		q->cond = p;
3367dd7cddfSDavid du Colombier 		p = q;
3377dd7cddfSDavid du Colombier 	}
3387dd7cddfSDavid du Colombier 	p->mark |= FOLL;
3397dd7cddfSDavid du Colombier 	lastp->link = p;
3407dd7cddfSDavid du Colombier 	lastp = p;
341375daca8SDavid du Colombier 	if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI){
3427dd7cddfSDavid du Colombier 		if(p->mark & NOSCHED){
3437dd7cddfSDavid du Colombier 			p = p->link;
3447dd7cddfSDavid du Colombier 			goto loop;
3457dd7cddfSDavid du Colombier 		}
3467dd7cddfSDavid du Colombier 		return;
3477dd7cddfSDavid du Colombier 	}
3487dd7cddfSDavid du Colombier 	if(p->cond != P)
3497dd7cddfSDavid du Colombier 	if(a != ABL && p->link != P) {
3507dd7cddfSDavid du Colombier 		xfol(p->link);
3517dd7cddfSDavid du Colombier 		p = p->cond;
3527dd7cddfSDavid du Colombier 		if(p == P || (p->mark&FOLL))
3537dd7cddfSDavid du Colombier 			return;
3547dd7cddfSDavid du Colombier 		goto loop;
3557dd7cddfSDavid du Colombier 	}
3567dd7cddfSDavid du Colombier 	p = p->link;
3577dd7cddfSDavid du Colombier 	goto loop;
3587dd7cddfSDavid du Colombier }
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier void
patch(void)3617dd7cddfSDavid du Colombier patch(void)
3627dd7cddfSDavid du Colombier {
3637dd7cddfSDavid du Colombier 	long c, vexit;
3647dd7cddfSDavid du Colombier 	Prog *p, *q;
3657dd7cddfSDavid du Colombier 	Sym *s;
3667dd7cddfSDavid du Colombier 	int a;
3677dd7cddfSDavid du Colombier 
3687dd7cddfSDavid du Colombier 	if(debug['v'])
3697dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f patch\n", cputime());
3707dd7cddfSDavid du Colombier 	Bflush(&bso);
3717dd7cddfSDavid du Colombier 	mkfwd();
3727dd7cddfSDavid du Colombier 	s = lookup("exit", 0);
3737dd7cddfSDavid du Colombier 	vexit = s->value;
3747dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
3757dd7cddfSDavid du Colombier 		a = p->as;
3767dd7cddfSDavid du Colombier 		if(a == ATEXT)
3777dd7cddfSDavid du Colombier 			curtext = p;
3787dd7cddfSDavid du Colombier 		if((a == ABL || a == ARETURN) && p->to.sym != S) {
3797dd7cddfSDavid du Colombier 			s = p->to.sym;
380375daca8SDavid du Colombier 			if(s->type != STEXT && s->type != SUNDEF) {
3816b6b9ac8SDavid du Colombier 				diag("undefined: %s\n%P", s->name, p);
3827dd7cddfSDavid du Colombier 				s->type = STEXT;
3837dd7cddfSDavid du Colombier 				s->value = vexit;
3847dd7cddfSDavid du Colombier 			}
385375daca8SDavid du Colombier 			if(s->type == SUNDEF){
386375daca8SDavid du Colombier 				p->to.offset = 0;
387375daca8SDavid du Colombier 				p->cond = UP;
388375daca8SDavid du Colombier 			}
389375daca8SDavid du Colombier 			else
3907dd7cddfSDavid du Colombier 				p->to.offset = s->value;
3917dd7cddfSDavid du Colombier 			p->to.type = D_BRANCH;
3927dd7cddfSDavid du Colombier 		}
393375daca8SDavid du Colombier 		if(p->to.type != D_BRANCH || p->cond == UP)
3947dd7cddfSDavid du Colombier 			continue;
3957dd7cddfSDavid du Colombier 		c = p->to.offset;
3967dd7cddfSDavid du Colombier 		for(q = firstp; q != P;) {
3977dd7cddfSDavid du Colombier 			if(q->forwd != P)
3987dd7cddfSDavid du Colombier 			if(c >= q->forwd->pc) {
3997dd7cddfSDavid du Colombier 				q = q->forwd;
4007dd7cddfSDavid du Colombier 				continue;
4017dd7cddfSDavid du Colombier 			}
4027dd7cddfSDavid du Colombier 			if(c == q->pc)
4037dd7cddfSDavid du Colombier 				break;
4047dd7cddfSDavid du Colombier 			q = q->link;
4057dd7cddfSDavid du Colombier 		}
4067dd7cddfSDavid du Colombier 		if(q == P) {
4076b6b9ac8SDavid du Colombier 			diag("branch out of range %ld\n%P", c, p);
4087dd7cddfSDavid du Colombier 			p->to.type = D_NONE;
4097dd7cddfSDavid du Colombier 		}
4107dd7cddfSDavid du Colombier 		p->cond = q;
4117dd7cddfSDavid du Colombier 	}
4127dd7cddfSDavid du Colombier 
4137dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
4147dd7cddfSDavid du Colombier 		if(p->as == ATEXT)
4157dd7cddfSDavid du Colombier 			curtext = p;
416375daca8SDavid du Colombier 		p->mark = 0;	/* initialization for follow */
417375daca8SDavid du Colombier 		if(p->cond != P && p->cond != UP) {
4187dd7cddfSDavid du Colombier 			p->cond = brloop(p->cond);
4197dd7cddfSDavid du Colombier 			if(p->cond != P)
4207dd7cddfSDavid du Colombier 			if(p->to.type == D_BRANCH)
4217dd7cddfSDavid du Colombier 				p->to.offset = p->cond->pc;
4227dd7cddfSDavid du Colombier 		}
4237dd7cddfSDavid du Colombier 	}
4247dd7cddfSDavid du Colombier }
4257dd7cddfSDavid du Colombier 
4267dd7cddfSDavid du Colombier #define	LOG	5
4277dd7cddfSDavid du Colombier void
mkfwd(void)4287dd7cddfSDavid du Colombier mkfwd(void)
4297dd7cddfSDavid du Colombier {
4307dd7cddfSDavid du Colombier 	Prog *p;
4317dd7cddfSDavid du Colombier 	long dwn[LOG], cnt[LOG], i;
4327dd7cddfSDavid du Colombier 	Prog *lst[LOG];
4337dd7cddfSDavid du Colombier 
4347dd7cddfSDavid du Colombier 	for(i=0; i<LOG; i++) {
4357dd7cddfSDavid du Colombier 		if(i == 0)
4367dd7cddfSDavid du Colombier 			cnt[i] = 1; else
4377dd7cddfSDavid du Colombier 			cnt[i] = LOG * cnt[i-1];
4387dd7cddfSDavid du Colombier 		dwn[i] = 1;
4397dd7cddfSDavid du Colombier 		lst[i] = P;
4407dd7cddfSDavid du Colombier 	}
4417dd7cddfSDavid du Colombier 	i = 0;
4427dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
4437dd7cddfSDavid du Colombier 		if(p->as == ATEXT)
4447dd7cddfSDavid du Colombier 			curtext = p;
4457dd7cddfSDavid du Colombier 		i--;
4467dd7cddfSDavid du Colombier 		if(i < 0)
4477dd7cddfSDavid du Colombier 			i = LOG-1;
4487dd7cddfSDavid du Colombier 		p->forwd = P;
4497dd7cddfSDavid du Colombier 		dwn[i]--;
4507dd7cddfSDavid du Colombier 		if(dwn[i] <= 0) {
4517dd7cddfSDavid du Colombier 			dwn[i] = cnt[i];
4527dd7cddfSDavid du Colombier 			if(lst[i] != P)
4537dd7cddfSDavid du Colombier 				lst[i]->forwd = p;
4547dd7cddfSDavid du Colombier 			lst[i] = p;
4557dd7cddfSDavid du Colombier 		}
4567dd7cddfSDavid du Colombier 	}
4577dd7cddfSDavid du Colombier }
4587dd7cddfSDavid du Colombier 
4597dd7cddfSDavid du Colombier Prog*
brloop(Prog * p)4607dd7cddfSDavid du Colombier brloop(Prog *p)
4617dd7cddfSDavid du Colombier {
4627dd7cddfSDavid du Colombier 	Prog *q;
4637dd7cddfSDavid du Colombier 	int c;
4647dd7cddfSDavid du Colombier 
4657dd7cddfSDavid du Colombier 	for(c=0; p!=P;) {
4667dd7cddfSDavid du Colombier 		if(p->as != ABR || (p->mark&NOSCHED))
4677dd7cddfSDavid du Colombier 			return p;
4687dd7cddfSDavid du Colombier 		q = p->cond;
4697dd7cddfSDavid du Colombier 		if(q <= p) {
4707dd7cddfSDavid du Colombier 			c++;
4717dd7cddfSDavid du Colombier 			if(q == p || c > 5000)
4727dd7cddfSDavid du Colombier 				break;
4737dd7cddfSDavid du Colombier 		}
4747dd7cddfSDavid du Colombier 		p = q;
4757dd7cddfSDavid du Colombier 	}
4767dd7cddfSDavid du Colombier 	return P;
4777dd7cddfSDavid du Colombier }
4787dd7cddfSDavid du Colombier 
4797dd7cddfSDavid du Colombier long
atolwhex(char * s)4807dd7cddfSDavid du Colombier atolwhex(char *s)
4817dd7cddfSDavid du Colombier {
4827dd7cddfSDavid du Colombier 	long n;
4837dd7cddfSDavid du Colombier 	int f;
4847dd7cddfSDavid du Colombier 
4857dd7cddfSDavid du Colombier 	n = 0;
4867dd7cddfSDavid du Colombier 	f = 0;
4877dd7cddfSDavid du Colombier 	while(*s == ' ' || *s == '\t')
4887dd7cddfSDavid du Colombier 		s++;
4897dd7cddfSDavid du Colombier 	if(*s == '-' || *s == '+') {
4907dd7cddfSDavid du Colombier 		if(*s++ == '-')
4917dd7cddfSDavid du Colombier 			f = 1;
4927dd7cddfSDavid du Colombier 		while(*s == ' ' || *s == '\t')
4937dd7cddfSDavid du Colombier 			s++;
4947dd7cddfSDavid du Colombier 	}
4957dd7cddfSDavid du Colombier 	if(s[0]=='0' && s[1]){
4967dd7cddfSDavid du Colombier 		if(s[1]=='x' || s[1]=='X'){
4977dd7cddfSDavid du Colombier 			s += 2;
4987dd7cddfSDavid du Colombier 			for(;;){
4997dd7cddfSDavid du Colombier 				if(*s >= '0' && *s <= '9')
5007dd7cddfSDavid du Colombier 					n = n*16 + *s++ - '0';
5017dd7cddfSDavid du Colombier 				else if(*s >= 'a' && *s <= 'f')
5027dd7cddfSDavid du Colombier 					n = n*16 + *s++ - 'a' + 10;
5037dd7cddfSDavid du Colombier 				else if(*s >= 'A' && *s <= 'F')
5047dd7cddfSDavid du Colombier 					n = n*16 + *s++ - 'A' + 10;
5057dd7cddfSDavid du Colombier 				else
5067dd7cddfSDavid du Colombier 					break;
5077dd7cddfSDavid du Colombier 			}
5087dd7cddfSDavid du Colombier 		} else
5097dd7cddfSDavid du Colombier 			while(*s >= '0' && *s <= '7')
5107dd7cddfSDavid du Colombier 				n = n*8 + *s++ - '0';
5117dd7cddfSDavid du Colombier 	} else
5127dd7cddfSDavid du Colombier 		while(*s >= '0' && *s <= '9')
5137dd7cddfSDavid du Colombier 			n = n*10 + *s++ - '0';
5147dd7cddfSDavid du Colombier 	if(f)
5157dd7cddfSDavid du Colombier 		n = -n;
5167dd7cddfSDavid du Colombier 	return n;
5177dd7cddfSDavid du Colombier }
5187dd7cddfSDavid du Colombier 
5197dd7cddfSDavid du Colombier long
rnd(long v,long r)5207dd7cddfSDavid du Colombier rnd(long v, long r)
5217dd7cddfSDavid du Colombier {
5227dd7cddfSDavid du Colombier 	long c;
5237dd7cddfSDavid du Colombier 
5247dd7cddfSDavid du Colombier 	if(r <= 0)
5257dd7cddfSDavid du Colombier 		return v;
5267dd7cddfSDavid du Colombier 	v += r - 1;
5277dd7cddfSDavid du Colombier 	c = v % r;
5287dd7cddfSDavid du Colombier 	if(c < 0)
5297dd7cddfSDavid du Colombier 		c += r;
5307dd7cddfSDavid du Colombier 	v -= c;
5317dd7cddfSDavid du Colombier 	return v;
5327dd7cddfSDavid du Colombier }
533375daca8SDavid du Colombier 
534375daca8SDavid du Colombier void
import(void)535375daca8SDavid du Colombier import(void)
536375daca8SDavid du Colombier {
537375daca8SDavid du Colombier 	int i;
538375daca8SDavid du Colombier 	Sym *s;
539375daca8SDavid du Colombier 
540375daca8SDavid du Colombier 	for(i = 0; i < NHASH; i++)
541375daca8SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
542375daca8SDavid du Colombier 			if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
543375daca8SDavid du Colombier 				undefsym(s);
544375daca8SDavid du Colombier 				Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value);
545375daca8SDavid du Colombier 			}
546375daca8SDavid du Colombier }
547375daca8SDavid du Colombier 
548375daca8SDavid du Colombier void
ckoff(Sym * s,long v)549375daca8SDavid du Colombier ckoff(Sym *s, long v)
550375daca8SDavid du Colombier {
551375daca8SDavid du Colombier 	if(v < 0 || v >= 1<<Roffset)
552375daca8SDavid du Colombier 		diag("relocation offset %ld for %s out of range", v, s->name);
553375daca8SDavid du Colombier }
554375daca8SDavid du Colombier 
555375daca8SDavid du Colombier static Prog*
newdata(Sym * s,int o,int w,int t)556375daca8SDavid du Colombier newdata(Sym *s, int o, int w, int t)
557375daca8SDavid du Colombier {
558375daca8SDavid du Colombier 	Prog *p;
559375daca8SDavid du Colombier 
560375daca8SDavid du Colombier 	p = prg();
561375daca8SDavid du Colombier 	p->link = datap;
562375daca8SDavid du Colombier 	datap = p;
563375daca8SDavid du Colombier 	p->as = ADATA;
564375daca8SDavid du Colombier 	p->reg = w;
565375daca8SDavid du Colombier 	p->from.type = D_OREG;
566375daca8SDavid du Colombier 	p->from.name = t;
567375daca8SDavid du Colombier 	p->from.sym = s;
568375daca8SDavid du Colombier 	p->from.offset = o;
569375daca8SDavid du Colombier 	p->to.type = D_CONST;
570375daca8SDavid du Colombier 	p->to.name = D_NONE;
571375daca8SDavid du Colombier 	return p;
572375daca8SDavid du Colombier }
573375daca8SDavid du Colombier 
574375daca8SDavid du Colombier void
export(void)575375daca8SDavid du Colombier export(void)
576375daca8SDavid du Colombier {
577375daca8SDavid du Colombier 	int i, j, n, off, nb, sv, ne;
578375daca8SDavid du Colombier 	Sym *s, *et, *str, **esyms;
579375daca8SDavid du Colombier 	Prog *p;
580375daca8SDavid du Colombier 	char buf[NSNAME], *t;
581375daca8SDavid du Colombier 
582375daca8SDavid du Colombier 	n = 0;
583375daca8SDavid du Colombier 	for(i = 0; i < NHASH; i++)
584375daca8SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
585375daca8SDavid du Colombier 			if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
586375daca8SDavid du Colombier 				n++;
587375daca8SDavid du Colombier 	esyms = malloc(n*sizeof(Sym*));
588375daca8SDavid du Colombier 	ne = n;
589375daca8SDavid du Colombier 	n = 0;
590375daca8SDavid du Colombier 	for(i = 0; i < NHASH; i++)
591375daca8SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
592375daca8SDavid du Colombier 			if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
593375daca8SDavid du Colombier 				esyms[n++] = s;
594375daca8SDavid du Colombier 	for(i = 0; i < ne-1; i++)
595375daca8SDavid du Colombier 		for(j = i+1; j < ne; j++)
596375daca8SDavid du Colombier 			if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
597375daca8SDavid du Colombier 				s = esyms[i];
598375daca8SDavid du Colombier 				esyms[i] = esyms[j];
599375daca8SDavid du Colombier 				esyms[j] = s;
600375daca8SDavid du Colombier 			}
601375daca8SDavid du Colombier 
602375daca8SDavid du Colombier 	nb = 0;
603375daca8SDavid du Colombier 	off = 0;
604375daca8SDavid du Colombier 	et = lookup(EXPTAB, 0);
605375daca8SDavid du Colombier 	if(et->type != 0 && et->type != SXREF)
606375daca8SDavid du Colombier 		diag("%s already defined", EXPTAB);
607375daca8SDavid du Colombier 	et->type = SDATA;
608375daca8SDavid du Colombier 	str = lookup(".string", 0);
609375daca8SDavid du Colombier 	if(str->type == 0)
610375daca8SDavid du Colombier 		str->type = SDATA;
611375daca8SDavid du Colombier 	sv = str->value;
612375daca8SDavid du Colombier 	for(i = 0; i < ne; i++){
613375daca8SDavid du Colombier 		s = esyms[i];
614375daca8SDavid du Colombier 		Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
615375daca8SDavid du Colombier 
616375daca8SDavid du Colombier 		/* signature */
617375daca8SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
618375daca8SDavid du Colombier 		off += sizeof(long);
619375daca8SDavid du Colombier 		p->to.offset = s->sig;
620375daca8SDavid du Colombier 
621375daca8SDavid du Colombier 		/* address */
622375daca8SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
623375daca8SDavid du Colombier 		off += sizeof(long);
624375daca8SDavid du Colombier 		p->to.name = D_EXTERN;
625375daca8SDavid du Colombier 		p->to.sym = s;
626375daca8SDavid du Colombier 
627375daca8SDavid du Colombier 		/* string */
628375daca8SDavid du Colombier 		t = s->name;
629375daca8SDavid du Colombier 		n = strlen(t)+1;
630375daca8SDavid du Colombier 		for(;;){
631375daca8SDavid du Colombier 			buf[nb++] = *t;
632375daca8SDavid du Colombier 			sv++;
633375daca8SDavid du Colombier 			if(nb >= NSNAME){
634375daca8SDavid du Colombier 				p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
635375daca8SDavid du Colombier 				p->to.type = D_SCONST;
636375daca8SDavid du Colombier 				memmove(p->to.sval, buf, NSNAME);
637375daca8SDavid du Colombier 				nb = 0;
638375daca8SDavid du Colombier 			}
639375daca8SDavid du Colombier 			if(*t++ == 0)
640375daca8SDavid du Colombier 				break;
641375daca8SDavid du Colombier 		}
642375daca8SDavid du Colombier 
643375daca8SDavid du Colombier 		/* name */
644375daca8SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
645375daca8SDavid du Colombier 		off += sizeof(long);
646375daca8SDavid du Colombier 		p->to.name = D_STATIC;
647375daca8SDavid du Colombier 		p->to.sym = str;
648375daca8SDavid du Colombier 		p->to.offset = sv-n;
649375daca8SDavid du Colombier 	}
650375daca8SDavid du Colombier 
651375daca8SDavid du Colombier 	if(nb > 0){
652375daca8SDavid du Colombier 		p = newdata(str, sv-nb, nb, D_STATIC);
653375daca8SDavid du Colombier 		p->to.type = D_SCONST;
654375daca8SDavid du Colombier 		memmove(p->to.sval, buf, nb);
655375daca8SDavid du Colombier 	}
656375daca8SDavid du Colombier 
657375daca8SDavid du Colombier 	for(i = 0; i < 3; i++){
658375daca8SDavid du Colombier 		newdata(et, off, sizeof(long), D_EXTERN);
659375daca8SDavid du Colombier 		off += sizeof(long);
660375daca8SDavid du Colombier 	}
661375daca8SDavid du Colombier 	et->value = off;
662375daca8SDavid du Colombier 	if(sv == 0)
663375daca8SDavid du Colombier 		sv = 1;
664375daca8SDavid du Colombier 	str->value = sv;
665375daca8SDavid du Colombier 	exports = ne;
666375daca8SDavid du Colombier 	free(esyms);
667375daca8SDavid du Colombier }
668