xref: /inferno-os/utils/qc/peep.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth void
peep(void)474a4d8c2SCharles.Forsyth peep(void)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth 	Reg *r, *r1, *r2;
774a4d8c2SCharles.Forsyth 	Prog *p, *p1;
874a4d8c2SCharles.Forsyth 	int t;
974a4d8c2SCharles.Forsyth /*
1074a4d8c2SCharles.Forsyth  * complete R structure
1174a4d8c2SCharles.Forsyth  */
1274a4d8c2SCharles.Forsyth 	t = 0;
1374a4d8c2SCharles.Forsyth 	for(r=firstr; r!=R; r=r1) {
1474a4d8c2SCharles.Forsyth 		r1 = r->link;
1574a4d8c2SCharles.Forsyth 		if(r1 == R)
1674a4d8c2SCharles.Forsyth 			break;
1774a4d8c2SCharles.Forsyth 		p = r->prog->link;
1874a4d8c2SCharles.Forsyth 		while(p != r1->prog)
1974a4d8c2SCharles.Forsyth 		switch(p->as) {
2074a4d8c2SCharles.Forsyth 		default:
2174a4d8c2SCharles.Forsyth 			r2 = rega();
2274a4d8c2SCharles.Forsyth 			r->link = r2;
2374a4d8c2SCharles.Forsyth 			r2->link = r1;
2474a4d8c2SCharles.Forsyth 
2574a4d8c2SCharles.Forsyth 			r2->prog = p;
2674a4d8c2SCharles.Forsyth 			r2->p1 = r;
2774a4d8c2SCharles.Forsyth 			r->s1 = r2;
2874a4d8c2SCharles.Forsyth 			r2->s1 = r1;
2974a4d8c2SCharles.Forsyth 			r1->p1 = r2;
3074a4d8c2SCharles.Forsyth 
3174a4d8c2SCharles.Forsyth 			r = r2;
3274a4d8c2SCharles.Forsyth 			t++;
3374a4d8c2SCharles.Forsyth 
3474a4d8c2SCharles.Forsyth 		case ADATA:
3574a4d8c2SCharles.Forsyth 		case AGLOBL:
3674a4d8c2SCharles.Forsyth 		case ANAME:
3774a4d8c2SCharles.Forsyth 		case ASIGNAME:
3874a4d8c2SCharles.Forsyth 			p = p->link;
3974a4d8c2SCharles.Forsyth 		}
4074a4d8c2SCharles.Forsyth 	}
4174a4d8c2SCharles.Forsyth 
4274a4d8c2SCharles.Forsyth loop1:
4374a4d8c2SCharles.Forsyth 	t = 0;
4474a4d8c2SCharles.Forsyth 	for(r=firstr; r!=R; r=r->link) {
4574a4d8c2SCharles.Forsyth 		p = r->prog;
4674a4d8c2SCharles.Forsyth 		if(p->as == AMOVW || p->as == AFMOVS || p->as == AFMOVD)
4774a4d8c2SCharles.Forsyth 		if(regtyp(&p->to)) {
4874a4d8c2SCharles.Forsyth 			if(regtyp(&p->from))
4974a4d8c2SCharles.Forsyth 			if(p->from.type == p->to.type) {
5074a4d8c2SCharles.Forsyth 				if(copyprop(r)) {
5174a4d8c2SCharles.Forsyth 					excise(r);
5274a4d8c2SCharles.Forsyth 					t++;
5374a4d8c2SCharles.Forsyth 				} else
5474a4d8c2SCharles.Forsyth 				if(subprop(r) && copyprop(r)) {
5574a4d8c2SCharles.Forsyth 					excise(r);
5674a4d8c2SCharles.Forsyth 					t++;
5774a4d8c2SCharles.Forsyth 				}
5874a4d8c2SCharles.Forsyth 			}
5974a4d8c2SCharles.Forsyth 			if(regzer(&p->from))
6074a4d8c2SCharles.Forsyth 			if(p->to.type == D_REG) {
6174a4d8c2SCharles.Forsyth 				p->from.type = D_REG;
6274a4d8c2SCharles.Forsyth 				p->from.reg = REGZERO;
6374a4d8c2SCharles.Forsyth 				if(copyprop(r)) {
6474a4d8c2SCharles.Forsyth 					excise(r);
6574a4d8c2SCharles.Forsyth 					t++;
6674a4d8c2SCharles.Forsyth 				} else
6774a4d8c2SCharles.Forsyth 				if(subprop(r) && copyprop(r)) {
6874a4d8c2SCharles.Forsyth 					excise(r);
6974a4d8c2SCharles.Forsyth 					t++;
7074a4d8c2SCharles.Forsyth 				}
7174a4d8c2SCharles.Forsyth 			}
7274a4d8c2SCharles.Forsyth 		}
7374a4d8c2SCharles.Forsyth 	}
7474a4d8c2SCharles.Forsyth 	if(t)
7574a4d8c2SCharles.Forsyth 		goto loop1;
7674a4d8c2SCharles.Forsyth 	/*
7774a4d8c2SCharles.Forsyth 	 * look for MOVB x,R; MOVB R,R
7874a4d8c2SCharles.Forsyth 	 */
7974a4d8c2SCharles.Forsyth 	for(r=firstr; r!=R; r=r->link) {
8074a4d8c2SCharles.Forsyth 		p = r->prog;
8174a4d8c2SCharles.Forsyth 		switch(p->as) {
8274a4d8c2SCharles.Forsyth 		default:
8374a4d8c2SCharles.Forsyth 			continue;
8474a4d8c2SCharles.Forsyth 		case AMOVH:
8574a4d8c2SCharles.Forsyth 		case AMOVHZ:
8674a4d8c2SCharles.Forsyth 		case AMOVB:
8774a4d8c2SCharles.Forsyth 		case AMOVBZ:
8874a4d8c2SCharles.Forsyth 			if(p->to.type != D_REG)
8974a4d8c2SCharles.Forsyth 				continue;
9074a4d8c2SCharles.Forsyth 			break;
9174a4d8c2SCharles.Forsyth 		}
9274a4d8c2SCharles.Forsyth 		r1 = r->link;
9374a4d8c2SCharles.Forsyth 		if(r1 == R)
9474a4d8c2SCharles.Forsyth 			continue;
9574a4d8c2SCharles.Forsyth 		p1 = r1->prog;
9674a4d8c2SCharles.Forsyth 		if(p1->as != p->as)
9774a4d8c2SCharles.Forsyth 			continue;
9874a4d8c2SCharles.Forsyth 		if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
9974a4d8c2SCharles.Forsyth 			continue;
10074a4d8c2SCharles.Forsyth 		if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
10174a4d8c2SCharles.Forsyth 			continue;
10274a4d8c2SCharles.Forsyth 		excise(r1);
10374a4d8c2SCharles.Forsyth 	}
10474a4d8c2SCharles.Forsyth 
10574a4d8c2SCharles.Forsyth 	if(debug['Q'] > 1)
10674a4d8c2SCharles.Forsyth 		return;	/* allow following code improvement to be suppressed */
10774a4d8c2SCharles.Forsyth 
10874a4d8c2SCharles.Forsyth 	/*
10974a4d8c2SCharles.Forsyth 	 * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
11074a4d8c2SCharles.Forsyth 	 * when OP can set condition codes correctly
11174a4d8c2SCharles.Forsyth 	 */
11274a4d8c2SCharles.Forsyth 	for(r=firstr; r!=R; r=r->link) {
11374a4d8c2SCharles.Forsyth 		p = r->prog;
11474a4d8c2SCharles.Forsyth 		switch(p->as) {
11574a4d8c2SCharles.Forsyth 		case ACMP:
11674a4d8c2SCharles.Forsyth 			if(!regzer(&p->to))
11774a4d8c2SCharles.Forsyth 				continue;
11874a4d8c2SCharles.Forsyth 			r1 = r->s1;
11974a4d8c2SCharles.Forsyth 			if(r1 == R)
12074a4d8c2SCharles.Forsyth 				continue;
12174a4d8c2SCharles.Forsyth 			switch(r1->prog->as) {
12274a4d8c2SCharles.Forsyth 			default:
12374a4d8c2SCharles.Forsyth 				continue;
12474a4d8c2SCharles.Forsyth 			case ABCL:
12574a4d8c2SCharles.Forsyth 			case ABC:
12674a4d8c2SCharles.Forsyth 				/* the conditions can be complex and these are currently little used */
12774a4d8c2SCharles.Forsyth 				continue;
12874a4d8c2SCharles.Forsyth 			case ABEQ:
12974a4d8c2SCharles.Forsyth 			case ABGE:
13074a4d8c2SCharles.Forsyth 			case ABGT:
13174a4d8c2SCharles.Forsyth 			case ABLE:
13274a4d8c2SCharles.Forsyth 			case ABLT:
13374a4d8c2SCharles.Forsyth 			case ABNE:
13474a4d8c2SCharles.Forsyth 			case ABVC:
13574a4d8c2SCharles.Forsyth 			case ABVS:
13674a4d8c2SCharles.Forsyth 				break;
13774a4d8c2SCharles.Forsyth 			}
13874a4d8c2SCharles.Forsyth 			r1 = r;
13974a4d8c2SCharles.Forsyth 			do
14074a4d8c2SCharles.Forsyth 				r1 = uniqp(r1);
14174a4d8c2SCharles.Forsyth 			while (r1 != R && r1->prog->as == ANOP);
14274a4d8c2SCharles.Forsyth 			if(r1 == R)
14374a4d8c2SCharles.Forsyth 				continue;
14474a4d8c2SCharles.Forsyth 			p1 = r1->prog;
14574a4d8c2SCharles.Forsyth 			if(p1->to.type != D_REG || p1->to.reg != p->from.reg)
14674a4d8c2SCharles.Forsyth 				continue;
14774a4d8c2SCharles.Forsyth 			switch(p1->as) {
14874a4d8c2SCharles.Forsyth 			case ASUB:
14974a4d8c2SCharles.Forsyth 			case AADD:
15074a4d8c2SCharles.Forsyth 			case AXOR:
15174a4d8c2SCharles.Forsyth 			case AOR:
15274a4d8c2SCharles.Forsyth 				/* irregular instructions */
15374a4d8c2SCharles.Forsyth 				if(p1->from.type == D_CONST)
15474a4d8c2SCharles.Forsyth 					continue;
15574a4d8c2SCharles.Forsyth 				break;
15674a4d8c2SCharles.Forsyth 			}
15774a4d8c2SCharles.Forsyth 			switch(p1->as) {
15874a4d8c2SCharles.Forsyth 			default:
15974a4d8c2SCharles.Forsyth 				continue;
16074a4d8c2SCharles.Forsyth 			case AMOVW:
16174a4d8c2SCharles.Forsyth 				if(p1->from.type != D_REG)
16274a4d8c2SCharles.Forsyth 					continue;
16374a4d8c2SCharles.Forsyth 				continue;
16474a4d8c2SCharles.Forsyth 			case AANDCC:
16574a4d8c2SCharles.Forsyth 			case AANDNCC:
16674a4d8c2SCharles.Forsyth 			case AORCC:
16774a4d8c2SCharles.Forsyth 			case AORNCC:
16874a4d8c2SCharles.Forsyth 			case AXORCC:
16974a4d8c2SCharles.Forsyth 			case ASUBCC:
170d67b7dadSforsyth 			case ASUBECC:
171d67b7dadSforsyth 			case ASUBMECC:
172d67b7dadSforsyth 			case ASUBZECC:
17374a4d8c2SCharles.Forsyth 			case AADDCC:
174d67b7dadSforsyth 			case AADDCCC:
175d67b7dadSforsyth 			case AADDECC:
176d67b7dadSforsyth 			case AADDMECC:
177d67b7dadSforsyth 			case AADDZECC:
178d67b7dadSforsyth 			case ARLWMICC:
179d67b7dadSforsyth 			case ARLWNMCC:
18074a4d8c2SCharles.Forsyth 				t = p1->as;
18174a4d8c2SCharles.Forsyth 				break;
18274a4d8c2SCharles.Forsyth 			/* don't deal with floating point instructions for now */
18374a4d8c2SCharles.Forsyth /*
18474a4d8c2SCharles.Forsyth 			case AFABS:	t = AFABSCC; break;
18574a4d8c2SCharles.Forsyth 			case AFADD:	t = AFADDCC; break;
18674a4d8c2SCharles.Forsyth 			case AFADDS:	t = AFADDSCC; break;
18774a4d8c2SCharles.Forsyth 			case AFCTIW:	t = AFCTIWCC; break;
18874a4d8c2SCharles.Forsyth 			case AFCTIWZ:	t = AFCTIWZCC; break;
18974a4d8c2SCharles.Forsyth 			case AFDIV:	t = AFDIVCC; break;
19074a4d8c2SCharles.Forsyth 			case AFDIVS:	t = AFDIVSCC; break;
19174a4d8c2SCharles.Forsyth 			case AFMADD:	t = AFMADDCC; break;
19274a4d8c2SCharles.Forsyth 			case AFMADDS:	t = AFMADDSCC; break;
19374a4d8c2SCharles.Forsyth 			case AFMOVD:	t = AFMOVDCC; break;
19474a4d8c2SCharles.Forsyth 			case AFMSUB:	t = AFMSUBCC; break;
19574a4d8c2SCharles.Forsyth 			case AFMSUBS:	t = AFMSUBSCC; break;
19674a4d8c2SCharles.Forsyth 			case AFMUL:	t = AFMULCC; break;
19774a4d8c2SCharles.Forsyth 			case AFMULS:	t = AFMULSCC; break;
19874a4d8c2SCharles.Forsyth 			case AFNABS:	t = AFNABSCC; break;
19974a4d8c2SCharles.Forsyth 			case AFNEG:	t = AFNEGCC; break;
20074a4d8c2SCharles.Forsyth 			case AFNMADD:	t = AFNMADDCC; break;
20174a4d8c2SCharles.Forsyth 			case AFNMADDS:	t = AFNMADDSCC; break;
20274a4d8c2SCharles.Forsyth 			case AFNMSUB:	t = AFNMSUBCC; break;
20374a4d8c2SCharles.Forsyth 			case AFNMSUBS:	t = AFNMSUBSCC; break;
20474a4d8c2SCharles.Forsyth 			case AFRSP:	t = AFRSPCC; break;
20574a4d8c2SCharles.Forsyth 			case AFSUB:	t = AFSUBCC; break;
20674a4d8c2SCharles.Forsyth 			case AFSUBS:	t = AFSUBSCC; break;
20774a4d8c2SCharles.Forsyth 			case ACNTLZW:	t = ACNTLZWCC; break;
20874a4d8c2SCharles.Forsyth 			case AMTFSB0:	t = AMTFSB0CC; break;
20974a4d8c2SCharles.Forsyth 			case AMTFSB1:	t = AMTFSB1CC; break;
21074a4d8c2SCharles.Forsyth */
21174a4d8c2SCharles.Forsyth 			case AADD:	t = AADDCC; break;
21274a4d8c2SCharles.Forsyth 			case AADDV:	t = AADDVCC; break;
21374a4d8c2SCharles.Forsyth 			case AADDC:	t = AADDCCC; break;
21474a4d8c2SCharles.Forsyth 			case AADDCV:	t = AADDCVCC; break;
21574a4d8c2SCharles.Forsyth 			case AADDME:	t = AADDMECC; break;
21674a4d8c2SCharles.Forsyth 			case AADDMEV:	t = AADDMEVCC; break;
21774a4d8c2SCharles.Forsyth 			case AADDE:	t = AADDECC; break;
21874a4d8c2SCharles.Forsyth 			case AADDEV:	t = AADDEVCC; break;
21974a4d8c2SCharles.Forsyth 			case AADDZE:	t = AADDZECC; break;
22074a4d8c2SCharles.Forsyth 			case AADDZEV:	t = AADDZEVCC; break;
22174a4d8c2SCharles.Forsyth 			case AAND:	t = AANDCC; break;
22274a4d8c2SCharles.Forsyth 			case AANDN:	t = AANDNCC; break;
22374a4d8c2SCharles.Forsyth 			case ADIVW:	t = ADIVWCC; break;
22474a4d8c2SCharles.Forsyth 			case ADIVWV:	t = ADIVWVCC; break;
22574a4d8c2SCharles.Forsyth 			case ADIVWU:	t = ADIVWUCC; break;
22674a4d8c2SCharles.Forsyth 			case ADIVWUV:	t = ADIVWUVCC; break;
22774a4d8c2SCharles.Forsyth 			case AEQV:	t = AEQVCC; break;
22874a4d8c2SCharles.Forsyth 			case AEXTSB:	t = AEXTSBCC; break;
22974a4d8c2SCharles.Forsyth 			case AEXTSH:	t = AEXTSHCC; break;
23074a4d8c2SCharles.Forsyth 			case AMULHW:	t = AMULHWCC; break;
23174a4d8c2SCharles.Forsyth 			case AMULHWU:	t = AMULHWUCC; break;
23274a4d8c2SCharles.Forsyth 			case AMULLW:	t = AMULLWCC; break;
23374a4d8c2SCharles.Forsyth 			case AMULLWV:	t = AMULLWVCC; break;
23474a4d8c2SCharles.Forsyth 			case ANAND:	t = ANANDCC; break;
23574a4d8c2SCharles.Forsyth 			case ANEG:	t = ANEGCC; break;
23674a4d8c2SCharles.Forsyth 			case ANEGV:	t = ANEGVCC; break;
23774a4d8c2SCharles.Forsyth 			case ANOR:	t = ANORCC; break;
23874a4d8c2SCharles.Forsyth 			case AOR:	t = AORCC; break;
23974a4d8c2SCharles.Forsyth 			case AORN:	t = AORNCC; break;
24074a4d8c2SCharles.Forsyth 			case AREM:	t = AREMCC; break;
24174a4d8c2SCharles.Forsyth 			case AREMV:	t = AREMVCC; break;
24274a4d8c2SCharles.Forsyth 			case AREMU:	t = AREMUCC; break;
24374a4d8c2SCharles.Forsyth 			case AREMUV:	t = AREMUVCC; break;
24474a4d8c2SCharles.Forsyth 			case ARLWMI:	t = ARLWMICC; break;
24574a4d8c2SCharles.Forsyth 			case ARLWNM:	t = ARLWNMCC; break;
24674a4d8c2SCharles.Forsyth 			case ASLW:	t = ASLWCC; break;
24774a4d8c2SCharles.Forsyth 			case ASRAW:	t = ASRAWCC; break;
24874a4d8c2SCharles.Forsyth 			case ASRW:	t = ASRWCC; break;
24974a4d8c2SCharles.Forsyth 			case ASUB:	t = ASUBCC; break;
25074a4d8c2SCharles.Forsyth 			case ASUBV:	t = ASUBVCC; break;
25174a4d8c2SCharles.Forsyth 			case ASUBC:	t = ASUBCCC; break;
25274a4d8c2SCharles.Forsyth 			case ASUBCV:	t = ASUBCVCC; break;
25374a4d8c2SCharles.Forsyth 			case ASUBME:	t = ASUBMECC; break;
25474a4d8c2SCharles.Forsyth 			case ASUBMEV:	t = ASUBMEVCC; break;
25574a4d8c2SCharles.Forsyth 			case ASUBE:	t = ASUBECC; break;
25674a4d8c2SCharles.Forsyth 			case ASUBEV:	t = ASUBEVCC; break;
25774a4d8c2SCharles.Forsyth 			case ASUBZE:	t = ASUBZECC; break;
25874a4d8c2SCharles.Forsyth 			case ASUBZEV:	t = ASUBZEVCC; break;
25974a4d8c2SCharles.Forsyth 			case AXOR:	t = AXORCC; break;
26074a4d8c2SCharles.Forsyth 				break;
26174a4d8c2SCharles.Forsyth 			}
26274a4d8c2SCharles.Forsyth 			if(debug['Q'])
26374a4d8c2SCharles.Forsyth 				print("cmp %P; %P -> ", p1, p);
26474a4d8c2SCharles.Forsyth 			p1->as = t;
26574a4d8c2SCharles.Forsyth 			if(debug['Q'])
26674a4d8c2SCharles.Forsyth 				print("%P\n", p1);
26774a4d8c2SCharles.Forsyth 			excise(r);
26874a4d8c2SCharles.Forsyth 			continue;
26974a4d8c2SCharles.Forsyth 		}
27074a4d8c2SCharles.Forsyth 	}
27174a4d8c2SCharles.Forsyth }
27274a4d8c2SCharles.Forsyth 
27374a4d8c2SCharles.Forsyth void
excise(Reg * r)27474a4d8c2SCharles.Forsyth excise(Reg *r)
27574a4d8c2SCharles.Forsyth {
27674a4d8c2SCharles.Forsyth 	Prog *p;
27774a4d8c2SCharles.Forsyth 
27874a4d8c2SCharles.Forsyth 	p = r->prog;
27974a4d8c2SCharles.Forsyth 	p->as = ANOP;
28074a4d8c2SCharles.Forsyth 	p->from = zprog.from;
281d67b7dadSforsyth 	p->from3 = zprog.from3;
28274a4d8c2SCharles.Forsyth 	p->to = zprog.to;
28374a4d8c2SCharles.Forsyth 	p->reg = zprog.reg; /**/
28474a4d8c2SCharles.Forsyth }
28574a4d8c2SCharles.Forsyth 
28674a4d8c2SCharles.Forsyth Reg*
uniqp(Reg * r)28774a4d8c2SCharles.Forsyth uniqp(Reg *r)
28874a4d8c2SCharles.Forsyth {
28974a4d8c2SCharles.Forsyth 	Reg *r1;
29074a4d8c2SCharles.Forsyth 
29174a4d8c2SCharles.Forsyth 	r1 = r->p1;
29274a4d8c2SCharles.Forsyth 	if(r1 == R) {
29374a4d8c2SCharles.Forsyth 		r1 = r->p2;
29474a4d8c2SCharles.Forsyth 		if(r1 == R || r1->p2link != R)
29574a4d8c2SCharles.Forsyth 			return R;
29674a4d8c2SCharles.Forsyth 	} else
29774a4d8c2SCharles.Forsyth 		if(r->p2 != R)
29874a4d8c2SCharles.Forsyth 			return R;
29974a4d8c2SCharles.Forsyth 	return r1;
30074a4d8c2SCharles.Forsyth }
30174a4d8c2SCharles.Forsyth 
30274a4d8c2SCharles.Forsyth Reg*
uniqs(Reg * r)30374a4d8c2SCharles.Forsyth uniqs(Reg *r)
30474a4d8c2SCharles.Forsyth {
30574a4d8c2SCharles.Forsyth 	Reg *r1;
30674a4d8c2SCharles.Forsyth 
30774a4d8c2SCharles.Forsyth 	r1 = r->s1;
30874a4d8c2SCharles.Forsyth 	if(r1 == R) {
30974a4d8c2SCharles.Forsyth 		r1 = r->s2;
31074a4d8c2SCharles.Forsyth 		if(r1 == R)
31174a4d8c2SCharles.Forsyth 			return R;
31274a4d8c2SCharles.Forsyth 	} else
31374a4d8c2SCharles.Forsyth 		if(r->s2 != R)
31474a4d8c2SCharles.Forsyth 			return R;
31574a4d8c2SCharles.Forsyth 	return r1;
31674a4d8c2SCharles.Forsyth }
31774a4d8c2SCharles.Forsyth 
31874a4d8c2SCharles.Forsyth /*
31974a4d8c2SCharles.Forsyth  * if the system forces R0 to be zero,
32074a4d8c2SCharles.Forsyth  * convert references to $0 to references to R0.
32174a4d8c2SCharles.Forsyth  */
32241858f31Sforsyth int
regzer(Adr * a)32374a4d8c2SCharles.Forsyth regzer(Adr *a)
32474a4d8c2SCharles.Forsyth {
32574a4d8c2SCharles.Forsyth 	if(R0ISZERO) {
32674a4d8c2SCharles.Forsyth 		if(a->type == D_CONST)
32774a4d8c2SCharles.Forsyth 			if(a->sym == S)
32874a4d8c2SCharles.Forsyth 				if(a->offset == 0)
32974a4d8c2SCharles.Forsyth 					return 1;
33074a4d8c2SCharles.Forsyth 		if(a->type == D_REG)
33174a4d8c2SCharles.Forsyth 			if(a->reg == REGZERO)
33274a4d8c2SCharles.Forsyth 				return 1;
33374a4d8c2SCharles.Forsyth 	}
33474a4d8c2SCharles.Forsyth 	return 0;
33574a4d8c2SCharles.Forsyth }
33674a4d8c2SCharles.Forsyth 
33741858f31Sforsyth int
regtyp(Adr * a)33874a4d8c2SCharles.Forsyth regtyp(Adr *a)
33974a4d8c2SCharles.Forsyth {
34074a4d8c2SCharles.Forsyth 
34174a4d8c2SCharles.Forsyth 	if(a->type == D_REG) {
34274a4d8c2SCharles.Forsyth 		if(!R0ISZERO || a->reg != REGZERO)
34374a4d8c2SCharles.Forsyth 			return 1;
34474a4d8c2SCharles.Forsyth 		return 0;
34574a4d8c2SCharles.Forsyth 	}
34674a4d8c2SCharles.Forsyth 	if(a->type == D_FREG)
34774a4d8c2SCharles.Forsyth 		return 1;
34874a4d8c2SCharles.Forsyth 	return 0;
34974a4d8c2SCharles.Forsyth }
35074a4d8c2SCharles.Forsyth 
35174a4d8c2SCharles.Forsyth /*
35274a4d8c2SCharles.Forsyth  * the idea is to substitute
35374a4d8c2SCharles.Forsyth  * one register for another
35474a4d8c2SCharles.Forsyth  * from one MOV to another
35574a4d8c2SCharles.Forsyth  *	MOV	a, R0
35674a4d8c2SCharles.Forsyth  *	ADD	b, R0	/ no use of R1
35774a4d8c2SCharles.Forsyth  *	MOV	R0, R1
35874a4d8c2SCharles.Forsyth  * would be converted to
35974a4d8c2SCharles.Forsyth  *	MOV	a, R1
36074a4d8c2SCharles.Forsyth  *	ADD	b, R1
36174a4d8c2SCharles.Forsyth  *	MOV	R1, R0
36274a4d8c2SCharles.Forsyth  * hopefully, then the former or latter MOV
36374a4d8c2SCharles.Forsyth  * will be eliminated by copy propagation.
36474a4d8c2SCharles.Forsyth  */
36574a4d8c2SCharles.Forsyth int
subprop(Reg * r0)36674a4d8c2SCharles.Forsyth subprop(Reg *r0)
36774a4d8c2SCharles.Forsyth {
36874a4d8c2SCharles.Forsyth 	Prog *p;
36974a4d8c2SCharles.Forsyth 	Adr *v1, *v2;
37074a4d8c2SCharles.Forsyth 	Reg *r;
37174a4d8c2SCharles.Forsyth 	int t;
37274a4d8c2SCharles.Forsyth 
37374a4d8c2SCharles.Forsyth 	p = r0->prog;
37474a4d8c2SCharles.Forsyth 	v1 = &p->from;
37574a4d8c2SCharles.Forsyth 	if(!regtyp(v1))
37674a4d8c2SCharles.Forsyth 		return 0;
37774a4d8c2SCharles.Forsyth 	v2 = &p->to;
37874a4d8c2SCharles.Forsyth 	if(!regtyp(v2))
37974a4d8c2SCharles.Forsyth 		return 0;
38074a4d8c2SCharles.Forsyth 	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
38174a4d8c2SCharles.Forsyth 		if(uniqs(r) == R)
38274a4d8c2SCharles.Forsyth 			break;
38374a4d8c2SCharles.Forsyth 		p = r->prog;
38474a4d8c2SCharles.Forsyth 		switch(p->as) {
38574a4d8c2SCharles.Forsyth 		case ABL:
38674a4d8c2SCharles.Forsyth 			return 0;
38774a4d8c2SCharles.Forsyth 
38874a4d8c2SCharles.Forsyth 		case AADD:
389d67b7dadSforsyth 		case AADDC:
390d67b7dadSforsyth 		case AADDCC:
391d67b7dadSforsyth 		case AADDE:
392d67b7dadSforsyth 		case AADDECC:
39374a4d8c2SCharles.Forsyth 		case ASUB:
394d67b7dadSforsyth 		case ASUBCC:
395d67b7dadSforsyth 		case ASUBC:
396d67b7dadSforsyth 		case ASUBCCC:
397d67b7dadSforsyth 		case ASUBE:
398d67b7dadSforsyth 		case ASUBECC:
39974a4d8c2SCharles.Forsyth 		case ASLW:
400d67b7dadSforsyth 		case ASLWCC:
40174a4d8c2SCharles.Forsyth 		case ASRW:
402d67b7dadSforsyth 		case ASRWCC:
40374a4d8c2SCharles.Forsyth 		case ASRAW:
404d67b7dadSforsyth 		case ASRAWCC:
40574a4d8c2SCharles.Forsyth 		case AOR:
40674a4d8c2SCharles.Forsyth 		case AORCC:
40774a4d8c2SCharles.Forsyth 		case AORN:
40874a4d8c2SCharles.Forsyth 		case AORNCC:
40974a4d8c2SCharles.Forsyth 		case AAND:
41074a4d8c2SCharles.Forsyth 		case AANDCC:
41174a4d8c2SCharles.Forsyth 		case AANDN:
41274a4d8c2SCharles.Forsyth 		case AANDNCC:
41374a4d8c2SCharles.Forsyth 		case ANAND:
41474a4d8c2SCharles.Forsyth 		case ANANDCC:
41574a4d8c2SCharles.Forsyth 		case ANOR:
41674a4d8c2SCharles.Forsyth 		case ANORCC:
41774a4d8c2SCharles.Forsyth 		case AXOR:
41874a4d8c2SCharles.Forsyth 		case AXORCC:
419d67b7dadSforsyth 		case AMULHW:
420d67b7dadSforsyth 		case AMULHWU:
42174a4d8c2SCharles.Forsyth 		case AMULLW:
42274a4d8c2SCharles.Forsyth 		case ADIVW:
42374a4d8c2SCharles.Forsyth 		case ADIVWU:
42474a4d8c2SCharles.Forsyth 		case AREM:
42574a4d8c2SCharles.Forsyth 		case AREMU:
426d67b7dadSforsyth 		case ARLWNM:
427d67b7dadSforsyth 		case ARLWNMCC:
42874a4d8c2SCharles.Forsyth 
42974a4d8c2SCharles.Forsyth 		case AFADD:
43074a4d8c2SCharles.Forsyth 		case AFADDS:
43174a4d8c2SCharles.Forsyth 		case AFSUB:
43274a4d8c2SCharles.Forsyth 		case AFSUBS:
43374a4d8c2SCharles.Forsyth 		case AFMUL:
43474a4d8c2SCharles.Forsyth 		case AFMULS:
43574a4d8c2SCharles.Forsyth 		case AFDIV:
43674a4d8c2SCharles.Forsyth 		case AFDIVS:
43774a4d8c2SCharles.Forsyth 			if(p->to.type == v1->type)
43874a4d8c2SCharles.Forsyth 			if(p->to.reg == v1->reg) {
43974a4d8c2SCharles.Forsyth 				if(p->reg == NREG)
44074a4d8c2SCharles.Forsyth 					p->reg = p->to.reg;
44174a4d8c2SCharles.Forsyth 				goto gotit;
44274a4d8c2SCharles.Forsyth 			}
44374a4d8c2SCharles.Forsyth 			break;
44474a4d8c2SCharles.Forsyth 
445d67b7dadSforsyth 		case AADDME:
446d67b7dadSforsyth 		case AADDMECC:
447d67b7dadSforsyth 		case AADDZE:
448d67b7dadSforsyth 		case AADDZECC:
449d67b7dadSforsyth 		case ASUBME:
450d67b7dadSforsyth 		case ASUBMECC:
451d67b7dadSforsyth 		case ASUBZE:
452d67b7dadSforsyth 		case ASUBZECC:
453d67b7dadSforsyth 		case ANEG:
454d67b7dadSforsyth 		case ANEGCC:
455d67b7dadSforsyth 		case AFNEG:
456d67b7dadSforsyth 		case AFNEGCC:
45774a4d8c2SCharles.Forsyth 		case AFMOVS:
45874a4d8c2SCharles.Forsyth 		case AFMOVD:
45974a4d8c2SCharles.Forsyth 		case AMOVW:
46074a4d8c2SCharles.Forsyth 			if(p->to.type == v1->type)
46174a4d8c2SCharles.Forsyth 			if(p->to.reg == v1->reg)
46274a4d8c2SCharles.Forsyth 				goto gotit;
46374a4d8c2SCharles.Forsyth 			break;
46474a4d8c2SCharles.Forsyth 		}
46574a4d8c2SCharles.Forsyth 		if(copyau(&p->from, v2) ||
46674a4d8c2SCharles.Forsyth 		   copyau1(p, v2) ||
46774a4d8c2SCharles.Forsyth 		   copyau(&p->to, v2))
46874a4d8c2SCharles.Forsyth 			break;
46974a4d8c2SCharles.Forsyth 		if(copysub(&p->from, v1, v2, 0) ||
47074a4d8c2SCharles.Forsyth 		   copysub1(p, v1, v2, 0) ||
47174a4d8c2SCharles.Forsyth 		   copysub(&p->to, v1, v2, 0))
47274a4d8c2SCharles.Forsyth 			break;
47374a4d8c2SCharles.Forsyth 	}
47474a4d8c2SCharles.Forsyth 	return 0;
47574a4d8c2SCharles.Forsyth 
47674a4d8c2SCharles.Forsyth gotit:
47774a4d8c2SCharles.Forsyth 	copysub(&p->to, v1, v2, 1);
47874a4d8c2SCharles.Forsyth 	if(debug['P']) {
47974a4d8c2SCharles.Forsyth 		print("gotit: %D->%D\n%P", v1, v2, r->prog);
48074a4d8c2SCharles.Forsyth 		if(p->from.type == v2->type)
48174a4d8c2SCharles.Forsyth 			print(" excise");
48274a4d8c2SCharles.Forsyth 		print("\n");
48374a4d8c2SCharles.Forsyth 	}
48474a4d8c2SCharles.Forsyth 	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
48574a4d8c2SCharles.Forsyth 		p = r->prog;
48674a4d8c2SCharles.Forsyth 		copysub(&p->from, v1, v2, 1);
48774a4d8c2SCharles.Forsyth 		copysub1(p, v1, v2, 1);
48874a4d8c2SCharles.Forsyth 		copysub(&p->to, v1, v2, 1);
48974a4d8c2SCharles.Forsyth 		if(debug['P'])
49074a4d8c2SCharles.Forsyth 			print("%P\n", r->prog);
49174a4d8c2SCharles.Forsyth 	}
49274a4d8c2SCharles.Forsyth 	t = v1->reg;
49374a4d8c2SCharles.Forsyth 	v1->reg = v2->reg;
49474a4d8c2SCharles.Forsyth 	v2->reg = t;
49574a4d8c2SCharles.Forsyth 	if(debug['P'])
49674a4d8c2SCharles.Forsyth 		print("%P last\n", r->prog);
49774a4d8c2SCharles.Forsyth 	return 1;
49874a4d8c2SCharles.Forsyth }
49974a4d8c2SCharles.Forsyth 
50074a4d8c2SCharles.Forsyth /*
50174a4d8c2SCharles.Forsyth  * The idea is to remove redundant copies.
50274a4d8c2SCharles.Forsyth  *	v1->v2	F=0
50374a4d8c2SCharles.Forsyth  *	(use v2	s/v2/v1/)*
50474a4d8c2SCharles.Forsyth  *	set v1	F=1
50574a4d8c2SCharles.Forsyth  *	use v2	return fail
50674a4d8c2SCharles.Forsyth  *	-----------------
50774a4d8c2SCharles.Forsyth  *	v1->v2	F=0
50874a4d8c2SCharles.Forsyth  *	(use v2	s/v2/v1/)*
50974a4d8c2SCharles.Forsyth  *	set v1	F=1
51074a4d8c2SCharles.Forsyth  *	set v2	return success
51174a4d8c2SCharles.Forsyth  */
51274a4d8c2SCharles.Forsyth int
copyprop(Reg * r0)51374a4d8c2SCharles.Forsyth copyprop(Reg *r0)
51474a4d8c2SCharles.Forsyth {
51574a4d8c2SCharles.Forsyth 	Prog *p;
51674a4d8c2SCharles.Forsyth 	Adr *v1, *v2;
51774a4d8c2SCharles.Forsyth 	Reg *r;
51874a4d8c2SCharles.Forsyth 
51974a4d8c2SCharles.Forsyth 	p = r0->prog;
52074a4d8c2SCharles.Forsyth 	v1 = &p->from;
52174a4d8c2SCharles.Forsyth 	v2 = &p->to;
52274a4d8c2SCharles.Forsyth 	if(copyas(v1, v2))
52374a4d8c2SCharles.Forsyth 		return 1;
52474a4d8c2SCharles.Forsyth 	for(r=firstr; r!=R; r=r->link)
52574a4d8c2SCharles.Forsyth 		r->active = 0;
52674a4d8c2SCharles.Forsyth 	return copy1(v1, v2, r0->s1, 0);
52774a4d8c2SCharles.Forsyth }
52874a4d8c2SCharles.Forsyth 
52941858f31Sforsyth int
copy1(Adr * v1,Adr * v2,Reg * r,int f)53074a4d8c2SCharles.Forsyth copy1(Adr *v1, Adr *v2, Reg *r, int f)
53174a4d8c2SCharles.Forsyth {
53274a4d8c2SCharles.Forsyth 	int t;
53374a4d8c2SCharles.Forsyth 	Prog *p;
53474a4d8c2SCharles.Forsyth 
53574a4d8c2SCharles.Forsyth 	if(r->active) {
53674a4d8c2SCharles.Forsyth 		if(debug['P'])
53774a4d8c2SCharles.Forsyth 			print("act set; return 1\n");
53874a4d8c2SCharles.Forsyth 		return 1;
53974a4d8c2SCharles.Forsyth 	}
54074a4d8c2SCharles.Forsyth 	r->active = 1;
54174a4d8c2SCharles.Forsyth 	if(debug['P'])
54274a4d8c2SCharles.Forsyth 		print("copy %D->%D f=%d\n", v1, v2, f);
54374a4d8c2SCharles.Forsyth 	for(; r != R; r = r->s1) {
54474a4d8c2SCharles.Forsyth 		p = r->prog;
54574a4d8c2SCharles.Forsyth 		if(debug['P'])
54674a4d8c2SCharles.Forsyth 			print("%P", p);
54774a4d8c2SCharles.Forsyth 		if(!f && uniqp(r) == R) {
54874a4d8c2SCharles.Forsyth 			f = 1;
54974a4d8c2SCharles.Forsyth 			if(debug['P'])
55074a4d8c2SCharles.Forsyth 				print("; merge; f=%d", f);
55174a4d8c2SCharles.Forsyth 		}
55274a4d8c2SCharles.Forsyth 		t = copyu(p, v2, A);
55374a4d8c2SCharles.Forsyth 		switch(t) {
55474a4d8c2SCharles.Forsyth 		case 2:	/* rar, cant split */
55574a4d8c2SCharles.Forsyth 			if(debug['P'])
55674a4d8c2SCharles.Forsyth 				print("; %Drar; return 0\n", v2);
55774a4d8c2SCharles.Forsyth 			return 0;
55874a4d8c2SCharles.Forsyth 
55974a4d8c2SCharles.Forsyth 		case 3:	/* set */
56074a4d8c2SCharles.Forsyth 			if(debug['P'])
56174a4d8c2SCharles.Forsyth 				print("; %Dset; return 1\n", v2);
56274a4d8c2SCharles.Forsyth 			return 1;
56374a4d8c2SCharles.Forsyth 
56474a4d8c2SCharles.Forsyth 		case 1:	/* used, substitute */
56574a4d8c2SCharles.Forsyth 		case 4:	/* use and set */
56674a4d8c2SCharles.Forsyth 			if(f) {
56774a4d8c2SCharles.Forsyth 				if(!debug['P'])
56874a4d8c2SCharles.Forsyth 					return 0;
56974a4d8c2SCharles.Forsyth 				if(t == 4)
57074a4d8c2SCharles.Forsyth 					print("; %Dused+set and f=%d; return 0\n", v2, f);
57174a4d8c2SCharles.Forsyth 				else
57274a4d8c2SCharles.Forsyth 					print("; %Dused and f=%d; return 0\n", v2, f);
57374a4d8c2SCharles.Forsyth 				return 0;
57474a4d8c2SCharles.Forsyth 			}
57574a4d8c2SCharles.Forsyth 			if(copyu(p, v2, v1)) {
57674a4d8c2SCharles.Forsyth 				if(debug['P'])
57774a4d8c2SCharles.Forsyth 					print("; sub fail; return 0\n");
57874a4d8c2SCharles.Forsyth 				return 0;
57974a4d8c2SCharles.Forsyth 			}
58074a4d8c2SCharles.Forsyth 			if(debug['P'])
58174a4d8c2SCharles.Forsyth 				print("; sub%D/%D", v2, v1);
58274a4d8c2SCharles.Forsyth 			if(t == 4) {
58374a4d8c2SCharles.Forsyth 				if(debug['P'])
58474a4d8c2SCharles.Forsyth 					print("; %Dused+set; return 1\n", v2);
58574a4d8c2SCharles.Forsyth 				return 1;
58674a4d8c2SCharles.Forsyth 			}
58774a4d8c2SCharles.Forsyth 			break;
58874a4d8c2SCharles.Forsyth 		}
58974a4d8c2SCharles.Forsyth 		if(!f) {
59074a4d8c2SCharles.Forsyth 			t = copyu(p, v1, A);
59174a4d8c2SCharles.Forsyth 			if(!f && (t == 2 || t == 3 || t == 4)) {
59274a4d8c2SCharles.Forsyth 				f = 1;
59374a4d8c2SCharles.Forsyth 				if(debug['P'])
59474a4d8c2SCharles.Forsyth 					print("; %Dset and !f; f=%d", v1, f);
59574a4d8c2SCharles.Forsyth 			}
59674a4d8c2SCharles.Forsyth 		}
59774a4d8c2SCharles.Forsyth 		if(debug['P'])
59874a4d8c2SCharles.Forsyth 			print("\n");
59974a4d8c2SCharles.Forsyth 		if(r->s2)
60074a4d8c2SCharles.Forsyth 			if(!copy1(v1, v2, r->s2, f))
60174a4d8c2SCharles.Forsyth 				return 0;
60274a4d8c2SCharles.Forsyth 	}
60374a4d8c2SCharles.Forsyth 	return 1;
60474a4d8c2SCharles.Forsyth }
60574a4d8c2SCharles.Forsyth 
60674a4d8c2SCharles.Forsyth /*
60774a4d8c2SCharles.Forsyth  * return
60874a4d8c2SCharles.Forsyth  * 1 if v only used (and substitute),
60974a4d8c2SCharles.Forsyth  * 2 if read-alter-rewrite
61074a4d8c2SCharles.Forsyth  * 3 if set
61174a4d8c2SCharles.Forsyth  * 4 if set and used
61274a4d8c2SCharles.Forsyth  * 0 otherwise (not touched)
61374a4d8c2SCharles.Forsyth  */
61474a4d8c2SCharles.Forsyth int
copyu(Prog * p,Adr * v,Adr * s)61574a4d8c2SCharles.Forsyth copyu(Prog *p, Adr *v, Adr *s)
61674a4d8c2SCharles.Forsyth {
61774a4d8c2SCharles.Forsyth 
61874a4d8c2SCharles.Forsyth 	switch(p->as) {
61974a4d8c2SCharles.Forsyth 
62074a4d8c2SCharles.Forsyth 	default:
62174a4d8c2SCharles.Forsyth 		if(debug['P'])
622ed422d4bSforsyth 			print(" (?)");
62374a4d8c2SCharles.Forsyth 		return 2;
62474a4d8c2SCharles.Forsyth 
62574a4d8c2SCharles.Forsyth 	case ANOP:	/* read, write */
62674a4d8c2SCharles.Forsyth 	case AMOVW:
62774a4d8c2SCharles.Forsyth 	case AMOVH:
62874a4d8c2SCharles.Forsyth 	case AMOVHZ:
62974a4d8c2SCharles.Forsyth 	case AMOVB:
63074a4d8c2SCharles.Forsyth 	case AMOVBZ:
63174a4d8c2SCharles.Forsyth 
63274a4d8c2SCharles.Forsyth 	case ANEG:
63374a4d8c2SCharles.Forsyth 	case ANEGCC:
634d67b7dadSforsyth 	case AADDME:
635d67b7dadSforsyth 	case AADDMECC:
636d67b7dadSforsyth 	case AADDZE:
637d67b7dadSforsyth 	case AADDZECC:
638d67b7dadSforsyth 	case ASUBME:
639d67b7dadSforsyth 	case ASUBMECC:
640d67b7dadSforsyth 	case ASUBZE:
641d67b7dadSforsyth 	case ASUBZECC:
64274a4d8c2SCharles.Forsyth 
64374a4d8c2SCharles.Forsyth 	case AFCTIW:
64474a4d8c2SCharles.Forsyth 	case AFCTIWZ:
64574a4d8c2SCharles.Forsyth 	case AFMOVS:
64674a4d8c2SCharles.Forsyth 	case AFMOVD:
64774a4d8c2SCharles.Forsyth 	case AFRSP:
64874a4d8c2SCharles.Forsyth 	case AFNEG:
64974a4d8c2SCharles.Forsyth 	case AFNEGCC:
65074a4d8c2SCharles.Forsyth 		if(s != A) {
65174a4d8c2SCharles.Forsyth 			if(copysub(&p->from, v, s, 1))
65274a4d8c2SCharles.Forsyth 				return 1;
65374a4d8c2SCharles.Forsyth 			if(!copyas(&p->to, v))
65474a4d8c2SCharles.Forsyth 				if(copysub(&p->to, v, s, 1))
65574a4d8c2SCharles.Forsyth 					return 1;
65674a4d8c2SCharles.Forsyth 			return 0;
65774a4d8c2SCharles.Forsyth 		}
65874a4d8c2SCharles.Forsyth 		if(copyas(&p->to, v)) {
65974a4d8c2SCharles.Forsyth 			if(copyau(&p->from, v))
66074a4d8c2SCharles.Forsyth 				return 4;
66174a4d8c2SCharles.Forsyth 			return 3;
66274a4d8c2SCharles.Forsyth 		}
66374a4d8c2SCharles.Forsyth 		if(copyau(&p->from, v))
66474a4d8c2SCharles.Forsyth 			return 1;
66574a4d8c2SCharles.Forsyth 		if(copyau(&p->to, v))
66674a4d8c2SCharles.Forsyth 			return 1;
66774a4d8c2SCharles.Forsyth 		return 0;
66874a4d8c2SCharles.Forsyth 
669*45a20ab7Sforsyth 	case ARLWMI:	/* read read rar */
670*45a20ab7Sforsyth 	case ARLWMICC:
671*45a20ab7Sforsyth 		if(copyas(&p->to, v))
672*45a20ab7Sforsyth 			return 2;
673*45a20ab7Sforsyth 		/* fall through */
674*45a20ab7Sforsyth 
67574a4d8c2SCharles.Forsyth 	case AADD:	/* read read write */
676d67b7dadSforsyth 	case AADDC:
677d67b7dadSforsyth 	case AADDE:
67874a4d8c2SCharles.Forsyth 	case ASUB:
67974a4d8c2SCharles.Forsyth 	case ASLW:
68074a4d8c2SCharles.Forsyth 	case ASRW:
68174a4d8c2SCharles.Forsyth 	case ASRAW:
68274a4d8c2SCharles.Forsyth 	case AOR:
68374a4d8c2SCharles.Forsyth 	case AORCC:
68474a4d8c2SCharles.Forsyth 	case AORN:
68574a4d8c2SCharles.Forsyth 	case AORNCC:
68674a4d8c2SCharles.Forsyth 	case AAND:
68774a4d8c2SCharles.Forsyth 	case AANDCC:
68874a4d8c2SCharles.Forsyth 	case AANDN:
68974a4d8c2SCharles.Forsyth 	case AANDNCC:
69074a4d8c2SCharles.Forsyth 	case ANAND:
69174a4d8c2SCharles.Forsyth 	case ANANDCC:
69274a4d8c2SCharles.Forsyth 	case ANOR:
69374a4d8c2SCharles.Forsyth 	case ANORCC:
69474a4d8c2SCharles.Forsyth 	case AXOR:
695d67b7dadSforsyth 	case AMULHW:
696d67b7dadSforsyth 	case AMULHWU:
69774a4d8c2SCharles.Forsyth 	case AMULLW:
69874a4d8c2SCharles.Forsyth 	case ADIVW:
69974a4d8c2SCharles.Forsyth 	case ADIVWU:
70074a4d8c2SCharles.Forsyth 	case AREM:
70174a4d8c2SCharles.Forsyth 	case AREMU:
702d67b7dadSforsyth 	case ARLWNM:
703d67b7dadSforsyth 	case ARLWNMCC:
70474a4d8c2SCharles.Forsyth 
70574a4d8c2SCharles.Forsyth 	case AFADDS:
70674a4d8c2SCharles.Forsyth 	case AFADD:
70774a4d8c2SCharles.Forsyth 	case AFSUBS:
70874a4d8c2SCharles.Forsyth 	case AFSUB:
70974a4d8c2SCharles.Forsyth 	case AFMULS:
71074a4d8c2SCharles.Forsyth 	case AFMUL:
71174a4d8c2SCharles.Forsyth 	case AFDIVS:
71274a4d8c2SCharles.Forsyth 	case AFDIV:
71374a4d8c2SCharles.Forsyth 		if(s != A) {
71474a4d8c2SCharles.Forsyth 			if(copysub(&p->from, v, s, 1))
71574a4d8c2SCharles.Forsyth 				return 1;
71674a4d8c2SCharles.Forsyth 			if(copysub1(p, v, s, 1))
71774a4d8c2SCharles.Forsyth 				return 1;
71874a4d8c2SCharles.Forsyth 			if(!copyas(&p->to, v))
71974a4d8c2SCharles.Forsyth 				if(copysub(&p->to, v, s, 1))
72074a4d8c2SCharles.Forsyth 					return 1;
72174a4d8c2SCharles.Forsyth 			return 0;
72274a4d8c2SCharles.Forsyth 		}
72374a4d8c2SCharles.Forsyth 		if(copyas(&p->to, v)) {
72474a4d8c2SCharles.Forsyth 			if(p->reg == NREG)
72574a4d8c2SCharles.Forsyth 				p->reg = p->to.reg;
72674a4d8c2SCharles.Forsyth 			if(copyau(&p->from, v))
72774a4d8c2SCharles.Forsyth 				return 4;
72874a4d8c2SCharles.Forsyth 			if(copyau1(p, v))
72974a4d8c2SCharles.Forsyth 				return 4;
73074a4d8c2SCharles.Forsyth 			return 3;
73174a4d8c2SCharles.Forsyth 		}
73274a4d8c2SCharles.Forsyth 		if(copyau(&p->from, v))
73374a4d8c2SCharles.Forsyth 			return 1;
73474a4d8c2SCharles.Forsyth 		if(copyau1(p, v))
73574a4d8c2SCharles.Forsyth 			return 1;
73674a4d8c2SCharles.Forsyth 		if(copyau(&p->to, v))
73774a4d8c2SCharles.Forsyth 			return 1;
73874a4d8c2SCharles.Forsyth 		return 0;
73974a4d8c2SCharles.Forsyth 
74074a4d8c2SCharles.Forsyth 	case ABEQ:
74174a4d8c2SCharles.Forsyth 	case ABGT:
74274a4d8c2SCharles.Forsyth 	case ABGE:
74374a4d8c2SCharles.Forsyth 	case ABLT:
74474a4d8c2SCharles.Forsyth 	case ABLE:
74574a4d8c2SCharles.Forsyth 	case ABNE:
74674a4d8c2SCharles.Forsyth 	case ABVC:
74774a4d8c2SCharles.Forsyth 	case ABVS:
74874a4d8c2SCharles.Forsyth 		break;
74974a4d8c2SCharles.Forsyth 
75074a4d8c2SCharles.Forsyth 	case ACMP:	/* read read */
75174a4d8c2SCharles.Forsyth 	case ACMPU:
75274a4d8c2SCharles.Forsyth 	case AFCMPO:
75374a4d8c2SCharles.Forsyth 	case AFCMPU:
75474a4d8c2SCharles.Forsyth 		if(s != A) {
75574a4d8c2SCharles.Forsyth 			if(copysub(&p->from, v, s, 1))
75674a4d8c2SCharles.Forsyth 				return 1;
75774a4d8c2SCharles.Forsyth 			return copysub(&p->to, v, s, 1);
75874a4d8c2SCharles.Forsyth 		}
75974a4d8c2SCharles.Forsyth 		if(copyau(&p->from, v))
76074a4d8c2SCharles.Forsyth 			return 1;
76174a4d8c2SCharles.Forsyth 		if(copyau(&p->to, v))
76274a4d8c2SCharles.Forsyth 			return 1;
76374a4d8c2SCharles.Forsyth 		break;
76474a4d8c2SCharles.Forsyth 
76574a4d8c2SCharles.Forsyth 	case ABR:	/* funny */
76674a4d8c2SCharles.Forsyth 		if(s != A) {
76774a4d8c2SCharles.Forsyth 			if(copysub(&p->to, v, s, 1))
76874a4d8c2SCharles.Forsyth 				return 1;
76974a4d8c2SCharles.Forsyth 			return 0;
77074a4d8c2SCharles.Forsyth 		}
77174a4d8c2SCharles.Forsyth 		if(copyau(&p->to, v))
77274a4d8c2SCharles.Forsyth 			return 1;
77374a4d8c2SCharles.Forsyth 		return 0;
77474a4d8c2SCharles.Forsyth 
77574a4d8c2SCharles.Forsyth 	case ARETURN:	/* funny */
77674a4d8c2SCharles.Forsyth 		if(v->type == D_REG)
77774a4d8c2SCharles.Forsyth 			if(v->reg == REGRET)
77874a4d8c2SCharles.Forsyth 				return 2;
77974a4d8c2SCharles.Forsyth 		if(v->type == D_FREG)
78074a4d8c2SCharles.Forsyth 			if(v->reg == FREGRET)
78174a4d8c2SCharles.Forsyth 				return 2;
78274a4d8c2SCharles.Forsyth 
78374a4d8c2SCharles.Forsyth 	case ABL:	/* funny */
78474a4d8c2SCharles.Forsyth 		if(v->type == D_REG) {
78574a4d8c2SCharles.Forsyth 			if(v->reg <= REGEXT && v->reg > exregoffset)
78674a4d8c2SCharles.Forsyth 				return 2;
78774a4d8c2SCharles.Forsyth 			if(v->reg == REGARG)
78874a4d8c2SCharles.Forsyth 				return 2;
78974a4d8c2SCharles.Forsyth 		}
79074a4d8c2SCharles.Forsyth 		if(v->type == D_FREG) {
79174a4d8c2SCharles.Forsyth 			if(v->reg <= FREGEXT && v->reg > exfregoffset)
79274a4d8c2SCharles.Forsyth 				return 2;
79374a4d8c2SCharles.Forsyth 		}
79474a4d8c2SCharles.Forsyth 
79574a4d8c2SCharles.Forsyth 		if(s != A) {
79674a4d8c2SCharles.Forsyth 			if(copysub(&p->to, v, s, 1))
79774a4d8c2SCharles.Forsyth 				return 1;
79874a4d8c2SCharles.Forsyth 			return 0;
79974a4d8c2SCharles.Forsyth 		}
80074a4d8c2SCharles.Forsyth 		if(copyau(&p->to, v))
80174a4d8c2SCharles.Forsyth 			return 4;
80274a4d8c2SCharles.Forsyth 		return 3;
80374a4d8c2SCharles.Forsyth 
80474a4d8c2SCharles.Forsyth 	case ATEXT:	/* funny */
80574a4d8c2SCharles.Forsyth 		if(v->type == D_REG)
80674a4d8c2SCharles.Forsyth 			if(v->reg == REGARG)
80774a4d8c2SCharles.Forsyth 				return 3;
80874a4d8c2SCharles.Forsyth 		return 0;
80974a4d8c2SCharles.Forsyth 	}
81074a4d8c2SCharles.Forsyth 	return 0;
81174a4d8c2SCharles.Forsyth }
81274a4d8c2SCharles.Forsyth 
81374a4d8c2SCharles.Forsyth int
a2type(Prog * p)81474a4d8c2SCharles.Forsyth a2type(Prog *p)
81574a4d8c2SCharles.Forsyth {
81674a4d8c2SCharles.Forsyth 
81774a4d8c2SCharles.Forsyth 	switch(p->as) {
81874a4d8c2SCharles.Forsyth 	case AADD:
819d67b7dadSforsyth 	case AADDC:
82074a4d8c2SCharles.Forsyth 	case AADDCC:
821d67b7dadSforsyth 	case AADDCCC:
822d67b7dadSforsyth 	case AADDE:
823d67b7dadSforsyth 	case AADDECC:
824d67b7dadSforsyth 	case AADDME:
825d67b7dadSforsyth 	case AADDMECC:
826d67b7dadSforsyth 	case AADDZE:
827d67b7dadSforsyth 	case AADDZECC:
82874a4d8c2SCharles.Forsyth 	case ASUB:
829d67b7dadSforsyth 	case ASUBC:
83074a4d8c2SCharles.Forsyth 	case ASUBCC:
831d67b7dadSforsyth 	case ASUBCCC:
832d67b7dadSforsyth 	case ASUBE:
833d67b7dadSforsyth 	case ASUBECC:
834d67b7dadSforsyth 	case ASUBME:
835d67b7dadSforsyth 	case ASUBMECC:
836d67b7dadSforsyth 	case ASUBZE:
837d67b7dadSforsyth 	case ASUBZECC:
83874a4d8c2SCharles.Forsyth 	case ASLW:
83974a4d8c2SCharles.Forsyth 	case ASLWCC:
84074a4d8c2SCharles.Forsyth 	case ASRW:
84174a4d8c2SCharles.Forsyth 	case ASRWCC:
84274a4d8c2SCharles.Forsyth 	case ASRAW:
84374a4d8c2SCharles.Forsyth 	case ASRAWCC:
84474a4d8c2SCharles.Forsyth 	case AOR:
84574a4d8c2SCharles.Forsyth 	case AORCC:
84674a4d8c2SCharles.Forsyth 	case AORN:
84774a4d8c2SCharles.Forsyth 	case AORNCC:
84874a4d8c2SCharles.Forsyth 	case AAND:
84974a4d8c2SCharles.Forsyth 	case AANDCC:
85074a4d8c2SCharles.Forsyth 	case AANDN:
85174a4d8c2SCharles.Forsyth 	case AANDNCC:
85274a4d8c2SCharles.Forsyth 	case AXOR:
85374a4d8c2SCharles.Forsyth 	case AXORCC:
85474a4d8c2SCharles.Forsyth 	case ANEG:
85574a4d8c2SCharles.Forsyth 	case ANEGCC:
856d67b7dadSforsyth 	case AMULHW:
857d67b7dadSforsyth 	case AMULHWU:
85874a4d8c2SCharles.Forsyth 	case AMULLW:
85974a4d8c2SCharles.Forsyth 	case AMULLWCC:
86074a4d8c2SCharles.Forsyth 	case ADIVW:
86174a4d8c2SCharles.Forsyth 	case ADIVWCC:
86274a4d8c2SCharles.Forsyth 	case ADIVWU:
86374a4d8c2SCharles.Forsyth 	case ADIVWUCC:
86474a4d8c2SCharles.Forsyth 	case AREM:
86574a4d8c2SCharles.Forsyth 	case AREMCC:
86674a4d8c2SCharles.Forsyth 	case AREMU:
86774a4d8c2SCharles.Forsyth 	case AREMUCC:
86874a4d8c2SCharles.Forsyth 	case ANAND:
86974a4d8c2SCharles.Forsyth 	case ANANDCC:
87074a4d8c2SCharles.Forsyth 	case ANOR:
87174a4d8c2SCharles.Forsyth 	case ANORCC:
872d67b7dadSforsyth 	case ARLWMI:
873d67b7dadSforsyth 	case ARLWMICC:
874d67b7dadSforsyth 	case ARLWNM:
875d67b7dadSforsyth 	case ARLWNMCC:
87674a4d8c2SCharles.Forsyth 		return D_REG;
87774a4d8c2SCharles.Forsyth 
87874a4d8c2SCharles.Forsyth 	case AFADDS:
87974a4d8c2SCharles.Forsyth 	case AFADDSCC:
88074a4d8c2SCharles.Forsyth 	case AFADD:
88174a4d8c2SCharles.Forsyth 	case AFADDCC:
88274a4d8c2SCharles.Forsyth 	case AFSUBS:
88374a4d8c2SCharles.Forsyth 	case AFSUBSCC:
88474a4d8c2SCharles.Forsyth 	case AFSUB:
88574a4d8c2SCharles.Forsyth 	case AFSUBCC:
88674a4d8c2SCharles.Forsyth 	case AFMULS:
88774a4d8c2SCharles.Forsyth 	case AFMULSCC:
88874a4d8c2SCharles.Forsyth 	case AFMUL:
88974a4d8c2SCharles.Forsyth 	case AFMULCC:
89074a4d8c2SCharles.Forsyth 	case AFDIVS:
89174a4d8c2SCharles.Forsyth 	case AFDIVSCC:
89274a4d8c2SCharles.Forsyth 	case AFDIV:
89374a4d8c2SCharles.Forsyth 	case AFDIVCC:
89474a4d8c2SCharles.Forsyth 	case AFNEG:
89574a4d8c2SCharles.Forsyth 	case AFNEGCC:
89674a4d8c2SCharles.Forsyth 		return D_FREG;
89774a4d8c2SCharles.Forsyth 	}
89874a4d8c2SCharles.Forsyth 	return D_NONE;
89974a4d8c2SCharles.Forsyth }
90074a4d8c2SCharles.Forsyth 
90174a4d8c2SCharles.Forsyth /*
90274a4d8c2SCharles.Forsyth  * direct reference,
90374a4d8c2SCharles.Forsyth  * could be set/use depending on
90474a4d8c2SCharles.Forsyth  * semantics
90574a4d8c2SCharles.Forsyth  */
90674a4d8c2SCharles.Forsyth int
copyas(Adr * a,Adr * v)90774a4d8c2SCharles.Forsyth copyas(Adr *a, Adr *v)
90874a4d8c2SCharles.Forsyth {
90974a4d8c2SCharles.Forsyth 
91074a4d8c2SCharles.Forsyth 	if(regtyp(v))
91174a4d8c2SCharles.Forsyth 		if(a->type == v->type)
91274a4d8c2SCharles.Forsyth 		if(a->reg == v->reg)
91374a4d8c2SCharles.Forsyth 			return 1;
91474a4d8c2SCharles.Forsyth 	return 0;
91574a4d8c2SCharles.Forsyth }
91674a4d8c2SCharles.Forsyth 
91774a4d8c2SCharles.Forsyth /*
91874a4d8c2SCharles.Forsyth  * either direct or indirect
91974a4d8c2SCharles.Forsyth  */
92074a4d8c2SCharles.Forsyth int
copyau(Adr * a,Adr * v)92174a4d8c2SCharles.Forsyth copyau(Adr *a, Adr *v)
92274a4d8c2SCharles.Forsyth {
92374a4d8c2SCharles.Forsyth 
92474a4d8c2SCharles.Forsyth 	if(copyas(a, v))
92574a4d8c2SCharles.Forsyth 		return 1;
92674a4d8c2SCharles.Forsyth 	if(v->type == D_REG)
92774a4d8c2SCharles.Forsyth 		if(a->type == D_OREG)
92874a4d8c2SCharles.Forsyth 			if(v->reg == a->reg)
92974a4d8c2SCharles.Forsyth 				return 1;
93074a4d8c2SCharles.Forsyth 	return 0;
93174a4d8c2SCharles.Forsyth }
93274a4d8c2SCharles.Forsyth 
93374a4d8c2SCharles.Forsyth int
copyau1(Prog * p,Adr * v)93474a4d8c2SCharles.Forsyth copyau1(Prog *p, Adr *v)
93574a4d8c2SCharles.Forsyth {
93674a4d8c2SCharles.Forsyth 
93774a4d8c2SCharles.Forsyth 	if(regtyp(v))
93874a4d8c2SCharles.Forsyth 		if(p->from.type == v->type || p->to.type == v->type)
93974a4d8c2SCharles.Forsyth 		if(p->reg == v->reg) {
94074a4d8c2SCharles.Forsyth 			if(a2type(p) != v->type)
94174a4d8c2SCharles.Forsyth 				print("botch a2type %P\n", p);
94274a4d8c2SCharles.Forsyth 			return 1;
94374a4d8c2SCharles.Forsyth 		}
94474a4d8c2SCharles.Forsyth 	return 0;
94574a4d8c2SCharles.Forsyth }
94674a4d8c2SCharles.Forsyth 
94774a4d8c2SCharles.Forsyth /*
94874a4d8c2SCharles.Forsyth  * substitute s for v in a
94974a4d8c2SCharles.Forsyth  * return failure to substitute
95074a4d8c2SCharles.Forsyth  */
95174a4d8c2SCharles.Forsyth int
copysub(Adr * a,Adr * v,Adr * s,int f)95274a4d8c2SCharles.Forsyth copysub(Adr *a, Adr *v, Adr *s, int f)
95374a4d8c2SCharles.Forsyth {
95474a4d8c2SCharles.Forsyth 
95574a4d8c2SCharles.Forsyth 	if(f)
95674a4d8c2SCharles.Forsyth 	if(copyau(a, v))
95774a4d8c2SCharles.Forsyth 		a->reg = s->reg;
95874a4d8c2SCharles.Forsyth 	return 0;
95974a4d8c2SCharles.Forsyth }
96074a4d8c2SCharles.Forsyth 
96174a4d8c2SCharles.Forsyth int
copysub1(Prog * p1,Adr * v,Adr * s,int f)96274a4d8c2SCharles.Forsyth copysub1(Prog *p1, Adr *v, Adr *s, int f)
96374a4d8c2SCharles.Forsyth {
96474a4d8c2SCharles.Forsyth 
96574a4d8c2SCharles.Forsyth 	if(f)
96674a4d8c2SCharles.Forsyth 	if(copyau1(p1, v))
96774a4d8c2SCharles.Forsyth 		p1->reg = s->reg;
96874a4d8c2SCharles.Forsyth 	return 0;
96974a4d8c2SCharles.Forsyth }
970