xref: /plan9-contrib/sys/src/cmd/6c/reg.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
1e887ea33SDavid du Colombier #include "gc.h"
2e887ea33SDavid du Colombier 
3e887ea33SDavid du Colombier Reg*
rega(void)4e887ea33SDavid du Colombier rega(void)
5e887ea33SDavid du Colombier {
6e887ea33SDavid du Colombier 	Reg *r;
7e887ea33SDavid du Colombier 
8e887ea33SDavid du Colombier 	r = freer;
9e887ea33SDavid du Colombier 	if(r == R) {
10e887ea33SDavid du Colombier 		r = alloc(sizeof(*r));
11e887ea33SDavid du Colombier 	} else
12e887ea33SDavid du Colombier 		freer = r->link;
13e887ea33SDavid du Colombier 
14e887ea33SDavid du Colombier 	*r = zreg;
15e887ea33SDavid du Colombier 	return r;
16e887ea33SDavid du Colombier }
17e887ea33SDavid du Colombier 
18e887ea33SDavid du Colombier int
rcmp(const void * a1,const void * a2)19e887ea33SDavid du Colombier rcmp(const void *a1, const void *a2)
20e887ea33SDavid du Colombier {
21e887ea33SDavid du Colombier 	Rgn *p1, *p2;
22e887ea33SDavid du Colombier 	int c1, c2;
23e887ea33SDavid du Colombier 
24e887ea33SDavid du Colombier 	p1 = (Rgn*)a1;
25e887ea33SDavid du Colombier 	p2 = (Rgn*)a2;
26e887ea33SDavid du Colombier 	c1 = p2->cost;
27e887ea33SDavid du Colombier 	c2 = p1->cost;
28e887ea33SDavid du Colombier 	if(c1 -= c2)
29e887ea33SDavid du Colombier 		return c1;
30e887ea33SDavid du Colombier 	return p2->varno - p1->varno;
31e887ea33SDavid du Colombier }
32e887ea33SDavid du Colombier 
33e887ea33SDavid du Colombier void
regopt(Prog * p)34e887ea33SDavid du Colombier regopt(Prog *p)
35e887ea33SDavid du Colombier {
36e887ea33SDavid du Colombier 	Reg *r, *r1, *r2;
37e887ea33SDavid du Colombier 	Prog *p1;
38e887ea33SDavid du Colombier 	int i, z;
39e887ea33SDavid du Colombier 	long initpc, val, npc;
40e887ea33SDavid du Colombier 	ulong vreg;
41e887ea33SDavid du Colombier 	Bits bit;
42e887ea33SDavid du Colombier 	struct
43e887ea33SDavid du Colombier 	{
44e887ea33SDavid du Colombier 		long	m;
45e887ea33SDavid du Colombier 		long	c;
46e887ea33SDavid du Colombier 		Reg*	p;
47e887ea33SDavid du Colombier 	} log5[6], *lp;
48e887ea33SDavid du Colombier 
49e887ea33SDavid du Colombier 	firstr = R;
50e887ea33SDavid du Colombier 	lastr = R;
51e887ea33SDavid du Colombier 	nvar = 0;
52e887ea33SDavid du Colombier 	regbits = RtoB(D_SP) | RtoB(D_AX) | RtoB(D_X0);
53b94bb474SDavid du Colombier 	if(REGEXT)
54b94bb474SDavid du Colombier 		regbits |= RtoB(REGEXT) | RtoB(REGEXT-1);
55e887ea33SDavid du Colombier 	for(z=0; z<BITS; z++) {
56e887ea33SDavid du Colombier 		externs.b[z] = 0;
57e887ea33SDavid du Colombier 		params.b[z] = 0;
58e887ea33SDavid du Colombier 		consts.b[z] = 0;
59e887ea33SDavid du Colombier 		addrs.b[z] = 0;
60e887ea33SDavid du Colombier 	}
61e887ea33SDavid du Colombier 
62e887ea33SDavid du Colombier 	/*
63e887ea33SDavid du Colombier 	 * pass 1
64e887ea33SDavid du Colombier 	 * build aux data structure
65e887ea33SDavid du Colombier 	 * allocate pcs
66e887ea33SDavid du Colombier 	 * find use and set of variables
67e887ea33SDavid du Colombier 	 */
68e887ea33SDavid du Colombier 	val = 5L * 5L * 5L * 5L * 5L;
69e887ea33SDavid du Colombier 	lp = log5;
70e887ea33SDavid du Colombier 	for(i=0; i<5; i++) {
71e887ea33SDavid du Colombier 		lp->m = val;
72e887ea33SDavid du Colombier 		lp->c = 0;
73e887ea33SDavid du Colombier 		lp->p = R;
74e887ea33SDavid du Colombier 		val /= 5L;
75e887ea33SDavid du Colombier 		lp++;
76e887ea33SDavid du Colombier 	}
77e887ea33SDavid du Colombier 	val = 0;
78e887ea33SDavid du Colombier 	for(; p != P; p = p->link) {
79e887ea33SDavid du Colombier 		switch(p->as) {
80e887ea33SDavid du Colombier 		case ADATA:
81e887ea33SDavid du Colombier 		case AGLOBL:
82e887ea33SDavid du Colombier 		case ANAME:
83e887ea33SDavid du Colombier 		case ASIGNAME:
84e887ea33SDavid du Colombier 			continue;
85e887ea33SDavid du Colombier 		}
86e887ea33SDavid du Colombier 		r = rega();
87e887ea33SDavid du Colombier 		if(firstr == R) {
88e887ea33SDavid du Colombier 			firstr = r;
89e887ea33SDavid du Colombier 			lastr = r;
90e887ea33SDavid du Colombier 		} else {
91e887ea33SDavid du Colombier 			lastr->link = r;
92e887ea33SDavid du Colombier 			r->p1 = lastr;
93e887ea33SDavid du Colombier 			lastr->s1 = r;
94e887ea33SDavid du Colombier 			lastr = r;
95e887ea33SDavid du Colombier 		}
96e887ea33SDavid du Colombier 		r->prog = p;
97e887ea33SDavid du Colombier 		r->pc = val;
98e887ea33SDavid du Colombier 		val++;
99e887ea33SDavid du Colombier 
100e887ea33SDavid du Colombier 		lp = log5;
101e887ea33SDavid du Colombier 		for(i=0; i<5; i++) {
102e887ea33SDavid du Colombier 			lp->c--;
103e887ea33SDavid du Colombier 			if(lp->c <= 0) {
104e887ea33SDavid du Colombier 				lp->c = lp->m;
105e887ea33SDavid du Colombier 				if(lp->p != R)
106e887ea33SDavid du Colombier 					lp->p->log5 = r;
107e887ea33SDavid du Colombier 				lp->p = r;
108e887ea33SDavid du Colombier 				(lp+1)->c = 0;
109e887ea33SDavid du Colombier 				break;
110e887ea33SDavid du Colombier 			}
111e887ea33SDavid du Colombier 			lp++;
112e887ea33SDavid du Colombier 		}
113e887ea33SDavid du Colombier 
114e887ea33SDavid du Colombier 		r1 = r->p1;
115e887ea33SDavid du Colombier 		if(r1 != R)
116e887ea33SDavid du Colombier 		switch(r1->prog->as) {
117e887ea33SDavid du Colombier 		case ARET:
118e887ea33SDavid du Colombier 		case AJMP:
119e887ea33SDavid du Colombier 		case AIRETL:
120e887ea33SDavid du Colombier 		case AIRETQ:
121e887ea33SDavid du Colombier 			r->p1 = R;
122e887ea33SDavid du Colombier 			r1->s1 = R;
123e887ea33SDavid du Colombier 		}
124e887ea33SDavid du Colombier 
125e887ea33SDavid du Colombier 		bit = mkvar(r, &p->from);
126e887ea33SDavid du Colombier 		if(bany(&bit))
127e887ea33SDavid du Colombier 		switch(p->as) {
128e887ea33SDavid du Colombier 		/*
129e887ea33SDavid du Colombier 		 * funny
130e887ea33SDavid du Colombier 		 */
131e887ea33SDavid du Colombier 		case ALEAL:
132e887ea33SDavid du Colombier 		case ALEAQ:
133e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++)
134e887ea33SDavid du Colombier 				addrs.b[z] |= bit.b[z];
135e887ea33SDavid du Colombier 			break;
136e887ea33SDavid du Colombier 
137e887ea33SDavid du Colombier 		/*
138e887ea33SDavid du Colombier 		 * left side read
139e887ea33SDavid du Colombier 		 */
140e887ea33SDavid du Colombier 		default:
141e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++)
142e887ea33SDavid du Colombier 				r->use1.b[z] |= bit.b[z];
143e887ea33SDavid du Colombier 			break;
144e887ea33SDavid du Colombier 		}
145e887ea33SDavid du Colombier 
146e887ea33SDavid du Colombier 		bit = mkvar(r, &p->to);
147e887ea33SDavid du Colombier 		if(bany(&bit))
148e887ea33SDavid du Colombier 		switch(p->as) {
149e887ea33SDavid du Colombier 		default:
150e887ea33SDavid du Colombier 			diag(Z, "reg: unknown op: %A", p->as);
151e887ea33SDavid du Colombier 			break;
152e887ea33SDavid du Colombier 
153e887ea33SDavid du Colombier 		/*
154e887ea33SDavid du Colombier 		 * right side read
155e887ea33SDavid du Colombier 		 */
156e887ea33SDavid du Colombier 		case ACMPB:
157e887ea33SDavid du Colombier 		case ACMPL:
158e887ea33SDavid du Colombier 		case ACMPQ:
159e887ea33SDavid du Colombier 		case ACMPW:
160e887ea33SDavid du Colombier 		case ACOMISS:
161e887ea33SDavid du Colombier 		case ACOMISD:
162e887ea33SDavid du Colombier 		case AUCOMISS:
163e887ea33SDavid du Colombier 		case AUCOMISD:
164e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++)
165e887ea33SDavid du Colombier 				r->use2.b[z] |= bit.b[z];
166e887ea33SDavid du Colombier 			break;
167e887ea33SDavid du Colombier 
168e887ea33SDavid du Colombier 		/*
169e887ea33SDavid du Colombier 		 * right side write
170e887ea33SDavid du Colombier 		 */
171e887ea33SDavid du Colombier 		case ANOP:
172e887ea33SDavid du Colombier 		case AMOVL:
173e887ea33SDavid du Colombier 		case AMOVQ:
174e887ea33SDavid du Colombier 		case AMOVB:
175e887ea33SDavid du Colombier 		case AMOVW:
176e887ea33SDavid du Colombier 		case AMOVBLSX:
177e887ea33SDavid du Colombier 		case AMOVBLZX:
178e887ea33SDavid du Colombier 		case AMOVBQSX:
179e887ea33SDavid du Colombier 		case AMOVBQZX:
180e887ea33SDavid du Colombier 		case AMOVLQSX:
181e887ea33SDavid du Colombier 		case AMOVLQZX:
182e887ea33SDavid du Colombier 		case AMOVWLSX:
183e887ea33SDavid du Colombier 		case AMOVWLZX:
184e887ea33SDavid du Colombier 		case AMOVWQSX:
185e887ea33SDavid du Colombier 		case AMOVWQZX:
186*40d01547SDavid du Colombier 		case AMOVQL:
187e887ea33SDavid du Colombier 
188e887ea33SDavid du Colombier 		case AMOVSS:
189e887ea33SDavid du Colombier 		case AMOVSD:
190e887ea33SDavid du Colombier 		case ACVTSD2SL:
191e887ea33SDavid du Colombier 		case ACVTSD2SQ:
192e887ea33SDavid du Colombier 		case ACVTSD2SS:
193e887ea33SDavid du Colombier 		case ACVTSL2SD:
194e887ea33SDavid du Colombier 		case ACVTSL2SS:
195e887ea33SDavid du Colombier 		case ACVTSQ2SD:
196e887ea33SDavid du Colombier 		case ACVTSQ2SS:
197e887ea33SDavid du Colombier 		case ACVTSS2SD:
198e887ea33SDavid du Colombier 		case ACVTSS2SL:
199e887ea33SDavid du Colombier 		case ACVTSS2SQ:
200e887ea33SDavid du Colombier 		case ACVTTSD2SL:
201e887ea33SDavid du Colombier 		case ACVTTSD2SQ:
202e887ea33SDavid du Colombier 		case ACVTTSS2SL:
203e887ea33SDavid du Colombier 		case ACVTTSS2SQ:
204e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++)
205e887ea33SDavid du Colombier 				r->set.b[z] |= bit.b[z];
206e887ea33SDavid du Colombier 			break;
207e887ea33SDavid du Colombier 
208e887ea33SDavid du Colombier 		/*
209e887ea33SDavid du Colombier 		 * right side read+write
210e887ea33SDavid du Colombier 		 */
211e887ea33SDavid du Colombier 		case AADDB:
212e887ea33SDavid du Colombier 		case AADDL:
213e887ea33SDavid du Colombier 		case AADDQ:
214e887ea33SDavid du Colombier 		case AADDW:
215e887ea33SDavid du Colombier 		case AANDB:
216e887ea33SDavid du Colombier 		case AANDL:
217e887ea33SDavid du Colombier 		case AANDQ:
218e887ea33SDavid du Colombier 		case AANDW:
219e887ea33SDavid du Colombier 		case ASUBB:
220e887ea33SDavid du Colombier 		case ASUBL:
221e887ea33SDavid du Colombier 		case ASUBQ:
222e887ea33SDavid du Colombier 		case ASUBW:
223e887ea33SDavid du Colombier 		case AORB:
224e887ea33SDavid du Colombier 		case AORL:
225e887ea33SDavid du Colombier 		case AORQ:
226e887ea33SDavid du Colombier 		case AORW:
227e887ea33SDavid du Colombier 		case AXORB:
228e887ea33SDavid du Colombier 		case AXORL:
229e887ea33SDavid du Colombier 		case AXORQ:
230e887ea33SDavid du Colombier 		case AXORW:
231e887ea33SDavid du Colombier 		case ASALB:
232e887ea33SDavid du Colombier 		case ASALL:
233e887ea33SDavid du Colombier 		case ASALQ:
234e887ea33SDavid du Colombier 		case ASALW:
235e887ea33SDavid du Colombier 		case ASARB:
236e887ea33SDavid du Colombier 		case ASARL:
237e887ea33SDavid du Colombier 		case ASARQ:
238e887ea33SDavid du Colombier 		case ASARW:
239e887ea33SDavid du Colombier 		case AROLB:
240e887ea33SDavid du Colombier 		case AROLL:
241e887ea33SDavid du Colombier 		case AROLQ:
242e887ea33SDavid du Colombier 		case AROLW:
243e887ea33SDavid du Colombier 		case ARORB:
244e887ea33SDavid du Colombier 		case ARORL:
245e887ea33SDavid du Colombier 		case ARORQ:
246e887ea33SDavid du Colombier 		case ARORW:
247e887ea33SDavid du Colombier 		case ASHLB:
248e887ea33SDavid du Colombier 		case ASHLL:
249e887ea33SDavid du Colombier 		case ASHLQ:
250e887ea33SDavid du Colombier 		case ASHLW:
251e887ea33SDavid du Colombier 		case ASHRB:
252e887ea33SDavid du Colombier 		case ASHRL:
253e887ea33SDavid du Colombier 		case ASHRQ:
254e887ea33SDavid du Colombier 		case ASHRW:
255e887ea33SDavid du Colombier 		case AIMULL:
256e887ea33SDavid du Colombier 		case AIMULQ:
257e887ea33SDavid du Colombier 		case AIMULW:
258e887ea33SDavid du Colombier 		case ANEGL:
259e887ea33SDavid du Colombier 		case ANEGQ:
260e887ea33SDavid du Colombier 		case ANOTL:
261e887ea33SDavid du Colombier 		case ANOTQ:
262e887ea33SDavid du Colombier 		case AADCL:
263e887ea33SDavid du Colombier 		case AADCQ:
264e887ea33SDavid du Colombier 		case ASBBL:
265e887ea33SDavid du Colombier 		case ASBBQ:
266e887ea33SDavid du Colombier 
267e887ea33SDavid du Colombier 		case AADDSD:
268e887ea33SDavid du Colombier 		case AADDSS:
269e887ea33SDavid du Colombier 		case ACMPSD:
270e887ea33SDavid du Colombier 		case ACMPSS:
271e887ea33SDavid du Colombier 		case ADIVSD:
272e887ea33SDavid du Colombier 		case ADIVSS:
273e887ea33SDavid du Colombier 		case AMAXSD:
274e887ea33SDavid du Colombier 		case AMAXSS:
275e887ea33SDavid du Colombier 		case AMINSD:
276e887ea33SDavid du Colombier 		case AMINSS:
277e887ea33SDavid du Colombier 		case AMULSD:
278e887ea33SDavid du Colombier 		case AMULSS:
279e887ea33SDavid du Colombier 		case ARCPSS:
280e887ea33SDavid du Colombier 		case ARSQRTSS:
281e887ea33SDavid du Colombier 		case ASQRTSD:
282e887ea33SDavid du Colombier 		case ASQRTSS:
283e887ea33SDavid du Colombier 		case ASUBSD:
284e887ea33SDavid du Colombier 		case ASUBSS:
285e887ea33SDavid du Colombier 		case AXORPD:
286e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++) {
287e887ea33SDavid du Colombier 				r->set.b[z] |= bit.b[z];
288e887ea33SDavid du Colombier 				r->use2.b[z] |= bit.b[z];
289e887ea33SDavid du Colombier 			}
290e887ea33SDavid du Colombier 			break;
291e887ea33SDavid du Colombier 
292e887ea33SDavid du Colombier 		/*
293e887ea33SDavid du Colombier 		 * funny
294e887ea33SDavid du Colombier 		 */
295e887ea33SDavid du Colombier 		case ACALL:
296e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++)
297e887ea33SDavid du Colombier 				addrs.b[z] |= bit.b[z];
298e887ea33SDavid du Colombier 			break;
299e887ea33SDavid du Colombier 		}
300e887ea33SDavid du Colombier 
301e887ea33SDavid du Colombier 		switch(p->as) {
302e887ea33SDavid du Colombier 		case AIMULL:
303e887ea33SDavid du Colombier 		case AIMULQ:
304e887ea33SDavid du Colombier 		case AIMULW:
305e887ea33SDavid du Colombier 			if(p->to.type != D_NONE)
306e887ea33SDavid du Colombier 				break;
307e887ea33SDavid du Colombier 
308e887ea33SDavid du Colombier 		case AIDIVB:
309e887ea33SDavid du Colombier 		case AIDIVL:
310e887ea33SDavid du Colombier 		case AIDIVQ:
311e887ea33SDavid du Colombier 		case AIDIVW:
312e887ea33SDavid du Colombier 		case AIMULB:
313e887ea33SDavid du Colombier 		case ADIVB:
314e887ea33SDavid du Colombier 		case ADIVL:
315e887ea33SDavid du Colombier 		case ADIVQ:
316e887ea33SDavid du Colombier 		case ADIVW:
317e887ea33SDavid du Colombier 		case AMULB:
318e887ea33SDavid du Colombier 		case AMULL:
319e887ea33SDavid du Colombier 		case AMULQ:
320e887ea33SDavid du Colombier 		case AMULW:
321e887ea33SDavid du Colombier 
322e887ea33SDavid du Colombier 		case ACWD:
323e887ea33SDavid du Colombier 		case ACDQ:
324e887ea33SDavid du Colombier 		case ACQO:
325e887ea33SDavid du Colombier 			r->regu |= RtoB(D_AX) | RtoB(D_DX);
326e887ea33SDavid du Colombier 			break;
327e887ea33SDavid du Colombier 
328e887ea33SDavid du Colombier 		case AREP:
329e887ea33SDavid du Colombier 		case AREPN:
330e887ea33SDavid du Colombier 		case ALOOP:
331e887ea33SDavid du Colombier 		case ALOOPEQ:
332e887ea33SDavid du Colombier 		case ALOOPNE:
333e887ea33SDavid du Colombier 			r->regu |= RtoB(D_CX);
334e887ea33SDavid du Colombier 			break;
335e887ea33SDavid du Colombier 
336e887ea33SDavid du Colombier 		case AMOVSB:
337e887ea33SDavid du Colombier 		case AMOVSL:
338e887ea33SDavid du Colombier 		case AMOVSQ:
339e887ea33SDavid du Colombier 		case AMOVSW:
340e887ea33SDavid du Colombier 		case ACMPSB:
341e887ea33SDavid du Colombier 		case ACMPSL:
342e887ea33SDavid du Colombier 		case ACMPSQ:
343e887ea33SDavid du Colombier 		case ACMPSW:
344e887ea33SDavid du Colombier 			r->regu |= RtoB(D_SI) | RtoB(D_DI);
345e887ea33SDavid du Colombier 			break;
346e887ea33SDavid du Colombier 
347e887ea33SDavid du Colombier 		case ASTOSB:
348e887ea33SDavid du Colombier 		case ASTOSL:
349e887ea33SDavid du Colombier 		case ASTOSQ:
350e887ea33SDavid du Colombier 		case ASTOSW:
351e887ea33SDavid du Colombier 		case ASCASB:
352e887ea33SDavid du Colombier 		case ASCASL:
353e887ea33SDavid du Colombier 		case ASCASQ:
354e887ea33SDavid du Colombier 		case ASCASW:
355e887ea33SDavid du Colombier 			r->regu |= RtoB(D_AX) | RtoB(D_DI);
356e887ea33SDavid du Colombier 			break;
357e887ea33SDavid du Colombier 
358e887ea33SDavid du Colombier 		case AINSB:
359e887ea33SDavid du Colombier 		case AINSL:
360e887ea33SDavid du Colombier 		case AINSW:
361e887ea33SDavid du Colombier 		case AOUTSB:
362e887ea33SDavid du Colombier 		case AOUTSL:
363e887ea33SDavid du Colombier 		case AOUTSW:
364e887ea33SDavid du Colombier 			r->regu |= RtoB(D_DI) | RtoB(D_DX);
365e887ea33SDavid du Colombier 			break;
366e887ea33SDavid du Colombier 		}
367e887ea33SDavid du Colombier 	}
368e887ea33SDavid du Colombier 	if(firstr == R)
369e887ea33SDavid du Colombier 		return;
370e887ea33SDavid du Colombier 	initpc = pc - val;
371e887ea33SDavid du Colombier 	npc = val;
372e887ea33SDavid du Colombier 
373e887ea33SDavid du Colombier 	/*
374e887ea33SDavid du Colombier 	 * pass 2
375e887ea33SDavid du Colombier 	 * turn branch references to pointers
376e887ea33SDavid du Colombier 	 * build back pointers
377e887ea33SDavid du Colombier 	 */
378e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r->link) {
379e887ea33SDavid du Colombier 		p = r->prog;
380e887ea33SDavid du Colombier 		if(p->to.type == D_BRANCH) {
381e887ea33SDavid du Colombier 			val = p->to.offset - initpc;
382e887ea33SDavid du Colombier 			r1 = firstr;
383e887ea33SDavid du Colombier 			while(r1 != R) {
384e887ea33SDavid du Colombier 				r2 = r1->log5;
385e887ea33SDavid du Colombier 				if(r2 != R && val >= r2->pc) {
386e887ea33SDavid du Colombier 					r1 = r2;
387e887ea33SDavid du Colombier 					continue;
388e887ea33SDavid du Colombier 				}
389e887ea33SDavid du Colombier 				if(r1->pc == val)
390e887ea33SDavid du Colombier 					break;
391e887ea33SDavid du Colombier 				r1 = r1->link;
392e887ea33SDavid du Colombier 			}
393e887ea33SDavid du Colombier 			if(r1 == R) {
394e887ea33SDavid du Colombier 				nearln = p->lineno;
395e887ea33SDavid du Colombier 				diag(Z, "ref not found\n%P", p);
396e887ea33SDavid du Colombier 				continue;
397e887ea33SDavid du Colombier 			}
398e887ea33SDavid du Colombier 			if(r1 == r) {
399e887ea33SDavid du Colombier 				nearln = p->lineno;
400e887ea33SDavid du Colombier 				diag(Z, "ref to self\n%P", p);
401e887ea33SDavid du Colombier 				continue;
402e887ea33SDavid du Colombier 			}
403e887ea33SDavid du Colombier 			r->s2 = r1;
404e887ea33SDavid du Colombier 			r->p2link = r1->p2;
405e887ea33SDavid du Colombier 			r1->p2 = r;
406e887ea33SDavid du Colombier 		}
407e887ea33SDavid du Colombier 	}
408e887ea33SDavid du Colombier 	if(debug['R']) {
409e887ea33SDavid du Colombier 		p = firstr->prog;
410e887ea33SDavid du Colombier 		print("\n%L %D\n", p->lineno, &p->from);
411e887ea33SDavid du Colombier 	}
412e887ea33SDavid du Colombier 
413e887ea33SDavid du Colombier 	/*
414e887ea33SDavid du Colombier 	 * pass 2.5
415e887ea33SDavid du Colombier 	 * find looping structure
416e887ea33SDavid du Colombier 	 */
417e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
418e887ea33SDavid du Colombier 		r->active = 0;
419e887ea33SDavid du Colombier 	change = 0;
420e887ea33SDavid du Colombier 	loopit(firstr, npc);
421e887ea33SDavid du Colombier 	if(debug['R'] && debug['v']) {
422e887ea33SDavid du Colombier 		print("\nlooping structure:\n");
423e887ea33SDavid du Colombier 		for(r = firstr; r != R; r = r->link) {
424e887ea33SDavid du Colombier 			print("%ld:%P", r->loop, r->prog);
425e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++)
426e887ea33SDavid du Colombier 				bit.b[z] = r->use1.b[z] |
427e887ea33SDavid du Colombier 					   r->use2.b[z] |
428e887ea33SDavid du Colombier 					   r->set.b[z];
429e887ea33SDavid du Colombier 			if(bany(&bit)) {
430e887ea33SDavid du Colombier 				print("\t");
431e887ea33SDavid du Colombier 				if(bany(&r->use1))
432e887ea33SDavid du Colombier 					print(" u1=%B", r->use1);
433e887ea33SDavid du Colombier 				if(bany(&r->use2))
434e887ea33SDavid du Colombier 					print(" u2=%B", r->use2);
435e887ea33SDavid du Colombier 				if(bany(&r->set))
436e887ea33SDavid du Colombier 					print(" st=%B", r->set);
437e887ea33SDavid du Colombier 			}
438e887ea33SDavid du Colombier 			print("\n");
439e887ea33SDavid du Colombier 		}
440e887ea33SDavid du Colombier 	}
441e887ea33SDavid du Colombier 
442e887ea33SDavid du Colombier 	/*
443e887ea33SDavid du Colombier 	 * pass 3
444e887ea33SDavid du Colombier 	 * iterate propagating usage
445e887ea33SDavid du Colombier 	 * 	back until flow graph is complete
446e887ea33SDavid du Colombier 	 */
447e887ea33SDavid du Colombier loop1:
448e887ea33SDavid du Colombier 	change = 0;
449e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
450e887ea33SDavid du Colombier 		r->active = 0;
451e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
452e887ea33SDavid du Colombier 		if(r->prog->as == ARET)
453e887ea33SDavid du Colombier 			prop(r, zbits, zbits);
454e887ea33SDavid du Colombier loop11:
455e887ea33SDavid du Colombier 	/* pick up unreachable code */
456e887ea33SDavid du Colombier 	i = 0;
457e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r1) {
458e887ea33SDavid du Colombier 		r1 = r->link;
459e887ea33SDavid du Colombier 		if(r1 && r1->active && !r->active) {
460e887ea33SDavid du Colombier 			prop(r, zbits, zbits);
461e887ea33SDavid du Colombier 			i = 1;
462e887ea33SDavid du Colombier 		}
463e887ea33SDavid du Colombier 	}
464e887ea33SDavid du Colombier 	if(i)
465e887ea33SDavid du Colombier 		goto loop11;
466e887ea33SDavid du Colombier 	if(change)
467e887ea33SDavid du Colombier 		goto loop1;
468e887ea33SDavid du Colombier 
469e887ea33SDavid du Colombier 
470e887ea33SDavid du Colombier 	/*
471e887ea33SDavid du Colombier 	 * pass 4
472e887ea33SDavid du Colombier 	 * iterate propagating register/variable synchrony
473e887ea33SDavid du Colombier 	 * 	forward until graph is complete
474e887ea33SDavid du Colombier 	 */
475e887ea33SDavid du Colombier loop2:
476e887ea33SDavid du Colombier 	change = 0;
477e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
478e887ea33SDavid du Colombier 		r->active = 0;
479e887ea33SDavid du Colombier 	synch(firstr, zbits);
480e887ea33SDavid du Colombier 	if(change)
481e887ea33SDavid du Colombier 		goto loop2;
482e887ea33SDavid du Colombier 
483e887ea33SDavid du Colombier 
484e887ea33SDavid du Colombier 	/*
485e887ea33SDavid du Colombier 	 * pass 5
486e887ea33SDavid du Colombier 	 * isolate regions
487e887ea33SDavid du Colombier 	 * calculate costs (paint1)
488e887ea33SDavid du Colombier 	 */
489e887ea33SDavid du Colombier 	r = firstr;
490e887ea33SDavid du Colombier 	if(r) {
491e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++)
492e887ea33SDavid du Colombier 			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
493e887ea33SDavid du Colombier 			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
494e887ea33SDavid du Colombier 		if(bany(&bit)) {
495e887ea33SDavid du Colombier 			nearln = r->prog->lineno;
496e887ea33SDavid du Colombier 			warn(Z, "used and not set: %B", bit);
497e887ea33SDavid du Colombier 			if(debug['R'] && !debug['w'])
498e887ea33SDavid du Colombier 				print("used and not set: %B\n", bit);
499e887ea33SDavid du Colombier 		}
500e887ea33SDavid du Colombier 	}
501e887ea33SDavid du Colombier 	if(debug['R'] && debug['v'])
502e887ea33SDavid du Colombier 		print("\nprop structure:\n");
503e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
504e887ea33SDavid du Colombier 		r->act = zbits;
505e887ea33SDavid du Colombier 	rgp = region;
506e887ea33SDavid du Colombier 	nregion = 0;
507e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r->link) {
508e887ea33SDavid du Colombier 		if(debug['R'] && debug['v']) {
509e887ea33SDavid du Colombier 			print("%P\t", r->prog);
510e887ea33SDavid du Colombier 			if(bany(&r->set))
511e887ea33SDavid du Colombier 				print("s:%B ", r->set);
512e887ea33SDavid du Colombier 			if(bany(&r->refahead))
513e887ea33SDavid du Colombier 				print("ra:%B ", r->refahead);
514e887ea33SDavid du Colombier 			if(bany(&r->calahead))
515e887ea33SDavid du Colombier 				print("ca:%B ", r->calahead);
516e887ea33SDavid du Colombier 			print("\n");
517e887ea33SDavid du Colombier 		}
518e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++)
519e887ea33SDavid du Colombier 			bit.b[z] = r->set.b[z] &
520e887ea33SDavid du Colombier 			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
521e887ea33SDavid du Colombier 		if(bany(&bit)) {
522e887ea33SDavid du Colombier 			nearln = r->prog->lineno;
523e887ea33SDavid du Colombier 			warn(Z, "set and not used: %B", bit);
524e887ea33SDavid du Colombier 			if(debug['R'])
525e887ea33SDavid du Colombier 				print("set and not used: %B\n", bit);
526e887ea33SDavid du Colombier 			excise(r);
527e887ea33SDavid du Colombier 		}
528e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++)
529e887ea33SDavid du Colombier 			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
530e887ea33SDavid du Colombier 		while(bany(&bit)) {
531e887ea33SDavid du Colombier 			i = bnum(bit);
532e887ea33SDavid du Colombier 			rgp->enter = r;
533e887ea33SDavid du Colombier 			rgp->varno = i;
534e887ea33SDavid du Colombier 			change = 0;
535e887ea33SDavid du Colombier 			if(debug['R'] && debug['v'])
536e887ea33SDavid du Colombier 				print("\n");
537e887ea33SDavid du Colombier 			paint1(r, i);
538e887ea33SDavid du Colombier 			bit.b[i/32] &= ~(1L<<(i%32));
539e887ea33SDavid du Colombier 			if(change <= 0) {
540e887ea33SDavid du Colombier 				if(debug['R'])
541e887ea33SDavid du Colombier 					print("%L$%d: %B\n",
542e887ea33SDavid du Colombier 						r->prog->lineno, change, blsh(i));
543e887ea33SDavid du Colombier 				continue;
544e887ea33SDavid du Colombier 			}
545e887ea33SDavid du Colombier 			rgp->cost = change;
546e887ea33SDavid du Colombier 			nregion++;
547e887ea33SDavid du Colombier 			if(nregion >= NRGN) {
548e887ea33SDavid du Colombier 				warn(Z, "too many regions");
549e887ea33SDavid du Colombier 				goto brk;
550e887ea33SDavid du Colombier 			}
551e887ea33SDavid du Colombier 			rgp++;
552e887ea33SDavid du Colombier 		}
553e887ea33SDavid du Colombier 	}
554e887ea33SDavid du Colombier brk:
555e887ea33SDavid du Colombier 	qsort(region, nregion, sizeof(region[0]), rcmp);
556e887ea33SDavid du Colombier 
557e887ea33SDavid du Colombier 	/*
558e887ea33SDavid du Colombier 	 * pass 6
559e887ea33SDavid du Colombier 	 * determine used registers (paint2)
560e887ea33SDavid du Colombier 	 * replace code (paint3)
561e887ea33SDavid du Colombier 	 */
562e887ea33SDavid du Colombier 	rgp = region;
563e887ea33SDavid du Colombier 	for(i=0; i<nregion; i++) {
564e887ea33SDavid du Colombier 		bit = blsh(rgp->varno);
565e887ea33SDavid du Colombier 		vreg = paint2(rgp->enter, rgp->varno);
566e887ea33SDavid du Colombier 		vreg = allreg(vreg, rgp);
567e887ea33SDavid du Colombier 		if(debug['R']) {
568e887ea33SDavid du Colombier 			print("%L$%d %R: %B\n",
569e887ea33SDavid du Colombier 				rgp->enter->prog->lineno,
570e887ea33SDavid du Colombier 				rgp->cost,
571e887ea33SDavid du Colombier 				rgp->regno,
572e887ea33SDavid du Colombier 				bit);
573e887ea33SDavid du Colombier 		}
574e887ea33SDavid du Colombier 		if(rgp->regno != 0)
575e887ea33SDavid du Colombier 			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
576e887ea33SDavid du Colombier 		rgp++;
577e887ea33SDavid du Colombier 	}
578e887ea33SDavid du Colombier 	/*
579e887ea33SDavid du Colombier 	 * pass 7
580e887ea33SDavid du Colombier 	 * peep-hole on basic block
581e887ea33SDavid du Colombier 	 */
582e887ea33SDavid du Colombier 	if(!debug['R'] || debug['P'])
583e887ea33SDavid du Colombier 		peep();
584e887ea33SDavid du Colombier 
585e887ea33SDavid du Colombier 	/*
586e887ea33SDavid du Colombier 	 * pass 8
587e887ea33SDavid du Colombier 	 * recalculate pc
588e887ea33SDavid du Colombier 	 */
589e887ea33SDavid du Colombier 	val = initpc;
590e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r1) {
591e887ea33SDavid du Colombier 		r->pc = val;
592e887ea33SDavid du Colombier 		p = r->prog;
593e887ea33SDavid du Colombier 		p1 = P;
594e887ea33SDavid du Colombier 		r1 = r->link;
595e887ea33SDavid du Colombier 		if(r1 != R)
596e887ea33SDavid du Colombier 			p1 = r1->prog;
597e887ea33SDavid du Colombier 		for(; p != p1; p = p->link) {
598e887ea33SDavid du Colombier 			switch(p->as) {
599e887ea33SDavid du Colombier 			default:
600e887ea33SDavid du Colombier 				val++;
601e887ea33SDavid du Colombier 				break;
602e887ea33SDavid du Colombier 
603e887ea33SDavid du Colombier 			case ANOP:
604e887ea33SDavid du Colombier 			case ADATA:
605e887ea33SDavid du Colombier 			case AGLOBL:
606e887ea33SDavid du Colombier 			case ANAME:
607e887ea33SDavid du Colombier 			case ASIGNAME:
608e887ea33SDavid du Colombier 				break;
609e887ea33SDavid du Colombier 			}
610e887ea33SDavid du Colombier 		}
611e887ea33SDavid du Colombier 	}
612e887ea33SDavid du Colombier 	pc = val;
613e887ea33SDavid du Colombier 
614e887ea33SDavid du Colombier 	/*
615e887ea33SDavid du Colombier 	 * fix up branches
616e887ea33SDavid du Colombier 	 */
617e887ea33SDavid du Colombier 	if(debug['R'])
618e887ea33SDavid du Colombier 		if(bany(&addrs))
619e887ea33SDavid du Colombier 			print("addrs: %B\n", addrs);
620e887ea33SDavid du Colombier 
621e887ea33SDavid du Colombier 	r1 = 0; /* set */
622e887ea33SDavid du Colombier 	for(r = firstr; r != R; r = r->link) {
623e887ea33SDavid du Colombier 		p = r->prog;
624e887ea33SDavid du Colombier 		if(p->to.type == D_BRANCH)
625e887ea33SDavid du Colombier 			p->to.offset = r->s2->pc;
626e887ea33SDavid du Colombier 		r1 = r;
627e887ea33SDavid du Colombier 	}
628e887ea33SDavid du Colombier 
629e887ea33SDavid du Colombier 	/*
630e887ea33SDavid du Colombier 	 * last pass
631e887ea33SDavid du Colombier 	 * eliminate nops
632e887ea33SDavid du Colombier 	 * free aux structures
633e887ea33SDavid du Colombier 	 */
634e887ea33SDavid du Colombier 	for(p = firstr->prog; p != P; p = p->link){
635e887ea33SDavid du Colombier 		while(p->link && p->link->as == ANOP)
636e887ea33SDavid du Colombier 			p->link = p->link->link;
637e887ea33SDavid du Colombier 	}
638e887ea33SDavid du Colombier 	if(r1 != R) {
639e887ea33SDavid du Colombier 		r1->link = freer;
640e887ea33SDavid du Colombier 		freer = firstr;
641e887ea33SDavid du Colombier 	}
642e887ea33SDavid du Colombier }
643e887ea33SDavid du Colombier 
644e887ea33SDavid du Colombier /*
645e887ea33SDavid du Colombier  * add mov b,rn
646e887ea33SDavid du Colombier  * just after r
647e887ea33SDavid du Colombier  */
648e887ea33SDavid du Colombier void
addmove(Reg * r,int bn,int rn,int f)649e887ea33SDavid du Colombier addmove(Reg *r, int bn, int rn, int f)
650e887ea33SDavid du Colombier {
651e887ea33SDavid du Colombier 	Prog *p, *p1;
652e887ea33SDavid du Colombier 	Adr *a;
653e887ea33SDavid du Colombier 	Var *v;
654e887ea33SDavid du Colombier 
655e887ea33SDavid du Colombier 	p1 = alloc(sizeof(*p1));
656e887ea33SDavid du Colombier 	*p1 = zprog;
657e887ea33SDavid du Colombier 	p = r->prog;
658e887ea33SDavid du Colombier 
659e887ea33SDavid du Colombier 	p1->link = p->link;
660e887ea33SDavid du Colombier 	p->link = p1;
661e887ea33SDavid du Colombier 	p1->lineno = p->lineno;
662e887ea33SDavid du Colombier 
663e887ea33SDavid du Colombier 	v = var + bn;
664e887ea33SDavid du Colombier 
665e887ea33SDavid du Colombier 	a = &p1->to;
666e887ea33SDavid du Colombier 	a->sym = v->sym;
667e887ea33SDavid du Colombier 	a->offset = v->offset;
668e887ea33SDavid du Colombier 	a->etype = v->etype;
669e887ea33SDavid du Colombier 	a->type = v->name;
670e887ea33SDavid du Colombier 
671e887ea33SDavid du Colombier 	p1->as = AMOVL;
672e887ea33SDavid du Colombier 	if(v->etype == TCHAR || v->etype == TUCHAR)
673e887ea33SDavid du Colombier 		p1->as = AMOVB;
674e887ea33SDavid du Colombier 	if(v->etype == TSHORT || v->etype == TUSHORT)
675e887ea33SDavid du Colombier 		p1->as = AMOVW;
676e887ea33SDavid du Colombier 	if(v->etype == TVLONG || v->etype == TUVLONG || v->etype == TIND)
677e887ea33SDavid du Colombier 		p1->as = AMOVQ;
678e887ea33SDavid du Colombier 	if(v->etype == TFLOAT)
679e887ea33SDavid du Colombier 		p1->as = AMOVSS;
680e887ea33SDavid du Colombier 	if(v->etype == TDOUBLE)
681e887ea33SDavid du Colombier 		p1->as = AMOVSD;
682e887ea33SDavid du Colombier 
683e887ea33SDavid du Colombier 	p1->from.type = rn;
684e887ea33SDavid du Colombier 	if(!f) {
685e887ea33SDavid du Colombier 		p1->from = *a;
686e887ea33SDavid du Colombier 		*a = zprog.from;
687e887ea33SDavid du Colombier 		a->type = rn;
688e887ea33SDavid du Colombier 		if(v->etype == TUCHAR)
689e887ea33SDavid du Colombier 			p1->as = AMOVB;
690e887ea33SDavid du Colombier 		if(v->etype == TUSHORT)
691e887ea33SDavid du Colombier 			p1->as = AMOVW;
692e887ea33SDavid du Colombier 	}
693e887ea33SDavid du Colombier 	if(debug['R'])
694e887ea33SDavid du Colombier 		print("%P\t.a%P\n", p, p1);
695e887ea33SDavid du Colombier }
696e887ea33SDavid du Colombier 
697e887ea33SDavid du Colombier ulong
doregbits(int r)698e887ea33SDavid du Colombier doregbits(int r)
699e887ea33SDavid du Colombier {
700e887ea33SDavid du Colombier 	ulong b;
701e887ea33SDavid du Colombier 
702e887ea33SDavid du Colombier 	b = 0;
703e887ea33SDavid du Colombier 	if(r >= D_INDIR)
704e887ea33SDavid du Colombier 		r -= D_INDIR;
705e887ea33SDavid du Colombier 	if(r >= D_AX && r <= D_R15)
706e887ea33SDavid du Colombier 		b |= RtoB(r);
707e887ea33SDavid du Colombier 	else
708e887ea33SDavid du Colombier 	if(r >= D_AL && r <= D_R15B)
709e887ea33SDavid du Colombier 		b |= RtoB(r-D_AL+D_AX);
710e887ea33SDavid du Colombier 	else
711e887ea33SDavid du Colombier 	if(r >= D_AH && r <= D_BH)
712e887ea33SDavid du Colombier 		b |= RtoB(r-D_AH+D_AX);
713e887ea33SDavid du Colombier 	else
714e887ea33SDavid du Colombier 	if(r >= D_X0 && r <= D_X0+15)
715e887ea33SDavid du Colombier 		b |= FtoB(r);
716e887ea33SDavid du Colombier 	return b;
717e887ea33SDavid du Colombier }
718e887ea33SDavid du Colombier 
719e887ea33SDavid du Colombier Bits
mkvar(Reg * r,Adr * a)720e887ea33SDavid du Colombier mkvar(Reg *r, Adr *a)
721e887ea33SDavid du Colombier {
722e887ea33SDavid du Colombier 	Var *v;
723e887ea33SDavid du Colombier 	int i, t, n, et, z;
724e887ea33SDavid du Colombier 	long o;
725e887ea33SDavid du Colombier 	Bits bit;
726e887ea33SDavid du Colombier 	Sym *s;
727e887ea33SDavid du Colombier 
728e887ea33SDavid du Colombier 	/*
729e887ea33SDavid du Colombier 	 * mark registers used
730e887ea33SDavid du Colombier 	 */
731e887ea33SDavid du Colombier 	t = a->type;
732e887ea33SDavid du Colombier 	r->regu |= doregbits(t);
733e887ea33SDavid du Colombier 	r->regu |= doregbits(a->index);
734e887ea33SDavid du Colombier 
735*40d01547SDavid du Colombier 	s = a->sym;
736e887ea33SDavid du Colombier 	switch(t) {
737e887ea33SDavid du Colombier 	default:
738e887ea33SDavid du Colombier 		goto none;
739e887ea33SDavid du Colombier 	case D_ADDR:
740e887ea33SDavid du Colombier 		a->type = a->index;
741e887ea33SDavid du Colombier 		bit = mkvar(r, a);
742e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++)
743e887ea33SDavid du Colombier 			addrs.b[z] |= bit.b[z];
744e887ea33SDavid du Colombier 		a->type = t;
745e887ea33SDavid du Colombier 		goto none;
746e887ea33SDavid du Colombier 	case D_EXTERN:
747e887ea33SDavid du Colombier 	case D_STATIC:
748*40d01547SDavid du Colombier 		if(s->type != nil && s->type->garb & GVOLATILE)
749*40d01547SDavid du Colombier 			goto none;
750e887ea33SDavid du Colombier 	case D_PARAM:
751e887ea33SDavid du Colombier 	case D_AUTO:
752e887ea33SDavid du Colombier 		n = t;
753e887ea33SDavid du Colombier 		break;
754e887ea33SDavid du Colombier 	}
755e887ea33SDavid du Colombier 	if(s == S)
756e887ea33SDavid du Colombier 		goto none;
757e887ea33SDavid du Colombier 	if(s->name[0] == '.')
758e887ea33SDavid du Colombier 		goto none;
759e887ea33SDavid du Colombier 	et = a->etype;
760e887ea33SDavid du Colombier 	o = a->offset;
761e887ea33SDavid du Colombier 	v = var;
762e887ea33SDavid du Colombier 	for(i=0; i<nvar; i++) {
763e887ea33SDavid du Colombier 		if(s == v->sym)
764e887ea33SDavid du Colombier 		if(n == v->name)
765e887ea33SDavid du Colombier 		if(o == v->offset)
766e887ea33SDavid du Colombier 			goto out;
767e887ea33SDavid du Colombier 		v++;
768e887ea33SDavid du Colombier 	}
769e887ea33SDavid du Colombier 	if(nvar >= NVAR) {
770e887ea33SDavid du Colombier 		if(debug['w'] > 1 && s)
771e887ea33SDavid du Colombier 			warn(Z, "variable not optimized: %s", s->name);
772e887ea33SDavid du Colombier 		goto none;
773e887ea33SDavid du Colombier 	}
774e887ea33SDavid du Colombier 	i = nvar;
775e887ea33SDavid du Colombier 	nvar++;
776e887ea33SDavid du Colombier 	v = &var[i];
777e887ea33SDavid du Colombier 	v->sym = s;
778e887ea33SDavid du Colombier 	v->offset = o;
779e887ea33SDavid du Colombier 	v->name = n;
780e887ea33SDavid du Colombier 	v->etype = et;
781e887ea33SDavid du Colombier 	if(debug['R'])
782e887ea33SDavid du Colombier 		print("bit=%2d et=%2d %D\n", i, et, a);
783e887ea33SDavid du Colombier 
784e887ea33SDavid du Colombier out:
785e887ea33SDavid du Colombier 	bit = blsh(i);
786e887ea33SDavid du Colombier 	if(n == D_EXTERN || n == D_STATIC)
787e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++)
788e887ea33SDavid du Colombier 			externs.b[z] |= bit.b[z];
789e887ea33SDavid du Colombier 	if(n == D_PARAM)
790e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++)
791e887ea33SDavid du Colombier 			params.b[z] |= bit.b[z];
792e887ea33SDavid du Colombier 	if(v->etype != et || !(typechlpfd[et] || typev[et]))	/* funny punning */
793e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++)
794e887ea33SDavid du Colombier 			addrs.b[z] |= bit.b[z];
795e887ea33SDavid du Colombier 	return bit;
796e887ea33SDavid du Colombier 
797e887ea33SDavid du Colombier none:
798e887ea33SDavid du Colombier 	return zbits;
799e887ea33SDavid du Colombier }
800e887ea33SDavid du Colombier 
801e887ea33SDavid du Colombier void
prop(Reg * r,Bits ref,Bits cal)802e887ea33SDavid du Colombier prop(Reg *r, Bits ref, Bits cal)
803e887ea33SDavid du Colombier {
804e887ea33SDavid du Colombier 	Reg *r1, *r2;
805e887ea33SDavid du Colombier 	int z;
806e887ea33SDavid du Colombier 
807e887ea33SDavid du Colombier 	for(r1 = r; r1 != R; r1 = r1->p1) {
808e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++) {
809e887ea33SDavid du Colombier 			ref.b[z] |= r1->refahead.b[z];
810e887ea33SDavid du Colombier 			if(ref.b[z] != r1->refahead.b[z]) {
811e887ea33SDavid du Colombier 				r1->refahead.b[z] = ref.b[z];
812e887ea33SDavid du Colombier 				change++;
813e887ea33SDavid du Colombier 			}
814e887ea33SDavid du Colombier 			cal.b[z] |= r1->calahead.b[z];
815e887ea33SDavid du Colombier 			if(cal.b[z] != r1->calahead.b[z]) {
816e887ea33SDavid du Colombier 				r1->calahead.b[z] = cal.b[z];
817e887ea33SDavid du Colombier 				change++;
818e887ea33SDavid du Colombier 			}
819e887ea33SDavid du Colombier 		}
820e887ea33SDavid du Colombier 		switch(r1->prog->as) {
821e887ea33SDavid du Colombier 		case ACALL:
822e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++) {
823e887ea33SDavid du Colombier 				cal.b[z] |= ref.b[z] | externs.b[z];
824e887ea33SDavid du Colombier 				ref.b[z] = 0;
825e887ea33SDavid du Colombier 			}
826e887ea33SDavid du Colombier 			break;
827e887ea33SDavid du Colombier 
828e887ea33SDavid du Colombier 		case ATEXT:
829e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++) {
830e887ea33SDavid du Colombier 				cal.b[z] = 0;
831e887ea33SDavid du Colombier 				ref.b[z] = 0;
832e887ea33SDavid du Colombier 			}
833e887ea33SDavid du Colombier 			break;
834e887ea33SDavid du Colombier 
835e887ea33SDavid du Colombier 		case ARET:
836e887ea33SDavid du Colombier 			for(z=0; z<BITS; z++) {
837e887ea33SDavid du Colombier 				cal.b[z] = externs.b[z];
838e887ea33SDavid du Colombier 				ref.b[z] = 0;
839e887ea33SDavid du Colombier 			}
840e887ea33SDavid du Colombier 		}
841e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++) {
842e887ea33SDavid du Colombier 			ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
843e887ea33SDavid du Colombier 				r1->use1.b[z] | r1->use2.b[z];
844e887ea33SDavid du Colombier 			cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
845e887ea33SDavid du Colombier 			r1->refbehind.b[z] = ref.b[z];
846e887ea33SDavid du Colombier 			r1->calbehind.b[z] = cal.b[z];
847e887ea33SDavid du Colombier 		}
848e887ea33SDavid du Colombier 		if(r1->active)
849e887ea33SDavid du Colombier 			break;
850e887ea33SDavid du Colombier 		r1->active = 1;
851e887ea33SDavid du Colombier 	}
852e887ea33SDavid du Colombier 	for(; r != r1; r = r->p1)
853e887ea33SDavid du Colombier 		for(r2 = r->p2; r2 != R; r2 = r2->p2link)
854e887ea33SDavid du Colombier 			prop(r2, r->refbehind, r->calbehind);
855e887ea33SDavid du Colombier }
856e887ea33SDavid du Colombier 
857e887ea33SDavid du Colombier /*
858e887ea33SDavid du Colombier  * find looping structure
859e887ea33SDavid du Colombier  *
860e887ea33SDavid du Colombier  * 1) find reverse postordering
861e887ea33SDavid du Colombier  * 2) find approximate dominators,
862e887ea33SDavid du Colombier  *	the actual dominators if the flow graph is reducible
863e887ea33SDavid du Colombier  *	otherwise, dominators plus some other non-dominators.
864e887ea33SDavid du Colombier  *	See Matthew S. Hecht and Jeffrey D. Ullman,
865e887ea33SDavid du Colombier  *	"Analysis of a Simple Algorithm for Global Data Flow Problems",
866e887ea33SDavid du Colombier  *	Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
867e887ea33SDavid du Colombier  *	Oct. 1-3, 1973, pp.  207-217.
868e887ea33SDavid du Colombier  * 3) find all nodes with a predecessor dominated by the current node.
869e887ea33SDavid du Colombier  *	such a node is a loop head.
870e887ea33SDavid du Colombier  *	recursively, all preds with a greater rpo number are in the loop
871e887ea33SDavid du Colombier  */
872e887ea33SDavid du Colombier long
postorder(Reg * r,Reg ** rpo2r,long n)873e887ea33SDavid du Colombier postorder(Reg *r, Reg **rpo2r, long n)
874e887ea33SDavid du Colombier {
875e887ea33SDavid du Colombier 	Reg *r1;
876e887ea33SDavid du Colombier 
877e887ea33SDavid du Colombier 	r->rpo = 1;
878e887ea33SDavid du Colombier 	r1 = r->s1;
879e887ea33SDavid du Colombier 	if(r1 && !r1->rpo)
880e887ea33SDavid du Colombier 		n = postorder(r1, rpo2r, n);
881e887ea33SDavid du Colombier 	r1 = r->s2;
882e887ea33SDavid du Colombier 	if(r1 && !r1->rpo)
883e887ea33SDavid du Colombier 		n = postorder(r1, rpo2r, n);
884e887ea33SDavid du Colombier 	rpo2r[n] = r;
885e887ea33SDavid du Colombier 	n++;
886e887ea33SDavid du Colombier 	return n;
887e887ea33SDavid du Colombier }
888e887ea33SDavid du Colombier 
889e887ea33SDavid du Colombier long
rpolca(long * idom,long rpo1,long rpo2)890e887ea33SDavid du Colombier rpolca(long *idom, long rpo1, long rpo2)
891e887ea33SDavid du Colombier {
892e887ea33SDavid du Colombier 	long t;
893e887ea33SDavid du Colombier 
894e887ea33SDavid du Colombier 	if(rpo1 == -1)
895e887ea33SDavid du Colombier 		return rpo2;
896e887ea33SDavid du Colombier 	while(rpo1 != rpo2){
897e887ea33SDavid du Colombier 		if(rpo1 > rpo2){
898e887ea33SDavid du Colombier 			t = rpo2;
899e887ea33SDavid du Colombier 			rpo2 = rpo1;
900e887ea33SDavid du Colombier 			rpo1 = t;
901e887ea33SDavid du Colombier 		}
902e887ea33SDavid du Colombier 		while(rpo1 < rpo2){
903e887ea33SDavid du Colombier 			t = idom[rpo2];
904e887ea33SDavid du Colombier 			if(t >= rpo2)
905e887ea33SDavid du Colombier 				fatal(Z, "bad idom");
906e887ea33SDavid du Colombier 			rpo2 = t;
907e887ea33SDavid du Colombier 		}
908e887ea33SDavid du Colombier 	}
909e887ea33SDavid du Colombier 	return rpo1;
910e887ea33SDavid du Colombier }
911e887ea33SDavid du Colombier 
912e887ea33SDavid du Colombier int
doms(long * idom,long r,long s)913e887ea33SDavid du Colombier doms(long *idom, long r, long s)
914e887ea33SDavid du Colombier {
915e887ea33SDavid du Colombier 	while(s > r)
916e887ea33SDavid du Colombier 		s = idom[s];
917e887ea33SDavid du Colombier 	return s == r;
918e887ea33SDavid du Colombier }
919e887ea33SDavid du Colombier 
920e887ea33SDavid du Colombier int
loophead(long * idom,Reg * r)921e887ea33SDavid du Colombier loophead(long *idom, Reg *r)
922e887ea33SDavid du Colombier {
923e887ea33SDavid du Colombier 	long src;
924e887ea33SDavid du Colombier 
925e887ea33SDavid du Colombier 	src = r->rpo;
926e887ea33SDavid du Colombier 	if(r->p1 != R && doms(idom, src, r->p1->rpo))
927e887ea33SDavid du Colombier 		return 1;
928e887ea33SDavid du Colombier 	for(r = r->p2; r != R; r = r->p2link)
929e887ea33SDavid du Colombier 		if(doms(idom, src, r->rpo))
930e887ea33SDavid du Colombier 			return 1;
931e887ea33SDavid du Colombier 	return 0;
932e887ea33SDavid du Colombier }
933e887ea33SDavid du Colombier 
934e887ea33SDavid du Colombier void
loopmark(Reg ** rpo2r,long head,Reg * r)935e887ea33SDavid du Colombier loopmark(Reg **rpo2r, long head, Reg *r)
936e887ea33SDavid du Colombier {
937e887ea33SDavid du Colombier 	if(r->rpo < head || r->active == head)
938e887ea33SDavid du Colombier 		return;
939e887ea33SDavid du Colombier 	r->active = head;
940e887ea33SDavid du Colombier 	r->loop += LOOP;
941e887ea33SDavid du Colombier 	if(r->p1 != R)
942e887ea33SDavid du Colombier 		loopmark(rpo2r, head, r->p1);
943e887ea33SDavid du Colombier 	for(r = r->p2; r != R; r = r->p2link)
944e887ea33SDavid du Colombier 		loopmark(rpo2r, head, r);
945e887ea33SDavid du Colombier }
946e887ea33SDavid du Colombier 
947e887ea33SDavid du Colombier void
loopit(Reg * r,long nr)948e887ea33SDavid du Colombier loopit(Reg *r, long nr)
949e887ea33SDavid du Colombier {
950e887ea33SDavid du Colombier 	Reg *r1;
951e887ea33SDavid du Colombier 	long i, d, me;
952e887ea33SDavid du Colombier 
953e887ea33SDavid du Colombier 	if(nr > maxnr) {
954e887ea33SDavid du Colombier 		rpo2r = alloc(nr * sizeof(Reg*));
955e887ea33SDavid du Colombier 		idom = alloc(nr * sizeof(long));
956e887ea33SDavid du Colombier 		maxnr = nr;
957e887ea33SDavid du Colombier 	}
958e887ea33SDavid du Colombier 
959e887ea33SDavid du Colombier 	d = postorder(r, rpo2r, 0);
960e887ea33SDavid du Colombier 	if(d > nr)
961e887ea33SDavid du Colombier 		fatal(Z, "too many reg nodes");
962e887ea33SDavid du Colombier 	nr = d;
963e887ea33SDavid du Colombier 	for(i = 0; i < nr / 2; i++){
964e887ea33SDavid du Colombier 		r1 = rpo2r[i];
965e887ea33SDavid du Colombier 		rpo2r[i] = rpo2r[nr - 1 - i];
966e887ea33SDavid du Colombier 		rpo2r[nr - 1 - i] = r1;
967e887ea33SDavid du Colombier 	}
968e887ea33SDavid du Colombier 	for(i = 0; i < nr; i++)
969e887ea33SDavid du Colombier 		rpo2r[i]->rpo = i;
970e887ea33SDavid du Colombier 
971e887ea33SDavid du Colombier 	idom[0] = 0;
972e887ea33SDavid du Colombier 	for(i = 0; i < nr; i++){
973e887ea33SDavid du Colombier 		r1 = rpo2r[i];
974e887ea33SDavid du Colombier 		me = r1->rpo;
975e887ea33SDavid du Colombier 		d = -1;
976e887ea33SDavid du Colombier 		if(r1->p1 != R && r1->p1->rpo < me)
977e887ea33SDavid du Colombier 			d = r1->p1->rpo;
978e887ea33SDavid du Colombier 		for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
979e887ea33SDavid du Colombier 			if(r1->rpo < me)
980e887ea33SDavid du Colombier 				d = rpolca(idom, d, r1->rpo);
981e887ea33SDavid du Colombier 		idom[i] = d;
982e887ea33SDavid du Colombier 	}
983e887ea33SDavid du Colombier 
984e887ea33SDavid du Colombier 	for(i = 0; i < nr; i++){
985e887ea33SDavid du Colombier 		r1 = rpo2r[i];
986e887ea33SDavid du Colombier 		r1->loop++;
987e887ea33SDavid du Colombier 		if(r1->p2 != R && loophead(idom, r1))
988e887ea33SDavid du Colombier 			loopmark(rpo2r, i, r1);
989e887ea33SDavid du Colombier 	}
990e887ea33SDavid du Colombier }
991e887ea33SDavid du Colombier 
992e887ea33SDavid du Colombier void
synch(Reg * r,Bits dif)993e887ea33SDavid du Colombier synch(Reg *r, Bits dif)
994e887ea33SDavid du Colombier {
995e887ea33SDavid du Colombier 	Reg *r1;
996e887ea33SDavid du Colombier 	int z;
997e887ea33SDavid du Colombier 
998e887ea33SDavid du Colombier 	for(r1 = r; r1 != R; r1 = r1->s1) {
999e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++) {
1000e887ea33SDavid du Colombier 			dif.b[z] = (dif.b[z] &
1001e887ea33SDavid du Colombier 				~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
1002e887ea33SDavid du Colombier 					r1->set.b[z] | r1->regdiff.b[z];
1003e887ea33SDavid du Colombier 			if(dif.b[z] != r1->regdiff.b[z]) {
1004e887ea33SDavid du Colombier 				r1->regdiff.b[z] = dif.b[z];
1005e887ea33SDavid du Colombier 				change++;
1006e887ea33SDavid du Colombier 			}
1007e887ea33SDavid du Colombier 		}
1008e887ea33SDavid du Colombier 		if(r1->active)
1009e887ea33SDavid du Colombier 			break;
1010e887ea33SDavid du Colombier 		r1->active = 1;
1011e887ea33SDavid du Colombier 		for(z=0; z<BITS; z++)
1012e887ea33SDavid du Colombier 			dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
1013e887ea33SDavid du Colombier 		if(r1->s2 != R)
1014e887ea33SDavid du Colombier 			synch(r1->s2, dif);
1015e887ea33SDavid du Colombier 	}
1016e887ea33SDavid du Colombier }
1017e887ea33SDavid du Colombier 
1018e887ea33SDavid du Colombier ulong
allreg(ulong b,Rgn * r)1019e887ea33SDavid du Colombier allreg(ulong b, Rgn *r)
1020e887ea33SDavid du Colombier {
1021e887ea33SDavid du Colombier 	Var *v;
1022e887ea33SDavid du Colombier 	int i;
1023e887ea33SDavid du Colombier 
1024e887ea33SDavid du Colombier 	v = var + r->varno;
1025e887ea33SDavid du Colombier 	r->regno = 0;
1026e887ea33SDavid du Colombier 	switch(v->etype) {
1027e887ea33SDavid du Colombier 
1028e887ea33SDavid du Colombier 	default:
1029e887ea33SDavid du Colombier 		diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
1030e887ea33SDavid du Colombier 		break;
1031e887ea33SDavid du Colombier 
1032e887ea33SDavid du Colombier 	case TCHAR:
1033e887ea33SDavid du Colombier 	case TUCHAR:
1034e887ea33SDavid du Colombier 	case TSHORT:
1035e887ea33SDavid du Colombier 	case TUSHORT:
1036e887ea33SDavid du Colombier 	case TINT:
1037e887ea33SDavid du Colombier 	case TUINT:
1038e887ea33SDavid du Colombier 	case TLONG:
1039e887ea33SDavid du Colombier 	case TULONG:
1040e887ea33SDavid du Colombier 	case TVLONG:
1041e887ea33SDavid du Colombier 	case TUVLONG:
1042e887ea33SDavid du Colombier 	case TIND:
1043e887ea33SDavid du Colombier 	case TARRAY:
1044e887ea33SDavid du Colombier 		i = BtoR(~b);
1045e887ea33SDavid du Colombier 		if(i && r->cost > 0) {
1046e887ea33SDavid du Colombier 			r->regno = i;
1047e887ea33SDavid du Colombier 			return RtoB(i);
1048e887ea33SDavid du Colombier 		}
1049e887ea33SDavid du Colombier 		break;
1050e887ea33SDavid du Colombier 
1051e887ea33SDavid du Colombier 	case TDOUBLE:
1052e887ea33SDavid du Colombier 	case TFLOAT:
1053e887ea33SDavid du Colombier 		i = BtoF(~b);
1054e887ea33SDavid du Colombier 		if(i && r->cost > 0) {
1055e887ea33SDavid du Colombier 			r->regno = i;
1056e887ea33SDavid du Colombier 			return FtoB(i);
1057e887ea33SDavid du Colombier 		}
1058e887ea33SDavid du Colombier 		break;
1059e887ea33SDavid du Colombier 	}
1060e887ea33SDavid du Colombier 	return 0;
1061e887ea33SDavid du Colombier }
1062e887ea33SDavid du Colombier 
1063e887ea33SDavid du Colombier void
paint1(Reg * r,int bn)1064e887ea33SDavid du Colombier paint1(Reg *r, int bn)
1065e887ea33SDavid du Colombier {
1066e887ea33SDavid du Colombier 	Reg *r1;
1067e887ea33SDavid du Colombier 	Prog *p;
1068e887ea33SDavid du Colombier 	int z;
1069e887ea33SDavid du Colombier 	ulong bb;
1070e887ea33SDavid du Colombier 
1071e887ea33SDavid du Colombier 	z = bn/32;
1072e887ea33SDavid du Colombier 	bb = 1L<<(bn%32);
1073e887ea33SDavid du Colombier 	if(r->act.b[z] & bb)
1074e887ea33SDavid du Colombier 		return;
1075e887ea33SDavid du Colombier 	for(;;) {
1076e887ea33SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1077e887ea33SDavid du Colombier 			break;
1078e887ea33SDavid du Colombier 		r1 = r->p1;
1079e887ea33SDavid du Colombier 		if(r1 == R)
1080e887ea33SDavid du Colombier 			break;
1081e887ea33SDavid du Colombier 		if(!(r1->refahead.b[z] & bb))
1082e887ea33SDavid du Colombier 			break;
1083e887ea33SDavid du Colombier 		if(r1->act.b[z] & bb)
1084e887ea33SDavid du Colombier 			break;
1085e887ea33SDavid du Colombier 		r = r1;
1086e887ea33SDavid du Colombier 	}
1087e887ea33SDavid du Colombier 
1088e887ea33SDavid du Colombier 	if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
1089e887ea33SDavid du Colombier 		change -= CLOAD * r->loop;
1090e887ea33SDavid du Colombier 		if(debug['R'] && debug['v'])
1091e887ea33SDavid du Colombier 			print("%ld%P\tld %B $%d\n", r->loop,
1092e887ea33SDavid du Colombier 				r->prog, blsh(bn), change);
1093e887ea33SDavid du Colombier 	}
1094e887ea33SDavid du Colombier 	for(;;) {
1095e887ea33SDavid du Colombier 		r->act.b[z] |= bb;
1096e887ea33SDavid du Colombier 		p = r->prog;
1097e887ea33SDavid du Colombier 
1098e887ea33SDavid du Colombier 		if(r->use1.b[z] & bb) {
1099e887ea33SDavid du Colombier 			change += CREF * r->loop;
1100e887ea33SDavid du Colombier 			if(debug['R'] && debug['v'])
1101e887ea33SDavid du Colombier 				print("%ld%P\tu1 %B $%d\n", r->loop,
1102e887ea33SDavid du Colombier 					p, blsh(bn), change);
1103e887ea33SDavid du Colombier 		}
1104e887ea33SDavid du Colombier 
1105e887ea33SDavid du Colombier 		if((r->use2.b[z]|r->set.b[z]) & bb) {
1106e887ea33SDavid du Colombier 			change += CREF * r->loop;
1107e887ea33SDavid du Colombier 			if(debug['R'] && debug['v'])
1108e887ea33SDavid du Colombier 				print("%ld%P\tu2 %B $%d\n", r->loop,
1109e887ea33SDavid du Colombier 					p, blsh(bn), change);
1110e887ea33SDavid du Colombier 		}
1111e887ea33SDavid du Colombier 
1112e887ea33SDavid du Colombier 		if(STORE(r) & r->regdiff.b[z] & bb) {
1113e887ea33SDavid du Colombier 			change -= CLOAD * r->loop;
1114e887ea33SDavid du Colombier 			if(debug['R'] && debug['v'])
1115e887ea33SDavid du Colombier 				print("%ld%P\tst %B $%d\n", r->loop,
1116e887ea33SDavid du Colombier 					p, blsh(bn), change);
1117e887ea33SDavid du Colombier 		}
1118e887ea33SDavid du Colombier 
1119e887ea33SDavid du Colombier 		if(r->refbehind.b[z] & bb)
1120e887ea33SDavid du Colombier 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
1121e887ea33SDavid du Colombier 				if(r1->refahead.b[z] & bb)
1122e887ea33SDavid du Colombier 					paint1(r1, bn);
1123e887ea33SDavid du Colombier 
1124e887ea33SDavid du Colombier 		if(!(r->refahead.b[z] & bb))
1125e887ea33SDavid du Colombier 			break;
1126e887ea33SDavid du Colombier 		r1 = r->s2;
1127e887ea33SDavid du Colombier 		if(r1 != R)
1128e887ea33SDavid du Colombier 			if(r1->refbehind.b[z] & bb)
1129e887ea33SDavid du Colombier 				paint1(r1, bn);
1130e887ea33SDavid du Colombier 		r = r->s1;
1131e887ea33SDavid du Colombier 		if(r == R)
1132e887ea33SDavid du Colombier 			break;
1133e887ea33SDavid du Colombier 		if(r->act.b[z] & bb)
1134e887ea33SDavid du Colombier 			break;
1135e887ea33SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1136e887ea33SDavid du Colombier 			break;
1137e887ea33SDavid du Colombier 	}
1138e887ea33SDavid du Colombier }
1139e887ea33SDavid du Colombier 
1140e887ea33SDavid du Colombier ulong
regset(Reg * r,ulong bb)1141e887ea33SDavid du Colombier regset(Reg *r, ulong bb)
1142e887ea33SDavid du Colombier {
1143e887ea33SDavid du Colombier 	ulong b, set;
1144e887ea33SDavid du Colombier 	Adr v;
1145e887ea33SDavid du Colombier 	int c;
1146e887ea33SDavid du Colombier 
1147e887ea33SDavid du Colombier 	set = 0;
1148e887ea33SDavid du Colombier 	v = zprog.from;
1149e887ea33SDavid du Colombier 	while(b = bb & ~(bb-1)) {
1150e887ea33SDavid du Colombier 		v.type = b & 0xFFFF? BtoR(b): BtoF(b);
1151e887ea33SDavid du Colombier 		if(v.type == 0)
1152e887ea33SDavid du Colombier 			diag(Z, "zero v.type for %#lux", b);
1153e887ea33SDavid du Colombier 		c = copyu(r->prog, &v, A);
1154e887ea33SDavid du Colombier 		if(c == 3)
1155e887ea33SDavid du Colombier 			set |= b;
1156e887ea33SDavid du Colombier 		bb &= ~b;
1157e887ea33SDavid du Colombier 	}
1158e887ea33SDavid du Colombier 	return set;
1159e887ea33SDavid du Colombier }
1160e887ea33SDavid du Colombier 
1161e887ea33SDavid du Colombier ulong
reguse(Reg * r,ulong bb)1162e887ea33SDavid du Colombier reguse(Reg *r, ulong bb)
1163e887ea33SDavid du Colombier {
1164e887ea33SDavid du Colombier 	ulong b, set;
1165e887ea33SDavid du Colombier 	Adr v;
1166e887ea33SDavid du Colombier 	int c;
1167e887ea33SDavid du Colombier 
1168e887ea33SDavid du Colombier 	set = 0;
1169e887ea33SDavid du Colombier 	v = zprog.from;
1170e887ea33SDavid du Colombier 	while(b = bb & ~(bb-1)) {
1171e887ea33SDavid du Colombier 		v.type = b & 0xFFFF? BtoR(b): BtoF(b);
1172e887ea33SDavid du Colombier 		c = copyu(r->prog, &v, A);
1173e887ea33SDavid du Colombier 		if(c == 1 || c == 2 || c == 4)
1174e887ea33SDavid du Colombier 			set |= b;
1175e887ea33SDavid du Colombier 		bb &= ~b;
1176e887ea33SDavid du Colombier 	}
1177e887ea33SDavid du Colombier 	return set;
1178e887ea33SDavid du Colombier }
1179e887ea33SDavid du Colombier 
1180e887ea33SDavid du Colombier ulong
paint2(Reg * r,int bn)1181e887ea33SDavid du Colombier paint2(Reg *r, int bn)
1182e887ea33SDavid du Colombier {
1183e887ea33SDavid du Colombier 	Reg *r1;
1184e887ea33SDavid du Colombier 	int z;
1185e887ea33SDavid du Colombier 	ulong bb, vreg, x;
1186e887ea33SDavid du Colombier 
1187e887ea33SDavid du Colombier 	z = bn/32;
1188e887ea33SDavid du Colombier 	bb = 1L << (bn%32);
1189e887ea33SDavid du Colombier 	vreg = regbits;
1190e887ea33SDavid du Colombier 	if(!(r->act.b[z] & bb))
1191e887ea33SDavid du Colombier 		return vreg;
1192e887ea33SDavid du Colombier 	for(;;) {
1193e887ea33SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1194e887ea33SDavid du Colombier 			break;
1195e887ea33SDavid du Colombier 		r1 = r->p1;
1196e887ea33SDavid du Colombier 		if(r1 == R)
1197e887ea33SDavid du Colombier 			break;
1198e887ea33SDavid du Colombier 		if(!(r1->refahead.b[z] & bb))
1199e887ea33SDavid du Colombier 			break;
1200e887ea33SDavid du Colombier 		if(!(r1->act.b[z] & bb))
1201e887ea33SDavid du Colombier 			break;
1202e887ea33SDavid du Colombier 		r = r1;
1203e887ea33SDavid du Colombier 	}
1204e887ea33SDavid du Colombier 	for(;;) {
1205e887ea33SDavid du Colombier 		r->act.b[z] &= ~bb;
1206e887ea33SDavid du Colombier 
1207e887ea33SDavid du Colombier 		vreg |= r->regu;
1208e887ea33SDavid du Colombier 
1209e887ea33SDavid du Colombier 		if(r->refbehind.b[z] & bb)
1210e887ea33SDavid du Colombier 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
1211e887ea33SDavid du Colombier 				if(r1->refahead.b[z] & bb)
1212e887ea33SDavid du Colombier 					vreg |= paint2(r1, bn);
1213e887ea33SDavid du Colombier 
1214e887ea33SDavid du Colombier 		if(!(r->refahead.b[z] & bb))
1215e887ea33SDavid du Colombier 			break;
1216e887ea33SDavid du Colombier 		r1 = r->s2;
1217e887ea33SDavid du Colombier 		if(r1 != R)
1218e887ea33SDavid du Colombier 			if(r1->refbehind.b[z] & bb)
1219e887ea33SDavid du Colombier 				vreg |= paint2(r1, bn);
1220e887ea33SDavid du Colombier 		r = r->s1;
1221e887ea33SDavid du Colombier 		if(r == R)
1222e887ea33SDavid du Colombier 			break;
1223e887ea33SDavid du Colombier 		if(!(r->act.b[z] & bb))
1224e887ea33SDavid du Colombier 			break;
1225e887ea33SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1226e887ea33SDavid du Colombier 			break;
1227e887ea33SDavid du Colombier 	}
1228e887ea33SDavid du Colombier 
1229e887ea33SDavid du Colombier 	bb = vreg;
1230e887ea33SDavid du Colombier 	for(; r; r=r->s1) {
1231e887ea33SDavid du Colombier 		x = r->regu & ~bb;
1232e887ea33SDavid du Colombier 		if(x) {
1233e887ea33SDavid du Colombier 			vreg |= reguse(r, x);
1234e887ea33SDavid du Colombier 			bb |= regset(r, x);
1235e887ea33SDavid du Colombier 		}
1236e887ea33SDavid du Colombier 	}
1237e887ea33SDavid du Colombier 	return vreg;
1238e887ea33SDavid du Colombier }
1239e887ea33SDavid du Colombier 
1240e887ea33SDavid du Colombier void
paint3(Reg * r,int bn,long rb,int rn)1241e887ea33SDavid du Colombier paint3(Reg *r, int bn, long rb, int rn)
1242e887ea33SDavid du Colombier {
1243e887ea33SDavid du Colombier 	Reg *r1;
1244e887ea33SDavid du Colombier 	Prog *p;
1245e887ea33SDavid du Colombier 	int z;
1246e887ea33SDavid du Colombier 	ulong bb;
1247e887ea33SDavid du Colombier 
1248e887ea33SDavid du Colombier 	z = bn/32;
1249e887ea33SDavid du Colombier 	bb = 1L << (bn%32);
1250e887ea33SDavid du Colombier 	if(r->act.b[z] & bb)
1251e887ea33SDavid du Colombier 		return;
1252e887ea33SDavid du Colombier 	for(;;) {
1253e887ea33SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1254e887ea33SDavid du Colombier 			break;
1255e887ea33SDavid du Colombier 		r1 = r->p1;
1256e887ea33SDavid du Colombier 		if(r1 == R)
1257e887ea33SDavid du Colombier 			break;
1258e887ea33SDavid du Colombier 		if(!(r1->refahead.b[z] & bb))
1259e887ea33SDavid du Colombier 			break;
1260e887ea33SDavid du Colombier 		if(r1->act.b[z] & bb)
1261e887ea33SDavid du Colombier 			break;
1262e887ea33SDavid du Colombier 		r = r1;
1263e887ea33SDavid du Colombier 	}
1264e887ea33SDavid du Colombier 
1265e887ea33SDavid du Colombier 	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
1266e887ea33SDavid du Colombier 		addmove(r, bn, rn, 0);
1267e887ea33SDavid du Colombier 	for(;;) {
1268e887ea33SDavid du Colombier 		r->act.b[z] |= bb;
1269e887ea33SDavid du Colombier 		p = r->prog;
1270e887ea33SDavid du Colombier 
1271e887ea33SDavid du Colombier 		if(r->use1.b[z] & bb) {
1272e887ea33SDavid du Colombier 			if(debug['R'])
1273e887ea33SDavid du Colombier 				print("%P", p);
1274e887ea33SDavid du Colombier 			addreg(&p->from, rn);
1275e887ea33SDavid du Colombier 			if(debug['R'])
1276e887ea33SDavid du Colombier 				print("\t.c%P\n", p);
1277e887ea33SDavid du Colombier 		}
1278e887ea33SDavid du Colombier 		if((r->use2.b[z]|r->set.b[z]) & bb) {
1279e887ea33SDavid du Colombier 			if(debug['R'])
1280e887ea33SDavid du Colombier 				print("%P", p);
1281e887ea33SDavid du Colombier 			addreg(&p->to, rn);
1282e887ea33SDavid du Colombier 			if(debug['R'])
1283e887ea33SDavid du Colombier 				print("\t.c%P\n", p);
1284e887ea33SDavid du Colombier 		}
1285e887ea33SDavid du Colombier 
1286e887ea33SDavid du Colombier 		if(STORE(r) & r->regdiff.b[z] & bb)
1287e887ea33SDavid du Colombier 			addmove(r, bn, rn, 1);
1288e887ea33SDavid du Colombier 		r->regu |= rb;
1289e887ea33SDavid du Colombier 
1290e887ea33SDavid du Colombier 		if(r->refbehind.b[z] & bb)
1291e887ea33SDavid du Colombier 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
1292e887ea33SDavid du Colombier 				if(r1->refahead.b[z] & bb)
1293e887ea33SDavid du Colombier 					paint3(r1, bn, rb, rn);
1294e887ea33SDavid du Colombier 
1295e887ea33SDavid du Colombier 		if(!(r->refahead.b[z] & bb))
1296e887ea33SDavid du Colombier 			break;
1297e887ea33SDavid du Colombier 		r1 = r->s2;
1298e887ea33SDavid du Colombier 		if(r1 != R)
1299e887ea33SDavid du Colombier 			if(r1->refbehind.b[z] & bb)
1300e887ea33SDavid du Colombier 				paint3(r1, bn, rb, rn);
1301e887ea33SDavid du Colombier 		r = r->s1;
1302e887ea33SDavid du Colombier 		if(r == R)
1303e887ea33SDavid du Colombier 			break;
1304e887ea33SDavid du Colombier 		if(r->act.b[z] & bb)
1305e887ea33SDavid du Colombier 			break;
1306e887ea33SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1307e887ea33SDavid du Colombier 			break;
1308e887ea33SDavid du Colombier 	}
1309e887ea33SDavid du Colombier }
1310e887ea33SDavid du Colombier 
1311e887ea33SDavid du Colombier void
addreg(Adr * a,int rn)1312e887ea33SDavid du Colombier addreg(Adr *a, int rn)
1313e887ea33SDavid du Colombier {
1314e887ea33SDavid du Colombier 
1315e887ea33SDavid du Colombier 	a->sym = 0;
1316e887ea33SDavid du Colombier 	a->offset = 0;
1317e887ea33SDavid du Colombier 	a->type = rn;
1318e887ea33SDavid du Colombier }
1319e887ea33SDavid du Colombier 
1320e887ea33SDavid du Colombier long
RtoB(int r)1321e887ea33SDavid du Colombier RtoB(int r)
1322e887ea33SDavid du Colombier {
1323e887ea33SDavid du Colombier 
1324e887ea33SDavid du Colombier 	if(r < D_AX || r > D_R15)
1325e887ea33SDavid du Colombier 		return 0;
1326e887ea33SDavid du Colombier 	return 1L << (r-D_AX);
1327e887ea33SDavid du Colombier }
1328e887ea33SDavid du Colombier 
1329e887ea33SDavid du Colombier int
BtoR(long b)1330e887ea33SDavid du Colombier BtoR(long b)
1331e887ea33SDavid du Colombier {
1332e887ea33SDavid du Colombier 
1333e887ea33SDavid du Colombier 	b &= 0xffffL;
1334e887ea33SDavid du Colombier 	if(b == 0)
1335e887ea33SDavid du Colombier 		return 0;
1336e887ea33SDavid du Colombier 	return bitno(b) + D_AX;
1337e887ea33SDavid du Colombier }
1338e887ea33SDavid du Colombier 
1339e887ea33SDavid du Colombier /*
1340e887ea33SDavid du Colombier  *	bit	reg
1341e887ea33SDavid du Colombier  *	16	X5
1342e887ea33SDavid du Colombier  *	17	X6
1343e887ea33SDavid du Colombier  *	18	X7
1344e887ea33SDavid du Colombier  */
1345e887ea33SDavid du Colombier long
FtoB(int f)1346e887ea33SDavid du Colombier FtoB(int f)
1347e887ea33SDavid du Colombier {
1348e887ea33SDavid du Colombier 	if(f < FREGMIN || f > FREGEXT)
1349e887ea33SDavid du Colombier 		return 0;
1350e887ea33SDavid du Colombier 	return 1L << (f - FREGMIN + 16);
1351e887ea33SDavid du Colombier }
1352e887ea33SDavid du Colombier 
1353e887ea33SDavid du Colombier int
BtoF(long b)1354e887ea33SDavid du Colombier BtoF(long b)
1355e887ea33SDavid du Colombier {
1356e887ea33SDavid du Colombier 
1357e887ea33SDavid du Colombier 	b &= 0x70000L;
1358e887ea33SDavid du Colombier 	if(b == 0)
1359e887ea33SDavid du Colombier 		return 0;
1360e887ea33SDavid du Colombier 	return bitno(b) - 16 + FREGMIN;
1361e887ea33SDavid du Colombier }
1362