xref: /plan9/sys/src/cmd/5c/peep.c (revision 27acba7cf6d37c65abba4ecf8ad572a5980447ad)
17dd7cddfSDavid du Colombier #include "gc.h"
27dd7cddfSDavid du Colombier 
359cc4ca5SDavid du Colombier int xtramodes(Reg*, Adr*);
459cc4ca5SDavid du Colombier 
57dd7cddfSDavid du Colombier void
peep(void)67dd7cddfSDavid du Colombier peep(void)
77dd7cddfSDavid du Colombier {
87dd7cddfSDavid du Colombier 	Reg *r, *r1, *r2;
97dd7cddfSDavid du Colombier 	Prog *p, *p1;
107dd7cddfSDavid du Colombier 	int t;
117dd7cddfSDavid du Colombier /*
127dd7cddfSDavid du Colombier  * complete R structure
137dd7cddfSDavid du Colombier  */
147dd7cddfSDavid du Colombier 	t = 0;
157dd7cddfSDavid du Colombier 	for(r=firstr; r!=R; r=r1) {
167dd7cddfSDavid du Colombier 		r1 = r->link;
177dd7cddfSDavid du Colombier 		if(r1 == R)
187dd7cddfSDavid du Colombier 			break;
197dd7cddfSDavid du Colombier 		p = r->prog->link;
207dd7cddfSDavid du Colombier 		while(p != r1->prog)
217dd7cddfSDavid du Colombier 		switch(p->as) {
227dd7cddfSDavid du Colombier 		default:
237dd7cddfSDavid du Colombier 			r2 = rega();
247dd7cddfSDavid du Colombier 			r->link = r2;
257dd7cddfSDavid du Colombier 			r2->link = r1;
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier 			r2->prog = p;
287dd7cddfSDavid du Colombier 			r2->p1 = r;
297dd7cddfSDavid du Colombier 			r->s1 = r2;
307dd7cddfSDavid du Colombier 			r2->s1 = r1;
317dd7cddfSDavid du Colombier 			r1->p1 = r2;
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier 			r = r2;
347dd7cddfSDavid du Colombier 			t++;
357dd7cddfSDavid du Colombier 
367dd7cddfSDavid du Colombier 		case ADATA:
377dd7cddfSDavid du Colombier 		case AGLOBL:
387dd7cddfSDavid du Colombier 		case ANAME:
39375daca8SDavid du Colombier 		case ASIGNAME:
407dd7cddfSDavid du Colombier 			p = p->link;
417dd7cddfSDavid du Colombier 		}
427dd7cddfSDavid du Colombier 	}
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier loop1:
457dd7cddfSDavid du Colombier 	t = 0;
467dd7cddfSDavid du Colombier 	for(r=firstr; r!=R; r=r->link) {
477dd7cddfSDavid du Colombier 		p = r->prog;
4859cc4ca5SDavid du Colombier 		if(p->as == ASLL || p->as == ASRL || p->as == ASRA) {
4959cc4ca5SDavid du Colombier 			/*
5059cc4ca5SDavid du Colombier 			 * elide shift into D_SHIFT operand of subsequent instruction
5159cc4ca5SDavid du Colombier 			 */
5259cc4ca5SDavid du Colombier 			if(shiftprop(r)) {
5359cc4ca5SDavid du Colombier 				excise(r);
5459cc4ca5SDavid du Colombier 				t++;
5559cc4ca5SDavid du Colombier 			}
5659cc4ca5SDavid du Colombier 		}
577dd7cddfSDavid du Colombier 		if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
587dd7cddfSDavid du Colombier 		if(regtyp(&p->to)) {
5959cc4ca5SDavid du Colombier 			if(p->from.type == D_CONST)
6059cc4ca5SDavid du Colombier 				constprop(&p->from, &p->to, r->s1);
6159cc4ca5SDavid du Colombier 			else if(regtyp(&p->from))
627dd7cddfSDavid du Colombier 			if(p->from.type == p->to.type) {
637dd7cddfSDavid du Colombier 				if(copyprop(r)) {
647dd7cddfSDavid du Colombier 					excise(r);
657dd7cddfSDavid du Colombier 					t++;
667dd7cddfSDavid du Colombier 				} else
677dd7cddfSDavid du Colombier 				if(subprop(r) && copyprop(r)) {
687dd7cddfSDavid du Colombier 					excise(r);
697dd7cddfSDavid du Colombier 					t++;
707dd7cddfSDavid du Colombier 				}
717dd7cddfSDavid du Colombier 			}
727dd7cddfSDavid du Colombier 		}
737dd7cddfSDavid du Colombier 	}
747dd7cddfSDavid du Colombier 	if(t)
757dd7cddfSDavid du Colombier 		goto loop1;
767dd7cddfSDavid du Colombier 	/*
777dd7cddfSDavid du Colombier 	 * look for MOVB x,R; MOVB R,R
787dd7cddfSDavid du Colombier 	 */
797dd7cddfSDavid du Colombier 	for(r=firstr; r!=R; r=r->link) {
807dd7cddfSDavid du Colombier 		p = r->prog;
817dd7cddfSDavid du Colombier 		switch(p->as) {
827dd7cddfSDavid du Colombier 		default:
837dd7cddfSDavid du Colombier 			continue;
8459cc4ca5SDavid du Colombier 		case AEOR:
8559cc4ca5SDavid du Colombier 			/*
8659cc4ca5SDavid du Colombier 			 * EOR -1,x,y => MVN x,y
8759cc4ca5SDavid du Colombier 			 */
8859cc4ca5SDavid du Colombier 			if(p->from.type == D_CONST && p->from.offset == -1) {
8959cc4ca5SDavid du Colombier 				p->as = AMVN;
9059cc4ca5SDavid du Colombier 				p->from.type = D_REG;
9159cc4ca5SDavid du Colombier 				if(p->reg != NREG)
9259cc4ca5SDavid du Colombier 					p->from.reg = p->reg;
9359cc4ca5SDavid du Colombier 				else
9459cc4ca5SDavid du Colombier 					p->from.reg = p->to.reg;
9559cc4ca5SDavid du Colombier 				p->reg = NREG;
9659cc4ca5SDavid du Colombier 			}
9759cc4ca5SDavid du Colombier 			continue;
987dd7cddfSDavid du Colombier 		case AMOVH:
997dd7cddfSDavid du Colombier 		case AMOVHU:
1007dd7cddfSDavid du Colombier 		case AMOVB:
1017dd7cddfSDavid du Colombier 		case AMOVBU:
1027dd7cddfSDavid du Colombier 			if(p->to.type != D_REG)
1037dd7cddfSDavid du Colombier 				continue;
1047dd7cddfSDavid du Colombier 			break;
1057dd7cddfSDavid du Colombier 		}
1067dd7cddfSDavid du Colombier 		r1 = r->link;
1077dd7cddfSDavid du Colombier 		if(r1 == R)
1087dd7cddfSDavid du Colombier 			continue;
1097dd7cddfSDavid du Colombier 		p1 = r1->prog;
1107dd7cddfSDavid du Colombier 		if(p1->as != p->as)
1117dd7cddfSDavid du Colombier 			continue;
1127dd7cddfSDavid du Colombier 		if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
1137dd7cddfSDavid du Colombier 			continue;
1147dd7cddfSDavid du Colombier 		if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
1157dd7cddfSDavid du Colombier 			continue;
1167dd7cddfSDavid du Colombier 		excise(r1);
1177dd7cddfSDavid du Colombier 	}
1187dd7cddfSDavid du Colombier 
11959cc4ca5SDavid du Colombier 	for(r=firstr; r!=R; r=r->link) {
12059cc4ca5SDavid du Colombier 		p = r->prog;
12159cc4ca5SDavid du Colombier 		switch(p->as) {
12259cc4ca5SDavid du Colombier 		case AMOVW:
12359cc4ca5SDavid du Colombier 		case AMOVB:
12459cc4ca5SDavid du Colombier 		case AMOVBU:
12559cc4ca5SDavid du Colombier 			if(p->from.type == D_OREG && p->from.offset == 0)
12659cc4ca5SDavid du Colombier 				xtramodes(r, &p->from);
12759cc4ca5SDavid du Colombier 			else if(p->to.type == D_OREG && p->to.offset == 0)
12859cc4ca5SDavid du Colombier 				xtramodes(r, &p->to);
12959cc4ca5SDavid du Colombier 			else
13059cc4ca5SDavid du Colombier 				continue;
13159cc4ca5SDavid du Colombier 			break;
13259cc4ca5SDavid du Colombier 		case ACMP:
13359cc4ca5SDavid du Colombier 			/*
13459cc4ca5SDavid du Colombier 			 * elide CMP $0,x if calculation of x can set condition codes
13559cc4ca5SDavid du Colombier 			 */
13659cc4ca5SDavid du Colombier 			if(p->from.type != D_CONST || p->from.offset != 0)
13759cc4ca5SDavid du Colombier 				continue;
13859cc4ca5SDavid du Colombier 			r2 = r->s1;
13959cc4ca5SDavid du Colombier 			if(r2 == R)
14059cc4ca5SDavid du Colombier 				continue;
14159cc4ca5SDavid du Colombier 			t = r2->prog->as;
14259cc4ca5SDavid du Colombier 			switch(t) {
14359cc4ca5SDavid du Colombier 			default:
14459cc4ca5SDavid du Colombier 				continue;
14559cc4ca5SDavid du Colombier 			case ABEQ:
14659cc4ca5SDavid du Colombier 			case ABNE:
14759cc4ca5SDavid du Colombier 			case ABMI:
14859cc4ca5SDavid du Colombier 			case ABPL:
14959cc4ca5SDavid du Colombier 				break;
15059cc4ca5SDavid du Colombier 			case ABGE:
15159cc4ca5SDavid du Colombier 				t = ABPL;
15259cc4ca5SDavid du Colombier 				break;
15359cc4ca5SDavid du Colombier 			case ABLT:
15459cc4ca5SDavid du Colombier 				t = ABMI;
15559cc4ca5SDavid du Colombier 				break;
15659cc4ca5SDavid du Colombier 			case ABHI:
15759cc4ca5SDavid du Colombier 				t = ABNE;
15859cc4ca5SDavid du Colombier 				break;
15959cc4ca5SDavid du Colombier 			case ABLS:
16059cc4ca5SDavid du Colombier 				t = ABEQ;
16159cc4ca5SDavid du Colombier 				break;
16259cc4ca5SDavid du Colombier 			}
16359cc4ca5SDavid du Colombier 			r1 = r;
16459cc4ca5SDavid du Colombier 			do
16559cc4ca5SDavid du Colombier 				r1 = uniqp(r1);
16659cc4ca5SDavid du Colombier 			while (r1 != R && r1->prog->as == ANOP);
16759cc4ca5SDavid du Colombier 			if(r1 == R)
16859cc4ca5SDavid du Colombier 				continue;
16959cc4ca5SDavid du Colombier 			p1 = r1->prog;
17059cc4ca5SDavid du Colombier 			if(p1->to.type != D_REG)
17159cc4ca5SDavid du Colombier 				continue;
17259cc4ca5SDavid du Colombier 			if(p1->to.reg != p->reg)
17359cc4ca5SDavid du Colombier 			if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
17459cc4ca5SDavid du Colombier 				continue;
17559cc4ca5SDavid du Colombier 			switch(p1->as) {
17659cc4ca5SDavid du Colombier 			default:
17759cc4ca5SDavid du Colombier 				continue;
17859cc4ca5SDavid du Colombier 			case AMOVW:
17959cc4ca5SDavid du Colombier 				if(p1->from.type != D_REG)
18059cc4ca5SDavid du Colombier 					continue;
18159cc4ca5SDavid du Colombier 			case AAND:
18259cc4ca5SDavid du Colombier 			case AEOR:
18359cc4ca5SDavid du Colombier 			case AORR:
18459cc4ca5SDavid du Colombier 			case ABIC:
18559cc4ca5SDavid du Colombier 			case AMVN:
18659cc4ca5SDavid du Colombier 			case ASUB:
18759cc4ca5SDavid du Colombier 			case ARSB:
18859cc4ca5SDavid du Colombier 			case AADD:
18959cc4ca5SDavid du Colombier 			case AADC:
19059cc4ca5SDavid du Colombier 			case ASBC:
19159cc4ca5SDavid du Colombier 			case ARSC:
19259cc4ca5SDavid du Colombier 				break;
19359cc4ca5SDavid du Colombier 			}
19459cc4ca5SDavid du Colombier 			p1->scond |= C_SBIT;
19559cc4ca5SDavid du Colombier 			r2->prog->as = t;
19659cc4ca5SDavid du Colombier 			excise(r);
19759cc4ca5SDavid du Colombier 			continue;
19859cc4ca5SDavid du Colombier 		}
19959cc4ca5SDavid du Colombier 	}
20059cc4ca5SDavid du Colombier 
2017dd7cddfSDavid du Colombier 	predicate();
2027dd7cddfSDavid du Colombier }
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier void
excise(Reg * r)2057dd7cddfSDavid du Colombier excise(Reg *r)
2067dd7cddfSDavid du Colombier {
2077dd7cddfSDavid du Colombier 	Prog *p;
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier 	p = r->prog;
2107dd7cddfSDavid du Colombier 	p->as = ANOP;
21159cc4ca5SDavid du Colombier 	p->scond = zprog.scond;
2127dd7cddfSDavid du Colombier 	p->from = zprog.from;
2137dd7cddfSDavid du Colombier 	p->to = zprog.to;
2147dd7cddfSDavid du Colombier 	p->reg = zprog.reg; /**/
2157dd7cddfSDavid du Colombier }
2167dd7cddfSDavid du Colombier 
2177dd7cddfSDavid du Colombier Reg*
uniqp(Reg * r)2187dd7cddfSDavid du Colombier uniqp(Reg *r)
2197dd7cddfSDavid du Colombier {
2207dd7cddfSDavid du Colombier 	Reg *r1;
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier 	r1 = r->p1;
2237dd7cddfSDavid du Colombier 	if(r1 == R) {
2247dd7cddfSDavid du Colombier 		r1 = r->p2;
2257dd7cddfSDavid du Colombier 		if(r1 == R || r1->p2link != R)
2267dd7cddfSDavid du Colombier 			return R;
2277dd7cddfSDavid du Colombier 	} else
2287dd7cddfSDavid du Colombier 		if(r->p2 != R)
2297dd7cddfSDavid du Colombier 			return R;
2307dd7cddfSDavid du Colombier 	return r1;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier 
2337dd7cddfSDavid du Colombier Reg*
uniqs(Reg * r)2347dd7cddfSDavid du Colombier uniqs(Reg *r)
2357dd7cddfSDavid du Colombier {
2367dd7cddfSDavid du Colombier 	Reg *r1;
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier 	r1 = r->s1;
2397dd7cddfSDavid du Colombier 	if(r1 == R) {
2407dd7cddfSDavid du Colombier 		r1 = r->s2;
2417dd7cddfSDavid du Colombier 		if(r1 == R)
2427dd7cddfSDavid du Colombier 			return R;
2437dd7cddfSDavid du Colombier 	} else
2447dd7cddfSDavid du Colombier 		if(r->s2 != R)
2457dd7cddfSDavid du Colombier 			return R;
2467dd7cddfSDavid du Colombier 	return r1;
2477dd7cddfSDavid du Colombier }
2487dd7cddfSDavid du Colombier 
2497dd7cddfSDavid du Colombier int
regtyp(Adr * a)2507dd7cddfSDavid du Colombier regtyp(Adr *a)
2517dd7cddfSDavid du Colombier {
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier 	if(a->type == D_REG)
2547dd7cddfSDavid du Colombier 		return 1;
2557dd7cddfSDavid du Colombier 	if(a->type == D_FREG)
2567dd7cddfSDavid du Colombier 		return 1;
2577dd7cddfSDavid du Colombier 	return 0;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier /*
2617dd7cddfSDavid du Colombier  * the idea is to substitute
2627dd7cddfSDavid du Colombier  * one register for another
2637dd7cddfSDavid du Colombier  * from one MOV to another
2647dd7cddfSDavid du Colombier  *	MOV	a, R0
2657dd7cddfSDavid du Colombier  *	ADD	b, R0	/ no use of R1
2667dd7cddfSDavid du Colombier  *	MOV	R0, R1
2677dd7cddfSDavid du Colombier  * would be converted to
2687dd7cddfSDavid du Colombier  *	MOV	a, R1
2697dd7cddfSDavid du Colombier  *	ADD	b, R1
2707dd7cddfSDavid du Colombier  *	MOV	R1, R0
2717dd7cddfSDavid du Colombier  * hopefully, then the former or latter MOV
2727dd7cddfSDavid du Colombier  * will be eliminated by copy propagation.
2737dd7cddfSDavid du Colombier  */
2747dd7cddfSDavid du Colombier int
subprop(Reg * r0)2757dd7cddfSDavid du Colombier subprop(Reg *r0)
2767dd7cddfSDavid du Colombier {
2777dd7cddfSDavid du Colombier 	Prog *p;
2787dd7cddfSDavid du Colombier 	Adr *v1, *v2;
2797dd7cddfSDavid du Colombier 	Reg *r;
2807dd7cddfSDavid du Colombier 	int t;
2817dd7cddfSDavid du Colombier 
2827dd7cddfSDavid du Colombier 	p = r0->prog;
2837dd7cddfSDavid du Colombier 	v1 = &p->from;
2847dd7cddfSDavid du Colombier 	if(!regtyp(v1))
2857dd7cddfSDavid du Colombier 		return 0;
2867dd7cddfSDavid du Colombier 	v2 = &p->to;
2877dd7cddfSDavid du Colombier 	if(!regtyp(v2))
2887dd7cddfSDavid du Colombier 		return 0;
2897dd7cddfSDavid du Colombier 	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
2907dd7cddfSDavid du Colombier 		if(uniqs(r) == R)
2917dd7cddfSDavid du Colombier 			break;
2927dd7cddfSDavid du Colombier 		p = r->prog;
2937dd7cddfSDavid du Colombier 		switch(p->as) {
2947dd7cddfSDavid du Colombier 		case ABL:
2957dd7cddfSDavid du Colombier 			return 0;
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 		case ACMP:
29859cc4ca5SDavid du Colombier 		case ACMN:
2997dd7cddfSDavid du Colombier 		case AADD:
3007dd7cddfSDavid du Colombier 		case ASUB:
3017dd7cddfSDavid du Colombier 		case ARSB:
3027dd7cddfSDavid du Colombier 		case ASLL:
3037dd7cddfSDavid du Colombier 		case ASRL:
3047dd7cddfSDavid du Colombier 		case ASRA:
3057dd7cddfSDavid du Colombier 		case AORR:
3067dd7cddfSDavid du Colombier 		case AAND:
3077dd7cddfSDavid du Colombier 		case AEOR:
3087dd7cddfSDavid du Colombier 		case AMUL:
3097dd7cddfSDavid du Colombier 		case ADIV:
3107dd7cddfSDavid du Colombier 		case ADIVU:
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier 		case ACMPF:
3137dd7cddfSDavid du Colombier 		case ACMPD:
3147dd7cddfSDavid du Colombier 		case AADDD:
3157dd7cddfSDavid du Colombier 		case AADDF:
3167dd7cddfSDavid du Colombier 		case ASUBD:
3177dd7cddfSDavid du Colombier 		case ASUBF:
3187dd7cddfSDavid du Colombier 		case AMULD:
3197dd7cddfSDavid du Colombier 		case AMULF:
3207dd7cddfSDavid du Colombier 		case ADIVD:
3217dd7cddfSDavid du Colombier 		case ADIVF:
3227dd7cddfSDavid du Colombier 			if(p->to.type == v1->type)
3237dd7cddfSDavid du Colombier 			if(p->to.reg == v1->reg) {
3247dd7cddfSDavid du Colombier 				if(p->reg == NREG)
3257dd7cddfSDavid du Colombier 					p->reg = p->to.reg;
3267dd7cddfSDavid du Colombier 				goto gotit;
3277dd7cddfSDavid du Colombier 			}
3287dd7cddfSDavid du Colombier 			break;
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 		case AMOVF:
3317dd7cddfSDavid du Colombier 		case AMOVD:
3327dd7cddfSDavid du Colombier 		case AMOVW:
3337dd7cddfSDavid du Colombier 			if(p->to.type == v1->type)
3347dd7cddfSDavid du Colombier 			if(p->to.reg == v1->reg)
3357dd7cddfSDavid du Colombier 				goto gotit;
3367dd7cddfSDavid du Colombier 			break;
33759cc4ca5SDavid du Colombier 
33859cc4ca5SDavid du Colombier 		case AMOVM:
33959cc4ca5SDavid du Colombier 			t = 1<<v2->reg;
34059cc4ca5SDavid du Colombier 			if((p->from.type == D_CONST && (p->from.offset&t)) ||
34159cc4ca5SDavid du Colombier 			   (p->to.type == D_CONST && (p->to.offset&t)))
34259cc4ca5SDavid du Colombier 				return 0;
34359cc4ca5SDavid du Colombier 			break;
3447dd7cddfSDavid du Colombier 		}
3457dd7cddfSDavid du Colombier 		if(copyau(&p->from, v2) ||
3467dd7cddfSDavid du Colombier 		   copyau1(p, v2) ||
3477dd7cddfSDavid du Colombier 		   copyau(&p->to, v2))
3487dd7cddfSDavid du Colombier 			break;
3497dd7cddfSDavid du Colombier 		if(copysub(&p->from, v1, v2, 0) ||
3507dd7cddfSDavid du Colombier 		   copysub1(p, v1, v2, 0) ||
3517dd7cddfSDavid du Colombier 		   copysub(&p->to, v1, v2, 0))
3527dd7cddfSDavid du Colombier 			break;
3537dd7cddfSDavid du Colombier 	}
3547dd7cddfSDavid du Colombier 	return 0;
3557dd7cddfSDavid du Colombier 
3567dd7cddfSDavid du Colombier gotit:
3577dd7cddfSDavid du Colombier 	copysub(&p->to, v1, v2, 1);
3587dd7cddfSDavid du Colombier 	if(debug['P']) {
3597dd7cddfSDavid du Colombier 		print("gotit: %D->%D\n%P", v1, v2, r->prog);
3607dd7cddfSDavid du Colombier 		if(p->from.type == v2->type)
3617dd7cddfSDavid du Colombier 			print(" excise");
3627dd7cddfSDavid du Colombier 		print("\n");
3637dd7cddfSDavid du Colombier 	}
3647dd7cddfSDavid du Colombier 	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
3657dd7cddfSDavid du Colombier 		p = r->prog;
3667dd7cddfSDavid du Colombier 		copysub(&p->from, v1, v2, 1);
3677dd7cddfSDavid du Colombier 		copysub1(p, v1, v2, 1);
3687dd7cddfSDavid du Colombier 		copysub(&p->to, v1, v2, 1);
3697dd7cddfSDavid du Colombier 		if(debug['P'])
3707dd7cddfSDavid du Colombier 			print("%P\n", r->prog);
3717dd7cddfSDavid du Colombier 	}
3727dd7cddfSDavid du Colombier 	t = v1->reg;
3737dd7cddfSDavid du Colombier 	v1->reg = v2->reg;
3747dd7cddfSDavid du Colombier 	v2->reg = t;
3757dd7cddfSDavid du Colombier 	if(debug['P'])
3767dd7cddfSDavid du Colombier 		print("%P last\n", r->prog);
3777dd7cddfSDavid du Colombier 	return 1;
3787dd7cddfSDavid du Colombier }
3797dd7cddfSDavid du Colombier 
3807dd7cddfSDavid du Colombier /*
3817dd7cddfSDavid du Colombier  * The idea is to remove redundant copies.
3827dd7cddfSDavid du Colombier  *	v1->v2	F=0
3837dd7cddfSDavid du Colombier  *	(use v2	s/v2/v1/)*
3847dd7cddfSDavid du Colombier  *	set v1	F=1
3857dd7cddfSDavid du Colombier  *	use v2	return fail
3867dd7cddfSDavid du Colombier  *	-----------------
3877dd7cddfSDavid du Colombier  *	v1->v2	F=0
3887dd7cddfSDavid du Colombier  *	(use v2	s/v2/v1/)*
3897dd7cddfSDavid du Colombier  *	set v1	F=1
3907dd7cddfSDavid du Colombier  *	set v2	return success
3917dd7cddfSDavid du Colombier  */
3927dd7cddfSDavid du Colombier int
copyprop(Reg * r0)3937dd7cddfSDavid du Colombier copyprop(Reg *r0)
3947dd7cddfSDavid du Colombier {
3957dd7cddfSDavid du Colombier 	Prog *p;
3967dd7cddfSDavid du Colombier 	Adr *v1, *v2;
3977dd7cddfSDavid du Colombier 	Reg *r;
3987dd7cddfSDavid du Colombier 
3997dd7cddfSDavid du Colombier 	p = r0->prog;
4007dd7cddfSDavid du Colombier 	v1 = &p->from;
4017dd7cddfSDavid du Colombier 	v2 = &p->to;
4027dd7cddfSDavid du Colombier 	if(copyas(v1, v2))
4037dd7cddfSDavid du Colombier 		return 1;
4047dd7cddfSDavid du Colombier 	for(r=firstr; r!=R; r=r->link)
4057dd7cddfSDavid du Colombier 		r->active = 0;
4067dd7cddfSDavid du Colombier 	return copy1(v1, v2, r0->s1, 0);
4077dd7cddfSDavid du Colombier }
4087dd7cddfSDavid du Colombier 
4097dd7cddfSDavid du Colombier int
copy1(Adr * v1,Adr * v2,Reg * r,int f)4107dd7cddfSDavid du Colombier copy1(Adr *v1, Adr *v2, Reg *r, int f)
4117dd7cddfSDavid du Colombier {
4127dd7cddfSDavid du Colombier 	int t;
4137dd7cddfSDavid du Colombier 	Prog *p;
4147dd7cddfSDavid du Colombier 
4157dd7cddfSDavid du Colombier 	if(r->active) {
4167dd7cddfSDavid du Colombier 		if(debug['P'])
4177dd7cddfSDavid du Colombier 			print("act set; return 1\n");
4187dd7cddfSDavid du Colombier 		return 1;
4197dd7cddfSDavid du Colombier 	}
4207dd7cddfSDavid du Colombier 	r->active = 1;
4217dd7cddfSDavid du Colombier 	if(debug['P'])
4227dd7cddfSDavid du Colombier 		print("copy %D->%D f=%d\n", v1, v2, f);
4237dd7cddfSDavid du Colombier 	for(; r != R; r = r->s1) {
4247dd7cddfSDavid du Colombier 		p = r->prog;
4257dd7cddfSDavid du Colombier 		if(debug['P'])
4267dd7cddfSDavid du Colombier 			print("%P", p);
4277dd7cddfSDavid du Colombier 		if(!f && uniqp(r) == R) {
4287dd7cddfSDavid du Colombier 			f = 1;
4297dd7cddfSDavid du Colombier 			if(debug['P'])
4307dd7cddfSDavid du Colombier 				print("; merge; f=%d", f);
4317dd7cddfSDavid du Colombier 		}
4327dd7cddfSDavid du Colombier 		t = copyu(p, v2, A);
4337dd7cddfSDavid du Colombier 		switch(t) {
4347dd7cddfSDavid du Colombier 		case 2:	/* rar, cant split */
4357dd7cddfSDavid du Colombier 			if(debug['P'])
4367dd7cddfSDavid du Colombier 				print("; %Drar; return 0\n", v2);
4377dd7cddfSDavid du Colombier 			return 0;
4387dd7cddfSDavid du Colombier 
4397dd7cddfSDavid du Colombier 		case 3:	/* set */
4407dd7cddfSDavid du Colombier 			if(debug['P'])
4417dd7cddfSDavid du Colombier 				print("; %Dset; return 1\n", v2);
4427dd7cddfSDavid du Colombier 			return 1;
4437dd7cddfSDavid du Colombier 
4447dd7cddfSDavid du Colombier 		case 1:	/* used, substitute */
4457dd7cddfSDavid du Colombier 		case 4:	/* use and set */
4467dd7cddfSDavid du Colombier 			if(f) {
4477dd7cddfSDavid du Colombier 				if(!debug['P'])
4487dd7cddfSDavid du Colombier 					return 0;
4497dd7cddfSDavid du Colombier 				if(t == 4)
4507dd7cddfSDavid du Colombier 					print("; %Dused+set and f=%d; return 0\n", v2, f);
4517dd7cddfSDavid du Colombier 				else
4527dd7cddfSDavid du Colombier 					print("; %Dused and f=%d; return 0\n", v2, f);
4537dd7cddfSDavid du Colombier 				return 0;
4547dd7cddfSDavid du Colombier 			}
4557dd7cddfSDavid du Colombier 			if(copyu(p, v2, v1)) {
4567dd7cddfSDavid du Colombier 				if(debug['P'])
4577dd7cddfSDavid du Colombier 					print("; sub fail; return 0\n");
4587dd7cddfSDavid du Colombier 				return 0;
4597dd7cddfSDavid du Colombier 			}
4607dd7cddfSDavid du Colombier 			if(debug['P'])
4617dd7cddfSDavid du Colombier 				print("; sub%D/%D", v2, v1);
4627dd7cddfSDavid du Colombier 			if(t == 4) {
4637dd7cddfSDavid du Colombier 				if(debug['P'])
4647dd7cddfSDavid du Colombier 					print("; %Dused+set; return 1\n", v2);
4657dd7cddfSDavid du Colombier 				return 1;
4667dd7cddfSDavid du Colombier 			}
4677dd7cddfSDavid du Colombier 			break;
4687dd7cddfSDavid du Colombier 		}
4697dd7cddfSDavid du Colombier 		if(!f) {
4707dd7cddfSDavid du Colombier 			t = copyu(p, v1, A);
4717dd7cddfSDavid du Colombier 			if(!f && (t == 2 || t == 3 || t == 4)) {
4727dd7cddfSDavid du Colombier 				f = 1;
4737dd7cddfSDavid du Colombier 				if(debug['P'])
4747dd7cddfSDavid du Colombier 					print("; %Dset and !f; f=%d", v1, f);
4757dd7cddfSDavid du Colombier 			}
4767dd7cddfSDavid du Colombier 		}
4777dd7cddfSDavid du Colombier 		if(debug['P'])
4787dd7cddfSDavid du Colombier 			print("\n");
4797dd7cddfSDavid du Colombier 		if(r->s2)
4807dd7cddfSDavid du Colombier 			if(!copy1(v1, v2, r->s2, f))
4817dd7cddfSDavid du Colombier 				return 0;
4827dd7cddfSDavid du Colombier 	}
4837dd7cddfSDavid du Colombier 	return 1;
4847dd7cddfSDavid du Colombier }
4857dd7cddfSDavid du Colombier 
4867dd7cddfSDavid du Colombier /*
48759cc4ca5SDavid du Colombier  * The idea is to remove redundant constants.
48859cc4ca5SDavid du Colombier  *	$c1->v1
48959cc4ca5SDavid du Colombier  *	($c1->v2 s/$c1/v1)*
49059cc4ca5SDavid du Colombier  *	set v1  return
49159cc4ca5SDavid du Colombier  * The v1->v2 should be eliminated by copy propagation.
49259cc4ca5SDavid du Colombier  */
49359cc4ca5SDavid du Colombier void
constprop(Adr * c1,Adr * v1,Reg * r)49459cc4ca5SDavid du Colombier constprop(Adr *c1, Adr *v1, Reg *r)
49559cc4ca5SDavid du Colombier {
49659cc4ca5SDavid du Colombier 	Prog *p;
49759cc4ca5SDavid du Colombier 
49859cc4ca5SDavid du Colombier 	if(debug['C'])
49959cc4ca5SDavid du Colombier 		print("constprop %D->%D\n", c1, v1);
50059cc4ca5SDavid du Colombier 	for(; r != R; r = r->s1) {
50159cc4ca5SDavid du Colombier 		p = r->prog;
50259cc4ca5SDavid du Colombier 		if(debug['C'])
50359cc4ca5SDavid du Colombier 			print("%P", p);
50459cc4ca5SDavid du Colombier 		if(uniqp(r) == R) {
50559cc4ca5SDavid du Colombier 			if(debug['C'])
50659cc4ca5SDavid du Colombier 				print("; merge; return\n");
50759cc4ca5SDavid du Colombier 			return;
50859cc4ca5SDavid du Colombier 		}
50959cc4ca5SDavid du Colombier 		if(p->as == AMOVW && copyas(&p->from, c1)) {
51059cc4ca5SDavid du Colombier 				if(debug['C'])
51159cc4ca5SDavid du Colombier 					print("; sub%D/%D", &p->from, v1);
51259cc4ca5SDavid du Colombier 				p->from = *v1;
51359cc4ca5SDavid du Colombier 		} else if(copyu(p, v1, A) > 1) {
51459cc4ca5SDavid du Colombier 			if(debug['C'])
51559cc4ca5SDavid du Colombier 				print("; %Dset; return\n", v1);
51659cc4ca5SDavid du Colombier 			return;
51759cc4ca5SDavid du Colombier 		}
51859cc4ca5SDavid du Colombier 		if(debug['C'])
51959cc4ca5SDavid du Colombier 			print("\n");
52059cc4ca5SDavid du Colombier 		if(r->s2)
52159cc4ca5SDavid du Colombier 			constprop(c1, v1, r->s2);
52259cc4ca5SDavid du Colombier 	}
52359cc4ca5SDavid du Colombier }
52459cc4ca5SDavid du Colombier 
52559cc4ca5SDavid du Colombier /*
52659cc4ca5SDavid du Colombier  * ASLL x,y,w
52759cc4ca5SDavid du Colombier  * .. (not use w, not set x y w)
52859cc4ca5SDavid du Colombier  * AXXX w,a,b (a != w)
52959cc4ca5SDavid du Colombier  * .. (not use w)
53059cc4ca5SDavid du Colombier  * (set w)
53159cc4ca5SDavid du Colombier  * ----------- changed to
53259cc4ca5SDavid du Colombier  * ..
53359cc4ca5SDavid du Colombier  * AXXX (x<<y),a,b
53459cc4ca5SDavid du Colombier  * ..
53559cc4ca5SDavid du Colombier  */
53659cc4ca5SDavid du Colombier #define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
53759cc4ca5SDavid du Colombier int
shiftprop(Reg * r)53859cc4ca5SDavid du Colombier shiftprop(Reg *r)
53959cc4ca5SDavid du Colombier {
54059cc4ca5SDavid du Colombier 	Reg *r1;
54159cc4ca5SDavid du Colombier 	Prog *p, *p1, *p2;
54259cc4ca5SDavid du Colombier 	int n, o;
54359cc4ca5SDavid du Colombier 	Adr a;
54459cc4ca5SDavid du Colombier 
54559cc4ca5SDavid du Colombier 	p = r->prog;
54659cc4ca5SDavid du Colombier 	if(p->to.type != D_REG)
54759cc4ca5SDavid du Colombier 		FAIL("BOTCH: result not reg");
54859cc4ca5SDavid du Colombier 	n = p->to.reg;
54959cc4ca5SDavid du Colombier 	a = zprog.from;
55059cc4ca5SDavid du Colombier 	if(p->reg != NREG && p->reg != p->to.reg) {
55159cc4ca5SDavid du Colombier 		a.type = D_REG;
55259cc4ca5SDavid du Colombier 		a.reg = p->reg;
55359cc4ca5SDavid du Colombier 	}
55459cc4ca5SDavid du Colombier 	if(debug['H'])
55559cc4ca5SDavid du Colombier 		print("shiftprop\n%P", p);
55659cc4ca5SDavid du Colombier 	r1 = r;
55759cc4ca5SDavid du Colombier 	for(;;) {
55859cc4ca5SDavid du Colombier 		/* find first use of shift result; abort if shift operands or result are changed */
55959cc4ca5SDavid du Colombier 		r1 = uniqs(r1);
56059cc4ca5SDavid du Colombier 		if(r1 == R)
56159cc4ca5SDavid du Colombier 			FAIL("branch");
56259cc4ca5SDavid du Colombier 		if(uniqp(r1) == R)
56359cc4ca5SDavid du Colombier 			FAIL("merge");
56459cc4ca5SDavid du Colombier 		p1 = r1->prog;
56559cc4ca5SDavid du Colombier 		if(debug['H'])
56659cc4ca5SDavid du Colombier 			print("\n%P", p1);
56759cc4ca5SDavid du Colombier 		switch(copyu(p1, &p->to, A)) {
56859cc4ca5SDavid du Colombier 		case 0:	/* not used or set */
56959cc4ca5SDavid du Colombier 			if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
57059cc4ca5SDavid du Colombier 			   (a.type == D_REG && copyu(p1, &a, A) > 1))
57159cc4ca5SDavid du Colombier 				FAIL("args modified");
57259cc4ca5SDavid du Colombier 			continue;
57359cc4ca5SDavid du Colombier 		case 3:	/* set, not used */
57459cc4ca5SDavid du Colombier 			FAIL("BOTCH: noref");
57559cc4ca5SDavid du Colombier 		}
57659cc4ca5SDavid du Colombier 		break;
57759cc4ca5SDavid du Colombier 	}
57859cc4ca5SDavid du Colombier 	/* check whether substitution can be done */
57959cc4ca5SDavid du Colombier 	switch(p1->as) {
58059cc4ca5SDavid du Colombier 	default:
58159cc4ca5SDavid du Colombier 		FAIL("non-dpi");
58259cc4ca5SDavid du Colombier 	case AAND:
58359cc4ca5SDavid du Colombier 	case AEOR:
58459cc4ca5SDavid du Colombier 	case AADD:
58559cc4ca5SDavid du Colombier 	case AADC:
58659cc4ca5SDavid du Colombier 	case AORR:
58759cc4ca5SDavid du Colombier 	case ASUB:
58859cc4ca5SDavid du Colombier 	case ARSB:
58959cc4ca5SDavid du Colombier 	case ASBC:
59059cc4ca5SDavid du Colombier 	case ARSC:
59159cc4ca5SDavid du Colombier 		if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
59259cc4ca5SDavid du Colombier 			if(p1->from.type != D_REG)
59359cc4ca5SDavid du Colombier 				FAIL("can't swap");
59459cc4ca5SDavid du Colombier 			p1->reg = p1->from.reg;
59559cc4ca5SDavid du Colombier 			p1->from.reg = n;
59659cc4ca5SDavid du Colombier 			switch(p1->as) {
59759cc4ca5SDavid du Colombier 			case ASUB:
59859cc4ca5SDavid du Colombier 				p1->as = ARSB;
59959cc4ca5SDavid du Colombier 				break;
60059cc4ca5SDavid du Colombier 			case ARSB:
60159cc4ca5SDavid du Colombier 				p1->as = ASUB;
60259cc4ca5SDavid du Colombier 				break;
60359cc4ca5SDavid du Colombier 			case ASBC:
60459cc4ca5SDavid du Colombier 				p1->as = ARSC;
60559cc4ca5SDavid du Colombier 				break;
60659cc4ca5SDavid du Colombier 			case ARSC:
60759cc4ca5SDavid du Colombier 				p1->as = ASBC;
60859cc4ca5SDavid du Colombier 				break;
60959cc4ca5SDavid du Colombier 			}
61059cc4ca5SDavid du Colombier 			if(debug['H'])
61159cc4ca5SDavid du Colombier 				print("\t=>%P", p1);
61259cc4ca5SDavid du Colombier 		}
61359cc4ca5SDavid du Colombier 	case ABIC:
61459cc4ca5SDavid du Colombier 	case ACMP:
61559cc4ca5SDavid du Colombier 	case ACMN:
61659cc4ca5SDavid du Colombier 		if(p1->reg == n)
61759cc4ca5SDavid du Colombier 			FAIL("can't swap");
61859cc4ca5SDavid du Colombier 		if(p1->reg == NREG && p1->to.reg == n)
61959cc4ca5SDavid du Colombier 			FAIL("shift result used twice");
62059cc4ca5SDavid du Colombier 	case AMVN:
62159cc4ca5SDavid du Colombier 		if(p1->from.type == D_SHIFT)
62259cc4ca5SDavid du Colombier 			FAIL("shift result used in shift");
62359cc4ca5SDavid du Colombier 		if(p1->from.type != D_REG || p1->from.reg != n)
62459cc4ca5SDavid du Colombier 			FAIL("BOTCH: where is it used?");
62559cc4ca5SDavid du Colombier 		break;
62659cc4ca5SDavid du Colombier 	}
62759cc4ca5SDavid du Colombier 	/* check whether shift result is used subsequently */
62859cc4ca5SDavid du Colombier 	p2 = p1;
62959cc4ca5SDavid du Colombier 	if(p1->to.reg != n)
63059cc4ca5SDavid du Colombier 	for (;;) {
63159cc4ca5SDavid du Colombier 		r1 = uniqs(r1);
63259cc4ca5SDavid du Colombier 		if(r1 == R)
63359cc4ca5SDavid du Colombier 			FAIL("inconclusive");
63459cc4ca5SDavid du Colombier 		p1 = r1->prog;
63559cc4ca5SDavid du Colombier 		if(debug['H'])
63659cc4ca5SDavid du Colombier 			print("\n%P", p1);
63759cc4ca5SDavid du Colombier 		switch(copyu(p1, &p->to, A)) {
63859cc4ca5SDavid du Colombier 		case 0:	/* not used or set */
63959cc4ca5SDavid du Colombier 			continue;
64059cc4ca5SDavid du Colombier 		case 3: /* set, not used */
64159cc4ca5SDavid du Colombier 			break;
64259cc4ca5SDavid du Colombier 		default:/* used */
64359cc4ca5SDavid du Colombier 			FAIL("reused");
64459cc4ca5SDavid du Colombier 		}
64559cc4ca5SDavid du Colombier 		break;
64659cc4ca5SDavid du Colombier 	}
64759cc4ca5SDavid du Colombier 	/* make the substitution */
64859cc4ca5SDavid du Colombier 	p2->from.type = D_SHIFT;
64959cc4ca5SDavid du Colombier 	p2->from.reg = NREG;
65059cc4ca5SDavid du Colombier 	o = p->reg;
65159cc4ca5SDavid du Colombier 	if(o == NREG)
65259cc4ca5SDavid du Colombier 		o = p->to.reg;
65359cc4ca5SDavid du Colombier 	switch(p->from.type){
65459cc4ca5SDavid du Colombier 	case D_CONST:
65559cc4ca5SDavid du Colombier 		o |= (p->from.offset&0x1f)<<7;
65659cc4ca5SDavid du Colombier 		break;
65759cc4ca5SDavid du Colombier 	case D_REG:
65859cc4ca5SDavid du Colombier 		o |= (1<<4) | (p->from.reg<<8);
65959cc4ca5SDavid du Colombier 		break;
66059cc4ca5SDavid du Colombier 	}
66159cc4ca5SDavid du Colombier 	switch(p->as){
66259cc4ca5SDavid du Colombier 	case ASLL:
66359cc4ca5SDavid du Colombier 		o |= 0<<5;
66459cc4ca5SDavid du Colombier 		break;
66559cc4ca5SDavid du Colombier 	case ASRL:
66659cc4ca5SDavid du Colombier 		o |= 1<<5;
66759cc4ca5SDavid du Colombier 		break;
66859cc4ca5SDavid du Colombier 	case ASRA:
66959cc4ca5SDavid du Colombier 		o |= 2<<5;
67059cc4ca5SDavid du Colombier 		break;
67159cc4ca5SDavid du Colombier 	}
67259cc4ca5SDavid du Colombier 	p2->from.offset = o;
67359cc4ca5SDavid du Colombier 	if(debug['H'])
67459cc4ca5SDavid du Colombier 		print("\t=>%P\tSUCCEED\n", p2);
67559cc4ca5SDavid du Colombier 	return 1;
67659cc4ca5SDavid du Colombier }
67759cc4ca5SDavid du Colombier 
67859cc4ca5SDavid du Colombier Reg*
findpre(Reg * r,Adr * v)67959cc4ca5SDavid du Colombier findpre(Reg *r, Adr *v)
68059cc4ca5SDavid du Colombier {
68159cc4ca5SDavid du Colombier 	Reg *r1;
68259cc4ca5SDavid du Colombier 
68359cc4ca5SDavid du Colombier 	for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
68459cc4ca5SDavid du Colombier 		if(uniqs(r1) != r)
68559cc4ca5SDavid du Colombier 			return R;
68659cc4ca5SDavid du Colombier 		switch(copyu(r1->prog, v, A)) {
68759cc4ca5SDavid du Colombier 		case 1: /* used */
68859cc4ca5SDavid du Colombier 		case 2: /* read-alter-rewrite */
68959cc4ca5SDavid du Colombier 			return R;
69059cc4ca5SDavid du Colombier 		case 3: /* set */
69159cc4ca5SDavid du Colombier 		case 4: /* set and used */
69259cc4ca5SDavid du Colombier 			return r1;
69359cc4ca5SDavid du Colombier 		}
69459cc4ca5SDavid du Colombier 	}
69559cc4ca5SDavid du Colombier 	return R;
69659cc4ca5SDavid du Colombier }
69759cc4ca5SDavid du Colombier 
69859cc4ca5SDavid du Colombier Reg*
findinc(Reg * r,Reg * r2,Adr * v)69959cc4ca5SDavid du Colombier findinc(Reg *r, Reg *r2, Adr *v)
70059cc4ca5SDavid du Colombier {
70159cc4ca5SDavid du Colombier 	Reg *r1;
70259cc4ca5SDavid du Colombier 	Prog *p;
70359cc4ca5SDavid du Colombier 
70459cc4ca5SDavid du Colombier 
70559cc4ca5SDavid du Colombier 	for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
70659cc4ca5SDavid du Colombier 		if(uniqp(r1) != r)
70759cc4ca5SDavid du Colombier 			return R;
70859cc4ca5SDavid du Colombier 		switch(copyu(r1->prog, v, A)) {
70959cc4ca5SDavid du Colombier 		case 0: /* not touched */
71059cc4ca5SDavid du Colombier 			continue;
71159cc4ca5SDavid du Colombier 		case 4: /* set and used */
71259cc4ca5SDavid du Colombier 			p = r1->prog;
71359cc4ca5SDavid du Colombier 			if(p->as == AADD)
71459cc4ca5SDavid du Colombier 			if(p->from.type == D_CONST)
71559cc4ca5SDavid du Colombier 			if(p->from.offset > -4096 && p->from.offset < 4096)
71659cc4ca5SDavid du Colombier 				return r1;
71759cc4ca5SDavid du Colombier 		default:
71859cc4ca5SDavid du Colombier 			return R;
71959cc4ca5SDavid du Colombier 		}
72059cc4ca5SDavid du Colombier 	}
72159cc4ca5SDavid du Colombier 	return R;
72259cc4ca5SDavid du Colombier }
72359cc4ca5SDavid du Colombier 
72459cc4ca5SDavid du Colombier int
nochange(Reg * r,Reg * r2,Prog * p)72559cc4ca5SDavid du Colombier nochange(Reg *r, Reg *r2, Prog *p)
72659cc4ca5SDavid du Colombier {
72759cc4ca5SDavid du Colombier 	Adr a[3];
72859cc4ca5SDavid du Colombier 	int i, n;
72959cc4ca5SDavid du Colombier 
73059cc4ca5SDavid du Colombier 	if(r == r2)
73159cc4ca5SDavid du Colombier 		return 1;
73259cc4ca5SDavid du Colombier 	n = 0;
73359cc4ca5SDavid du Colombier 	if(p->reg != NREG && p->reg != p->to.reg) {
73459cc4ca5SDavid du Colombier 		a[n].type = D_REG;
73559cc4ca5SDavid du Colombier 		a[n++].reg = p->reg;
73659cc4ca5SDavid du Colombier 	}
73759cc4ca5SDavid du Colombier 	switch(p->from.type) {
73859cc4ca5SDavid du Colombier 	case D_SHIFT:
73959cc4ca5SDavid du Colombier 		a[n].type = D_REG;
74059cc4ca5SDavid du Colombier 		a[n++].reg = p->from.offset&0xf;
74159cc4ca5SDavid du Colombier 	case D_REG:
74259cc4ca5SDavid du Colombier 		a[n].type = D_REG;
74359cc4ca5SDavid du Colombier 		a[n++].reg = p->from.reg;
74459cc4ca5SDavid du Colombier 	}
74559cc4ca5SDavid du Colombier 	if(n == 0)
74659cc4ca5SDavid du Colombier 		return 1;
74759cc4ca5SDavid du Colombier 	for(; r!=R && r!=r2; r=uniqs(r)) {
74859cc4ca5SDavid du Colombier 		p = r->prog;
74959cc4ca5SDavid du Colombier 		for(i=0; i<n; i++)
75059cc4ca5SDavid du Colombier 			if(copyu(p, &a[i], A) > 1)
75159cc4ca5SDavid du Colombier 				return 0;
75259cc4ca5SDavid du Colombier 	}
75359cc4ca5SDavid du Colombier 	return 1;
75459cc4ca5SDavid du Colombier }
75559cc4ca5SDavid du Colombier 
75659cc4ca5SDavid du Colombier int
findu1(Reg * r,Adr * v)75759cc4ca5SDavid du Colombier findu1(Reg *r, Adr *v)
75859cc4ca5SDavid du Colombier {
75959cc4ca5SDavid du Colombier 	for(; r != R; r = r->s1) {
76059cc4ca5SDavid du Colombier 		if(r->active)
76159cc4ca5SDavid du Colombier 			return 0;
76259cc4ca5SDavid du Colombier 		r->active = 1;
76359cc4ca5SDavid du Colombier 		switch(copyu(r->prog, v, A)) {
76459cc4ca5SDavid du Colombier 		case 1: /* used */
76559cc4ca5SDavid du Colombier 		case 2: /* read-alter-rewrite */
76659cc4ca5SDavid du Colombier 		case 4: /* set and used */
76759cc4ca5SDavid du Colombier 			return 1;
76859cc4ca5SDavid du Colombier 		case 3: /* set */
76959cc4ca5SDavid du Colombier 			return 0;
77059cc4ca5SDavid du Colombier 		}
77159cc4ca5SDavid du Colombier 		if(r->s2)
77259cc4ca5SDavid du Colombier 			if (findu1(r->s2, v))
77359cc4ca5SDavid du Colombier 				return 1;
77459cc4ca5SDavid du Colombier 	}
77559cc4ca5SDavid du Colombier 	return 0;
77659cc4ca5SDavid du Colombier }
77759cc4ca5SDavid du Colombier 
77859cc4ca5SDavid du Colombier int
finduse(Reg * r,Adr * v)77959cc4ca5SDavid du Colombier finduse(Reg *r, Adr *v)
78059cc4ca5SDavid du Colombier {
78159cc4ca5SDavid du Colombier 	Reg *r1;
78259cc4ca5SDavid du Colombier 
78359cc4ca5SDavid du Colombier 	for(r1=firstr; r1!=R; r1=r1->link)
78459cc4ca5SDavid du Colombier 		r1->active = 0;
78559cc4ca5SDavid du Colombier 	return findu1(r, v);
78659cc4ca5SDavid du Colombier }
78759cc4ca5SDavid du Colombier 
78859cc4ca5SDavid du Colombier int
xtramodes(Reg * r,Adr * a)78959cc4ca5SDavid du Colombier xtramodes(Reg *r, Adr *a)
79059cc4ca5SDavid du Colombier {
79159cc4ca5SDavid du Colombier 	Reg *r1, *r2, *r3;
79259cc4ca5SDavid du Colombier 	Prog *p, *p1;
79359cc4ca5SDavid du Colombier 	Adr v;
79459cc4ca5SDavid du Colombier 
79559cc4ca5SDavid du Colombier 	p = r->prog;
796375daca8SDavid du Colombier 	if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG)	/* byte load */
797375daca8SDavid du Colombier 		return 0;
79859cc4ca5SDavid du Colombier 	v = *a;
79959cc4ca5SDavid du Colombier 	v.type = D_REG;
80059cc4ca5SDavid du Colombier 	r1 = findpre(r, &v);
80159cc4ca5SDavid du Colombier 	if(r1 != R) {
80259cc4ca5SDavid du Colombier 		p1 = r1->prog;
80359cc4ca5SDavid du Colombier 		if(p1->to.type == D_REG && p1->to.reg == v.reg)
80459cc4ca5SDavid du Colombier 		switch(p1->as) {
80559cc4ca5SDavid du Colombier 		case AADD:
80659cc4ca5SDavid du Colombier 			if(p1->from.type == D_REG ||
80759cc4ca5SDavid du Colombier 			   (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
80859cc4ca5SDavid du Colombier 			    (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
80959cc4ca5SDavid du Colombier 			   (p1->from.type == D_CONST &&
81059cc4ca5SDavid du Colombier 			    p1->from.offset > -4096 && p1->from.offset < 4096))
81159cc4ca5SDavid du Colombier 			if(nochange(uniqs(r1), r, p1)) {
81259cc4ca5SDavid du Colombier 				if(a != &p->from || v.reg != p->to.reg)
81359cc4ca5SDavid du Colombier 				if (finduse(r->s1, &v)) {
81459cc4ca5SDavid du Colombier 					if(p1->reg == NREG || p1->reg == v.reg)
81559cc4ca5SDavid du Colombier 						/* pre-indexing */
81659cc4ca5SDavid du Colombier 						p->scond |= C_WBIT;
81759cc4ca5SDavid du Colombier 					else return 0;
81859cc4ca5SDavid du Colombier 				}
81959cc4ca5SDavid du Colombier 				switch (p1->from.type) {
82059cc4ca5SDavid du Colombier 				case D_REG:
82159cc4ca5SDavid du Colombier 					/* register offset */
82259cc4ca5SDavid du Colombier 					a->type = D_SHIFT;
82359cc4ca5SDavid du Colombier 					a->offset = p1->from.reg;
82459cc4ca5SDavid du Colombier 					break;
82559cc4ca5SDavid du Colombier 				case D_SHIFT:
82659cc4ca5SDavid du Colombier 					/* scaled register offset */
82759cc4ca5SDavid du Colombier 					a->type = D_SHIFT;
82859cc4ca5SDavid du Colombier 				case D_CONST:
82959cc4ca5SDavid du Colombier 					/* immediate offset */
83059cc4ca5SDavid du Colombier 					a->offset = p1->from.offset;
83159cc4ca5SDavid du Colombier 					break;
83259cc4ca5SDavid du Colombier 				}
83359cc4ca5SDavid du Colombier 				if(p1->reg != NREG)
83459cc4ca5SDavid du Colombier 					a->reg = p1->reg;
83559cc4ca5SDavid du Colombier 				excise(r1);
83659cc4ca5SDavid du Colombier 				return 1;
83759cc4ca5SDavid du Colombier 			}
83859cc4ca5SDavid du Colombier 			break;
83959cc4ca5SDavid du Colombier 		case AMOVW:
84059cc4ca5SDavid du Colombier 			if(p1->from.type == D_REG)
84159cc4ca5SDavid du Colombier 			if((r2 = findinc(r1, r, &p1->from)) != R) {
84259cc4ca5SDavid du Colombier 			for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
84359cc4ca5SDavid du Colombier 				;
84459cc4ca5SDavid du Colombier 			if(r3 == r) {
84559cc4ca5SDavid du Colombier 				/* post-indexing */
84659cc4ca5SDavid du Colombier 				p1 = r2->prog;
84759cc4ca5SDavid du Colombier 				a->reg = p1->to.reg;
84859cc4ca5SDavid du Colombier 				a->offset = p1->from.offset;
84959cc4ca5SDavid du Colombier 				p->scond |= C_PBIT;
85059cc4ca5SDavid du Colombier 				if(!finduse(r, &r1->prog->to))
85159cc4ca5SDavid du Colombier 					excise(r1);
85259cc4ca5SDavid du Colombier 				excise(r2);
85359cc4ca5SDavid du Colombier 				return 1;
85459cc4ca5SDavid du Colombier 			}
85559cc4ca5SDavid du Colombier 			}
85659cc4ca5SDavid du Colombier 			break;
85759cc4ca5SDavid du Colombier 		}
85859cc4ca5SDavid du Colombier 	}
85959cc4ca5SDavid du Colombier 	if(a != &p->from || a->reg != p->to.reg)
86059cc4ca5SDavid du Colombier 	if((r1 = findinc(r, R, &v)) != R) {
86159cc4ca5SDavid du Colombier 		/* post-indexing */
86259cc4ca5SDavid du Colombier 		p1 = r1->prog;
86359cc4ca5SDavid du Colombier 		a->offset = p1->from.offset;
86459cc4ca5SDavid du Colombier 		p->scond |= C_PBIT;
86559cc4ca5SDavid du Colombier 		excise(r1);
86659cc4ca5SDavid du Colombier 		return 1;
86759cc4ca5SDavid du Colombier 	}
86859cc4ca5SDavid du Colombier 	return 0;
86959cc4ca5SDavid du Colombier }
87059cc4ca5SDavid du Colombier 
87159cc4ca5SDavid du Colombier /*
8727dd7cddfSDavid du Colombier  * return
8737dd7cddfSDavid du Colombier  * 1 if v only used (and substitute),
8747dd7cddfSDavid du Colombier  * 2 if read-alter-rewrite
8757dd7cddfSDavid du Colombier  * 3 if set
8767dd7cddfSDavid du Colombier  * 4 if set and used
8777dd7cddfSDavid du Colombier  * 0 otherwise (not touched)
8787dd7cddfSDavid du Colombier  */
8797dd7cddfSDavid du Colombier int
copyu(Prog * p,Adr * v,Adr * s)8807dd7cddfSDavid du Colombier copyu(Prog *p, Adr *v, Adr *s)
8817dd7cddfSDavid du Colombier {
8827dd7cddfSDavid du Colombier 
8837dd7cddfSDavid du Colombier 	switch(p->as) {
8847dd7cddfSDavid du Colombier 
8857dd7cddfSDavid du Colombier 	default:
8867dd7cddfSDavid du Colombier 		if(debug['P'])
8877dd7cddfSDavid du Colombier 			print(" (???)");
8887dd7cddfSDavid du Colombier 		return 2;
8897dd7cddfSDavid du Colombier 
89059cc4ca5SDavid du Colombier 	case AMOVM:
89159cc4ca5SDavid du Colombier 		if(v->type != D_REG)
89259cc4ca5SDavid du Colombier 			return 0;
89359cc4ca5SDavid du Colombier 		if(p->from.type == D_CONST) {	/* read reglist, read/rar */
89459cc4ca5SDavid du Colombier 			if(s != A) {
89559cc4ca5SDavid du Colombier 				if(p->from.offset&(1<<v->reg))
89659cc4ca5SDavid du Colombier 					return 1;
89759cc4ca5SDavid du Colombier 				if(copysub(&p->to, v, s, 1))
89859cc4ca5SDavid du Colombier 					return 1;
89959cc4ca5SDavid du Colombier 				return 0;
90059cc4ca5SDavid du Colombier 			}
90159cc4ca5SDavid du Colombier 			if(copyau(&p->to, v)) {
90259cc4ca5SDavid du Colombier 				if(p->scond&C_WBIT)
90359cc4ca5SDavid du Colombier 					return 2;
90459cc4ca5SDavid du Colombier 				return 1;
90559cc4ca5SDavid du Colombier 			}
90659cc4ca5SDavid du Colombier 			if(p->from.offset&(1<<v->reg))
90759cc4ca5SDavid du Colombier 				return 1;
90859cc4ca5SDavid du Colombier 		} else {			/* read/rar, write reglist */
90959cc4ca5SDavid du Colombier 			if(s != A) {
91059cc4ca5SDavid du Colombier 				if(p->to.offset&(1<<v->reg))
91159cc4ca5SDavid du Colombier 					return 1;
91259cc4ca5SDavid du Colombier 				if(copysub(&p->from, v, s, 1))
91359cc4ca5SDavid du Colombier 					return 1;
91459cc4ca5SDavid du Colombier 				return 0;
91559cc4ca5SDavid du Colombier 			}
91659cc4ca5SDavid du Colombier 			if(copyau(&p->from, v)) {
91759cc4ca5SDavid du Colombier 				if(p->scond&C_WBIT)
91859cc4ca5SDavid du Colombier 					return 2;
91959cc4ca5SDavid du Colombier 				if(p->to.offset&(1<<v->reg))
92059cc4ca5SDavid du Colombier 					return 4;
92159cc4ca5SDavid du Colombier 				return 1;
92259cc4ca5SDavid du Colombier 			}
92359cc4ca5SDavid du Colombier 			if(p->to.offset&(1<<v->reg))
92459cc4ca5SDavid du Colombier 				return 3;
92559cc4ca5SDavid du Colombier 		}
92659cc4ca5SDavid du Colombier 		return 0;
9277dd7cddfSDavid du Colombier 
9287dd7cddfSDavid du Colombier 	case ANOP:	/* read, write */
9297dd7cddfSDavid du Colombier 	case AMOVW:
9307dd7cddfSDavid du Colombier 	case AMOVF:
9317dd7cddfSDavid du Colombier 	case AMOVD:
9327dd7cddfSDavid du Colombier 	case AMOVH:
9337dd7cddfSDavid du Colombier 	case AMOVHU:
9347dd7cddfSDavid du Colombier 	case AMOVB:
9357dd7cddfSDavid du Colombier 	case AMOVBU:
9367dd7cddfSDavid du Colombier 	case AMOVDW:
9377dd7cddfSDavid du Colombier 	case AMOVWD:
9387dd7cddfSDavid du Colombier 	case AMOVFD:
9397dd7cddfSDavid du Colombier 	case AMOVDF:
94059cc4ca5SDavid du Colombier 		if(p->scond&(C_WBIT|C_PBIT))
94159cc4ca5SDavid du Colombier 		if(v->type == D_REG) {
94259cc4ca5SDavid du Colombier 			if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
94359cc4ca5SDavid du Colombier 				if(p->from.reg == v->reg)
94459cc4ca5SDavid du Colombier 					return 2;
94559cc4ca5SDavid du Colombier 			} else {
94659cc4ca5SDavid du Colombier 		  		if(p->to.reg == v->reg)
94759cc4ca5SDavid du Colombier 				return 2;
94859cc4ca5SDavid du Colombier 			}
94959cc4ca5SDavid du Colombier 		}
9507dd7cddfSDavid du Colombier 		if(s != A) {
9517dd7cddfSDavid du Colombier 			if(copysub(&p->from, v, s, 1))
9527dd7cddfSDavid du Colombier 				return 1;
9537dd7cddfSDavid du Colombier 			if(!copyas(&p->to, v))
9547dd7cddfSDavid du Colombier 				if(copysub(&p->to, v, s, 1))
9557dd7cddfSDavid du Colombier 					return 1;
9567dd7cddfSDavid du Colombier 			return 0;
9577dd7cddfSDavid du Colombier 		}
9587dd7cddfSDavid du Colombier 		if(copyas(&p->to, v)) {
9597dd7cddfSDavid du Colombier 			if(copyau(&p->from, v))
9607dd7cddfSDavid du Colombier 				return 4;
9617dd7cddfSDavid du Colombier 			return 3;
9627dd7cddfSDavid du Colombier 		}
9637dd7cddfSDavid du Colombier 		if(copyau(&p->from, v))
9647dd7cddfSDavid du Colombier 			return 1;
9657dd7cddfSDavid du Colombier 		if(copyau(&p->to, v))
9667dd7cddfSDavid du Colombier 			return 1;
9677dd7cddfSDavid du Colombier 		return 0;
9687dd7cddfSDavid du Colombier 
9697dd7cddfSDavid du Colombier 
9707dd7cddfSDavid du Colombier 	case AADD:	/* read, read, write */
9717dd7cddfSDavid du Colombier 	case ASUB:
9727dd7cddfSDavid du Colombier 	case ARSB:
9737dd7cddfSDavid du Colombier 	case ASLL:
9747dd7cddfSDavid du Colombier 	case ASRL:
9757dd7cddfSDavid du Colombier 	case ASRA:
9767dd7cddfSDavid du Colombier 	case AORR:
9777dd7cddfSDavid du Colombier 	case AAND:
9787dd7cddfSDavid du Colombier 	case AEOR:
9797dd7cddfSDavid du Colombier 	case AMUL:
9807dd7cddfSDavid du Colombier 	case ADIV:
9817dd7cddfSDavid du Colombier 	case ADIVU:
9827dd7cddfSDavid du Colombier 	case AADDF:
9837dd7cddfSDavid du Colombier 	case AADDD:
9847dd7cddfSDavid du Colombier 	case ASUBF:
9857dd7cddfSDavid du Colombier 	case ASUBD:
9867dd7cddfSDavid du Colombier 	case AMULF:
9877dd7cddfSDavid du Colombier 	case AMULD:
9887dd7cddfSDavid du Colombier 	case ADIVF:
9897dd7cddfSDavid du Colombier 	case ADIVD:
9907dd7cddfSDavid du Colombier 
9917dd7cddfSDavid du Colombier 	case ACMPF:
9927dd7cddfSDavid du Colombier 	case ACMPD:
9937dd7cddfSDavid du Colombier 	case ACMP:
99459cc4ca5SDavid du Colombier 	case ACMN:
99559cc4ca5SDavid du Colombier 	case ACASE:
9967dd7cddfSDavid du Colombier 		if(s != A) {
9977dd7cddfSDavid du Colombier 			if(copysub(&p->from, v, s, 1))
9987dd7cddfSDavid du Colombier 				return 1;
9997dd7cddfSDavid du Colombier 			if(copysub1(p, v, s, 1))
10007dd7cddfSDavid du Colombier 				return 1;
10017dd7cddfSDavid du Colombier 			if(!copyas(&p->to, v))
10027dd7cddfSDavid du Colombier 				if(copysub(&p->to, v, s, 1))
10037dd7cddfSDavid du Colombier 					return 1;
10047dd7cddfSDavid du Colombier 			return 0;
10057dd7cddfSDavid du Colombier 		}
10067dd7cddfSDavid du Colombier 		if(copyas(&p->to, v)) {
10077dd7cddfSDavid du Colombier 			if(p->reg == NREG)
10087dd7cddfSDavid du Colombier 				p->reg = p->to.reg;
10097dd7cddfSDavid du Colombier 			if(copyau(&p->from, v))
10107dd7cddfSDavid du Colombier 				return 4;
10117dd7cddfSDavid du Colombier 			if(copyau1(p, v))
10127dd7cddfSDavid du Colombier 				return 4;
10137dd7cddfSDavid du Colombier 			return 3;
10147dd7cddfSDavid du Colombier 		}
10157dd7cddfSDavid du Colombier 		if(copyau(&p->from, v))
10167dd7cddfSDavid du Colombier 			return 1;
10177dd7cddfSDavid du Colombier 		if(copyau1(p, v))
10187dd7cddfSDavid du Colombier 			return 1;
10197dd7cddfSDavid du Colombier 		if(copyau(&p->to, v))
10207dd7cddfSDavid du Colombier 			return 1;
10217dd7cddfSDavid du Colombier 		return 0;
10227dd7cddfSDavid du Colombier 
10237dd7cddfSDavid du Colombier 	case ABEQ:	/* read, read */
10247dd7cddfSDavid du Colombier 	case ABNE:
10257dd7cddfSDavid du Colombier 	case ABCS:
10267dd7cddfSDavid du Colombier 	case ABHS:
10277dd7cddfSDavid du Colombier 	case ABCC:
10287dd7cddfSDavid du Colombier 	case ABLO:
10297dd7cddfSDavid du Colombier 	case ABMI:
10307dd7cddfSDavid du Colombier 	case ABPL:
10317dd7cddfSDavid du Colombier 	case ABVS:
10327dd7cddfSDavid du Colombier 	case ABVC:
10337dd7cddfSDavid du Colombier 	case ABHI:
10347dd7cddfSDavid du Colombier 	case ABLS:
10357dd7cddfSDavid du Colombier 	case ABGE:
10367dd7cddfSDavid du Colombier 	case ABLT:
10377dd7cddfSDavid du Colombier 	case ABGT:
10387dd7cddfSDavid du Colombier 	case ABLE:
10397dd7cddfSDavid du Colombier 		if(s != A) {
10407dd7cddfSDavid du Colombier 			if(copysub(&p->from, v, s, 1))
10417dd7cddfSDavid du Colombier 				return 1;
10427dd7cddfSDavid du Colombier 			return copysub1(p, v, s, 1);
10437dd7cddfSDavid du Colombier 		}
10447dd7cddfSDavid du Colombier 		if(copyau(&p->from, v))
10457dd7cddfSDavid du Colombier 			return 1;
10467dd7cddfSDavid du Colombier 		if(copyau1(p, v))
10477dd7cddfSDavid du Colombier 			return 1;
10487dd7cddfSDavid du Colombier 		return 0;
10497dd7cddfSDavid du Colombier 
10507dd7cddfSDavid du Colombier 	case AB:	/* funny */
10517dd7cddfSDavid du Colombier 		if(s != A) {
10527dd7cddfSDavid du Colombier 			if(copysub(&p->to, v, s, 1))
10537dd7cddfSDavid du Colombier 				return 1;
10547dd7cddfSDavid du Colombier 			return 0;
10557dd7cddfSDavid du Colombier 		}
10567dd7cddfSDavid du Colombier 		if(copyau(&p->to, v))
10577dd7cddfSDavid du Colombier 			return 1;
10587dd7cddfSDavid du Colombier 		return 0;
10597dd7cddfSDavid du Colombier 
10607dd7cddfSDavid du Colombier 	case ARET:	/* funny */
10617dd7cddfSDavid du Colombier 		if(v->type == D_REG)
10627dd7cddfSDavid du Colombier 		if(v->reg == REGRET)
10637dd7cddfSDavid du Colombier 			return 2;
10647dd7cddfSDavid du Colombier 		if(v->type == D_FREG)
10657dd7cddfSDavid du Colombier 		if(v->reg == FREGRET)
10667dd7cddfSDavid du Colombier 			return 2;
10677dd7cddfSDavid du Colombier 
10687dd7cddfSDavid du Colombier 	case ABL:	/* funny */
10697dd7cddfSDavid du Colombier 		if(v->type == D_REG) {
10707dd7cddfSDavid du Colombier 			if(v->reg <= REGEXT && v->reg > exregoffset)
10717dd7cddfSDavid du Colombier 				return 2;
1072*27acba7cSDavid du Colombier 			if(v->reg == (uchar)REGARG)
10737dd7cddfSDavid du Colombier 				return 2;
10747dd7cddfSDavid du Colombier 		}
10757dd7cddfSDavid du Colombier 		if(v->type == D_FREG)
10767dd7cddfSDavid du Colombier 			if(v->reg <= FREGEXT && v->reg > exfregoffset)
10777dd7cddfSDavid du Colombier 				return 2;
10787dd7cddfSDavid du Colombier 
10797dd7cddfSDavid du Colombier 		if(s != A) {
10807dd7cddfSDavid du Colombier 			if(copysub(&p->to, v, s, 1))
10817dd7cddfSDavid du Colombier 				return 1;
10827dd7cddfSDavid du Colombier 			return 0;
10837dd7cddfSDavid du Colombier 		}
10847dd7cddfSDavid du Colombier 		if(copyau(&p->to, v))
10857dd7cddfSDavid du Colombier 			return 4;
10867dd7cddfSDavid du Colombier 		return 3;
10877dd7cddfSDavid du Colombier 
10887dd7cddfSDavid du Colombier 	case ATEXT:	/* funny */
10897dd7cddfSDavid du Colombier 		if(v->type == D_REG)
1090*27acba7cSDavid du Colombier 			if(v->reg == (uchar)REGARG)
10917dd7cddfSDavid du Colombier 				return 3;
10927dd7cddfSDavid du Colombier 		return 0;
10937dd7cddfSDavid du Colombier 	}
10947dd7cddfSDavid du Colombier }
10957dd7cddfSDavid du Colombier 
10967dd7cddfSDavid du Colombier int
a2type(Prog * p)10977dd7cddfSDavid du Colombier a2type(Prog *p)
10987dd7cddfSDavid du Colombier {
10997dd7cddfSDavid du Colombier 
11007dd7cddfSDavid du Colombier 	switch(p->as) {
11017dd7cddfSDavid du Colombier 
11027dd7cddfSDavid du Colombier 	case ACMP:
110359cc4ca5SDavid du Colombier 	case ACMN:
11047dd7cddfSDavid du Colombier 
11057dd7cddfSDavid du Colombier 	case AADD:
11067dd7cddfSDavid du Colombier 	case ASUB:
11077dd7cddfSDavid du Colombier 	case ARSB:
11087dd7cddfSDavid du Colombier 	case ASLL:
11097dd7cddfSDavid du Colombier 	case ASRL:
11107dd7cddfSDavid du Colombier 	case ASRA:
11117dd7cddfSDavid du Colombier 	case AORR:
11127dd7cddfSDavid du Colombier 	case AAND:
11137dd7cddfSDavid du Colombier 	case AEOR:
11147dd7cddfSDavid du Colombier 	case AMUL:
11157dd7cddfSDavid du Colombier 	case ADIV:
11167dd7cddfSDavid du Colombier 	case ADIVU:
11177dd7cddfSDavid du Colombier 		return D_REG;
11187dd7cddfSDavid du Colombier 
11197dd7cddfSDavid du Colombier 	case ACMPF:
11207dd7cddfSDavid du Colombier 	case ACMPD:
11217dd7cddfSDavid du Colombier 
11227dd7cddfSDavid du Colombier 	case AADDF:
11237dd7cddfSDavid du Colombier 	case AADDD:
11247dd7cddfSDavid du Colombier 	case ASUBF:
11257dd7cddfSDavid du Colombier 	case ASUBD:
11267dd7cddfSDavid du Colombier 	case AMULF:
11277dd7cddfSDavid du Colombier 	case AMULD:
11287dd7cddfSDavid du Colombier 	case ADIVF:
11297dd7cddfSDavid du Colombier 	case ADIVD:
11307dd7cddfSDavid du Colombier 		return D_FREG;
11317dd7cddfSDavid du Colombier 	}
11327dd7cddfSDavid du Colombier 	return D_NONE;
11337dd7cddfSDavid du Colombier }
11347dd7cddfSDavid du Colombier 
11357dd7cddfSDavid du Colombier /*
11367dd7cddfSDavid du Colombier  * direct reference,
11377dd7cddfSDavid du Colombier  * could be set/use depending on
11387dd7cddfSDavid du Colombier  * semantics
11397dd7cddfSDavid du Colombier  */
11407dd7cddfSDavid du Colombier int
copyas(Adr * a,Adr * v)11417dd7cddfSDavid du Colombier copyas(Adr *a, Adr *v)
11427dd7cddfSDavid du Colombier {
11437dd7cddfSDavid du Colombier 
114459cc4ca5SDavid du Colombier 	if(regtyp(v)) {
11457dd7cddfSDavid du Colombier 		if(a->type == v->type)
11467dd7cddfSDavid du Colombier 		if(a->reg == v->reg)
11477dd7cddfSDavid du Colombier 			return 1;
114859cc4ca5SDavid du Colombier 	} else if(v->type == D_CONST) {		/* for constprop */
114959cc4ca5SDavid du Colombier 		if(a->type == v->type)
115059cc4ca5SDavid du Colombier 		if(a->name == v->name)
115159cc4ca5SDavid du Colombier 		if(a->sym == v->sym)
115259cc4ca5SDavid du Colombier 		if(a->reg == v->reg)
115359cc4ca5SDavid du Colombier 		if(a->offset == v->offset)
115459cc4ca5SDavid du Colombier 			return 1;
115559cc4ca5SDavid du Colombier 	}
11567dd7cddfSDavid du Colombier 	return 0;
11577dd7cddfSDavid du Colombier }
11587dd7cddfSDavid du Colombier 
11597dd7cddfSDavid du Colombier /*
11607dd7cddfSDavid du Colombier  * either direct or indirect
11617dd7cddfSDavid du Colombier  */
11627dd7cddfSDavid du Colombier int
copyau(Adr * a,Adr * v)11637dd7cddfSDavid du Colombier copyau(Adr *a, Adr *v)
11647dd7cddfSDavid du Colombier {
11657dd7cddfSDavid du Colombier 
11667dd7cddfSDavid du Colombier 	if(copyas(a, v))
11677dd7cddfSDavid du Colombier 		return 1;
116859cc4ca5SDavid du Colombier 	if(v->type == D_REG) {
116959cc4ca5SDavid du Colombier 		if(a->type == D_OREG) {
11707dd7cddfSDavid du Colombier 			if(v->reg == a->reg)
11717dd7cddfSDavid du Colombier 				return 1;
117259cc4ca5SDavid du Colombier 		} else if(a->type == D_SHIFT) {
117359cc4ca5SDavid du Colombier 			if((a->offset&0xf) == v->reg)
117459cc4ca5SDavid du Colombier 				return 1;
117559cc4ca5SDavid du Colombier 			if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
117659cc4ca5SDavid du Colombier 				return 1;
117759cc4ca5SDavid du Colombier 		}
117859cc4ca5SDavid du Colombier 	}
11797dd7cddfSDavid du Colombier 	return 0;
11807dd7cddfSDavid du Colombier }
11817dd7cddfSDavid du Colombier 
11827dd7cddfSDavid du Colombier int
copyau1(Prog * p,Adr * v)11837dd7cddfSDavid du Colombier copyau1(Prog *p, Adr *v)
11847dd7cddfSDavid du Colombier {
11857dd7cddfSDavid du Colombier 
11867dd7cddfSDavid du Colombier 	if(regtyp(v)) {
11877dd7cddfSDavid du Colombier 		if(a2type(p) == v->type)
11887dd7cddfSDavid du Colombier 		if(p->reg == v->reg) {
11897dd7cddfSDavid du Colombier 			if(a2type(p) != v->type)
11907dd7cddfSDavid du Colombier 				print("botch a2type %P\n", p);
11917dd7cddfSDavid du Colombier 			return 1;
11927dd7cddfSDavid du Colombier 		}
11937dd7cddfSDavid du Colombier 	}
11947dd7cddfSDavid du Colombier 	return 0;
11957dd7cddfSDavid du Colombier }
11967dd7cddfSDavid du Colombier 
11977dd7cddfSDavid du Colombier /*
11987dd7cddfSDavid du Colombier  * substitute s for v in a
11997dd7cddfSDavid du Colombier  * return failure to substitute
12007dd7cddfSDavid du Colombier  */
12017dd7cddfSDavid du Colombier int
copysub(Adr * a,Adr * v,Adr * s,int f)12027dd7cddfSDavid du Colombier copysub(Adr *a, Adr *v, Adr *s, int f)
12037dd7cddfSDavid du Colombier {
12047dd7cddfSDavid du Colombier 
12057dd7cddfSDavid du Colombier 	if(f)
120659cc4ca5SDavid du Colombier 	if(copyau(a, v)) {
120759cc4ca5SDavid du Colombier 		if(a->type == D_SHIFT) {
120859cc4ca5SDavid du Colombier 			if((a->offset&0xf) == v->reg)
120959cc4ca5SDavid du Colombier 				a->offset = (a->offset&~0xf)|s->reg;
121059cc4ca5SDavid du Colombier 			if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
121159cc4ca5SDavid du Colombier 				a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
121259cc4ca5SDavid du Colombier 		} else
12137dd7cddfSDavid du Colombier 			a->reg = s->reg;
121459cc4ca5SDavid du Colombier 	}
12157dd7cddfSDavid du Colombier 	return 0;
12167dd7cddfSDavid du Colombier }
12177dd7cddfSDavid du Colombier 
12187dd7cddfSDavid du Colombier int
copysub1(Prog * p1,Adr * v,Adr * s,int f)12197dd7cddfSDavid du Colombier copysub1(Prog *p1, Adr *v, Adr *s, int f)
12207dd7cddfSDavid du Colombier {
12217dd7cddfSDavid du Colombier 
12227dd7cddfSDavid du Colombier 	if(f)
12237dd7cddfSDavid du Colombier 	if(copyau1(p1, v))
12247dd7cddfSDavid du Colombier 		p1->reg = s->reg;
12257dd7cddfSDavid du Colombier 	return 0;
12267dd7cddfSDavid du Colombier }
12277dd7cddfSDavid du Colombier 
12287dd7cddfSDavid du Colombier struct {
12297dd7cddfSDavid du Colombier 	int opcode;
123059cc4ca5SDavid du Colombier 	int notopcode;
12317dd7cddfSDavid du Colombier 	int scond;
12327dd7cddfSDavid du Colombier 	int notscond;
12337dd7cddfSDavid du Colombier } predinfo[]  = {
123459cc4ca5SDavid du Colombier 	{ ABEQ,	ABNE,	0x0,	0x1, },
123559cc4ca5SDavid du Colombier 	{ ABNE,	ABEQ,	0x1,	0x0, },
123659cc4ca5SDavid du Colombier 	{ ABCS,	ABCC,	0x2,	0x3, },
123759cc4ca5SDavid du Colombier 	{ ABHS,	ABLO,	0x2,	0x3, },
123859cc4ca5SDavid du Colombier 	{ ABCC,	ABCS,	0x3,	0x2, },
123959cc4ca5SDavid du Colombier 	{ ABLO,	ABHS,	0x3,	0x2, },
124059cc4ca5SDavid du Colombier 	{ ABMI,	ABPL,	0x4,	0x5, },
124159cc4ca5SDavid du Colombier 	{ ABPL,	ABMI,	0x5,	0x4, },
124259cc4ca5SDavid du Colombier 	{ ABVS,	ABVC,	0x6,	0x7, },
124359cc4ca5SDavid du Colombier 	{ ABVC,	ABVS,	0x7,	0x6, },
124459cc4ca5SDavid du Colombier 	{ ABHI,	ABLS,	0x8,	0x9, },
124559cc4ca5SDavid du Colombier 	{ ABLS,	ABHI,	0x9,	0x8, },
124659cc4ca5SDavid du Colombier 	{ ABGE,	ABLT,	0xA,	0xB, },
124759cc4ca5SDavid du Colombier 	{ ABLT,	ABGE,	0xB,	0xA, },
124859cc4ca5SDavid du Colombier 	{ ABGT,	ABLE,	0xC,	0xD, },
124959cc4ca5SDavid du Colombier 	{ ABLE,	ABGT,	0xD,	0xC, },
12507dd7cddfSDavid du Colombier };
12517dd7cddfSDavid du Colombier 
125259cc4ca5SDavid du Colombier typedef struct {
125359cc4ca5SDavid du Colombier 	Reg *start;
125459cc4ca5SDavid du Colombier 	Reg *last;
125559cc4ca5SDavid du Colombier 	Reg *end;
125659cc4ca5SDavid du Colombier 	int len;
125759cc4ca5SDavid du Colombier } Joininfo;
12587dd7cddfSDavid du Colombier 
125959cc4ca5SDavid du Colombier enum {
126059cc4ca5SDavid du Colombier 	Join,
126159cc4ca5SDavid du Colombier 	Split,
126259cc4ca5SDavid du Colombier 	End,
126359cc4ca5SDavid du Colombier 	Branch,
126459cc4ca5SDavid du Colombier 	Setcond,
126559cc4ca5SDavid du Colombier 	Toolong
126659cc4ca5SDavid du Colombier };
126759cc4ca5SDavid du Colombier 
126859cc4ca5SDavid du Colombier enum {
126959cc4ca5SDavid du Colombier 	Falsecond,
127059cc4ca5SDavid du Colombier 	Truecond,
127159cc4ca5SDavid du Colombier 	Delbranch,
127259cc4ca5SDavid du Colombier 	Keepbranch
127359cc4ca5SDavid du Colombier };
12747dd7cddfSDavid du Colombier 
12757dd7cddfSDavid du Colombier int
isbranch(Prog * p)12767dd7cddfSDavid du Colombier isbranch(Prog *p)
12777dd7cddfSDavid du Colombier {
12787dd7cddfSDavid du Colombier 	return (ABEQ <= p->as) && (p->as <= ABLE);
12797dd7cddfSDavid du Colombier }
12807dd7cddfSDavid du Colombier 
12817dd7cddfSDavid du Colombier int
predicable(Prog * p)12827dd7cddfSDavid du Colombier predicable(Prog *p)
12837dd7cddfSDavid du Colombier {
12847dd7cddfSDavid du Colombier 	if (isbranch(p)
128559cc4ca5SDavid du Colombier 		|| p->as == ANOP
12867dd7cddfSDavid du Colombier 		|| p->as == AXXX
12877dd7cddfSDavid du Colombier 		|| p->as == ADATA
12887dd7cddfSDavid du Colombier 		|| p->as == AGLOBL
12897dd7cddfSDavid du Colombier 		|| p->as == AGOK
12907dd7cddfSDavid du Colombier 		|| p->as == AHISTORY
12917dd7cddfSDavid du Colombier 		|| p->as == ANAME
1292375daca8SDavid du Colombier 		|| p->as == ASIGNAME
12937dd7cddfSDavid du Colombier 		|| p->as == ATEXT
12947dd7cddfSDavid du Colombier 		|| p->as == AWORD
12957dd7cddfSDavid du Colombier 		|| p->as == ADYNT
12967dd7cddfSDavid du Colombier 		|| p->as == AINIT
12977dd7cddfSDavid du Colombier 		|| p->as == ABCASE
12987dd7cddfSDavid du Colombier 		|| p->as == ACASE)
12997dd7cddfSDavid du Colombier 		return 0;
13007dd7cddfSDavid du Colombier 	return 1;
13017dd7cddfSDavid du Colombier }
13027dd7cddfSDavid du Colombier 
13037dd7cddfSDavid du Colombier /*
13047dd7cddfSDavid du Colombier  * Depends on an analysis of the encodings performed by 5l.
13057dd7cddfSDavid du Colombier  * These seem to be all of the opcodes that lead to the "S" bit
13067dd7cddfSDavid du Colombier  * being set in the instruction encodings.
13077dd7cddfSDavid du Colombier  *
130859cc4ca5SDavid du Colombier  * C_SBIT may also have been set explicitly in p->scond.
13097dd7cddfSDavid du Colombier  */
13107dd7cddfSDavid du Colombier int
modifiescpsr(Prog * p)13117dd7cddfSDavid du Colombier modifiescpsr(Prog *p)
13127dd7cddfSDavid du Colombier {
131359cc4ca5SDavid du Colombier 	return (p->scond&C_SBIT)
131459cc4ca5SDavid du Colombier 		|| p->as == ATST
13157dd7cddfSDavid du Colombier 		|| p->as == ATEQ
13167dd7cddfSDavid du Colombier 		|| p->as == ACMN
13177dd7cddfSDavid du Colombier 		|| p->as == ACMP
13187dd7cddfSDavid du Colombier 		|| p->as == AMULU
13197dd7cddfSDavid du Colombier 		|| p->as == ADIVU
13207dd7cddfSDavid du Colombier 		|| p->as == AMUL
13217dd7cddfSDavid du Colombier 		|| p->as == ADIV
13227dd7cddfSDavid du Colombier 		|| p->as == AMOD
13237dd7cddfSDavid du Colombier 		|| p->as == AMODU
13247dd7cddfSDavid du Colombier 		|| p->as == ABL;
13257dd7cddfSDavid du Colombier }
13267dd7cddfSDavid du Colombier 
132759cc4ca5SDavid du Colombier /*
132859cc4ca5SDavid du Colombier  * Find the maximal chain of instructions starting with r which could
132959cc4ca5SDavid du Colombier  * be executed conditionally
133059cc4ca5SDavid du Colombier  */
133159cc4ca5SDavid du Colombier int
joinsplit(Reg * r,Joininfo * j)133259cc4ca5SDavid du Colombier joinsplit(Reg *r, Joininfo *j)
13337dd7cddfSDavid du Colombier {
133459cc4ca5SDavid du Colombier 	j->start = r;
133559cc4ca5SDavid du Colombier 	j->last = r;
133659cc4ca5SDavid du Colombier 	j->len = 0;
133759cc4ca5SDavid du Colombier 	do {
133859cc4ca5SDavid du Colombier 		if (r->p2 && (r->p1 || r->p2->p2link)) {
133959cc4ca5SDavid du Colombier 			j->end = r;
134059cc4ca5SDavid du Colombier 			return Join;
13417dd7cddfSDavid du Colombier 		}
134259cc4ca5SDavid du Colombier 		if (r->s1 && r->s2) {
134359cc4ca5SDavid du Colombier 			j->end = r;
134459cc4ca5SDavid du Colombier 			return Split;
134559cc4ca5SDavid du Colombier 		}
134659cc4ca5SDavid du Colombier 		j->last = r;
134759cc4ca5SDavid du Colombier 		if (r->prog->as != ANOP)
134859cc4ca5SDavid du Colombier 			j->len++;
134959cc4ca5SDavid du Colombier 		if (!r->s1 && !r->s2) {
135059cc4ca5SDavid du Colombier 			j->end = r->link;
135159cc4ca5SDavid du Colombier 			return End;
135259cc4ca5SDavid du Colombier 		}
135359cc4ca5SDavid du Colombier 		if (r->s2) {
135459cc4ca5SDavid du Colombier 			j->end = r->s2;
135559cc4ca5SDavid du Colombier 			return Branch;
135659cc4ca5SDavid du Colombier 		}
135759cc4ca5SDavid du Colombier 		if (modifiescpsr(r->prog)) {
135859cc4ca5SDavid du Colombier 			j->end = r->s1;
135959cc4ca5SDavid du Colombier 			return Setcond;
136059cc4ca5SDavid du Colombier 		}
136159cc4ca5SDavid du Colombier 		r = r->s1;
136259cc4ca5SDavid du Colombier 	} while (j->len < 4);
136359cc4ca5SDavid du Colombier 	j->end = r;
136459cc4ca5SDavid du Colombier 	return Toolong;
13657dd7cddfSDavid du Colombier }
13667dd7cddfSDavid du Colombier 
13677dd7cddfSDavid du Colombier Reg *
successor(Reg * r)13687dd7cddfSDavid du Colombier successor(Reg *r)
13697dd7cddfSDavid du Colombier {
13707dd7cddfSDavid du Colombier 	if (r->s1)
13717dd7cddfSDavid du Colombier 		return r->s1;
13727dd7cddfSDavid du Colombier 	else
13737dd7cddfSDavid du Colombier 		return r->s2;
13747dd7cddfSDavid du Colombier }
13757dd7cddfSDavid du Colombier 
137659cc4ca5SDavid du Colombier void
applypred(Reg * rstart,Joininfo * j,int cond,int branch)137759cc4ca5SDavid du Colombier applypred(Reg *rstart, Joininfo *j, int cond, int branch)
13787dd7cddfSDavid du Colombier {
137959cc4ca5SDavid du Colombier 	int pred;
13807dd7cddfSDavid du Colombier 	Reg *r;
13817dd7cddfSDavid du Colombier 
138259cc4ca5SDavid du Colombier 	if(j->len == 0)
138359cc4ca5SDavid du Colombier 		return;
138459cc4ca5SDavid du Colombier 	if (cond == Truecond)
138559cc4ca5SDavid du Colombier 		pred = predinfo[rstart->prog->as - ABEQ].scond;
138659cc4ca5SDavid du Colombier 	else
138759cc4ca5SDavid du Colombier 		pred = predinfo[rstart->prog->as - ABEQ].notscond;
138859cc4ca5SDavid du Colombier 
138959cc4ca5SDavid du Colombier 	for (r = j->start; ; r = successor(r)) {
139059cc4ca5SDavid du Colombier 		if (r->prog->as == AB) {
139159cc4ca5SDavid du Colombier 			if (r != j->last || branch == Delbranch)
139259cc4ca5SDavid du Colombier 				excise(r);
139359cc4ca5SDavid du Colombier 			else {
139459cc4ca5SDavid du Colombier 			  if (cond == Truecond)
139559cc4ca5SDavid du Colombier 				r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
139659cc4ca5SDavid du Colombier 			  else
139759cc4ca5SDavid du Colombier 				r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
13987dd7cddfSDavid du Colombier 			}
13997dd7cddfSDavid du Colombier 		}
140059cc4ca5SDavid du Colombier 		else if (predicable(r->prog))
140159cc4ca5SDavid du Colombier 			r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
140259cc4ca5SDavid du Colombier 		if (r->s1 != r->link) {
140359cc4ca5SDavid du Colombier 			r->s1 = r->link;
140459cc4ca5SDavid du Colombier 			r->link->p1 = r;
140559cc4ca5SDavid du Colombier 		}
140659cc4ca5SDavid du Colombier 		if (r == j->last)
140759cc4ca5SDavid du Colombier 			break;
140859cc4ca5SDavid du Colombier 	}
14097dd7cddfSDavid du Colombier }
14107dd7cddfSDavid du Colombier 
14117dd7cddfSDavid du Colombier void
predicate(void)141259cc4ca5SDavid du Colombier predicate(void)
14137dd7cddfSDavid du Colombier {
14147dd7cddfSDavid du Colombier 	Reg *r;
141559cc4ca5SDavid du Colombier 	int t1, t2;
141659cc4ca5SDavid du Colombier 	Joininfo j1, j2;
14177dd7cddfSDavid du Colombier 
141859cc4ca5SDavid du Colombier 	for(r=firstr; r!=R; r=r->link) {
141959cc4ca5SDavid du Colombier 		if (isbranch(r->prog)) {
142059cc4ca5SDavid du Colombier 			t1 = joinsplit(r->s1, &j1);
142159cc4ca5SDavid du Colombier 			t2 = joinsplit(r->s2, &j2);
142259cc4ca5SDavid du Colombier 			if(j1.last->link != j2.start)
142359cc4ca5SDavid du Colombier 				continue;
142459cc4ca5SDavid du Colombier 			if(j1.end == j2.end)
142559cc4ca5SDavid du Colombier 			if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
142659cc4ca5SDavid du Colombier 			   (t2 == Join && (t1 == Join || t1 == Setcond))) {
142759cc4ca5SDavid du Colombier 				applypred(r, &j1, Falsecond, Delbranch);
142859cc4ca5SDavid du Colombier 				applypred(r, &j2, Truecond, Delbranch);
14297dd7cddfSDavid du Colombier 				excise(r);
143059cc4ca5SDavid du Colombier 				continue;
143159cc4ca5SDavid du Colombier 			}
143259cc4ca5SDavid du Colombier 			if(t1 == End || t1 == Branch) {
143359cc4ca5SDavid du Colombier 				applypred(r, &j1, Falsecond, Keepbranch);
143459cc4ca5SDavid du Colombier 				excise(r);
143559cc4ca5SDavid du Colombier 				continue;
143659cc4ca5SDavid du Colombier 			}
143759cc4ca5SDavid du Colombier 		}
143859cc4ca5SDavid du Colombier 	}
14397dd7cddfSDavid du Colombier }
1440