xref: /inferno-os/utils/0l/pass.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth #include	"l.h"
2*74a4d8c2SCharles.Forsyth 
3*74a4d8c2SCharles.Forsyth void
dodata(void)4*74a4d8c2SCharles.Forsyth dodata(void)
5*74a4d8c2SCharles.Forsyth {
6*74a4d8c2SCharles.Forsyth 	int i, t;
7*74a4d8c2SCharles.Forsyth 	Sym *s;
8*74a4d8c2SCharles.Forsyth 	Prog *p, *p1;
9*74a4d8c2SCharles.Forsyth 	long orig, orig1, v;
10*74a4d8c2SCharles.Forsyth 
11*74a4d8c2SCharles.Forsyth 	if(debug['v'])
12*74a4d8c2SCharles.Forsyth 		Bprint(&bso, "%5.2f dodata\n", cputime());
13*74a4d8c2SCharles.Forsyth 	Bflush(&bso);
14*74a4d8c2SCharles.Forsyth 	for(p = datap; p != P; p = p->link) {
15*74a4d8c2SCharles.Forsyth 		s = p->from.sym;
16*74a4d8c2SCharles.Forsyth 		if(p->as == ADYNT || p->as == AINIT)
17*74a4d8c2SCharles.Forsyth 			s->value = dtype;
18*74a4d8c2SCharles.Forsyth 		if(s->type == SBSS)
19*74a4d8c2SCharles.Forsyth 			s->type = SDATA;
20*74a4d8c2SCharles.Forsyth 		if(s->type != SDATA)
21*74a4d8c2SCharles.Forsyth 			diag("initialize non-data (%d): %s\n%P\n",
22*74a4d8c2SCharles.Forsyth 				s->type, s->name, p);
23*74a4d8c2SCharles.Forsyth 		v = p->from.offset + p->reg;
24*74a4d8c2SCharles.Forsyth 		if(v > s->value)
25*74a4d8c2SCharles.Forsyth 			diag("initialize bounds (%ld): %s\n%P\n",
26*74a4d8c2SCharles.Forsyth 				s->value, s->name, p);
27*74a4d8c2SCharles.Forsyth 	}
28*74a4d8c2SCharles.Forsyth 
29*74a4d8c2SCharles.Forsyth 	/*
30*74a4d8c2SCharles.Forsyth 	 * pass 1
31*74a4d8c2SCharles.Forsyth 	 *	assign 'small' variables to data segment
32*74a4d8c2SCharles.Forsyth 	 *	(rational is that data segment is more easily
33*74a4d8c2SCharles.Forsyth 	 *	 addressed through offset on R30)
34*74a4d8c2SCharles.Forsyth 	 */
35*74a4d8c2SCharles.Forsyth 	orig = 0;
36*74a4d8c2SCharles.Forsyth 	for(i=0; i<NHASH; i++)
37*74a4d8c2SCharles.Forsyth 	for(s = hash[i]; s != S; s = s->link) {
38*74a4d8c2SCharles.Forsyth 		t = s->type;
39*74a4d8c2SCharles.Forsyth 		if(t != SDATA && t != SBSS)
40*74a4d8c2SCharles.Forsyth 			continue;
41*74a4d8c2SCharles.Forsyth 		v = s->value;
42*74a4d8c2SCharles.Forsyth 		if(v == 0) {
43*74a4d8c2SCharles.Forsyth 			diag("%s: no size\n", s->name);
44*74a4d8c2SCharles.Forsyth 			v = 1;
45*74a4d8c2SCharles.Forsyth 		}
46*74a4d8c2SCharles.Forsyth 		while(v & 7)
47*74a4d8c2SCharles.Forsyth 			v++;
48*74a4d8c2SCharles.Forsyth 		s->value = v;
49*74a4d8c2SCharles.Forsyth 		if(v > MINSIZ)
50*74a4d8c2SCharles.Forsyth 			continue;
51*74a4d8c2SCharles.Forsyth 		s->value = orig;
52*74a4d8c2SCharles.Forsyth 		orig += v;
53*74a4d8c2SCharles.Forsyth 		s->type = SDATA1;
54*74a4d8c2SCharles.Forsyth 	}
55*74a4d8c2SCharles.Forsyth 	orig1 = orig;
56*74a4d8c2SCharles.Forsyth 
57*74a4d8c2SCharles.Forsyth 	/*
58*74a4d8c2SCharles.Forsyth 	 * pass 2
59*74a4d8c2SCharles.Forsyth 	 *	assign 'data' variables to data segment
60*74a4d8c2SCharles.Forsyth 	 */
61*74a4d8c2SCharles.Forsyth 	for(i=0; i<NHASH; i++)
62*74a4d8c2SCharles.Forsyth 	for(s = hash[i]; s != S; s = s->link) {
63*74a4d8c2SCharles.Forsyth 		t = s->type;
64*74a4d8c2SCharles.Forsyth 		if(t != SDATA) {
65*74a4d8c2SCharles.Forsyth 			if(t == SDATA1)
66*74a4d8c2SCharles.Forsyth 				s->type = SDATA;
67*74a4d8c2SCharles.Forsyth 			continue;
68*74a4d8c2SCharles.Forsyth 		}
69*74a4d8c2SCharles.Forsyth 		v = s->value;
70*74a4d8c2SCharles.Forsyth 		while(v & 7)
71*74a4d8c2SCharles.Forsyth 			v++;
72*74a4d8c2SCharles.Forsyth 		s->value = orig;
73*74a4d8c2SCharles.Forsyth 		orig += v;
74*74a4d8c2SCharles.Forsyth 		s->type = SDATA1;
75*74a4d8c2SCharles.Forsyth 	}
76*74a4d8c2SCharles.Forsyth 
77*74a4d8c2SCharles.Forsyth 	while(orig & 7)
78*74a4d8c2SCharles.Forsyth 		orig++;
79*74a4d8c2SCharles.Forsyth 	datsize = orig;
80*74a4d8c2SCharles.Forsyth 
81*74a4d8c2SCharles.Forsyth 	/*
82*74a4d8c2SCharles.Forsyth 	 * pass 3
83*74a4d8c2SCharles.Forsyth 	 *	everything else to bss segment
84*74a4d8c2SCharles.Forsyth 	 */
85*74a4d8c2SCharles.Forsyth 	for(i=0; i<NHASH; i++)
86*74a4d8c2SCharles.Forsyth 	for(s = hash[i]; s != S; s = s->link) {
87*74a4d8c2SCharles.Forsyth 		if(s->type != SBSS)
88*74a4d8c2SCharles.Forsyth 			continue;
89*74a4d8c2SCharles.Forsyth 		v = s->value;
90*74a4d8c2SCharles.Forsyth 		while(v & 7)
91*74a4d8c2SCharles.Forsyth 			v++;
92*74a4d8c2SCharles.Forsyth 		s->value = orig;
93*74a4d8c2SCharles.Forsyth 		orig += v;
94*74a4d8c2SCharles.Forsyth 	}
95*74a4d8c2SCharles.Forsyth 	while(orig & 7)
96*74a4d8c2SCharles.Forsyth 		orig++;
97*74a4d8c2SCharles.Forsyth 	bsssize = orig-datsize;
98*74a4d8c2SCharles.Forsyth 
99*74a4d8c2SCharles.Forsyth 	/*
100*74a4d8c2SCharles.Forsyth 	 * pass 4
101*74a4d8c2SCharles.Forsyth 	 *	add literals to all large values.
102*74a4d8c2SCharles.Forsyth 	 *	at this time:
103*74a4d8c2SCharles.Forsyth 	 *		small data is allocated DATA
104*74a4d8c2SCharles.Forsyth 	 *		large data is allocated DATA1
105*74a4d8c2SCharles.Forsyth 	 *		large bss is allocated BSS
106*74a4d8c2SCharles.Forsyth 	 *	the new literals are loaded between
107*74a4d8c2SCharles.Forsyth 	 *	small data and large data.
108*74a4d8c2SCharles.Forsyth 	 */
109*74a4d8c2SCharles.Forsyth 	orig = 0;
110*74a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
111*74a4d8c2SCharles.Forsyth 		if(p->as != AMOVW)
112*74a4d8c2SCharles.Forsyth 			continue;
113*74a4d8c2SCharles.Forsyth 		if(p->from.type != D_CONST)
114*74a4d8c2SCharles.Forsyth 			continue;
115*74a4d8c2SCharles.Forsyth 		if(s = p->from.sym) {
116*74a4d8c2SCharles.Forsyth 			t = s->type;
117*74a4d8c2SCharles.Forsyth 			if(t != SDATA && t != SDATA1 && t != SBSS)
118*74a4d8c2SCharles.Forsyth 				continue;
119*74a4d8c2SCharles.Forsyth 			t = p->from.name;
120*74a4d8c2SCharles.Forsyth 			if(t != D_EXTERN && t != D_STATIC)
121*74a4d8c2SCharles.Forsyth 				continue;
122*74a4d8c2SCharles.Forsyth 			v = s->value + p->from.offset;
123*74a4d8c2SCharles.Forsyth 			if(v >= 0 && v <= 0xffff)
124*74a4d8c2SCharles.Forsyth 				continue;
125*74a4d8c2SCharles.Forsyth 			if(!strcmp(s->name, "setR30"))
126*74a4d8c2SCharles.Forsyth 				continue;
127*74a4d8c2SCharles.Forsyth 			/* size should be 19 max */
128*74a4d8c2SCharles.Forsyth 			if(strlen(s->name) >= 10)	/* has loader address */
129*74a4d8c2SCharles.Forsyth 				sprint(literal, "$%lux.%lux", (long)s, p->from.offset);
130*74a4d8c2SCharles.Forsyth 			else
131*74a4d8c2SCharles.Forsyth 				sprint(literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
132*74a4d8c2SCharles.Forsyth 		} else {
133*74a4d8c2SCharles.Forsyth 			if(p->from.name != D_NONE)
134*74a4d8c2SCharles.Forsyth 				continue;
135*74a4d8c2SCharles.Forsyth 			if(p->from.reg != NREG)
136*74a4d8c2SCharles.Forsyth 				continue;
137*74a4d8c2SCharles.Forsyth 			v = p->from.offset;
138*74a4d8c2SCharles.Forsyth 			if(v >= -0x7fff && v <= 0xffff)
139*74a4d8c2SCharles.Forsyth 				continue;
140*74a4d8c2SCharles.Forsyth 			if(!(v & 0xffff))
141*74a4d8c2SCharles.Forsyth 				continue;
142*74a4d8c2SCharles.Forsyth 			/* size should be 9 max */
143*74a4d8c2SCharles.Forsyth 			sprint(literal, "$%lux", v);
144*74a4d8c2SCharles.Forsyth 		}
145*74a4d8c2SCharles.Forsyth 		s = lookup(literal, 0);
146*74a4d8c2SCharles.Forsyth 		if(s->type == 0) {
147*74a4d8c2SCharles.Forsyth 			s->type = SDATA;
148*74a4d8c2SCharles.Forsyth 			s->value = orig1+orig;
149*74a4d8c2SCharles.Forsyth 			orig += 8;
150*74a4d8c2SCharles.Forsyth 			p1 = prg();
151*74a4d8c2SCharles.Forsyth 			p1->line = p->line;
152*74a4d8c2SCharles.Forsyth 			p1->as = ADATA;
153*74a4d8c2SCharles.Forsyth 			p1->from.type = D_OREG;
154*74a4d8c2SCharles.Forsyth 			p1->from.sym = s;
155*74a4d8c2SCharles.Forsyth 			p1->from.name = D_EXTERN;
156*74a4d8c2SCharles.Forsyth 			p1->reg = 4;
157*74a4d8c2SCharles.Forsyth 			p1->to = p->from;
158*74a4d8c2SCharles.Forsyth 			p1->link = datap;
159*74a4d8c2SCharles.Forsyth 			datap = p1;
160*74a4d8c2SCharles.Forsyth 		}
161*74a4d8c2SCharles.Forsyth 		if(s->type != SDATA)
162*74a4d8c2SCharles.Forsyth 			diag("literal not data: %s", s->name);
163*74a4d8c2SCharles.Forsyth 		p->from.type = D_OREG;
164*74a4d8c2SCharles.Forsyth 		p->from.sym = s;
165*74a4d8c2SCharles.Forsyth 		p->from.name = D_EXTERN;
166*74a4d8c2SCharles.Forsyth 		p->from.offset = 0;
167*74a4d8c2SCharles.Forsyth 		nocache(p);
168*74a4d8c2SCharles.Forsyth 		continue;
169*74a4d8c2SCharles.Forsyth 	}
170*74a4d8c2SCharles.Forsyth 	while(orig & 7)
171*74a4d8c2SCharles.Forsyth 		orig++;
172*74a4d8c2SCharles.Forsyth 	/*
173*74a4d8c2SCharles.Forsyth 	 * pass 5
174*74a4d8c2SCharles.Forsyth 	 *	re-adjust offsets
175*74a4d8c2SCharles.Forsyth 	 */
176*74a4d8c2SCharles.Forsyth 	for(i=0; i<NHASH; i++)
177*74a4d8c2SCharles.Forsyth 	for(s = hash[i]; s != S; s = s->link) {
178*74a4d8c2SCharles.Forsyth 		t = s->type;
179*74a4d8c2SCharles.Forsyth 		if(t == SBSS) {
180*74a4d8c2SCharles.Forsyth 			s->value += orig;
181*74a4d8c2SCharles.Forsyth 			continue;
182*74a4d8c2SCharles.Forsyth 		}
183*74a4d8c2SCharles.Forsyth 		if(t == SDATA1) {
184*74a4d8c2SCharles.Forsyth 			s->type = SDATA;
185*74a4d8c2SCharles.Forsyth 			s->value += orig;
186*74a4d8c2SCharles.Forsyth 			continue;
187*74a4d8c2SCharles.Forsyth 		}
188*74a4d8c2SCharles.Forsyth 	}
189*74a4d8c2SCharles.Forsyth 	datsize += orig;
190*74a4d8c2SCharles.Forsyth 	xdefine("setR30", SDATA, 0L+BIG);
191*74a4d8c2SCharles.Forsyth 	xdefine("bdata", SDATA, 0L);
192*74a4d8c2SCharles.Forsyth 	xdefine("edata", SDATA, datsize);
193*74a4d8c2SCharles.Forsyth 	xdefine("end", SBSS, datsize+bsssize);
194*74a4d8c2SCharles.Forsyth 	xdefine("etext", STEXT, 0L);
195*74a4d8c2SCharles.Forsyth }
196*74a4d8c2SCharles.Forsyth 
197*74a4d8c2SCharles.Forsyth void
undef(void)198*74a4d8c2SCharles.Forsyth undef(void)
199*74a4d8c2SCharles.Forsyth {
200*74a4d8c2SCharles.Forsyth 	int i;
201*74a4d8c2SCharles.Forsyth 	Sym *s;
202*74a4d8c2SCharles.Forsyth 
203*74a4d8c2SCharles.Forsyth 	for(i=0; i<NHASH; i++)
204*74a4d8c2SCharles.Forsyth 	for(s = hash[i]; s != S; s = s->link)
205*74a4d8c2SCharles.Forsyth 		if(s->type == SXREF)
206*74a4d8c2SCharles.Forsyth 			diag("%s: not defined\n", s->name);
207*74a4d8c2SCharles.Forsyth }
208*74a4d8c2SCharles.Forsyth 
209*74a4d8c2SCharles.Forsyth void
follow(void)210*74a4d8c2SCharles.Forsyth follow(void)
211*74a4d8c2SCharles.Forsyth {
212*74a4d8c2SCharles.Forsyth 	if(debug['v'])
213*74a4d8c2SCharles.Forsyth 		Bprint(&bso, "%5.2f follow\n", cputime());
214*74a4d8c2SCharles.Forsyth 	Bflush(&bso);
215*74a4d8c2SCharles.Forsyth 
216*74a4d8c2SCharles.Forsyth 	firstp = prg();
217*74a4d8c2SCharles.Forsyth 	lastp = firstp;
218*74a4d8c2SCharles.Forsyth 	xfol(textp);
219*74a4d8c2SCharles.Forsyth 
220*74a4d8c2SCharles.Forsyth 	firstp = firstp->link;
221*74a4d8c2SCharles.Forsyth 	lastp->link = P;
222*74a4d8c2SCharles.Forsyth }
223*74a4d8c2SCharles.Forsyth 
224*74a4d8c2SCharles.Forsyth void
xfol(Prog * p)225*74a4d8c2SCharles.Forsyth xfol(Prog *p)
226*74a4d8c2SCharles.Forsyth {
227*74a4d8c2SCharles.Forsyth 	Prog *q, *r;
228*74a4d8c2SCharles.Forsyth 	int a, i;
229*74a4d8c2SCharles.Forsyth 
230*74a4d8c2SCharles.Forsyth loop:
231*74a4d8c2SCharles.Forsyth 	if(p == P)
232*74a4d8c2SCharles.Forsyth 		return;
233*74a4d8c2SCharles.Forsyth 	a = p->as;
234*74a4d8c2SCharles.Forsyth 	if(a == ATEXT)
235*74a4d8c2SCharles.Forsyth 		curtext = p;
236*74a4d8c2SCharles.Forsyth 	if(a == AJMP) {
237*74a4d8c2SCharles.Forsyth 		q = p->cond;
238*74a4d8c2SCharles.Forsyth 		if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
239*74a4d8c2SCharles.Forsyth 			p->mark |= FOLL;
240*74a4d8c2SCharles.Forsyth 			lastp->link = p;
241*74a4d8c2SCharles.Forsyth 			lastp = p;
242*74a4d8c2SCharles.Forsyth 			p = p->link;
243*74a4d8c2SCharles.Forsyth 			xfol(p);
244*74a4d8c2SCharles.Forsyth 			p = q;
245*74a4d8c2SCharles.Forsyth 			if(p && !(p->mark & FOLL))
246*74a4d8c2SCharles.Forsyth 				goto loop;
247*74a4d8c2SCharles.Forsyth 			return;
248*74a4d8c2SCharles.Forsyth 		}
249*74a4d8c2SCharles.Forsyth 		if(q != P) {
250*74a4d8c2SCharles.Forsyth 			p->mark |= FOLL;
251*74a4d8c2SCharles.Forsyth 			p = q;
252*74a4d8c2SCharles.Forsyth 			if(!(p->mark & FOLL))
253*74a4d8c2SCharles.Forsyth 				goto loop;
254*74a4d8c2SCharles.Forsyth 		}
255*74a4d8c2SCharles.Forsyth 	}
256*74a4d8c2SCharles.Forsyth 	if(p->mark & FOLL) {
257*74a4d8c2SCharles.Forsyth 		for(i=0,q=p; i<4; i++,q=q->link) {
258*74a4d8c2SCharles.Forsyth 			if(q == lastp || (q->mark&NOSCHED))
259*74a4d8c2SCharles.Forsyth 				break;
260*74a4d8c2SCharles.Forsyth 			a = q->as;
261*74a4d8c2SCharles.Forsyth 			if(a == ANOP) {
262*74a4d8c2SCharles.Forsyth 				i--;
263*74a4d8c2SCharles.Forsyth 				continue;
264*74a4d8c2SCharles.Forsyth 			}
265*74a4d8c2SCharles.Forsyth 			if(a == AJMP || a == ARET || a == ARFE)
266*74a4d8c2SCharles.Forsyth 				goto copy;
267*74a4d8c2SCharles.Forsyth 			if(!q->cond || (q->cond->mark&FOLL))
268*74a4d8c2SCharles.Forsyth 				continue;
269*74a4d8c2SCharles.Forsyth 			if(a != ABEQ && a != ABNE)
270*74a4d8c2SCharles.Forsyth 				continue;
271*74a4d8c2SCharles.Forsyth 		copy:
272*74a4d8c2SCharles.Forsyth 			for(;;) {
273*74a4d8c2SCharles.Forsyth 				r = prg();
274*74a4d8c2SCharles.Forsyth 				*r = *p;
275*74a4d8c2SCharles.Forsyth 				if(!(r->mark&FOLL))
276*74a4d8c2SCharles.Forsyth 					print("cant happen 1\n");
277*74a4d8c2SCharles.Forsyth 				r->mark |= FOLL;
278*74a4d8c2SCharles.Forsyth 				if(p != q) {
279*74a4d8c2SCharles.Forsyth 					p = p->link;
280*74a4d8c2SCharles.Forsyth 					lastp->link = r;
281*74a4d8c2SCharles.Forsyth 					lastp = r;
282*74a4d8c2SCharles.Forsyth 					continue;
283*74a4d8c2SCharles.Forsyth 				}
284*74a4d8c2SCharles.Forsyth 				lastp->link = r;
285*74a4d8c2SCharles.Forsyth 				lastp = r;
286*74a4d8c2SCharles.Forsyth 				if(a == AJMP || a == ARET || a == ARFE)
287*74a4d8c2SCharles.Forsyth 					return;
288*74a4d8c2SCharles.Forsyth 				r->as = ABNE;
289*74a4d8c2SCharles.Forsyth 				if(a == ABNE)
290*74a4d8c2SCharles.Forsyth 					r->as = ABEQ;
291*74a4d8c2SCharles.Forsyth 				r->cond = p->link;
292*74a4d8c2SCharles.Forsyth 				r->link = p->cond;
293*74a4d8c2SCharles.Forsyth 				if(!(r->link->mark&FOLL))
294*74a4d8c2SCharles.Forsyth 					xfol(r->link);
295*74a4d8c2SCharles.Forsyth 				if(!(r->cond->mark&FOLL))
296*74a4d8c2SCharles.Forsyth 					print("cant happen 2\n");
297*74a4d8c2SCharles.Forsyth 				return;
298*74a4d8c2SCharles.Forsyth 			}
299*74a4d8c2SCharles.Forsyth 		}
300*74a4d8c2SCharles.Forsyth 		a = AJMP;
301*74a4d8c2SCharles.Forsyth 		q = prg();
302*74a4d8c2SCharles.Forsyth 		q->as = a;
303*74a4d8c2SCharles.Forsyth 		q->line = p->line;
304*74a4d8c2SCharles.Forsyth 		q->to.type = D_BRANCH;
305*74a4d8c2SCharles.Forsyth 		q->to.offset = p->pc;
306*74a4d8c2SCharles.Forsyth 		q->cond = p;
307*74a4d8c2SCharles.Forsyth 		p = q;
308*74a4d8c2SCharles.Forsyth 	}
309*74a4d8c2SCharles.Forsyth 	p->mark |= FOLL;
310*74a4d8c2SCharles.Forsyth 	lastp->link = p;
311*74a4d8c2SCharles.Forsyth 	lastp = p;
312*74a4d8c2SCharles.Forsyth 	if(a == AJMP || a == ARET || a == ARFE){
313*74a4d8c2SCharles.Forsyth 		if(p->mark & NOSCHED){
314*74a4d8c2SCharles.Forsyth 			p = p->link;
315*74a4d8c2SCharles.Forsyth 			goto loop;
316*74a4d8c2SCharles.Forsyth 		}
317*74a4d8c2SCharles.Forsyth 		return;
318*74a4d8c2SCharles.Forsyth 	}
319*74a4d8c2SCharles.Forsyth 	if(p->cond != P)
320*74a4d8c2SCharles.Forsyth 	if(a != AJAL && p->link != P) {
321*74a4d8c2SCharles.Forsyth 		xfol(p->link);
322*74a4d8c2SCharles.Forsyth 		p = p->cond;
323*74a4d8c2SCharles.Forsyth 		if(p == P || (p->mark&FOLL))
324*74a4d8c2SCharles.Forsyth 			return;
325*74a4d8c2SCharles.Forsyth 		goto loop;
326*74a4d8c2SCharles.Forsyth 	}
327*74a4d8c2SCharles.Forsyth 	p = p->link;
328*74a4d8c2SCharles.Forsyth 	goto loop;
329*74a4d8c2SCharles.Forsyth }
330*74a4d8c2SCharles.Forsyth 
331*74a4d8c2SCharles.Forsyth void
patch(void)332*74a4d8c2SCharles.Forsyth patch(void)
333*74a4d8c2SCharles.Forsyth {
334*74a4d8c2SCharles.Forsyth 	long c, vexit;
335*74a4d8c2SCharles.Forsyth 	Prog *p, *q;
336*74a4d8c2SCharles.Forsyth 	Sym *s;
337*74a4d8c2SCharles.Forsyth 	int a;
338*74a4d8c2SCharles.Forsyth 
339*74a4d8c2SCharles.Forsyth 	if(debug['v'])
340*74a4d8c2SCharles.Forsyth 		Bprint(&bso, "%5.2f patch\n", cputime());
341*74a4d8c2SCharles.Forsyth 	Bflush(&bso);
342*74a4d8c2SCharles.Forsyth 	mkfwd();
343*74a4d8c2SCharles.Forsyth 	s = lookup("exit", 0);
344*74a4d8c2SCharles.Forsyth 	vexit = s->value;
345*74a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
346*74a4d8c2SCharles.Forsyth 		a = p->as;
347*74a4d8c2SCharles.Forsyth 		if(a == ATEXT)
348*74a4d8c2SCharles.Forsyth 			curtext = p;
349*74a4d8c2SCharles.Forsyth 		if((a == AJAL || a == AJMP || a == ARET) &&
350*74a4d8c2SCharles.Forsyth 		   p->to.type != D_BRANCH && p->to.sym != S) {
351*74a4d8c2SCharles.Forsyth 			s = p->to.sym;
352*74a4d8c2SCharles.Forsyth 			if(s->type != STEXT) {
353*74a4d8c2SCharles.Forsyth 				diag("undefined: %s\n%P\n", s->name, p);
354*74a4d8c2SCharles.Forsyth 				s->type = STEXT;
355*74a4d8c2SCharles.Forsyth 				s->value = vexit;
356*74a4d8c2SCharles.Forsyth 			}
357*74a4d8c2SCharles.Forsyth 			p->to.offset = s->value;
358*74a4d8c2SCharles.Forsyth 			p->to.type = D_BRANCH;
359*74a4d8c2SCharles.Forsyth 		}
360*74a4d8c2SCharles.Forsyth 		if(p->to.type != D_BRANCH)
361*74a4d8c2SCharles.Forsyth 			continue;
362*74a4d8c2SCharles.Forsyth 		c = p->to.offset;
363*74a4d8c2SCharles.Forsyth 		for(q = firstp; q != P;) {
364*74a4d8c2SCharles.Forsyth 			if(q->forwd != P)
365*74a4d8c2SCharles.Forsyth 			if(c >= q->forwd->pc) {
366*74a4d8c2SCharles.Forsyth 				q = q->forwd;
367*74a4d8c2SCharles.Forsyth 				continue;
368*74a4d8c2SCharles.Forsyth 			}
369*74a4d8c2SCharles.Forsyth 			if(c == q->pc)
370*74a4d8c2SCharles.Forsyth 				break;
371*74a4d8c2SCharles.Forsyth 			q = q->link;
372*74a4d8c2SCharles.Forsyth 		}
373*74a4d8c2SCharles.Forsyth 		if(q == P) {
374*74a4d8c2SCharles.Forsyth 			diag("branch out of range %ld\n%P\n", c, p);
375*74a4d8c2SCharles.Forsyth 			p->to.type = D_NONE;
376*74a4d8c2SCharles.Forsyth 		}
377*74a4d8c2SCharles.Forsyth 		p->cond = q;
378*74a4d8c2SCharles.Forsyth 	}
379*74a4d8c2SCharles.Forsyth 
380*74a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
381*74a4d8c2SCharles.Forsyth 		if(p->as == ATEXT)
382*74a4d8c2SCharles.Forsyth 			curtext = p;
383*74a4d8c2SCharles.Forsyth 		if(p->cond != P) {
384*74a4d8c2SCharles.Forsyth 			p->cond = brloop(p->cond);
385*74a4d8c2SCharles.Forsyth 			if(p->cond != P)
386*74a4d8c2SCharles.Forsyth 			if(p->to.type == D_BRANCH)
387*74a4d8c2SCharles.Forsyth 				p->to.offset = p->cond->pc;
388*74a4d8c2SCharles.Forsyth 		}
389*74a4d8c2SCharles.Forsyth 	}
390*74a4d8c2SCharles.Forsyth }
391*74a4d8c2SCharles.Forsyth 
392*74a4d8c2SCharles.Forsyth #define	LOG	5
393*74a4d8c2SCharles.Forsyth void
mkfwd(void)394*74a4d8c2SCharles.Forsyth mkfwd(void)
395*74a4d8c2SCharles.Forsyth {
396*74a4d8c2SCharles.Forsyth 	Prog *p;
397*74a4d8c2SCharles.Forsyth 	long dwn[LOG], cnt[LOG], i;
398*74a4d8c2SCharles.Forsyth 	Prog *lst[LOG];
399*74a4d8c2SCharles.Forsyth 
400*74a4d8c2SCharles.Forsyth 	for(i=0; i<LOG; i++) {
401*74a4d8c2SCharles.Forsyth 		if(i == 0)
402*74a4d8c2SCharles.Forsyth 			cnt[i] = 1; else
403*74a4d8c2SCharles.Forsyth 			cnt[i] = LOG * cnt[i-1];
404*74a4d8c2SCharles.Forsyth 		dwn[i] = 1;
405*74a4d8c2SCharles.Forsyth 		lst[i] = P;
406*74a4d8c2SCharles.Forsyth 	}
407*74a4d8c2SCharles.Forsyth 	i = 0;
408*74a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
409*74a4d8c2SCharles.Forsyth 		if(p->as == ATEXT)
410*74a4d8c2SCharles.Forsyth 			curtext = p;
411*74a4d8c2SCharles.Forsyth 		i--;
412*74a4d8c2SCharles.Forsyth 		if(i < 0)
413*74a4d8c2SCharles.Forsyth 			i = LOG-1;
414*74a4d8c2SCharles.Forsyth 		p->forwd = P;
415*74a4d8c2SCharles.Forsyth 		dwn[i]--;
416*74a4d8c2SCharles.Forsyth 		if(dwn[i] <= 0) {
417*74a4d8c2SCharles.Forsyth 			dwn[i] = cnt[i];
418*74a4d8c2SCharles.Forsyth 			if(lst[i] != P)
419*74a4d8c2SCharles.Forsyth 				lst[i]->forwd = p;
420*74a4d8c2SCharles.Forsyth 			lst[i] = p;
421*74a4d8c2SCharles.Forsyth 		}
422*74a4d8c2SCharles.Forsyth 	}
423*74a4d8c2SCharles.Forsyth }
424*74a4d8c2SCharles.Forsyth 
425*74a4d8c2SCharles.Forsyth Prog*
brloop(Prog * p)426*74a4d8c2SCharles.Forsyth brloop(Prog *p)
427*74a4d8c2SCharles.Forsyth {
428*74a4d8c2SCharles.Forsyth 	Prog *q;
429*74a4d8c2SCharles.Forsyth 	int c;
430*74a4d8c2SCharles.Forsyth 
431*74a4d8c2SCharles.Forsyth 	for(c=0; p!=P;) {
432*74a4d8c2SCharles.Forsyth 		if(p->as != AJMP || (p->mark&NOSCHED))
433*74a4d8c2SCharles.Forsyth 			return p;
434*74a4d8c2SCharles.Forsyth 		q = p->cond;
435*74a4d8c2SCharles.Forsyth 		if(q <= p) {
436*74a4d8c2SCharles.Forsyth 			c++;
437*74a4d8c2SCharles.Forsyth 			if(q == p || c > 5000)
438*74a4d8c2SCharles.Forsyth 				break;
439*74a4d8c2SCharles.Forsyth 		}
440*74a4d8c2SCharles.Forsyth 		p = q;
441*74a4d8c2SCharles.Forsyth 	}
442*74a4d8c2SCharles.Forsyth 	return P;
443*74a4d8c2SCharles.Forsyth }
444*74a4d8c2SCharles.Forsyth 
445*74a4d8c2SCharles.Forsyth long
atolwhex(char * s)446*74a4d8c2SCharles.Forsyth atolwhex(char *s)
447*74a4d8c2SCharles.Forsyth {
448*74a4d8c2SCharles.Forsyth 	long n;
449*74a4d8c2SCharles.Forsyth 	int f;
450*74a4d8c2SCharles.Forsyth 
451*74a4d8c2SCharles.Forsyth 	n = 0;
452*74a4d8c2SCharles.Forsyth 	f = 0;
453*74a4d8c2SCharles.Forsyth 	while(*s == ' ' || *s == '\t')
454*74a4d8c2SCharles.Forsyth 		s++;
455*74a4d8c2SCharles.Forsyth 	if(*s == '-' || *s == '+') {
456*74a4d8c2SCharles.Forsyth 		if(*s++ == '-')
457*74a4d8c2SCharles.Forsyth 			f = 1;
458*74a4d8c2SCharles.Forsyth 		while(*s == ' ' || *s == '\t')
459*74a4d8c2SCharles.Forsyth 			s++;
460*74a4d8c2SCharles.Forsyth 	}
461*74a4d8c2SCharles.Forsyth 	if(s[0]=='0' && s[1]){
462*74a4d8c2SCharles.Forsyth 		if(s[1]=='x' || s[1]=='X'){
463*74a4d8c2SCharles.Forsyth 			s += 2;
464*74a4d8c2SCharles.Forsyth 			for(;;){
465*74a4d8c2SCharles.Forsyth 				if(*s >= '0' && *s <= '9')
466*74a4d8c2SCharles.Forsyth 					n = n*16 + *s++ - '0';
467*74a4d8c2SCharles.Forsyth 				else if(*s >= 'a' && *s <= 'f')
468*74a4d8c2SCharles.Forsyth 					n = n*16 + *s++ - 'a' + 10;
469*74a4d8c2SCharles.Forsyth 				else if(*s >= 'A' && *s <= 'F')
470*74a4d8c2SCharles.Forsyth 					n = n*16 + *s++ - 'A' + 10;
471*74a4d8c2SCharles.Forsyth 				else
472*74a4d8c2SCharles.Forsyth 					break;
473*74a4d8c2SCharles.Forsyth 			}
474*74a4d8c2SCharles.Forsyth 		} else
475*74a4d8c2SCharles.Forsyth 			while(*s >= '0' && *s <= '7')
476*74a4d8c2SCharles.Forsyth 				n = n*8 + *s++ - '0';
477*74a4d8c2SCharles.Forsyth 	} else
478*74a4d8c2SCharles.Forsyth 		while(*s >= '0' && *s <= '9')
479*74a4d8c2SCharles.Forsyth 			n = n*10 + *s++ - '0';
480*74a4d8c2SCharles.Forsyth 	if(f)
481*74a4d8c2SCharles.Forsyth 		n = -n;
482*74a4d8c2SCharles.Forsyth 	return n;
483*74a4d8c2SCharles.Forsyth }
484*74a4d8c2SCharles.Forsyth 
485*74a4d8c2SCharles.Forsyth long
rnd(long v,long r)486*74a4d8c2SCharles.Forsyth rnd(long v, long r)
487*74a4d8c2SCharles.Forsyth {
488*74a4d8c2SCharles.Forsyth 	long c;
489*74a4d8c2SCharles.Forsyth 
490*74a4d8c2SCharles.Forsyth 	if(r <= 0)
491*74a4d8c2SCharles.Forsyth 		return v;
492*74a4d8c2SCharles.Forsyth 	v += r - 1;
493*74a4d8c2SCharles.Forsyth 	c = v % r;
494*74a4d8c2SCharles.Forsyth 	if(c < 0)
495*74a4d8c2SCharles.Forsyth 		c += r;
496*74a4d8c2SCharles.Forsyth 	v -= c;
497*74a4d8c2SCharles.Forsyth 	return v;
498*74a4d8c2SCharles.Forsyth }
499