xref: /plan9/sys/src/cmd/5l/pass.c (revision 375daca8932d0755549a5f8e4d068a24a49927d4)
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;
97dd7cddfSDavid du Colombier 	long orig, 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 
299a747e4fSDavid du Colombier 	if(debug['t']) {
309a747e4fSDavid du Colombier 		/*
319a747e4fSDavid du Colombier 		 * pull out string constants
329a747e4fSDavid du Colombier 		 */
339a747e4fSDavid du Colombier 		for(p = datap; p != P; p = p->link) {
349a747e4fSDavid du Colombier 			s = p->from.sym;
359a747e4fSDavid du Colombier 			if(p->to.type == D_SCONST)
369a747e4fSDavid du Colombier 				s->type = SSTRING;
379a747e4fSDavid du Colombier 		}
389a747e4fSDavid du Colombier 	}
399a747e4fSDavid du Colombier 
407dd7cddfSDavid du Colombier 	/*
417dd7cddfSDavid du Colombier 	 * pass 1
427dd7cddfSDavid du Colombier 	 *	assign 'small' variables to data segment
437dd7cddfSDavid du Colombier 	 *	(rational is that data segment is more easily
447dd7cddfSDavid du Colombier 	 *	 addressed through offset on R12)
457dd7cddfSDavid du Colombier 	 */
467dd7cddfSDavid du Colombier 	orig = 0;
477dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
487dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
497dd7cddfSDavid du Colombier 		t = s->type;
507dd7cddfSDavid du Colombier 		if(t != SDATA && t != SBSS)
517dd7cddfSDavid du Colombier 			continue;
527dd7cddfSDavid du Colombier 		v = s->value;
537dd7cddfSDavid du Colombier 		if(v == 0) {
546b6b9ac8SDavid du Colombier 			diag("%s: no size", s->name);
557dd7cddfSDavid du Colombier 			v = 1;
567dd7cddfSDavid du Colombier 		}
577dd7cddfSDavid du Colombier 		while(v & 3)
587dd7cddfSDavid du Colombier 			v++;
597dd7cddfSDavid du Colombier 		s->value = v;
607dd7cddfSDavid du Colombier 		if(v > MINSIZ)
617dd7cddfSDavid du Colombier 			continue;
627dd7cddfSDavid du Colombier 		s->value = orig;
637dd7cddfSDavid du Colombier 		orig += v;
647dd7cddfSDavid du Colombier 		s->type = SDATA1;
657dd7cddfSDavid du Colombier 	}
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier 	/*
687dd7cddfSDavid du Colombier 	 * pass 2
697dd7cddfSDavid du Colombier 	 *	assign large 'data' variables to data segment
707dd7cddfSDavid du Colombier 	 */
717dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
727dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
737dd7cddfSDavid du Colombier 		t = s->type;
747dd7cddfSDavid du Colombier 		if(t != SDATA) {
757dd7cddfSDavid du Colombier 			if(t == SDATA1)
767dd7cddfSDavid du Colombier 				s->type = SDATA;
777dd7cddfSDavid du Colombier 			continue;
787dd7cddfSDavid du Colombier 		}
797dd7cddfSDavid du Colombier 		v = s->value;
807dd7cddfSDavid du Colombier 		s->value = orig;
817dd7cddfSDavid du Colombier 		orig += v;
827dd7cddfSDavid du Colombier 	}
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier 	while(orig & 7)
857dd7cddfSDavid du Colombier 		orig++;
867dd7cddfSDavid du Colombier 	datsize = orig;
877dd7cddfSDavid du Colombier 
887dd7cddfSDavid du Colombier 	/*
897dd7cddfSDavid du Colombier 	 * pass 3
907dd7cddfSDavid du Colombier 	 *	everything else to bss segment
917dd7cddfSDavid du Colombier 	 */
927dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
937dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
947dd7cddfSDavid du Colombier 		if(s->type != SBSS)
957dd7cddfSDavid du Colombier 			continue;
967dd7cddfSDavid du Colombier 		v = s->value;
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 	xdefine("setR12", SDATA, 0L+BIG);
1057dd7cddfSDavid du Colombier 	xdefine("bdata", SDATA, 0L);
1067dd7cddfSDavid du Colombier 	xdefine("edata", SDATA, datsize);
1077dd7cddfSDavid du Colombier 	xdefine("end", SBSS, datsize+bsssize);
1087dd7cddfSDavid du Colombier 	xdefine("etext", STEXT, 0L);
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier void
undef(void)1127dd7cddfSDavid du Colombier undef(void)
1137dd7cddfSDavid du Colombier {
1147dd7cddfSDavid du Colombier 	int i;
1157dd7cddfSDavid du Colombier 	Sym *s;
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
1187dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link)
1197dd7cddfSDavid du Colombier 		if(s->type == SXREF)
1206b6b9ac8SDavid du Colombier 			diag("%s: not defined", s->name);
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier 
12359cc4ca5SDavid du Colombier Prog*
brchain(Prog * p)12459cc4ca5SDavid du Colombier brchain(Prog *p)
12559cc4ca5SDavid du Colombier {
12659cc4ca5SDavid du Colombier 	int i;
12759cc4ca5SDavid du Colombier 
12859cc4ca5SDavid du Colombier 	for(i=0; i<20; i++) {
12959cc4ca5SDavid du Colombier 		if(p == P || p->as != AB)
13059cc4ca5SDavid du Colombier 			return p;
13159cc4ca5SDavid du Colombier 		p = p->cond;
13259cc4ca5SDavid du Colombier 	}
13359cc4ca5SDavid du Colombier 	return P;
13459cc4ca5SDavid du Colombier }
13559cc4ca5SDavid du Colombier 
13659cc4ca5SDavid du Colombier int
relinv(int a)13759cc4ca5SDavid du Colombier relinv(int a)
13859cc4ca5SDavid du Colombier {
13959cc4ca5SDavid du Colombier 	switch(a) {
14059cc4ca5SDavid du Colombier 	case ABEQ:	return ABNE;
14159cc4ca5SDavid du Colombier 	case ABNE:	return ABEQ;
14259cc4ca5SDavid du Colombier 	case ABCS:	return ABCC;
14359cc4ca5SDavid du Colombier 	case ABHS:	return ABLO;
14459cc4ca5SDavid du Colombier 	case ABCC:	return ABCS;
14559cc4ca5SDavid du Colombier 	case ABLO:	return ABHS;
14659cc4ca5SDavid du Colombier 	case ABMI:	return ABPL;
14759cc4ca5SDavid du Colombier 	case ABPL:	return ABMI;
14859cc4ca5SDavid du Colombier 	case ABVS:	return ABVC;
14959cc4ca5SDavid du Colombier 	case ABVC:	return ABVS;
15059cc4ca5SDavid du Colombier 	case ABHI:	return ABLS;
15159cc4ca5SDavid du Colombier 	case ABLS:	return ABHI;
15259cc4ca5SDavid du Colombier 	case ABGE:	return ABLT;
15359cc4ca5SDavid du Colombier 	case ABLT:	return ABGE;
15459cc4ca5SDavid du Colombier 	case ABGT:	return ABLE;
15559cc4ca5SDavid du Colombier 	case ABLE:	return ABGT;
15659cc4ca5SDavid du Colombier 	}
1576b6b9ac8SDavid du Colombier 	diag("unknown relation: %s", anames[a]);
15859cc4ca5SDavid du Colombier 	return a;
15959cc4ca5SDavid du Colombier }
16059cc4ca5SDavid du Colombier 
1617dd7cddfSDavid du Colombier void
follow(void)1627dd7cddfSDavid du Colombier follow(void)
1637dd7cddfSDavid du Colombier {
1647dd7cddfSDavid du Colombier 	if(debug['v'])
1657dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f follow\n", cputime());
1667dd7cddfSDavid du Colombier 	Bflush(&bso);
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier 	firstp = prg();
1697dd7cddfSDavid du Colombier 	lastp = firstp;
1707dd7cddfSDavid du Colombier 	xfol(textp);
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier 	firstp = firstp->link;
1737dd7cddfSDavid du Colombier 	lastp->link = P;
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier void
xfol(Prog * p)1777dd7cddfSDavid du Colombier xfol(Prog *p)
1787dd7cddfSDavid du Colombier {
1797dd7cddfSDavid du Colombier 	Prog *q, *r;
1807dd7cddfSDavid du Colombier 	int a, i;
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier loop:
1837dd7cddfSDavid du Colombier 	if(p == P)
1847dd7cddfSDavid du Colombier 		return;
1857dd7cddfSDavid du Colombier 	a = p->as;
1867dd7cddfSDavid du Colombier 	if(a == ATEXT)
1877dd7cddfSDavid du Colombier 		curtext = p;
1887dd7cddfSDavid du Colombier 	if(a == AB) {
1897dd7cddfSDavid du Colombier 		q = p->cond;
1907dd7cddfSDavid du Colombier 		if(q != P) {
1917dd7cddfSDavid du Colombier 			p->mark |= FOLL;
1927dd7cddfSDavid du Colombier 			p = q;
1937dd7cddfSDavid du Colombier 			if(!(p->mark & FOLL))
1947dd7cddfSDavid du Colombier 				goto loop;
1957dd7cddfSDavid du Colombier 		}
1967dd7cddfSDavid du Colombier 	}
1977dd7cddfSDavid du Colombier 	if(p->mark & FOLL) {
1987dd7cddfSDavid du Colombier 		for(i=0,q=p; i<4; i++,q=q->link) {
1997dd7cddfSDavid du Colombier 			if(q == lastp)
2007dd7cddfSDavid du Colombier 				break;
2017dd7cddfSDavid du Colombier 			a = q->as;
2027dd7cddfSDavid du Colombier 			if(a == ANOP) {
2037dd7cddfSDavid du Colombier 				i--;
2047dd7cddfSDavid du Colombier 				continue;
2057dd7cddfSDavid du Colombier 			}
20659cc4ca5SDavid du Colombier 			if(a == AB || (a == ARET && q->scond == 14) || a == ARFE)
2077dd7cddfSDavid du Colombier 				goto copy;
2087dd7cddfSDavid du Colombier 			if(!q->cond || (q->cond->mark&FOLL))
2097dd7cddfSDavid du Colombier 				continue;
2107dd7cddfSDavid du Colombier 			if(a != ABEQ && a != ABNE)
2117dd7cddfSDavid du Colombier 				continue;
2127dd7cddfSDavid du Colombier 		copy:
2137dd7cddfSDavid du Colombier 			for(;;) {
2147dd7cddfSDavid du Colombier 				r = prg();
2157dd7cddfSDavid du Colombier 				*r = *p;
2167dd7cddfSDavid du Colombier 				if(!(r->mark&FOLL))
2177dd7cddfSDavid du Colombier 					print("cant happen 1\n");
2187dd7cddfSDavid du Colombier 				r->mark |= FOLL;
2197dd7cddfSDavid du Colombier 				if(p != q) {
2207dd7cddfSDavid du Colombier 					p = p->link;
2217dd7cddfSDavid du Colombier 					lastp->link = r;
2227dd7cddfSDavid du Colombier 					lastp = r;
2237dd7cddfSDavid du Colombier 					continue;
2247dd7cddfSDavid du Colombier 				}
2257dd7cddfSDavid du Colombier 				lastp->link = r;
2267dd7cddfSDavid du Colombier 				lastp = r;
22759cc4ca5SDavid du Colombier 				if(a == AB || (a == ARET && q->scond == 14) || a == ARFE)
2287dd7cddfSDavid du Colombier 					return;
2297dd7cddfSDavid du Colombier 				r->as = ABNE;
2307dd7cddfSDavid du Colombier 				if(a == ABNE)
2317dd7cddfSDavid du Colombier 					r->as = ABEQ;
2327dd7cddfSDavid du Colombier 				r->cond = p->link;
2337dd7cddfSDavid du Colombier 				r->link = p->cond;
2347dd7cddfSDavid du Colombier 				if(!(r->link->mark&FOLL))
2357dd7cddfSDavid du Colombier 					xfol(r->link);
2367dd7cddfSDavid du Colombier 				if(!(r->cond->mark&FOLL))
2377dd7cddfSDavid du Colombier 					print("cant happen 2\n");
2387dd7cddfSDavid du Colombier 				return;
2397dd7cddfSDavid du Colombier 			}
2407dd7cddfSDavid du Colombier 		}
2417dd7cddfSDavid du Colombier 		a = AB;
2427dd7cddfSDavid du Colombier 		q = prg();
2437dd7cddfSDavid du Colombier 		q->as = a;
2447dd7cddfSDavid du Colombier 		q->line = p->line;
2457dd7cddfSDavid du Colombier 		q->to.type = D_BRANCH;
2467dd7cddfSDavid du Colombier 		q->to.offset = p->pc;
2477dd7cddfSDavid du Colombier 		q->cond = p;
2487dd7cddfSDavid du Colombier 		p = q;
2497dd7cddfSDavid du Colombier 	}
2507dd7cddfSDavid du Colombier 	p->mark |= FOLL;
2517dd7cddfSDavid du Colombier 	lastp->link = p;
2527dd7cddfSDavid du Colombier 	lastp = p;
25359cc4ca5SDavid du Colombier 	if(a == AB || (a == ARET && p->scond == 14) || a == ARFE){
2547dd7cddfSDavid du Colombier 		return;
2557dd7cddfSDavid du Colombier 	}
2567dd7cddfSDavid du Colombier 	if(p->cond != P)
2577dd7cddfSDavid du Colombier 	if(a != ABL && p->link != P) {
25859cc4ca5SDavid du Colombier 		q = brchain(p->link);
25959cc4ca5SDavid du Colombier 		if(a != ATEXT && a != ABCASE)
26059cc4ca5SDavid du Colombier 		if(q != P && (q->mark&FOLL)) {
26159cc4ca5SDavid du Colombier 			p->as = relinv(a);
26259cc4ca5SDavid du Colombier 			p->link = p->cond;
26359cc4ca5SDavid du Colombier 			p->cond = q;
26459cc4ca5SDavid du Colombier 		}
2657dd7cddfSDavid du Colombier 		xfol(p->link);
26659cc4ca5SDavid du Colombier 		q = brchain(p->cond);
26759cc4ca5SDavid du Colombier 		if(q == P)
26859cc4ca5SDavid du Colombier 			q = p->cond;
26959cc4ca5SDavid du Colombier 		if(q->mark&FOLL) {
27059cc4ca5SDavid du Colombier 			p->cond = q;
2717dd7cddfSDavid du Colombier 			return;
27259cc4ca5SDavid du Colombier 		}
27359cc4ca5SDavid du Colombier 		p = q;
2747dd7cddfSDavid du Colombier 		goto loop;
2757dd7cddfSDavid du Colombier 	}
2767dd7cddfSDavid du Colombier 	p = p->link;
2777dd7cddfSDavid du Colombier 	goto loop;
2787dd7cddfSDavid du Colombier }
2797dd7cddfSDavid du Colombier 
2807dd7cddfSDavid du Colombier void
patch(void)2817dd7cddfSDavid du Colombier patch(void)
2827dd7cddfSDavid du Colombier {
2837dd7cddfSDavid du Colombier 	long c, vexit;
2847dd7cddfSDavid du Colombier 	Prog *p, *q;
2857dd7cddfSDavid du Colombier 	Sym *s;
2867dd7cddfSDavid du Colombier 	int a;
2877dd7cddfSDavid du Colombier 
2887dd7cddfSDavid du Colombier 	if(debug['v'])
2897dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f patch\n", cputime());
2907dd7cddfSDavid du Colombier 	Bflush(&bso);
2917dd7cddfSDavid du Colombier 	mkfwd();
2927dd7cddfSDavid du Colombier 	s = lookup("exit", 0);
2937dd7cddfSDavid du Colombier 	vexit = s->value;
2947dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
2957dd7cddfSDavid du Colombier 		a = p->as;
2967dd7cddfSDavid du Colombier 		if(a == ATEXT)
2977dd7cddfSDavid du Colombier 			curtext = p;
2987dd7cddfSDavid du Colombier 		if((a == ABL || a == AB || a == ARET) &&
2997dd7cddfSDavid du Colombier 		   p->to.type != D_BRANCH && p->to.sym != S) {
3007dd7cddfSDavid du Colombier 			s = p->to.sym;
301*375daca8SDavid du Colombier 			switch(s->type) {
302*375daca8SDavid du Colombier 			default:
3036b6b9ac8SDavid du Colombier 				diag("undefined: %s\n%P", s->name, p);
3047dd7cddfSDavid du Colombier 				s->type = STEXT;
3057dd7cddfSDavid du Colombier 				s->value = vexit;
306*375daca8SDavid du Colombier 				break;
307*375daca8SDavid du Colombier 			case STEXT:
3087dd7cddfSDavid du Colombier 				p->to.offset = s->value;
3097dd7cddfSDavid du Colombier 				p->to.type = D_BRANCH;
310*375daca8SDavid du Colombier 				break;
311*375daca8SDavid du Colombier 			case SUNDEF:
312*375daca8SDavid du Colombier 				if(p->as != ABL)
313*375daca8SDavid du Colombier 					diag("help: SUNDEF in AB || ARET");
314*375daca8SDavid du Colombier 				p->to.offset = 0;
315*375daca8SDavid du Colombier 				p->to.type = D_BRANCH;
316*375daca8SDavid du Colombier 				p->cond = UP;
317*375daca8SDavid du Colombier 				break;
3187dd7cddfSDavid du Colombier 			}
319*375daca8SDavid du Colombier 		}
320*375daca8SDavid du Colombier 		if(p->to.type != D_BRANCH || p->cond == UP)
3217dd7cddfSDavid du Colombier 			continue;
3227dd7cddfSDavid du Colombier 		c = p->to.offset;
3237dd7cddfSDavid du Colombier 		for(q = firstp; q != P;) {
3247dd7cddfSDavid du Colombier 			if(q->forwd != P)
3257dd7cddfSDavid du Colombier 			if(c >= q->forwd->pc) {
3267dd7cddfSDavid du Colombier 				q = q->forwd;
3277dd7cddfSDavid du Colombier 				continue;
3287dd7cddfSDavid du Colombier 			}
3297dd7cddfSDavid du Colombier 			if(c == q->pc)
3307dd7cddfSDavid du Colombier 				break;
3317dd7cddfSDavid du Colombier 			q = q->link;
3327dd7cddfSDavid du Colombier 		}
3337dd7cddfSDavid du Colombier 		if(q == P) {
3346b6b9ac8SDavid du Colombier 			diag("branch out of range %ld\n%P", c, p);
3357dd7cddfSDavid du Colombier 			p->to.type = D_NONE;
3367dd7cddfSDavid du Colombier 		}
3377dd7cddfSDavid du Colombier 		p->cond = q;
3387dd7cddfSDavid du Colombier 	}
3397dd7cddfSDavid du Colombier 
3407dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
3417dd7cddfSDavid du Colombier 		if(p->as == ATEXT)
3427dd7cddfSDavid du Colombier 			curtext = p;
3439a747e4fSDavid du Colombier 		if(p->cond != P && p->cond != UP) {
3447dd7cddfSDavid du Colombier 			p->cond = brloop(p->cond);
3457dd7cddfSDavid du Colombier 			if(p->cond != P)
3467dd7cddfSDavid du Colombier 			if(p->to.type == D_BRANCH)
3477dd7cddfSDavid du Colombier 				p->to.offset = p->cond->pc;
3487dd7cddfSDavid du Colombier 		}
3497dd7cddfSDavid du Colombier 	}
3507dd7cddfSDavid du Colombier }
3517dd7cddfSDavid du Colombier 
3527dd7cddfSDavid du Colombier #define	LOG	5
3537dd7cddfSDavid du Colombier void
mkfwd(void)3547dd7cddfSDavid du Colombier mkfwd(void)
3557dd7cddfSDavid du Colombier {
3567dd7cddfSDavid du Colombier 	Prog *p;
3577dd7cddfSDavid du Colombier 	long dwn[LOG], cnt[LOG], i;
3587dd7cddfSDavid du Colombier 	Prog *lst[LOG];
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier 	for(i=0; i<LOG; i++) {
3617dd7cddfSDavid du Colombier 		if(i == 0)
3627dd7cddfSDavid du Colombier 			cnt[i] = 1; else
3637dd7cddfSDavid du Colombier 			cnt[i] = LOG * cnt[i-1];
3647dd7cddfSDavid du Colombier 		dwn[i] = 1;
3657dd7cddfSDavid du Colombier 		lst[i] = P;
3667dd7cddfSDavid du Colombier 	}
3677dd7cddfSDavid du Colombier 	i = 0;
3687dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
3697dd7cddfSDavid du Colombier 		if(p->as == ATEXT)
3707dd7cddfSDavid du Colombier 			curtext = p;
3717dd7cddfSDavid du Colombier 		i--;
3727dd7cddfSDavid du Colombier 		if(i < 0)
3737dd7cddfSDavid du Colombier 			i = LOG-1;
3747dd7cddfSDavid du Colombier 		p->forwd = P;
3757dd7cddfSDavid du Colombier 		dwn[i]--;
3767dd7cddfSDavid du Colombier 		if(dwn[i] <= 0) {
3777dd7cddfSDavid du Colombier 			dwn[i] = cnt[i];
3787dd7cddfSDavid du Colombier 			if(lst[i] != P)
3797dd7cddfSDavid du Colombier 				lst[i]->forwd = p;
3807dd7cddfSDavid du Colombier 			lst[i] = p;
3817dd7cddfSDavid du Colombier 		}
3827dd7cddfSDavid du Colombier 	}
3837dd7cddfSDavid du Colombier }
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier Prog*
brloop(Prog * p)3867dd7cddfSDavid du Colombier brloop(Prog *p)
3877dd7cddfSDavid du Colombier {
3887dd7cddfSDavid du Colombier 	Prog *q;
3897dd7cddfSDavid du Colombier 	int c;
3907dd7cddfSDavid du Colombier 
3917dd7cddfSDavid du Colombier 	for(c=0; p!=P;) {
3927dd7cddfSDavid du Colombier 		if(p->as != AB)
3937dd7cddfSDavid du Colombier 			return p;
3947dd7cddfSDavid du Colombier 		q = p->cond;
3957dd7cddfSDavid du Colombier 		if(q <= p) {
3967dd7cddfSDavid du Colombier 			c++;
3977dd7cddfSDavid du Colombier 			if(q == p || c > 5000)
3987dd7cddfSDavid du Colombier 				break;
3997dd7cddfSDavid du Colombier 		}
4007dd7cddfSDavid du Colombier 		p = q;
4017dd7cddfSDavid du Colombier 	}
4027dd7cddfSDavid du Colombier 	return P;
4037dd7cddfSDavid du Colombier }
4047dd7cddfSDavid du Colombier 
4057dd7cddfSDavid du Colombier long
atolwhex(char * s)4067dd7cddfSDavid du Colombier atolwhex(char *s)
4077dd7cddfSDavid du Colombier {
4087dd7cddfSDavid du Colombier 	long n;
4097dd7cddfSDavid du Colombier 	int f;
4107dd7cddfSDavid du Colombier 
4117dd7cddfSDavid du Colombier 	n = 0;
4127dd7cddfSDavid du Colombier 	f = 0;
4137dd7cddfSDavid du Colombier 	while(*s == ' ' || *s == '\t')
4147dd7cddfSDavid du Colombier 		s++;
4157dd7cddfSDavid du Colombier 	if(*s == '-' || *s == '+') {
4167dd7cddfSDavid du Colombier 		if(*s++ == '-')
4177dd7cddfSDavid du Colombier 			f = 1;
4187dd7cddfSDavid du Colombier 		while(*s == ' ' || *s == '\t')
4197dd7cddfSDavid du Colombier 			s++;
4207dd7cddfSDavid du Colombier 	}
4217dd7cddfSDavid du Colombier 	if(s[0]=='0' && s[1]){
4227dd7cddfSDavid du Colombier 		if(s[1]=='x' || s[1]=='X'){
4237dd7cddfSDavid du Colombier 			s += 2;
4247dd7cddfSDavid du Colombier 			for(;;){
4257dd7cddfSDavid du Colombier 				if(*s >= '0' && *s <= '9')
4267dd7cddfSDavid du Colombier 					n = n*16 + *s++ - '0';
4277dd7cddfSDavid du Colombier 				else if(*s >= 'a' && *s <= 'f')
4287dd7cddfSDavid du Colombier 					n = n*16 + *s++ - 'a' + 10;
4297dd7cddfSDavid du Colombier 				else if(*s >= 'A' && *s <= 'F')
4307dd7cddfSDavid du Colombier 					n = n*16 + *s++ - 'A' + 10;
4317dd7cddfSDavid du Colombier 				else
4327dd7cddfSDavid du Colombier 					break;
4337dd7cddfSDavid du Colombier 			}
4347dd7cddfSDavid du Colombier 		} else
4357dd7cddfSDavid du Colombier 			while(*s >= '0' && *s <= '7')
4367dd7cddfSDavid du Colombier 				n = n*8 + *s++ - '0';
4377dd7cddfSDavid du Colombier 	} else
4387dd7cddfSDavid du Colombier 		while(*s >= '0' && *s <= '9')
4397dd7cddfSDavid du Colombier 			n = n*10 + *s++ - '0';
4407dd7cddfSDavid du Colombier 	if(f)
4417dd7cddfSDavid du Colombier 		n = -n;
4427dd7cddfSDavid du Colombier 	return n;
4437dd7cddfSDavid du Colombier }
4447dd7cddfSDavid du Colombier 
4457dd7cddfSDavid du Colombier long
rnd(long v,long r)4467dd7cddfSDavid du Colombier rnd(long v, long r)
4477dd7cddfSDavid du Colombier {
4487dd7cddfSDavid du Colombier 	long c;
4497dd7cddfSDavid du Colombier 
4507dd7cddfSDavid du Colombier 	if(r <= 0)
4517dd7cddfSDavid du Colombier 		return v;
4527dd7cddfSDavid du Colombier 	v += r - 1;
4537dd7cddfSDavid du Colombier 	c = v % r;
4547dd7cddfSDavid du Colombier 	if(c < 0)
4557dd7cddfSDavid du Colombier 		c += r;
4567dd7cddfSDavid du Colombier 	v -= c;
4577dd7cddfSDavid du Colombier 	return v;
4587dd7cddfSDavid du Colombier }
459*375daca8SDavid du Colombier 
460*375daca8SDavid du Colombier void
import(void)461*375daca8SDavid du Colombier import(void)
462*375daca8SDavid du Colombier {
463*375daca8SDavid du Colombier 	int i;
464*375daca8SDavid du Colombier 	Sym *s;
465*375daca8SDavid du Colombier 
466*375daca8SDavid du Colombier 	for(i = 0; i < NHASH; i++)
467*375daca8SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
468*375daca8SDavid du Colombier 			if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
469*375daca8SDavid du Colombier 				undefsym(s);
470*375daca8SDavid du Colombier 				Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value);
471*375daca8SDavid du Colombier 			}
472*375daca8SDavid du Colombier }
473*375daca8SDavid du Colombier 
474*375daca8SDavid du Colombier void
ckoff(Sym * s,long v)475*375daca8SDavid du Colombier ckoff(Sym *s, long v)
476*375daca8SDavid du Colombier {
477*375daca8SDavid du Colombier 	if(v < 0 || v >= 1<<Roffset)
478*375daca8SDavid du Colombier 		diag("relocation offset %ld for %s out of range", v, s->name);
479*375daca8SDavid du Colombier }
480*375daca8SDavid du Colombier 
481*375daca8SDavid du Colombier static Prog*
newdata(Sym * s,int o,int w,int t)482*375daca8SDavid du Colombier newdata(Sym *s, int o, int w, int t)
483*375daca8SDavid du Colombier {
484*375daca8SDavid du Colombier 	Prog *p;
485*375daca8SDavid du Colombier 
486*375daca8SDavid du Colombier 	p = prg();
487*375daca8SDavid du Colombier 	p->link = datap;
488*375daca8SDavid du Colombier 	datap = p;
489*375daca8SDavid du Colombier 	p->as = ADATA;
490*375daca8SDavid du Colombier 	p->reg = w;
491*375daca8SDavid du Colombier 	p->from.type = D_OREG;
492*375daca8SDavid du Colombier 	p->from.name = t;
493*375daca8SDavid du Colombier 	p->from.sym = s;
494*375daca8SDavid du Colombier 	p->from.offset = o;
495*375daca8SDavid du Colombier 	p->to.type = D_CONST;
496*375daca8SDavid du Colombier 	p->to.name = D_NONE;
497*375daca8SDavid du Colombier 	return p;
498*375daca8SDavid du Colombier }
499*375daca8SDavid du Colombier 
500*375daca8SDavid du Colombier void
export(void)501*375daca8SDavid du Colombier export(void)
502*375daca8SDavid du Colombier {
503*375daca8SDavid du Colombier 	int i, j, n, off, nb, sv, ne;
504*375daca8SDavid du Colombier 	Sym *s, *et, *str, **esyms;
505*375daca8SDavid du Colombier 	Prog *p;
506*375daca8SDavid du Colombier 	char buf[NSNAME], *t;
507*375daca8SDavid du Colombier 
508*375daca8SDavid du Colombier 	n = 0;
509*375daca8SDavid du Colombier 	for(i = 0; i < NHASH; i++)
510*375daca8SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
511*375daca8SDavid du Colombier 			if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
512*375daca8SDavid du Colombier 				n++;
513*375daca8SDavid du Colombier 	esyms = malloc(n*sizeof(Sym*));
514*375daca8SDavid du Colombier 	ne = n;
515*375daca8SDavid du Colombier 	n = 0;
516*375daca8SDavid du Colombier 	for(i = 0; i < NHASH; i++)
517*375daca8SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
518*375daca8SDavid du Colombier 			if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
519*375daca8SDavid du Colombier 				esyms[n++] = s;
520*375daca8SDavid du Colombier 	for(i = 0; i < ne-1; i++)
521*375daca8SDavid du Colombier 		for(j = i+1; j < ne; j++)
522*375daca8SDavid du Colombier 			if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
523*375daca8SDavid du Colombier 				s = esyms[i];
524*375daca8SDavid du Colombier 				esyms[i] = esyms[j];
525*375daca8SDavid du Colombier 				esyms[j] = s;
526*375daca8SDavid du Colombier 			}
527*375daca8SDavid du Colombier 
528*375daca8SDavid du Colombier 	nb = 0;
529*375daca8SDavid du Colombier 	off = 0;
530*375daca8SDavid du Colombier 	et = lookup(EXPTAB, 0);
531*375daca8SDavid du Colombier 	if(et->type != 0 && et->type != SXREF)
532*375daca8SDavid du Colombier 		diag("%s already defined", EXPTAB);
533*375daca8SDavid du Colombier 	et->type = SDATA;
534*375daca8SDavid du Colombier 	str = lookup(".string", 0);
535*375daca8SDavid du Colombier 	if(str->type == 0)
536*375daca8SDavid du Colombier 		str->type = SDATA;
537*375daca8SDavid du Colombier 	sv = str->value;
538*375daca8SDavid du Colombier 	for(i = 0; i < ne; i++){
539*375daca8SDavid du Colombier 		s = esyms[i];
540*375daca8SDavid du Colombier 		Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
541*375daca8SDavid du Colombier 
542*375daca8SDavid du Colombier 		/* signature */
543*375daca8SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
544*375daca8SDavid du Colombier 		off += sizeof(long);
545*375daca8SDavid du Colombier 		p->to.offset = s->sig;
546*375daca8SDavid du Colombier 
547*375daca8SDavid du Colombier 		/* address */
548*375daca8SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
549*375daca8SDavid du Colombier 		off += sizeof(long);
550*375daca8SDavid du Colombier 		p->to.name = D_EXTERN;
551*375daca8SDavid du Colombier 		p->to.sym = s;
552*375daca8SDavid du Colombier 
553*375daca8SDavid du Colombier 		/* string */
554*375daca8SDavid du Colombier 		t = s->name;
555*375daca8SDavid du Colombier 		n = strlen(t)+1;
556*375daca8SDavid du Colombier 		for(;;){
557*375daca8SDavid du Colombier 			buf[nb++] = *t;
558*375daca8SDavid du Colombier 			sv++;
559*375daca8SDavid du Colombier 			if(nb >= NSNAME){
560*375daca8SDavid du Colombier 				p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
561*375daca8SDavid du Colombier 				p->to.type = D_SCONST;
562*375daca8SDavid du Colombier 				p->to.sval = malloc(NSNAME);
563*375daca8SDavid du Colombier 				memmove(p->to.sval, buf, NSNAME);
564*375daca8SDavid du Colombier 				nb = 0;
565*375daca8SDavid du Colombier 			}
566*375daca8SDavid du Colombier 			if(*t++ == 0)
567*375daca8SDavid du Colombier 				break;
568*375daca8SDavid du Colombier 		}
569*375daca8SDavid du Colombier 
570*375daca8SDavid du Colombier 		/* name */
571*375daca8SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
572*375daca8SDavid du Colombier 		off += sizeof(long);
573*375daca8SDavid du Colombier 		p->to.name = D_STATIC;
574*375daca8SDavid du Colombier 		p->to.sym = str;
575*375daca8SDavid du Colombier 		p->to.offset = sv-n;
576*375daca8SDavid du Colombier 	}
577*375daca8SDavid du Colombier 
578*375daca8SDavid du Colombier 	if(nb > 0){
579*375daca8SDavid du Colombier 		p = newdata(str, sv-nb, nb, D_STATIC);
580*375daca8SDavid du Colombier 		p->to.type = D_SCONST;
581*375daca8SDavid du Colombier 		p->to.sval = malloc(NSNAME);
582*375daca8SDavid du Colombier 		memmove(p->to.sval, buf, nb);
583*375daca8SDavid du Colombier 	}
584*375daca8SDavid du Colombier 
585*375daca8SDavid du Colombier 	for(i = 0; i < 3; i++){
586*375daca8SDavid du Colombier 		newdata(et, off, sizeof(long), D_EXTERN);
587*375daca8SDavid du Colombier 		off += sizeof(long);
588*375daca8SDavid du Colombier 	}
589*375daca8SDavid du Colombier 	et->value = off;
590*375daca8SDavid du Colombier 	if(sv == 0)
591*375daca8SDavid du Colombier 		sv = 1;
592*375daca8SDavid du Colombier 	str->value = sv;
593*375daca8SDavid du Colombier 	exports = ne;
594*375daca8SDavid du Colombier 	free(esyms);
595*375daca8SDavid du Colombier }
596