xref: /csrg-svn/old/pcc/c2.tahoe/c21.c (revision 35390)
126440Ssam #ifndef lint
2*35390Sdonn static char sccsid[] = "@(#)c21.c	1.10 (Berkeley/CCI) 08/25/88";
326440Ssam #endif
426440Ssam 
526440Ssam /*
626440Ssam  * C object code improver-- second part
726440Ssam  */
826440Ssam 
926440Ssam #include "c2.h"
1026440Ssam #include <stdio.h>
1126440Ssam #include <ctype.h>
1226440Ssam 
1326440Ssam int bitsize[] = {0,8,16,32,64,32,64}; /* index by type codes */
1426440Ssam 
redun3(p)1526440Ssam redun3(p) register struct node *p; {
1626440Ssam /* check for 3 addr instr which should be 2 addr */
1729775Ssam 	if (has3ops(p)) {
1826440Ssam 		if (equstr(regs[RT1],regs[RT3])
1926440Ssam 		  && (p->op==ADD || p->op==MUL || p->op==AND || p->op==OR || p->op==XOR)) {
2026440Ssam 			register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t;
2126440Ssam 		}
2226440Ssam 		if (equstr(regs[RT2],regs[RT3])) {
2326440Ssam 			p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0;
2426440Ssam 			lastrand=regs[RT2]; *regs[RT3]=0; return(1);
2526440Ssam 		}
2626440Ssam 	} return(0);
2726440Ssam }
2826440Ssam 
bmove()2926440Ssam bmove() {
3026440Ssam 	register struct node *p, *lastp; register char *cp1,*cp2; register int r;
3126440Ssam 	struct node *flops();
3226440Ssam 
3326440Ssam 	refcount();
3426440Ssam 	for (p=lastp= &first; 0!=(p=p->forw); lastp=p);
3526440Ssam 	clearreg(); clearuse();
3626440Ssam 	for (p=lastp; p!= &first; p=p->back) {
3726440Ssam 	if (debug) {
3826440Ssam 		printf("Uses: ");
3926440Ssam 		if (useacc)
4026440Ssam 			printf("acc: %s\n",useacc->code? useacc->code:"");
4126440Ssam 		for (r=NUSE;--r>=0;) if (uses[r])
4226440Ssam 			printf("%d: %s\n",r,uses[r]->code? uses[r]->code:"");
4326440Ssam 		printf("-\n");
4426440Ssam 	}
4526440Ssam 	r=(p->subop>>4)&0xF;
4626440Ssam 	splitrand(p);
4726440Ssam 	if (OP3==r && 0!=redun3(p)) {newcode(p); redunm++;}
4826440Ssam 		/* ops that do nothing */
4926440Ssam 	if(p->op==MOV && equstr(regs[RT1], regs[RT2]))
5026440Ssam 		if(p->forw->op!=CBR) {
5126440Ssam 			delnode(p); redunm++; continue;
5226440Ssam 		} else {
5326440Ssam 			p->op=TST; p->pop=0;
5426440Ssam 			while(*p->code++ != ',');
5526440Ssam 			redunm++;
5626440Ssam 		}
5726440Ssam 	else if((cp1=p->code, *cp1++)=='$' &&
5826440Ssam 	 (*cp1=='0' || *cp1=='1' || *cp1++=='-' && *cp1=='1') && cp1[1]==',') {
5929775Ssam 		switch((p->code[1]<<8)|ord(p->op)) {
6029775Ssam 		case (('0'<<8)|ord(ADD)):
6129775Ssam 		case (('0'<<8)|ord(SUB)):
6229775Ssam 		case (('-'<<8)|ord(AND)):
6329775Ssam 		case (('0'<<8)|ord(OR)):
6429775Ssam 		case (('0'<<8)|ord(XOR)):
6529775Ssam 		case (('1'<<8)|ord(MUL)):
6629775Ssam 		case (('1'<<8)|ord(DIV)):
6729775Ssam 		case (('0'<<8)|ord(SHAL)):
6829775Ssam 		case (('0'<<8)|ord(SHAR)):
6929775Ssam 		case (('0'<<8)|ord(SHL)):
7029775Ssam 		case (('0'<<8)|ord(SHR)):
7126440Ssam 			if(r == OP2) {
7226440Ssam 				if(p->forw->op!=CBR) {
7326440Ssam 					delnode(p); redunm++; continue;
7426440Ssam 				} else {
7526440Ssam 					p->op=TST; p->subop&=0xF; p->pop=0;
7626440Ssam 					while(*p->code++ != ',');
7726440Ssam 					redunm++;
7826440Ssam 				}
7926440Ssam 			} else {	/* OP3 or shift */
8026440Ssam 				p->op=MOV; p->subop&=0xF; p->pop=0;
8126440Ssam 				while(*p->code++ != ',');
8226440Ssam 				p = p->forw; redunm++; continue;
8326440Ssam 			}
8426440Ssam 			break;
8529775Ssam 		case (('0'<<8)|ord(MUL)):
8629775Ssam 		case (('0'<<8)|ord(AND)):
8726440Ssam 			p->op=CLR; p->subop&=0xF; p->pop=0;
8826440Ssam 			while(*p->code++ != ',');
8926440Ssam 			if(r == OP3)
9026440Ssam 				while(*p->code++ != ',');
9126440Ssam 			redunm++;
9226440Ssam 		}
9326440Ssam 	}
9426440Ssam 	switch (p->op) {
9526440Ssam 	case LABEL: case DLABEL:
9626440Ssam 		for (r=NUSE; --r>=0;)
9726440Ssam 			if (uses[r]) p->ref=(struct node *) (((int)p->ref)|(1<<r));
9826440Ssam 			if (useacc) p->ref=(struct node *) (((int)p->ref)|(1<<NUSE));
9926440Ssam 		break;
10026440Ssam 	case CALLS:
10126440Ssam 	case CALLF:
10226440Ssam 		clearuse(); goto std;
10329775Ssam 	case NIL:
10426440Ssam 		clearuse(); break;
10526440Ssam 	case CVT:
10626440Ssam 		{ long n;
10726440Ssam 		if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
10826440Ssam 		if (*cp1++!='$') goto std; splitrand(p);
10926440Ssam 		n = getnum(&regs[RT1][1]);
11026440Ssam 		if(r==BYTE && (n<-128 || n>127)) goto std;
11126440Ssam 		if(r==WORD && (n<-32768 || n>32767)) goto std;
11226440Ssam 		p->op = MOV; p->subop = r; p->pop = 0;
11326440Ssam 		} goto std;
11426440Ssam 
11526440Ssam 	case SUB:
11626440Ssam 		if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
11726440Ssam 		if (*cp1++!='$') goto std; splitrand(p);
11826440Ssam #ifdef MOVAFASTER
11926440Ssam 		if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
12026440Ssam 			char buf[C2_ASIZE]; cp2=buf; *cp2++='-';
12126440Ssam 			cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
12226440Ssam 			cp1="(fp),"; while (*cp2++= *cp1++); --cp2;
12326440Ssam 			cp1=regs[RT3]; while (*cp2++= *cp1++);
12426440Ssam 			p->code=copy(buf); p->op = MOVA; p->subop = BYTE; p->pop=0;
12526440Ssam 		} else
12626440Ssam #endif MOVAFASTER
12729670Ssam 		if (*cp1++=='-' && 0==(r=getnum(cp1)) &&
12829670Ssam 		!checkexpr(cp1)) {
12926440Ssam 			p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1;
13026440Ssam 		} goto std;
13126440Ssam 	case ADD:
13226440Ssam 		if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
13326440Ssam 		if (*cp1++!='$') goto std; splitrand(p);
13429775Ssam 		if (isstatic(cp1) && tempreg(regs[RT2],r) && uses[r]==p->forw)
13526440Ssam 		{
13626440Ssam 			/* address comp:
13726440Ssam 			**	addl2	$_foo,r0  \	movab	_foo[r0],bar
13826440Ssam 			**	movl	r0,bar	  /
13926440Ssam 			*/
14026440Ssam 			register struct	node	*pnext = p->forw;
14126440Ssam 			char	buf[C2_ASIZE];
14226440Ssam 
14326440Ssam 			if (pnext->op == MOV && pnext->subop == LONG)
14426440Ssam 			{
14526440Ssam 				cp1 = &regs[RT1][1]; cp2 = &buf[0];
14626440Ssam 				while (*cp2++ = *cp1++) ; cp2--;
14726440Ssam 				splitrand(pnext);
14826440Ssam 				if (r == isreg(regs[RT1]))
14926440Ssam 				{
15026440Ssam 					delnode(p); p = pnext;
15126440Ssam 					p->op = MOVA; p->subop = BYTE;
15226440Ssam 					p->pop = 0;
15326440Ssam 					cp1 = regs[RT1]; *cp2++ = '[';
15426440Ssam 					while (*cp2++ = *cp1++) ; cp2--;
15526440Ssam 					*cp2++ = ']'; *cp2++ = ',';
15626440Ssam 					cp1 = regs[RT2];
15726440Ssam 					while (*cp2++ = *cp1++) ;
15826440Ssam 					p->code = copy(buf);
15926440Ssam 				}
16026440Ssam 			}
16126440Ssam 		}
16226440Ssam 		else
16326440Ssam #ifdef MOVAFASTER
16426440Ssam 		if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
16526440Ssam 			cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
16626440Ssam 			cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=',';
16726440Ssam 			p->op = MOVA; p->subop = BYTE; p->pop=0;
16826440Ssam 		} else
16926440Ssam #endif MOVAFASTER
17029670Ssam 		if (*cp1++=='-' && 0==(r=getnum(cp1)) &&
17129670Ssam 		!checkexpr(cp1)) {
17226440Ssam 			p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1;
17326440Ssam 		}
17426440Ssam 		/* fall thru ... */
17526440Ssam 	case CASE:
17626440Ssam 	default: std:
17726440Ssam 		p=bflow(p); break;
17826440Ssam 
17926440Ssam 	case MUL:
18026440Ssam 		/*
18126440Ssam 		** Change multiplication
18226440Ssam 		** by constant powers of 2 to shifts.
18326440Ssam 		*/
18426440Ssam 		splitrand(p);
18526440Ssam 		if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std;
18626440Ssam 		if ((r = ispow2(getnum(&regs[RT1][1]))) <= 0) goto std;
18726440Ssam  		/* mull2 $2,x */
18826440Ssam 		if(r == 1 && p->subop == U(LONG, OP2)) {
18926440Ssam 			strcpy(regs[RT1], regs[RT2]);
19026440Ssam 			p->op = ADD; p->pop = 0; newcode(p);
19126440Ssam 			goto std;
19226440Ssam 		}
19326440Ssam 		if (p->subop == U(LONG,OP2))
19426440Ssam 			strcpy(regs[RT3], regs[RT2]);
19526440Ssam 		sprintf(regs[RT1], "$%d", r);
19626440Ssam 		p->op = SHL; p->subop = LONG;
19726440Ssam 		p->pop = 0; newcode(p);
19826440Ssam 		goto std;
19926440Ssam 
20026440Ssam 	case SHAL:
20126440Ssam 	case SHL:
20226440Ssam 	{
20326440Ssam 		/* bit tests:
20426440Ssam 		**	shll	A,$1,rC    \
20526440Ssam 		**	bitl	B,rC	    >	jbc	A,B,D
20626440Ssam 		**	jeql	D	   /
20726440Ssam 		**
20826440Ssam 		** address comp:
20926440Ssam 		**	shll	$1,bar,r0  \	movl	bar,r0
21026440Ssam 		**	movab	_foo[r0]   /	movaw	_foo[r0]
21126440Ssam 		**
21226440Ssam 		**	shll	$2,r0,r0   \	moval	_foo[r0]
21326440Ssam 		**	movab	_foo[r0]   /
21426440Ssam 		*/
21526440Ssam 		register struct	node	*pf;
21626440Ssam 		register struct	node	*pn;
21726440Ssam 		register int	shfrom, shto;
21826440Ssam 		long	shcnt;
21926440Ssam 		char	*regfrom;
22026440Ssam 
22126440Ssam 		splitrand(p);
22226440Ssam 		if (regs[RT1][0] != '$') {
22326440Ssam 			if(isreg(regs[RT1]) < 0) goto std; /* alignment */
22426440Ssam 			if (regs[RT2][0] != '$') goto std;
22526440Ssam 			if (getnum(&regs[RT2][1]) != 1) goto std;
22629775Ssam 			if (!tempreg(regs[RT3],r)) goto std;
22726440Ssam 			if ((pf = p->forw)->op != BIT && pf->op!=AND) goto std;
22826440Ssam 			if (uses[r] && uses[r] != pf) goto std;
22926440Ssam 			splitrand(pf);
23026440Ssam 			if (r == isreg(regs[RT1])) cp2 = regs[RT2];
23126440Ssam 			else if (r == isreg(regs[RT2])) cp2 = regs[RT1];
23226440Ssam 			else goto std;
23326440Ssam 			if (*cp2 == '$') goto std;
23426440Ssam 			if ((pn = pf->forw)->op != CBR) goto std;
23526440Ssam 			if (pn->subop != JEQ && pn->subop != JNE) goto std;
23626440Ssam 			delnode(p); delnode(pf);
23726440Ssam 			pn->subop = (pn->subop == JEQ) ? JBC : JBS;
23826440Ssam 			for(cp1=p->code; *cp1++!=',';);
23926440Ssam 			while (*cp1++= *cp2++);
24026440Ssam 			pn->code = p->code; pn->pop = NULL;
24126440Ssam 			uses[r] = NULL;
24226440Ssam 			nbj++;
24326440Ssam 			p = pn;
24426440Ssam 			goto std;
24526440Ssam 		}
24626440Ssam 		if ((shcnt = getnum(&regs[RT1][1])) < 1 || shcnt > 2) goto std;
24726440Ssam 		if ((shfrom = isreg(regs[RT2])) >= 0)
24826440Ssam 			regfrom = copy(regs[RT2]);
24929775Ssam 		if (tempreg(regs[RT3],shto))
25026440Ssam 		{
25126440Ssam 			int	regnum;
25226440Ssam 
25326440Ssam 			if (uses[shto] != (pf = p->forw)) goto ashadd;
25426440Ssam 			if (pf->op != MOVA && pf->op != PUSHA) goto ashadd;
25526440Ssam 			if (pf->subop != BYTE) goto ashadd;
25626440Ssam 			splitrand(pf);
25726440Ssam 			if (!indexa(regs[RT1])) goto std;
25826440Ssam 			cp2 = regs[RT1];
25926440Ssam 			if(!isstatic(cp2)) goto std;
26026440Ssam 			while (*cp2++ != '[') ;
26126440Ssam 			if (*cp2++ != 'r' || !isdigit(*cp2)) goto std;
26226440Ssam 			regnum = *cp2++ - '0';
26326440Ssam 			if (isdigit(*cp2))
26426440Ssam 			{
26526440Ssam 				if (cp2[1] != ']') goto std;
26626440Ssam 				regnum *= 10; regnum += *cp2 - '0';
26726440Ssam 			}
26826440Ssam 			if (regnum != shto) goto std;
26926440Ssam 			if (shfrom >= 0)	/* shll $N,r*,r0 */
27026440Ssam 			{
27126440Ssam 				delnode(p);
27226440Ssam 				p = pf;
27326440Ssam 				if (shfrom != shto)
27426440Ssam 				{
27526440Ssam 					uses[shto] = NULL; splitrand(pf);
27626440Ssam 					cp2=regs[RT1]; while (*cp2++!='[');
27726440Ssam 					cp1=regfrom; while (*cp2++= *cp1++);
27826440Ssam 					cp2[-1] = ']'; *cp2 = 0;
27926440Ssam 					newcode(pf);
28026440Ssam 				}
28126440Ssam 			}
28226440Ssam 			else
28326440Ssam 			{
28426440Ssam 				p->op = MOV; splitrand(p);
28526440Ssam 				strcpy(regs[RT1], regs[RT2]);
28626440Ssam 				strcpy(regs[RT2], regs[RT3]);
28726440Ssam 				regs[RT3][0] = '\0';
28826440Ssam 				p->pop = 0; newcode(p);
28926440Ssam 			}
29026440Ssam 			switch (shcnt)
29126440Ssam 			{
29226440Ssam 			case 1:	pf->subop = WORD; break;
29326440Ssam 			case 2:	pf->subop = LONG; break;
29426440Ssam 			}
29534266Sdonn 			pf->pop = 0;
29626440Ssam 			redunm++; nsaddr++;
297*35390Sdonn 			goto std;
29826440Ssam 		}
29926440Ssam ashadd:
30026440Ssam 		/* at this point, RT2 and RT3 are guaranteed to be simple regs*/
30126440Ssam 		if (shcnt == 1) {
30226440Ssam 			/*
30326440Ssam 			** quickie:
30426440Ssam 			**	shll	$1,A,A	>	addl2	A,A
30526440Ssam 			**	shll	$1,A,B	>	addl3	A,A,B
30626440Ssam 			*/
307*35390Sdonn 			if ((pf = p->forw)->op == CBR ||
308*35390Sdonn 			    (pf->op == MOV && (pf = pf->forw)->op == CBR))
309*35390Sdonn 				/*
310*35390Sdonn 				** shll and addl handle the N bit differently
311*35390Sdonn 				** on overflow; avoid N bit CBRs
312*35390Sdonn 				*/
313*35390Sdonn 				switch (pf->subop) {
314*35390Sdonn 				case JLE: case JGE: case JLT: case JGT:
315*35390Sdonn 					goto std;
316*35390Sdonn 				}
31726440Ssam 			p->op = ADD;
31826440Ssam 			strcpy(regs[RT1], regs[RT2]);
31926440Ssam 			if(equstr(regs[RT2], regs[RT3])) {
32026440Ssam 				p->subop = U(LONG,OP2);
32126440Ssam 				regs[RT3][0] = '\0';
32226440Ssam 			} else
32326440Ssam 				p->subop = U(LONG,OP3);
32426440Ssam 			p->pop = 0;
32526440Ssam 			newcode(p);
32626440Ssam 		}
32726440Ssam 		goto std;
32826440Ssam 	}
32926440Ssam 
33026440Ssam 	case SHAR:
33126440Ssam 	case SHR:
33226440Ssam 	{
33326440Ssam 		/* bit tests:
33426440Ssam 		**	shrl	A,B,rC     \
33526440Ssam 		**	bitl	$1,rC	    >	jbc	A,B,D
33626440Ssam 		**	jeql	D	   /
33726440Ssam 		*/
33826440Ssam 		register struct	node	*pf;	/* forward node */
33926440Ssam 		register struct	node	*pn;	/* next node (after pf) */
34026440Ssam 		register int	extreg;		/* reg extracted to */
34126440Ssam 
34226440Ssam 		splitrand(p);
34326440Ssam 		if(isreg(regs[RT1]) < 0) goto std; /* alignment */
34429775Ssam 		if (!tempreg(regs[RT3],extreg)) goto std;
34526440Ssam 		if ((pf = p->forw)->op != BIT) goto std;
34626440Ssam 		if (uses[extreg] && uses[extreg] != pf) goto std;
34726440Ssam 		splitrand(pf);
34826440Ssam 		if (regs[RT1][0] != '$') goto std;
34926440Ssam 		if (getnum(&regs[RT1][1]) != 1) goto std;
35026440Ssam 		if (extreg != isreg(regs[RT2])) goto std;
35126440Ssam 		if ((pn = pf->forw)->op != CBR) goto std;
35226440Ssam 		if (pn->subop != JEQ && pn->subop != JNE) goto std;
35326440Ssam 		delnode(p); delnode(pf);
35426440Ssam 		pn->subop = (pn->subop == JEQ) ? JBC : JBS;
35526440Ssam 		for(cp1=p->code; *cp1++!=',';);
35626440Ssam 		while (*cp1!=',') cp1++; *cp1='\0';
35726440Ssam 		pn->code = p->code; pn->pop = NULL;
35826440Ssam 		uses[extreg] = NULL; nbj++;
35926440Ssam 		p = pn;
36026440Ssam 		goto std;
36126440Ssam 	}
36226440Ssam 
36326440Ssam 	case AND:
36426440Ssam 	{
36526440Ssam 		/* unsigned conversion:
36626440Ssam 		**	cvtbl	A,B;	andl2	$255,B > movzbl	A,B
36726440Ssam 		**
36826440Ssam 		** also byte- and word-size fields:
36926440Ssam 		**	shrl	$(3-n)*8,A,B; andl2	$255,B	>	movzbl	n+A,B
37026440Ssam 		**	shrl	$(1-n)*16,A,B; andl2	$65535,B >	movzwl	n+A,B
37126440Ssam 		*/
37226440Ssam 		char src[C2_ASIZE];
37326440Ssam 		register int f;	/* field length */
37426440Ssam 		register struct	node	*pb = p->back;	/* backward node */
37526440Ssam 
37626440Ssam 		if (p->subop != U(LONG,OP2))
37726440Ssam 			goto std;
37826440Ssam 		splitrand(p); cp1=regs[RT1];
37926440Ssam 		if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff)
38026440Ssam 			goto std;
38126440Ssam 		f = f==0xff ? 8 : 16;
38226440Ssam 		if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR)
38326440Ssam 			goto std;
38426440Ssam 		/* save source of ANDL in 'src' */
38526440Ssam 		strcpy(src, regs[RT2]);
38626440Ssam 		splitrand(pb);
38726440Ssam 		if (!equstr(src,lastrand))
38826440Ssam 			goto std;
38926440Ssam 		if (pb->op==CVT || pb->op==MOVZ) {
39026440Ssam 			if (!(bitsize[pb->subop&0xF]==f
39126440Ssam 			  && bitsize[pb->subop>>4]>=f)) /* good CVT */
39226440Ssam 				goto std;
39326440Ssam 			strcpy(src, regs[RT1]);
39426440Ssam 		} else {
39526440Ssam 			register int	boff;	/* bit offset */
39626440Ssam 
39726440Ssam 			if (regs[RT1][0] != '$') goto std;
39826440Ssam 			if ((boff = getnum(&regs[RT1][1])) < 0) goto std;
39926440Ssam 			if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std;
40026440Ssam 			if ((boff & (f-1)) != 0) goto std;
40126440Ssam 			boff = (32-boff-f) / 8;
40226440Ssam 			if (boff == 0)
40326440Ssam 				strcpy(src, regs[RT2]);
40426440Ssam 			else
40526440Ssam 				sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+",
40626440Ssam 					regs[RT2]);
40726440Ssam 		}
40826440Ssam 		delnode(pb);
40926440Ssam 		p->op = MOVZ;
41026440Ssam 		p->subop = U((f==8 ? BYTE : WORD), LONG);
41126440Ssam 		sprintf(line,"%s,%s",src,lastrand);
41226440Ssam 		p->pop=0;
41326440Ssam 		p->code = copy(line);
41426440Ssam 		goto std;
41526440Ssam 	}
41626440Ssam 
41726440Ssam 	case CMP:
41826440Ssam 	{
41926440Ssam 		/* comparison to -63 to -1:
42026440Ssam 		**	cmpl	r0,$-1	>	incl	r0
42126440Ssam 		**	jeql	...
42226440Ssam 		**
42326440Ssam 		**	cmpl	r0,$-63	>	addl2	$63,r0
42426440Ssam 		**	jeql	...
42526440Ssam 		*/
42626440Ssam 		register int	num;
42726440Ssam 		register int	reg;
42826440Ssam 		register struct	node	*regp = p->back;
42926440Ssam 
43026440Ssam 		if (p->forw->op != CBR) goto std;
43126440Ssam 		if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std;
43226440Ssam 		splitrand(p);
43326440Ssam 		if (strncmp(regs[RT2], "$-", 2) != 0) goto std;
43426440Ssam 		reg = r = isreg(regs[RT1]);
43526440Ssam 		if (r < 0) goto std;
43626440Ssam 		if (r < NUSE && uses[r] != 0) goto std;
43726440Ssam 		if (r >= NUSE && regp->op == MOV && p->subop == regp->subop)
43826440Ssam 		{
43926440Ssam 			if (*regp->code != 'r') goto std;
44026440Ssam 			reg = regp->code[1] - '0';
44126440Ssam 			if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg])
44226440Ssam 				goto std;
44326440Ssam 		}
44426440Ssam 		if (r >= NUSE) goto std;
44526440Ssam 		if (reg != r)
44626440Ssam 			sprintf(regs[RT1], "r%d", reg);
44726440Ssam 		if ((num = getnum(&regs[RT2][2])) <= 0 || num > 63) goto std;
44826440Ssam 		if (num == 1)
44926440Ssam 		{
45026440Ssam 			p->op = INC; regs[RT2][0] = '\0';
45126440Ssam 		}
45226440Ssam 		else
45326440Ssam 		{
45426440Ssam 			register char	*t;
45526440Ssam 
45626440Ssam 			t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t;
45726440Ssam 			p->op = ADD; p->subop = U(p->subop, OP2);
45826440Ssam 			for (t = &regs[RT1][2]; t[-1] = *t; t++) ;
45926440Ssam 		}
46026440Ssam 		p->pop = 0; newcode(p);
46126440Ssam 		goto std;
46226440Ssam 	}
46326440Ssam 
46426440Ssam 	case JBR: case JMP:
46526440Ssam 		clearuse();
46626440Ssam 		if ((p->subop&0xF)==RET) {
46726440Ssam 			switch((p->subop>>4)&0xF) {
46826440Ssam 				case 2: uses[1]=p; regs[1][0]= -1;
46926440Ssam 				case 1: uses[0]=p; regs[0][0]= -1;
47026440Ssam 			}
47126440Ssam 			break;
47226440Ssam 		}
47326440Ssam 		if (p->ref==0) goto std;	/* jmp (r0) */
47426440Ssam 		/* fall through */
47526440Ssam 	case CBR:
47626440Ssam 		if (p->ref->ref!=0) {
47726440Ssam 			for (r=NUSE;--r>=0;)
47826440Ssam 				if ((1<<r) & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;}
47926440Ssam 			if ((1<<NUSE) & (int)p->ref->ref) useacc=p;
48026440Ssam 		}
48126440Ssam 		break;
48226440Ssam 	case LNF:
48326440Ssam 		/* lnf a; addf b ==> ldf b; subf a */
48426440Ssam 		{ register struct node	*pf = p->forw;
48526440Ssam 		if(pf->op==ADDF && p->subop==pf->subop) {
48626440Ssam 			p->op = LDF;
48726440Ssam 			p->pop = 0;
48826440Ssam 			pf->op = SUBF;
48926440Ssam 			pf->pop = 0;
49026440Ssam 			cp1 = p->code;
49126440Ssam 			p->code = pf->code;
49226440Ssam 			pf->code = cp1;
49326440Ssam 			p = pf->forw;
49426440Ssam 			break;
49526440Ssam 		}}
49626440Ssam 	case LDF: case LDFD: case CVLF: /* destroy acc */
49726440Ssam 		useacc = 0;
49826440Ssam 		goto std;
49926440Ssam 	case STF:
50026440Ssam 		{ register struct node	*pf;
50126440Ssam 		if((pf=flops(p)) != p) {
50226440Ssam 			p = pf; /* usually p->forw; */
50326440Ssam 			break;
50426440Ssam 		}}
50526440Ssam 		if(ldmov(p)) {
50626440Ssam 			p = p->forw;
50726440Ssam 			break;
50826440Ssam 		}
50926440Ssam 		if(useacc == 0)
51026440Ssam 			useacc = p;
51126440Ssam 		goto std;
51226440Ssam 	case ADDF: case MULF: /* commutatives - create clients for flops */
51326440Ssam 		/* stf a; ldf b; addf a => stf a; ldf a; addf b */
51426440Ssam 		{ register struct node	*pb = p->back;
51526440Ssam 		register struct node	*pbb = pb->back;
51626440Ssam 		if(pb->op==LDF && pb->subop==p->subop &&
51726440Ssam 		 pbb && pbb->op==STF && pbb->subop==p->subop &&
51826440Ssam 		 equstr(pbb->code, p->code)) {
51926440Ssam 			cp1 = p->code;
52026440Ssam 			p->code = pb->code;
52126440Ssam 			pb->code = cp1;
52226440Ssam 		}}
52326440Ssam 	/* use acc and regs */
52426440Ssam 	case CMPF: case CVFL: case SUBF: case DIVF:
52526440Ssam 		if(useacc == 0)
52626440Ssam 			useacc = p;
52726440Ssam 		goto std;
52829670Ssam 	case TSTF:
52929670Ssam 		break;
53029670Ssam 	case PUSHD:
53126440Ssam 		if(ldmov(p)) {
53226440Ssam 			p = p->forw;
53326440Ssam 			break;
53426440Ssam 		}
53526440Ssam 	case CVDF: case NEGF: /* use only acc */
53626440Ssam 	case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF:
53726440Ssam 		if(useacc == 0)
53826440Ssam 			useacc = p;
53926440Ssam 	case EROU: case JSW:
54026440Ssam 	case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ;
54126440Ssam 	}
54226440Ssam 	}
54326440Ssam 	for (p= &first; p!=0; p=p->forw)
54426440Ssam 		if (p->op==LABEL || p->op==DLABEL) p->ref=0;	/* erase our tracks */
54526440Ssam }
54626440Ssam 
54726440Ssam char *
byondrd(p)54826440Ssam byondrd(p) register struct node *p; {
54926440Ssam /* return pointer to register which is "beyond last read/modify operand" */
55029775Ssam 	if (has2ops(p)) return(regs[RT3]);
55126440Ssam 	switch (p->op) {
55226440Ssam 		case MFPR:
55326440Ssam 		case PUSHA:
55426440Ssam 		case TST: case INC: case DEC: case PUSH:
55526440Ssam 		case LDF: case LNF: case CVLF: case LDFD:
55626440Ssam 		case ADDF: case SUBF: case MULF: case DIVF:
55726440Ssam 		case CMPF:
55826440Ssam 			return(regs[RT2]);
55926440Ssam 		case MTPR:
56026440Ssam #ifndef EMOD
56126440Ssam 		case EDIV:
56226440Ssam #endif EMOD
56326440Ssam 		case CBR: /* must be JBC/JBS */
56426440Ssam 		case BIT: case CMP: case CALLS:	case CALLF:
56526440Ssam 		case CMPF2:
56626440Ssam 			return(regs[RT3]);
56726440Ssam 		case EMUL:
56826440Ssam 		case PROBE:
56926440Ssam 		case MOVBLK:
57026440Ssam 		case CASE:
57126440Ssam 			return(regs[RT4]);
57226440Ssam 	}
57326440Ssam 	return(lastrand);
57426440Ssam }
57526440Ssam 
57626440Ssam struct node *
bflow(p)57726440Ssam bflow(p)
57829775Ssam 	register struct node *p;
57926440Ssam {
58026440Ssam 	register char *cp1,*cp2,**preg;
58126440Ssam 	register int r, fr, dblflg=0;
58226440Ssam 	int flow= -1;
58326440Ssam 	struct node *olduse=0, *olduse1=0;
58426440Ssam 
58533361Sdonn 	if (p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4 ||
58633361Sdonn 	    p->op==EMUL)
58726440Ssam 		dblflg |= 1;	/* double dest */
58829775Ssam 	if ((p->subop&0xF)==DOUBLE || p->subop==QUAD)
58926440Ssam 		dblflg |= 2;	/* double src */
59026440Ssam 	splitrand(p);
59129775Ssam 	if (p->op!=PUSH &&
59226440Ssam #ifndef EMOD
59329775Ssam 	p->op!=EDIV &&
59426440Ssam #endif EMOD
59529775Ssam 	p->op!=EMUL &&
59629775Ssam 	p->subop && tempreg(lastrand,r) && uses[r]==p->forw) {
59729775Ssam 	if (equtype(p->subop,regs[r][0]) ||
59829775Ssam 	    ((p->op==CVT || p->op==MOVZ || p->op==CVFL) &&
59929775Ssam 	     (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) ||
60029775Ssam 	    p->op==MOVA && compat(LONG, regs[r][0])) {
60126440Ssam 		register int r2;
60229775Ssam 
60329775Ssam 		if (regs[r][1]!=0) {	/* send directly to destination */
60426440Ssam 			if (p->op==INC || p->op==DEC) {
60529775Ssam 				p->op = (p->op==DEC) ? SUB : ADD;
60629775Ssam 				/* use 2 now, convert to 3 later */
60729775Ssam 				p->subop=(OP2<<4)+(p->subop&0xF);
60826440Ssam 				p->pop=0;
60929775Ssam 				cp1=lastrand; cp2=regs[RT2];
61029775Ssam 				while (*cp2++= *cp1++)	/* copy reg */
61129775Ssam 					;
61226440Ssam 				cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0;
61326440Ssam 			}
61426440Ssam 			cp1=regs[r]+1; cp2=lastrand;
61529775Ssam 			if (has2ops(p)) {
61629775Ssam 				/* use 3 operand form of instruction */
61726440Ssam 				p->pop=0;
61829775Ssam 				p->subop += (OP3-OP2)<<4;
61929775Ssam 				lastrand = cp2 = regs[RT3];
62026440Ssam 			}
62129775Ssam 			while (*cp2++= *cp1++)
62229775Ssam 				;
62326440Ssam 			if (p->op==MOVA && p->forw->op==PUSH) {
62426440Ssam 				p->op=PUSHA;
62526440Ssam 				*regs[RT2]=0; p->pop=0;
62629775Ssam 			} else if ((p->op==MOV || p->op==CVT) &&
62729775Ssam 			    p->forw->op==PUSH) {
62826440Ssam 				p->op=PUSH; p->subop &= 0xF;
62926440Ssam 				*regs[RT2]=0; p->pop=0;
63026440Ssam 			}
63126440Ssam 			delnode(p->forw);
63229775Ssam 			if (tempreg(lastrand,r2))
63329775Ssam 				uses[r2]=uses[r], uses[r]=0;
63426440Ssam 			redun3(p);
63526440Ssam 			newcode(p); redunm++; flow=r;
63629775Ssam 		} else if (p->op==MOV) {	/* superfluous fetch */
63726440Ssam 			int nmatch;
63826440Ssam 			char src[C2_ASIZE];
63926440Ssam 	movit:
64029775Ssam 			for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;)
64129775Ssam 				;
64226440Ssam 			splitrand(p->forw);
64326440Ssam 			if (p->forw->op != INC && p->forw->op != DEC)
64426440Ssam 				lastrand=byondrd(p->forw);
64526440Ssam 			nmatch=0;
64626440Ssam 			for (preg=regs+RT1;*preg!=lastrand;preg++)
64726440Ssam 				if (r==isreg(*preg)) {
64829775Ssam 					cp2= *preg; cp1=src;
64929775Ssam 					while (*cp2++= *cp1++)
65029775Ssam 						;
65129775Ssam 					++nmatch;
65226440Ssam 				}
65326440Ssam 			if (nmatch==1) {
65429775Ssam 				if (has2ops(p->forw) && equstr(src,regs[RT2])) {
65526440Ssam 					p->forw->pop=0;
65629775Ssam 					p->forw->subop += (OP3-OP2)<<4;
65729775Ssam 					cp1=regs[RT3];
65829775Ssam 					*cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0;
65926440Ssam 				}
66029775Ssam 				delnode(p);
66129775Ssam 				p=p->forw;
66229775Ssam 				if (tempreg(src,r2))
66329775Ssam 					uses[r2]=uses[r], uses[r]=0;
66426440Ssam 				redun3(p);
66533359Sdonn 				newcode(p); redunm++;
66633359Sdonn 				return(p);	/* avoid stale uses[] data */
66729775Ssam 			} else
66829775Ssam 				splitrand(p);
66926440Ssam 		}
67029775Ssam 	} else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) &&
67129775Ssam 	    p->forw->subop&0xf && 	/* if base or index, then forget it */
67229775Ssam 	    compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1]))
67329775Ssam 		goto movit;
67426440Ssam 	}
67526440Ssam 	/* adjust 'lastrand' past any 'read' or 'modify' operands. */
67626440Ssam 	lastrand=byondrd(p);
67726440Ssam 	/* a 'write' clobbers the register. */
67829775Ssam 	if (tempreg(lastrand,r) ||
67929775Ssam 	    (has2ops(p) && tempreg(regs[RT2],r) && uses[r]==0)) {
68029775Ssam 		/*
68129775Ssam 		 * Writing a dead register is useless,
68229775Ssam 		 * but watch side effects
68329775Ssam 		 */
68426440Ssam 		switch (p->op) {
68526440Ssam #ifndef EMOD
68626440Ssam 		case EDIV:
68726440Ssam #endif EMOD
68829775Ssam 		case AOBLEQ: case AOBLSS:
68929775Ssam 			break;
69026440Ssam 		default:
69129775Ssam 			/*
69229775Ssam 			 * If no direct uses, check for
69329775Ssam 			 * use of condition codes
69429775Ssam 			 */
69526440Ssam 			if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) {
69629775Ssam 				register struct node *q = p;
69729775Ssam 
69829775Ssam 				while ((q = nonlab(q->forw))->op==JBR &&
69929775Ssam 				    q->subop==0)
70029775Ssam 					q=q->ref; /* cc unused, unchanged */
70129775Ssam 				if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) {
70229775Ssam 					/* ... and destroyed */
70326440Ssam 					preg=regs+RT1;
70429775Ssam 					while (cp1 = *preg++) {
70529775Ssam 						if (cp1==lastrand &&
70629775Ssam 						    p->op != CLR &&
70729775Ssam 						    p->op != CVFL) {
70829775Ssam 							redunm++;
70929775Ssam 							delnode(p);
71029775Ssam 							return(p->forw);
71129775Ssam 						}
71229775Ssam 						if (equstr(cp1,lastrand))
71329775Ssam 							break;
71426440Ssam 					}
71526440Ssam 				}
71626440Ssam 			}
71726440Ssam 			flow=r;
71826440Ssam 		}
71926440Ssam 	}
72029775Ssam 	if ((r=flow) >= 0) {
72129775Ssam 		olduse=uses[r], uses[r]=0;
72229775Ssam 		*(short *)(regs[r])=0;
72326440Ssam 		/* if r0 destroyed, dont keep r1 */
72429775Ssam 		if (dblflg&1) {
72529775Ssam 			olduse1=uses[++r], uses[r]=0;
72629775Ssam 			*(short *)(regs[r])=0;
72726440Ssam 		}
72826440Ssam 	}
72926440Ssam 	/* now look for 'read' or 'modify' (read & write) uses */
73026440Ssam 	preg=regs+RT1;
73126440Ssam 	while (*(cp1= *preg++)) {
73226440Ssam 		/* check for  r  */
73333301Sdonn 		if (lastrand!=cp1 && tempreg(cp1,r)) {
73433301Sdonn 			int isunused;
73533301Sdonn 			if (isunused=(uses[r]==0)) {
73633301Sdonn 				uses[r]=p;
73733301Sdonn 				cp2=regs[r]; *cp2++=p->subop;
73833301Sdonn 				if ((p->op==SHAL || p->op==SHAR ||
73933301Sdonn 				    p->op==SHL || p->op==SHR) &&
74033301Sdonn 				    cp1==regs[RT1])
74133301Sdonn 					cp2[-1] = BYTE;
74233301Sdonn 				if (p->op==CBR && (p->subop==JBC || p->subop==JBS))
74333301Sdonn 					cp2[-1] = LONG;
74433301Sdonn 				if (p->op==MOVA && cp1==regs[RT2])
74533301Sdonn 					cp2[-1]=LONG;
74633301Sdonn 			}
74726440Ssam 			/* ediv/emod's 2nd operand is quad */
74829775Ssam 			if (((p->op==EDIV
74926440Ssam #ifdef EMOD
75029775Ssam 			   || p->op==EMOD
75126440Ssam #endif EMOD
75229775Ssam 			   ) && cp1==regs[RT2] || (dblflg&2)) &&
75329775Ssam 			   ++r<NUSE && uses[r]==0) {
75433301Sdonn 				if (isunused)
75533301Sdonn 					*cp2=0;
75629775Ssam 				uses[r]=p;
75729775Ssam 				cp2=regs[r]; *cp2++=p->subop;
75833301Sdonn 				if (!isunused)
75933301Sdonn 					*cp2=0;
76026440Ssam 			}
76133301Sdonn 			if (!isunused)
76233301Sdonn 				continue;
76329775Ssam 			if (p->op==MOV || p->op==PUSH || p->op==CVT ||
76429775Ssam 			    p->op==MOVZ || p->op==COM || p->op==NEG ||
76529775Ssam 			    p->op==STF) {
76629775Ssam 				if (p->op!=PUSH) {
76726440Ssam 					cp1=regs[RT2];
76829775Ssam 					if (tempreg(cp1,r)) {
76929775Ssam 						/*
77029775Ssam 						 * reincarnation!!
77129775Ssam 						 * (as in  addl2 r0,r1;
77229775Ssam 						 *  movl r1,r0;  ret)
77329775Ssam 						 */
77429775Ssam 						if (uses[r]==0)
77526440Ssam 							uses[r]=olduse;
77629775Ssam 						if ((dblflg&1) && uses[r+1]==0)
77726440Ssam 							uses[r+1]=olduse1;
77826440Ssam 					}
77929775Ssam 					if (p->op!=MOV)
78029775Ssam 						cp1=0;
78129775Ssam 				} else
78229775Ssam 					cp1="-(sp)";
78329775Ssam 				if (cp1)
78429775Ssam 					while (*cp2++= *cp1++)
78529775Ssam 						;
78629775Ssam 				else
78729775Ssam 					*cp2=0;
78829775Ssam 			} else
78929775Ssam 				*cp2=0;
79026440Ssam 			continue;
79126440Ssam 		}
79226440Ssam 		/* check for (r),[r] */
79329775Ssam 		do {
79429775Ssam 			if (*cp1=='(' || *cp1=='[') { /* get register number */
79529775Ssam 				char t;
79629775Ssam 				for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';)
79729775Ssam 					;
79829775Ssam 				t= *cp1; *cp1=0;
79929775Ssam 				if (tempreg(cp2,r) &&
80029775Ssam 				    (uses[r]==0 || uses[r]==p)) {
80129775Ssam 					uses[r]=p;
80229775Ssam 					regs[r][0] =
80329775Ssam 					    (*--cp2=='[' ? OPX<<4 : OPB<<4);
80434266Sdonn 					regs[r][1] = '\0';
80529775Ssam 				}
80629775Ssam 				*cp1=t;
80726440Ssam 			}
80826440Ssam 		} while (*++cp1);
80926440Ssam 	}
81026440Ssam #ifdef MOVAFASTER
81126440Ssam 	/* pushax or movax possibility? */
81226440Ssam 	cp1=regs[RT1];
81326440Ssam 	if (*cp1++=='$' && isstatic(cp1)) {
81426440Ssam 		if (p->op==MOV && p->subop==LONG) {
81526440Ssam 			if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) {
81626440Ssam 				cp1=p->code; while (*cp1++!=','); p->code= --cp1;
81726440Ssam 			}
81826440Ssam 			p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0;
81926440Ssam 		} else if (p->op==PUSH && p->subop==LONG) {
82026440Ssam 			p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0;
82126440Ssam 		} else if (p->op==ADD && p->subop==U(LONG,OP3)
82226440Ssam 				 && 0<=(r=isreg(regs[RT2]))) {
82326440Ssam 			cp1=cp2=p->code; ++cp1;
82426440Ssam 			do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='[';
82526440Ssam 			do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']';
82626440Ssam 			if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;}
82726440Ssam 			else {p->op = PUSHA; p->subop = BYTE; *cp2=0;}
82826440Ssam 			if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;}
82926440Ssam 			p->pop=0;
83026440Ssam 		}
83126440Ssam 	}
83226440Ssam #endif MOVAFASTER
83329775Ssam 	return (p);
83426440Ssam }
83526440Ssam 
83626440Ssam /* try to eliminate STF's */
83726440Ssam struct node *
flops(q)83826440Ssam flops(q)
83926440Ssam register struct node *q;
84026440Ssam {
84126440Ssam 	register struct node *p;
84226440Ssam 	register int r;
84326440Ssam 
84429775Ssam 	if(q->op!=STF || !tempreg(q->code,r))
84526440Ssam 		return(q);
84626440Ssam 	if(uses[r]) {
84726440Ssam 		/* see if anyone destroys acc between us */
84826440Ssam 		for(p=q->forw; p!=uses[r]; p=p->forw)
84926440Ssam 			switch(p->op) {
85026440Ssam 			case LABEL:
85126440Ssam 			case LDF: case LNF: case CVLF: case LDFD:
85226440Ssam 			case CVDF: case NEGF: case ADDF: case SUBF:
85326440Ssam 			case MULF: case DIVF: case SINF: case COSF:
85426440Ssam 			case ATANF: case LOGF: case SQRTF: case EXPF:
85526440Ssam 				return(q);
85626440Ssam 			}
85734266Sdonn 	again:
85826440Ssam 		if(q->subop == p->subop)
85926440Ssam 			switch(p->op) {	/* do it in the accumulator */
86026440Ssam 			case LDF:	/* redundant load */
86126440Ssam 				delnode(p); nld++;
86226440Ssam 				p = p->forw;
86326440Ssam 				break;
86426440Ssam 			case LNF: /* stf r; lnf r ==> negf */
86526440Ssam 				p->op = NEGF;
86626440Ssam 				p->pop = 0;
86726440Ssam 				p->code = 0;
86826440Ssam 				break;
86926440Ssam 			case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */
87026440Ssam 				{ register char *s;
87126440Ssam 				register struct node *p1=p->forw;
87226440Ssam 				for(s=p->code; *s!=','; s++);
87326440Ssam 				*s = 0;
87426440Ssam 				if(isreg(p->code) == r)
87526440Ssam 					p->code = s+1;
87626440Ssam 				else {
87726440Ssam 					if(p1->op != CBR || isreg(s+1) != r) {
87826440Ssam 						*s = ',';
87926440Ssam 						return(q);
88026440Ssam 					}
88126440Ssam 					if(p1->subop > JNE) {
88226440Ssam 						p1->subop ^= 1;
88326440Ssam 						p1->pop = 0;
88426440Ssam 						nrevbr++;
88526440Ssam 					}
88626440Ssam 				}
88726440Ssam 				p->op = CMPF;
88826440Ssam 				p->pop = 0;
88926440Ssam 				}
89026440Ssam 				break;
89126440Ssam 			default:
89226440Ssam 				return(q);
89326440Ssam 			}
89426440Ssam 		else if(p->subop==LONG) {
89526440Ssam 			switch(p->op) {
89626440Ssam 			case TST:	/* stf r; tstl r ==> tstf */
89726440Ssam 				p->op = TSTF;
89826440Ssam 				p->code = 0;
89926440Ssam 				break;
90026440Ssam 			/* send directly to destination */
90126440Ssam 			case MOV:	/* stf r; movl r,x ==> stf x */
90226440Ssam 			case PUSH:	/* stf r; pushl r ==> stf -(sp)/pushd */
90326440Ssam 				if(q->subop == DOUBLE) {
90426440Ssam 					register struct node *b = p->back;
90526440Ssam 					/* assume b's 2nd arg is ok */
90626440Ssam 					if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG))
90726440Ssam 						return(q);
90826440Ssam 					delnode(b); redunm++;
90926440Ssam 				}
91026440Ssam 				if(p->op==PUSH) {
91126440Ssam 					if(q->subop == DOUBLE) {
91226440Ssam 						p->op = PUSHD;
91326440Ssam 						p->code = 0;
91426440Ssam 					} else {
91526440Ssam 						p->op = q->op;
91626440Ssam 						p->code = copy("-(sp)");
91726440Ssam 					}
91826440Ssam 				} else {
91926440Ssam 					p->op = q->op;
92026440Ssam 					while(*p->code++ != ',');
92126440Ssam 				}
92226440Ssam 				break;
92326440Ssam 			default:
92426440Ssam 				return(q);
92526440Ssam 			}
92626440Ssam 			p->pop = 0;
92726440Ssam 			p->subop = q->subop;
92826440Ssam 		} else
92926440Ssam 			return(q);
93026440Ssam 		uses[r] = 0;
93126440Ssam 		if(q->subop == DOUBLE)
93226440Ssam 			uses[r+1] = 0;
93334266Sdonn 		for(p = p->back; p != q && (!uses[r] || !uses[r+1]); p = p->back) {
93434266Sdonn 			int xr;
93534266Sdonn 
93634266Sdonn 			splitrand(p);
93734266Sdonn 			if((xr=isreg(regs[RT1])) < 0)
93834266Sdonn 				continue;
93934266Sdonn 			if(!uses[r] && xr == r)
94034266Sdonn 				uses[r] = p;
94134266Sdonn 			else if(q->subop == DOUBLE && !uses[r+1] && xr == r+1)
94234266Sdonn 				uses[r+1] = p;
94334266Sdonn 		}
94434266Sdonn 		if(p = uses[r])
94534266Sdonn 			goto again;
94633615Sdonn 		return(q->forw); /* DON'T re-scan code with dated uses[] */
94726440Ssam 	}
94826440Ssam 	/* it's a store to reg which isnt used elsewhere */
94926440Ssam 	if((p=q->forw)->op == CBR) {
95026440Ssam 		q->op = TSTF;
95126440Ssam 		q->pop = 0;
95226440Ssam 		q->code = 0;
95326440Ssam 	} else {
95426440Ssam 		delnode(q); nst++;
95526440Ssam 		if(p->op ==STF || p->op==TSTF || p->op==PUSHD) {
95626440Ssam 			if(useacc == p)
95726440Ssam 				useacc = 0;
95826440Ssam 			return(p->forw);	/* so ldmov can be used on p */
95926440Ssam 		}
96026440Ssam 	}
96126440Ssam 	return(p);
96226440Ssam }
96326440Ssam 
96426440Ssam /* try to change load/store sequences to movl */
ldmov(q)96526440Ssam ldmov(q)
96626440Ssam register struct node *q;
96726440Ssam {
96826440Ssam 	register struct node *p;
96926440Ssam 	register char *s, *pcod, *cp;
97026440Ssam 	char *dlsw();
97126440Ssam 
97226440Ssam 	p = q->back;
97326440Ssam 	if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD)
97426440Ssam 	 && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE))))
97526440Ssam 		return(0);
97626440Ssam 	pcod = p->code;
97726440Ssam  	cp = p->code;
97826440Ssam 	/* prepare args for movl/pushl */
97926440Ssam 	if(q->op!=TSTF && q->subop==DOUBLE) {
98026440Ssam 		if(p->op == LDF) {
98126440Ssam 			if((s = dlsw(p->code)) == NULL)
98226440Ssam 				return(0);
98329670Ssam 
98426440Ssam 			strcpy(line, s);
98526440Ssam 			if(q->op == STF) {
98626440Ssam 				strcat(line, ",");
98726440Ssam 				if((s = dlsw(q->code)) == NULL)
98826440Ssam 					return(0);
98926440Ssam 				strcat(line, s);
99026440Ssam 				p->op = MOV;
99126440Ssam 			} else
99226440Ssam 				p->op = PUSH;
99326440Ssam 		} else { /* LDFD */
99426440Ssam 			if(q->op == STF) {
99526440Ssam 				if((s = dlsw(q->code)) == NULL)
99626440Ssam 					return(0);
99726440Ssam 			} else
99826440Ssam 				s = "-(sp)";
99926440Ssam 			strcpy(line, s);
100026440Ssam 			p->op = CLR;
100126440Ssam 		}
100226440Ssam 		p->pop = 0;
100326440Ssam 		p->subop = LONG;
100426440Ssam 		p->code = copy(line);
100526440Ssam 	} else
100626440Ssam 		{
100726440Ssam  		if ((p->op == LDF) && (p->subop == DOUBLE) &&
100826440Ssam  	           (indexa(cp)))  return(0);
100926440Ssam 		delnode(p);
101026440Ssam 		}
101126440Ssam 	strcpy(line, pcod);
101226440Ssam 	if(q->op == STF) {	/* ldf x; stf y ==> movl x,y */
101326440Ssam 		strcat(line, ",");
101426440Ssam 		strcat(line, q->code);
101526440Ssam 		q->op = MOV;
101626440Ssam 		nst++;
101726440Ssam 	} else if(q->op == TSTF)	/* ldf x; tstf ==> tstl x */
101826440Ssam 		q->op = TST;
101926440Ssam 	else	/* ldd x; pushd ==> pushl x+4; pushl x */
102026440Ssam 		q->op = PUSH;
102126440Ssam 	q->pop = 0;
102226440Ssam 	q->subop = LONG;
102326440Ssam 	q->code = copy(line);
102426440Ssam 	nld++;
102526440Ssam 	return(1);
102626440Ssam }
102726440Ssam 
102826440Ssam /* reconstruct the address of l.s.w. of a double operand */
102926440Ssam char *
dlsw(d)103026440Ssam dlsw(d)
103126440Ssam 	register char *d;
103226440Ssam {
103329670Ssam 	register char *s, *t, *c;
103426440Ssam 	register int r;
103526440Ssam 	static char lsw[C2_ASIZE];
103626440Ssam 
103726440Ssam 	if(d[0] == '*' || d[0] == '$')
103826440Ssam 		return(NULL);
103929670Ssam 	if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2]))
104029670Ssam 		return(NULL);
104126440Ssam 	t = lsw;
104226440Ssam 	if((r=isreg(d)) >= 0)
104326440Ssam 		sprintf(t, "r%d", r+1);
104426440Ssam 	else {
104526440Ssam 		for(s=d; *s && *s!='('; *t++ = *s++)
104626440Ssam 			if(*s == '[')
104726440Ssam 				return(NULL);
104829670Ssam 		if(s!=d)
104929670Ssam 			*t++ = '+';
105029670Ssam 		*t++ = '4';
105126440Ssam 		while(*t++ = *s)
105229670Ssam 			if(*s++ == '[' )
105329670Ssam 			{
105426440Ssam 				return(NULL);
105529670Ssam 			}
105626440Ssam 	}
105726440Ssam 	return(lsw);
105826440Ssam }
checkexpr(p)105929670Ssam checkexpr(p)
106029670Ssam register char *p;
106129670Ssam {
106229670Ssam 
106329670Ssam 	while(*p && *p != ','){
106429670Ssam 	if ((*p == '+' ) || (*p == '-'))
106529670Ssam 		return(1);
106629670Ssam 	*p++;
106729670Ssam 	}
106829670Ssam 	return(0);
106929670Ssam }
1070