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