xref: /plan9-contrib/sys/src/cmd/5c/peep.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
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:
309*40d01547SDavid du Colombier 		case AMULU:
3107dd7cddfSDavid du Colombier 		case ADIV:
3117dd7cddfSDavid du Colombier 		case ADIVU:
3127dd7cddfSDavid du Colombier 
3137dd7cddfSDavid du Colombier 		case ACMPF:
3147dd7cddfSDavid du Colombier 		case ACMPD:
3157dd7cddfSDavid du Colombier 		case AADDD:
3167dd7cddfSDavid du Colombier 		case AADDF:
3177dd7cddfSDavid du Colombier 		case ASUBD:
3187dd7cddfSDavid du Colombier 		case ASUBF:
3197dd7cddfSDavid du Colombier 		case AMULD:
3207dd7cddfSDavid du Colombier 		case AMULF:
3217dd7cddfSDavid du Colombier 		case ADIVD:
3227dd7cddfSDavid du Colombier 		case ADIVF:
3237dd7cddfSDavid du Colombier 			if(p->to.type == v1->type)
3247dd7cddfSDavid du Colombier 			if(p->to.reg == v1->reg) {
3257dd7cddfSDavid du Colombier 				if(p->reg == NREG)
3267dd7cddfSDavid du Colombier 					p->reg = p->to.reg;
3277dd7cddfSDavid du Colombier 				goto gotit;
3287dd7cddfSDavid du Colombier 			}
3297dd7cddfSDavid du Colombier 			break;
3307dd7cddfSDavid du Colombier 
3317dd7cddfSDavid du Colombier 		case AMOVF:
3327dd7cddfSDavid du Colombier 		case AMOVD:
3337dd7cddfSDavid du Colombier 		case AMOVW:
3347dd7cddfSDavid du Colombier 			if(p->to.type == v1->type)
3357dd7cddfSDavid du Colombier 			if(p->to.reg == v1->reg)
3367dd7cddfSDavid du Colombier 				goto gotit;
3377dd7cddfSDavid du Colombier 			break;
33859cc4ca5SDavid du Colombier 
33959cc4ca5SDavid du Colombier 		case AMOVM:
34059cc4ca5SDavid du Colombier 			t = 1<<v2->reg;
34159cc4ca5SDavid du Colombier 			if((p->from.type == D_CONST && (p->from.offset&t)) ||
34259cc4ca5SDavid du Colombier 			   (p->to.type == D_CONST && (p->to.offset&t)))
34359cc4ca5SDavid du Colombier 				return 0;
34459cc4ca5SDavid du Colombier 			break;
3457dd7cddfSDavid du Colombier 		}
3467dd7cddfSDavid du Colombier 		if(copyau(&p->from, v2) ||
3477dd7cddfSDavid du Colombier 		   copyau1(p, v2) ||
3487dd7cddfSDavid du Colombier 		   copyau(&p->to, v2))
3497dd7cddfSDavid du Colombier 			break;
3507dd7cddfSDavid du Colombier 		if(copysub(&p->from, v1, v2, 0) ||
3517dd7cddfSDavid du Colombier 		   copysub1(p, v1, v2, 0) ||
3527dd7cddfSDavid du Colombier 		   copysub(&p->to, v1, v2, 0))
3537dd7cddfSDavid du Colombier 			break;
3547dd7cddfSDavid du Colombier 	}
3557dd7cddfSDavid du Colombier 	return 0;
3567dd7cddfSDavid du Colombier 
3577dd7cddfSDavid du Colombier gotit:
3587dd7cddfSDavid du Colombier 	copysub(&p->to, v1, v2, 1);
3597dd7cddfSDavid du Colombier 	if(debug['P']) {
3607dd7cddfSDavid du Colombier 		print("gotit: %D->%D\n%P", v1, v2, r->prog);
3617dd7cddfSDavid du Colombier 		if(p->from.type == v2->type)
3627dd7cddfSDavid du Colombier 			print(" excise");
3637dd7cddfSDavid du Colombier 		print("\n");
3647dd7cddfSDavid du Colombier 	}
3657dd7cddfSDavid du Colombier 	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
3667dd7cddfSDavid du Colombier 		p = r->prog;
3677dd7cddfSDavid du Colombier 		copysub(&p->from, v1, v2, 1);
3687dd7cddfSDavid du Colombier 		copysub1(p, v1, v2, 1);
3697dd7cddfSDavid du Colombier 		copysub(&p->to, v1, v2, 1);
3707dd7cddfSDavid du Colombier 		if(debug['P'])
3717dd7cddfSDavid du Colombier 			print("%P\n", r->prog);
3727dd7cddfSDavid du Colombier 	}
3737dd7cddfSDavid du Colombier 	t = v1->reg;
3747dd7cddfSDavid du Colombier 	v1->reg = v2->reg;
3757dd7cddfSDavid du Colombier 	v2->reg = t;
3767dd7cddfSDavid du Colombier 	if(debug['P'])
3777dd7cddfSDavid du Colombier 		print("%P last\n", r->prog);
3787dd7cddfSDavid du Colombier 	return 1;
3797dd7cddfSDavid du Colombier }
3807dd7cddfSDavid du Colombier 
3817dd7cddfSDavid du Colombier /*
3827dd7cddfSDavid du Colombier  * The idea is to remove redundant copies.
3837dd7cddfSDavid du Colombier  *	v1->v2	F=0
3847dd7cddfSDavid du Colombier  *	(use v2	s/v2/v1/)*
3857dd7cddfSDavid du Colombier  *	set v1	F=1
3867dd7cddfSDavid du Colombier  *	use v2	return fail
3877dd7cddfSDavid du Colombier  *	-----------------
3887dd7cddfSDavid du Colombier  *	v1->v2	F=0
3897dd7cddfSDavid du Colombier  *	(use v2	s/v2/v1/)*
3907dd7cddfSDavid du Colombier  *	set v1	F=1
3917dd7cddfSDavid du Colombier  *	set v2	return success
3927dd7cddfSDavid du Colombier  */
3937dd7cddfSDavid du Colombier int
copyprop(Reg * r0)3947dd7cddfSDavid du Colombier copyprop(Reg *r0)
3957dd7cddfSDavid du Colombier {
3967dd7cddfSDavid du Colombier 	Prog *p;
3977dd7cddfSDavid du Colombier 	Adr *v1, *v2;
3987dd7cddfSDavid du Colombier 	Reg *r;
3997dd7cddfSDavid du Colombier 
4007dd7cddfSDavid du Colombier 	p = r0->prog;
4017dd7cddfSDavid du Colombier 	v1 = &p->from;
4027dd7cddfSDavid du Colombier 	v2 = &p->to;
4037dd7cddfSDavid du Colombier 	if(copyas(v1, v2))
4047dd7cddfSDavid du Colombier 		return 1;
4057dd7cddfSDavid du Colombier 	for(r=firstr; r!=R; r=r->link)
4067dd7cddfSDavid du Colombier 		r->active = 0;
4077dd7cddfSDavid du Colombier 	return copy1(v1, v2, r0->s1, 0);
4087dd7cddfSDavid du Colombier }
4097dd7cddfSDavid du Colombier 
4107dd7cddfSDavid du Colombier int
copy1(Adr * v1,Adr * v2,Reg * r,int f)4117dd7cddfSDavid du Colombier copy1(Adr *v1, Adr *v2, Reg *r, int f)
4127dd7cddfSDavid du Colombier {
4137dd7cddfSDavid du Colombier 	int t;
4147dd7cddfSDavid du Colombier 	Prog *p;
4157dd7cddfSDavid du Colombier 
4167dd7cddfSDavid du Colombier 	if(r->active) {
4177dd7cddfSDavid du Colombier 		if(debug['P'])
4187dd7cddfSDavid du Colombier 			print("act set; return 1\n");
4197dd7cddfSDavid du Colombier 		return 1;
4207dd7cddfSDavid du Colombier 	}
4217dd7cddfSDavid du Colombier 	r->active = 1;
4227dd7cddfSDavid du Colombier 	if(debug['P'])
4237dd7cddfSDavid du Colombier 		print("copy %D->%D f=%d\n", v1, v2, f);
4247dd7cddfSDavid du Colombier 	for(; r != R; r = r->s1) {
4257dd7cddfSDavid du Colombier 		p = r->prog;
4267dd7cddfSDavid du Colombier 		if(debug['P'])
4277dd7cddfSDavid du Colombier 			print("%P", p);
4287dd7cddfSDavid du Colombier 		if(!f && uniqp(r) == R) {
4297dd7cddfSDavid du Colombier 			f = 1;
4307dd7cddfSDavid du Colombier 			if(debug['P'])
4317dd7cddfSDavid du Colombier 				print("; merge; f=%d", f);
4327dd7cddfSDavid du Colombier 		}
4337dd7cddfSDavid du Colombier 		t = copyu(p, v2, A);
4347dd7cddfSDavid du Colombier 		switch(t) {
4357dd7cddfSDavid du Colombier 		case 2:	/* rar, cant split */
4367dd7cddfSDavid du Colombier 			if(debug['P'])
4377dd7cddfSDavid du Colombier 				print("; %Drar; return 0\n", v2);
4387dd7cddfSDavid du Colombier 			return 0;
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier 		case 3:	/* set */
4417dd7cddfSDavid du Colombier 			if(debug['P'])
4427dd7cddfSDavid du Colombier 				print("; %Dset; return 1\n", v2);
4437dd7cddfSDavid du Colombier 			return 1;
4447dd7cddfSDavid du Colombier 
4457dd7cddfSDavid du Colombier 		case 1:	/* used, substitute */
4467dd7cddfSDavid du Colombier 		case 4:	/* use and set */
4477dd7cddfSDavid du Colombier 			if(f) {
4487dd7cddfSDavid du Colombier 				if(!debug['P'])
4497dd7cddfSDavid du Colombier 					return 0;
4507dd7cddfSDavid du Colombier 				if(t == 4)
4517dd7cddfSDavid du Colombier 					print("; %Dused+set and f=%d; return 0\n", v2, f);
4527dd7cddfSDavid du Colombier 				else
4537dd7cddfSDavid du Colombier 					print("; %Dused and f=%d; return 0\n", v2, f);
4547dd7cddfSDavid du Colombier 				return 0;
4557dd7cddfSDavid du Colombier 			}
4567dd7cddfSDavid du Colombier 			if(copyu(p, v2, v1)) {
4577dd7cddfSDavid du Colombier 				if(debug['P'])
4587dd7cddfSDavid du Colombier 					print("; sub fail; return 0\n");
4597dd7cddfSDavid du Colombier 				return 0;
4607dd7cddfSDavid du Colombier 			}
4617dd7cddfSDavid du Colombier 			if(debug['P'])
4627dd7cddfSDavid du Colombier 				print("; sub%D/%D", v2, v1);
4637dd7cddfSDavid du Colombier 			if(t == 4) {
4647dd7cddfSDavid du Colombier 				if(debug['P'])
4657dd7cddfSDavid du Colombier 					print("; %Dused+set; return 1\n", v2);
4667dd7cddfSDavid du Colombier 				return 1;
4677dd7cddfSDavid du Colombier 			}
4687dd7cddfSDavid du Colombier 			break;
4697dd7cddfSDavid du Colombier 		}
4707dd7cddfSDavid du Colombier 		if(!f) {
4717dd7cddfSDavid du Colombier 			t = copyu(p, v1, A);
4727dd7cddfSDavid du Colombier 			if(!f && (t == 2 || t == 3 || t == 4)) {
4737dd7cddfSDavid du Colombier 				f = 1;
4747dd7cddfSDavid du Colombier 				if(debug['P'])
4757dd7cddfSDavid du Colombier 					print("; %Dset and !f; f=%d", v1, f);
4767dd7cddfSDavid du Colombier 			}
4777dd7cddfSDavid du Colombier 		}
4787dd7cddfSDavid du Colombier 		if(debug['P'])
4797dd7cddfSDavid du Colombier 			print("\n");
4807dd7cddfSDavid du Colombier 		if(r->s2)
4817dd7cddfSDavid du Colombier 			if(!copy1(v1, v2, r->s2, f))
4827dd7cddfSDavid du Colombier 				return 0;
4837dd7cddfSDavid du Colombier 	}
4847dd7cddfSDavid du Colombier 	return 1;
4857dd7cddfSDavid du Colombier }
4867dd7cddfSDavid du Colombier 
4877dd7cddfSDavid du Colombier /*
48859cc4ca5SDavid du Colombier  * The idea is to remove redundant constants.
48959cc4ca5SDavid du Colombier  *	$c1->v1
49059cc4ca5SDavid du Colombier  *	($c1->v2 s/$c1/v1)*
49159cc4ca5SDavid du Colombier  *	set v1  return
49259cc4ca5SDavid du Colombier  * The v1->v2 should be eliminated by copy propagation.
49359cc4ca5SDavid du Colombier  */
49459cc4ca5SDavid du Colombier void
constprop(Adr * c1,Adr * v1,Reg * r)49559cc4ca5SDavid du Colombier constprop(Adr *c1, Adr *v1, Reg *r)
49659cc4ca5SDavid du Colombier {
49759cc4ca5SDavid du Colombier 	Prog *p;
49859cc4ca5SDavid du Colombier 
49959cc4ca5SDavid du Colombier 	if(debug['C'])
50059cc4ca5SDavid du Colombier 		print("constprop %D->%D\n", c1, v1);
50159cc4ca5SDavid du Colombier 	for(; r != R; r = r->s1) {
50259cc4ca5SDavid du Colombier 		p = r->prog;
50359cc4ca5SDavid du Colombier 		if(debug['C'])
50459cc4ca5SDavid du Colombier 			print("%P", p);
50559cc4ca5SDavid du Colombier 		if(uniqp(r) == R) {
50659cc4ca5SDavid du Colombier 			if(debug['C'])
50759cc4ca5SDavid du Colombier 				print("; merge; return\n");
50859cc4ca5SDavid du Colombier 			return;
50959cc4ca5SDavid du Colombier 		}
51059cc4ca5SDavid du Colombier 		if(p->as == AMOVW && copyas(&p->from, c1)) {
51159cc4ca5SDavid du Colombier 				if(debug['C'])
51259cc4ca5SDavid du Colombier 					print("; sub%D/%D", &p->from, v1);
51359cc4ca5SDavid du Colombier 				p->from = *v1;
51459cc4ca5SDavid du Colombier 		} else if(copyu(p, v1, A) > 1) {
51559cc4ca5SDavid du Colombier 			if(debug['C'])
51659cc4ca5SDavid du Colombier 				print("; %Dset; return\n", v1);
51759cc4ca5SDavid du Colombier 			return;
51859cc4ca5SDavid du Colombier 		}
51959cc4ca5SDavid du Colombier 		if(debug['C'])
52059cc4ca5SDavid du Colombier 			print("\n");
52159cc4ca5SDavid du Colombier 		if(r->s2)
52259cc4ca5SDavid du Colombier 			constprop(c1, v1, r->s2);
52359cc4ca5SDavid du Colombier 	}
52459cc4ca5SDavid du Colombier }
52559cc4ca5SDavid du Colombier 
52659cc4ca5SDavid du Colombier /*
52759cc4ca5SDavid du Colombier  * ASLL x,y,w
52859cc4ca5SDavid du Colombier  * .. (not use w, not set x y w)
52959cc4ca5SDavid du Colombier  * AXXX w,a,b (a != w)
53059cc4ca5SDavid du Colombier  * .. (not use w)
53159cc4ca5SDavid du Colombier  * (set w)
53259cc4ca5SDavid du Colombier  * ----------- changed to
53359cc4ca5SDavid du Colombier  * ..
53459cc4ca5SDavid du Colombier  * AXXX (x<<y),a,b
53559cc4ca5SDavid du Colombier  * ..
53659cc4ca5SDavid du Colombier  */
53759cc4ca5SDavid du Colombier #define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
53859cc4ca5SDavid du Colombier int
shiftprop(Reg * r)53959cc4ca5SDavid du Colombier shiftprop(Reg *r)
54059cc4ca5SDavid du Colombier {
54159cc4ca5SDavid du Colombier 	Reg *r1;
54259cc4ca5SDavid du Colombier 	Prog *p, *p1, *p2;
54359cc4ca5SDavid du Colombier 	int n, o;
54459cc4ca5SDavid du Colombier 	Adr a;
54559cc4ca5SDavid du Colombier 
54659cc4ca5SDavid du Colombier 	p = r->prog;
54759cc4ca5SDavid du Colombier 	if(p->to.type != D_REG)
54859cc4ca5SDavid du Colombier 		FAIL("BOTCH: result not reg");
54959cc4ca5SDavid du Colombier 	n = p->to.reg;
55059cc4ca5SDavid du Colombier 	a = zprog.from;
55159cc4ca5SDavid du Colombier 	if(p->reg != NREG && p->reg != p->to.reg) {
55259cc4ca5SDavid du Colombier 		a.type = D_REG;
55359cc4ca5SDavid du Colombier 		a.reg = p->reg;
55459cc4ca5SDavid du Colombier 	}
55559cc4ca5SDavid du Colombier 	if(debug['H'])
55659cc4ca5SDavid du Colombier 		print("shiftprop\n%P", p);
55759cc4ca5SDavid du Colombier 	r1 = r;
55859cc4ca5SDavid du Colombier 	for(;;) {
55959cc4ca5SDavid du Colombier 		/* find first use of shift result; abort if shift operands or result are changed */
56059cc4ca5SDavid du Colombier 		r1 = uniqs(r1);
56159cc4ca5SDavid du Colombier 		if(r1 == R)
56259cc4ca5SDavid du Colombier 			FAIL("branch");
56359cc4ca5SDavid du Colombier 		if(uniqp(r1) == R)
56459cc4ca5SDavid du Colombier 			FAIL("merge");
56559cc4ca5SDavid du Colombier 		p1 = r1->prog;
56659cc4ca5SDavid du Colombier 		if(debug['H'])
56759cc4ca5SDavid du Colombier 			print("\n%P", p1);
56859cc4ca5SDavid du Colombier 		switch(copyu(p1, &p->to, A)) {
56959cc4ca5SDavid du Colombier 		case 0:	/* not used or set */
57059cc4ca5SDavid du Colombier 			if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
57159cc4ca5SDavid du Colombier 			   (a.type == D_REG && copyu(p1, &a, A) > 1))
57259cc4ca5SDavid du Colombier 				FAIL("args modified");
57359cc4ca5SDavid du Colombier 			continue;
57459cc4ca5SDavid du Colombier 		case 3:	/* set, not used */
57559cc4ca5SDavid du Colombier 			FAIL("BOTCH: noref");
57659cc4ca5SDavid du Colombier 		}
57759cc4ca5SDavid du Colombier 		break;
57859cc4ca5SDavid du Colombier 	}
57959cc4ca5SDavid du Colombier 	/* check whether substitution can be done */
58059cc4ca5SDavid du Colombier 	switch(p1->as) {
58159cc4ca5SDavid du Colombier 	default:
58259cc4ca5SDavid du Colombier 		FAIL("non-dpi");
58359cc4ca5SDavid du Colombier 	case AAND:
58459cc4ca5SDavid du Colombier 	case AEOR:
58559cc4ca5SDavid du Colombier 	case AADD:
58659cc4ca5SDavid du Colombier 	case AADC:
58759cc4ca5SDavid du Colombier 	case AORR:
58859cc4ca5SDavid du Colombier 	case ASUB:
58959cc4ca5SDavid du Colombier 	case ARSB:
59059cc4ca5SDavid du Colombier 	case ASBC:
59159cc4ca5SDavid du Colombier 	case ARSC:
59259cc4ca5SDavid du Colombier 		if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
59359cc4ca5SDavid du Colombier 			if(p1->from.type != D_REG)
59459cc4ca5SDavid du Colombier 				FAIL("can't swap");
59559cc4ca5SDavid du Colombier 			p1->reg = p1->from.reg;
59659cc4ca5SDavid du Colombier 			p1->from.reg = n;
59759cc4ca5SDavid du Colombier 			switch(p1->as) {
59859cc4ca5SDavid du Colombier 			case ASUB:
59959cc4ca5SDavid du Colombier 				p1->as = ARSB;
60059cc4ca5SDavid du Colombier 				break;
60159cc4ca5SDavid du Colombier 			case ARSB:
60259cc4ca5SDavid du Colombier 				p1->as = ASUB;
60359cc4ca5SDavid du Colombier 				break;
60459cc4ca5SDavid du Colombier 			case ASBC:
60559cc4ca5SDavid du Colombier 				p1->as = ARSC;
60659cc4ca5SDavid du Colombier 				break;
60759cc4ca5SDavid du Colombier 			case ARSC:
60859cc4ca5SDavid du Colombier 				p1->as = ASBC;
60959cc4ca5SDavid du Colombier 				break;
61059cc4ca5SDavid du Colombier 			}
61159cc4ca5SDavid du Colombier 			if(debug['H'])
61259cc4ca5SDavid du Colombier 				print("\t=>%P", p1);
61359cc4ca5SDavid du Colombier 		}
61459cc4ca5SDavid du Colombier 	case ABIC:
61559cc4ca5SDavid du Colombier 	case ACMP:
61659cc4ca5SDavid du Colombier 	case ACMN:
61759cc4ca5SDavid du Colombier 		if(p1->reg == n)
61859cc4ca5SDavid du Colombier 			FAIL("can't swap");
61959cc4ca5SDavid du Colombier 		if(p1->reg == NREG && p1->to.reg == n)
62059cc4ca5SDavid du Colombier 			FAIL("shift result used twice");
62159cc4ca5SDavid du Colombier 	case AMVN:
62259cc4ca5SDavid du Colombier 		if(p1->from.type == D_SHIFT)
62359cc4ca5SDavid du Colombier 			FAIL("shift result used in shift");
62459cc4ca5SDavid du Colombier 		if(p1->from.type != D_REG || p1->from.reg != n)
62559cc4ca5SDavid du Colombier 			FAIL("BOTCH: where is it used?");
62659cc4ca5SDavid du Colombier 		break;
62759cc4ca5SDavid du Colombier 	}
62859cc4ca5SDavid du Colombier 	/* check whether shift result is used subsequently */
62959cc4ca5SDavid du Colombier 	p2 = p1;
63059cc4ca5SDavid du Colombier 	if(p1->to.reg != n)
63159cc4ca5SDavid du Colombier 	for (;;) {
63259cc4ca5SDavid du Colombier 		r1 = uniqs(r1);
63359cc4ca5SDavid du Colombier 		if(r1 == R)
63459cc4ca5SDavid du Colombier 			FAIL("inconclusive");
63559cc4ca5SDavid du Colombier 		p1 = r1->prog;
63659cc4ca5SDavid du Colombier 		if(debug['H'])
63759cc4ca5SDavid du Colombier 			print("\n%P", p1);
63859cc4ca5SDavid du Colombier 		switch(copyu(p1, &p->to, A)) {
63959cc4ca5SDavid du Colombier 		case 0:	/* not used or set */
64059cc4ca5SDavid du Colombier 			continue;
64159cc4ca5SDavid du Colombier 		case 3: /* set, not used */
64259cc4ca5SDavid du Colombier 			break;
64359cc4ca5SDavid du Colombier 		default:/* used */
64459cc4ca5SDavid du Colombier 			FAIL("reused");
64559cc4ca5SDavid du Colombier 		}
64659cc4ca5SDavid du Colombier 		break;
64759cc4ca5SDavid du Colombier 	}
64859cc4ca5SDavid du Colombier 	/* make the substitution */
64959cc4ca5SDavid du Colombier 	p2->from.type = D_SHIFT;
65059cc4ca5SDavid du Colombier 	p2->from.reg = NREG;
65159cc4ca5SDavid du Colombier 	o = p->reg;
65259cc4ca5SDavid du Colombier 	if(o == NREG)
65359cc4ca5SDavid du Colombier 		o = p->to.reg;
65459cc4ca5SDavid du Colombier 	switch(p->from.type){
65559cc4ca5SDavid du Colombier 	case D_CONST:
65659cc4ca5SDavid du Colombier 		o |= (p->from.offset&0x1f)<<7;
65759cc4ca5SDavid du Colombier 		break;
65859cc4ca5SDavid du Colombier 	case D_REG:
65959cc4ca5SDavid du Colombier 		o |= (1<<4) | (p->from.reg<<8);
66059cc4ca5SDavid du Colombier 		break;
66159cc4ca5SDavid du Colombier 	}
66259cc4ca5SDavid du Colombier 	switch(p->as){
66359cc4ca5SDavid du Colombier 	case ASLL:
66459cc4ca5SDavid du Colombier 		o |= 0<<5;
66559cc4ca5SDavid du Colombier 		break;
66659cc4ca5SDavid du Colombier 	case ASRL:
66759cc4ca5SDavid du Colombier 		o |= 1<<5;
66859cc4ca5SDavid du Colombier 		break;
66959cc4ca5SDavid du Colombier 	case ASRA:
67059cc4ca5SDavid du Colombier 		o |= 2<<5;
67159cc4ca5SDavid du Colombier 		break;
67259cc4ca5SDavid du Colombier 	}
67359cc4ca5SDavid du Colombier 	p2->from.offset = o;
67459cc4ca5SDavid du Colombier 	if(debug['H'])
67559cc4ca5SDavid du Colombier 		print("\t=>%P\tSUCCEED\n", p2);
67659cc4ca5SDavid du Colombier 	return 1;
67759cc4ca5SDavid du Colombier }
67859cc4ca5SDavid du Colombier 
67959cc4ca5SDavid du Colombier Reg*
findpre(Reg * r,Adr * v)68059cc4ca5SDavid du Colombier findpre(Reg *r, Adr *v)
68159cc4ca5SDavid du Colombier {
68259cc4ca5SDavid du Colombier 	Reg *r1;
68359cc4ca5SDavid du Colombier 
68459cc4ca5SDavid du Colombier 	for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
68559cc4ca5SDavid du Colombier 		if(uniqs(r1) != r)
68659cc4ca5SDavid du Colombier 			return R;
68759cc4ca5SDavid du Colombier 		switch(copyu(r1->prog, v, A)) {
68859cc4ca5SDavid du Colombier 		case 1: /* used */
68959cc4ca5SDavid du Colombier 		case 2: /* read-alter-rewrite */
69059cc4ca5SDavid du Colombier 			return R;
69159cc4ca5SDavid du Colombier 		case 3: /* set */
69259cc4ca5SDavid du Colombier 		case 4: /* set and used */
69359cc4ca5SDavid du Colombier 			return r1;
69459cc4ca5SDavid du Colombier 		}
69559cc4ca5SDavid du Colombier 	}
69659cc4ca5SDavid du Colombier 	return R;
69759cc4ca5SDavid du Colombier }
69859cc4ca5SDavid du Colombier 
69959cc4ca5SDavid du Colombier Reg*
findinc(Reg * r,Reg * r2,Adr * v)70059cc4ca5SDavid du Colombier findinc(Reg *r, Reg *r2, Adr *v)
70159cc4ca5SDavid du Colombier {
70259cc4ca5SDavid du Colombier 	Reg *r1;
70359cc4ca5SDavid du Colombier 	Prog *p;
70459cc4ca5SDavid du Colombier 
70559cc4ca5SDavid du Colombier 
70659cc4ca5SDavid du Colombier 	for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
70759cc4ca5SDavid du Colombier 		if(uniqp(r1) != r)
70859cc4ca5SDavid du Colombier 			return R;
70959cc4ca5SDavid du Colombier 		switch(copyu(r1->prog, v, A)) {
71059cc4ca5SDavid du Colombier 		case 0: /* not touched */
71159cc4ca5SDavid du Colombier 			continue;
71259cc4ca5SDavid du Colombier 		case 4: /* set and used */
71359cc4ca5SDavid du Colombier 			p = r1->prog;
71459cc4ca5SDavid du Colombier 			if(p->as == AADD)
71559cc4ca5SDavid du Colombier 			if(p->from.type == D_CONST)
71659cc4ca5SDavid du Colombier 			if(p->from.offset > -4096 && p->from.offset < 4096)
71759cc4ca5SDavid du Colombier 				return r1;
71859cc4ca5SDavid du Colombier 		default:
71959cc4ca5SDavid du Colombier 			return R;
72059cc4ca5SDavid du Colombier 		}
72159cc4ca5SDavid du Colombier 	}
72259cc4ca5SDavid du Colombier 	return R;
72359cc4ca5SDavid du Colombier }
72459cc4ca5SDavid du Colombier 
72559cc4ca5SDavid du Colombier int
nochange(Reg * r,Reg * r2,Prog * p)72659cc4ca5SDavid du Colombier nochange(Reg *r, Reg *r2, Prog *p)
72759cc4ca5SDavid du Colombier {
72859cc4ca5SDavid du Colombier 	Adr a[3];
72959cc4ca5SDavid du Colombier 	int i, n;
73059cc4ca5SDavid du Colombier 
73159cc4ca5SDavid du Colombier 	if(r == r2)
73259cc4ca5SDavid du Colombier 		return 1;
73359cc4ca5SDavid du Colombier 	n = 0;
73459cc4ca5SDavid du Colombier 	if(p->reg != NREG && p->reg != p->to.reg) {
73559cc4ca5SDavid du Colombier 		a[n].type = D_REG;
73659cc4ca5SDavid du Colombier 		a[n++].reg = p->reg;
73759cc4ca5SDavid du Colombier 	}
73859cc4ca5SDavid du Colombier 	switch(p->from.type) {
73959cc4ca5SDavid du Colombier 	case D_SHIFT:
74059cc4ca5SDavid du Colombier 		a[n].type = D_REG;
74159cc4ca5SDavid du Colombier 		a[n++].reg = p->from.offset&0xf;
74259cc4ca5SDavid du Colombier 	case D_REG:
74359cc4ca5SDavid du Colombier 		a[n].type = D_REG;
74459cc4ca5SDavid du Colombier 		a[n++].reg = p->from.reg;
74559cc4ca5SDavid du Colombier 	}
74659cc4ca5SDavid du Colombier 	if(n == 0)
74759cc4ca5SDavid du Colombier 		return 1;
74859cc4ca5SDavid du Colombier 	for(; r!=R && r!=r2; r=uniqs(r)) {
74959cc4ca5SDavid du Colombier 		p = r->prog;
75059cc4ca5SDavid du Colombier 		for(i=0; i<n; i++)
75159cc4ca5SDavid du Colombier 			if(copyu(p, &a[i], A) > 1)
75259cc4ca5SDavid du Colombier 				return 0;
75359cc4ca5SDavid du Colombier 	}
75459cc4ca5SDavid du Colombier 	return 1;
75559cc4ca5SDavid du Colombier }
75659cc4ca5SDavid du Colombier 
75759cc4ca5SDavid du Colombier int
findu1(Reg * r,Adr * v)75859cc4ca5SDavid du Colombier findu1(Reg *r, Adr *v)
75959cc4ca5SDavid du Colombier {
76059cc4ca5SDavid du Colombier 	for(; r != R; r = r->s1) {
76159cc4ca5SDavid du Colombier 		if(r->active)
76259cc4ca5SDavid du Colombier 			return 0;
76359cc4ca5SDavid du Colombier 		r->active = 1;
76459cc4ca5SDavid du Colombier 		switch(copyu(r->prog, v, A)) {
76559cc4ca5SDavid du Colombier 		case 1: /* used */
76659cc4ca5SDavid du Colombier 		case 2: /* read-alter-rewrite */
76759cc4ca5SDavid du Colombier 		case 4: /* set and used */
76859cc4ca5SDavid du Colombier 			return 1;
76959cc4ca5SDavid du Colombier 		case 3: /* set */
77059cc4ca5SDavid du Colombier 			return 0;
77159cc4ca5SDavid du Colombier 		}
77259cc4ca5SDavid du Colombier 		if(r->s2)
77359cc4ca5SDavid du Colombier 			if (findu1(r->s2, v))
77459cc4ca5SDavid du Colombier 				return 1;
77559cc4ca5SDavid du Colombier 	}
77659cc4ca5SDavid du Colombier 	return 0;
77759cc4ca5SDavid du Colombier }
77859cc4ca5SDavid du Colombier 
77959cc4ca5SDavid du Colombier int
finduse(Reg * r,Adr * v)78059cc4ca5SDavid du Colombier finduse(Reg *r, Adr *v)
78159cc4ca5SDavid du Colombier {
78259cc4ca5SDavid du Colombier 	Reg *r1;
78359cc4ca5SDavid du Colombier 
78459cc4ca5SDavid du Colombier 	for(r1=firstr; r1!=R; r1=r1->link)
78559cc4ca5SDavid du Colombier 		r1->active = 0;
78659cc4ca5SDavid du Colombier 	return findu1(r, v);
78759cc4ca5SDavid du Colombier }
78859cc4ca5SDavid du Colombier 
78959cc4ca5SDavid du Colombier int
xtramodes(Reg * r,Adr * a)79059cc4ca5SDavid du Colombier xtramodes(Reg *r, Adr *a)
79159cc4ca5SDavid du Colombier {
79259cc4ca5SDavid du Colombier 	Reg *r1, *r2, *r3;
79359cc4ca5SDavid du Colombier 	Prog *p, *p1;
79459cc4ca5SDavid du Colombier 	Adr v;
79559cc4ca5SDavid du Colombier 
79659cc4ca5SDavid du Colombier 	p = r->prog;
797375daca8SDavid du Colombier 	if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG)	/* byte load */
798375daca8SDavid du Colombier 		return 0;
79959cc4ca5SDavid du Colombier 	v = *a;
80059cc4ca5SDavid du Colombier 	v.type = D_REG;
80159cc4ca5SDavid du Colombier 	r1 = findpre(r, &v);
80259cc4ca5SDavid du Colombier 	if(r1 != R) {
80359cc4ca5SDavid du Colombier 		p1 = r1->prog;
80459cc4ca5SDavid du Colombier 		if(p1->to.type == D_REG && p1->to.reg == v.reg)
80559cc4ca5SDavid du Colombier 		switch(p1->as) {
80659cc4ca5SDavid du Colombier 		case AADD:
80759cc4ca5SDavid du Colombier 			if(p1->from.type == D_REG ||
80859cc4ca5SDavid du Colombier 			   (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
80959cc4ca5SDavid du Colombier 			    (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
81059cc4ca5SDavid du Colombier 			   (p1->from.type == D_CONST &&
81159cc4ca5SDavid du Colombier 			    p1->from.offset > -4096 && p1->from.offset < 4096))
81259cc4ca5SDavid du Colombier 			if(nochange(uniqs(r1), r, p1)) {
81359cc4ca5SDavid du Colombier 				if(a != &p->from || v.reg != p->to.reg)
81459cc4ca5SDavid du Colombier 				if (finduse(r->s1, &v)) {
81559cc4ca5SDavid du Colombier 					if(p1->reg == NREG || p1->reg == v.reg)
81659cc4ca5SDavid du Colombier 						/* pre-indexing */
81759cc4ca5SDavid du Colombier 						p->scond |= C_WBIT;
81859cc4ca5SDavid du Colombier 					else return 0;
81959cc4ca5SDavid du Colombier 				}
82059cc4ca5SDavid du Colombier 				switch (p1->from.type) {
82159cc4ca5SDavid du Colombier 				case D_REG:
82259cc4ca5SDavid du Colombier 					/* register offset */
82359cc4ca5SDavid du Colombier 					a->type = D_SHIFT;
82459cc4ca5SDavid du Colombier 					a->offset = p1->from.reg;
82559cc4ca5SDavid du Colombier 					break;
82659cc4ca5SDavid du Colombier 				case D_SHIFT:
82759cc4ca5SDavid du Colombier 					/* scaled register offset */
82859cc4ca5SDavid du Colombier 					a->type = D_SHIFT;
82959cc4ca5SDavid du Colombier 				case D_CONST:
83059cc4ca5SDavid du Colombier 					/* immediate offset */
83159cc4ca5SDavid du Colombier 					a->offset = p1->from.offset;
83259cc4ca5SDavid du Colombier 					break;
83359cc4ca5SDavid du Colombier 				}
83459cc4ca5SDavid du Colombier 				if(p1->reg != NREG)
83559cc4ca5SDavid du Colombier 					a->reg = p1->reg;
83659cc4ca5SDavid du Colombier 				excise(r1);
83759cc4ca5SDavid du Colombier 				return 1;
83859cc4ca5SDavid du Colombier 			}
83959cc4ca5SDavid du Colombier 			break;
84059cc4ca5SDavid du Colombier 		case AMOVW:
84159cc4ca5SDavid du Colombier 			if(p1->from.type == D_REG)
84259cc4ca5SDavid du Colombier 			if((r2 = findinc(r1, r, &p1->from)) != R) {
84359cc4ca5SDavid du Colombier 			for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
84459cc4ca5SDavid du Colombier 				;
84559cc4ca5SDavid du Colombier 			if(r3 == r) {
84659cc4ca5SDavid du Colombier 				/* post-indexing */
84759cc4ca5SDavid du Colombier 				p1 = r2->prog;
84859cc4ca5SDavid du Colombier 				a->reg = p1->to.reg;
84959cc4ca5SDavid du Colombier 				a->offset = p1->from.offset;
85059cc4ca5SDavid du Colombier 				p->scond |= C_PBIT;
85159cc4ca5SDavid du Colombier 				if(!finduse(r, &r1->prog->to))
85259cc4ca5SDavid du Colombier 					excise(r1);
85359cc4ca5SDavid du Colombier 				excise(r2);
85459cc4ca5SDavid du Colombier 				return 1;
85559cc4ca5SDavid du Colombier 			}
85659cc4ca5SDavid du Colombier 			}
85759cc4ca5SDavid du Colombier 			break;
85859cc4ca5SDavid du Colombier 		}
85959cc4ca5SDavid du Colombier 	}
86059cc4ca5SDavid du Colombier 	if(a != &p->from || a->reg != p->to.reg)
86159cc4ca5SDavid du Colombier 	if((r1 = findinc(r, R, &v)) != R) {
86259cc4ca5SDavid du Colombier 		/* post-indexing */
86359cc4ca5SDavid du Colombier 		p1 = r1->prog;
86459cc4ca5SDavid du Colombier 		a->offset = p1->from.offset;
86559cc4ca5SDavid du Colombier 		p->scond |= C_PBIT;
86659cc4ca5SDavid du Colombier 		excise(r1);
86759cc4ca5SDavid du Colombier 		return 1;
86859cc4ca5SDavid du Colombier 	}
86959cc4ca5SDavid du Colombier 	return 0;
87059cc4ca5SDavid du Colombier }
87159cc4ca5SDavid du Colombier 
87259cc4ca5SDavid du Colombier /*
8737dd7cddfSDavid du Colombier  * return
8747dd7cddfSDavid du Colombier  * 1 if v only used (and substitute),
8757dd7cddfSDavid du Colombier  * 2 if read-alter-rewrite
8767dd7cddfSDavid du Colombier  * 3 if set
8777dd7cddfSDavid du Colombier  * 4 if set and used
8787dd7cddfSDavid du Colombier  * 0 otherwise (not touched)
8797dd7cddfSDavid du Colombier  */
8807dd7cddfSDavid du Colombier int
copyu(Prog * p,Adr * v,Adr * s)8817dd7cddfSDavid du Colombier copyu(Prog *p, Adr *v, Adr *s)
8827dd7cddfSDavid du Colombier {
8837dd7cddfSDavid du Colombier 
8847dd7cddfSDavid du Colombier 	switch(p->as) {
8857dd7cddfSDavid du Colombier 
8867dd7cddfSDavid du Colombier 	default:
8877dd7cddfSDavid du Colombier 		if(debug['P'])
8887dd7cddfSDavid du Colombier 			print(" (???)");
8897dd7cddfSDavid du Colombier 		return 2;
8907dd7cddfSDavid du Colombier 
89159cc4ca5SDavid du Colombier 	case AMOVM:
89259cc4ca5SDavid du Colombier 		if(v->type != D_REG)
89359cc4ca5SDavid du Colombier 			return 0;
89459cc4ca5SDavid du Colombier 		if(p->from.type == D_CONST) {	/* read reglist, read/rar */
89559cc4ca5SDavid du Colombier 			if(s != A) {
89659cc4ca5SDavid du Colombier 				if(p->from.offset&(1<<v->reg))
89759cc4ca5SDavid du Colombier 					return 1;
89859cc4ca5SDavid du Colombier 				if(copysub(&p->to, v, s, 1))
89959cc4ca5SDavid du Colombier 					return 1;
90059cc4ca5SDavid du Colombier 				return 0;
90159cc4ca5SDavid du Colombier 			}
90259cc4ca5SDavid du Colombier 			if(copyau(&p->to, v)) {
90359cc4ca5SDavid du Colombier 				if(p->scond&C_WBIT)
90459cc4ca5SDavid du Colombier 					return 2;
90559cc4ca5SDavid du Colombier 				return 1;
90659cc4ca5SDavid du Colombier 			}
90759cc4ca5SDavid du Colombier 			if(p->from.offset&(1<<v->reg))
90859cc4ca5SDavid du Colombier 				return 1;
90959cc4ca5SDavid du Colombier 		} else {			/* read/rar, write reglist */
91059cc4ca5SDavid du Colombier 			if(s != A) {
91159cc4ca5SDavid du Colombier 				if(p->to.offset&(1<<v->reg))
91259cc4ca5SDavid du Colombier 					return 1;
91359cc4ca5SDavid du Colombier 				if(copysub(&p->from, v, s, 1))
91459cc4ca5SDavid du Colombier 					return 1;
91559cc4ca5SDavid du Colombier 				return 0;
91659cc4ca5SDavid du Colombier 			}
91759cc4ca5SDavid du Colombier 			if(copyau(&p->from, v)) {
91859cc4ca5SDavid du Colombier 				if(p->scond&C_WBIT)
91959cc4ca5SDavid du Colombier 					return 2;
92059cc4ca5SDavid du Colombier 				if(p->to.offset&(1<<v->reg))
92159cc4ca5SDavid du Colombier 					return 4;
92259cc4ca5SDavid du Colombier 				return 1;
92359cc4ca5SDavid du Colombier 			}
92459cc4ca5SDavid du Colombier 			if(p->to.offset&(1<<v->reg))
92559cc4ca5SDavid du Colombier 				return 3;
92659cc4ca5SDavid du Colombier 		}
92759cc4ca5SDavid du Colombier 		return 0;
9287dd7cddfSDavid du Colombier 
9297dd7cddfSDavid du Colombier 	case ANOP:	/* read, write */
9307dd7cddfSDavid du Colombier 	case AMOVW:
9317dd7cddfSDavid du Colombier 	case AMOVF:
9327dd7cddfSDavid du Colombier 	case AMOVD:
9337dd7cddfSDavid du Colombier 	case AMOVH:
9347dd7cddfSDavid du Colombier 	case AMOVHU:
9357dd7cddfSDavid du Colombier 	case AMOVB:
9367dd7cddfSDavid du Colombier 	case AMOVBU:
9377dd7cddfSDavid du Colombier 	case AMOVDW:
9387dd7cddfSDavid du Colombier 	case AMOVWD:
9397dd7cddfSDavid du Colombier 	case AMOVFD:
9407dd7cddfSDavid du Colombier 	case AMOVDF:
94159cc4ca5SDavid du Colombier 		if(p->scond&(C_WBIT|C_PBIT))
94259cc4ca5SDavid du Colombier 		if(v->type == D_REG) {
94359cc4ca5SDavid du Colombier 			if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
94459cc4ca5SDavid du Colombier 				if(p->from.reg == v->reg)
94559cc4ca5SDavid du Colombier 					return 2;
94659cc4ca5SDavid du Colombier 			} else {
94759cc4ca5SDavid du Colombier 		  		if(p->to.reg == v->reg)
94859cc4ca5SDavid du Colombier 				return 2;
94959cc4ca5SDavid du Colombier 			}
95059cc4ca5SDavid du Colombier 		}
9517dd7cddfSDavid du Colombier 		if(s != A) {
9527dd7cddfSDavid du Colombier 			if(copysub(&p->from, v, s, 1))
9537dd7cddfSDavid du Colombier 				return 1;
9547dd7cddfSDavid du Colombier 			if(!copyas(&p->to, v))
9557dd7cddfSDavid du Colombier 				if(copysub(&p->to, v, s, 1))
9567dd7cddfSDavid du Colombier 					return 1;
9577dd7cddfSDavid du Colombier 			return 0;
9587dd7cddfSDavid du Colombier 		}
9597dd7cddfSDavid du Colombier 		if(copyas(&p->to, v)) {
9607dd7cddfSDavid du Colombier 			if(copyau(&p->from, v))
9617dd7cddfSDavid du Colombier 				return 4;
9627dd7cddfSDavid du Colombier 			return 3;
9637dd7cddfSDavid du Colombier 		}
9647dd7cddfSDavid du Colombier 		if(copyau(&p->from, v))
9657dd7cddfSDavid du Colombier 			return 1;
9667dd7cddfSDavid du Colombier 		if(copyau(&p->to, v))
9677dd7cddfSDavid du Colombier 			return 1;
9687dd7cddfSDavid du Colombier 		return 0;
9697dd7cddfSDavid du Colombier 
9707dd7cddfSDavid du Colombier 
9717dd7cddfSDavid du Colombier 	case AADD:	/* read, read, write */
9727dd7cddfSDavid du Colombier 	case ASUB:
9737dd7cddfSDavid du Colombier 	case ARSB:
9747dd7cddfSDavid du Colombier 	case ASLL:
9757dd7cddfSDavid du Colombier 	case ASRL:
9767dd7cddfSDavid du Colombier 	case ASRA:
9777dd7cddfSDavid du Colombier 	case AORR:
9787dd7cddfSDavid du Colombier 	case AAND:
9797dd7cddfSDavid du Colombier 	case AEOR:
9807dd7cddfSDavid du Colombier 	case AMUL:
981*40d01547SDavid du Colombier 	case AMULU:
9827dd7cddfSDavid du Colombier 	case ADIV:
9837dd7cddfSDavid du Colombier 	case ADIVU:
9847dd7cddfSDavid du Colombier 	case AADDF:
9857dd7cddfSDavid du Colombier 	case AADDD:
9867dd7cddfSDavid du Colombier 	case ASUBF:
9877dd7cddfSDavid du Colombier 	case ASUBD:
9887dd7cddfSDavid du Colombier 	case AMULF:
9897dd7cddfSDavid du Colombier 	case AMULD:
9907dd7cddfSDavid du Colombier 	case ADIVF:
9917dd7cddfSDavid du Colombier 	case ADIVD:
9927dd7cddfSDavid du Colombier 
9937dd7cddfSDavid du Colombier 	case ACMPF:
9947dd7cddfSDavid du Colombier 	case ACMPD:
9957dd7cddfSDavid du Colombier 	case ACMP:
99659cc4ca5SDavid du Colombier 	case ACMN:
99759cc4ca5SDavid du Colombier 	case ACASE:
9987dd7cddfSDavid du Colombier 		if(s != A) {
9997dd7cddfSDavid du Colombier 			if(copysub(&p->from, v, s, 1))
10007dd7cddfSDavid du Colombier 				return 1;
10017dd7cddfSDavid du Colombier 			if(copysub1(p, v, s, 1))
10027dd7cddfSDavid du Colombier 				return 1;
10037dd7cddfSDavid du Colombier 			if(!copyas(&p->to, v))
10047dd7cddfSDavid du Colombier 				if(copysub(&p->to, v, s, 1))
10057dd7cddfSDavid du Colombier 					return 1;
10067dd7cddfSDavid du Colombier 			return 0;
10077dd7cddfSDavid du Colombier 		}
10087dd7cddfSDavid du Colombier 		if(copyas(&p->to, v)) {
10097dd7cddfSDavid du Colombier 			if(p->reg == NREG)
10107dd7cddfSDavid du Colombier 				p->reg = p->to.reg;
10117dd7cddfSDavid du Colombier 			if(copyau(&p->from, v))
10127dd7cddfSDavid du Colombier 				return 4;
10137dd7cddfSDavid du Colombier 			if(copyau1(p, v))
10147dd7cddfSDavid du Colombier 				return 4;
10157dd7cddfSDavid du Colombier 			return 3;
10167dd7cddfSDavid du Colombier 		}
10177dd7cddfSDavid du Colombier 		if(copyau(&p->from, v))
10187dd7cddfSDavid du Colombier 			return 1;
10197dd7cddfSDavid du Colombier 		if(copyau1(p, v))
10207dd7cddfSDavid du Colombier 			return 1;
10217dd7cddfSDavid du Colombier 		if(copyau(&p->to, v))
10227dd7cddfSDavid du Colombier 			return 1;
10237dd7cddfSDavid du Colombier 		return 0;
10247dd7cddfSDavid du Colombier 
10257dd7cddfSDavid du Colombier 	case ABEQ:	/* read, read */
10267dd7cddfSDavid du Colombier 	case ABNE:
10277dd7cddfSDavid du Colombier 	case ABCS:
10287dd7cddfSDavid du Colombier 	case ABHS:
10297dd7cddfSDavid du Colombier 	case ABCC:
10307dd7cddfSDavid du Colombier 	case ABLO:
10317dd7cddfSDavid du Colombier 	case ABMI:
10327dd7cddfSDavid du Colombier 	case ABPL:
10337dd7cddfSDavid du Colombier 	case ABVS:
10347dd7cddfSDavid du Colombier 	case ABVC:
10357dd7cddfSDavid du Colombier 	case ABHI:
10367dd7cddfSDavid du Colombier 	case ABLS:
10377dd7cddfSDavid du Colombier 	case ABGE:
10387dd7cddfSDavid du Colombier 	case ABLT:
10397dd7cddfSDavid du Colombier 	case ABGT:
10407dd7cddfSDavid du Colombier 	case ABLE:
10417dd7cddfSDavid du Colombier 		if(s != A) {
10427dd7cddfSDavid du Colombier 			if(copysub(&p->from, v, s, 1))
10437dd7cddfSDavid du Colombier 				return 1;
10447dd7cddfSDavid du Colombier 			return copysub1(p, v, s, 1);
10457dd7cddfSDavid du Colombier 		}
10467dd7cddfSDavid du Colombier 		if(copyau(&p->from, v))
10477dd7cddfSDavid du Colombier 			return 1;
10487dd7cddfSDavid du Colombier 		if(copyau1(p, v))
10497dd7cddfSDavid du Colombier 			return 1;
10507dd7cddfSDavid du Colombier 		return 0;
10517dd7cddfSDavid du Colombier 
10527dd7cddfSDavid du Colombier 	case AB:	/* funny */
10537dd7cddfSDavid du Colombier 		if(s != A) {
10547dd7cddfSDavid du Colombier 			if(copysub(&p->to, v, s, 1))
10557dd7cddfSDavid du Colombier 				return 1;
10567dd7cddfSDavid du Colombier 			return 0;
10577dd7cddfSDavid du Colombier 		}
10587dd7cddfSDavid du Colombier 		if(copyau(&p->to, v))
10597dd7cddfSDavid du Colombier 			return 1;
10607dd7cddfSDavid du Colombier 		return 0;
10617dd7cddfSDavid du Colombier 
10627dd7cddfSDavid du Colombier 	case ARET:	/* funny */
10637dd7cddfSDavid du Colombier 		if(v->type == D_REG)
10647dd7cddfSDavid du Colombier 		if(v->reg == REGRET)
10657dd7cddfSDavid du Colombier 			return 2;
10667dd7cddfSDavid du Colombier 		if(v->type == D_FREG)
10677dd7cddfSDavid du Colombier 		if(v->reg == FREGRET)
10687dd7cddfSDavid du Colombier 			return 2;
10697dd7cddfSDavid du Colombier 
10707dd7cddfSDavid du Colombier 	case ABL:	/* funny */
10717dd7cddfSDavid du Colombier 		if(v->type == D_REG) {
10727dd7cddfSDavid du Colombier 			if(v->reg <= REGEXT && v->reg > exregoffset)
10737dd7cddfSDavid du Colombier 				return 2;
107427acba7cSDavid du Colombier 			if(v->reg == (uchar)REGARG)
10757dd7cddfSDavid du Colombier 				return 2;
10767dd7cddfSDavid du Colombier 		}
10777dd7cddfSDavid du Colombier 		if(v->type == D_FREG)
10787dd7cddfSDavid du Colombier 			if(v->reg <= FREGEXT && v->reg > exfregoffset)
10797dd7cddfSDavid du Colombier 				return 2;
10807dd7cddfSDavid du Colombier 
10817dd7cddfSDavid du Colombier 		if(s != A) {
10827dd7cddfSDavid du Colombier 			if(copysub(&p->to, v, s, 1))
10837dd7cddfSDavid du Colombier 				return 1;
10847dd7cddfSDavid du Colombier 			return 0;
10857dd7cddfSDavid du Colombier 		}
10867dd7cddfSDavid du Colombier 		if(copyau(&p->to, v))
10877dd7cddfSDavid du Colombier 			return 4;
10887dd7cddfSDavid du Colombier 		return 3;
10897dd7cddfSDavid du Colombier 
10907dd7cddfSDavid du Colombier 	case ATEXT:	/* funny */
10917dd7cddfSDavid du Colombier 		if(v->type == D_REG)
109227acba7cSDavid du Colombier 			if(v->reg == (uchar)REGARG)
10937dd7cddfSDavid du Colombier 				return 3;
10947dd7cddfSDavid du Colombier 		return 0;
10957dd7cddfSDavid du Colombier 	}
10967dd7cddfSDavid du Colombier }
10977dd7cddfSDavid du Colombier 
10987dd7cddfSDavid du Colombier int
a2type(Prog * p)10997dd7cddfSDavid du Colombier a2type(Prog *p)
11007dd7cddfSDavid du Colombier {
11017dd7cddfSDavid du Colombier 
11027dd7cddfSDavid du Colombier 	switch(p->as) {
11037dd7cddfSDavid du Colombier 
11047dd7cddfSDavid du Colombier 	case ACMP:
110559cc4ca5SDavid du Colombier 	case ACMN:
11067dd7cddfSDavid du Colombier 
11077dd7cddfSDavid du Colombier 	case AADD:
11087dd7cddfSDavid du Colombier 	case ASUB:
11097dd7cddfSDavid du Colombier 	case ARSB:
11107dd7cddfSDavid du Colombier 	case ASLL:
11117dd7cddfSDavid du Colombier 	case ASRL:
11127dd7cddfSDavid du Colombier 	case ASRA:
11137dd7cddfSDavid du Colombier 	case AORR:
11147dd7cddfSDavid du Colombier 	case AAND:
11157dd7cddfSDavid du Colombier 	case AEOR:
11167dd7cddfSDavid du Colombier 	case AMUL:
1117*40d01547SDavid du Colombier 	case AMULU:
11187dd7cddfSDavid du Colombier 	case ADIV:
11197dd7cddfSDavid du Colombier 	case ADIVU:
11207dd7cddfSDavid du Colombier 		return D_REG;
11217dd7cddfSDavid du Colombier 
11227dd7cddfSDavid du Colombier 	case ACMPF:
11237dd7cddfSDavid du Colombier 	case ACMPD:
11247dd7cddfSDavid du Colombier 
11257dd7cddfSDavid du Colombier 	case AADDF:
11267dd7cddfSDavid du Colombier 	case AADDD:
11277dd7cddfSDavid du Colombier 	case ASUBF:
11287dd7cddfSDavid du Colombier 	case ASUBD:
11297dd7cddfSDavid du Colombier 	case AMULF:
11307dd7cddfSDavid du Colombier 	case AMULD:
11317dd7cddfSDavid du Colombier 	case ADIVF:
11327dd7cddfSDavid du Colombier 	case ADIVD:
11337dd7cddfSDavid du Colombier 		return D_FREG;
11347dd7cddfSDavid du Colombier 	}
11357dd7cddfSDavid du Colombier 	return D_NONE;
11367dd7cddfSDavid du Colombier }
11377dd7cddfSDavid du Colombier 
11387dd7cddfSDavid du Colombier /*
11397dd7cddfSDavid du Colombier  * direct reference,
11407dd7cddfSDavid du Colombier  * could be set/use depending on
11417dd7cddfSDavid du Colombier  * semantics
11427dd7cddfSDavid du Colombier  */
11437dd7cddfSDavid du Colombier int
copyas(Adr * a,Adr * v)11447dd7cddfSDavid du Colombier copyas(Adr *a, Adr *v)
11457dd7cddfSDavid du Colombier {
11467dd7cddfSDavid du Colombier 
114759cc4ca5SDavid du Colombier 	if(regtyp(v)) {
11487dd7cddfSDavid du Colombier 		if(a->type == v->type)
11497dd7cddfSDavid du Colombier 		if(a->reg == v->reg)
11507dd7cddfSDavid du Colombier 			return 1;
115159cc4ca5SDavid du Colombier 	} else if(v->type == D_CONST) {		/* for constprop */
115259cc4ca5SDavid du Colombier 		if(a->type == v->type)
115359cc4ca5SDavid du Colombier 		if(a->name == v->name)
115459cc4ca5SDavid du Colombier 		if(a->sym == v->sym)
115559cc4ca5SDavid du Colombier 		if(a->reg == v->reg)
115659cc4ca5SDavid du Colombier 		if(a->offset == v->offset)
115759cc4ca5SDavid du Colombier 			return 1;
115859cc4ca5SDavid du Colombier 	}
11597dd7cddfSDavid du Colombier 	return 0;
11607dd7cddfSDavid du Colombier }
11617dd7cddfSDavid du Colombier 
11627dd7cddfSDavid du Colombier /*
11637dd7cddfSDavid du Colombier  * either direct or indirect
11647dd7cddfSDavid du Colombier  */
11657dd7cddfSDavid du Colombier int
copyau(Adr * a,Adr * v)11667dd7cddfSDavid du Colombier copyau(Adr *a, Adr *v)
11677dd7cddfSDavid du Colombier {
11687dd7cddfSDavid du Colombier 
11697dd7cddfSDavid du Colombier 	if(copyas(a, v))
11707dd7cddfSDavid du Colombier 		return 1;
117159cc4ca5SDavid du Colombier 	if(v->type == D_REG) {
117259cc4ca5SDavid du Colombier 		if(a->type == D_OREG) {
11737dd7cddfSDavid du Colombier 			if(v->reg == a->reg)
11747dd7cddfSDavid du Colombier 				return 1;
117559cc4ca5SDavid du Colombier 		} else if(a->type == D_SHIFT) {
117659cc4ca5SDavid du Colombier 			if((a->offset&0xf) == v->reg)
117759cc4ca5SDavid du Colombier 				return 1;
117859cc4ca5SDavid du Colombier 			if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
117959cc4ca5SDavid du Colombier 				return 1;
118059cc4ca5SDavid du Colombier 		}
118159cc4ca5SDavid du Colombier 	}
11827dd7cddfSDavid du Colombier 	return 0;
11837dd7cddfSDavid du Colombier }
11847dd7cddfSDavid du Colombier 
11857dd7cddfSDavid du Colombier int
copyau1(Prog * p,Adr * v)11867dd7cddfSDavid du Colombier copyau1(Prog *p, Adr *v)
11877dd7cddfSDavid du Colombier {
11887dd7cddfSDavid du Colombier 
11897dd7cddfSDavid du Colombier 	if(regtyp(v)) {
11907dd7cddfSDavid du Colombier 		if(a2type(p) == v->type)
11917dd7cddfSDavid du Colombier 		if(p->reg == v->reg) {
11927dd7cddfSDavid du Colombier 			if(a2type(p) != v->type)
11937dd7cddfSDavid du Colombier 				print("botch a2type %P\n", p);
11947dd7cddfSDavid du Colombier 			return 1;
11957dd7cddfSDavid du Colombier 		}
11967dd7cddfSDavid du Colombier 	}
11977dd7cddfSDavid du Colombier 	return 0;
11987dd7cddfSDavid du Colombier }
11997dd7cddfSDavid du Colombier 
12007dd7cddfSDavid du Colombier /*
12017dd7cddfSDavid du Colombier  * substitute s for v in a
12027dd7cddfSDavid du Colombier  * return failure to substitute
12037dd7cddfSDavid du Colombier  */
12047dd7cddfSDavid du Colombier int
copysub(Adr * a,Adr * v,Adr * s,int f)12057dd7cddfSDavid du Colombier copysub(Adr *a, Adr *v, Adr *s, int f)
12067dd7cddfSDavid du Colombier {
12077dd7cddfSDavid du Colombier 
12087dd7cddfSDavid du Colombier 	if(f)
120959cc4ca5SDavid du Colombier 	if(copyau(a, v)) {
121059cc4ca5SDavid du Colombier 		if(a->type == D_SHIFT) {
121159cc4ca5SDavid du Colombier 			if((a->offset&0xf) == v->reg)
121259cc4ca5SDavid du Colombier 				a->offset = (a->offset&~0xf)|s->reg;
121359cc4ca5SDavid du Colombier 			if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
121459cc4ca5SDavid du Colombier 				a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
121559cc4ca5SDavid du Colombier 		} else
12167dd7cddfSDavid du Colombier 			a->reg = s->reg;
121759cc4ca5SDavid du Colombier 	}
12187dd7cddfSDavid du Colombier 	return 0;
12197dd7cddfSDavid du Colombier }
12207dd7cddfSDavid du Colombier 
12217dd7cddfSDavid du Colombier int
copysub1(Prog * p1,Adr * v,Adr * s,int f)12227dd7cddfSDavid du Colombier copysub1(Prog *p1, Adr *v, Adr *s, int f)
12237dd7cddfSDavid du Colombier {
12247dd7cddfSDavid du Colombier 
12257dd7cddfSDavid du Colombier 	if(f)
12267dd7cddfSDavid du Colombier 	if(copyau1(p1, v))
12277dd7cddfSDavid du Colombier 		p1->reg = s->reg;
12287dd7cddfSDavid du Colombier 	return 0;
12297dd7cddfSDavid du Colombier }
12307dd7cddfSDavid du Colombier 
12317dd7cddfSDavid du Colombier struct {
12327dd7cddfSDavid du Colombier 	int opcode;
123359cc4ca5SDavid du Colombier 	int notopcode;
12347dd7cddfSDavid du Colombier 	int scond;
12357dd7cddfSDavid du Colombier 	int notscond;
12367dd7cddfSDavid du Colombier } predinfo[]  = {
123759cc4ca5SDavid du Colombier 	{ ABEQ,	ABNE,	0x0,	0x1, },
123859cc4ca5SDavid du Colombier 	{ ABNE,	ABEQ,	0x1,	0x0, },
123959cc4ca5SDavid du Colombier 	{ ABCS,	ABCC,	0x2,	0x3, },
124059cc4ca5SDavid du Colombier 	{ ABHS,	ABLO,	0x2,	0x3, },
124159cc4ca5SDavid du Colombier 	{ ABCC,	ABCS,	0x3,	0x2, },
124259cc4ca5SDavid du Colombier 	{ ABLO,	ABHS,	0x3,	0x2, },
124359cc4ca5SDavid du Colombier 	{ ABMI,	ABPL,	0x4,	0x5, },
124459cc4ca5SDavid du Colombier 	{ ABPL,	ABMI,	0x5,	0x4, },
124559cc4ca5SDavid du Colombier 	{ ABVS,	ABVC,	0x6,	0x7, },
124659cc4ca5SDavid du Colombier 	{ ABVC,	ABVS,	0x7,	0x6, },
124759cc4ca5SDavid du Colombier 	{ ABHI,	ABLS,	0x8,	0x9, },
124859cc4ca5SDavid du Colombier 	{ ABLS,	ABHI,	0x9,	0x8, },
124959cc4ca5SDavid du Colombier 	{ ABGE,	ABLT,	0xA,	0xB, },
125059cc4ca5SDavid du Colombier 	{ ABLT,	ABGE,	0xB,	0xA, },
125159cc4ca5SDavid du Colombier 	{ ABGT,	ABLE,	0xC,	0xD, },
125259cc4ca5SDavid du Colombier 	{ ABLE,	ABGT,	0xD,	0xC, },
12537dd7cddfSDavid du Colombier };
12547dd7cddfSDavid du Colombier 
125559cc4ca5SDavid du Colombier typedef struct {
125659cc4ca5SDavid du Colombier 	Reg *start;
125759cc4ca5SDavid du Colombier 	Reg *last;
125859cc4ca5SDavid du Colombier 	Reg *end;
125959cc4ca5SDavid du Colombier 	int len;
126059cc4ca5SDavid du Colombier } Joininfo;
12617dd7cddfSDavid du Colombier 
126259cc4ca5SDavid du Colombier enum {
126359cc4ca5SDavid du Colombier 	Join,
126459cc4ca5SDavid du Colombier 	Split,
126559cc4ca5SDavid du Colombier 	End,
126659cc4ca5SDavid du Colombier 	Branch,
126759cc4ca5SDavid du Colombier 	Setcond,
126859cc4ca5SDavid du Colombier 	Toolong
126959cc4ca5SDavid du Colombier };
127059cc4ca5SDavid du Colombier 
127159cc4ca5SDavid du Colombier enum {
127259cc4ca5SDavid du Colombier 	Falsecond,
127359cc4ca5SDavid du Colombier 	Truecond,
127459cc4ca5SDavid du Colombier 	Delbranch,
127559cc4ca5SDavid du Colombier 	Keepbranch
127659cc4ca5SDavid du Colombier };
12777dd7cddfSDavid du Colombier 
12787dd7cddfSDavid du Colombier int
isbranch(Prog * p)12797dd7cddfSDavid du Colombier isbranch(Prog *p)
12807dd7cddfSDavid du Colombier {
12817dd7cddfSDavid du Colombier 	return (ABEQ <= p->as) && (p->as <= ABLE);
12827dd7cddfSDavid du Colombier }
12837dd7cddfSDavid du Colombier 
12847dd7cddfSDavid du Colombier int
predicable(Prog * p)12857dd7cddfSDavid du Colombier predicable(Prog *p)
12867dd7cddfSDavid du Colombier {
12877dd7cddfSDavid du Colombier 	if (isbranch(p)
128859cc4ca5SDavid du Colombier 		|| p->as == ANOP
12897dd7cddfSDavid du Colombier 		|| p->as == AXXX
12907dd7cddfSDavid du Colombier 		|| p->as == ADATA
12917dd7cddfSDavid du Colombier 		|| p->as == AGLOBL
12927dd7cddfSDavid du Colombier 		|| p->as == AGOK
12937dd7cddfSDavid du Colombier 		|| p->as == AHISTORY
12947dd7cddfSDavid du Colombier 		|| p->as == ANAME
1295375daca8SDavid du Colombier 		|| p->as == ASIGNAME
12967dd7cddfSDavid du Colombier 		|| p->as == ATEXT
12977dd7cddfSDavid du Colombier 		|| p->as == AWORD
12987dd7cddfSDavid du Colombier 		|| p->as == ADYNT
12997dd7cddfSDavid du Colombier 		|| p->as == AINIT
13007dd7cddfSDavid du Colombier 		|| p->as == ABCASE
13017dd7cddfSDavid du Colombier 		|| p->as == ACASE)
13027dd7cddfSDavid du Colombier 		return 0;
13037dd7cddfSDavid du Colombier 	return 1;
13047dd7cddfSDavid du Colombier }
13057dd7cddfSDavid du Colombier 
13067dd7cddfSDavid du Colombier /*
13077dd7cddfSDavid du Colombier  * Depends on an analysis of the encodings performed by 5l.
13087dd7cddfSDavid du Colombier  * These seem to be all of the opcodes that lead to the "S" bit
13097dd7cddfSDavid du Colombier  * being set in the instruction encodings.
13107dd7cddfSDavid du Colombier  *
131159cc4ca5SDavid du Colombier  * C_SBIT may also have been set explicitly in p->scond.
13127dd7cddfSDavid du Colombier  */
13137dd7cddfSDavid du Colombier int
modifiescpsr(Prog * p)13147dd7cddfSDavid du Colombier modifiescpsr(Prog *p)
13157dd7cddfSDavid du Colombier {
131659cc4ca5SDavid du Colombier 	return (p->scond&C_SBIT)
131759cc4ca5SDavid du Colombier 		|| p->as == ATST
13187dd7cddfSDavid du Colombier 		|| p->as == ATEQ
13197dd7cddfSDavid du Colombier 		|| p->as == ACMN
13207dd7cddfSDavid du Colombier 		|| p->as == ACMP
13217dd7cddfSDavid du Colombier 		|| p->as == AMULU
13227dd7cddfSDavid du Colombier 		|| p->as == ADIVU
13237dd7cddfSDavid du Colombier 		|| p->as == AMUL
13247dd7cddfSDavid du Colombier 		|| p->as == ADIV
13257dd7cddfSDavid du Colombier 		|| p->as == AMOD
13267dd7cddfSDavid du Colombier 		|| p->as == AMODU
13277dd7cddfSDavid du Colombier 		|| p->as == ABL;
13287dd7cddfSDavid du Colombier }
13297dd7cddfSDavid du Colombier 
133059cc4ca5SDavid du Colombier /*
133159cc4ca5SDavid du Colombier  * Find the maximal chain of instructions starting with r which could
133259cc4ca5SDavid du Colombier  * be executed conditionally
133359cc4ca5SDavid du Colombier  */
133459cc4ca5SDavid du Colombier int
joinsplit(Reg * r,Joininfo * j)133559cc4ca5SDavid du Colombier joinsplit(Reg *r, Joininfo *j)
13367dd7cddfSDavid du Colombier {
133759cc4ca5SDavid du Colombier 	j->start = r;
133859cc4ca5SDavid du Colombier 	j->last = r;
133959cc4ca5SDavid du Colombier 	j->len = 0;
134059cc4ca5SDavid du Colombier 	do {
134159cc4ca5SDavid du Colombier 		if (r->p2 && (r->p1 || r->p2->p2link)) {
134259cc4ca5SDavid du Colombier 			j->end = r;
134359cc4ca5SDavid du Colombier 			return Join;
13447dd7cddfSDavid du Colombier 		}
134559cc4ca5SDavid du Colombier 		if (r->s1 && r->s2) {
134659cc4ca5SDavid du Colombier 			j->end = r;
134759cc4ca5SDavid du Colombier 			return Split;
134859cc4ca5SDavid du Colombier 		}
134959cc4ca5SDavid du Colombier 		j->last = r;
135059cc4ca5SDavid du Colombier 		if (r->prog->as != ANOP)
135159cc4ca5SDavid du Colombier 			j->len++;
135259cc4ca5SDavid du Colombier 		if (!r->s1 && !r->s2) {
135359cc4ca5SDavid du Colombier 			j->end = r->link;
135459cc4ca5SDavid du Colombier 			return End;
135559cc4ca5SDavid du Colombier 		}
135659cc4ca5SDavid du Colombier 		if (r->s2) {
135759cc4ca5SDavid du Colombier 			j->end = r->s2;
135859cc4ca5SDavid du Colombier 			return Branch;
135959cc4ca5SDavid du Colombier 		}
136059cc4ca5SDavid du Colombier 		if (modifiescpsr(r->prog)) {
136159cc4ca5SDavid du Colombier 			j->end = r->s1;
136259cc4ca5SDavid du Colombier 			return Setcond;
136359cc4ca5SDavid du Colombier 		}
136459cc4ca5SDavid du Colombier 		r = r->s1;
136559cc4ca5SDavid du Colombier 	} while (j->len < 4);
136659cc4ca5SDavid du Colombier 	j->end = r;
136759cc4ca5SDavid du Colombier 	return Toolong;
13687dd7cddfSDavid du Colombier }
13697dd7cddfSDavid du Colombier 
13707dd7cddfSDavid du Colombier Reg *
successor(Reg * r)13717dd7cddfSDavid du Colombier successor(Reg *r)
13727dd7cddfSDavid du Colombier {
13737dd7cddfSDavid du Colombier 	if (r->s1)
13747dd7cddfSDavid du Colombier 		return r->s1;
13757dd7cddfSDavid du Colombier 	else
13767dd7cddfSDavid du Colombier 		return r->s2;
13777dd7cddfSDavid du Colombier }
13787dd7cddfSDavid du Colombier 
137959cc4ca5SDavid du Colombier void
applypred(Reg * rstart,Joininfo * j,int cond,int branch)138059cc4ca5SDavid du Colombier applypred(Reg *rstart, Joininfo *j, int cond, int branch)
13817dd7cddfSDavid du Colombier {
138259cc4ca5SDavid du Colombier 	int pred;
13837dd7cddfSDavid du Colombier 	Reg *r;
13847dd7cddfSDavid du Colombier 
138559cc4ca5SDavid du Colombier 	if(j->len == 0)
138659cc4ca5SDavid du Colombier 		return;
138759cc4ca5SDavid du Colombier 	if (cond == Truecond)
138859cc4ca5SDavid du Colombier 		pred = predinfo[rstart->prog->as - ABEQ].scond;
138959cc4ca5SDavid du Colombier 	else
139059cc4ca5SDavid du Colombier 		pred = predinfo[rstart->prog->as - ABEQ].notscond;
139159cc4ca5SDavid du Colombier 
139259cc4ca5SDavid du Colombier 	for (r = j->start; ; r = successor(r)) {
139359cc4ca5SDavid du Colombier 		if (r->prog->as == AB) {
139459cc4ca5SDavid du Colombier 			if (r != j->last || branch == Delbranch)
139559cc4ca5SDavid du Colombier 				excise(r);
139659cc4ca5SDavid du Colombier 			else {
139759cc4ca5SDavid du Colombier 			  if (cond == Truecond)
139859cc4ca5SDavid du Colombier 				r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
139959cc4ca5SDavid du Colombier 			  else
140059cc4ca5SDavid du Colombier 				r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
14017dd7cddfSDavid du Colombier 			}
14027dd7cddfSDavid du Colombier 		}
140359cc4ca5SDavid du Colombier 		else if (predicable(r->prog))
140459cc4ca5SDavid du Colombier 			r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
140559cc4ca5SDavid du Colombier 		if (r->s1 != r->link) {
140659cc4ca5SDavid du Colombier 			r->s1 = r->link;
140759cc4ca5SDavid du Colombier 			r->link->p1 = r;
140859cc4ca5SDavid du Colombier 		}
140959cc4ca5SDavid du Colombier 		if (r == j->last)
141059cc4ca5SDavid du Colombier 			break;
141159cc4ca5SDavid du Colombier 	}
14127dd7cddfSDavid du Colombier }
14137dd7cddfSDavid du Colombier 
14147dd7cddfSDavid du Colombier void
predicate(void)141559cc4ca5SDavid du Colombier predicate(void)
14167dd7cddfSDavid du Colombier {
14177dd7cddfSDavid du Colombier 	Reg *r;
141859cc4ca5SDavid du Colombier 	int t1, t2;
141959cc4ca5SDavid du Colombier 	Joininfo j1, j2;
14207dd7cddfSDavid du Colombier 
142159cc4ca5SDavid du Colombier 	for(r=firstr; r!=R; r=r->link) {
142259cc4ca5SDavid du Colombier 		if (isbranch(r->prog)) {
142359cc4ca5SDavid du Colombier 			t1 = joinsplit(r->s1, &j1);
142459cc4ca5SDavid du Colombier 			t2 = joinsplit(r->s2, &j2);
142559cc4ca5SDavid du Colombier 			if(j1.last->link != j2.start)
142659cc4ca5SDavid du Colombier 				continue;
142759cc4ca5SDavid du Colombier 			if(j1.end == j2.end)
142859cc4ca5SDavid du Colombier 			if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
142959cc4ca5SDavid du Colombier 			   (t2 == Join && (t1 == Join || t1 == Setcond))) {
143059cc4ca5SDavid du Colombier 				applypred(r, &j1, Falsecond, Delbranch);
143159cc4ca5SDavid du Colombier 				applypred(r, &j2, Truecond, Delbranch);
14327dd7cddfSDavid du Colombier 				excise(r);
143359cc4ca5SDavid du Colombier 				continue;
143459cc4ca5SDavid du Colombier 			}
143559cc4ca5SDavid du Colombier 			if(t1 == End || t1 == Branch) {
143659cc4ca5SDavid du Colombier 				applypred(r, &j1, Falsecond, Keepbranch);
143759cc4ca5SDavid du Colombier 				excise(r);
143859cc4ca5SDavid du Colombier 				continue;
143959cc4ca5SDavid du Colombier 			}
144059cc4ca5SDavid du Colombier 		}
144159cc4ca5SDavid du Colombier 	}
14427dd7cddfSDavid du Colombier }
1443