xref: /plan9-contrib/sys/src/cmd/6l/pass.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
1e887ea33SDavid du Colombier #include	"l.h"
2e887ea33SDavid du Colombier 
3e887ea33SDavid du Colombier void
dodata(void)4e887ea33SDavid du Colombier dodata(void)
5e887ea33SDavid du Colombier {
6e887ea33SDavid du Colombier 	int i;
7e887ea33SDavid du Colombier 	Sym *s;
8e887ea33SDavid du Colombier 	Prog *p;
9e887ea33SDavid du Colombier 	long t, u;
10e887ea33SDavid du Colombier 
11e887ea33SDavid du Colombier 	if(debug['v'])
12e887ea33SDavid du Colombier 		Bprint(&bso, "%5.2f dodata\n", cputime());
13e887ea33SDavid du Colombier 	Bflush(&bso);
14e887ea33SDavid du Colombier 	for(p = datap; p != P; p = p->link) {
15e887ea33SDavid du Colombier 		s = p->from.sym;
16e887ea33SDavid du Colombier 		if(p->as == ADYNT || p->as == AINIT)
17e887ea33SDavid du Colombier 			s->value = dtype;
18e887ea33SDavid du Colombier 		if(s->type == SBSS)
19e887ea33SDavid du Colombier 			s->type = SDATA;
20e887ea33SDavid du Colombier 		if(s->type != SDATA)
21e887ea33SDavid du Colombier 			diag("initialize non-data (%d): %s\n%P",
22e887ea33SDavid du Colombier 				s->type, s->name, p);
23e887ea33SDavid du Colombier 		t = p->from.offset + p->width;
24e887ea33SDavid du Colombier 		if(t > s->value)
25e887ea33SDavid du Colombier 			diag("initialize bounds (%lld): %s\n%P",
26e887ea33SDavid du Colombier 				s->value, s->name, p);
27e887ea33SDavid du Colombier 	}
28e887ea33SDavid du Colombier 	/* allocate small guys */
29e887ea33SDavid du Colombier 	datsize = 0;
30e887ea33SDavid du Colombier 	for(i=0; i<NHASH; i++)
31e887ea33SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
32e887ea33SDavid du Colombier 		if(s->type != SDATA)
33e887ea33SDavid du Colombier 		if(s->type != SBSS)
34e887ea33SDavid du Colombier 			continue;
35e887ea33SDavid du Colombier 		t = s->value;
36e887ea33SDavid du Colombier 		if(t == 0) {
37e887ea33SDavid du Colombier 			diag("%s: no size", s->name);
38e887ea33SDavid du Colombier 			t = 1;
39e887ea33SDavid du Colombier 		}
40e887ea33SDavid du Colombier 		t = rnd(t, 4);
41e887ea33SDavid du Colombier 		s->value = t;
42e887ea33SDavid du Colombier 		if(t > MINSIZ)
43e887ea33SDavid du Colombier 			continue;
44e887ea33SDavid du Colombier 		if(t >= 8)
45e887ea33SDavid du Colombier 			datsize = rnd(datsize, 8);
46e887ea33SDavid du Colombier 		s->value = datsize;
47e887ea33SDavid du Colombier 		datsize += t;
48e887ea33SDavid du Colombier 		s->type = SDATA1;
49e887ea33SDavid du Colombier 	}
50e887ea33SDavid du Colombier 
51e887ea33SDavid du Colombier 	/* allocate the rest of the data */
52e887ea33SDavid du Colombier 	for(i=0; i<NHASH; i++)
53e887ea33SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
54e887ea33SDavid du Colombier 		if(s->type != SDATA) {
55e887ea33SDavid du Colombier 			if(s->type == SDATA1)
56e887ea33SDavid du Colombier 				s->type = SDATA;
57e887ea33SDavid du Colombier 			continue;
58e887ea33SDavid du Colombier 		}
59e887ea33SDavid du Colombier 		t = s->value;
60e887ea33SDavid du Colombier 		if(t >= 8)
61e887ea33SDavid du Colombier 			datsize = rnd(datsize, 8);
62e887ea33SDavid du Colombier 		s->value = datsize;
63e887ea33SDavid du Colombier 		datsize += t;
64e887ea33SDavid du Colombier 	}
65e887ea33SDavid du Colombier 	if(datsize)
66e887ea33SDavid du Colombier 		datsize = rnd(datsize, 8);
67e887ea33SDavid du Colombier 
68e887ea33SDavid du Colombier 	if(debug['j']) {
69e887ea33SDavid du Colombier 		/*
70e887ea33SDavid du Colombier 		 * pad data with bss that fits up to next
71e887ea33SDavid du Colombier 		 * 8k boundary, then push data to 8k
72e887ea33SDavid du Colombier 		 */
73e887ea33SDavid du Colombier 		u = rnd(datsize, 8192);
74e887ea33SDavid du Colombier 		u -= datsize;
75e887ea33SDavid du Colombier 		for(i=0; i<NHASH; i++)
76e887ea33SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link) {
77e887ea33SDavid du Colombier 			if(s->type != SBSS)
78e887ea33SDavid du Colombier 				continue;
79e887ea33SDavid du Colombier 			t = s->value;
80e887ea33SDavid du Colombier 			if(t > u)
81e887ea33SDavid du Colombier 				continue;
82e887ea33SDavid du Colombier 			u -= t;
83e887ea33SDavid du Colombier 			s->value = datsize;
84e887ea33SDavid du Colombier 			s->type = SDATA;
85e887ea33SDavid du Colombier 			datsize += t;
86e887ea33SDavid du Colombier 		}
87e887ea33SDavid du Colombier 		datsize += u;
88e887ea33SDavid du Colombier 	}
89e887ea33SDavid du Colombier 
90e887ea33SDavid du Colombier 	/* now the bss */
91e887ea33SDavid du Colombier 	bsssize = 0;
92e887ea33SDavid du Colombier 	for(i=0; i<NHASH; i++)
93e887ea33SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
94e887ea33SDavid du Colombier 		if(s->type != SBSS)
95e887ea33SDavid du Colombier 			continue;
96e887ea33SDavid du Colombier 		t = s->value;
97e887ea33SDavid du Colombier 		if(t >= 8)
98e887ea33SDavid du Colombier 			bsssize = rnd(bsssize, 8);
99e887ea33SDavid du Colombier 		s->value = bsssize + datsize;
100e887ea33SDavid du Colombier 		bsssize += t;
101e887ea33SDavid du Colombier 	}
102*40d01547SDavid du Colombier 	xdefine("bdata", SDATA, 0L);
103e887ea33SDavid du Colombier 	xdefine("edata", SBSS, datsize);
104e887ea33SDavid du Colombier 	xdefine("end", SBSS, bsssize + datsize);
105*40d01547SDavid du Colombier 	/* etext is defined in span.c */
106e887ea33SDavid du Colombier }
107e887ea33SDavid du Colombier 
108e887ea33SDavid du Colombier Prog*
brchain(Prog * p)109e887ea33SDavid du Colombier brchain(Prog *p)
110e887ea33SDavid du Colombier {
111e887ea33SDavid du Colombier 	int i;
112e887ea33SDavid du Colombier 
113e887ea33SDavid du Colombier 	for(i=0; i<20; i++) {
114e887ea33SDavid du Colombier 		if(p == P || p->as != AJMP)
115e887ea33SDavid du Colombier 			return p;
116e887ea33SDavid du Colombier 		p = p->pcond;
117e887ea33SDavid du Colombier 	}
118e887ea33SDavid du Colombier 	return P;
119e887ea33SDavid du Colombier }
120e887ea33SDavid du Colombier 
121e887ea33SDavid du Colombier void
follow(void)122e887ea33SDavid du Colombier follow(void)
123e887ea33SDavid du Colombier {
124e887ea33SDavid du Colombier 
125e887ea33SDavid du Colombier 	if(debug['v'])
126e887ea33SDavid du Colombier 		Bprint(&bso, "%5.2f follow\n", cputime());
127e887ea33SDavid du Colombier 	Bflush(&bso);
128e887ea33SDavid du Colombier 	firstp = prg();
129e887ea33SDavid du Colombier 	lastp = firstp;
130e887ea33SDavid du Colombier 	xfol(textp);
131e887ea33SDavid du Colombier 	lastp->link = P;
132e887ea33SDavid du Colombier 	firstp = firstp->link;
133e887ea33SDavid du Colombier }
134e887ea33SDavid du Colombier 
135e887ea33SDavid du Colombier void
xfol(Prog * p)136e887ea33SDavid du Colombier xfol(Prog *p)
137e887ea33SDavid du Colombier {
138e887ea33SDavid du Colombier 	Prog *q;
139e887ea33SDavid du Colombier 	int i;
140e887ea33SDavid du Colombier 	enum as a;
141e887ea33SDavid du Colombier 
142e887ea33SDavid du Colombier loop:
143e887ea33SDavid du Colombier 	if(p == P)
144e887ea33SDavid du Colombier 		return;
145e887ea33SDavid du Colombier 	if(p->as == ATEXT)
146e887ea33SDavid du Colombier 		curtext = p;
147e887ea33SDavid du Colombier 	if(p->as == AJMP)
148e887ea33SDavid du Colombier 	if((q = p->pcond) != P) {
149e887ea33SDavid du Colombier 		p->mark = 1;
150e887ea33SDavid du Colombier 		p = q;
151e887ea33SDavid du Colombier 		if(p->mark == 0)
152e887ea33SDavid du Colombier 			goto loop;
153e887ea33SDavid du Colombier 	}
154e887ea33SDavid du Colombier 	if(p->mark) {
155e887ea33SDavid du Colombier 		/* copy up to 4 instructions to avoid branch */
156e887ea33SDavid du Colombier 		for(i=0,q=p; i<4; i++,q=q->link) {
157e887ea33SDavid du Colombier 			if(q == P)
158e887ea33SDavid du Colombier 				break;
159e887ea33SDavid du Colombier 			if(q == lastp)
160e887ea33SDavid du Colombier 				break;
161e887ea33SDavid du Colombier 			a = q->as;
162*40d01547SDavid du Colombier 			if(a == ANOP || a == ATEXT) {
163e887ea33SDavid du Colombier 				i--;
164e887ea33SDavid du Colombier 				continue;
165e887ea33SDavid du Colombier 			}
166e887ea33SDavid du Colombier 			switch(a) {
167e887ea33SDavid du Colombier 			case AJMP:
168e887ea33SDavid du Colombier 			case ARET:
169e887ea33SDavid du Colombier 			case AIRETL:
170e887ea33SDavid du Colombier 			case AIRETQ:
171e887ea33SDavid du Colombier 			case AIRETW:
172e887ea33SDavid du Colombier 			case ARETFL:
173e887ea33SDavid du Colombier 			case ARETFQ:
174e887ea33SDavid du Colombier 			case ARETFW:
175e887ea33SDavid du Colombier 
176e887ea33SDavid du Colombier 			case APUSHL:
177e887ea33SDavid du Colombier 			case APUSHFL:
178e887ea33SDavid du Colombier 			case APUSHQ:
179e887ea33SDavid du Colombier 			case APUSHFQ:
180e887ea33SDavid du Colombier 			case APUSHW:
181e887ea33SDavid du Colombier 			case APUSHFW:
182e887ea33SDavid du Colombier 			case APOPL:
183e887ea33SDavid du Colombier 			case APOPFL:
184e887ea33SDavid du Colombier 			case APOPQ:
185e887ea33SDavid du Colombier 			case APOPFQ:
186e887ea33SDavid du Colombier 			case APOPW:
187e887ea33SDavid du Colombier 			case APOPFW:
188e887ea33SDavid du Colombier 				goto brk;
189e887ea33SDavid du Colombier 			}
190e887ea33SDavid du Colombier 			if(q->pcond == P || q->pcond->mark)
191e887ea33SDavid du Colombier 				continue;
192e887ea33SDavid du Colombier 			if(a == ACALL || a == ALOOP)
193e887ea33SDavid du Colombier 				continue;
194e887ea33SDavid du Colombier 			for(;;) {
195e887ea33SDavid du Colombier 				if(p->as == ANOP) {
196e887ea33SDavid du Colombier 					p = p->link;
197e887ea33SDavid du Colombier 					continue;
198e887ea33SDavid du Colombier 				}
199e887ea33SDavid du Colombier 				q = copyp(p);
200e887ea33SDavid du Colombier 				p = p->link;
201e887ea33SDavid du Colombier 				q->mark = 1;
202e887ea33SDavid du Colombier 				lastp->link = q;
203e887ea33SDavid du Colombier 				lastp = q;
204e887ea33SDavid du Colombier 				if(q->as != a || q->pcond == P || q->pcond->mark)
205e887ea33SDavid du Colombier 					continue;
206e887ea33SDavid du Colombier 
207e887ea33SDavid du Colombier 				q->as = relinv(q->as);
208e887ea33SDavid du Colombier 				p = q->pcond;
209e887ea33SDavid du Colombier 				q->pcond = q->link;
210e887ea33SDavid du Colombier 				q->link = p;
211e887ea33SDavid du Colombier 				xfol(q->link);
212e887ea33SDavid du Colombier 				p = q->link;
213e887ea33SDavid du Colombier 				if(p->mark)
214e887ea33SDavid du Colombier 					return;
215e887ea33SDavid du Colombier 				goto loop;
216e887ea33SDavid du Colombier 			}
217e887ea33SDavid du Colombier 		} /* */
218e887ea33SDavid du Colombier 	brk:;
219e887ea33SDavid du Colombier 		q = prg();
220e887ea33SDavid du Colombier 		q->as = AJMP;
221e887ea33SDavid du Colombier 		q->line = p->line;
222e887ea33SDavid du Colombier 		q->to.type = D_BRANCH;
223e887ea33SDavid du Colombier 		q->to.offset = p->pc;
224e887ea33SDavid du Colombier 		q->pcond = p;
225e887ea33SDavid du Colombier 		p = q;
226e887ea33SDavid du Colombier 	}
227e887ea33SDavid du Colombier 	p->mark = 1;
228e887ea33SDavid du Colombier 	lastp->link = p;
229e887ea33SDavid du Colombier 	lastp = p;
230e887ea33SDavid du Colombier 	a = p->as;
231e887ea33SDavid du Colombier 	if(a == AJMP || a == ARET || a == AIRETL || a == AIRETQ || a == AIRETW ||
232e887ea33SDavid du Colombier 	   a == ARETFL || a == ARETFQ || a == ARETFW)
233e887ea33SDavid du Colombier 		return;
234*40d01547SDavid du Colombier 	if(a == ATEXT) {
235*40d01547SDavid du Colombier 		xfol(p->link);
236*40d01547SDavid du Colombier 		q = p->pcond;
237*40d01547SDavid du Colombier 		if(q == P || q->mark)
238*40d01547SDavid du Colombier 			return;
239*40d01547SDavid du Colombier 		p = q;
240*40d01547SDavid du Colombier 		goto loop;
241*40d01547SDavid du Colombier 	}
242e887ea33SDavid du Colombier 	if(p->pcond != P)
243e887ea33SDavid du Colombier 	if(a != ACALL) {
244e887ea33SDavid du Colombier 		q = brchain(p->link);
245e887ea33SDavid du Colombier 		if(q != P && q->mark)
246*40d01547SDavid du Colombier 		if(a != ALOOP && a != ATEXT) {
247e887ea33SDavid du Colombier 			p->as = relinv(a);
248e887ea33SDavid du Colombier 			p->link = p->pcond;
249e887ea33SDavid du Colombier 			p->pcond = q;
250e887ea33SDavid du Colombier 		}
251e887ea33SDavid du Colombier 		xfol(p->link);
252e887ea33SDavid du Colombier 		q = brchain(p->pcond);
253e887ea33SDavid du Colombier 		if(q->mark) {
254e887ea33SDavid du Colombier 			p->pcond = q;
255e887ea33SDavid du Colombier 			return;
256e887ea33SDavid du Colombier 		}
257e887ea33SDavid du Colombier 		p = q;
258e887ea33SDavid du Colombier 		goto loop;
259e887ea33SDavid du Colombier 	}
260e887ea33SDavid du Colombier 	p = p->link;
261e887ea33SDavid du Colombier 	goto loop;
262e887ea33SDavid du Colombier }
263e887ea33SDavid du Colombier 
264e887ea33SDavid du Colombier int
relinv(int a)265e887ea33SDavid du Colombier relinv(int a)
266e887ea33SDavid du Colombier {
267e887ea33SDavid du Colombier 
268e887ea33SDavid du Colombier 	switch(a) {
269e887ea33SDavid du Colombier 	case AJEQ:	return AJNE;
270e887ea33SDavid du Colombier 	case AJNE:	return AJEQ;
271e887ea33SDavid du Colombier 	case AJLE:	return AJGT;
272e887ea33SDavid du Colombier 	case AJLS:	return AJHI;
273e887ea33SDavid du Colombier 	case AJLT:	return AJGE;
274e887ea33SDavid du Colombier 	case AJMI:	return AJPL;
275e887ea33SDavid du Colombier 	case AJGE:	return AJLT;
276e887ea33SDavid du Colombier 	case AJPL:	return AJMI;
277e887ea33SDavid du Colombier 	case AJGT:	return AJLE;
278e887ea33SDavid du Colombier 	case AJHI:	return AJLS;
279e887ea33SDavid du Colombier 	case AJCS:	return AJCC;
280e887ea33SDavid du Colombier 	case AJCC:	return AJCS;
281e887ea33SDavid du Colombier 	case AJPS:	return AJPC;
282e887ea33SDavid du Colombier 	case AJPC:	return AJPS;
283e887ea33SDavid du Colombier 	case AJOS:	return AJOC;
284e887ea33SDavid du Colombier 	case AJOC:	return AJOS;
285e887ea33SDavid du Colombier 	}
286e887ea33SDavid du Colombier 	diag("unknown relation: %s in %s", anames[a], TNAME);
287e887ea33SDavid du Colombier 	return a;
288e887ea33SDavid du Colombier }
289e887ea33SDavid du Colombier 
290e887ea33SDavid du Colombier void
doinit(void)291e887ea33SDavid du Colombier doinit(void)
292e887ea33SDavid du Colombier {
293e887ea33SDavid du Colombier 	Sym *s;
294e887ea33SDavid du Colombier 	Prog *p;
295e887ea33SDavid du Colombier 	int x;
296e887ea33SDavid du Colombier 
297e887ea33SDavid du Colombier 	for(p = datap; p != P; p = p->link) {
298e887ea33SDavid du Colombier 		x = p->to.type;
299e887ea33SDavid du Colombier 		if(x != D_EXTERN && x != D_STATIC)
300e887ea33SDavid du Colombier 			continue;
301e887ea33SDavid du Colombier 		s = p->to.sym;
302e887ea33SDavid du Colombier 		if(s->type == 0 || s->type == SXREF)
303e887ea33SDavid du Colombier 			diag("undefined %s initializer of %s",
304e887ea33SDavid du Colombier 				s->name, p->from.sym->name);
305e887ea33SDavid du Colombier 		p->to.offset += s->value;
306e887ea33SDavid du Colombier 		p->to.type = D_CONST;
307e887ea33SDavid du Colombier 		if(s->type == SDATA || s->type == SBSS)
308e887ea33SDavid du Colombier 			p->to.offset += INITDAT;
309e887ea33SDavid du Colombier 	}
310e887ea33SDavid du Colombier }
311e887ea33SDavid du Colombier 
312e887ea33SDavid du Colombier void
patch(void)313e887ea33SDavid du Colombier patch(void)
314e887ea33SDavid du Colombier {
315e887ea33SDavid du Colombier 	long c;
316e887ea33SDavid du Colombier 	Prog *p, *q;
317e887ea33SDavid du Colombier 	Sym *s;
318e887ea33SDavid du Colombier 	long vexit;
319e887ea33SDavid du Colombier 
320e887ea33SDavid du Colombier 	if(debug['v'])
321e887ea33SDavid du Colombier 		Bprint(&bso, "%5.2f mkfwd\n", cputime());
322e887ea33SDavid du Colombier 	Bflush(&bso);
323e887ea33SDavid du Colombier 	mkfwd();
324e887ea33SDavid du Colombier 	if(debug['v'])
325e887ea33SDavid du Colombier 		Bprint(&bso, "%5.2f patch\n", cputime());
326e887ea33SDavid du Colombier 	Bflush(&bso);
327e887ea33SDavid du Colombier 	s = lookup("exit", 0);
328e887ea33SDavid du Colombier 	vexit = s->value;
329e887ea33SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
330e887ea33SDavid du Colombier 		if(p->as == ATEXT)
331e887ea33SDavid du Colombier 			curtext = p;
332e887ea33SDavid du Colombier 		if(p->as == ACALL || p->as == ARET) {
333e887ea33SDavid du Colombier 			s = p->to.sym;
334e887ea33SDavid du Colombier 			if(s) {
335e887ea33SDavid du Colombier 				if(debug['c'])
336e887ea33SDavid du Colombier 					Bprint(&bso, "%s calls %s\n", TNAME, s->name);
337e887ea33SDavid du Colombier 				switch(s->type) {
338e887ea33SDavid du Colombier 				default:
339*40d01547SDavid du Colombier 					/* diag prints TNAME first */
340*40d01547SDavid du Colombier 					diag("undefined: %s", s->name);
341e887ea33SDavid du Colombier 					s->type = STEXT;
342e887ea33SDavid du Colombier 					s->value = vexit;
343e887ea33SDavid du Colombier 					break;	/* or fall through to set offset? */
344e887ea33SDavid du Colombier 				case STEXT:
345e887ea33SDavid du Colombier 					p->to.offset = s->value;
346e887ea33SDavid du Colombier 					break;
347e887ea33SDavid du Colombier 				case SUNDEF:
348e887ea33SDavid du Colombier 					p->pcond = UP;
349e887ea33SDavid du Colombier 					p->to.offset = 0;
350e887ea33SDavid du Colombier 					break;
351e887ea33SDavid du Colombier 				}
352e887ea33SDavid du Colombier 				p->to.type = D_BRANCH;
353e887ea33SDavid du Colombier 			}
354e887ea33SDavid du Colombier 		}
355e887ea33SDavid du Colombier 		if(p->to.type != D_BRANCH || p->pcond == UP)
356e887ea33SDavid du Colombier 			continue;
357e887ea33SDavid du Colombier 		c = p->to.offset;
358e887ea33SDavid du Colombier 		for(q = firstp; q != P;) {
359e887ea33SDavid du Colombier 			if(q->forwd != P)
360e887ea33SDavid du Colombier 			if(c >= q->forwd->pc) {
361e887ea33SDavid du Colombier 				q = q->forwd;
362e887ea33SDavid du Colombier 				continue;
363e887ea33SDavid du Colombier 			}
364e887ea33SDavid du Colombier 			if(c == q->pc)
365e887ea33SDavid du Colombier 				break;
366e887ea33SDavid du Colombier 			q = q->link;
367e887ea33SDavid du Colombier 		}
368e887ea33SDavid du Colombier 		if(q == P) {
369e887ea33SDavid du Colombier 			diag("branch out of range in %s\n%P", TNAME, p);
370e887ea33SDavid du Colombier 			p->to.type = D_NONE;
371e887ea33SDavid du Colombier 		}
372e887ea33SDavid du Colombier 		p->pcond = q;
373e887ea33SDavid du Colombier 	}
374e887ea33SDavid du Colombier 
375e887ea33SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
376e887ea33SDavid du Colombier 		if(p->as == ATEXT)
377e887ea33SDavid du Colombier 			curtext = p;
378e887ea33SDavid du Colombier 		p->mark = 0;	/* initialization for follow */
379e887ea33SDavid du Colombier 		if(p->pcond != P && p->pcond != UP) {
380e887ea33SDavid du Colombier 			p->pcond = brloop(p->pcond);
381e887ea33SDavid du Colombier 			if(p->pcond != P)
382e887ea33SDavid du Colombier 			if(p->to.type == D_BRANCH)
383e887ea33SDavid du Colombier 				p->to.offset = p->pcond->pc;
384e887ea33SDavid du Colombier 		}
385e887ea33SDavid du Colombier 	}
386e887ea33SDavid du Colombier }
387e887ea33SDavid du Colombier 
388e887ea33SDavid du Colombier #define	LOG	5
389e887ea33SDavid du Colombier void
mkfwd(void)390e887ea33SDavid du Colombier mkfwd(void)
391e887ea33SDavid du Colombier {
392e887ea33SDavid du Colombier 	Prog *p;
393e887ea33SDavid du Colombier 	int i;
394e887ea33SDavid du Colombier 	long dwn[LOG], cnt[LOG];
395e887ea33SDavid du Colombier 	Prog *lst[LOG];
396e887ea33SDavid du Colombier 
397e887ea33SDavid du Colombier 	for(i=0; i<LOG; i++) {
398e887ea33SDavid du Colombier 		if(i == 0)
399e887ea33SDavid du Colombier 			cnt[i] = 1; else
400e887ea33SDavid du Colombier 			cnt[i] = LOG * cnt[i-1];
401e887ea33SDavid du Colombier 		dwn[i] = 1;
402e887ea33SDavid du Colombier 		lst[i] = P;
403e887ea33SDavid du Colombier 	}
404e887ea33SDavid du Colombier 	i = 0;
405e887ea33SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
406e887ea33SDavid du Colombier 		if(p->as == ATEXT)
407e887ea33SDavid du Colombier 			curtext = p;
408e887ea33SDavid du Colombier 		i--;
409e887ea33SDavid du Colombier 		if(i < 0)
410e887ea33SDavid du Colombier 			i = LOG-1;
411e887ea33SDavid du Colombier 		p->forwd = P;
412e887ea33SDavid du Colombier 		dwn[i]--;
413e887ea33SDavid du Colombier 		if(dwn[i] <= 0) {
414e887ea33SDavid du Colombier 			dwn[i] = cnt[i];
415e887ea33SDavid du Colombier 			if(lst[i] != P)
416e887ea33SDavid du Colombier 				lst[i]->forwd = p;
417e887ea33SDavid du Colombier 			lst[i] = p;
418e887ea33SDavid du Colombier 		}
419e887ea33SDavid du Colombier 	}
420e887ea33SDavid du Colombier }
421e887ea33SDavid du Colombier 
422e887ea33SDavid du Colombier Prog*
brloop(Prog * p)423e887ea33SDavid du Colombier brloop(Prog *p)
424e887ea33SDavid du Colombier {
425e887ea33SDavid du Colombier 	int c;
426e887ea33SDavid du Colombier 	Prog *q;
427e887ea33SDavid du Colombier 
428e887ea33SDavid du Colombier 	c = 0;
429e887ea33SDavid du Colombier 	for(q = p; q != P; q = q->pcond) {
430e887ea33SDavid du Colombier 		if(q->as != AJMP)
431e887ea33SDavid du Colombier 			break;
432e887ea33SDavid du Colombier 		c++;
433e887ea33SDavid du Colombier 		if(c >= 5000)
434e887ea33SDavid du Colombier 			return P;
435e887ea33SDavid du Colombier 	}
436e887ea33SDavid du Colombier 	return q;
437e887ea33SDavid du Colombier }
438e887ea33SDavid du Colombier 
439e887ea33SDavid du Colombier void
dostkoff(void)440e887ea33SDavid du Colombier dostkoff(void)
441e887ea33SDavid du Colombier {
442e887ea33SDavid du Colombier 	Prog *p, *q;
443e887ea33SDavid du Colombier 	long autoffset, deltasp;
444e887ea33SDavid du Colombier 	int a, f, curframe, curbecome, maxbecome, pcsize;
445e887ea33SDavid du Colombier 
446e887ea33SDavid du Colombier 	curframe = 0;
447e887ea33SDavid du Colombier 	curbecome = 0;
448e887ea33SDavid du Colombier 	maxbecome = 0;
449e887ea33SDavid du Colombier 	curtext = 0;
450e887ea33SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
451e887ea33SDavid du Colombier 
452e887ea33SDavid du Colombier 		/* find out how much arg space is used in this TEXT */
453e887ea33SDavid du Colombier 		if(p->to.type == (D_INDIR+D_SP))
454e887ea33SDavid du Colombier 			if(p->to.offset > curframe)
455e887ea33SDavid du Colombier 				curframe = p->to.offset;
456e887ea33SDavid du Colombier 
457e887ea33SDavid du Colombier 		switch(p->as) {
458e887ea33SDavid du Colombier 		case ATEXT:
459e887ea33SDavid du Colombier 			if(curtext && curtext->from.sym) {
460e887ea33SDavid du Colombier 				curtext->from.sym->frame = curframe;
461e887ea33SDavid du Colombier 				curtext->from.sym->become = curbecome;
462e887ea33SDavid du Colombier 				if(curbecome > maxbecome)
463e887ea33SDavid du Colombier 					maxbecome = curbecome;
464e887ea33SDavid du Colombier 			}
465e887ea33SDavid du Colombier 			curframe = 0;
466e887ea33SDavid du Colombier 			curbecome = 0;
467e887ea33SDavid du Colombier 
468e887ea33SDavid du Colombier 			curtext = p;
469e887ea33SDavid du Colombier 			break;
470e887ea33SDavid du Colombier 
471e887ea33SDavid du Colombier 		case ARET:
472e887ea33SDavid du Colombier 			/* special form of RET is BECOME */
473e887ea33SDavid du Colombier 			if(p->from.type == D_CONST)
474e887ea33SDavid du Colombier 				if(p->from.offset > curbecome)
475e887ea33SDavid du Colombier 					curbecome = p->from.offset;
476e887ea33SDavid du Colombier 			break;
477e887ea33SDavid du Colombier 		}
478e887ea33SDavid du Colombier 	}
479e887ea33SDavid du Colombier 	if(curtext && curtext->from.sym) {
480e887ea33SDavid du Colombier 		curtext->from.sym->frame = curframe;
481e887ea33SDavid du Colombier 		curtext->from.sym->become = curbecome;
482e887ea33SDavid du Colombier 		if(curbecome > maxbecome)
483e887ea33SDavid du Colombier 			maxbecome = curbecome;
484e887ea33SDavid du Colombier 	}
485e887ea33SDavid du Colombier 
486e887ea33SDavid du Colombier 	if(debug['b'])
487e887ea33SDavid du Colombier 		print("max become = %d\n", maxbecome);
488e887ea33SDavid du Colombier 	xdefine("ALEFbecome", STEXT, maxbecome);
489e887ea33SDavid du Colombier 
490e887ea33SDavid du Colombier 	curtext = 0;
491e887ea33SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
492e887ea33SDavid du Colombier 		switch(p->as) {
493e887ea33SDavid du Colombier 		case ATEXT:
494e887ea33SDavid du Colombier 			curtext = p;
495e887ea33SDavid du Colombier 			break;
496e887ea33SDavid du Colombier 		case ACALL:
497e887ea33SDavid du Colombier 			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
498e887ea33SDavid du Colombier 				f = maxbecome - curtext->from.sym->frame;
499e887ea33SDavid du Colombier 				if(f <= 0)
500e887ea33SDavid du Colombier 					break;
501e887ea33SDavid du Colombier 				/* calling a become or calling a variable */
502e887ea33SDavid du Colombier 				if(p->to.sym == S || p->to.sym->become) {
503e887ea33SDavid du Colombier 					curtext->to.offset += f;
504e887ea33SDavid du Colombier 					if(debug['b']) {
505e887ea33SDavid du Colombier 						curp = p;
506e887ea33SDavid du Colombier 						print("%D calling %D increase %d\n",
507e887ea33SDavid du Colombier 							&curtext->from, &p->to, f);
508e887ea33SDavid du Colombier 					}
509e887ea33SDavid du Colombier 				}
510e887ea33SDavid du Colombier 			}
511e887ea33SDavid du Colombier 			break;
512e887ea33SDavid du Colombier 		}
513e887ea33SDavid du Colombier 	}
514e887ea33SDavid du Colombier 
515e887ea33SDavid du Colombier 	autoffset = 0;
516e887ea33SDavid du Colombier 	deltasp = 0;
517e887ea33SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
518e887ea33SDavid du Colombier 		if(p->as == ATEXT) {
519e887ea33SDavid du Colombier 			curtext = p;
520e887ea33SDavid du Colombier 			autoffset = p->to.offset;
521e887ea33SDavid du Colombier 			if(autoffset < 0)
522e887ea33SDavid du Colombier 				autoffset = 0;
523e887ea33SDavid du Colombier 			if(autoffset) {
524e887ea33SDavid du Colombier 				p = appendp(p);
525e887ea33SDavid du Colombier 				p->as = AADJSP;
526e887ea33SDavid du Colombier 				p->from.type = D_CONST;
527e887ea33SDavid du Colombier 				p->from.offset = autoffset;
528e887ea33SDavid du Colombier 			}
529e887ea33SDavid du Colombier 			deltasp = autoffset;
530e887ea33SDavid du Colombier 		}
531e887ea33SDavid du Colombier 		pcsize = p->mode/8;
532e887ea33SDavid du Colombier 		a = p->from.type;
533e887ea33SDavid du Colombier 		if(a == D_AUTO)
534e887ea33SDavid du Colombier 			p->from.offset += deltasp;
535e887ea33SDavid du Colombier 		if(a == D_PARAM)
536e887ea33SDavid du Colombier 			p->from.offset += deltasp + pcsize;
537e887ea33SDavid du Colombier 		a = p->to.type;
538e887ea33SDavid du Colombier 		if(a == D_AUTO)
539e887ea33SDavid du Colombier 			p->to.offset += deltasp;
540e887ea33SDavid du Colombier 		if(a == D_PARAM)
541e887ea33SDavid du Colombier 			p->to.offset += deltasp + pcsize;
542e887ea33SDavid du Colombier 
543e887ea33SDavid du Colombier 		switch(p->as) {
544e887ea33SDavid du Colombier 		default:
545e887ea33SDavid du Colombier 			continue;
546e887ea33SDavid du Colombier 		case APUSHL:
547e887ea33SDavid du Colombier 		case APUSHFL:
548e887ea33SDavid du Colombier 			deltasp += 4;
549e887ea33SDavid du Colombier 			continue;
550e887ea33SDavid du Colombier 		case APUSHQ:
551e887ea33SDavid du Colombier 		case APUSHFQ:
552e887ea33SDavid du Colombier 			deltasp += 8;
553e887ea33SDavid du Colombier 			continue;
554e887ea33SDavid du Colombier 		case APUSHW:
555e887ea33SDavid du Colombier 		case APUSHFW:
556e887ea33SDavid du Colombier 			deltasp += 2;
557e887ea33SDavid du Colombier 			continue;
558e887ea33SDavid du Colombier 		case APOPL:
559e887ea33SDavid du Colombier 		case APOPFL:
560e887ea33SDavid du Colombier 			deltasp -= 4;
561e887ea33SDavid du Colombier 			continue;
562e887ea33SDavid du Colombier 		case APOPQ:
563e887ea33SDavid du Colombier 		case APOPFQ:
564e887ea33SDavid du Colombier 			deltasp -= 8;
565e887ea33SDavid du Colombier 			continue;
566e887ea33SDavid du Colombier 		case APOPW:
567e887ea33SDavid du Colombier 		case APOPFW:
568e887ea33SDavid du Colombier 			deltasp -= 2;
569e887ea33SDavid du Colombier 			continue;
570e887ea33SDavid du Colombier 		case ARET:
571e887ea33SDavid du Colombier 			break;
572e887ea33SDavid du Colombier 		}
573e887ea33SDavid du Colombier 
574e887ea33SDavid du Colombier 		if(autoffset != deltasp)
575e887ea33SDavid du Colombier 			diag("unbalanced PUSH/POP");
576e887ea33SDavid du Colombier 		if(p->from.type == D_CONST)
577e887ea33SDavid du Colombier 			goto become;
578e887ea33SDavid du Colombier 
579e887ea33SDavid du Colombier 		if(autoffset) {
580e887ea33SDavid du Colombier 			q = p;
581e887ea33SDavid du Colombier 			p = appendp(p);
582e887ea33SDavid du Colombier 			p->as = ARET;
583e887ea33SDavid du Colombier 
584e887ea33SDavid du Colombier 			q->as = AADJSP;
585e887ea33SDavid du Colombier 			q->from.type = D_CONST;
586e887ea33SDavid du Colombier 			q->from.offset = -autoffset;
587e887ea33SDavid du Colombier 		}
588e887ea33SDavid du Colombier 		continue;
589e887ea33SDavid du Colombier 
590e887ea33SDavid du Colombier 	become:
591e887ea33SDavid du Colombier 		q = p;
592e887ea33SDavid du Colombier 		p = appendp(p);
593e887ea33SDavid du Colombier 		p->as = AJMP;
594e887ea33SDavid du Colombier 		p->to = q->to;
595e887ea33SDavid du Colombier 		p->pcond = q->pcond;
596e887ea33SDavid du Colombier 
597e887ea33SDavid du Colombier 		q->as = AADJSP;
598e887ea33SDavid du Colombier 		q->from = zprg.from;
599e887ea33SDavid du Colombier 		q->from.type = D_CONST;
600e887ea33SDavid du Colombier 		q->from.offset = -autoffset;
601e887ea33SDavid du Colombier 		q->to = zprg.to;
602e887ea33SDavid du Colombier 		continue;
603e887ea33SDavid du Colombier 	}
604e887ea33SDavid du Colombier }
605e887ea33SDavid du Colombier 
606e887ea33SDavid du Colombier vlong
atolwhex(char * s)607e887ea33SDavid du Colombier atolwhex(char *s)
608e887ea33SDavid du Colombier {
609e887ea33SDavid du Colombier 	vlong n;
610e887ea33SDavid du Colombier 	int f;
611e887ea33SDavid du Colombier 
612e887ea33SDavid du Colombier 	n = 0;
613e887ea33SDavid du Colombier 	f = 0;
614e887ea33SDavid du Colombier 	while(*s == ' ' || *s == '\t')
615e887ea33SDavid du Colombier 		s++;
616e887ea33SDavid du Colombier 	if(*s == '-' || *s == '+') {
617e887ea33SDavid du Colombier 		if(*s++ == '-')
618e887ea33SDavid du Colombier 			f = 1;
619e887ea33SDavid du Colombier 		while(*s == ' ' || *s == '\t')
620e887ea33SDavid du Colombier 			s++;
621e887ea33SDavid du Colombier 	}
622e887ea33SDavid du Colombier 	if(s[0]=='0' && s[1]){
623e887ea33SDavid du Colombier 		if(s[1]=='x' || s[1]=='X'){
624e887ea33SDavid du Colombier 			s += 2;
625e887ea33SDavid du Colombier 			for(;;){
626e887ea33SDavid du Colombier 				if(*s >= '0' && *s <= '9')
627e887ea33SDavid du Colombier 					n = n*16 + *s++ - '0';
628e887ea33SDavid du Colombier 				else if(*s >= 'a' && *s <= 'f')
629e887ea33SDavid du Colombier 					n = n*16 + *s++ - 'a' + 10;
630e887ea33SDavid du Colombier 				else if(*s >= 'A' && *s <= 'F')
631e887ea33SDavid du Colombier 					n = n*16 + *s++ - 'A' + 10;
632e887ea33SDavid du Colombier 				else
633e887ea33SDavid du Colombier 					break;
634e887ea33SDavid du Colombier 			}
635e887ea33SDavid du Colombier 		} else
636e887ea33SDavid du Colombier 			while(*s >= '0' && *s <= '7')
637e887ea33SDavid du Colombier 				n = n*8 + *s++ - '0';
638e887ea33SDavid du Colombier 	} else
639e887ea33SDavid du Colombier 		while(*s >= '0' && *s <= '9')
640e887ea33SDavid du Colombier 			n = n*10 + *s++ - '0';
641e887ea33SDavid du Colombier 	if(f)
642e887ea33SDavid du Colombier 		n = -n;
643e887ea33SDavid du Colombier 	return n;
644e887ea33SDavid du Colombier }
645e887ea33SDavid du Colombier 
646e887ea33SDavid du Colombier void
undef(void)647e887ea33SDavid du Colombier undef(void)
648e887ea33SDavid du Colombier {
649e887ea33SDavid du Colombier 	int i;
650e887ea33SDavid du Colombier 	Sym *s;
651e887ea33SDavid du Colombier 
652e887ea33SDavid du Colombier 	for(i=0; i<NHASH; i++)
653e887ea33SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link)
654e887ea33SDavid du Colombier 		if(s->type == SXREF)
655e887ea33SDavid du Colombier 			diag("%s: not defined", s->name);
656e887ea33SDavid du Colombier }
657e887ea33SDavid du Colombier 
658e887ea33SDavid du Colombier void
import(void)659e887ea33SDavid du Colombier import(void)
660e887ea33SDavid du Colombier {
661e887ea33SDavid du Colombier 	int i;
662e887ea33SDavid du Colombier 	Sym *s;
663e887ea33SDavid du Colombier 
664e887ea33SDavid du Colombier 	for(i = 0; i < NHASH; i++)
665e887ea33SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
666e887ea33SDavid du Colombier 			if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
667e887ea33SDavid du Colombier 				if(s->value != 0)
668e887ea33SDavid du Colombier 					diag("value != 0 on SXREF");
669e887ea33SDavid du Colombier 				undefsym(s);
670*40d01547SDavid du Colombier 				if(debug['X'])
671e887ea33SDavid du Colombier 					Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, s->value);
672e887ea33SDavid du Colombier 				if(debug['S'])
673e887ea33SDavid du Colombier 					s->sig = 0;
674e887ea33SDavid du Colombier 			}
675e887ea33SDavid du Colombier }
676e887ea33SDavid du Colombier 
677e887ea33SDavid du Colombier void
ckoff(Sym * s,long v)678e887ea33SDavid du Colombier ckoff(Sym *s, long v)
679e887ea33SDavid du Colombier {
680e887ea33SDavid du Colombier 	if(v < 0 || v >= 1<<Roffset)
681e887ea33SDavid du Colombier 		diag("relocation offset %ld for %s out of range", v, s->name);
682e887ea33SDavid du Colombier }
683e887ea33SDavid du Colombier 
684e887ea33SDavid du Colombier static Prog*
newdata(Sym * s,int o,int w,int t)685e887ea33SDavid du Colombier newdata(Sym *s, int o, int w, int t)
686e887ea33SDavid du Colombier {
687e887ea33SDavid du Colombier 	Prog *p;
688e887ea33SDavid du Colombier 
689e887ea33SDavid du Colombier 	p = prg();
690e887ea33SDavid du Colombier 	if(edatap == P)
691e887ea33SDavid du Colombier 		datap = p;
692e887ea33SDavid du Colombier 	else
693e887ea33SDavid du Colombier 		edatap->link = p;
694e887ea33SDavid du Colombier 	edatap = p;
695e887ea33SDavid du Colombier 	p->as = ADATA;
696e887ea33SDavid du Colombier 	p->width = w;
697e887ea33SDavid du Colombier 	p->from.scale = w;
698e887ea33SDavid du Colombier 	p->from.type = t;
699e887ea33SDavid du Colombier 	p->from.sym = s;
700e887ea33SDavid du Colombier 	p->from.offset = o;
701e887ea33SDavid du Colombier 	p->to.type = D_CONST;
702e887ea33SDavid du Colombier 	return p;
703e887ea33SDavid du Colombier }
704e887ea33SDavid du Colombier 
705e887ea33SDavid du Colombier void
export(void)706e887ea33SDavid du Colombier export(void)
707e887ea33SDavid du Colombier {
708e887ea33SDavid du Colombier 	int i, j, n, off, nb, sv, ne;
709e887ea33SDavid du Colombier 	Sym *s, *et, *str, **esyms;
710e887ea33SDavid du Colombier 	Prog *p;
711e887ea33SDavid du Colombier 	char buf[NSNAME], *t;
712e887ea33SDavid du Colombier 
713e887ea33SDavid du Colombier 	n = 0;
714e887ea33SDavid du Colombier 	for(i = 0; i < NHASH; i++)
715e887ea33SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
716*40d01547SDavid du Colombier 			if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport))
717e887ea33SDavid du Colombier 				n++;
718e887ea33SDavid du Colombier 	esyms = malloc(n*sizeof(Sym*));
719e887ea33SDavid du Colombier 	ne = n;
720e887ea33SDavid du Colombier 	n = 0;
721e887ea33SDavid du Colombier 	for(i = 0; i < NHASH; i++)
722e887ea33SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
723*40d01547SDavid du Colombier 			if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport))
724e887ea33SDavid du Colombier 				esyms[n++] = s;
725e887ea33SDavid du Colombier 	for(i = 0; i < ne-1; i++)
726e887ea33SDavid du Colombier 		for(j = i+1; j < ne; j++)
727e887ea33SDavid du Colombier 			if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
728e887ea33SDavid du Colombier 				s = esyms[i];
729e887ea33SDavid du Colombier 				esyms[i] = esyms[j];
730e887ea33SDavid du Colombier 				esyms[j] = s;
731e887ea33SDavid du Colombier 			}
732e887ea33SDavid du Colombier 
733e887ea33SDavid du Colombier 	nb = 0;
734e887ea33SDavid du Colombier 	off = 0;
735e887ea33SDavid du Colombier 	et = lookup(EXPTAB, 0);
736e887ea33SDavid du Colombier 	if(et->type != 0 && et->type != SXREF)
737e887ea33SDavid du Colombier 		diag("%s already defined", EXPTAB);
738e887ea33SDavid du Colombier 	et->type = SDATA;
739e887ea33SDavid du Colombier 	str = lookup(".string", 0);
740e887ea33SDavid du Colombier 	if(str->type == 0)
741e887ea33SDavid du Colombier 		str->type = SDATA;
742e887ea33SDavid du Colombier 	sv = str->value;
743e887ea33SDavid du Colombier 	for(i = 0; i < ne; i++){
744e887ea33SDavid du Colombier 		s = esyms[i];
745e887ea33SDavid du Colombier 		if(debug['S'])
746e887ea33SDavid du Colombier 			s->sig = 0;
747e887ea33SDavid du Colombier 		/* Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); */
748e887ea33SDavid du Colombier 
749e887ea33SDavid du Colombier 		/* signature */
750e887ea33SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
751e887ea33SDavid du Colombier 		off += sizeof(long);
752e887ea33SDavid du Colombier 		p->to.offset = s->sig;
753e887ea33SDavid du Colombier 
754e887ea33SDavid du Colombier 		/* address */
755e887ea33SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
756e887ea33SDavid du Colombier 		off += sizeof(long);
757e887ea33SDavid du Colombier 		p->to.type = D_ADDR;
758e887ea33SDavid du Colombier 		p->to.index = D_EXTERN;
759e887ea33SDavid du Colombier 		p->to.sym = s;
760e887ea33SDavid du Colombier 
761e887ea33SDavid du Colombier 		/* string */
762e887ea33SDavid du Colombier 		t = s->name;
763e887ea33SDavid du Colombier 		n = strlen(t)+1;
764e887ea33SDavid du Colombier 		for(;;){
765e887ea33SDavid du Colombier 			buf[nb++] = *t;
766e887ea33SDavid du Colombier 			sv++;
767e887ea33SDavid du Colombier 			if(nb >= NSNAME){
768e887ea33SDavid du Colombier 				p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
769e887ea33SDavid du Colombier 				p->to.type = D_SCONST;
770e887ea33SDavid du Colombier 				memmove(p->to.scon, buf, NSNAME);
771e887ea33SDavid du Colombier 				nb = 0;
772e887ea33SDavid du Colombier 			}
773e887ea33SDavid du Colombier 			if(*t++ == 0)
774e887ea33SDavid du Colombier 				break;
775e887ea33SDavid du Colombier 		}
776e887ea33SDavid du Colombier 
777e887ea33SDavid du Colombier 		/* name */
778e887ea33SDavid du Colombier 		p = newdata(et, off, sizeof(long), D_EXTERN);
779e887ea33SDavid du Colombier 		off += sizeof(long);
780e887ea33SDavid du Colombier 		p->to.type = D_ADDR;
781e887ea33SDavid du Colombier 		p->to.index = D_STATIC;
782e887ea33SDavid du Colombier 		p->to.sym = str;
783e887ea33SDavid du Colombier 		p->to.offset = sv-n;
784e887ea33SDavid du Colombier 	}
785e887ea33SDavid du Colombier 
786e887ea33SDavid du Colombier 	if(nb > 0){
787e887ea33SDavid du Colombier 		p = newdata(str, sv-nb, nb, D_STATIC);
788e887ea33SDavid du Colombier 		p->to.type = D_SCONST;
789e887ea33SDavid du Colombier 		memmove(p->to.scon, buf, nb);
790e887ea33SDavid du Colombier 	}
791e887ea33SDavid du Colombier 
792e887ea33SDavid du Colombier 	for(i = 0; i < 3; i++){
793e887ea33SDavid du Colombier 		newdata(et, off, sizeof(long), D_EXTERN);
794e887ea33SDavid du Colombier 		off += sizeof(long);
795e887ea33SDavid du Colombier 	}
796e887ea33SDavid du Colombier 	et->value = off;
797e887ea33SDavid du Colombier 	if(sv == 0)
798e887ea33SDavid du Colombier 		sv = 1;
799e887ea33SDavid du Colombier 	str->value = sv;
800e887ea33SDavid du Colombier 	exports = ne;
801e887ea33SDavid du Colombier 	free(esyms);
802e887ea33SDavid du Colombier }
803