xref: /plan9-contrib/sys/src/cmd/9l/pass.c (revision fbadb1c4d4463e58337ffb1ed396c9caee5d1889)
1*fbadb1c4SDavid du Colombier #include	"l.h"
2*fbadb1c4SDavid du Colombier 
3*fbadb1c4SDavid du Colombier void
dodata(void)4*fbadb1c4SDavid du Colombier dodata(void)
5*fbadb1c4SDavid du Colombier {
6*fbadb1c4SDavid du Colombier 	int i, t;
7*fbadb1c4SDavid du Colombier 	Sym *s;
8*fbadb1c4SDavid du Colombier 	Prog *p, *p1;
9*fbadb1c4SDavid du Colombier 	vlong orig, orig1, v;
10*fbadb1c4SDavid du Colombier 
11*fbadb1c4SDavid du Colombier 	if(debug['v'])
12*fbadb1c4SDavid du Colombier 		Bprint(&bso, "%5.2f dodata\n", cputime());
13*fbadb1c4SDavid du Colombier 	Bflush(&bso);
14*fbadb1c4SDavid du Colombier 	for(p = datap; p != P; p = p->link) {
15*fbadb1c4SDavid du Colombier 		s = p->from.sym;
16*fbadb1c4SDavid du Colombier 		if(p->as == ADYNT || p->as == AINIT)
17*fbadb1c4SDavid du Colombier 			s->value = dtype;
18*fbadb1c4SDavid du Colombier 		if(s->type == SBSS)
19*fbadb1c4SDavid du Colombier 			s->type = SDATA;
20*fbadb1c4SDavid du Colombier 		if(s->type != SDATA)
21*fbadb1c4SDavid du Colombier 			diag("initialize non-data (%d): %s\n%P",
22*fbadb1c4SDavid du Colombier 				s->type, s->name, p);
23*fbadb1c4SDavid du Colombier 		v = p->from.offset + p->reg;
24*fbadb1c4SDavid du Colombier 		if(v > s->value)
25*fbadb1c4SDavid du Colombier 			diag("initialize bounds (%lld): %s\n%P",
26*fbadb1c4SDavid du Colombier 				s->value, s->name, p);
27*fbadb1c4SDavid du Colombier 	}
28*fbadb1c4SDavid du Colombier 
29*fbadb1c4SDavid du Colombier 	/*
30*fbadb1c4SDavid du Colombier 	 * pass 1
31*fbadb1c4SDavid du Colombier 	 *	assign 'small' variables to data segment
32*fbadb1c4SDavid du Colombier 	 *	(rational is that data segment is more easily
33*fbadb1c4SDavid du Colombier 	 *	 addressed through offset on REGSB)
34*fbadb1c4SDavid du Colombier 	 */
35*fbadb1c4SDavid du Colombier 	orig = 0;
36*fbadb1c4SDavid du Colombier 	for(i=0; i<NHASH; i++)
37*fbadb1c4SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
38*fbadb1c4SDavid du Colombier 		t = s->type;
39*fbadb1c4SDavid du Colombier 		if(t != SDATA && t != SBSS)
40*fbadb1c4SDavid du Colombier 			continue;
41*fbadb1c4SDavid du Colombier 		v = s->value;
42*fbadb1c4SDavid du Colombier 		if(v == 0) {
43*fbadb1c4SDavid du Colombier 			diag("%s: no size", s->name);
44*fbadb1c4SDavid du Colombier 			v = 1;
45*fbadb1c4SDavid du Colombier 		}
46*fbadb1c4SDavid du Colombier 		v = rnd(v, 4);
47*fbadb1c4SDavid du Colombier 		s->value = v;
48*fbadb1c4SDavid du Colombier 		if(v > MINSIZ)
49*fbadb1c4SDavid du Colombier 			continue;
50*fbadb1c4SDavid du Colombier 		if(v >= 8)
51*fbadb1c4SDavid du Colombier 			orig = rnd(orig, 8);
52*fbadb1c4SDavid du Colombier 		s->value = orig;
53*fbadb1c4SDavid du Colombier 		orig += v;
54*fbadb1c4SDavid du Colombier 		s->type = SDATA1;
55*fbadb1c4SDavid du Colombier 	}
56*fbadb1c4SDavid du Colombier 	orig1 = orig;
57*fbadb1c4SDavid du Colombier 
58*fbadb1c4SDavid du Colombier 	/*
59*fbadb1c4SDavid du Colombier 	 * pass 2
60*fbadb1c4SDavid du Colombier 	 *	assign 'data' variables to data segment
61*fbadb1c4SDavid du Colombier 	 */
62*fbadb1c4SDavid du Colombier 	for(i=0; i<NHASH; i++)
63*fbadb1c4SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
64*fbadb1c4SDavid du Colombier 		t = s->type;
65*fbadb1c4SDavid du Colombier 		if(t != SDATA) {
66*fbadb1c4SDavid du Colombier 			if(t == SDATA1)
67*fbadb1c4SDavid du Colombier 				s->type = SDATA;
68*fbadb1c4SDavid du Colombier 			continue;
69*fbadb1c4SDavid du Colombier 		}
70*fbadb1c4SDavid du Colombier 		v = s->value;
71*fbadb1c4SDavid du Colombier 		if(v >= 8)
72*fbadb1c4SDavid du Colombier 			orig = rnd(orig, 8);
73*fbadb1c4SDavid du Colombier 		s->value = orig;
74*fbadb1c4SDavid du Colombier 		orig += v;
75*fbadb1c4SDavid du Colombier 		s->type = SDATA1;
76*fbadb1c4SDavid du Colombier 	}
77*fbadb1c4SDavid du Colombier 
78*fbadb1c4SDavid du Colombier 	if(orig)
79*fbadb1c4SDavid du Colombier 		orig = rnd(orig, 8);
80*fbadb1c4SDavid du Colombier 	datsize = orig;
81*fbadb1c4SDavid du Colombier 
82*fbadb1c4SDavid du Colombier 	/*
83*fbadb1c4SDavid du Colombier 	 * pass 3
84*fbadb1c4SDavid du Colombier 	 *	everything else to bss segment
85*fbadb1c4SDavid du Colombier 	 */
86*fbadb1c4SDavid du Colombier 	for(i=0; i<NHASH; i++)
87*fbadb1c4SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
88*fbadb1c4SDavid du Colombier 		if(s->type != SBSS)
89*fbadb1c4SDavid du Colombier 			continue;
90*fbadb1c4SDavid du Colombier 		v = s->value;
91*fbadb1c4SDavid du Colombier 		if(v >= 8)
92*fbadb1c4SDavid du Colombier 			orig = rnd(orig, 8);
93*fbadb1c4SDavid du Colombier 		s->value = orig;
94*fbadb1c4SDavid du Colombier 		orig += v;
95*fbadb1c4SDavid du Colombier 	}
96*fbadb1c4SDavid du Colombier 	if(orig)
97*fbadb1c4SDavid du Colombier 		orig = rnd(orig, 8);
98*fbadb1c4SDavid du Colombier 	bsssize = orig-datsize;
99*fbadb1c4SDavid du Colombier 
100*fbadb1c4SDavid du Colombier 	/*
101*fbadb1c4SDavid du Colombier 	 * pass 4
102*fbadb1c4SDavid du Colombier 	 *	add literals to all large values.
103*fbadb1c4SDavid du Colombier 	 *	at this time:
104*fbadb1c4SDavid du Colombier 	 *		small data is allocated DATA
105*fbadb1c4SDavid du Colombier 	 *		large data is allocated DATA1
106*fbadb1c4SDavid du Colombier 	 *		large bss is allocated BSS
107*fbadb1c4SDavid du Colombier 	 *	the new literals are loaded between
108*fbadb1c4SDavid du Colombier 	 *	small data and large data.
109*fbadb1c4SDavid du Colombier 	 */
110*fbadb1c4SDavid du Colombier 	orig = 0;
111*fbadb1c4SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
112*fbadb1c4SDavid du Colombier 		if(p->as != AMOVW)
113*fbadb1c4SDavid du Colombier 			continue;
114*fbadb1c4SDavid du Colombier 		if(p->from.type != D_CONST)
115*fbadb1c4SDavid du Colombier 			continue;
116*fbadb1c4SDavid du Colombier 		if(s = p->from.sym) {
117*fbadb1c4SDavid du Colombier 			t = s->type;
118*fbadb1c4SDavid du Colombier 			if(t != SDATA && t != SDATA1 && t != SBSS)
119*fbadb1c4SDavid du Colombier 				continue;
120*fbadb1c4SDavid du Colombier 			t = p->from.name;
121*fbadb1c4SDavid du Colombier 			if(t != D_EXTERN && t != D_STATIC)
122*fbadb1c4SDavid du Colombier 				continue;
123*fbadb1c4SDavid du Colombier 			v = s->value + p->from.offset;
124*fbadb1c4SDavid du Colombier 			if(v >= 0 && v <= 0xffff)
125*fbadb1c4SDavid du Colombier 				continue;
126*fbadb1c4SDavid du Colombier 			if(!strcmp(s->name, "setSB"))
127*fbadb1c4SDavid du Colombier 				continue;
128*fbadb1c4SDavid du Colombier 			/* size should be 19 max */
129*fbadb1c4SDavid du Colombier 			if(strlen(s->name) >= 10)	/* has loader address */
130*fbadb1c4SDavid du Colombier 				sprint(literal, "$%p.%llux", s, p->from.offset);
131*fbadb1c4SDavid du Colombier 			else
132*fbadb1c4SDavid du Colombier 				sprint(literal, "$%s.%d.%llux", s->name, s->version, p->from.offset);
133*fbadb1c4SDavid du Colombier 		} else {
134*fbadb1c4SDavid du Colombier 			if(p->from.name != D_NONE)
135*fbadb1c4SDavid du Colombier 				continue;
136*fbadb1c4SDavid du Colombier 			if(p->from.reg != NREG)
137*fbadb1c4SDavid du Colombier 				continue;
138*fbadb1c4SDavid du Colombier 			v = p->from.offset;
139*fbadb1c4SDavid du Colombier 			if(v >= -0x7fff-1 && v <= 0x7fff)
140*fbadb1c4SDavid du Colombier 				continue;
141*fbadb1c4SDavid du Colombier 			if(!(v & 0xffff))
142*fbadb1c4SDavid du Colombier 				continue;
143*fbadb1c4SDavid du Colombier 			if(v)
144*fbadb1c4SDavid du Colombier 				continue;	/* quicker to build it than load it */
145*fbadb1c4SDavid du Colombier 			/* size should be 9 max */
146*fbadb1c4SDavid du Colombier 			sprint(literal, "$%llux", v);
147*fbadb1c4SDavid du Colombier 		}
148*fbadb1c4SDavid du Colombier 		s = lookup(literal, 0);
149*fbadb1c4SDavid du Colombier 		if(s->type == 0) {
150*fbadb1c4SDavid du Colombier 			s->type = SDATA;
151*fbadb1c4SDavid du Colombier 			s->value = orig1+orig;
152*fbadb1c4SDavid du Colombier 			orig += 4;
153*fbadb1c4SDavid du Colombier 			p1 = prg();
154*fbadb1c4SDavid du Colombier 			p1->as = ADATA;
155*fbadb1c4SDavid du Colombier 			p1->line = p->line;
156*fbadb1c4SDavid du Colombier 			p1->from.type = D_OREG;
157*fbadb1c4SDavid du Colombier 			p1->from.sym = s;
158*fbadb1c4SDavid du Colombier 			p1->from.name = D_EXTERN;
159*fbadb1c4SDavid du Colombier 			p1->reg = 4;
160*fbadb1c4SDavid du Colombier 			p1->to = p->from;
161*fbadb1c4SDavid du Colombier 			p1->link = datap;
162*fbadb1c4SDavid du Colombier 			datap = p1;
163*fbadb1c4SDavid du Colombier 		}
164*fbadb1c4SDavid du Colombier 		if(s->type != SDATA)
165*fbadb1c4SDavid du Colombier 			diag("literal not data: %s", s->name);
166*fbadb1c4SDavid du Colombier 		p->from.type = D_OREG;
167*fbadb1c4SDavid du Colombier 		p->from.sym = s;
168*fbadb1c4SDavid du Colombier 		p->from.name = D_EXTERN;
169*fbadb1c4SDavid du Colombier 		p->from.offset = 0;
170*fbadb1c4SDavid du Colombier 		continue;
171*fbadb1c4SDavid du Colombier 	}
172*fbadb1c4SDavid du Colombier 	while(orig & 7)
173*fbadb1c4SDavid du Colombier 		orig++;
174*fbadb1c4SDavid du Colombier 	/*
175*fbadb1c4SDavid du Colombier 	 * pass 5
176*fbadb1c4SDavid du Colombier 	 *	re-adjust offsets
177*fbadb1c4SDavid du Colombier 	 */
178*fbadb1c4SDavid du Colombier 	for(i=0; i<NHASH; i++)
179*fbadb1c4SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
180*fbadb1c4SDavid du Colombier 		t = s->type;
181*fbadb1c4SDavid du Colombier 		if(t == SBSS) {
182*fbadb1c4SDavid du Colombier 			s->value += orig;
183*fbadb1c4SDavid du Colombier 			continue;
184*fbadb1c4SDavid du Colombier 		}
185*fbadb1c4SDavid du Colombier 		if(t == SDATA1) {
186*fbadb1c4SDavid du Colombier 			s->type = SDATA;
187*fbadb1c4SDavid du Colombier 			s->value += orig;
188*fbadb1c4SDavid du Colombier 			continue;
189*fbadb1c4SDavid du Colombier 		}
190*fbadb1c4SDavid du Colombier 	}
191*fbadb1c4SDavid du Colombier 	datsize += orig;
192*fbadb1c4SDavid du Colombier 	xdefine("setSB", SDATA, 0+BIG);
193*fbadb1c4SDavid du Colombier 	xdefine("bdata", SDATA, 0);
194*fbadb1c4SDavid du Colombier 	xdefine("edata", SDATA, datsize);
195*fbadb1c4SDavid du Colombier 	xdefine("end", SBSS, datsize+bsssize);
196*fbadb1c4SDavid du Colombier 	xdefine("etext", STEXT, 0);
197*fbadb1c4SDavid du Colombier }
198*fbadb1c4SDavid du Colombier 
199*fbadb1c4SDavid du Colombier void
undef(void)200*fbadb1c4SDavid du Colombier undef(void)
201*fbadb1c4SDavid du Colombier {
202*fbadb1c4SDavid du Colombier 	int i;
203*fbadb1c4SDavid du Colombier 	Sym *s;
204*fbadb1c4SDavid du Colombier 
205*fbadb1c4SDavid du Colombier 	for(i=0; i<NHASH; i++)
206*fbadb1c4SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link)
207*fbadb1c4SDavid du Colombier 		if(s->type == SXREF)
208*fbadb1c4SDavid du Colombier 			diag("%s: not defined", s->name);
209*fbadb1c4SDavid du Colombier }
210*fbadb1c4SDavid du Colombier 
211*fbadb1c4SDavid du Colombier int
relinv(int a)212*fbadb1c4SDavid du Colombier relinv(int a)
213*fbadb1c4SDavid du Colombier {
214*fbadb1c4SDavid du Colombier 
215*fbadb1c4SDavid du Colombier 	switch(a) {
216*fbadb1c4SDavid du Colombier 	case ABEQ:	return ABNE;
217*fbadb1c4SDavid du Colombier 	case ABNE:	return ABEQ;
218*fbadb1c4SDavid du Colombier 
219*fbadb1c4SDavid du Colombier 	case ABGE:	return ABLT;
220*fbadb1c4SDavid du Colombier 	case ABLT:	return ABGE;
221*fbadb1c4SDavid du Colombier 
222*fbadb1c4SDavid du Colombier 	case ABGT:	return ABLE;
223*fbadb1c4SDavid du Colombier 	case ABLE:	return ABGT;
224*fbadb1c4SDavid du Colombier 
225*fbadb1c4SDavid du Colombier 	case ABVC:	return ABVS;
226*fbadb1c4SDavid du Colombier 	case ABVS:	return ABVC;
227*fbadb1c4SDavid du Colombier 	}
228*fbadb1c4SDavid du Colombier 	return 0;
229*fbadb1c4SDavid du Colombier }
230*fbadb1c4SDavid du Colombier 
231*fbadb1c4SDavid du Colombier void
follow(void)232*fbadb1c4SDavid du Colombier follow(void)
233*fbadb1c4SDavid du Colombier {
234*fbadb1c4SDavid du Colombier 
235*fbadb1c4SDavid du Colombier 	if(debug['v'])
236*fbadb1c4SDavid du Colombier 		Bprint(&bso, "%5.2f follow\n", cputime());
237*fbadb1c4SDavid du Colombier 	Bflush(&bso);
238*fbadb1c4SDavid du Colombier 
239*fbadb1c4SDavid du Colombier 	firstp = prg();
240*fbadb1c4SDavid du Colombier 	lastp = firstp;
241*fbadb1c4SDavid du Colombier 
242*fbadb1c4SDavid du Colombier 	xfol(textp);
243*fbadb1c4SDavid du Colombier 
244*fbadb1c4SDavid du Colombier 	firstp = firstp->link;
245*fbadb1c4SDavid du Colombier 	lastp->link = P;
246*fbadb1c4SDavid du Colombier }
247*fbadb1c4SDavid du Colombier 
248*fbadb1c4SDavid du Colombier void
xfol(Prog * p)249*fbadb1c4SDavid du Colombier xfol(Prog *p)
250*fbadb1c4SDavid du Colombier {
251*fbadb1c4SDavid du Colombier 	Prog *q, *r;
252*fbadb1c4SDavid du Colombier 	int a, b, i;
253*fbadb1c4SDavid du Colombier 
254*fbadb1c4SDavid du Colombier loop:
255*fbadb1c4SDavid du Colombier 	if(p == P)
256*fbadb1c4SDavid du Colombier 		return;
257*fbadb1c4SDavid du Colombier 	a = p->as;
258*fbadb1c4SDavid du Colombier 	if(a == ATEXT)
259*fbadb1c4SDavid du Colombier 		curtext = p;
260*fbadb1c4SDavid du Colombier 	if(a == ABR) {
261*fbadb1c4SDavid du Colombier 		q = p->cond;
262*fbadb1c4SDavid du Colombier 		if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
263*fbadb1c4SDavid du Colombier 			p->mark |= FOLL;
264*fbadb1c4SDavid du Colombier 			lastp->link = p;
265*fbadb1c4SDavid du Colombier 			lastp = p;
266*fbadb1c4SDavid du Colombier 			p = p->link;
267*fbadb1c4SDavid du Colombier 			xfol(p);
268*fbadb1c4SDavid du Colombier 			p = q;
269*fbadb1c4SDavid du Colombier 			if(p && !(p->mark & FOLL))
270*fbadb1c4SDavid du Colombier 				goto loop;
271*fbadb1c4SDavid du Colombier 			return;
272*fbadb1c4SDavid du Colombier 		}
273*fbadb1c4SDavid du Colombier 		if(q != P) {
274*fbadb1c4SDavid du Colombier 			p->mark |= FOLL;
275*fbadb1c4SDavid du Colombier 			p = q;
276*fbadb1c4SDavid du Colombier 			if(!(p->mark & FOLL))
277*fbadb1c4SDavid du Colombier 				goto loop;
278*fbadb1c4SDavid du Colombier 		}
279*fbadb1c4SDavid du Colombier 	}
280*fbadb1c4SDavid du Colombier 	if(p->mark & FOLL) {
281*fbadb1c4SDavid du Colombier 		for(i=0,q=p; i<4; i++,q=q->link) {
282*fbadb1c4SDavid du Colombier 			if(q == lastp || (q->mark&NOSCHED))
283*fbadb1c4SDavid du Colombier 				break;
284*fbadb1c4SDavid du Colombier 			b = 0;		/* set */
285*fbadb1c4SDavid du Colombier 			a = q->as;
286*fbadb1c4SDavid du Colombier 			if(a == ANOP) {
287*fbadb1c4SDavid du Colombier 				i--;
288*fbadb1c4SDavid du Colombier 				continue;
289*fbadb1c4SDavid du Colombier 			}
290*fbadb1c4SDavid du Colombier 			if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID)
291*fbadb1c4SDavid du Colombier 				goto copy;
292*fbadb1c4SDavid du Colombier 			if(!q->cond || (q->cond->mark&FOLL))
293*fbadb1c4SDavid du Colombier 				continue;
294*fbadb1c4SDavid du Colombier 			b = relinv(a);
295*fbadb1c4SDavid du Colombier 			if(!b)
296*fbadb1c4SDavid du Colombier 				continue;
297*fbadb1c4SDavid du Colombier 		copy:
298*fbadb1c4SDavid du Colombier 			for(;;) {
299*fbadb1c4SDavid du Colombier 				r = prg();
300*fbadb1c4SDavid du Colombier 				*r = *p;
301*fbadb1c4SDavid du Colombier 				if(!(r->mark&FOLL))
302*fbadb1c4SDavid du Colombier 					print("cant happen 1\n");
303*fbadb1c4SDavid du Colombier 				r->mark |= FOLL;
304*fbadb1c4SDavid du Colombier 				if(p != q) {
305*fbadb1c4SDavid du Colombier 					p = p->link;
306*fbadb1c4SDavid du Colombier 					lastp->link = r;
307*fbadb1c4SDavid du Colombier 					lastp = r;
308*fbadb1c4SDavid du Colombier 					continue;
309*fbadb1c4SDavid du Colombier 				}
310*fbadb1c4SDavid du Colombier 				lastp->link = r;
311*fbadb1c4SDavid du Colombier 				lastp = r;
312*fbadb1c4SDavid du Colombier 				if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID)
313*fbadb1c4SDavid du Colombier 					return;
314*fbadb1c4SDavid du Colombier 				r->as = b;
315*fbadb1c4SDavid du Colombier 				r->cond = p->link;
316*fbadb1c4SDavid du Colombier 				r->link = p->cond;
317*fbadb1c4SDavid du Colombier 				if(!(r->link->mark&FOLL))
318*fbadb1c4SDavid du Colombier 					xfol(r->link);
319*fbadb1c4SDavid du Colombier 				if(!(r->cond->mark&FOLL))
320*fbadb1c4SDavid du Colombier 					print("cant happen 2\n");
321*fbadb1c4SDavid du Colombier 				return;
322*fbadb1c4SDavid du Colombier 			}
323*fbadb1c4SDavid du Colombier 		}
324*fbadb1c4SDavid du Colombier 
325*fbadb1c4SDavid du Colombier 		a = ABR;
326*fbadb1c4SDavid du Colombier 		q = prg();
327*fbadb1c4SDavid du Colombier 		q->as = a;
328*fbadb1c4SDavid du Colombier 		q->line = p->line;
329*fbadb1c4SDavid du Colombier 		q->to.type = D_BRANCH;
330*fbadb1c4SDavid du Colombier 		q->to.offset = p->pc;
331*fbadb1c4SDavid du Colombier 		q->cond = p;
332*fbadb1c4SDavid du Colombier 		p = q;
333*fbadb1c4SDavid du Colombier 	}
334*fbadb1c4SDavid du Colombier 	p->mark |= FOLL;
335*fbadb1c4SDavid du Colombier 	lastp->link = p;
336*fbadb1c4SDavid du Colombier 	lastp = p;
337*fbadb1c4SDavid du Colombier 	if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID){
338*fbadb1c4SDavid du Colombier 		if(p->mark & NOSCHED){
339*fbadb1c4SDavid du Colombier 			p = p->link;
340*fbadb1c4SDavid du Colombier 			goto loop;
341*fbadb1c4SDavid du Colombier 		}
342*fbadb1c4SDavid du Colombier 		return;
343*fbadb1c4SDavid du Colombier 	}
344*fbadb1c4SDavid du Colombier 	if(p->cond != P)
345*fbadb1c4SDavid du Colombier 	if(a != ABL && p->link != P) {
346*fbadb1c4SDavid du Colombier 		xfol(p->link);
347*fbadb1c4SDavid du Colombier 		p = p->cond;
348*fbadb1c4SDavid du Colombier 		if(p == P || (p->mark&FOLL))
349*fbadb1c4SDavid du Colombier 			return;
350*fbadb1c4SDavid du Colombier 		goto loop;
351*fbadb1c4SDavid du Colombier 	}
352*fbadb1c4SDavid du Colombier 	p = p->link;
353*fbadb1c4SDavid du Colombier 	goto loop;
354*fbadb1c4SDavid du Colombier }
355*fbadb1c4SDavid du Colombier 
356*fbadb1c4SDavid du Colombier void
patch(void)357*fbadb1c4SDavid du Colombier patch(void)
358*fbadb1c4SDavid du Colombier {
359*fbadb1c4SDavid du Colombier 	long c;
360*fbadb1c4SDavid du Colombier 	Prog *p, *q;
361*fbadb1c4SDavid du Colombier 	Sym *s;
362*fbadb1c4SDavid du Colombier 	int a;
363*fbadb1c4SDavid du Colombier 	vlong vexit;
364*fbadb1c4SDavid du Colombier 
365*fbadb1c4SDavid du Colombier 	if(debug['v'])
366*fbadb1c4SDavid du Colombier 		Bprint(&bso, "%5.2f patch\n", cputime());
367*fbadb1c4SDavid du Colombier 	Bflush(&bso);
368*fbadb1c4SDavid du Colombier 	mkfwd();
369*fbadb1c4SDavid du Colombier 	s = lookup("exit", 0);
370*fbadb1c4SDavid du Colombier 	vexit = s->value;
371*fbadb1c4SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
372*fbadb1c4SDavid du Colombier 		a = p->as;
373*fbadb1c4SDavid du Colombier 		if(a == ATEXT)
374*fbadb1c4SDavid du Colombier 			curtext = p;
375*fbadb1c4SDavid du Colombier 		if((a == ABL || a == ARETURN) && p->to.sym != S) {
376*fbadb1c4SDavid du Colombier 			s = p->to.sym;
377*fbadb1c4SDavid du Colombier 			if(s->type != STEXT && s->type != SUNDEF) {
378*fbadb1c4SDavid du Colombier 				diag("undefined: %s\n%P", s->name, p);
379*fbadb1c4SDavid du Colombier 				s->type = STEXT;
380*fbadb1c4SDavid du Colombier 				s->value = vexit;
381*fbadb1c4SDavid du Colombier 			}
382*fbadb1c4SDavid du Colombier 			if(s->type == SUNDEF){
383*fbadb1c4SDavid du Colombier 				p->to.offset = 0;
384*fbadb1c4SDavid du Colombier 				p->cond = UP;
385*fbadb1c4SDavid du Colombier 			}
386*fbadb1c4SDavid du Colombier 			else
387*fbadb1c4SDavid du Colombier 				p->to.offset = s->value;
388*fbadb1c4SDavid du Colombier 			p->to.type = D_BRANCH;
389*fbadb1c4SDavid du Colombier 		}
390*fbadb1c4SDavid du Colombier 		if(p->to.type != D_BRANCH || p->cond == UP)
391*fbadb1c4SDavid du Colombier 			continue;
392*fbadb1c4SDavid du Colombier 		c = p->to.offset;
393*fbadb1c4SDavid du Colombier 		for(q = firstp; q != P;) {
394*fbadb1c4SDavid du Colombier 			if(q->forwd != P)
395*fbadb1c4SDavid du Colombier 			if(c >= q->forwd->pc) {
396*fbadb1c4SDavid du Colombier 				q = q->forwd;
397*fbadb1c4SDavid du Colombier 				continue;
398*fbadb1c4SDavid du Colombier 			}
399*fbadb1c4SDavid du Colombier 			if(c == q->pc)
400*fbadb1c4SDavid du Colombier 				break;
401*fbadb1c4SDavid du Colombier 			q = q->link;
402*fbadb1c4SDavid du Colombier 		}
403*fbadb1c4SDavid du Colombier 		if(q == P) {
404*fbadb1c4SDavid du Colombier 			diag("branch out of range %ld\n%P", c, p);
405*fbadb1c4SDavid du Colombier 			p->to.type = D_NONE;
406*fbadb1c4SDavid du Colombier 		}
407*fbadb1c4SDavid du Colombier 		p->cond = q;
408*fbadb1c4SDavid du Colombier 	}
409*fbadb1c4SDavid du Colombier 
410*fbadb1c4SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
411*fbadb1c4SDavid du Colombier 		if(p->as == ATEXT)
412*fbadb1c4SDavid du Colombier 			curtext = p;
413*fbadb1c4SDavid du Colombier 		p->mark = 0;	/* initialization for follow */
414*fbadb1c4SDavid du Colombier 		if(p->cond != P && p->cond != UP) {
415*fbadb1c4SDavid du Colombier 			p->cond = brloop(p->cond);
416*fbadb1c4SDavid du Colombier 			if(p->cond != P)
417*fbadb1c4SDavid du Colombier 			if(p->to.type == D_BRANCH)
418*fbadb1c4SDavid du Colombier 				p->to.offset = p->cond->pc;
419*fbadb1c4SDavid du Colombier 		}
420*fbadb1c4SDavid du Colombier 	}
421*fbadb1c4SDavid du Colombier }
422*fbadb1c4SDavid du Colombier 
423*fbadb1c4SDavid du Colombier #define	LOG	5
424*fbadb1c4SDavid du Colombier void
mkfwd(void)425*fbadb1c4SDavid du Colombier mkfwd(void)
426*fbadb1c4SDavid du Colombier {
427*fbadb1c4SDavid du Colombier 	Prog *p;
428*fbadb1c4SDavid du Colombier 	long dwn[LOG], cnt[LOG], i;
429*fbadb1c4SDavid du Colombier 	Prog *lst[LOG];
430*fbadb1c4SDavid du Colombier 
431*fbadb1c4SDavid du Colombier 	for(i=0; i<LOG; i++) {
432*fbadb1c4SDavid du Colombier 		if(i == 0)
433*fbadb1c4SDavid du Colombier 			cnt[i] = 1; else
434*fbadb1c4SDavid du Colombier 			cnt[i] = LOG * cnt[i-1];
435*fbadb1c4SDavid du Colombier 		dwn[i] = 1;
436*fbadb1c4SDavid du Colombier 		lst[i] = P;
437*fbadb1c4SDavid du Colombier 	}
438*fbadb1c4SDavid du Colombier 	i = 0;
439*fbadb1c4SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
440*fbadb1c4SDavid du Colombier 		if(p->as == ATEXT)
441*fbadb1c4SDavid du Colombier 			curtext = p;
442*fbadb1c4SDavid du Colombier 		i--;
443*fbadb1c4SDavid du Colombier 		if(i < 0)
444*fbadb1c4SDavid du Colombier 			i = LOG-1;
445*fbadb1c4SDavid du Colombier 		p->forwd = P;
446*fbadb1c4SDavid du Colombier 		dwn[i]--;
447*fbadb1c4SDavid du Colombier 		if(dwn[i] <= 0) {
448*fbadb1c4SDavid du Colombier 			dwn[i] = cnt[i];
449*fbadb1c4SDavid du Colombier 			if(lst[i] != P)
450*fbadb1c4SDavid du Colombier 				lst[i]->forwd = p;
451*fbadb1c4SDavid du Colombier 			lst[i] = p;
452*fbadb1c4SDavid du Colombier 		}
453*fbadb1c4SDavid du Colombier 	}
454*fbadb1c4SDavid du Colombier }
455*fbadb1c4SDavid du Colombier 
456*fbadb1c4SDavid du Colombier Prog*
brloop(Prog * p)457*fbadb1c4SDavid du Colombier brloop(Prog *p)
458*fbadb1c4SDavid du Colombier {
459*fbadb1c4SDavid du Colombier 	Prog *q;
460*fbadb1c4SDavid du Colombier 	int c;
461*fbadb1c4SDavid du Colombier 
462*fbadb1c4SDavid du Colombier 	for(c=0; p!=P;) {
463*fbadb1c4SDavid du Colombier 		if(p->as != ABR || (p->mark&NOSCHED))
464*fbadb1c4SDavid du Colombier 			return p;
465*fbadb1c4SDavid du Colombier 		q = p->cond;
466*fbadb1c4SDavid du Colombier 		if(q <= p) {
467*fbadb1c4SDavid du Colombier 			c++;
468*fbadb1c4SDavid du Colombier 			if(q == p || c > 5000)
469*fbadb1c4SDavid du Colombier 				break;
470*fbadb1c4SDavid du Colombier 		}
471*fbadb1c4SDavid du Colombier 		p = q;
472*fbadb1c4SDavid du Colombier 	}
473*fbadb1c4SDavid du Colombier 	return P;
474*fbadb1c4SDavid du Colombier }
475*fbadb1c4SDavid du Colombier 
476*fbadb1c4SDavid du Colombier vlong
atolwhex(char * s)477*fbadb1c4SDavid du Colombier atolwhex(char *s)
478*fbadb1c4SDavid du Colombier {
479*fbadb1c4SDavid du Colombier 	vlong n;
480*fbadb1c4SDavid du Colombier 	int f;
481*fbadb1c4SDavid du Colombier 
482*fbadb1c4SDavid du Colombier 	n = 0;
483*fbadb1c4SDavid du Colombier 	f = 0;
484*fbadb1c4SDavid du Colombier 	while(*s == ' ' || *s == '\t')
485*fbadb1c4SDavid du Colombier 		s++;
486*fbadb1c4SDavid du Colombier 	if(*s == '-' || *s == '+') {
487*fbadb1c4SDavid du Colombier 		if(*s++ == '-')
488*fbadb1c4SDavid du Colombier 			f = 1;
489*fbadb1c4SDavid du Colombier 		while(*s == ' ' || *s == '\t')
490*fbadb1c4SDavid du Colombier 			s++;
491*fbadb1c4SDavid du Colombier 	}
492*fbadb1c4SDavid du Colombier 	if(s[0]=='0' && s[1]){
493*fbadb1c4SDavid du Colombier 		if(s[1]=='x' || s[1]=='X'){
494*fbadb1c4SDavid du Colombier 			s += 2;
495*fbadb1c4SDavid du Colombier 			for(;;){
496*fbadb1c4SDavid du Colombier 				if(*s >= '0' && *s <= '9')
497*fbadb1c4SDavid du Colombier 					n = n*16 + *s++ - '0';
498*fbadb1c4SDavid du Colombier 				else if(*s >= 'a' && *s <= 'f')
499*fbadb1c4SDavid du Colombier 					n = n*16 + *s++ - 'a' + 10;
500*fbadb1c4SDavid du Colombier 				else if(*s >= 'A' && *s <= 'F')
501*fbadb1c4SDavid du Colombier 					n = n*16 + *s++ - 'A' + 10;
502*fbadb1c4SDavid du Colombier 				else
503*fbadb1c4SDavid du Colombier 					break;
504*fbadb1c4SDavid du Colombier 			}
505*fbadb1c4SDavid du Colombier 		} else
506*fbadb1c4SDavid du Colombier 			while(*s >= '0' && *s <= '7')
507*fbadb1c4SDavid du Colombier 				n = n*8 + *s++ - '0';
508*fbadb1c4SDavid du Colombier 	} else
509*fbadb1c4SDavid du Colombier 		while(*s >= '0' && *s <= '9')
510*fbadb1c4SDavid du Colombier 			n = n*10 + *s++ - '0';
511*fbadb1c4SDavid du Colombier 	if(f)
512*fbadb1c4SDavid du Colombier 		n = -n;
513*fbadb1c4SDavid du Colombier 	return n;
514*fbadb1c4SDavid du Colombier }
515*fbadb1c4SDavid du Colombier 
516*fbadb1c4SDavid du Colombier vlong
rnd(vlong v,long r)517*fbadb1c4SDavid du Colombier rnd(vlong v, long r)
518*fbadb1c4SDavid du Colombier {
519*fbadb1c4SDavid du Colombier 	vlong c;
520*fbadb1c4SDavid du Colombier 
521*fbadb1c4SDavid du Colombier 	if(r <= 0)
522*fbadb1c4SDavid du Colombier 		return v;
523*fbadb1c4SDavid du Colombier 	v += r - 1;
524*fbadb1c4SDavid du Colombier 	c = v % r;
525*fbadb1c4SDavid du Colombier 	if(c < 0)
526*fbadb1c4SDavid du Colombier 		c += r;
527*fbadb1c4SDavid du Colombier 	v -= c;
528*fbadb1c4SDavid du Colombier 	return v;
529*fbadb1c4SDavid du Colombier }
530*fbadb1c4SDavid du Colombier 
531*fbadb1c4SDavid du Colombier void
import(void)532*fbadb1c4SDavid du Colombier import(void)
533*fbadb1c4SDavid du Colombier {
534*fbadb1c4SDavid du Colombier 	int i;
535*fbadb1c4SDavid du Colombier 	Sym *s;
536*fbadb1c4SDavid du Colombier 
537*fbadb1c4SDavid du Colombier 	for(i = 0; i < NHASH; i++)
538*fbadb1c4SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
539*fbadb1c4SDavid du Colombier 			if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
540*fbadb1c4SDavid du Colombier 				undefsym(s);
541*fbadb1c4SDavid du Colombier 				Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, s->value);
542*fbadb1c4SDavid du Colombier 				if(debug['S'])
543*fbadb1c4SDavid du Colombier 					s->sig = 0;
544*fbadb1c4SDavid du Colombier 			}
545*fbadb1c4SDavid du Colombier }
546*fbadb1c4SDavid du Colombier 
547*fbadb1c4SDavid du Colombier void
ckoff(Sym * s,vlong v)548*fbadb1c4SDavid du Colombier ckoff(Sym *s, vlong v)
549*fbadb1c4SDavid du Colombier {
550*fbadb1c4SDavid du Colombier 	if(v < 0 || v >= 1<<Roffset)
551*fbadb1c4SDavid du Colombier 		diag("relocation offset %lld for %s out of range", v, s->name);
552*fbadb1c4SDavid du Colombier }
553*fbadb1c4SDavid du Colombier 
554*fbadb1c4SDavid du Colombier static Prog*
newdata(Sym * s,int o,int w,int t)555*fbadb1c4SDavid du Colombier newdata(Sym *s, int o, int w, int t)
556*fbadb1c4SDavid du Colombier {
557*fbadb1c4SDavid du Colombier 	Prog *p;
558*fbadb1c4SDavid du Colombier 
559*fbadb1c4SDavid du Colombier 	p = prg();
560*fbadb1c4SDavid du Colombier 	p->link = datap;
561*fbadb1c4SDavid du Colombier 	datap = p;
562*fbadb1c4SDavid du Colombier 	p->as = ADATA;
563*fbadb1c4SDavid du Colombier 	p->reg = w;
564*fbadb1c4SDavid du Colombier 	p->from.type = D_OREG;
565*fbadb1c4SDavid du Colombier 	p->from.name = t;
566*fbadb1c4SDavid du Colombier 	p->from.sym = s;
567*fbadb1c4SDavid du Colombier 	p->from.offset = o;
568*fbadb1c4SDavid du Colombier 	p->to.type = D_CONST;
569*fbadb1c4SDavid du Colombier 	p->to.name = D_NONE;
570*fbadb1c4SDavid du Colombier 	return p;
571*fbadb1c4SDavid du Colombier }
572*fbadb1c4SDavid du Colombier 
573*fbadb1c4SDavid du Colombier void
export(void)574*fbadb1c4SDavid du Colombier export(void)
575*fbadb1c4SDavid du Colombier {
576*fbadb1c4SDavid du Colombier 	int i, j, n, off, nb, sv, ne;
577*fbadb1c4SDavid du Colombier 	Sym *s, *et, *str, **esyms;
578*fbadb1c4SDavid du Colombier 	Prog *p;
579*fbadb1c4SDavid du Colombier 	char buf[NSNAME], *t;
580*fbadb1c4SDavid du Colombier 
581*fbadb1c4SDavid du Colombier 	n = 0;
582*fbadb1c4SDavid du Colombier 	for(i = 0; i < NHASH; i++)
583*fbadb1c4SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
584*fbadb1c4SDavid du Colombier 			if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport))
585*fbadb1c4SDavid du Colombier 				n++;
586*fbadb1c4SDavid du Colombier 	esyms = malloc(n*sizeof(Sym*));
587*fbadb1c4SDavid du Colombier 	ne = n;
588*fbadb1c4SDavid du Colombier 	n = 0;
589*fbadb1c4SDavid du Colombier 	for(i = 0; i < NHASH; i++)
590*fbadb1c4SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
591*fbadb1c4SDavid du Colombier 			if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport))
592*fbadb1c4SDavid du Colombier 				esyms[n++] = s;
593*fbadb1c4SDavid du Colombier 	for(i = 0; i < ne-1; i++)
594*fbadb1c4SDavid du Colombier 		for(j = i+1; j < ne; j++)
595*fbadb1c4SDavid du Colombier 			if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
596*fbadb1c4SDavid du Colombier 				s = esyms[i];
597*fbadb1c4SDavid du Colombier 				esyms[i] = esyms[j];
598*fbadb1c4SDavid du Colombier 				esyms[j] = s;
599*fbadb1c4SDavid du Colombier 			}
600*fbadb1c4SDavid du Colombier 
601*fbadb1c4SDavid du Colombier 	nb = 0;
602*fbadb1c4SDavid du Colombier 	off = 0;
603*fbadb1c4SDavid du Colombier 	et = lookup(EXPTAB, 0);
604*fbadb1c4SDavid du Colombier 	if(et->type != 0 && et->type != SXREF)
605*fbadb1c4SDavid du Colombier 		diag("%s already defined", EXPTAB);
606*fbadb1c4SDavid du Colombier 	et->type = SDATA;
607*fbadb1c4SDavid du Colombier 	str = lookup(".string", 0);
608*fbadb1c4SDavid du Colombier 	if(str->type == 0)
609*fbadb1c4SDavid du Colombier 		str->type = SDATA;
610*fbadb1c4SDavid du Colombier 	sv = str->value;
611*fbadb1c4SDavid du Colombier 	for(i = 0; i < ne; i++){
612*fbadb1c4SDavid du Colombier 		s = esyms[i];
613*fbadb1c4SDavid du Colombier 		Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
614*fbadb1c4SDavid du Colombier 
615*fbadb1c4SDavid du Colombier 		/* signature */
616*fbadb1c4SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
617*fbadb1c4SDavid du Colombier 		off += sizeof(long);
618*fbadb1c4SDavid du Colombier 		p->to.offset = s->sig;
619*fbadb1c4SDavid du Colombier 
620*fbadb1c4SDavid du Colombier 		/* address */
621*fbadb1c4SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
622*fbadb1c4SDavid du Colombier 		off += sizeof(long);		/* TO DO: bug */
623*fbadb1c4SDavid du Colombier 		p->to.name = D_EXTERN;
624*fbadb1c4SDavid du Colombier 		p->to.sym = s;
625*fbadb1c4SDavid du Colombier 
626*fbadb1c4SDavid du Colombier 		/* string */
627*fbadb1c4SDavid du Colombier 		t = s->name;
628*fbadb1c4SDavid du Colombier 		n = strlen(t)+1;
629*fbadb1c4SDavid du Colombier 		for(;;){
630*fbadb1c4SDavid du Colombier 			buf[nb++] = *t;
631*fbadb1c4SDavid du Colombier 			sv++;
632*fbadb1c4SDavid du Colombier 			if(nb >= NSNAME){
633*fbadb1c4SDavid du Colombier 				p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
634*fbadb1c4SDavid du Colombier 				p->to.type = D_SCONST;
635*fbadb1c4SDavid du Colombier 				memmove(p->to.sval, buf, NSNAME);
636*fbadb1c4SDavid du Colombier 				nb = 0;
637*fbadb1c4SDavid du Colombier 			}
638*fbadb1c4SDavid du Colombier 			if(*t++ == 0)
639*fbadb1c4SDavid du Colombier 				break;
640*fbadb1c4SDavid du Colombier 		}
641*fbadb1c4SDavid du Colombier 
642*fbadb1c4SDavid du Colombier 		/* name */
643*fbadb1c4SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
644*fbadb1c4SDavid du Colombier 		off += sizeof(long);
645*fbadb1c4SDavid du Colombier 		p->to.name = D_STATIC;
646*fbadb1c4SDavid du Colombier 		p->to.sym = str;
647*fbadb1c4SDavid du Colombier 		p->to.offset = sv-n;
648*fbadb1c4SDavid du Colombier 	}
649*fbadb1c4SDavid du Colombier 
650*fbadb1c4SDavid du Colombier 	if(nb > 0){
651*fbadb1c4SDavid du Colombier 		p = newdata(str, sv-nb, nb, D_STATIC);
652*fbadb1c4SDavid du Colombier 		p->to.type = D_SCONST;
653*fbadb1c4SDavid du Colombier 		memmove(p->to.sval, buf, nb);
654*fbadb1c4SDavid du Colombier 	}
655*fbadb1c4SDavid du Colombier 
656*fbadb1c4SDavid du Colombier 	for(i = 0; i < 3; i++){
657*fbadb1c4SDavid du Colombier 		newdata(et, off, sizeof(long), D_EXTERN);
658*fbadb1c4SDavid du Colombier 		off += sizeof(long);
659*fbadb1c4SDavid du Colombier 	}
660*fbadb1c4SDavid du Colombier 	et->value = off;
661*fbadb1c4SDavid du Colombier 	if(sv == 0)
662*fbadb1c4SDavid du Colombier 		sv = 1;
663*fbadb1c4SDavid du Colombier 	str->value = sv;
664*fbadb1c4SDavid du Colombier 	exports = ne;
665*fbadb1c4SDavid du Colombier 	free(esyms);
666*fbadb1c4SDavid du Colombier }
667