xref: /csrg-svn/old/pcc/c2.tahoe/c22.c (revision 34265)
126441Ssam #ifndef lint
2*34265Sdonn static char sccsid[] = "@(#)c22.c	1.9 (Berkeley/CCI) 05/12/88";
326441Ssam #endif
426441Ssam 
526441Ssam /*
626441Ssam  * C object code improver-- third part
726441Ssam  */
826441Ssam 
926441Ssam #include "c2.h"
1026441Ssam #include <stdio.h>
1126441Ssam #include <ctype.h>
1226441Ssam 
rmove()1326441Ssam rmove()
1426441Ssam {
1526441Ssam 	register struct node *p;
1626441Ssam 	register int r, r1;
1726441Ssam 
1826441Ssam 	clearreg();
1926441Ssam 	for (p=first.forw; p!=0; p = p->forw) {
2026441Ssam 	if (debug) {
2126441Ssam 		printf("Regs: ");
2226441Ssam 		for (r=0; r<=NREG; r++)
2326441Ssam 			if (regs[r][0]) {
2426441Ssam 				r1=regs[r][0];
2526441Ssam 				printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1);
2626441Ssam 			}
2726441Ssam 		printf("-\n");
2826441Ssam 	}
2926441Ssam 	switch (p->op) {
3026441Ssam 
3126441Ssam 	case CVT:
3226441Ssam 	case MOVZ:
3326441Ssam 		splitrand(p);
3426441Ssam 		repladdr(p);
3526441Ssam 		r = isreg(regs[RT1]);
3626441Ssam 		r1 = isreg(regs[RT2]);
3733350Sdonn 		dest(regs[RT2],p->subop, p->op!=CVT || r<0);
3826441Ssam 		if (r>=0 && r1>=0) {
3926441Ssam 			p->op = MOV; p->subop = LONG;
4026441Ssam 			p->pop = 0;
4126441Ssam 			nchange++;
4226441Ssam 			goto case_mov;
4326441Ssam 		}
4426441Ssam 		if(p->op == CVT) {
4526441Ssam 			if (r1>=0) savereg(r1, regs[RT1], p->subop);
4626441Ssam 		} else
4726441Ssam 			ccloc[0] = 0;
4826441Ssam 		break;
4926441Ssam 
5026441Ssam 	case MOV:
5126441Ssam 	case_mov:
5226441Ssam 		splitrand(p);
5326441Ssam 		if ((r = findrand(regs[RT1],p->subop)) >= 0) {
5426441Ssam 			if (r == isreg(regs[RT2]))
5526441Ssam 				if(p->forw->op!=CBR) {
5626441Ssam 					delnode(p); redunm++; nchange++; break;
5726441Ssam 				} else {
5826441Ssam 					p->op=TST; p->pop=0;
5926441Ssam 					while(*p->code++ != ',');
6026441Ssam 					redunm++; nchange++;
6126441Ssam 					goto case_tst;
6226441Ssam 				}
6326441Ssam 		}
6426441Ssam 		repladdr(p);
6526441Ssam 		r = isreg(regs[RT1]);
6626441Ssam 		r1 = isreg(regs[RT2]);
6726441Ssam 		dest(regs[RT2],p->subop, 1);
6829775Ssam 		if ((regs[ACC][0]) && equstr(regs[RT2],regs[ACC]+1))
6929775Ssam 			*(short *)(regs[ACC]) = 0;
7026441Ssam 		if (r>=0) {
7126441Ssam 			if (r1>=0) {
7226441Ssam 				if (r == r1 && p->forw->op!=CBR) {
7329775Ssam 					delnode(p); redunm++; nchange++;
7429775Ssam 					break;
7526441Ssam 				}
7626441Ssam 				if(regs[r][0])
7726441Ssam 					savereg(r1, regs[r]+1, p->subop);
7829775Ssam 			} else
7929775Ssam 				savereg(r, regs[RT2], p->subop);
8029775Ssam 		} else if (r1>=0)
8129775Ssam 			savereg(r1, regs[RT1], p->subop);
8229775Ssam 		else
8329775Ssam 			setcon(regs[RT1], regs[RT2], p->subop);
8426441Ssam 		break;
8526441Ssam 
8626441Ssam /* .rx,.wx or .rx,.rx,.wx */
8726441Ssam 	case ADD:
8826441Ssam 	case SUB:
8926441Ssam 	case AND:
9026441Ssam 	case OR:
9126441Ssam 	case XOR:
9226441Ssam 	case MUL:
9326441Ssam 	case DIV:
9426441Ssam #ifdef EMOD
9526441Ssam 	case EDIV:
9626441Ssam 	case EMOD:
9726441Ssam #endif EMOD
9826441Ssam 	case SHAL:
9926441Ssam 	case SHAR:
10026441Ssam 	case SHL:
10126441Ssam 	case SHR:
10226441Ssam 	case ADDA:
10326441Ssam 	case SUBA:
10426441Ssam /* .rx,.wx */
10526441Ssam 	case MFPR:
10626441Ssam 	case COM:
10726441Ssam 	case NEG:
10826441Ssam 		splitrand(p);
10926441Ssam 		repladdr(p);
11026441Ssam 		dest(lastrand,p->subop, p->op!=ADDA && p->op!=SUBA);
11126441Ssam 		break;
11226441Ssam 
11326441Ssam /* .mx or .wx */
11426441Ssam 	case STF:
11526441Ssam 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
11626441Ssam 			delnode(p);
11726441Ssam 			nst++; nchange++; break;
11826441Ssam 		}
11926441Ssam 		savereg(ACC, p->code, p->subop);
12026441Ssam 	case INC:
12126441Ssam 	case DEC:
12226441Ssam 	case CVFL:
12326441Ssam 		dest(p->code,p->subop, 1);
12426441Ssam 		break;
12526441Ssam 
12629775Ssam 	case CLR:
12729775Ssam 		dest(p->code,p->subop, 1);
12829775Ssam 		if ((regs[ACC][0]) && equstr(p->code,regs[ACC]+1))
12929775Ssam 			*(short *)(regs[ACC]) = 0;
13029775Ssam 		if ((r = isreg(p->code)) < 0)
13129775Ssam 			setcon("$0", p->code, p->subop);
13229775Ssam 		else
13329775Ssam 			savereg(r, "$0", p->subop);
13429775Ssam 		break;
13529775Ssam 
13626441Ssam /* .rx */
13726441Ssam 	case LDF:
13826441Ssam 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
13926441Ssam 			delnode(p);
14026441Ssam 			nld++; nchange++; break;
14126441Ssam 		}
14226441Ssam 		savereg(ACC, p->code, p->subop);
14326441Ssam 		goto case_tst;
14426441Ssam 	case LNF:
14526441Ssam 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
14626441Ssam 			p->op = NEGF; p->pop = 0; p->code = 0;
14726441Ssam 			regs[ACC][0] = 0;
14826441Ssam 			break;
14926441Ssam 		}
15026441Ssam 	case CVLF:
15126441Ssam 	case LDFD:
15226441Ssam 	case ADDF:
15326441Ssam 	case SUBF:
15426441Ssam 	case MULF:
15526441Ssam 	case DIVF:
15626441Ssam 		regs[ACC][0] = 0;
15726441Ssam 	case TST:
15826441Ssam 	case_tst:
15926441Ssam 	case PUSH:
16026441Ssam 		splitrand(p);
16126441Ssam 		lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */
16226441Ssam 		repladdr(p);
16326441Ssam 		lastrand=regs[RT1];
16426441Ssam 		if (p->op==TST && equstr(lastrand, ccloc+1)
16526441Ssam 		  && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop))) {
16626441Ssam 			delnode(p); nrtst++; nchange++; break;
16726441Ssam 		}
16826441Ssam 		if (p->op==PUSH && p->subop!=LONG &&
16926441Ssam 		 (isreg(lastrand)>=0 || *lastrand=='$')) {
17026441Ssam 			p->subop = LONG;
17126441Ssam 			p->pop = 0;
17226441Ssam 			nchange++;
17326441Ssam 		}
17426441Ssam 		if (p->op==TST || p->op==PUSH)
17526441Ssam 			setcc(lastrand,p->subop);
17626441Ssam 		break;
17726441Ssam 
17826441Ssam /* .rx,.rx,.rx */
17926441Ssam 	case PROBE:
18026441Ssam 	case CASE:
18126441Ssam /* .rx,.rx */
18226441Ssam 	case MTPR:
18326441Ssam 	case CALLS:
18426441Ssam 	case CALLF:
18526441Ssam 	case CMP:
18626441Ssam 	case BIT:
18726441Ssam 	case CMPF:
18826441Ssam 	case CMPF2:
18926441Ssam 		splitrand(p);
19026441Ssam 		/* fool repladdr into doing right number of operands */
19126441Ssam 		lastrand=byondrd(p);
19226441Ssam 		if (p->op==CALLF || p->op==CALLS) clearreg();
19326441Ssam 		else repladdr(p);
19426441Ssam 	case TSTF:
19526441Ssam 		ccloc[0]=0;
19626441Ssam 	case PUSHD:
19726441Ssam 		break;
19826441Ssam 
19926441Ssam /* acc only */
20026441Ssam 	case CVDF:
20126441Ssam 	case NEGF:
20226441Ssam 	case SINF:
20326441Ssam 	case COSF:
20426441Ssam 	case ATANF:
20526441Ssam 	case LOGF:
20626441Ssam 	case SQRTF:
20726441Ssam 	case EXPF:
20826441Ssam 		regs[ACC][0] = 0;
20926441Ssam 		break;
21026441Ssam 
21126441Ssam #ifndef EMOD
21226441Ssam /* .rx,.rx,.wx,.wx */
21326441Ssam 	case EDIV:
21426441Ssam 		splitrand(p);
21526441Ssam 		lastrand = regs[RT3];
21626441Ssam 		repladdr(p);
21726441Ssam 		dest(regs[RT3], p->subop, 1);
21826441Ssam 		dest(regs[RT4], p->subop, 0);
21926441Ssam 		break;
22026441Ssam #endif EMOD
22126441Ssam 
22226441Ssam /* .rx,.rx,.rx,wx */
22326441Ssam 	case EMUL:
22426441Ssam 		splitrand(p);
22526441Ssam 		lastrand = regs[RT4];
22626441Ssam 		repladdr(p);
22726441Ssam 		dest(regs[RT4],QUAD, 1); /* fourth operand is a quad */
22826441Ssam 		break;
22926441Ssam 	case CBR:
23026441Ssam 		if (p->subop>=JBC) {
23126441Ssam 			splitrand(p);
23226441Ssam 			lastrand=regs[RT3]; /* 2 operands can be optimized */
23326441Ssam 			repladdr(p);
23426441Ssam 			ccloc[0] = 0;
23526441Ssam 		} else
23626441Ssam 			reduncbr(p);
23726441Ssam 		break;
23826441Ssam 
23926441Ssam 	case JBR:
24026441Ssam 		redunbr(p);
24126441Ssam 
24226441Ssam 	default:
24326441Ssam 		clearreg();
24426441Ssam 	}
24526441Ssam 	}
24626441Ssam }
24726441Ssam 
jumpsw()24826441Ssam jumpsw()
24926441Ssam {
25026441Ssam 	register struct node *p, *p1, *pt;
25126441Ssam 	register int t, nj;
25226441Ssam 
25326441Ssam 	t = 0;
25426441Ssam 	nj = 0;
25526441Ssam 	for (p=first.forw; p!=0; p = p->forw)
25626441Ssam 		p->seq = ++t;
25726441Ssam 	for (p=first.forw; p!=0; p = p1) {
25826441Ssam 		p1 = p->forw;
25926441Ssam 		if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
26026441Ssam 		 && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) {
26126441Ssam 			if (p->ref==p1->ref)
26226441Ssam 				continue;
26326441Ssam 			p->subop = revbr[p->subop];
26426441Ssam 			p->pop=0;
26526441Ssam 			pt = p1->ref;
26626441Ssam 			p1->ref = p->ref;
26726441Ssam 			p->ref = pt;
26826441Ssam 			t = p1->labno;
26926441Ssam 			p1->labno = p->labno;
27026441Ssam 			p->labno = t;
27126441Ssam #ifdef COPYCODE
27226441Ssam 			if (p->labno == 0) {
27326441Ssam 				pt = (struct node *)p1->code; p1->code = p->code; p->code = (char *)pt;
27426441Ssam 			}
27526441Ssam #endif
27626441Ssam 			nrevbr++;
27726441Ssam 			nj++;
27826441Ssam 		}
27926441Ssam 	}
28026441Ssam 	return(nj);
28126441Ssam }
28226441Ssam 
addaob()28326441Ssam addaob()
28426441Ssam {
28526441Ssam 	register struct node *p, *p1, *p2, *p3;
28626441Ssam 
28726441Ssam 	for (p = &first; (p1 = p->forw)!=0; p = p1) {
28826441Ssam 	if (p->op==INC && p->subop==LONG) {
28926441Ssam 		if (p1->op==LABEL && p1->refc==1 && p1->forw->op==CMP && p1->forw->subop==LONG
29026441Ssam 		  && (p2=p1->forw->forw)->op==CBR && p2->subop==JLE
29126441Ssam 		  && (p3=p2->ref->back)->op==JBR && p3->subop==0 && p3->ref==p1
29226441Ssam 		  && p3->forw->op==LABEL && p3->forw==p2->ref) {
29326441Ssam 			/* change	INC LAB: CMP	to	LAB: INC CMP */
29426441Ssam 			p->back->forw=p1; p1->back=p->back;
29526441Ssam 			p->forw=p1->forw; p1->forw->back=p;
29626441Ssam 			p->back=p1; p1->forw=p;
29726441Ssam 			p1=p->forw;
29826441Ssam 			/* adjust beginning value by 1 */
29926441Ssam 			p2=alloc(sizeof first); p2->op = DEC; p2->subop = LONG;
30026441Ssam 			p2->pop=0;
30126441Ssam 			p2->forw=p3; p2->back=p3->back; p3->back->forw=p2;
30226441Ssam 			p3->back=p2; p2->code=p->code; p2->labno=0;
30326441Ssam 		}
30426441Ssam 		if (p1->op==CMP && p1->subop==LONG &&
30526441Ssam 		  (p2=p1->forw)->op==CBR && p2->forw->op!=CBR) {
30626441Ssam 			register char *cp1,*cp2;
30726441Ssam 			splitrand(p1); if (!equstr(p->code,regs[RT1])) continue;
30829670Ssam 			if ((p2->subop==JLE || p2->subop==JLT) &&
30929670Ssam 			    checkaobdisp(p2)){
31026441Ssam 				if (p2->subop==JLE) p->op = AOBLEQ; else p->op = AOBLSS; p->subop = 0;
31126441Ssam 				cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */
31226441Ssam 				cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */
31326441Ssam 				p->pop=0; newcode(p);
31426441Ssam 				p->labno = p2->labno; delnode(p2); delnode(p1); naob++;
31526441Ssam 			}
31626441Ssam 		}
31726441Ssam 	}
31826441Ssam 	}
31926441Ssam }
32026441Ssam 
ispow2(n)32126441Ssam ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */
32226441Ssam 	register int log;
32326441Ssam 	if (n==0 || n&(n-1)) return(-1); log=0;
32426441Ssam 	for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}
32526441Ssam }
32626441Ssam 
equop(p1,p2)32726441Ssam equop(p1, p2)
32826441Ssam register struct node *p1, *p2;
32926441Ssam {
33026441Ssam 	register char *cp1, *cp2;
33126441Ssam 
33226441Ssam 	if (p1->op != p2->op || p1->subop != p2->subop)
33326441Ssam 		return(0);
33433300Sdonn 	if (p1->op == NIL && p1->subop == 0 && p1->pop != p2->pop)
33533300Sdonn 		return(0);
33629775Ssam 	if (p1->op != NIL && ord(p1->op) < ord(MOV))
33726441Ssam 		return(0);
33833300Sdonn 	switch (p1->op) {
33933300Sdonn 	case EROU:	case JSW:	case TEXT:	case DATA:
34033300Sdonn 	case BSS:	case ALIGN:	case WGEN:	case END:
34133300Sdonn 		/* sufficient? */
34233300Sdonn 		return(0);
34333300Sdonn 	}
34426441Ssam 	if (p1->op==MOVA && p1->labno!=p2->labno) return(0);
34526441Ssam 	cp1 = p1->code;
34626441Ssam 	cp2 = p2->code;
34726441Ssam 	if (cp1==0 && cp2==0)
34826441Ssam 		return(1);
34926441Ssam 	if (cp1==0 || cp2==0)
35026441Ssam 		return(0);
35126441Ssam 	while (*cp1 == *cp2++)
35226441Ssam 		if (*cp1++ == 0)
35326441Ssam 			return(1);
35426441Ssam 	return(0);
35526441Ssam }
35626441Ssam 
delnode(p)35726441Ssam delnode(p) register struct node *p; {
35826441Ssam 	p->back->forw = p->forw;
35926441Ssam 	p->forw->back = p->back;
36026441Ssam }
36126441Ssam 
decref(p)36226441Ssam decref(p)
36326441Ssam register struct node *p;
36426441Ssam {
36526441Ssam 	if (p && --p->refc <= 0) {
36626441Ssam 		nrlab++; nchange++;
36726441Ssam 		delnode(p);
36826441Ssam 	}
36926441Ssam }
37026441Ssam 
37126441Ssam struct node *
nonlab(ap)37226441Ssam nonlab(ap)
37326441Ssam struct node *ap;
37426441Ssam {
37526441Ssam 	register struct node *p;
37626441Ssam 
37726441Ssam 	p = ap;
37826441Ssam 	while (p && p->op==LABEL)
37926441Ssam 		p = p->forw;
38026441Ssam 	return(p);
38126441Ssam }
38226441Ssam 
clearuse()38326441Ssam clearuse() {
38426441Ssam 	register struct node **i;
38529670Ssam 	for (i=uses+NREG; i>uses;) *--i=0;
38626441Ssam 	useacc = 0;
38726441Ssam }
38826441Ssam 
clearreg()38926441Ssam clearreg() {
39026441Ssam 	register char **i;
39126441Ssam 	for (i=regs+NREG+1; i>regs;){ **--i=0; **i=0; }
39226441Ssam 	conloc[0] = 0; ccloc[0] = 0;
39326441Ssam }
39426441Ssam 
savereg(ai,s,type)39526441Ssam savereg(ai, s, type)
39626441Ssam register char *s;
39726441Ssam {
39826441Ssam 	register char *p, *sp;
39926441Ssam 
40026441Ssam 	sp = p = regs[ai];
40126441Ssam 	/* if any indexing, must be parameter or local */
40226441Ssam 	/* indirection (as in "*-4(fp)") is ok, however */
40326441Ssam 	*p++ = type;
40426441Ssam 	if (*s=='*' || *s=='$')
40526441Ssam 		*p++ = *s++;
40626441Ssam 	if (natural(s))
40726441Ssam 		strcpy(p, s);
40826441Ssam 	else {*sp = 0; return;}
40926441Ssam }
41026441Ssam 
dest(s,type,ccflg)41126441Ssam dest(s,type, ccflg)
41226441Ssam register char *s;
41326441Ssam {
41426441Ssam 	register int i;
41526441Ssam 
41626441Ssam 	if ((i = isreg(s)) >= 0) {
41726441Ssam 		*(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */
41826441Ssam 		if (DOUBLE==(type&0xF) || DOUBLE==((type>>4)&0xF) || type==QUAD)
41926441Ssam 			*(short *)(regs[i+1]) = 0;
42026441Ssam 	}
42126441Ssam 	for (i=NREG; --i>=0;)
42226441Ssam 		if (regs[i][1]=='*' && equstr(s, regs[i]+2))
42326441Ssam 			*(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */
42426441Ssam 	while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */
42526441Ssam 		*(short *)(regs[i]) = 0;
42626441Ssam 
42726441Ssam 	if (!natural(s)) {/* wild store, everything except constants vanishes */
42826441Ssam 		for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0;
42926441Ssam 		conloc[0] = 0; ccloc[0] = 0;
43026441Ssam 	} else {
43126441Ssam 		if(ccflg)setcc(s,type); /* natural destinations set condition codes */
43226441Ssam 		if (equstr(s, conloc))
43326441Ssam 			conloc[0] = 0;
43426441Ssam 	}
43526441Ssam }
43626441Ssam 
43726441Ssam splitrand(p) struct node *p; {
43826441Ssam /* separate operands at commas, set up 'regs' and 'lastrand' */
43926441Ssam register char *p1, *p2; register char **preg;
44026441Ssam 
44126441Ssam 	preg=regs+RT1;
44226441Ssam 	if (p1=p->code) while (*p1) {
44326441Ssam 		lastrand=p2= *preg++;
44426441Ssam 		while (*p1) if (','==(*p2++= *p1++)) {--p2; break;}
44526441Ssam 		*p2=0;
44626441Ssam 	}
44726441Ssam 	while (preg<(regs+RT1+5)) *(*preg++)=0;
44826441Ssam }
44926441Ssam 
compat(have,want)45026441Ssam compat(have, want)
45126441Ssam register int have, want;
45226441Ssam {
45326441Ssam 	register int hsrc, hdst;
45426441Ssam 	extern int bitsize[];
45526441Ssam 
45626441Ssam 	if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */
45726441Ssam 	hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc;
45826441Ssam 	if (want>=QUAD)
45926441Ssam 		return(bitsize[hdst]==bitsize[want] && bitsize[hsrc]==bitsize[want]);
46026441Ssam 	return(hsrc==want && hdst>=want && hdst<QUAD);
46126441Ssam }
46226441Ssam 
equtype(t1,t2)46326441Ssam equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}
46426441Ssam 
findrand(as,type)46526441Ssam findrand(as, type)
46626441Ssam char *as;
46726441Ssam {
46826441Ssam 	register char **i;
46926441Ssam 	for (i = regs+NREG; --i>=regs;) {
47026441Ssam 		if (**i && equstr(*i+1, as) && compat(**i,type))
47126441Ssam 			return(i-regs);
47226441Ssam 	}
47326441Ssam 	return(-1);
47426441Ssam }
47526441Ssam 
isreg(s)47626441Ssam isreg(s)
47726441Ssam register char *s;
47826441Ssam {
47926441Ssam 	if (*s++!='r' || !isdigit(*s++)) return(-1);
48026441Ssam 	if (*s==0) return(*--s-'0');
48126441Ssam 	if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0');
48226441Ssam 	return(-1);
48326441Ssam }
48426441Ssam 
48526441Ssam /*
48626441Ssam check()
48726441Ssam {
48826441Ssam 	register struct node *p, *lp;
48926441Ssam 
49026441Ssam 	lp = &first;
49126441Ssam 	for (p=first.forw; p!=0; p = p->forw) {
49226441Ssam 		if (p->back != lp)
49326441Ssam 			abort(-1);
49426441Ssam 		lp = p;
49526441Ssam 	}
49626441Ssam }
49726441Ssam */
49826441Ssam 
49926441Ssam newcode(p) struct node *p; {
50026441Ssam 	register char *p1,*p2,**preg;
50126441Ssam 
50226441Ssam 	preg=regs+RT1; p2=line;
50326441Ssam 	while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';}
50426441Ssam 	*--p2=0;
50526441Ssam 	p->code=copy(line);
50626441Ssam }
50726441Ssam 
50826441Ssam repladdr(p)
50926441Ssam struct node *p;
51026441Ssam {
51126441Ssam 	register int r;
51226441Ssam 	register char *p1;
51326441Ssam 	register char **preg;
51426441Ssam 	register int nrepl;
51526441Ssam 
51626441Ssam 	preg=regs+RT1; nrepl=0;
51726441Ssam 	while (lastrand!=(p1= *preg++))
51826441Ssam 		if (0<=(r=findrand(p1,p->subop))) {
51926441Ssam 			*p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0;
52026441Ssam 			nchange++; nrepl++; nsaddr++;
52126441Ssam 		}
52226441Ssam 	if (nrepl) newcode(p);
52326441Ssam }
52426441Ssam 
52526441Ssam /* conditional branches which are never/always taken */
reduncbr(p)52626441Ssam reduncbr(p)
52726441Ssam register struct node *p;
52826441Ssam {
52926441Ssam 	register struct node *p1;
53026441Ssam 	register char *ap1, *ap2;
53126441Ssam 
53226441Ssam 	p1 = p->back;
53326441Ssam 	if (p1->op==CMP) {
53426441Ssam 		splitrand(p1);
53526441Ssam 		ap1 = findcon(regs[RT1], p1->subop);
53626441Ssam 		ap2 = findcon(regs[RT2], p1->subop);
53726441Ssam 	} else {
53826441Ssam 		if(!ccloc[0])
53926441Ssam 			return;
54026441Ssam 		ap1 = findcon(ccloc+1, ccloc[0]);
54126441Ssam 		ap2 = "$0";
54226441Ssam 	}
54326441Ssam 	switch (compare(p->subop, ap1, ap2)) {
54426441Ssam 	case 0:		/* branch never taken */
54526441Ssam 		delnode(p);
54626441Ssam 		nredunj++;
54726441Ssam 		nchange++;
54826441Ssam 		decref(p->ref);
54926441Ssam 		if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) {
55026441Ssam 			delnode(p1);
55126441Ssam 			nrtst++;
55226441Ssam 		}
55326441Ssam 		break;
55426441Ssam 	case 1:		/* branch always taken */
55526441Ssam 		p->op = JBR;
55626441Ssam 		p->subop = 0;
55726441Ssam 		p->pop = 0;
55826441Ssam 		nchange++;
55926441Ssam 		if(nonlab(p->ref)->op!=CBR && (p1->op==TST || p1->op==CMP)) {
56026441Ssam 			delnode(p1);
56126441Ssam 			nrtst++;
56226441Ssam 		}
56326441Ssam 	}
56426441Ssam }
56526441Ssam 
56626441Ssam /* a jump to a redundant compare (start of a 'for') */
redunbr(p)56726441Ssam redunbr(p)
56826441Ssam register struct node *p;
56926441Ssam {
57026441Ssam 	register struct node *p1;
57126441Ssam 	register char *ap1, *ap2;
57226441Ssam 
57326441Ssam 	if ((p1 = p->ref) == 0)
57426441Ssam 		return;
57526441Ssam 	p1 = nonlab(p1);
57626441Ssam 	if (p1->op==TST || p1->op==CMP)
57726441Ssam 		splitrand(p1);
57826441Ssam 	else
57926441Ssam 		return;
58026441Ssam 	if (p1->forw->op==CBR) {
58126441Ssam 		ap1 = findcon(regs[RT1], p1->subop);
58226441Ssam 		if (p1->op==TST)
58326441Ssam 			ap2 = "$0";
58426441Ssam 		else
58526441Ssam 			ap2 = findcon(regs[RT2], p1->subop);
58626441Ssam 		p1 = p1->forw;
58726441Ssam 		if (compare(p1->subop, ap1, ap2) > 0) {
58826441Ssam 			nredunj++;
58926441Ssam 			nchange++;
59026441Ssam 			decref(p->ref);
59126441Ssam 			p->ref = p1->ref;
59226441Ssam 			p->labno = p1->labno;
59326441Ssam #ifdef COPYCODE
59426441Ssam 			if (p->labno == 0)
59526441Ssam 				p->code = p1->code;
59626441Ssam 			if (p->ref)
59726441Ssam #endif
59826441Ssam 				p->ref->refc++;
59926441Ssam 		}
60026441Ssam 	} else if (p1->op==TST && equstr(regs[RT1],ccloc+1) &&
60126441Ssam 			equtype(ccloc[0],p1->subop)) {
60226441Ssam 		p1=insertl(p1->forw); decref(p->ref); p->ref=p1;
603*34265Sdonn 		p->labno=p1->labno;
60426441Ssam 		nrtst++; nchange++;
60526441Ssam 	}
60626441Ssam }
60726441Ssam 
60826441Ssam char *
findcon(p,type)60926441Ssam findcon(p, type)
61026441Ssam 	register char *p;
61126441Ssam {
61226441Ssam 	register int r;
61326441Ssam 
61426441Ssam 	if (*p=='$')
61526441Ssam 		return(p);
61626441Ssam 	if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
61726441Ssam 		return(regs[r]+1);
61829731Ssam 	if (equstr(p, conloc) && equtype(conloc[0], type))
61926441Ssam 		return(conval+1);
62026441Ssam 	return(p);
62126441Ssam }
62226441Ssam 
62326441Ssam /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
compare(op,acp1,acp2)62426441Ssam compare(op, acp1, acp2)
62526441Ssam char *acp1, *acp2;
62626441Ssam {
62726441Ssam 	register char *cp1, *cp2;
62826441Ssam 	register int n1, n2, sign;
62926441Ssam 
63026441Ssam 	cp1 = acp1;
63126441Ssam 	cp2 = acp2;
63226441Ssam 	if (*cp1++ != '$' || *cp2++ != '$')
63326441Ssam 		return(-1);
63426441Ssam 	n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
63526441Ssam 	while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';}
63626441Ssam 	n1 *= sign;
63726441Ssam 	n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
63826441Ssam 	while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';}
63926441Ssam 	n2 *= sign;
64026441Ssam 	if (*cp1=='+')
64126441Ssam 		cp1++;
64226441Ssam 	if (*cp2=='+')
64326441Ssam 		cp2++;
64426441Ssam 	do {
64526441Ssam 		if (*cp1++ != *cp2)
64626441Ssam 			return(-1);
64726441Ssam 	} while (*cp2++);
64826441Ssam 	switch(op) {
64926441Ssam 
65026441Ssam 	case JEQ:
65126441Ssam 		return(n1 == n2);
65226441Ssam 	case JNE:
65326441Ssam 		return(n1 != n2);
65426441Ssam 	case JLE:
65526441Ssam 		return(n1 <= n2);
65626441Ssam 	case JGE:
65726441Ssam 		return(n1 >= n2);
65826441Ssam 	case JLT:
65926441Ssam 		return(n1 < n2);
66026441Ssam 	case JGT:
66126441Ssam 		return(n1 > n2);
66226441Ssam 	case JLO:
66326441Ssam 		return((unsigned)n1 < (unsigned)n2);
66426441Ssam 	case JHI:
66526441Ssam 		return((unsigned)n1 > (unsigned)n2);
66626441Ssam 	case JLOS:
66726441Ssam 		return((unsigned)n1 <= (unsigned)n2);
66826441Ssam 	case JHIS:
66926441Ssam 		return((unsigned)n1 >= (unsigned)n2);
67026441Ssam 	}
67126441Ssam 	return(-1);
67226441Ssam }
67326441Ssam 
setcon(cv,cl,type)67426441Ssam setcon(cv, cl, type)
67526441Ssam register char *cv, *cl;
67626441Ssam {
67726441Ssam 	register char *p;
67826441Ssam 
67926441Ssam 	if (*cv != '$')
68026441Ssam 		return;
68126441Ssam 	if (!natural(cl))
68226441Ssam 		return;
68326441Ssam 	p = conloc;
68426441Ssam 	while (*p++ = *cl++);
68526441Ssam 	p = conval;
68626441Ssam 	*p++ = type;
68726441Ssam 	while (*p++ = *cv++);
68826441Ssam }
68926441Ssam 
setcc(ap,type)69026441Ssam setcc(ap,type)
69126441Ssam char *ap;
69226441Ssam {
69326441Ssam 	register char *p, *p1;
69426441Ssam 
69526441Ssam 	p = ap;
69626441Ssam 	if (!natural(p)) {
69726441Ssam 		ccloc[0] = 0;
69826441Ssam 		return;
69926441Ssam 	}
70026441Ssam 	p1 = ccloc;
70126441Ssam 	*p1++ = type;
70226441Ssam 	while (*p1++ = *p++);
70326441Ssam }
70426441Ssam 
indexa(p)70526441Ssam indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
70626441Ssam 	while (*p) if (*p++=='[') return(1);
70726441Ssam 	return(0);
70826441Ssam }
70926441Ssam 
natural(p)71026441Ssam natural(p)
71126441Ssam register char *p;
71226441Ssam {/* 1->simple local, parameter, global, or register; 0->otherwise */
71326441Ssam 
71426441Ssam 	if (*p=='*' || *p=='(' || *p=='$')
71526441Ssam 		return(0);
71626441Ssam 	while (*p++);
71726441Ssam 	p--;
71826441Ssam 	if (*--p==']' || *p==')' &&
71926441Ssam 	 !(*(p-2)=='f' || fortflg && (*--p=='1' || *p=='2') && *--p=='1'))
72026441Ssam 		return(0);
72126441Ssam 	return(1);
72226441Ssam }
72326441Ssam 
72426441Ssam /*
72526441Ssam ** Tell if an argument is most likely static.
72626441Ssam */
72726441Ssam 
isstatic(cp)72826441Ssam isstatic(cp)
72926441Ssam register char	*cp;
73026441Ssam {
73126441Ssam 	if (*cp == '_' || *cp == 'L')
73226441Ssam 		return (1);
73326441Ssam 	return (0);
73426441Ssam }
73529670Ssam 
73629670Ssam 
checkaobdisp(p)73729670Ssam checkaobdisp(p)
73829670Ssam register struct node *p;
73929670Ssam {
74029670Ssam register struct node *q;
74129670Ssam register int i;
74229670Ssam 
74329670Ssam 
74429670Ssam if (!aobflag) return(1);
74529670Ssam /*  backward search */
74629670Ssam 	i = 0;
74729670Ssam 	q = p;
74829670Ssam 	while (i++ < MAXAOBDISP && ((q= q->back) !=&first))
74929670Ssam 	{
75029670Ssam 		if (p->ref == q)
75129670Ssam 		   return(1);
75229670Ssam 	}
75329670Ssam 
75429670Ssam /*  forward search */
75529670Ssam 	i = 0;
75629670Ssam 	q = p;
75729670Ssam 	while (i++ < MAXAOBDISP && ((q= q->forw) !=0))
75829670Ssam 	{
75929670Ssam 		if (p->ref == q)
76029670Ssam 		   return(1);
76129670Ssam 	}
76229670Ssam 	return(0);
76329670Ssam }
76429670Ssam 
76529670Ssam 
76629670Ssam struct intleavetab intltab[] = {
76729670Ssam 	ADDF,	FLOAT,		1,
76829670Ssam 	ADDF,	DOUBLE,		1,
76929670Ssam 	SUBF,	FLOAT,		1,
77029670Ssam 	SUBF,	DOUBLE,		1,
77129670Ssam 	MULF,	FLOAT,		1,
77229670Ssam 	MULF,	DOUBLE,		1,
77329670Ssam 	DIVF,	FLOAT,		1,
77429670Ssam 	DIVF,	DOUBLE,		1,
77529670Ssam 	SINF,	FLOAT,		1,
77629670Ssam 	COSF,	FLOAT,		1,
77729670Ssam 	ATANF,	FLOAT,		1,
77829670Ssam 	LOGF,	FLOAT,		1,
77929670Ssam 	SQRTF,	FLOAT,		1,
78029670Ssam 	EXPF,	FLOAT,		1,
78129670Ssam 	LDF,	FLOAT,		0,
78229670Ssam 	LDF,	DOUBLE,		0,
78329670Ssam 	LNF,	FLOAT,		0,
78429670Ssam 	LNF,	DOUBLE,		0,
78529670Ssam 	STF,	FLOAT,		0,
78629670Ssam 	CMPF,	FLOAT,		0,
78729670Ssam 	CMPF,	DOUBLE,		0,
78829670Ssam 	CMPF2,	FLOAT,		0,
78929670Ssam 	TSTF,	FLOAT,		0,
79029670Ssam 	TSTF,	DOUBLE,		0,
79129670Ssam 	PUSHD,	DOUBLE,		0,
79229670Ssam 	CVLF,	U(LONG,FLOAT),	0,
79329670Ssam 	CVFL,	U(FLOAT,LONG),	0,
79429670Ssam 	LDFD,	U(FLOAT,DOUBLE),0,
79529670Ssam 	CVDF,	U(DOUBLE,FLOAT),0,
79629670Ssam 	NEGF,	FLOAT,		0,
79729775Ssam 	NIL,	0,		0};
79829670Ssam 
interleave()79929670Ssam interleave()
80029670Ssam {
80129670Ssam 	register struct node *p, *p1;
80229670Ssam 
80329670Ssam 	register struct intleavetab *t;
80429670Ssam 	register int r;
80529670Ssam 	int count;
80629670Ssam 	for (p= first.forw; p!=0; p = p->forw){
80729670Ssam 		count = 0;
80829775Ssam 		for  (t =intltab; t->op != NIL; t++){
80929670Ssam 			if (t->op == p->op && t->subop == p->subop){
81029670Ssam 			count = t->intleavect;
81129670Ssam 			break;
81229670Ssam 			}
81329670Ssam 		}
81429670Ssam 		if (count < 1) continue;
81529670Ssam 		p1 = p->forw;
81629670Ssam 		clearuse();
81729670Ssam 		clearreg();
81829670Ssam 		while ((p1 != 0) && (p1->op != CBR) &&
81929670Ssam 		      (p1->subop == FLOAT || p1->subop == DOUBLE ||
82029670Ssam 	              ((p1->subop&0xF0)==DOUBLE<<4) || ((p1->subop&0xF)==DOUBLE )||
82129670Ssam 	              ((p1->subop&0xF0)==FLOAT<<4) || (p1->subop&0xF)==FLOAT))
82229670Ssam 		{
82329670Ssam 			if (((r = isreg(p1->code)) >= 0)){
82429670Ssam 			uses[r] = p1;
82529670Ssam 			if ((p1->subop == DOUBLE) || ((p->subop&0xF0)==DOUBLE<<4) ||
82629670Ssam 		           ((p->subop&0xF)==DOUBLE))
82729670Ssam 				uses[r+1] = p1;
82829670Ssam 			}
82929670Ssam 			else checkreg(p1,p1->code);
83029670Ssam 			p1 = p1->forw;
83129670Ssam 
83229670Ssam 		}
83329670Ssam 		if (p1 == 0) return;
83429670Ssam 		if (!(sideeffect(p, p1)))
83529670Ssam 			insertblk(p,p1);
83629670Ssam 	}
83729670Ssam 
83829670Ssam }
83929670Ssam 
84029670Ssam 
84129670Ssam insertblk(p, p1)
84229670Ssam struct node *p, *p1;
84329670Ssam {
84429670Ssam 	p1->back->forw = p1->forw;
84529670Ssam 	p1->forw->back = p1->back;
84629670Ssam 	p1->forw = p->forw;
84729670Ssam 	p->forw->back = p1;
84829670Ssam 	p->forw = p1;
84929670Ssam 	p1->back = p;
85029670Ssam }
85129670Ssam 
85229775Ssam OpCode termop[] = {
85329670Ssam 	JBR, CBR, JMP, LABEL, DLABEL, EROU, JSW, TST, CMP, BIT,
85429670Ssam 	CALLF, CALLS, CASE, AOBLEQ, AOBLSS, CMPF, CMPF2, TSTF, MOVBLK, MFPR,
85529670Ssam 	MTPR, PROBE, MOVO, TEXT, DATA, BSS, ALIGN, END, LGEN, SET,
85629775Ssam 	LCOMM, COMM, NIL
85729775Ssam };
85829670Ssam 
85929670Ssam sideeffect(p,p1)
86029670Ssam struct node *p, *p1;
86129670Ssam {
86229670Ssam 	register struct node *q;
86329670Ssam 	register int r;
86429775Ssam 	register OpCode *t;
86529670Ssam 	register char *cp;
86629670Ssam 	int i;
86729670Ssam 
86829775Ssam 	if (p1->op == NIL) return(1);  /*  special instructions */
86929670Ssam 
87029775Ssam 	for (t = termop; *t!=NIL; t++){
87129670Ssam 		if (*t == p1->op) return(1);
87229670Ssam 	}
87329670Ssam 	if ((p1->forw != NULL) && (p1->forw->op == CBR))
87429670Ssam 		return(1);
87529670Ssam 	splitrand(p1);
87629670Ssam 	r = isreg(lastrand);
87729670Ssam 	if (uses[r] &&  r >= 0 ) return(1);
87829670Ssam 	if ((p1->op == EDIV) && (r = isreg(regs[RT3]) >= 0) &&
87929670Ssam 	   (uses[r]))  return(1);
88029670Ssam 
88129670Ssam 	for (q = p1->back ; q!=p; q=q->back)
88229670Ssam 	{
88329670Ssam 		if ((p1->op == PUSH || p1->op == PUSHA) &&
88429670Ssam 		    (q->op == PUSHD || q->op == PUSH || q->op == PUSHA))
88529670Ssam 		     return(1); 		     /* keep args in order */
88629670Ssam 		if (((i = strlen(q->code)) >= 5 &&    /* cvdl -(sp); pushl r0*/
88729670Ssam 		    (strcmp(q->code+i-5,"-(sp)") == 0 )) ||
88829670Ssam 		    (strcmp(lastrand,"-(sp)") == 0)) return(1);
88929670Ssam 		if (equstr(q->code, lastrand))
89029670Ssam 		    return(1);
89129670Ssam 		if (q->op == STF || q->op == CVFL || q->op == CVLF)
89229670Ssam 		   {
89329670Ssam 		    if (equstr(q->code, regs[RT1])) return(1);
89429775Ssam 		if (has3ops(p1) || p1->op == EMUL || p1->op == EDIV)
89529670Ssam 		    if (equstr(q->code, regs[RT2]))
89629670Ssam 		       return(1);
89729670Ssam 		/*  handle the case  std -56(fp) pushl -60(fp) pushl
89829670Ssam 		    -56(fp);
89929670Ssam 		*/
90029670Ssam 		if ((p1->forw != NULL) &&  (q->op == STF) &&
90129670Ssam 		(q->subop == DOUBLE)){
90229670Ssam 		if (!strncmp(q->code,p1->forw->code,strlen(q->code)))
90329670Ssam 			return(1);
90429670Ssam 		}
90529670Ssam 		}
90629670Ssam 	}
90729670Ssam 	return(0);
90829670Ssam }
90929670Ssam checkreg(p,s)
91029670Ssam struct node *p;
91129670Ssam char *s;
91229670Ssam {
91329670Ssam char *cp2;
91429670Ssam register int r;
91529670Ssam 	/* check for (r),[r] */
91629670Ssam 	do if (*s=='(' || *s=='[') {/* get register number */
91729670Ssam 		char t;
91829670Ssam 		cp2= ++s; while (*++s!=')' && *s!=']'); t= *s; *s=0;
91929670Ssam 		if ((r=isreg(cp2)) >= 0)  {
92029670Ssam 			uses[r]=p;
92129670Ssam 		}
92229670Ssam 		*s=t;
92329670Ssam 	} while (*++s);
92429670Ssam }
925