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