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