xref: /inferno-os/utils/8c/reg.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth Reg*
rega(void)474a4d8c2SCharles.Forsyth rega(void)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth 	Reg *r;
774a4d8c2SCharles.Forsyth 
874a4d8c2SCharles.Forsyth 	r = freer;
974a4d8c2SCharles.Forsyth 	if(r == R) {
1074a4d8c2SCharles.Forsyth 		r = alloc(sizeof(*r));
1174a4d8c2SCharles.Forsyth 	} else
1274a4d8c2SCharles.Forsyth 		freer = r->link;
1374a4d8c2SCharles.Forsyth 
1474a4d8c2SCharles.Forsyth 	*r = zreg;
1574a4d8c2SCharles.Forsyth 	return r;
1674a4d8c2SCharles.Forsyth }
1774a4d8c2SCharles.Forsyth 
1874a4d8c2SCharles.Forsyth int
rcmp(void * a1,void * a2)19*45a20ab7Sforsyth rcmp(void *a1, void *a2)
2074a4d8c2SCharles.Forsyth {
2174a4d8c2SCharles.Forsyth 	Rgn *p1, *p2;
2274a4d8c2SCharles.Forsyth 	int c1, c2;
2374a4d8c2SCharles.Forsyth 
2474a4d8c2SCharles.Forsyth 	p1 = (Rgn*)a1;
2574a4d8c2SCharles.Forsyth 	p2 = (Rgn*)a2;
2674a4d8c2SCharles.Forsyth 	c1 = p2->cost;
2774a4d8c2SCharles.Forsyth 	c2 = p1->cost;
2874a4d8c2SCharles.Forsyth 	if(c1 -= c2)
2974a4d8c2SCharles.Forsyth 		return c1;
3074a4d8c2SCharles.Forsyth 	return p2->varno - p1->varno;
3174a4d8c2SCharles.Forsyth }
3274a4d8c2SCharles.Forsyth 
3374a4d8c2SCharles.Forsyth void
regopt(Prog * p)3474a4d8c2SCharles.Forsyth regopt(Prog *p)
3574a4d8c2SCharles.Forsyth {
3674a4d8c2SCharles.Forsyth 	Reg *r, *r1, *r2;
3774a4d8c2SCharles.Forsyth 	Prog *p1;
3874a4d8c2SCharles.Forsyth 	int i, z;
3974a4d8c2SCharles.Forsyth 	long initpc, val, npc;
4074a4d8c2SCharles.Forsyth 	ulong vreg;
4174a4d8c2SCharles.Forsyth 	Bits bit;
4274a4d8c2SCharles.Forsyth 	struct
4374a4d8c2SCharles.Forsyth 	{
4474a4d8c2SCharles.Forsyth 		long	m;
4574a4d8c2SCharles.Forsyth 		long	c;
4674a4d8c2SCharles.Forsyth 		Reg*	p;
4774a4d8c2SCharles.Forsyth 	} log5[6], *lp;
4874a4d8c2SCharles.Forsyth 
4974a4d8c2SCharles.Forsyth 	firstr = R;
5074a4d8c2SCharles.Forsyth 	lastr = R;
5174a4d8c2SCharles.Forsyth 	nvar = 0;
5274a4d8c2SCharles.Forsyth 	regbits = RtoB(D_SP) | RtoB(D_AX);
5374a4d8c2SCharles.Forsyth 	for(z=0; z<BITS; z++) {
5474a4d8c2SCharles.Forsyth 		externs.b[z] = 0;
5574a4d8c2SCharles.Forsyth 		params.b[z] = 0;
5674a4d8c2SCharles.Forsyth 		consts.b[z] = 0;
5774a4d8c2SCharles.Forsyth 		addrs.b[z] = 0;
5874a4d8c2SCharles.Forsyth 	}
5974a4d8c2SCharles.Forsyth 
6074a4d8c2SCharles.Forsyth 	/*
6174a4d8c2SCharles.Forsyth 	 * pass 1
6274a4d8c2SCharles.Forsyth 	 * build aux data structure
6374a4d8c2SCharles.Forsyth 	 * allocate pcs
6474a4d8c2SCharles.Forsyth 	 * find use and set of variables
6574a4d8c2SCharles.Forsyth 	 */
6674a4d8c2SCharles.Forsyth 	val = 5L * 5L * 5L * 5L * 5L;
6774a4d8c2SCharles.Forsyth 	lp = log5;
6874a4d8c2SCharles.Forsyth 	for(i=0; i<5; i++) {
6974a4d8c2SCharles.Forsyth 		lp->m = val;
7074a4d8c2SCharles.Forsyth 		lp->c = 0;
7174a4d8c2SCharles.Forsyth 		lp->p = R;
7274a4d8c2SCharles.Forsyth 		val /= 5L;
7374a4d8c2SCharles.Forsyth 		lp++;
7474a4d8c2SCharles.Forsyth 	}
7574a4d8c2SCharles.Forsyth 	val = 0;
7674a4d8c2SCharles.Forsyth 	for(; p != P; p = p->link) {
7774a4d8c2SCharles.Forsyth 		switch(p->as) {
7874a4d8c2SCharles.Forsyth 		case ADATA:
7974a4d8c2SCharles.Forsyth 		case AGLOBL:
8074a4d8c2SCharles.Forsyth 		case ANAME:
8174a4d8c2SCharles.Forsyth 		case ASIGNAME:
8274a4d8c2SCharles.Forsyth 			continue;
8374a4d8c2SCharles.Forsyth 		}
8474a4d8c2SCharles.Forsyth 		r = rega();
8574a4d8c2SCharles.Forsyth 		if(firstr == R) {
8674a4d8c2SCharles.Forsyth 			firstr = r;
8774a4d8c2SCharles.Forsyth 			lastr = r;
8874a4d8c2SCharles.Forsyth 		} else {
8974a4d8c2SCharles.Forsyth 			lastr->link = r;
9074a4d8c2SCharles.Forsyth 			r->p1 = lastr;
9174a4d8c2SCharles.Forsyth 			lastr->s1 = r;
9274a4d8c2SCharles.Forsyth 			lastr = r;
9374a4d8c2SCharles.Forsyth 		}
9474a4d8c2SCharles.Forsyth 		r->prog = p;
9574a4d8c2SCharles.Forsyth 		r->pc = val;
9674a4d8c2SCharles.Forsyth 		val++;
9774a4d8c2SCharles.Forsyth 
9874a4d8c2SCharles.Forsyth 		lp = log5;
9974a4d8c2SCharles.Forsyth 		for(i=0; i<5; i++) {
10074a4d8c2SCharles.Forsyth 			lp->c--;
10174a4d8c2SCharles.Forsyth 			if(lp->c <= 0) {
10274a4d8c2SCharles.Forsyth 				lp->c = lp->m;
10374a4d8c2SCharles.Forsyth 				if(lp->p != R)
10474a4d8c2SCharles.Forsyth 					lp->p->log5 = r;
10574a4d8c2SCharles.Forsyth 				lp->p = r;
10674a4d8c2SCharles.Forsyth 				(lp+1)->c = 0;
10774a4d8c2SCharles.Forsyth 				break;
10874a4d8c2SCharles.Forsyth 			}
10974a4d8c2SCharles.Forsyth 			lp++;
11074a4d8c2SCharles.Forsyth 		}
11174a4d8c2SCharles.Forsyth 
11274a4d8c2SCharles.Forsyth 		r1 = r->p1;
11374a4d8c2SCharles.Forsyth 		if(r1 != R)
11474a4d8c2SCharles.Forsyth 		switch(r1->prog->as) {
11574a4d8c2SCharles.Forsyth 		case ARET:
11674a4d8c2SCharles.Forsyth 		case AJMP:
11774a4d8c2SCharles.Forsyth 		case AIRETL:
11874a4d8c2SCharles.Forsyth 			r->p1 = R;
11974a4d8c2SCharles.Forsyth 			r1->s1 = R;
12074a4d8c2SCharles.Forsyth 		}
12174a4d8c2SCharles.Forsyth 
122*45a20ab7Sforsyth 		bit = mkvar(r, &p->from, p->as==AMOVL);
12374a4d8c2SCharles.Forsyth 		if(bany(&bit))
12474a4d8c2SCharles.Forsyth 		switch(p->as) {
12574a4d8c2SCharles.Forsyth 		/*
12674a4d8c2SCharles.Forsyth 		 * funny
12774a4d8c2SCharles.Forsyth 		 */
12874a4d8c2SCharles.Forsyth 		case ALEAL:
12974a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++)
13074a4d8c2SCharles.Forsyth 				addrs.b[z] |= bit.b[z];
13174a4d8c2SCharles.Forsyth 			break;
13274a4d8c2SCharles.Forsyth 
13374a4d8c2SCharles.Forsyth 		/*
13474a4d8c2SCharles.Forsyth 		 * left side read
13574a4d8c2SCharles.Forsyth 		 */
13674a4d8c2SCharles.Forsyth 		default:
13774a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++)
13874a4d8c2SCharles.Forsyth 				r->use1.b[z] |= bit.b[z];
13974a4d8c2SCharles.Forsyth 			break;
14074a4d8c2SCharles.Forsyth 		}
14174a4d8c2SCharles.Forsyth 
142*45a20ab7Sforsyth 		bit = mkvar(r, &p->to, 0);
14374a4d8c2SCharles.Forsyth 		if(bany(&bit))
14474a4d8c2SCharles.Forsyth 		switch(p->as) {
14574a4d8c2SCharles.Forsyth 		default:
14674a4d8c2SCharles.Forsyth 			diag(Z, "reg: unknown op: %A", p->as);
14774a4d8c2SCharles.Forsyth 			break;
14874a4d8c2SCharles.Forsyth 
14974a4d8c2SCharles.Forsyth 		/*
15074a4d8c2SCharles.Forsyth 		 * right side read
15174a4d8c2SCharles.Forsyth 		 */
15274a4d8c2SCharles.Forsyth 		case ACMPB:
15374a4d8c2SCharles.Forsyth 		case ACMPL:
15474a4d8c2SCharles.Forsyth 		case ACMPW:
15574a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++)
15674a4d8c2SCharles.Forsyth 				r->use2.b[z] |= bit.b[z];
15774a4d8c2SCharles.Forsyth 			break;
15874a4d8c2SCharles.Forsyth 
15974a4d8c2SCharles.Forsyth 		/*
16074a4d8c2SCharles.Forsyth 		 * right side write
16174a4d8c2SCharles.Forsyth 		 */
16274a4d8c2SCharles.Forsyth 		case ANOP:
16374a4d8c2SCharles.Forsyth 		case AMOVL:
16474a4d8c2SCharles.Forsyth 		case AMOVB:
16574a4d8c2SCharles.Forsyth 		case AMOVW:
16674a4d8c2SCharles.Forsyth 		case AMOVBLSX:
16774a4d8c2SCharles.Forsyth 		case AMOVBLZX:
16874a4d8c2SCharles.Forsyth 		case AMOVWLSX:
16974a4d8c2SCharles.Forsyth 		case AMOVWLZX:
17074a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++)
17174a4d8c2SCharles.Forsyth 				r->set.b[z] |= bit.b[z];
17274a4d8c2SCharles.Forsyth 			break;
17374a4d8c2SCharles.Forsyth 
17474a4d8c2SCharles.Forsyth 		/*
17574a4d8c2SCharles.Forsyth 		 * right side read+write
17674a4d8c2SCharles.Forsyth 		 */
17774a4d8c2SCharles.Forsyth 		case AADDB:
17874a4d8c2SCharles.Forsyth 		case AADDL:
17974a4d8c2SCharles.Forsyth 		case AADDW:
18074a4d8c2SCharles.Forsyth 		case AANDB:
18174a4d8c2SCharles.Forsyth 		case AANDL:
18274a4d8c2SCharles.Forsyth 		case AANDW:
18374a4d8c2SCharles.Forsyth 		case ASUBB:
18474a4d8c2SCharles.Forsyth 		case ASUBL:
18574a4d8c2SCharles.Forsyth 		case ASUBW:
18674a4d8c2SCharles.Forsyth 		case AORB:
18774a4d8c2SCharles.Forsyth 		case AORL:
18874a4d8c2SCharles.Forsyth 		case AORW:
18974a4d8c2SCharles.Forsyth 		case AXORB:
19074a4d8c2SCharles.Forsyth 		case AXORL:
19174a4d8c2SCharles.Forsyth 		case AXORW:
19274a4d8c2SCharles.Forsyth 		case ASALB:
19374a4d8c2SCharles.Forsyth 		case ASALL:
19474a4d8c2SCharles.Forsyth 		case ASALW:
19574a4d8c2SCharles.Forsyth 		case ASARB:
19674a4d8c2SCharles.Forsyth 		case ASARL:
19774a4d8c2SCharles.Forsyth 		case ASARW:
19874a4d8c2SCharles.Forsyth 		case AROLB:
19974a4d8c2SCharles.Forsyth 		case AROLL:
20074a4d8c2SCharles.Forsyth 		case AROLW:
20174a4d8c2SCharles.Forsyth 		case ARORB:
20274a4d8c2SCharles.Forsyth 		case ARORL:
20374a4d8c2SCharles.Forsyth 		case ARORW:
20474a4d8c2SCharles.Forsyth 		case ASHLB:
20574a4d8c2SCharles.Forsyth 		case ASHLL:
20674a4d8c2SCharles.Forsyth 		case ASHLW:
20774a4d8c2SCharles.Forsyth 		case ASHRB:
20874a4d8c2SCharles.Forsyth 		case ASHRL:
20974a4d8c2SCharles.Forsyth 		case ASHRW:
21074a4d8c2SCharles.Forsyth 		case AIMULL:
21174a4d8c2SCharles.Forsyth 		case AIMULW:
21274a4d8c2SCharles.Forsyth 		case ANEGL:
21374a4d8c2SCharles.Forsyth 		case ANOTL:
21474a4d8c2SCharles.Forsyth 		case AADCL:
21574a4d8c2SCharles.Forsyth 		case ASBBL:
21674a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++) {
21774a4d8c2SCharles.Forsyth 				r->set.b[z] |= bit.b[z];
21874a4d8c2SCharles.Forsyth 				r->use2.b[z] |= bit.b[z];
21974a4d8c2SCharles.Forsyth 			}
22074a4d8c2SCharles.Forsyth 			break;
22174a4d8c2SCharles.Forsyth 
22274a4d8c2SCharles.Forsyth 		/*
22374a4d8c2SCharles.Forsyth 		 * funny
22474a4d8c2SCharles.Forsyth 		 */
22574a4d8c2SCharles.Forsyth 		case AFMOVDP:
22674a4d8c2SCharles.Forsyth 		case AFMOVFP:
2274d1cf526Sforsyth 		case AFMOVLP:
22874a4d8c2SCharles.Forsyth 		case AFMOVVP:
2294d1cf526Sforsyth 		case AFMOVWP:
23074a4d8c2SCharles.Forsyth 		case ACALL:
23174a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++)
23274a4d8c2SCharles.Forsyth 				addrs.b[z] |= bit.b[z];
23374a4d8c2SCharles.Forsyth 			break;
23474a4d8c2SCharles.Forsyth 		}
23574a4d8c2SCharles.Forsyth 
23674a4d8c2SCharles.Forsyth 		switch(p->as) {
23774a4d8c2SCharles.Forsyth 		case AIMULL:
23874a4d8c2SCharles.Forsyth 		case AIMULW:
23974a4d8c2SCharles.Forsyth 			if(p->to.type != D_NONE)
24074a4d8c2SCharles.Forsyth 				break;
24174a4d8c2SCharles.Forsyth 
24274a4d8c2SCharles.Forsyth 		case AIDIVB:
24374a4d8c2SCharles.Forsyth 		case AIDIVL:
24474a4d8c2SCharles.Forsyth 		case AIDIVW:
24574a4d8c2SCharles.Forsyth 		case AIMULB:
24674a4d8c2SCharles.Forsyth 		case ADIVB:
24774a4d8c2SCharles.Forsyth 		case ADIVL:
24874a4d8c2SCharles.Forsyth 		case ADIVW:
24974a4d8c2SCharles.Forsyth 		case AMULB:
25074a4d8c2SCharles.Forsyth 		case AMULL:
25174a4d8c2SCharles.Forsyth 		case AMULW:
25274a4d8c2SCharles.Forsyth 
25374a4d8c2SCharles.Forsyth 		case ACWD:
25474a4d8c2SCharles.Forsyth 		case ACDQ:
25574a4d8c2SCharles.Forsyth 			r->regu |= RtoB(D_AX) | RtoB(D_DX);
25674a4d8c2SCharles.Forsyth 			break;
25774a4d8c2SCharles.Forsyth 
25874a4d8c2SCharles.Forsyth 		case AREP:
25974a4d8c2SCharles.Forsyth 		case AREPN:
26074a4d8c2SCharles.Forsyth 		case ALOOP:
26174a4d8c2SCharles.Forsyth 		case ALOOPEQ:
26274a4d8c2SCharles.Forsyth 		case ALOOPNE:
26374a4d8c2SCharles.Forsyth 			r->regu |= RtoB(D_CX);
26474a4d8c2SCharles.Forsyth 			break;
26574a4d8c2SCharles.Forsyth 
26674a4d8c2SCharles.Forsyth 		case AMOVSB:
26774a4d8c2SCharles.Forsyth 		case AMOVSL:
26874a4d8c2SCharles.Forsyth 		case AMOVSW:
26974a4d8c2SCharles.Forsyth 		case ACMPSB:
27074a4d8c2SCharles.Forsyth 		case ACMPSL:
27174a4d8c2SCharles.Forsyth 		case ACMPSW:
27274a4d8c2SCharles.Forsyth 			r->regu |= RtoB(D_SI) | RtoB(D_DI);
27374a4d8c2SCharles.Forsyth 			break;
27474a4d8c2SCharles.Forsyth 
27574a4d8c2SCharles.Forsyth 		case ASTOSB:
27674a4d8c2SCharles.Forsyth 		case ASTOSL:
27774a4d8c2SCharles.Forsyth 		case ASTOSW:
27874a4d8c2SCharles.Forsyth 		case ASCASB:
27974a4d8c2SCharles.Forsyth 		case ASCASL:
28074a4d8c2SCharles.Forsyth 		case ASCASW:
28174a4d8c2SCharles.Forsyth 			r->regu |= RtoB(D_AX) | RtoB(D_DI);
28274a4d8c2SCharles.Forsyth 			break;
28374a4d8c2SCharles.Forsyth 
28474a4d8c2SCharles.Forsyth 		case AINSB:
28574a4d8c2SCharles.Forsyth 		case AINSL:
28674a4d8c2SCharles.Forsyth 		case AINSW:
28774a4d8c2SCharles.Forsyth 		case AOUTSB:
28874a4d8c2SCharles.Forsyth 		case AOUTSL:
28974a4d8c2SCharles.Forsyth 		case AOUTSW:
29074a4d8c2SCharles.Forsyth 			r->regu |= RtoB(D_DI) | RtoB(D_DX);
29174a4d8c2SCharles.Forsyth 			break;
29274a4d8c2SCharles.Forsyth 
29374a4d8c2SCharles.Forsyth 		case AFSTSW:
29474a4d8c2SCharles.Forsyth 		case ASAHF:
29574a4d8c2SCharles.Forsyth 			r->regu |= RtoB(D_AX);
29674a4d8c2SCharles.Forsyth 			break;
29774a4d8c2SCharles.Forsyth 		}
29874a4d8c2SCharles.Forsyth 	}
29974a4d8c2SCharles.Forsyth 	if(firstr == R)
30074a4d8c2SCharles.Forsyth 		return;
30174a4d8c2SCharles.Forsyth 	initpc = pc - val;
30274a4d8c2SCharles.Forsyth 	npc = val;
30374a4d8c2SCharles.Forsyth 
30474a4d8c2SCharles.Forsyth 	/*
30574a4d8c2SCharles.Forsyth 	 * pass 2
30674a4d8c2SCharles.Forsyth 	 * turn branch references to pointers
30774a4d8c2SCharles.Forsyth 	 * build back pointers
30874a4d8c2SCharles.Forsyth 	 */
30974a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r->link) {
31074a4d8c2SCharles.Forsyth 		p = r->prog;
31174a4d8c2SCharles.Forsyth 		if(p->to.type == D_BRANCH) {
31274a4d8c2SCharles.Forsyth 			val = p->to.offset - initpc;
31374a4d8c2SCharles.Forsyth 			r1 = firstr;
31474a4d8c2SCharles.Forsyth 			while(r1 != R) {
31574a4d8c2SCharles.Forsyth 				r2 = r1->log5;
31674a4d8c2SCharles.Forsyth 				if(r2 != R && val >= r2->pc) {
31774a4d8c2SCharles.Forsyth 					r1 = r2;
31874a4d8c2SCharles.Forsyth 					continue;
31974a4d8c2SCharles.Forsyth 				}
32074a4d8c2SCharles.Forsyth 				if(r1->pc == val)
32174a4d8c2SCharles.Forsyth 					break;
32274a4d8c2SCharles.Forsyth 				r1 = r1->link;
32374a4d8c2SCharles.Forsyth 			}
32474a4d8c2SCharles.Forsyth 			if(r1 == R) {
32574a4d8c2SCharles.Forsyth 				nearln = p->lineno;
32674a4d8c2SCharles.Forsyth 				diag(Z, "ref not found\n%P", p);
32774a4d8c2SCharles.Forsyth 				continue;
32874a4d8c2SCharles.Forsyth 			}
32974a4d8c2SCharles.Forsyth 			if(r1 == r) {
33074a4d8c2SCharles.Forsyth 				nearln = p->lineno;
33174a4d8c2SCharles.Forsyth 				diag(Z, "ref to self\n%P", p);
33274a4d8c2SCharles.Forsyth 				continue;
33374a4d8c2SCharles.Forsyth 			}
33474a4d8c2SCharles.Forsyth 			r->s2 = r1;
33574a4d8c2SCharles.Forsyth 			r->p2link = r1->p2;
33674a4d8c2SCharles.Forsyth 			r1->p2 = r;
33774a4d8c2SCharles.Forsyth 		}
33874a4d8c2SCharles.Forsyth 	}
33974a4d8c2SCharles.Forsyth 	if(debug['R']) {
34074a4d8c2SCharles.Forsyth 		p = firstr->prog;
34174a4d8c2SCharles.Forsyth 		print("\n%L %D\n", p->lineno, &p->from);
34274a4d8c2SCharles.Forsyth 	}
34374a4d8c2SCharles.Forsyth 
34474a4d8c2SCharles.Forsyth 	/*
34574a4d8c2SCharles.Forsyth 	 * pass 2.5
34674a4d8c2SCharles.Forsyth 	 * find looping structure
34774a4d8c2SCharles.Forsyth 	 */
34874a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r->link)
34974a4d8c2SCharles.Forsyth 		r->active = 0;
35074a4d8c2SCharles.Forsyth 	change = 0;
35174a4d8c2SCharles.Forsyth 	loopit(firstr, npc);
35274a4d8c2SCharles.Forsyth 	if(debug['R'] && debug['v']) {
35374a4d8c2SCharles.Forsyth 		print("\nlooping structure:\n");
35474a4d8c2SCharles.Forsyth 		for(r = firstr; r != R; r = r->link) {
35574a4d8c2SCharles.Forsyth 			print("%ld:%P", r->loop, r->prog);
35674a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++)
35774a4d8c2SCharles.Forsyth 				bit.b[z] = r->use1.b[z] |
35874a4d8c2SCharles.Forsyth 					   r->use2.b[z] |
35974a4d8c2SCharles.Forsyth 					   r->set.b[z];
36074a4d8c2SCharles.Forsyth 			if(bany(&bit)) {
36174a4d8c2SCharles.Forsyth 				print("\t");
36274a4d8c2SCharles.Forsyth 				if(bany(&r->use1))
36374a4d8c2SCharles.Forsyth 					print(" u1=%B", r->use1);
36474a4d8c2SCharles.Forsyth 				if(bany(&r->use2))
36574a4d8c2SCharles.Forsyth 					print(" u2=%B", r->use2);
36674a4d8c2SCharles.Forsyth 				if(bany(&r->set))
36774a4d8c2SCharles.Forsyth 					print(" st=%B", r->set);
36874a4d8c2SCharles.Forsyth 			}
36974a4d8c2SCharles.Forsyth 			print("\n");
37074a4d8c2SCharles.Forsyth 		}
37174a4d8c2SCharles.Forsyth 	}
37274a4d8c2SCharles.Forsyth 
37374a4d8c2SCharles.Forsyth 	/*
37474a4d8c2SCharles.Forsyth 	 * pass 3
37574a4d8c2SCharles.Forsyth 	 * iterate propagating usage
37674a4d8c2SCharles.Forsyth 	 * 	back until flow graph is complete
37774a4d8c2SCharles.Forsyth 	 */
37874a4d8c2SCharles.Forsyth loop1:
37974a4d8c2SCharles.Forsyth 	change = 0;
38074a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r->link)
38174a4d8c2SCharles.Forsyth 		r->active = 0;
38274a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r->link)
38374a4d8c2SCharles.Forsyth 		if(r->prog->as == ARET)
38474a4d8c2SCharles.Forsyth 			prop(r, zbits, zbits);
38574a4d8c2SCharles.Forsyth loop11:
38674a4d8c2SCharles.Forsyth 	/* pick up unreachable code */
38774a4d8c2SCharles.Forsyth 	i = 0;
38874a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r1) {
38974a4d8c2SCharles.Forsyth 		r1 = r->link;
39074a4d8c2SCharles.Forsyth 		if(r1 && r1->active && !r->active) {
39174a4d8c2SCharles.Forsyth 			prop(r, zbits, zbits);
39274a4d8c2SCharles.Forsyth 			i = 1;
39374a4d8c2SCharles.Forsyth 		}
39474a4d8c2SCharles.Forsyth 	}
39574a4d8c2SCharles.Forsyth 	if(i)
39674a4d8c2SCharles.Forsyth 		goto loop11;
39774a4d8c2SCharles.Forsyth 	if(change)
39874a4d8c2SCharles.Forsyth 		goto loop1;
39974a4d8c2SCharles.Forsyth 
40074a4d8c2SCharles.Forsyth 
40174a4d8c2SCharles.Forsyth 	/*
40274a4d8c2SCharles.Forsyth 	 * pass 4
40374a4d8c2SCharles.Forsyth 	 * iterate propagating register/variable synchrony
40474a4d8c2SCharles.Forsyth 	 * 	forward until graph is complete
40574a4d8c2SCharles.Forsyth 	 */
40674a4d8c2SCharles.Forsyth loop2:
40774a4d8c2SCharles.Forsyth 	change = 0;
40874a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r->link)
40974a4d8c2SCharles.Forsyth 		r->active = 0;
41074a4d8c2SCharles.Forsyth 	synch(firstr, zbits);
41174a4d8c2SCharles.Forsyth 	if(change)
41274a4d8c2SCharles.Forsyth 		goto loop2;
41374a4d8c2SCharles.Forsyth 
41474a4d8c2SCharles.Forsyth 
41574a4d8c2SCharles.Forsyth 	/*
41674a4d8c2SCharles.Forsyth 	 * pass 5
41774a4d8c2SCharles.Forsyth 	 * isolate regions
41874a4d8c2SCharles.Forsyth 	 * calculate costs (paint1)
41974a4d8c2SCharles.Forsyth 	 */
42074a4d8c2SCharles.Forsyth 	r = firstr;
42174a4d8c2SCharles.Forsyth 	if(r) {
42274a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++)
42374a4d8c2SCharles.Forsyth 			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
42474a4d8c2SCharles.Forsyth 			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
42574a4d8c2SCharles.Forsyth 		if(bany(&bit)) {
42674a4d8c2SCharles.Forsyth 			nearln = r->prog->lineno;
42774a4d8c2SCharles.Forsyth 			warn(Z, "used and not set: %B", bit);
42874a4d8c2SCharles.Forsyth 			if(debug['R'] && !debug['w'])
42974a4d8c2SCharles.Forsyth 				print("used and not set: %B\n", bit);
43074a4d8c2SCharles.Forsyth 		}
43174a4d8c2SCharles.Forsyth 	}
43274a4d8c2SCharles.Forsyth 	if(debug['R'] && debug['v'])
43374a4d8c2SCharles.Forsyth 		print("\nprop structure:\n");
43474a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r->link)
43574a4d8c2SCharles.Forsyth 		r->act = zbits;
43674a4d8c2SCharles.Forsyth 	rgp = region;
43774a4d8c2SCharles.Forsyth 	nregion = 0;
43874a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r->link) {
43974a4d8c2SCharles.Forsyth 		if(debug['R'] && debug['v']) {
44074a4d8c2SCharles.Forsyth 			print("%P\t", r->prog);
44174a4d8c2SCharles.Forsyth 			if(bany(&r->set))
44274a4d8c2SCharles.Forsyth 				print("s:%B ", r->set);
44374a4d8c2SCharles.Forsyth 			if(bany(&r->refahead))
44474a4d8c2SCharles.Forsyth 				print("ra:%B ", r->refahead);
44574a4d8c2SCharles.Forsyth 			if(bany(&r->calahead))
44674a4d8c2SCharles.Forsyth 				print("ca:%B ", r->calahead);
44774a4d8c2SCharles.Forsyth 			print("\n");
44874a4d8c2SCharles.Forsyth 		}
44974a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++)
45074a4d8c2SCharles.Forsyth 			bit.b[z] = r->set.b[z] &
45174a4d8c2SCharles.Forsyth 			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
45274a4d8c2SCharles.Forsyth 		if(bany(&bit)) {
45374a4d8c2SCharles.Forsyth 			nearln = r->prog->lineno;
45474a4d8c2SCharles.Forsyth 			warn(Z, "set and not used: %B", bit);
45574a4d8c2SCharles.Forsyth 			if(debug['R'])
45674a4d8c2SCharles.Forsyth 				print("set and not used: %B\n", bit);
45774a4d8c2SCharles.Forsyth 			excise(r);
45874a4d8c2SCharles.Forsyth 		}
45974a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++)
46074a4d8c2SCharles.Forsyth 			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
46174a4d8c2SCharles.Forsyth 		while(bany(&bit)) {
46274a4d8c2SCharles.Forsyth 			i = bnum(bit);
46374a4d8c2SCharles.Forsyth 			rgp->enter = r;
46474a4d8c2SCharles.Forsyth 			rgp->varno = i;
46574a4d8c2SCharles.Forsyth 			change = 0;
46674a4d8c2SCharles.Forsyth 			if(debug['R'] && debug['v'])
46774a4d8c2SCharles.Forsyth 				print("\n");
46874a4d8c2SCharles.Forsyth 			paint1(r, i);
46974a4d8c2SCharles.Forsyth 			bit.b[i/32] &= ~(1L<<(i%32));
47074a4d8c2SCharles.Forsyth 			if(change <= 0) {
47174a4d8c2SCharles.Forsyth 				if(debug['R'])
47274a4d8c2SCharles.Forsyth 					print("%L$%d: %B\n",
47374a4d8c2SCharles.Forsyth 						r->prog->lineno, change, blsh(i));
47474a4d8c2SCharles.Forsyth 				continue;
47574a4d8c2SCharles.Forsyth 			}
47674a4d8c2SCharles.Forsyth 			rgp->cost = change;
47774a4d8c2SCharles.Forsyth 			nregion++;
47874a4d8c2SCharles.Forsyth 			if(nregion >= NRGN) {
47974a4d8c2SCharles.Forsyth 				warn(Z, "too many regions");
48074a4d8c2SCharles.Forsyth 				goto brk;
48174a4d8c2SCharles.Forsyth 			}
48274a4d8c2SCharles.Forsyth 			rgp++;
48374a4d8c2SCharles.Forsyth 		}
48474a4d8c2SCharles.Forsyth 	}
48574a4d8c2SCharles.Forsyth brk:
48674a4d8c2SCharles.Forsyth 	qsort(region, nregion, sizeof(region[0]), rcmp);
48774a4d8c2SCharles.Forsyth 
48874a4d8c2SCharles.Forsyth 	/*
48974a4d8c2SCharles.Forsyth 	 * pass 6
49074a4d8c2SCharles.Forsyth 	 * determine used registers (paint2)
49174a4d8c2SCharles.Forsyth 	 * replace code (paint3)
49274a4d8c2SCharles.Forsyth 	 */
49374a4d8c2SCharles.Forsyth 	rgp = region;
49474a4d8c2SCharles.Forsyth 	for(i=0; i<nregion; i++) {
49574a4d8c2SCharles.Forsyth 		bit = blsh(rgp->varno);
49674a4d8c2SCharles.Forsyth 		vreg = paint2(rgp->enter, rgp->varno);
49774a4d8c2SCharles.Forsyth 		vreg = allreg(vreg, rgp);
49874a4d8c2SCharles.Forsyth 		if(debug['R']) {
49974a4d8c2SCharles.Forsyth 			print("%L$%d %R: %B\n",
50074a4d8c2SCharles.Forsyth 				rgp->enter->prog->lineno,
50174a4d8c2SCharles.Forsyth 				rgp->cost,
50274a4d8c2SCharles.Forsyth 				rgp->regno,
50374a4d8c2SCharles.Forsyth 				bit);
50474a4d8c2SCharles.Forsyth 		}
50574a4d8c2SCharles.Forsyth 		if(rgp->regno != 0)
50674a4d8c2SCharles.Forsyth 			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
50774a4d8c2SCharles.Forsyth 		rgp++;
50874a4d8c2SCharles.Forsyth 	}
50974a4d8c2SCharles.Forsyth 	/*
51074a4d8c2SCharles.Forsyth 	 * pass 7
51174a4d8c2SCharles.Forsyth 	 * peep-hole on basic block
51274a4d8c2SCharles.Forsyth 	 */
51374a4d8c2SCharles.Forsyth 	if(!debug['R'] || debug['P'])
51474a4d8c2SCharles.Forsyth 		peep();
51574a4d8c2SCharles.Forsyth 
51674a4d8c2SCharles.Forsyth 	/*
51774a4d8c2SCharles.Forsyth 	 * pass 8
51874a4d8c2SCharles.Forsyth 	 * recalculate pc
51974a4d8c2SCharles.Forsyth 	 */
52074a4d8c2SCharles.Forsyth 	val = initpc;
52174a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r1) {
52274a4d8c2SCharles.Forsyth 		r->pc = val;
52374a4d8c2SCharles.Forsyth 		p = r->prog;
52474a4d8c2SCharles.Forsyth 		p1 = P;
52574a4d8c2SCharles.Forsyth 		r1 = r->link;
52674a4d8c2SCharles.Forsyth 		if(r1 != R)
52774a4d8c2SCharles.Forsyth 			p1 = r1->prog;
52874a4d8c2SCharles.Forsyth 		for(; p != p1; p = p->link) {
52974a4d8c2SCharles.Forsyth 			switch(p->as) {
53074a4d8c2SCharles.Forsyth 			default:
53174a4d8c2SCharles.Forsyth 				val++;
53274a4d8c2SCharles.Forsyth 				break;
53374a4d8c2SCharles.Forsyth 
53474a4d8c2SCharles.Forsyth 			case ANOP:
53574a4d8c2SCharles.Forsyth 			case ADATA:
53674a4d8c2SCharles.Forsyth 			case AGLOBL:
53774a4d8c2SCharles.Forsyth 			case ANAME:
53874a4d8c2SCharles.Forsyth 			case ASIGNAME:
53974a4d8c2SCharles.Forsyth 				break;
54074a4d8c2SCharles.Forsyth 			}
54174a4d8c2SCharles.Forsyth 		}
54274a4d8c2SCharles.Forsyth 	}
54374a4d8c2SCharles.Forsyth 	pc = val;
54474a4d8c2SCharles.Forsyth 
54574a4d8c2SCharles.Forsyth 	/*
54674a4d8c2SCharles.Forsyth 	 * fix up branches
54774a4d8c2SCharles.Forsyth 	 */
54874a4d8c2SCharles.Forsyth 	if(debug['R'])
54974a4d8c2SCharles.Forsyth 		if(bany(&addrs))
55074a4d8c2SCharles.Forsyth 			print("addrs: %B\n", addrs);
55174a4d8c2SCharles.Forsyth 
55274a4d8c2SCharles.Forsyth 	r1 = 0; /* set */
55374a4d8c2SCharles.Forsyth 	for(r = firstr; r != R; r = r->link) {
55474a4d8c2SCharles.Forsyth 		p = r->prog;
55574a4d8c2SCharles.Forsyth 		if(p->to.type == D_BRANCH)
55674a4d8c2SCharles.Forsyth 			p->to.offset = r->s2->pc;
55774a4d8c2SCharles.Forsyth 		r1 = r;
55874a4d8c2SCharles.Forsyth 	}
55974a4d8c2SCharles.Forsyth 
56074a4d8c2SCharles.Forsyth 	/*
56174a4d8c2SCharles.Forsyth 	 * last pass
56274a4d8c2SCharles.Forsyth 	 * eliminate nops
56374a4d8c2SCharles.Forsyth 	 * free aux structures
56474a4d8c2SCharles.Forsyth 	 */
56574a4d8c2SCharles.Forsyth 	for(p = firstr->prog; p != P; p = p->link){
56674a4d8c2SCharles.Forsyth 		while(p->link && p->link->as == ANOP)
56774a4d8c2SCharles.Forsyth 			p->link = p->link->link;
56874a4d8c2SCharles.Forsyth 	}
56974a4d8c2SCharles.Forsyth 	if(r1 != R) {
57074a4d8c2SCharles.Forsyth 		r1->link = freer;
57174a4d8c2SCharles.Forsyth 		freer = firstr;
57274a4d8c2SCharles.Forsyth 	}
57374a4d8c2SCharles.Forsyth }
57474a4d8c2SCharles.Forsyth 
57574a4d8c2SCharles.Forsyth /*
57674a4d8c2SCharles.Forsyth  * add mov b,rn
57774a4d8c2SCharles.Forsyth  * just after r
57874a4d8c2SCharles.Forsyth  */
57974a4d8c2SCharles.Forsyth void
addmove(Reg * r,int bn,int rn,int f)58074a4d8c2SCharles.Forsyth addmove(Reg *r, int bn, int rn, int f)
58174a4d8c2SCharles.Forsyth {
58274a4d8c2SCharles.Forsyth 	Prog *p, *p1;
58374a4d8c2SCharles.Forsyth 	Adr *a;
58474a4d8c2SCharles.Forsyth 	Var *v;
58574a4d8c2SCharles.Forsyth 
58674a4d8c2SCharles.Forsyth 	p1 = alloc(sizeof(*p1));
58774a4d8c2SCharles.Forsyth 	*p1 = zprog;
58874a4d8c2SCharles.Forsyth 	p = r->prog;
58974a4d8c2SCharles.Forsyth 
59074a4d8c2SCharles.Forsyth 	p1->link = p->link;
59174a4d8c2SCharles.Forsyth 	p->link = p1;
59274a4d8c2SCharles.Forsyth 	p1->lineno = p->lineno;
59374a4d8c2SCharles.Forsyth 
59474a4d8c2SCharles.Forsyth 	v = var + bn;
59574a4d8c2SCharles.Forsyth 
59674a4d8c2SCharles.Forsyth 	a = &p1->to;
59774a4d8c2SCharles.Forsyth 	a->sym = v->sym;
59874a4d8c2SCharles.Forsyth 	a->offset = v->offset;
59974a4d8c2SCharles.Forsyth 	a->etype = v->etype;
60074a4d8c2SCharles.Forsyth 	a->type = v->name;
60174a4d8c2SCharles.Forsyth 
60274a4d8c2SCharles.Forsyth 	p1->as = AMOVL;
60374a4d8c2SCharles.Forsyth 	if(v->etype == TCHAR || v->etype == TUCHAR)
60474a4d8c2SCharles.Forsyth 		p1->as = AMOVB;
60574a4d8c2SCharles.Forsyth 	if(v->etype == TSHORT || v->etype == TUSHORT)
60674a4d8c2SCharles.Forsyth 		p1->as = AMOVW;
60774a4d8c2SCharles.Forsyth 
60874a4d8c2SCharles.Forsyth 	p1->from.type = rn;
60974a4d8c2SCharles.Forsyth 	if(!f) {
61074a4d8c2SCharles.Forsyth 		p1->from = *a;
61174a4d8c2SCharles.Forsyth 		*a = zprog.from;
61274a4d8c2SCharles.Forsyth 		a->type = rn;
61374a4d8c2SCharles.Forsyth 		if(v->etype == TUCHAR)
61474a4d8c2SCharles.Forsyth 			p1->as = AMOVB;
61574a4d8c2SCharles.Forsyth 		if(v->etype == TUSHORT)
61674a4d8c2SCharles.Forsyth 			p1->as = AMOVW;
61774a4d8c2SCharles.Forsyth 	}
61874a4d8c2SCharles.Forsyth 	if(debug['R'])
61974a4d8c2SCharles.Forsyth 		print("%P\t.a%P\n", p, p1);
62074a4d8c2SCharles.Forsyth }
62174a4d8c2SCharles.Forsyth 
62274a4d8c2SCharles.Forsyth ulong
doregbits(int r)62374a4d8c2SCharles.Forsyth doregbits(int r)
62474a4d8c2SCharles.Forsyth {
62574a4d8c2SCharles.Forsyth 	ulong b;
62674a4d8c2SCharles.Forsyth 
62774a4d8c2SCharles.Forsyth 	b = 0;
62874a4d8c2SCharles.Forsyth 	if(r >= D_INDIR)
62974a4d8c2SCharles.Forsyth 		r -= D_INDIR;
63074a4d8c2SCharles.Forsyth 	if(r >= D_AX && r <= D_DI)
63174a4d8c2SCharles.Forsyth 		b |= RtoB(r);
63274a4d8c2SCharles.Forsyth 	else
63374a4d8c2SCharles.Forsyth 	if(r >= D_AL && r <= D_BL)
63474a4d8c2SCharles.Forsyth 		b |= RtoB(r-D_AL+D_AX);
63574a4d8c2SCharles.Forsyth 	else
63674a4d8c2SCharles.Forsyth 	if(r >= D_AH && r <= D_BH)
63774a4d8c2SCharles.Forsyth 		b |= RtoB(r-D_AH+D_AX);
63874a4d8c2SCharles.Forsyth 	return b;
63974a4d8c2SCharles.Forsyth }
64074a4d8c2SCharles.Forsyth 
64174a4d8c2SCharles.Forsyth Bits
mkvar(Reg * r,Adr * a,int isro)642*45a20ab7Sforsyth mkvar(Reg *r, Adr *a, int isro)
64374a4d8c2SCharles.Forsyth {
64474a4d8c2SCharles.Forsyth 	Var *v;
64574a4d8c2SCharles.Forsyth 	int i, t, n, et, z;
64674a4d8c2SCharles.Forsyth 	long o;
64774a4d8c2SCharles.Forsyth 	Bits bit;
64874a4d8c2SCharles.Forsyth 	Sym *s;
64974a4d8c2SCharles.Forsyth 
65074a4d8c2SCharles.Forsyth 	/*
65174a4d8c2SCharles.Forsyth 	 * mark registers used
65274a4d8c2SCharles.Forsyth 	 */
65374a4d8c2SCharles.Forsyth 	t = a->type;
65474a4d8c2SCharles.Forsyth 	r->regu |= doregbits(t);
65574a4d8c2SCharles.Forsyth 	r->regu |= doregbits(a->index);
656*45a20ab7Sforsyth 	et = a->etype;
65774a4d8c2SCharles.Forsyth 
65874a4d8c2SCharles.Forsyth 	switch(t) {
65974a4d8c2SCharles.Forsyth 	default:
66074a4d8c2SCharles.Forsyth 		goto none;
661*45a20ab7Sforsyth 	case D_INDIR+D_GS:
662*45a20ab7Sforsyth 		if(!isro || 1)
663*45a20ab7Sforsyth 			goto none;
664*45a20ab7Sforsyth 		n = t;
665*45a20ab7Sforsyth 		{static Sym er; a->sym = &er;}
666*45a20ab7Sforsyth 		a->sym->name = "$extreg";
667*45a20ab7Sforsyth 		break;
66874a4d8c2SCharles.Forsyth 	case D_ADDR:
66974a4d8c2SCharles.Forsyth 		a->type = a->index;
670*45a20ab7Sforsyth 		bit = mkvar(r, a, 0);
67174a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++)
67274a4d8c2SCharles.Forsyth 			addrs.b[z] |= bit.b[z];
67374a4d8c2SCharles.Forsyth 		a->type = t;
67474a4d8c2SCharles.Forsyth 		goto none;
67574a4d8c2SCharles.Forsyth 	case D_EXTERN:
67674a4d8c2SCharles.Forsyth 	case D_STATIC:
67774a4d8c2SCharles.Forsyth 	case D_PARAM:
67874a4d8c2SCharles.Forsyth 	case D_AUTO:
67974a4d8c2SCharles.Forsyth 		n = t;
68074a4d8c2SCharles.Forsyth 		break;
68174a4d8c2SCharles.Forsyth 	}
68274a4d8c2SCharles.Forsyth 	s = a->sym;
68374a4d8c2SCharles.Forsyth 	if(s == S)
68474a4d8c2SCharles.Forsyth 		goto none;
68574a4d8c2SCharles.Forsyth 	if(s->name[0] == '.')
68674a4d8c2SCharles.Forsyth 		goto none;
68774a4d8c2SCharles.Forsyth 	o = a->offset;
68874a4d8c2SCharles.Forsyth 	v = var;
68974a4d8c2SCharles.Forsyth 	for(i=0; i<nvar; i++) {
69074a4d8c2SCharles.Forsyth 		if(s == v->sym)
69174a4d8c2SCharles.Forsyth 		if(n == v->name)
69274a4d8c2SCharles.Forsyth 		if(o == v->offset)
69374a4d8c2SCharles.Forsyth 			goto out;
69474a4d8c2SCharles.Forsyth 		v++;
69574a4d8c2SCharles.Forsyth 	}
69674a4d8c2SCharles.Forsyth 	if(nvar >= NVAR) {
69774a4d8c2SCharles.Forsyth 		if(debug['w'] > 1 && s)
69874a4d8c2SCharles.Forsyth 			warn(Z, "variable not optimized: %s", s->name);
69974a4d8c2SCharles.Forsyth 		goto none;
70074a4d8c2SCharles.Forsyth 	}
70174a4d8c2SCharles.Forsyth 	i = nvar;
70274a4d8c2SCharles.Forsyth 	nvar++;
70374a4d8c2SCharles.Forsyth 	v = &var[i];
70474a4d8c2SCharles.Forsyth 	v->sym = s;
70574a4d8c2SCharles.Forsyth 	v->offset = o;
70674a4d8c2SCharles.Forsyth 	v->name = n;
70774a4d8c2SCharles.Forsyth 	v->etype = et;
70874a4d8c2SCharles.Forsyth 	if(debug['R'])
70974a4d8c2SCharles.Forsyth 		print("bit=%2d et=%2d %D\n", i, et, a);
71074a4d8c2SCharles.Forsyth 
71174a4d8c2SCharles.Forsyth out:
71274a4d8c2SCharles.Forsyth 	bit = blsh(i);
71374a4d8c2SCharles.Forsyth 	if(n == D_EXTERN || n == D_STATIC)
71474a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++)
71574a4d8c2SCharles.Forsyth 			externs.b[z] |= bit.b[z];
71674a4d8c2SCharles.Forsyth 	if(n == D_PARAM)
71774a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++)
71874a4d8c2SCharles.Forsyth 			params.b[z] |= bit.b[z];
71974a4d8c2SCharles.Forsyth 	if(v->etype != et || !typechlpfd[et])	/* funny punning */
72074a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++)
72174a4d8c2SCharles.Forsyth 			addrs.b[z] |= bit.b[z];
72274a4d8c2SCharles.Forsyth 	return bit;
72374a4d8c2SCharles.Forsyth 
72474a4d8c2SCharles.Forsyth none:
72574a4d8c2SCharles.Forsyth 	return zbits;
72674a4d8c2SCharles.Forsyth }
72774a4d8c2SCharles.Forsyth 
72874a4d8c2SCharles.Forsyth void
prop(Reg * r,Bits ref,Bits cal)72974a4d8c2SCharles.Forsyth prop(Reg *r, Bits ref, Bits cal)
73074a4d8c2SCharles.Forsyth {
73174a4d8c2SCharles.Forsyth 	Reg *r1, *r2;
73274a4d8c2SCharles.Forsyth 	int z;
73374a4d8c2SCharles.Forsyth 
73474a4d8c2SCharles.Forsyth 	for(r1 = r; r1 != R; r1 = r1->p1) {
73574a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++) {
73674a4d8c2SCharles.Forsyth 			ref.b[z] |= r1->refahead.b[z];
73774a4d8c2SCharles.Forsyth 			if(ref.b[z] != r1->refahead.b[z]) {
73874a4d8c2SCharles.Forsyth 				r1->refahead.b[z] = ref.b[z];
73974a4d8c2SCharles.Forsyth 				change++;
74074a4d8c2SCharles.Forsyth 			}
74174a4d8c2SCharles.Forsyth 			cal.b[z] |= r1->calahead.b[z];
74274a4d8c2SCharles.Forsyth 			if(cal.b[z] != r1->calahead.b[z]) {
74374a4d8c2SCharles.Forsyth 				r1->calahead.b[z] = cal.b[z];
74474a4d8c2SCharles.Forsyth 				change++;
74574a4d8c2SCharles.Forsyth 			}
74674a4d8c2SCharles.Forsyth 		}
74774a4d8c2SCharles.Forsyth 		switch(r1->prog->as) {
74874a4d8c2SCharles.Forsyth 		case ACALL:
74974a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++) {
75074a4d8c2SCharles.Forsyth 				cal.b[z] |= ref.b[z] | externs.b[z];
75174a4d8c2SCharles.Forsyth 				ref.b[z] = 0;
75274a4d8c2SCharles.Forsyth 			}
75374a4d8c2SCharles.Forsyth 			break;
75474a4d8c2SCharles.Forsyth 
75574a4d8c2SCharles.Forsyth 		case ATEXT:
75674a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++) {
75774a4d8c2SCharles.Forsyth 				cal.b[z] = 0;
75874a4d8c2SCharles.Forsyth 				ref.b[z] = 0;
75974a4d8c2SCharles.Forsyth 			}
76074a4d8c2SCharles.Forsyth 			break;
76174a4d8c2SCharles.Forsyth 
76274a4d8c2SCharles.Forsyth 		case ARET:
76374a4d8c2SCharles.Forsyth 			for(z=0; z<BITS; z++) {
76474a4d8c2SCharles.Forsyth 				cal.b[z] = externs.b[z];
76574a4d8c2SCharles.Forsyth 				ref.b[z] = 0;
76674a4d8c2SCharles.Forsyth 			}
76774a4d8c2SCharles.Forsyth 		}
76874a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++) {
76974a4d8c2SCharles.Forsyth 			ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
77074a4d8c2SCharles.Forsyth 				r1->use1.b[z] | r1->use2.b[z];
77174a4d8c2SCharles.Forsyth 			cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
77274a4d8c2SCharles.Forsyth 			r1->refbehind.b[z] = ref.b[z];
77374a4d8c2SCharles.Forsyth 			r1->calbehind.b[z] = cal.b[z];
77474a4d8c2SCharles.Forsyth 		}
77574a4d8c2SCharles.Forsyth 		if(r1->active)
77674a4d8c2SCharles.Forsyth 			break;
77774a4d8c2SCharles.Forsyth 		r1->active = 1;
77874a4d8c2SCharles.Forsyth 	}
77974a4d8c2SCharles.Forsyth 	for(; r != r1; r = r->p1)
78074a4d8c2SCharles.Forsyth 		for(r2 = r->p2; r2 != R; r2 = r2->p2link)
78174a4d8c2SCharles.Forsyth 			prop(r2, r->refbehind, r->calbehind);
78274a4d8c2SCharles.Forsyth }
78374a4d8c2SCharles.Forsyth 
78474a4d8c2SCharles.Forsyth /*
78574a4d8c2SCharles.Forsyth  * find looping structure
78674a4d8c2SCharles.Forsyth  *
78774a4d8c2SCharles.Forsyth  * 1) find reverse postordering
78874a4d8c2SCharles.Forsyth  * 2) find approximate dominators,
78974a4d8c2SCharles.Forsyth  *	the actual dominators if the flow graph is reducible
79074a4d8c2SCharles.Forsyth  *	otherwise, dominators plus some other non-dominators.
79174a4d8c2SCharles.Forsyth  *	See Matthew S. Hecht and Jeffrey D. Ullman,
79274a4d8c2SCharles.Forsyth  *	"Analysis of a Simple Algorithm for Global Data Flow Problems",
79374a4d8c2SCharles.Forsyth  *	Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
79474a4d8c2SCharles.Forsyth  *	Oct. 1-3, 1973, pp.  207-217.
79574a4d8c2SCharles.Forsyth  * 3) find all nodes with a predecessor dominated by the current node.
79674a4d8c2SCharles.Forsyth  *	such a node is a loop head.
79774a4d8c2SCharles.Forsyth  *	recursively, all preds with a greater rpo number are in the loop
79874a4d8c2SCharles.Forsyth  */
79974a4d8c2SCharles.Forsyth long
postorder(Reg * r,Reg ** rpo2r,long n)80074a4d8c2SCharles.Forsyth postorder(Reg *r, Reg **rpo2r, long n)
80174a4d8c2SCharles.Forsyth {
80274a4d8c2SCharles.Forsyth 	Reg *r1;
80374a4d8c2SCharles.Forsyth 
80474a4d8c2SCharles.Forsyth 	r->rpo = 1;
80574a4d8c2SCharles.Forsyth 	r1 = r->s1;
80674a4d8c2SCharles.Forsyth 	if(r1 && !r1->rpo)
80774a4d8c2SCharles.Forsyth 		n = postorder(r1, rpo2r, n);
80874a4d8c2SCharles.Forsyth 	r1 = r->s2;
80974a4d8c2SCharles.Forsyth 	if(r1 && !r1->rpo)
81074a4d8c2SCharles.Forsyth 		n = postorder(r1, rpo2r, n);
81174a4d8c2SCharles.Forsyth 	rpo2r[n] = r;
81274a4d8c2SCharles.Forsyth 	n++;
81374a4d8c2SCharles.Forsyth 	return n;
81474a4d8c2SCharles.Forsyth }
81574a4d8c2SCharles.Forsyth 
81674a4d8c2SCharles.Forsyth long
rpolca(long * idom,long rpo1,long rpo2)81774a4d8c2SCharles.Forsyth rpolca(long *idom, long rpo1, long rpo2)
81874a4d8c2SCharles.Forsyth {
81974a4d8c2SCharles.Forsyth 	long t;
82074a4d8c2SCharles.Forsyth 
82174a4d8c2SCharles.Forsyth 	if(rpo1 == -1)
82274a4d8c2SCharles.Forsyth 		return rpo2;
82374a4d8c2SCharles.Forsyth 	while(rpo1 != rpo2){
82474a4d8c2SCharles.Forsyth 		if(rpo1 > rpo2){
82574a4d8c2SCharles.Forsyth 			t = rpo2;
82674a4d8c2SCharles.Forsyth 			rpo2 = rpo1;
82774a4d8c2SCharles.Forsyth 			rpo1 = t;
82874a4d8c2SCharles.Forsyth 		}
82974a4d8c2SCharles.Forsyth 		while(rpo1 < rpo2){
83074a4d8c2SCharles.Forsyth 			t = idom[rpo2];
83174a4d8c2SCharles.Forsyth 			if(t >= rpo2)
83274a4d8c2SCharles.Forsyth 				fatal(Z, "bad idom");
83374a4d8c2SCharles.Forsyth 			rpo2 = t;
83474a4d8c2SCharles.Forsyth 		}
83574a4d8c2SCharles.Forsyth 	}
83674a4d8c2SCharles.Forsyth 	return rpo1;
83774a4d8c2SCharles.Forsyth }
83874a4d8c2SCharles.Forsyth 
83974a4d8c2SCharles.Forsyth int
doms(long * idom,long r,long s)84074a4d8c2SCharles.Forsyth doms(long *idom, long r, long s)
84174a4d8c2SCharles.Forsyth {
84274a4d8c2SCharles.Forsyth 	while(s > r)
84374a4d8c2SCharles.Forsyth 		s = idom[s];
84474a4d8c2SCharles.Forsyth 	return s == r;
84574a4d8c2SCharles.Forsyth }
84674a4d8c2SCharles.Forsyth 
84774a4d8c2SCharles.Forsyth int
loophead(long * idom,Reg * r)84874a4d8c2SCharles.Forsyth loophead(long *idom, Reg *r)
84974a4d8c2SCharles.Forsyth {
85074a4d8c2SCharles.Forsyth 	long src;
85174a4d8c2SCharles.Forsyth 
85274a4d8c2SCharles.Forsyth 	src = r->rpo;
85374a4d8c2SCharles.Forsyth 	if(r->p1 != R && doms(idom, src, r->p1->rpo))
85474a4d8c2SCharles.Forsyth 		return 1;
85574a4d8c2SCharles.Forsyth 	for(r = r->p2; r != R; r = r->p2link)
85674a4d8c2SCharles.Forsyth 		if(doms(idom, src, r->rpo))
85774a4d8c2SCharles.Forsyth 			return 1;
85874a4d8c2SCharles.Forsyth 	return 0;
85974a4d8c2SCharles.Forsyth }
86074a4d8c2SCharles.Forsyth 
86174a4d8c2SCharles.Forsyth void
loopmark(Reg ** rpo2r,long head,Reg * r)86274a4d8c2SCharles.Forsyth loopmark(Reg **rpo2r, long head, Reg *r)
86374a4d8c2SCharles.Forsyth {
86474a4d8c2SCharles.Forsyth 	if(r->rpo < head || r->active == head)
86574a4d8c2SCharles.Forsyth 		return;
86674a4d8c2SCharles.Forsyth 	r->active = head;
86774a4d8c2SCharles.Forsyth 	r->loop += LOOP;
86874a4d8c2SCharles.Forsyth 	if(r->p1 != R)
86974a4d8c2SCharles.Forsyth 		loopmark(rpo2r, head, r->p1);
87074a4d8c2SCharles.Forsyth 	for(r = r->p2; r != R; r = r->p2link)
87174a4d8c2SCharles.Forsyth 		loopmark(rpo2r, head, r);
87274a4d8c2SCharles.Forsyth }
87374a4d8c2SCharles.Forsyth 
87474a4d8c2SCharles.Forsyth void
loopit(Reg * r,long nr)87574a4d8c2SCharles.Forsyth loopit(Reg *r, long nr)
87674a4d8c2SCharles.Forsyth {
87774a4d8c2SCharles.Forsyth 	Reg *r1;
87874a4d8c2SCharles.Forsyth 	long i, d, me;
87974a4d8c2SCharles.Forsyth 
88074a4d8c2SCharles.Forsyth 	if(nr > maxnr) {
88174a4d8c2SCharles.Forsyth 		rpo2r = alloc(nr * sizeof(Reg*));
88274a4d8c2SCharles.Forsyth 		idom = alloc(nr * sizeof(long));
88374a4d8c2SCharles.Forsyth 		maxnr = nr;
88474a4d8c2SCharles.Forsyth 	}
88574a4d8c2SCharles.Forsyth 
88674a4d8c2SCharles.Forsyth 	d = postorder(r, rpo2r, 0);
88774a4d8c2SCharles.Forsyth 	if(d > nr)
88874a4d8c2SCharles.Forsyth 		fatal(Z, "too many reg nodes");
88974a4d8c2SCharles.Forsyth 	nr = d;
89074a4d8c2SCharles.Forsyth 	for(i = 0; i < nr / 2; i++){
89174a4d8c2SCharles.Forsyth 		r1 = rpo2r[i];
89274a4d8c2SCharles.Forsyth 		rpo2r[i] = rpo2r[nr - 1 - i];
89374a4d8c2SCharles.Forsyth 		rpo2r[nr - 1 - i] = r1;
89474a4d8c2SCharles.Forsyth 	}
89574a4d8c2SCharles.Forsyth 	for(i = 0; i < nr; i++)
89674a4d8c2SCharles.Forsyth 		rpo2r[i]->rpo = i;
89774a4d8c2SCharles.Forsyth 
89874a4d8c2SCharles.Forsyth 	idom[0] = 0;
89974a4d8c2SCharles.Forsyth 	for(i = 0; i < nr; i++){
90074a4d8c2SCharles.Forsyth 		r1 = rpo2r[i];
90174a4d8c2SCharles.Forsyth 		me = r1->rpo;
90274a4d8c2SCharles.Forsyth 		d = -1;
90374a4d8c2SCharles.Forsyth 		if(r1->p1 != R && r1->p1->rpo < me)
90474a4d8c2SCharles.Forsyth 			d = r1->p1->rpo;
90574a4d8c2SCharles.Forsyth 		for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
90674a4d8c2SCharles.Forsyth 			if(r1->rpo < me)
90774a4d8c2SCharles.Forsyth 				d = rpolca(idom, d, r1->rpo);
90874a4d8c2SCharles.Forsyth 		idom[i] = d;
90974a4d8c2SCharles.Forsyth 	}
91074a4d8c2SCharles.Forsyth 
91174a4d8c2SCharles.Forsyth 	for(i = 0; i < nr; i++){
91274a4d8c2SCharles.Forsyth 		r1 = rpo2r[i];
91374a4d8c2SCharles.Forsyth 		r1->loop++;
91474a4d8c2SCharles.Forsyth 		if(r1->p2 != R && loophead(idom, r1))
91574a4d8c2SCharles.Forsyth 			loopmark(rpo2r, i, r1);
91674a4d8c2SCharles.Forsyth 	}
91774a4d8c2SCharles.Forsyth }
91874a4d8c2SCharles.Forsyth 
91974a4d8c2SCharles.Forsyth void
synch(Reg * r,Bits dif)92074a4d8c2SCharles.Forsyth synch(Reg *r, Bits dif)
92174a4d8c2SCharles.Forsyth {
92274a4d8c2SCharles.Forsyth 	Reg *r1;
92374a4d8c2SCharles.Forsyth 	int z;
92474a4d8c2SCharles.Forsyth 
92574a4d8c2SCharles.Forsyth 	for(r1 = r; r1 != R; r1 = r1->s1) {
92674a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++) {
92774a4d8c2SCharles.Forsyth 			dif.b[z] = (dif.b[z] &
92874a4d8c2SCharles.Forsyth 				~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
92974a4d8c2SCharles.Forsyth 					r1->set.b[z] | r1->regdiff.b[z];
93074a4d8c2SCharles.Forsyth 			if(dif.b[z] != r1->regdiff.b[z]) {
93174a4d8c2SCharles.Forsyth 				r1->regdiff.b[z] = dif.b[z];
93274a4d8c2SCharles.Forsyth 				change++;
93374a4d8c2SCharles.Forsyth 			}
93474a4d8c2SCharles.Forsyth 		}
93574a4d8c2SCharles.Forsyth 		if(r1->active)
93674a4d8c2SCharles.Forsyth 			break;
93774a4d8c2SCharles.Forsyth 		r1->active = 1;
93874a4d8c2SCharles.Forsyth 		for(z=0; z<BITS; z++)
93974a4d8c2SCharles.Forsyth 			dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
94074a4d8c2SCharles.Forsyth 		if(r1->s2 != R)
94174a4d8c2SCharles.Forsyth 			synch(r1->s2, dif);
94274a4d8c2SCharles.Forsyth 	}
94374a4d8c2SCharles.Forsyth }
94474a4d8c2SCharles.Forsyth 
94574a4d8c2SCharles.Forsyth ulong
allreg(ulong b,Rgn * r)94674a4d8c2SCharles.Forsyth allreg(ulong b, Rgn *r)
94774a4d8c2SCharles.Forsyth {
94874a4d8c2SCharles.Forsyth 	Var *v;
94974a4d8c2SCharles.Forsyth 	int i;
95074a4d8c2SCharles.Forsyth 
95174a4d8c2SCharles.Forsyth 	v = var + r->varno;
95274a4d8c2SCharles.Forsyth 	r->regno = 0;
95374a4d8c2SCharles.Forsyth 	switch(v->etype) {
95474a4d8c2SCharles.Forsyth 
95574a4d8c2SCharles.Forsyth 	default:
95674a4d8c2SCharles.Forsyth 		diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
95774a4d8c2SCharles.Forsyth 		break;
95874a4d8c2SCharles.Forsyth 
95974a4d8c2SCharles.Forsyth 	case TCHAR:
96074a4d8c2SCharles.Forsyth 	case TUCHAR:
96174a4d8c2SCharles.Forsyth 	case TSHORT:
96274a4d8c2SCharles.Forsyth 	case TUSHORT:
96374a4d8c2SCharles.Forsyth 	case TINT:
96474a4d8c2SCharles.Forsyth 	case TUINT:
96574a4d8c2SCharles.Forsyth 	case TLONG:
96674a4d8c2SCharles.Forsyth 	case TULONG:
96774a4d8c2SCharles.Forsyth 	case TIND:
96874a4d8c2SCharles.Forsyth 	case TARRAY:
96974a4d8c2SCharles.Forsyth 		i = BtoR(~b);
97074a4d8c2SCharles.Forsyth 		if(i && r->cost > 0) {
97174a4d8c2SCharles.Forsyth 			r->regno = i;
97274a4d8c2SCharles.Forsyth 			return RtoB(i);
97374a4d8c2SCharles.Forsyth 		}
97474a4d8c2SCharles.Forsyth 		break;
97574a4d8c2SCharles.Forsyth 
97674a4d8c2SCharles.Forsyth 	case TDOUBLE:
97774a4d8c2SCharles.Forsyth 	case TFLOAT:
97874a4d8c2SCharles.Forsyth 		break;
97974a4d8c2SCharles.Forsyth 	}
98074a4d8c2SCharles.Forsyth 	return 0;
98174a4d8c2SCharles.Forsyth }
98274a4d8c2SCharles.Forsyth 
98374a4d8c2SCharles.Forsyth void
paint1(Reg * r,int bn)98474a4d8c2SCharles.Forsyth paint1(Reg *r, int bn)
98574a4d8c2SCharles.Forsyth {
98674a4d8c2SCharles.Forsyth 	Reg *r1;
98774a4d8c2SCharles.Forsyth 	Prog *p;
98874a4d8c2SCharles.Forsyth 	int z;
98974a4d8c2SCharles.Forsyth 	ulong bb;
99074a4d8c2SCharles.Forsyth 
99174a4d8c2SCharles.Forsyth 	z = bn/32;
99274a4d8c2SCharles.Forsyth 	bb = 1L<<(bn%32);
99374a4d8c2SCharles.Forsyth 	if(r->act.b[z] & bb)
99474a4d8c2SCharles.Forsyth 		return;
99574a4d8c2SCharles.Forsyth 	for(;;) {
99674a4d8c2SCharles.Forsyth 		if(!(r->refbehind.b[z] & bb))
99774a4d8c2SCharles.Forsyth 			break;
99874a4d8c2SCharles.Forsyth 		r1 = r->p1;
99974a4d8c2SCharles.Forsyth 		if(r1 == R)
100074a4d8c2SCharles.Forsyth 			break;
100174a4d8c2SCharles.Forsyth 		if(!(r1->refahead.b[z] & bb))
100274a4d8c2SCharles.Forsyth 			break;
100374a4d8c2SCharles.Forsyth 		if(r1->act.b[z] & bb)
100474a4d8c2SCharles.Forsyth 			break;
100574a4d8c2SCharles.Forsyth 		r = r1;
100674a4d8c2SCharles.Forsyth 	}
100774a4d8c2SCharles.Forsyth 
100874a4d8c2SCharles.Forsyth 	if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
100974a4d8c2SCharles.Forsyth 		change -= CLOAD * r->loop;
101074a4d8c2SCharles.Forsyth 		if(debug['R'] && debug['v'])
101174a4d8c2SCharles.Forsyth 			print("%ld%P\tld %B $%d\n", r->loop,
101274a4d8c2SCharles.Forsyth 				r->prog, blsh(bn), change);
101374a4d8c2SCharles.Forsyth 	}
101474a4d8c2SCharles.Forsyth 	for(;;) {
101574a4d8c2SCharles.Forsyth 		r->act.b[z] |= bb;
101674a4d8c2SCharles.Forsyth 		p = r->prog;
101774a4d8c2SCharles.Forsyth 
101874a4d8c2SCharles.Forsyth 		if(r->use1.b[z] & bb) {
101974a4d8c2SCharles.Forsyth 			change += CREF * r->loop;
1020*45a20ab7Sforsyth 			if(p->as == AFMOVL || p->as == AFMOVW)
102174a4d8c2SCharles.Forsyth 				if(BtoR(bb) != D_F0)
102274a4d8c2SCharles.Forsyth 					change = -CINF;
102374a4d8c2SCharles.Forsyth 			if(debug['R'] && debug['v'])
102474a4d8c2SCharles.Forsyth 				print("%ld%P\tu1 %B $%d\n", r->loop,
102574a4d8c2SCharles.Forsyth 					p, blsh(bn), change);
102674a4d8c2SCharles.Forsyth 		}
102774a4d8c2SCharles.Forsyth 
102874a4d8c2SCharles.Forsyth 		if((r->use2.b[z]|r->set.b[z]) & bb) {
102974a4d8c2SCharles.Forsyth 			change += CREF * r->loop;
1030*45a20ab7Sforsyth 			if(p->as == AFMOVL || p->as == AFMOVW)
103174a4d8c2SCharles.Forsyth 				if(BtoR(bb) != D_F0)
103274a4d8c2SCharles.Forsyth 					change = -CINF;
103374a4d8c2SCharles.Forsyth 			if(debug['R'] && debug['v'])
103474a4d8c2SCharles.Forsyth 				print("%ld%P\tu2 %B $%d\n", r->loop,
103574a4d8c2SCharles.Forsyth 					p, blsh(bn), change);
103674a4d8c2SCharles.Forsyth 		}
103774a4d8c2SCharles.Forsyth 
103874a4d8c2SCharles.Forsyth 		if(STORE(r) & r->regdiff.b[z] & bb) {
103974a4d8c2SCharles.Forsyth 			change -= CLOAD * r->loop;
1040*45a20ab7Sforsyth 			if(p->as == AFMOVL || p->as == AFMOVW)
104174a4d8c2SCharles.Forsyth 				if(BtoR(bb) != D_F0)
104274a4d8c2SCharles.Forsyth 					change = -CINF;
104374a4d8c2SCharles.Forsyth 			if(debug['R'] && debug['v'])
104474a4d8c2SCharles.Forsyth 				print("%ld%P\tst %B $%d\n", r->loop,
104574a4d8c2SCharles.Forsyth 					p, blsh(bn), change);
104674a4d8c2SCharles.Forsyth 		}
104774a4d8c2SCharles.Forsyth 
104874a4d8c2SCharles.Forsyth 		if(r->refbehind.b[z] & bb)
104974a4d8c2SCharles.Forsyth 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
105074a4d8c2SCharles.Forsyth 				if(r1->refahead.b[z] & bb)
105174a4d8c2SCharles.Forsyth 					paint1(r1, bn);
105274a4d8c2SCharles.Forsyth 
105374a4d8c2SCharles.Forsyth 		if(!(r->refahead.b[z] & bb))
105474a4d8c2SCharles.Forsyth 			break;
105574a4d8c2SCharles.Forsyth 		r1 = r->s2;
105674a4d8c2SCharles.Forsyth 		if(r1 != R)
105774a4d8c2SCharles.Forsyth 			if(r1->refbehind.b[z] & bb)
105874a4d8c2SCharles.Forsyth 				paint1(r1, bn);
105974a4d8c2SCharles.Forsyth 		r = r->s1;
106074a4d8c2SCharles.Forsyth 		if(r == R)
106174a4d8c2SCharles.Forsyth 			break;
106274a4d8c2SCharles.Forsyth 		if(r->act.b[z] & bb)
106374a4d8c2SCharles.Forsyth 			break;
106474a4d8c2SCharles.Forsyth 		if(!(r->refbehind.b[z] & bb))
106574a4d8c2SCharles.Forsyth 			break;
106674a4d8c2SCharles.Forsyth 	}
106774a4d8c2SCharles.Forsyth }
106874a4d8c2SCharles.Forsyth 
106974a4d8c2SCharles.Forsyth ulong
regset(Reg * r,ulong bb)107074a4d8c2SCharles.Forsyth regset(Reg *r, ulong bb)
107174a4d8c2SCharles.Forsyth {
107274a4d8c2SCharles.Forsyth 	ulong b, set;
107374a4d8c2SCharles.Forsyth 	Adr v;
107474a4d8c2SCharles.Forsyth 	int c;
107574a4d8c2SCharles.Forsyth 
107674a4d8c2SCharles.Forsyth 	set = 0;
107774a4d8c2SCharles.Forsyth 	v = zprog.from;
107874a4d8c2SCharles.Forsyth 	while(b = bb & ~(bb-1)) {
107974a4d8c2SCharles.Forsyth 		v.type = BtoR(b);
108074a4d8c2SCharles.Forsyth 		c = copyu(r->prog, &v, A);
108174a4d8c2SCharles.Forsyth 		if(c == 3)
108274a4d8c2SCharles.Forsyth 			set |= b;
108374a4d8c2SCharles.Forsyth 		bb &= ~b;
108474a4d8c2SCharles.Forsyth 	}
108574a4d8c2SCharles.Forsyth 	return set;
108674a4d8c2SCharles.Forsyth }
108774a4d8c2SCharles.Forsyth 
108874a4d8c2SCharles.Forsyth ulong
reguse(Reg * r,ulong bb)108974a4d8c2SCharles.Forsyth reguse(Reg *r, ulong bb)
109074a4d8c2SCharles.Forsyth {
109174a4d8c2SCharles.Forsyth 	ulong b, set;
109274a4d8c2SCharles.Forsyth 	Adr v;
109374a4d8c2SCharles.Forsyth 	int c;
109474a4d8c2SCharles.Forsyth 
109574a4d8c2SCharles.Forsyth 	set = 0;
109674a4d8c2SCharles.Forsyth 	v = zprog.from;
109774a4d8c2SCharles.Forsyth 	while(b = bb & ~(bb-1)) {
109874a4d8c2SCharles.Forsyth 		v.type = BtoR(b);
109974a4d8c2SCharles.Forsyth 		c = copyu(r->prog, &v, A);
110074a4d8c2SCharles.Forsyth 		if(c == 1 || c == 2 || c == 4)
110174a4d8c2SCharles.Forsyth 			set |= b;
110274a4d8c2SCharles.Forsyth 		bb &= ~b;
110374a4d8c2SCharles.Forsyth 	}
110474a4d8c2SCharles.Forsyth 	return set;
110574a4d8c2SCharles.Forsyth }
110674a4d8c2SCharles.Forsyth 
110774a4d8c2SCharles.Forsyth ulong
paint2(Reg * r,int bn)110874a4d8c2SCharles.Forsyth paint2(Reg *r, int bn)
110974a4d8c2SCharles.Forsyth {
111074a4d8c2SCharles.Forsyth 	Reg *r1;
111174a4d8c2SCharles.Forsyth 	int z;
111274a4d8c2SCharles.Forsyth 	ulong bb, vreg, x;
111374a4d8c2SCharles.Forsyth 
111474a4d8c2SCharles.Forsyth 	z = bn/32;
111574a4d8c2SCharles.Forsyth 	bb = 1L << (bn%32);
111674a4d8c2SCharles.Forsyth 	vreg = regbits;
111774a4d8c2SCharles.Forsyth 	if(!(r->act.b[z] & bb))
111874a4d8c2SCharles.Forsyth 		return vreg;
111974a4d8c2SCharles.Forsyth 	for(;;) {
112074a4d8c2SCharles.Forsyth 		if(!(r->refbehind.b[z] & bb))
112174a4d8c2SCharles.Forsyth 			break;
112274a4d8c2SCharles.Forsyth 		r1 = r->p1;
112374a4d8c2SCharles.Forsyth 		if(r1 == R)
112474a4d8c2SCharles.Forsyth 			break;
112574a4d8c2SCharles.Forsyth 		if(!(r1->refahead.b[z] & bb))
112674a4d8c2SCharles.Forsyth 			break;
112774a4d8c2SCharles.Forsyth 		if(!(r1->act.b[z] & bb))
112874a4d8c2SCharles.Forsyth 			break;
112974a4d8c2SCharles.Forsyth 		r = r1;
113074a4d8c2SCharles.Forsyth 	}
113174a4d8c2SCharles.Forsyth 	for(;;) {
113274a4d8c2SCharles.Forsyth 		r->act.b[z] &= ~bb;
113374a4d8c2SCharles.Forsyth 
113474a4d8c2SCharles.Forsyth 		vreg |= r->regu;
113574a4d8c2SCharles.Forsyth 
113674a4d8c2SCharles.Forsyth 		if(r->refbehind.b[z] & bb)
113774a4d8c2SCharles.Forsyth 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
113874a4d8c2SCharles.Forsyth 				if(r1->refahead.b[z] & bb)
113974a4d8c2SCharles.Forsyth 					vreg |= paint2(r1, bn);
114074a4d8c2SCharles.Forsyth 
114174a4d8c2SCharles.Forsyth 		if(!(r->refahead.b[z] & bb))
114274a4d8c2SCharles.Forsyth 			break;
114374a4d8c2SCharles.Forsyth 		r1 = r->s2;
114474a4d8c2SCharles.Forsyth 		if(r1 != R)
114574a4d8c2SCharles.Forsyth 			if(r1->refbehind.b[z] & bb)
114674a4d8c2SCharles.Forsyth 				vreg |= paint2(r1, bn);
114774a4d8c2SCharles.Forsyth 		r = r->s1;
114874a4d8c2SCharles.Forsyth 		if(r == R)
114974a4d8c2SCharles.Forsyth 			break;
115074a4d8c2SCharles.Forsyth 		if(!(r->act.b[z] & bb))
115174a4d8c2SCharles.Forsyth 			break;
115274a4d8c2SCharles.Forsyth 		if(!(r->refbehind.b[z] & bb))
115374a4d8c2SCharles.Forsyth 			break;
115474a4d8c2SCharles.Forsyth 	}
115574a4d8c2SCharles.Forsyth 
115674a4d8c2SCharles.Forsyth 	bb = vreg;
115774a4d8c2SCharles.Forsyth 	for(; r; r=r->s1) {
115874a4d8c2SCharles.Forsyth 		x = r->regu & ~bb;
115974a4d8c2SCharles.Forsyth 		if(x) {
116074a4d8c2SCharles.Forsyth 			vreg |= reguse(r, x);
116174a4d8c2SCharles.Forsyth 			bb |= regset(r, x);
116274a4d8c2SCharles.Forsyth 		}
116374a4d8c2SCharles.Forsyth 	}
116474a4d8c2SCharles.Forsyth 	return vreg;
116574a4d8c2SCharles.Forsyth }
116674a4d8c2SCharles.Forsyth 
116774a4d8c2SCharles.Forsyth void
paint3(Reg * r,int bn,long rb,int rn)116874a4d8c2SCharles.Forsyth paint3(Reg *r, int bn, long rb, int rn)
116974a4d8c2SCharles.Forsyth {
117074a4d8c2SCharles.Forsyth 	Reg *r1;
117174a4d8c2SCharles.Forsyth 	Prog *p;
117274a4d8c2SCharles.Forsyth 	int z;
117374a4d8c2SCharles.Forsyth 	ulong bb;
117474a4d8c2SCharles.Forsyth 
117574a4d8c2SCharles.Forsyth 	z = bn/32;
117674a4d8c2SCharles.Forsyth 	bb = 1L << (bn%32);
117774a4d8c2SCharles.Forsyth 	if(r->act.b[z] & bb)
117874a4d8c2SCharles.Forsyth 		return;
117974a4d8c2SCharles.Forsyth 	for(;;) {
118074a4d8c2SCharles.Forsyth 		if(!(r->refbehind.b[z] & bb))
118174a4d8c2SCharles.Forsyth 			break;
118274a4d8c2SCharles.Forsyth 		r1 = r->p1;
118374a4d8c2SCharles.Forsyth 		if(r1 == R)
118474a4d8c2SCharles.Forsyth 			break;
118574a4d8c2SCharles.Forsyth 		if(!(r1->refahead.b[z] & bb))
118674a4d8c2SCharles.Forsyth 			break;
118774a4d8c2SCharles.Forsyth 		if(r1->act.b[z] & bb)
118874a4d8c2SCharles.Forsyth 			break;
118974a4d8c2SCharles.Forsyth 		r = r1;
119074a4d8c2SCharles.Forsyth 	}
119174a4d8c2SCharles.Forsyth 
119274a4d8c2SCharles.Forsyth 	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
119374a4d8c2SCharles.Forsyth 		addmove(r, bn, rn, 0);
119474a4d8c2SCharles.Forsyth 	for(;;) {
119574a4d8c2SCharles.Forsyth 		r->act.b[z] |= bb;
119674a4d8c2SCharles.Forsyth 		p = r->prog;
119774a4d8c2SCharles.Forsyth 
119874a4d8c2SCharles.Forsyth 		if(r->use1.b[z] & bb) {
119974a4d8c2SCharles.Forsyth 			if(debug['R'])
120074a4d8c2SCharles.Forsyth 				print("%P", p);
120174a4d8c2SCharles.Forsyth 			addreg(&p->from, rn);
120274a4d8c2SCharles.Forsyth 			if(debug['R'])
120374a4d8c2SCharles.Forsyth 				print("\t.c%P\n", p);
120474a4d8c2SCharles.Forsyth 		}
120574a4d8c2SCharles.Forsyth 		if((r->use2.b[z]|r->set.b[z]) & bb) {
120674a4d8c2SCharles.Forsyth 			if(debug['R'])
120774a4d8c2SCharles.Forsyth 				print("%P", p);
120874a4d8c2SCharles.Forsyth 			addreg(&p->to, rn);
120974a4d8c2SCharles.Forsyth 			if(debug['R'])
121074a4d8c2SCharles.Forsyth 				print("\t.c%P\n", p);
121174a4d8c2SCharles.Forsyth 		}
121274a4d8c2SCharles.Forsyth 
121374a4d8c2SCharles.Forsyth 		if(STORE(r) & r->regdiff.b[z] & bb)
121474a4d8c2SCharles.Forsyth 			addmove(r, bn, rn, 1);
121574a4d8c2SCharles.Forsyth 		r->regu |= rb;
121674a4d8c2SCharles.Forsyth 
121774a4d8c2SCharles.Forsyth 		if(r->refbehind.b[z] & bb)
121874a4d8c2SCharles.Forsyth 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
121974a4d8c2SCharles.Forsyth 				if(r1->refahead.b[z] & bb)
122074a4d8c2SCharles.Forsyth 					paint3(r1, bn, rb, rn);
122174a4d8c2SCharles.Forsyth 
122274a4d8c2SCharles.Forsyth 		if(!(r->refahead.b[z] & bb))
122374a4d8c2SCharles.Forsyth 			break;
122474a4d8c2SCharles.Forsyth 		r1 = r->s2;
122574a4d8c2SCharles.Forsyth 		if(r1 != R)
122674a4d8c2SCharles.Forsyth 			if(r1->refbehind.b[z] & bb)
122774a4d8c2SCharles.Forsyth 				paint3(r1, bn, rb, rn);
122874a4d8c2SCharles.Forsyth 		r = r->s1;
122974a4d8c2SCharles.Forsyth 		if(r == R)
123074a4d8c2SCharles.Forsyth 			break;
123174a4d8c2SCharles.Forsyth 		if(r->act.b[z] & bb)
123274a4d8c2SCharles.Forsyth 			break;
123374a4d8c2SCharles.Forsyth 		if(!(r->refbehind.b[z] & bb))
123474a4d8c2SCharles.Forsyth 			break;
123574a4d8c2SCharles.Forsyth 	}
123674a4d8c2SCharles.Forsyth }
123774a4d8c2SCharles.Forsyth 
123874a4d8c2SCharles.Forsyth void
addreg(Adr * a,int rn)123974a4d8c2SCharles.Forsyth addreg(Adr *a, int rn)
124074a4d8c2SCharles.Forsyth {
124174a4d8c2SCharles.Forsyth 
124274a4d8c2SCharles.Forsyth 	a->sym = 0;
124374a4d8c2SCharles.Forsyth 	a->offset = 0;
124474a4d8c2SCharles.Forsyth 	a->type = rn;
124574a4d8c2SCharles.Forsyth }
124674a4d8c2SCharles.Forsyth 
124774a4d8c2SCharles.Forsyth long
RtoB(int r)124874a4d8c2SCharles.Forsyth RtoB(int r)
124974a4d8c2SCharles.Forsyth {
125074a4d8c2SCharles.Forsyth 
125174a4d8c2SCharles.Forsyth 	if(r < D_AX || r > D_DI)
125274a4d8c2SCharles.Forsyth 		return 0;
125374a4d8c2SCharles.Forsyth 	return 1L << (r-D_AX);
125474a4d8c2SCharles.Forsyth }
125574a4d8c2SCharles.Forsyth 
125674a4d8c2SCharles.Forsyth int
BtoR(long b)125774a4d8c2SCharles.Forsyth BtoR(long b)
125874a4d8c2SCharles.Forsyth {
125974a4d8c2SCharles.Forsyth 
126074a4d8c2SCharles.Forsyth 	b &= 0xffL;
126174a4d8c2SCharles.Forsyth 	if(b == 0)
126274a4d8c2SCharles.Forsyth 		return 0;
126374a4d8c2SCharles.Forsyth 	return bitno(b) + D_AX;
126474a4d8c2SCharles.Forsyth }
1265