xref: /inferno-os/utils/8c/peep.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth static int
needc(Prog * p)474a4d8c2SCharles.Forsyth needc(Prog *p)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth 	while(p != P) {
774a4d8c2SCharles.Forsyth 		switch(p->as) {
874a4d8c2SCharles.Forsyth 		case AADCL:
974a4d8c2SCharles.Forsyth 		case ASBBL:
1074a4d8c2SCharles.Forsyth 		case ARCRL:
1174a4d8c2SCharles.Forsyth 			return 1;
1274a4d8c2SCharles.Forsyth 		case AADDL:
1374a4d8c2SCharles.Forsyth 		case ASUBL:
1474a4d8c2SCharles.Forsyth 		case AJMP:
1574a4d8c2SCharles.Forsyth 		case ARET:
1674a4d8c2SCharles.Forsyth 		case ACALL:
1774a4d8c2SCharles.Forsyth 			return 0;
1874a4d8c2SCharles.Forsyth 		default:
1974a4d8c2SCharles.Forsyth 			if(p->to.type == D_BRANCH)
2074a4d8c2SCharles.Forsyth 				return 0;
2174a4d8c2SCharles.Forsyth 		}
2274a4d8c2SCharles.Forsyth 		p = p->link;
2374a4d8c2SCharles.Forsyth 	}
2474a4d8c2SCharles.Forsyth 	return 0;
2574a4d8c2SCharles.Forsyth }
2674a4d8c2SCharles.Forsyth 
2774a4d8c2SCharles.Forsyth void
peep(void)2874a4d8c2SCharles.Forsyth peep(void)
2974a4d8c2SCharles.Forsyth {
3074a4d8c2SCharles.Forsyth 	Reg *r, *r1, *r2;
3174a4d8c2SCharles.Forsyth 	Prog *p, *p1;
3274a4d8c2SCharles.Forsyth 	int t;
3374a4d8c2SCharles.Forsyth 
3474a4d8c2SCharles.Forsyth 	/*
3574a4d8c2SCharles.Forsyth 	 * complete R structure
3674a4d8c2SCharles.Forsyth 	 */
3774a4d8c2SCharles.Forsyth 	t = 0;
3874a4d8c2SCharles.Forsyth 	for(r=firstr; r!=R; r=r1) {
3974a4d8c2SCharles.Forsyth 		r1 = r->link;
4074a4d8c2SCharles.Forsyth 		if(r1 == R)
4174a4d8c2SCharles.Forsyth 			break;
4274a4d8c2SCharles.Forsyth 		p = r->prog->link;
4374a4d8c2SCharles.Forsyth 		while(p != r1->prog)
4474a4d8c2SCharles.Forsyth 		switch(p->as) {
4574a4d8c2SCharles.Forsyth 		default:
4674a4d8c2SCharles.Forsyth 			r2 = rega();
4774a4d8c2SCharles.Forsyth 			r->link = r2;
4874a4d8c2SCharles.Forsyth 			r2->link = r1;
4974a4d8c2SCharles.Forsyth 
5074a4d8c2SCharles.Forsyth 			r2->prog = p;
5174a4d8c2SCharles.Forsyth 			r2->p1 = r;
5274a4d8c2SCharles.Forsyth 			r->s1 = r2;
5374a4d8c2SCharles.Forsyth 			r2->s1 = r1;
5474a4d8c2SCharles.Forsyth 			r1->p1 = r2;
5574a4d8c2SCharles.Forsyth 
5674a4d8c2SCharles.Forsyth 			r = r2;
5774a4d8c2SCharles.Forsyth 			t++;
5874a4d8c2SCharles.Forsyth 
5974a4d8c2SCharles.Forsyth 		case ADATA:
6074a4d8c2SCharles.Forsyth 		case AGLOBL:
6174a4d8c2SCharles.Forsyth 		case ANAME:
6274a4d8c2SCharles.Forsyth 		case ASIGNAME:
6374a4d8c2SCharles.Forsyth 			p = p->link;
6474a4d8c2SCharles.Forsyth 		}
6574a4d8c2SCharles.Forsyth 	}
6674a4d8c2SCharles.Forsyth 
6774a4d8c2SCharles.Forsyth 	pc = 0;	/* speculating it won't kill */
6874a4d8c2SCharles.Forsyth 
6974a4d8c2SCharles.Forsyth loop1:
7074a4d8c2SCharles.Forsyth 
7174a4d8c2SCharles.Forsyth 	t = 0;
7274a4d8c2SCharles.Forsyth 	for(r=firstr; r!=R; r=r->link) {
7374a4d8c2SCharles.Forsyth 		p = r->prog;
7474a4d8c2SCharles.Forsyth 		switch(p->as) {
7574a4d8c2SCharles.Forsyth 		case AMOVL:
7674a4d8c2SCharles.Forsyth 			if(regtyp(&p->to))
7774a4d8c2SCharles.Forsyth 			if(regtyp(&p->from)) {
7874a4d8c2SCharles.Forsyth 				if(copyprop(r)) {
7974a4d8c2SCharles.Forsyth 					excise(r);
8074a4d8c2SCharles.Forsyth 					t++;
8174a4d8c2SCharles.Forsyth 				}
8274a4d8c2SCharles.Forsyth 				if(subprop(r) && copyprop(r)) {
8374a4d8c2SCharles.Forsyth 					excise(r);
8474a4d8c2SCharles.Forsyth 					t++;
8574a4d8c2SCharles.Forsyth 				}
8674a4d8c2SCharles.Forsyth 			}
8774a4d8c2SCharles.Forsyth 			break;
8874a4d8c2SCharles.Forsyth 
8974a4d8c2SCharles.Forsyth 		case AMOVBLSX:
9074a4d8c2SCharles.Forsyth 		case AMOVBLZX:
9174a4d8c2SCharles.Forsyth 		case AMOVWLSX:
9274a4d8c2SCharles.Forsyth 		case AMOVWLZX:
9374a4d8c2SCharles.Forsyth 			if(regtyp(&p->to)) {
9474a4d8c2SCharles.Forsyth 				r1 = uniqs(r);
9574a4d8c2SCharles.Forsyth 				if(r1 != R) {
9674a4d8c2SCharles.Forsyth 					p1 = r1->prog;
9774a4d8c2SCharles.Forsyth 					if(p->as == p1->as && p->to.type == p1->from.type)
9874a4d8c2SCharles.Forsyth 						p1->as = AMOVL;
9974a4d8c2SCharles.Forsyth 				}
10074a4d8c2SCharles.Forsyth 			}
10174a4d8c2SCharles.Forsyth 			break;
10274a4d8c2SCharles.Forsyth 		case AADDL:
10374a4d8c2SCharles.Forsyth 		case AADDW:
10474a4d8c2SCharles.Forsyth 			if(p->from.type != D_CONST || needc(p->link))
10574a4d8c2SCharles.Forsyth 				break;
10674a4d8c2SCharles.Forsyth 			if(p->from.offset == -1){
10774a4d8c2SCharles.Forsyth 				if(p->as == AADDL)
10874a4d8c2SCharles.Forsyth 					p->as = ADECL;
10974a4d8c2SCharles.Forsyth 				else
11074a4d8c2SCharles.Forsyth 					p->as = ADECW;
11174a4d8c2SCharles.Forsyth 				p->from = zprog.from;
11274a4d8c2SCharles.Forsyth 			}
11374a4d8c2SCharles.Forsyth 			else if(p->from.offset == 1){
11474a4d8c2SCharles.Forsyth 				if(p->as == AADDL)
11574a4d8c2SCharles.Forsyth 					p->as = AINCL;
11674a4d8c2SCharles.Forsyth 				else
11774a4d8c2SCharles.Forsyth 					p->as = AINCW;
11874a4d8c2SCharles.Forsyth 				p->from = zprog.from;
11974a4d8c2SCharles.Forsyth 			}
12074a4d8c2SCharles.Forsyth 			break;
12174a4d8c2SCharles.Forsyth 		case ASUBL:
12274a4d8c2SCharles.Forsyth 		case ASUBW:
12374a4d8c2SCharles.Forsyth 			if(p->from.type != D_CONST || needc(p->link))
12474a4d8c2SCharles.Forsyth 				break;
12574a4d8c2SCharles.Forsyth 			if(p->from.offset == -1) {
12674a4d8c2SCharles.Forsyth 				if(p->as == ASUBL)
12774a4d8c2SCharles.Forsyth 					p->as = AINCL;
12874a4d8c2SCharles.Forsyth 				else
12974a4d8c2SCharles.Forsyth 					p->as = AINCW;
13074a4d8c2SCharles.Forsyth 				p->from = zprog.from;
13174a4d8c2SCharles.Forsyth 			}
13274a4d8c2SCharles.Forsyth 			else if(p->from.offset == 1){
13374a4d8c2SCharles.Forsyth 				if(p->as == ASUBL)
13474a4d8c2SCharles.Forsyth 					p->as = ADECL;
13574a4d8c2SCharles.Forsyth 				else
13674a4d8c2SCharles.Forsyth 					p->as = ADECW;
13774a4d8c2SCharles.Forsyth 				p->from = zprog.from;
13874a4d8c2SCharles.Forsyth 			}
13974a4d8c2SCharles.Forsyth 			break;
14074a4d8c2SCharles.Forsyth 		}
14174a4d8c2SCharles.Forsyth 	}
14274a4d8c2SCharles.Forsyth 	if(t)
14374a4d8c2SCharles.Forsyth 		goto loop1;
14474a4d8c2SCharles.Forsyth }
14574a4d8c2SCharles.Forsyth 
14674a4d8c2SCharles.Forsyth void
excise(Reg * r)14774a4d8c2SCharles.Forsyth excise(Reg *r)
14874a4d8c2SCharles.Forsyth {
14974a4d8c2SCharles.Forsyth 	Prog *p;
15074a4d8c2SCharles.Forsyth 
15174a4d8c2SCharles.Forsyth 	p = r->prog;
15274a4d8c2SCharles.Forsyth 	p->as = ANOP;
15374a4d8c2SCharles.Forsyth 	p->from = zprog.from;
15474a4d8c2SCharles.Forsyth 	p->to = zprog.to;
15574a4d8c2SCharles.Forsyth }
15674a4d8c2SCharles.Forsyth 
15774a4d8c2SCharles.Forsyth Reg*
uniqp(Reg * r)15874a4d8c2SCharles.Forsyth uniqp(Reg *r)
15974a4d8c2SCharles.Forsyth {
16074a4d8c2SCharles.Forsyth 	Reg *r1;
16174a4d8c2SCharles.Forsyth 
16274a4d8c2SCharles.Forsyth 	r1 = r->p1;
16374a4d8c2SCharles.Forsyth 	if(r1 == R) {
16474a4d8c2SCharles.Forsyth 		r1 = r->p2;
16574a4d8c2SCharles.Forsyth 		if(r1 == R || r1->p2link != R)
16674a4d8c2SCharles.Forsyth 			return R;
16774a4d8c2SCharles.Forsyth 	} else
16874a4d8c2SCharles.Forsyth 		if(r->p2 != R)
16974a4d8c2SCharles.Forsyth 			return R;
17074a4d8c2SCharles.Forsyth 	return r1;
17174a4d8c2SCharles.Forsyth }
17274a4d8c2SCharles.Forsyth 
17374a4d8c2SCharles.Forsyth Reg*
uniqs(Reg * r)17474a4d8c2SCharles.Forsyth uniqs(Reg *r)
17574a4d8c2SCharles.Forsyth {
17674a4d8c2SCharles.Forsyth 	Reg *r1;
17774a4d8c2SCharles.Forsyth 
17874a4d8c2SCharles.Forsyth 	r1 = r->s1;
17974a4d8c2SCharles.Forsyth 	if(r1 == R) {
18074a4d8c2SCharles.Forsyth 		r1 = r->s2;
18174a4d8c2SCharles.Forsyth 		if(r1 == R)
18274a4d8c2SCharles.Forsyth 			return R;
18374a4d8c2SCharles.Forsyth 	} else
18474a4d8c2SCharles.Forsyth 		if(r->s2 != R)
18574a4d8c2SCharles.Forsyth 			return R;
18674a4d8c2SCharles.Forsyth 	return r1;
18774a4d8c2SCharles.Forsyth }
18874a4d8c2SCharles.Forsyth 
18974a4d8c2SCharles.Forsyth int
regtyp(Adr * a)19074a4d8c2SCharles.Forsyth regtyp(Adr *a)
19174a4d8c2SCharles.Forsyth {
19274a4d8c2SCharles.Forsyth 	int t;
19374a4d8c2SCharles.Forsyth 
19474a4d8c2SCharles.Forsyth 	t = a->type;
19574a4d8c2SCharles.Forsyth 	if(t >= D_AX && t <= D_DI)
19674a4d8c2SCharles.Forsyth 		return 1;
19774a4d8c2SCharles.Forsyth 	return 0;
19874a4d8c2SCharles.Forsyth }
19974a4d8c2SCharles.Forsyth 
20074a4d8c2SCharles.Forsyth /*
20174a4d8c2SCharles.Forsyth  * the idea is to substitute
20274a4d8c2SCharles.Forsyth  * one register for another
20374a4d8c2SCharles.Forsyth  * from one MOV to another
20474a4d8c2SCharles.Forsyth  *	MOV	a, R0
20574a4d8c2SCharles.Forsyth  *	ADD	b, R0	/ no use of R1
20674a4d8c2SCharles.Forsyth  *	MOV	R0, R1
20774a4d8c2SCharles.Forsyth  * would be converted to
20874a4d8c2SCharles.Forsyth  *	MOV	a, R1
20974a4d8c2SCharles.Forsyth  *	ADD	b, R1
21074a4d8c2SCharles.Forsyth  *	MOV	R1, R0
21174a4d8c2SCharles.Forsyth  * hopefully, then the former or latter MOV
21274a4d8c2SCharles.Forsyth  * will be eliminated by copy propagation.
21374a4d8c2SCharles.Forsyth  */
21474a4d8c2SCharles.Forsyth int
subprop(Reg * r0)21574a4d8c2SCharles.Forsyth subprop(Reg *r0)
21674a4d8c2SCharles.Forsyth {
21774a4d8c2SCharles.Forsyth 	Prog *p;
21874a4d8c2SCharles.Forsyth 	Adr *v1, *v2;
21974a4d8c2SCharles.Forsyth 	Reg *r;
22074a4d8c2SCharles.Forsyth 	int t;
22174a4d8c2SCharles.Forsyth 
22274a4d8c2SCharles.Forsyth 	p = r0->prog;
22374a4d8c2SCharles.Forsyth 	v1 = &p->from;
22474a4d8c2SCharles.Forsyth 	if(!regtyp(v1))
22574a4d8c2SCharles.Forsyth 		return 0;
22674a4d8c2SCharles.Forsyth 	v2 = &p->to;
22774a4d8c2SCharles.Forsyth 	if(!regtyp(v2))
22874a4d8c2SCharles.Forsyth 		return 0;
22974a4d8c2SCharles.Forsyth 	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
23074a4d8c2SCharles.Forsyth 		if(uniqs(r) == R)
23174a4d8c2SCharles.Forsyth 			break;
23274a4d8c2SCharles.Forsyth 		p = r->prog;
23374a4d8c2SCharles.Forsyth 		switch(p->as) {
23474a4d8c2SCharles.Forsyth 		case ACALL:
23574a4d8c2SCharles.Forsyth 			return 0;
23674a4d8c2SCharles.Forsyth 
23774a4d8c2SCharles.Forsyth 		case AIMULL:
23874a4d8c2SCharles.Forsyth 		case AIMULW:
23974a4d8c2SCharles.Forsyth 			if(p->to.type != D_NONE)
24074a4d8c2SCharles.Forsyth 				break;
24174a4d8c2SCharles.Forsyth 
24274a4d8c2SCharles.Forsyth 		case ADIVB:
24374a4d8c2SCharles.Forsyth 		case ADIVL:
24474a4d8c2SCharles.Forsyth 		case ADIVW:
24574a4d8c2SCharles.Forsyth 		case AIDIVB:
24674a4d8c2SCharles.Forsyth 		case AIDIVL:
24774a4d8c2SCharles.Forsyth 		case AIDIVW:
24874a4d8c2SCharles.Forsyth 		case AIMULB:
24974a4d8c2SCharles.Forsyth 		case AMULB:
25074a4d8c2SCharles.Forsyth 		case AMULL:
25174a4d8c2SCharles.Forsyth 		case AMULW:
25274a4d8c2SCharles.Forsyth 
25374a4d8c2SCharles.Forsyth 		case AROLB:
25474a4d8c2SCharles.Forsyth 		case AROLL:
25574a4d8c2SCharles.Forsyth 		case AROLW:
25674a4d8c2SCharles.Forsyth 		case ARORB:
25774a4d8c2SCharles.Forsyth 		case ARORL:
25874a4d8c2SCharles.Forsyth 		case ARORW:
25974a4d8c2SCharles.Forsyth 		case ASALB:
26074a4d8c2SCharles.Forsyth 		case ASALL:
26174a4d8c2SCharles.Forsyth 		case ASALW:
26274a4d8c2SCharles.Forsyth 		case ASARB:
26374a4d8c2SCharles.Forsyth 		case ASARL:
26474a4d8c2SCharles.Forsyth 		case ASARW:
26574a4d8c2SCharles.Forsyth 		case ASHLB:
26674a4d8c2SCharles.Forsyth 		case ASHLL:
26774a4d8c2SCharles.Forsyth 		case ASHLW:
26874a4d8c2SCharles.Forsyth 		case ASHRB:
26974a4d8c2SCharles.Forsyth 		case ASHRL:
27074a4d8c2SCharles.Forsyth 		case ASHRW:
27174a4d8c2SCharles.Forsyth 
27274a4d8c2SCharles.Forsyth 		case AREP:
27374a4d8c2SCharles.Forsyth 		case AREPN:
27474a4d8c2SCharles.Forsyth 
27574a4d8c2SCharles.Forsyth 		case ACWD:
27674a4d8c2SCharles.Forsyth 		case ACDQ:
27774a4d8c2SCharles.Forsyth 
278*45a20ab7Sforsyth 		case ASTOSB:
279*45a20ab7Sforsyth 		case ASTOSL:
280*45a20ab7Sforsyth 		case AMOVSB:
28174a4d8c2SCharles.Forsyth 		case AMOVSL:
28274a4d8c2SCharles.Forsyth 		case AFSTSW:
28374a4d8c2SCharles.Forsyth 			return 0;
28474a4d8c2SCharles.Forsyth 
28574a4d8c2SCharles.Forsyth 		case AMOVL:
28674a4d8c2SCharles.Forsyth 			if(p->to.type == v1->type)
28774a4d8c2SCharles.Forsyth 				goto gotit;
28874a4d8c2SCharles.Forsyth 			break;
28974a4d8c2SCharles.Forsyth 		}
29074a4d8c2SCharles.Forsyth 		if(copyau(&p->from, v2) ||
29174a4d8c2SCharles.Forsyth 		   copyau(&p->to, v2))
29274a4d8c2SCharles.Forsyth 			break;
29374a4d8c2SCharles.Forsyth 		if(copysub(&p->from, v1, v2, 0) ||
29474a4d8c2SCharles.Forsyth 		   copysub(&p->to, v1, v2, 0))
29574a4d8c2SCharles.Forsyth 			break;
29674a4d8c2SCharles.Forsyth 	}
29774a4d8c2SCharles.Forsyth 	return 0;
29874a4d8c2SCharles.Forsyth 
29974a4d8c2SCharles.Forsyth gotit:
30074a4d8c2SCharles.Forsyth 	copysub(&p->to, v1, v2, 1);
30174a4d8c2SCharles.Forsyth 	if(debug['P']) {
30274a4d8c2SCharles.Forsyth 		print("gotit: %D->%D\n%P", v1, v2, r->prog);
30374a4d8c2SCharles.Forsyth 		if(p->from.type == v2->type)
30474a4d8c2SCharles.Forsyth 			print(" excise");
30574a4d8c2SCharles.Forsyth 		print("\n");
30674a4d8c2SCharles.Forsyth 	}
30774a4d8c2SCharles.Forsyth 	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
30874a4d8c2SCharles.Forsyth 		p = r->prog;
30974a4d8c2SCharles.Forsyth 		copysub(&p->from, v1, v2, 1);
31074a4d8c2SCharles.Forsyth 		copysub(&p->to, v1, v2, 1);
31174a4d8c2SCharles.Forsyth 		if(debug['P'])
31274a4d8c2SCharles.Forsyth 			print("%P\n", r->prog);
31374a4d8c2SCharles.Forsyth 	}
31474a4d8c2SCharles.Forsyth 	t = v1->type;
31574a4d8c2SCharles.Forsyth 	v1->type = v2->type;
31674a4d8c2SCharles.Forsyth 	v2->type = t;
31774a4d8c2SCharles.Forsyth 	if(debug['P'])
31874a4d8c2SCharles.Forsyth 		print("%P last\n", r->prog);
31974a4d8c2SCharles.Forsyth 	return 1;
32074a4d8c2SCharles.Forsyth }
32174a4d8c2SCharles.Forsyth 
32274a4d8c2SCharles.Forsyth /*
32374a4d8c2SCharles.Forsyth  * The idea is to remove redundant copies.
32474a4d8c2SCharles.Forsyth  *	v1->v2	F=0
32574a4d8c2SCharles.Forsyth  *	(use v2	s/v2/v1/)*
32674a4d8c2SCharles.Forsyth  *	set v1	F=1
32774a4d8c2SCharles.Forsyth  *	use v2	return fail
32874a4d8c2SCharles.Forsyth  *	-----------------
32974a4d8c2SCharles.Forsyth  *	v1->v2	F=0
33074a4d8c2SCharles.Forsyth  *	(use v2	s/v2/v1/)*
33174a4d8c2SCharles.Forsyth  *	set v1	F=1
33274a4d8c2SCharles.Forsyth  *	set v2	return success
33374a4d8c2SCharles.Forsyth  */
33474a4d8c2SCharles.Forsyth int
copyprop(Reg * r0)33574a4d8c2SCharles.Forsyth copyprop(Reg *r0)
33674a4d8c2SCharles.Forsyth {
33774a4d8c2SCharles.Forsyth 	Prog *p;
33874a4d8c2SCharles.Forsyth 	Adr *v1, *v2;
33974a4d8c2SCharles.Forsyth 	Reg *r;
34074a4d8c2SCharles.Forsyth 
34174a4d8c2SCharles.Forsyth 	p = r0->prog;
34274a4d8c2SCharles.Forsyth 	v1 = &p->from;
34374a4d8c2SCharles.Forsyth 	v2 = &p->to;
34474a4d8c2SCharles.Forsyth 	if(copyas(v1, v2))
34574a4d8c2SCharles.Forsyth 		return 1;
34674a4d8c2SCharles.Forsyth 	for(r=firstr; r!=R; r=r->link)
34774a4d8c2SCharles.Forsyth 		r->active = 0;
34874a4d8c2SCharles.Forsyth 	return copy1(v1, v2, r0->s1, 0);
34974a4d8c2SCharles.Forsyth }
35074a4d8c2SCharles.Forsyth 
35174a4d8c2SCharles.Forsyth int
copy1(Adr * v1,Adr * v2,Reg * r,int f)35274a4d8c2SCharles.Forsyth copy1(Adr *v1, Adr *v2, Reg *r, int f)
35374a4d8c2SCharles.Forsyth {
35474a4d8c2SCharles.Forsyth 	int t;
35574a4d8c2SCharles.Forsyth 	Prog *p;
35674a4d8c2SCharles.Forsyth 
35774a4d8c2SCharles.Forsyth 	if(r->active) {
35874a4d8c2SCharles.Forsyth 		if(debug['P'])
35974a4d8c2SCharles.Forsyth 			print("act set; return 1\n");
36074a4d8c2SCharles.Forsyth 		return 1;
36174a4d8c2SCharles.Forsyth 	}
36274a4d8c2SCharles.Forsyth 	r->active = 1;
36374a4d8c2SCharles.Forsyth 	if(debug['P'])
36474a4d8c2SCharles.Forsyth 		print("copy %D->%D f=%d\n", v1, v2, f);
36574a4d8c2SCharles.Forsyth 	for(; r != R; r = r->s1) {
36674a4d8c2SCharles.Forsyth 		p = r->prog;
36774a4d8c2SCharles.Forsyth 		if(debug['P'])
36874a4d8c2SCharles.Forsyth 			print("%P", p);
36974a4d8c2SCharles.Forsyth 		if(!f && uniqp(r) == R) {
37074a4d8c2SCharles.Forsyth 			f = 1;
37174a4d8c2SCharles.Forsyth 			if(debug['P'])
37274a4d8c2SCharles.Forsyth 				print("; merge; f=%d", f);
37374a4d8c2SCharles.Forsyth 		}
37474a4d8c2SCharles.Forsyth 		t = copyu(p, v2, A);
37574a4d8c2SCharles.Forsyth 		switch(t) {
37674a4d8c2SCharles.Forsyth 		case 2:	/* rar, cant split */
37774a4d8c2SCharles.Forsyth 			if(debug['P'])
37874a4d8c2SCharles.Forsyth 				print("; %D rar; return 0\n", v2);
37974a4d8c2SCharles.Forsyth 			return 0;
38074a4d8c2SCharles.Forsyth 
38174a4d8c2SCharles.Forsyth 		case 3:	/* set */
38274a4d8c2SCharles.Forsyth 			if(debug['P'])
38374a4d8c2SCharles.Forsyth 				print("; %D set; return 1\n", v2);
38474a4d8c2SCharles.Forsyth 			return 1;
38574a4d8c2SCharles.Forsyth 
38674a4d8c2SCharles.Forsyth 		case 1:	/* used, substitute */
38774a4d8c2SCharles.Forsyth 		case 4:	/* use and set */
38874a4d8c2SCharles.Forsyth 			if(f) {
38974a4d8c2SCharles.Forsyth 				if(!debug['P'])
39074a4d8c2SCharles.Forsyth 					return 0;
39174a4d8c2SCharles.Forsyth 				if(t == 4)
39274a4d8c2SCharles.Forsyth 					print("; %D used+set and f=%d; return 0\n", v2, f);
39374a4d8c2SCharles.Forsyth 				else
39474a4d8c2SCharles.Forsyth 					print("; %D used and f=%d; return 0\n", v2, f);
39574a4d8c2SCharles.Forsyth 				return 0;
39674a4d8c2SCharles.Forsyth 			}
39774a4d8c2SCharles.Forsyth 			if(copyu(p, v2, v1)) {
39874a4d8c2SCharles.Forsyth 				if(debug['P'])
39974a4d8c2SCharles.Forsyth 					print("; sub fail; return 0\n");
40074a4d8c2SCharles.Forsyth 				return 0;
40174a4d8c2SCharles.Forsyth 			}
40274a4d8c2SCharles.Forsyth 			if(debug['P'])
40374a4d8c2SCharles.Forsyth 				print("; sub %D/%D", v2, v1);
40474a4d8c2SCharles.Forsyth 			if(t == 4) {
40574a4d8c2SCharles.Forsyth 				if(debug['P'])
40674a4d8c2SCharles.Forsyth 					print("; %D used+set; return 1\n", v2);
40774a4d8c2SCharles.Forsyth 				return 1;
40874a4d8c2SCharles.Forsyth 			}
40974a4d8c2SCharles.Forsyth 			break;
41074a4d8c2SCharles.Forsyth 		}
41174a4d8c2SCharles.Forsyth 		if(!f) {
41274a4d8c2SCharles.Forsyth 			t = copyu(p, v1, A);
41374a4d8c2SCharles.Forsyth 			if(!f && (t == 2 || t == 3 || t == 4)) {
41474a4d8c2SCharles.Forsyth 				f = 1;
41574a4d8c2SCharles.Forsyth 				if(debug['P'])
41674a4d8c2SCharles.Forsyth 					print("; %D set and !f; f=%d", v1, f);
41774a4d8c2SCharles.Forsyth 			}
41874a4d8c2SCharles.Forsyth 		}
41974a4d8c2SCharles.Forsyth 		if(debug['P'])
42074a4d8c2SCharles.Forsyth 			print("\n");
42174a4d8c2SCharles.Forsyth 		if(r->s2)
42274a4d8c2SCharles.Forsyth 			if(!copy1(v1, v2, r->s2, f))
42374a4d8c2SCharles.Forsyth 				return 0;
42474a4d8c2SCharles.Forsyth 	}
42574a4d8c2SCharles.Forsyth 	return 1;
42674a4d8c2SCharles.Forsyth }
42774a4d8c2SCharles.Forsyth 
42874a4d8c2SCharles.Forsyth /*
42974a4d8c2SCharles.Forsyth  * return
43074a4d8c2SCharles.Forsyth  * 1 if v only used (and substitute),
43174a4d8c2SCharles.Forsyth  * 2 if read-alter-rewrite
43274a4d8c2SCharles.Forsyth  * 3 if set
43374a4d8c2SCharles.Forsyth  * 4 if set and used
43474a4d8c2SCharles.Forsyth  * 0 otherwise (not touched)
43574a4d8c2SCharles.Forsyth  */
43674a4d8c2SCharles.Forsyth int
copyu(Prog * p,Adr * v,Adr * s)43774a4d8c2SCharles.Forsyth copyu(Prog *p, Adr *v, Adr *s)
43874a4d8c2SCharles.Forsyth {
43974a4d8c2SCharles.Forsyth 
44074a4d8c2SCharles.Forsyth 	switch(p->as) {
44174a4d8c2SCharles.Forsyth 
44274a4d8c2SCharles.Forsyth 	default:
44374a4d8c2SCharles.Forsyth 		if(debug['P'])
44474a4d8c2SCharles.Forsyth 			print("unknown op %A\n", p->as);
44574a4d8c2SCharles.Forsyth 		return 2;
44674a4d8c2SCharles.Forsyth 
44774a4d8c2SCharles.Forsyth 	case ANEGB:
44874a4d8c2SCharles.Forsyth 	case ANEGW:
44974a4d8c2SCharles.Forsyth 	case ANEGL:
45074a4d8c2SCharles.Forsyth 	case ANOTB:
45174a4d8c2SCharles.Forsyth 	case ANOTW:
45274a4d8c2SCharles.Forsyth 	case ANOTL:
45374a4d8c2SCharles.Forsyth 		if(copyas(&p->to, v))
45474a4d8c2SCharles.Forsyth 			return 2;
45574a4d8c2SCharles.Forsyth 		break;
45674a4d8c2SCharles.Forsyth 
45774a4d8c2SCharles.Forsyth 	case ALEAL:	/* lhs addr, rhs store */
45874a4d8c2SCharles.Forsyth 		if(copyas(&p->from, v))
45974a4d8c2SCharles.Forsyth 			return 2;
46074a4d8c2SCharles.Forsyth 
46174a4d8c2SCharles.Forsyth 
46274a4d8c2SCharles.Forsyth 	case ANOP:	/* rhs store */
46374a4d8c2SCharles.Forsyth 	case AMOVL:
46474a4d8c2SCharles.Forsyth 	case AMOVBLSX:
46574a4d8c2SCharles.Forsyth 	case AMOVBLZX:
46674a4d8c2SCharles.Forsyth 	case AMOVWLSX:
46774a4d8c2SCharles.Forsyth 	case AMOVWLZX:
46874a4d8c2SCharles.Forsyth 		if(copyas(&p->to, v)) {
46974a4d8c2SCharles.Forsyth 			if(s != A)
47074a4d8c2SCharles.Forsyth 				return copysub(&p->from, v, s, 1);
47174a4d8c2SCharles.Forsyth 			if(copyau(&p->from, v))
47274a4d8c2SCharles.Forsyth 				return 4;
47374a4d8c2SCharles.Forsyth 			return 3;
47474a4d8c2SCharles.Forsyth 		}
47574a4d8c2SCharles.Forsyth 		goto caseread;
47674a4d8c2SCharles.Forsyth 
47774a4d8c2SCharles.Forsyth 	case AROLB:
47874a4d8c2SCharles.Forsyth 	case AROLL:
47974a4d8c2SCharles.Forsyth 	case AROLW:
48074a4d8c2SCharles.Forsyth 	case ARORB:
48174a4d8c2SCharles.Forsyth 	case ARORL:
48274a4d8c2SCharles.Forsyth 	case ARORW:
48374a4d8c2SCharles.Forsyth 	case ASALB:
48474a4d8c2SCharles.Forsyth 	case ASALL:
48574a4d8c2SCharles.Forsyth 	case ASALW:
48674a4d8c2SCharles.Forsyth 	case ASARB:
48774a4d8c2SCharles.Forsyth 	case ASARL:
48874a4d8c2SCharles.Forsyth 	case ASARW:
48974a4d8c2SCharles.Forsyth 	case ASHLB:
49074a4d8c2SCharles.Forsyth 	case ASHLL:
49174a4d8c2SCharles.Forsyth 	case ASHLW:
49274a4d8c2SCharles.Forsyth 	case ASHRB:
49374a4d8c2SCharles.Forsyth 	case ASHRL:
49474a4d8c2SCharles.Forsyth 	case ASHRW:
49574a4d8c2SCharles.Forsyth 		if(copyas(&p->to, v))
49674a4d8c2SCharles.Forsyth 			return 2;
49774a4d8c2SCharles.Forsyth 		if(copyas(&p->from, v))
49874a4d8c2SCharles.Forsyth 			if(p->from.type == D_CX)
49974a4d8c2SCharles.Forsyth 				return 2;
50074a4d8c2SCharles.Forsyth 		goto caseread;
50174a4d8c2SCharles.Forsyth 
50274a4d8c2SCharles.Forsyth 	case AADDB:	/* rhs rar */
50374a4d8c2SCharles.Forsyth 	case AADDL:
50474a4d8c2SCharles.Forsyth 	case AADDW:
50574a4d8c2SCharles.Forsyth 	case AANDB:
50674a4d8c2SCharles.Forsyth 	case AANDL:
50774a4d8c2SCharles.Forsyth 	case AANDW:
50874a4d8c2SCharles.Forsyth 	case ADECL:
50974a4d8c2SCharles.Forsyth 	case ADECW:
51074a4d8c2SCharles.Forsyth 	case AINCL:
51174a4d8c2SCharles.Forsyth 	case AINCW:
51274a4d8c2SCharles.Forsyth 	case ASUBB:
51374a4d8c2SCharles.Forsyth 	case ASUBL:
51474a4d8c2SCharles.Forsyth 	case ASUBW:
51574a4d8c2SCharles.Forsyth 	case AORB:
51674a4d8c2SCharles.Forsyth 	case AORL:
51774a4d8c2SCharles.Forsyth 	case AORW:
51874a4d8c2SCharles.Forsyth 	case AXORB:
51974a4d8c2SCharles.Forsyth 	case AXORL:
52074a4d8c2SCharles.Forsyth 	case AXORW:
52174a4d8c2SCharles.Forsyth 	case AMOVB:
52274a4d8c2SCharles.Forsyth 	case AMOVW:
52374a4d8c2SCharles.Forsyth 
52474a4d8c2SCharles.Forsyth 	case AFMOVB:
52574a4d8c2SCharles.Forsyth 	case AFMOVBP:
52674a4d8c2SCharles.Forsyth 	case AFMOVD:
52774a4d8c2SCharles.Forsyth 	case AFMOVDP:
52874a4d8c2SCharles.Forsyth 	case AFMOVF:
52974a4d8c2SCharles.Forsyth 	case AFMOVFP:
53074a4d8c2SCharles.Forsyth 	case AFMOVL:
53174a4d8c2SCharles.Forsyth 	case AFMOVLP:
53274a4d8c2SCharles.Forsyth 	case AFMOVV:
53374a4d8c2SCharles.Forsyth 	case AFMOVVP:
53474a4d8c2SCharles.Forsyth 	case AFMOVW:
53574a4d8c2SCharles.Forsyth 	case AFMOVWP:
53674a4d8c2SCharles.Forsyth 	case AFMOVX:
53774a4d8c2SCharles.Forsyth 	case AFMOVXP:
53874a4d8c2SCharles.Forsyth 	case AFADDDP:
53974a4d8c2SCharles.Forsyth 	case AFADDW:
54074a4d8c2SCharles.Forsyth 	case AFADDL:
54174a4d8c2SCharles.Forsyth 	case AFADDF:
54274a4d8c2SCharles.Forsyth 	case AFADDD:
54374a4d8c2SCharles.Forsyth 	case AFMULDP:
54474a4d8c2SCharles.Forsyth 	case AFMULW:
54574a4d8c2SCharles.Forsyth 	case AFMULL:
54674a4d8c2SCharles.Forsyth 	case AFMULF:
54774a4d8c2SCharles.Forsyth 	case AFMULD:
54874a4d8c2SCharles.Forsyth 	case AFSUBDP:
54974a4d8c2SCharles.Forsyth 	case AFSUBW:
55074a4d8c2SCharles.Forsyth 	case AFSUBL:
55174a4d8c2SCharles.Forsyth 	case AFSUBF:
55274a4d8c2SCharles.Forsyth 	case AFSUBD:
55374a4d8c2SCharles.Forsyth 	case AFSUBRDP:
55474a4d8c2SCharles.Forsyth 	case AFSUBRW:
55574a4d8c2SCharles.Forsyth 	case AFSUBRL:
55674a4d8c2SCharles.Forsyth 	case AFSUBRF:
55774a4d8c2SCharles.Forsyth 	case AFSUBRD:
55874a4d8c2SCharles.Forsyth 	case AFDIVDP:
55974a4d8c2SCharles.Forsyth 	case AFDIVW:
56074a4d8c2SCharles.Forsyth 	case AFDIVL:
56174a4d8c2SCharles.Forsyth 	case AFDIVF:
56274a4d8c2SCharles.Forsyth 	case AFDIVD:
56374a4d8c2SCharles.Forsyth 	case AFDIVRDP:
56474a4d8c2SCharles.Forsyth 	case AFDIVRW:
56574a4d8c2SCharles.Forsyth 	case AFDIVRL:
56674a4d8c2SCharles.Forsyth 	case AFDIVRF:
56774a4d8c2SCharles.Forsyth 	case AFDIVRD:
56874a4d8c2SCharles.Forsyth 		if(copyas(&p->to, v))
56974a4d8c2SCharles.Forsyth 			return 2;
57074a4d8c2SCharles.Forsyth 		goto caseread;
57174a4d8c2SCharles.Forsyth 
57274a4d8c2SCharles.Forsyth 	case ACMPL:	/* read only */
57374a4d8c2SCharles.Forsyth 	case ACMPW:
57474a4d8c2SCharles.Forsyth 	case ACMPB:
57574a4d8c2SCharles.Forsyth 
57674a4d8c2SCharles.Forsyth 	case AFCOMB:
57774a4d8c2SCharles.Forsyth 	case AFCOMBP:
57874a4d8c2SCharles.Forsyth 	case AFCOMD:
57974a4d8c2SCharles.Forsyth 	case AFCOMDP:
58074a4d8c2SCharles.Forsyth 	case AFCOMDPP:
58174a4d8c2SCharles.Forsyth 	case AFCOMF:
58274a4d8c2SCharles.Forsyth 	case AFCOMFP:
58374a4d8c2SCharles.Forsyth 	case AFCOML:
58474a4d8c2SCharles.Forsyth 	case AFCOMLP:
58574a4d8c2SCharles.Forsyth 	case AFCOMW:
58674a4d8c2SCharles.Forsyth 	case AFCOMWP:
58774a4d8c2SCharles.Forsyth 	case AFUCOM:
58874a4d8c2SCharles.Forsyth 	case AFUCOMP:
58974a4d8c2SCharles.Forsyth 	case AFUCOMPP:
59074a4d8c2SCharles.Forsyth 	caseread:
59174a4d8c2SCharles.Forsyth 		if(s != A) {
59274a4d8c2SCharles.Forsyth 			if(copysub(&p->from, v, s, 1))
59374a4d8c2SCharles.Forsyth 				return 1;
59474a4d8c2SCharles.Forsyth 			return copysub(&p->to, v, s, 1);
59574a4d8c2SCharles.Forsyth 		}
59674a4d8c2SCharles.Forsyth 		if(copyau(&p->from, v))
59774a4d8c2SCharles.Forsyth 			return 1;
59874a4d8c2SCharles.Forsyth 		if(copyau(&p->to, v))
59974a4d8c2SCharles.Forsyth 			return 1;
60074a4d8c2SCharles.Forsyth 		break;
60174a4d8c2SCharles.Forsyth 
60274a4d8c2SCharles.Forsyth 	case AJGE:	/* no reference */
60374a4d8c2SCharles.Forsyth 	case AJNE:
60474a4d8c2SCharles.Forsyth 	case AJLE:
60574a4d8c2SCharles.Forsyth 	case AJEQ:
60674a4d8c2SCharles.Forsyth 	case AJHI:
60774a4d8c2SCharles.Forsyth 	case AJLS:
60874a4d8c2SCharles.Forsyth 	case AJMI:
60974a4d8c2SCharles.Forsyth 	case AJPL:
61074a4d8c2SCharles.Forsyth 	case AJGT:
61174a4d8c2SCharles.Forsyth 	case AJLT:
61274a4d8c2SCharles.Forsyth 	case AJCC:
61374a4d8c2SCharles.Forsyth 	case AJCS:
61474a4d8c2SCharles.Forsyth 
61574a4d8c2SCharles.Forsyth 	case AADJSP:
61674a4d8c2SCharles.Forsyth 	case AFLDZ:
61774a4d8c2SCharles.Forsyth 	case AWAIT:
61874a4d8c2SCharles.Forsyth 		break;
61974a4d8c2SCharles.Forsyth 
62074a4d8c2SCharles.Forsyth 	case AIMULL:
62174a4d8c2SCharles.Forsyth 	case AIMULW:
62274a4d8c2SCharles.Forsyth 		if(p->to.type != D_NONE) {
62374a4d8c2SCharles.Forsyth 			if(copyas(&p->to, v))
62474a4d8c2SCharles.Forsyth 				return 2;
62574a4d8c2SCharles.Forsyth 			goto caseread;
62674a4d8c2SCharles.Forsyth 		}
62774a4d8c2SCharles.Forsyth 
62874a4d8c2SCharles.Forsyth 	case ADIVB:
62974a4d8c2SCharles.Forsyth 	case ADIVL:
63074a4d8c2SCharles.Forsyth 	case ADIVW:
63174a4d8c2SCharles.Forsyth 	case AIDIVB:
63274a4d8c2SCharles.Forsyth 	case AIDIVL:
63374a4d8c2SCharles.Forsyth 	case AIDIVW:
63474a4d8c2SCharles.Forsyth 	case AIMULB:
63574a4d8c2SCharles.Forsyth 	case AMULB:
63674a4d8c2SCharles.Forsyth 	case AMULL:
63774a4d8c2SCharles.Forsyth 	case AMULW:
63874a4d8c2SCharles.Forsyth 
63974a4d8c2SCharles.Forsyth 	case ACWD:
64074a4d8c2SCharles.Forsyth 	case ACDQ:
64174a4d8c2SCharles.Forsyth 		if(v->type == D_AX || v->type == D_DX)
64274a4d8c2SCharles.Forsyth 			return 2;
64374a4d8c2SCharles.Forsyth 		goto caseread;
64474a4d8c2SCharles.Forsyth 
64574a4d8c2SCharles.Forsyth 	case AREP:
64674a4d8c2SCharles.Forsyth 	case AREPN:
6474d1cf526Sforsyth 		if(v->type == D_CX)
6484d1cf526Sforsyth 			return 2;
6494d1cf526Sforsyth 		goto caseread;
6504d1cf526Sforsyth 
651*45a20ab7Sforsyth 	case AMOVSB:
6524d1cf526Sforsyth 	case AMOVSL:
6534d1cf526Sforsyth 		if(v->type == D_DI || v->type == D_SI)
65474a4d8c2SCharles.Forsyth 			return 2;
65574a4d8c2SCharles.Forsyth 		goto caseread;
65674a4d8c2SCharles.Forsyth 
657*45a20ab7Sforsyth 	case ASTOSB:
658*45a20ab7Sforsyth 	case ASTOSL:
659*45a20ab7Sforsyth 		if(v->type == D_AX || v->type == D_DI)
660*45a20ab7Sforsyth 			return 2;
661*45a20ab7Sforsyth 		goto caseread;
662*45a20ab7Sforsyth 
66374a4d8c2SCharles.Forsyth 	case AFSTSW:
66474a4d8c2SCharles.Forsyth 		if(v->type == D_AX)
66574a4d8c2SCharles.Forsyth 			return 2;
66674a4d8c2SCharles.Forsyth 		goto caseread;
66774a4d8c2SCharles.Forsyth 
66874a4d8c2SCharles.Forsyth 	case AJMP:	/* funny */
66974a4d8c2SCharles.Forsyth 		if(s != A) {
67074a4d8c2SCharles.Forsyth 			if(copysub(&p->to, v, s, 1))
67174a4d8c2SCharles.Forsyth 				return 1;
67274a4d8c2SCharles.Forsyth 			return 0;
67374a4d8c2SCharles.Forsyth 		}
67474a4d8c2SCharles.Forsyth 		if(copyau(&p->to, v))
67574a4d8c2SCharles.Forsyth 			return 1;
67674a4d8c2SCharles.Forsyth 		return 0;
67774a4d8c2SCharles.Forsyth 
67874a4d8c2SCharles.Forsyth 	case ARET:	/* funny */
67974a4d8c2SCharles.Forsyth 		if(v->type == REGRET)
68074a4d8c2SCharles.Forsyth 			return 2;
68174a4d8c2SCharles.Forsyth 		if(s != A)
68274a4d8c2SCharles.Forsyth 			return 1;
68374a4d8c2SCharles.Forsyth 		return 3;
68474a4d8c2SCharles.Forsyth 
68574a4d8c2SCharles.Forsyth 	case ACALL:	/* funny */
686c0927006Sforsyth 		if(REGARG>=0 && v->type == REGARG)
68774a4d8c2SCharles.Forsyth 			return 2;
68874a4d8c2SCharles.Forsyth 
68974a4d8c2SCharles.Forsyth 		if(s != A) {
69074a4d8c2SCharles.Forsyth 			if(copysub(&p->to, v, s, 1))
69174a4d8c2SCharles.Forsyth 				return 1;
69274a4d8c2SCharles.Forsyth 			return 0;
69374a4d8c2SCharles.Forsyth 		}
69474a4d8c2SCharles.Forsyth 		if(copyau(&p->to, v))
69574a4d8c2SCharles.Forsyth 			return 4;
69674a4d8c2SCharles.Forsyth 		return 3;
69774a4d8c2SCharles.Forsyth 	}
69874a4d8c2SCharles.Forsyth 	return 0;
69974a4d8c2SCharles.Forsyth }
70074a4d8c2SCharles.Forsyth 
70174a4d8c2SCharles.Forsyth /*
70274a4d8c2SCharles.Forsyth  * direct reference,
70374a4d8c2SCharles.Forsyth  * could be set/use depending on
70474a4d8c2SCharles.Forsyth  * semantics
70574a4d8c2SCharles.Forsyth  */
70674a4d8c2SCharles.Forsyth int
copyas(Adr * a,Adr * v)70774a4d8c2SCharles.Forsyth copyas(Adr *a, Adr *v)
70874a4d8c2SCharles.Forsyth {
70974a4d8c2SCharles.Forsyth 	if(a->type != v->type)
71074a4d8c2SCharles.Forsyth 		return 0;
71174a4d8c2SCharles.Forsyth 	if(regtyp(v))
71274a4d8c2SCharles.Forsyth 		return 1;
71374a4d8c2SCharles.Forsyth 	if(v->type == D_AUTO || v->type == D_PARAM)
71474a4d8c2SCharles.Forsyth 		if(v->offset == a->offset)
71574a4d8c2SCharles.Forsyth 			return 1;
71674a4d8c2SCharles.Forsyth 	return 0;
71774a4d8c2SCharles.Forsyth }
71874a4d8c2SCharles.Forsyth 
71974a4d8c2SCharles.Forsyth /*
72074a4d8c2SCharles.Forsyth  * either direct or indirect
72174a4d8c2SCharles.Forsyth  */
72274a4d8c2SCharles.Forsyth int
copyau(Adr * a,Adr * v)72374a4d8c2SCharles.Forsyth copyau(Adr *a, Adr *v)
72474a4d8c2SCharles.Forsyth {
72574a4d8c2SCharles.Forsyth 
72674a4d8c2SCharles.Forsyth 	if(copyas(a, v))
72774a4d8c2SCharles.Forsyth 		return 1;
72874a4d8c2SCharles.Forsyth 	if(regtyp(v)) {
72974a4d8c2SCharles.Forsyth 		if(a->type-D_INDIR == v->type)
73074a4d8c2SCharles.Forsyth 			return 1;
73174a4d8c2SCharles.Forsyth 		if(a->index == v->type)
73274a4d8c2SCharles.Forsyth 			return 1;
73374a4d8c2SCharles.Forsyth 	}
73474a4d8c2SCharles.Forsyth 	return 0;
73574a4d8c2SCharles.Forsyth }
73674a4d8c2SCharles.Forsyth 
73774a4d8c2SCharles.Forsyth /*
73874a4d8c2SCharles.Forsyth  * substitute s for v in a
73974a4d8c2SCharles.Forsyth  * return failure to substitute
74074a4d8c2SCharles.Forsyth  */
74174a4d8c2SCharles.Forsyth int
copysub(Adr * a,Adr * v,Adr * s,int f)74274a4d8c2SCharles.Forsyth copysub(Adr *a, Adr *v, Adr *s, int f)
74374a4d8c2SCharles.Forsyth {
74474a4d8c2SCharles.Forsyth 	int t;
74574a4d8c2SCharles.Forsyth 
74674a4d8c2SCharles.Forsyth 	if(copyas(a, v)) {
74774a4d8c2SCharles.Forsyth 		t = s->type;
74874a4d8c2SCharles.Forsyth 		if(t >= D_AX && t <= D_DI) {
74974a4d8c2SCharles.Forsyth 			if(f)
75074a4d8c2SCharles.Forsyth 				a->type = t;
75174a4d8c2SCharles.Forsyth 		}
75274a4d8c2SCharles.Forsyth 		return 0;
75374a4d8c2SCharles.Forsyth 	}
75474a4d8c2SCharles.Forsyth 	if(regtyp(v)) {
75574a4d8c2SCharles.Forsyth 		t = v->type;
75674a4d8c2SCharles.Forsyth 		if(a->type == t+D_INDIR) {
75774a4d8c2SCharles.Forsyth 			if(s->type == D_BP && a->index != D_NONE)
75874a4d8c2SCharles.Forsyth 				return 1;	/* can't use BP-base with index */
75974a4d8c2SCharles.Forsyth 			if(f)
76074a4d8c2SCharles.Forsyth 				a->type = s->type+D_INDIR;
76174a4d8c2SCharles.Forsyth //			return 0;
76274a4d8c2SCharles.Forsyth 		}
76374a4d8c2SCharles.Forsyth 		if(a->index == t) {
76474a4d8c2SCharles.Forsyth 			if(f)
76574a4d8c2SCharles.Forsyth 				a->index = s->type;
76674a4d8c2SCharles.Forsyth 			return 0;
76774a4d8c2SCharles.Forsyth 		}
76874a4d8c2SCharles.Forsyth 		return 0;
76974a4d8c2SCharles.Forsyth 	}
77074a4d8c2SCharles.Forsyth 	return 0;
77174a4d8c2SCharles.Forsyth }
772