xref: /csrg-svn/old/pcc/c2.tahoe/c22.c (revision 26441)
1*26441Ssam #ifndef lint
2*26441Ssam static char sccsid[] = "@(#)c22.c	1.1 (Berkeley) 03/02/86";
3*26441Ssam #endif
4*26441Ssam 
5*26441Ssam /*
6*26441Ssam  * C object code improver-- third part
7*26441Ssam  */
8*26441Ssam 
9*26441Ssam #include "c2.h"
10*26441Ssam #include <stdio.h>
11*26441Ssam #include <ctype.h>
12*26441Ssam 
13*26441Ssam rmove()
14*26441Ssam {
15*26441Ssam 	register struct node *p;
16*26441Ssam 	register int r, r1;
17*26441Ssam 
18*26441Ssam 	clearreg();
19*26441Ssam 	for (p=first.forw; p!=0; p = p->forw) {
20*26441Ssam 	if (debug) {
21*26441Ssam 		printf("Regs: ");
22*26441Ssam 		for (r=0; r<=NREG; r++)
23*26441Ssam 			if (regs[r][0]) {
24*26441Ssam 				r1=regs[r][0];
25*26441Ssam 				printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1);
26*26441Ssam 			}
27*26441Ssam 		printf("-\n");
28*26441Ssam 	}
29*26441Ssam 	switch (p->op) {
30*26441Ssam 
31*26441Ssam 	case CVT:
32*26441Ssam 	case MOVZ:
33*26441Ssam 		splitrand(p);
34*26441Ssam 		repladdr(p);
35*26441Ssam 		r = isreg(regs[RT1]);
36*26441Ssam 		r1 = isreg(regs[RT2]);
37*26441Ssam 		dest(regs[RT2],p->subop, 1);
38*26441Ssam 		if (r>=0 && r1>=0) {
39*26441Ssam 			p->op = MOV; p->subop = LONG;
40*26441Ssam 			p->pop = 0;
41*26441Ssam 			nchange++;
42*26441Ssam 			goto case_mov;
43*26441Ssam 		}
44*26441Ssam 		if(p->op == CVT) {
45*26441Ssam 			if (r1>=0) savereg(r1, regs[RT1], p->subop);
46*26441Ssam 		} else
47*26441Ssam 			ccloc[0] = 0;
48*26441Ssam 		break;
49*26441Ssam 
50*26441Ssam 	case MOV:
51*26441Ssam 	case_mov:
52*26441Ssam 		splitrand(p);
53*26441Ssam 		if ((r = findrand(regs[RT1],p->subop)) >= 0) {
54*26441Ssam 			if (r == isreg(regs[RT2]))
55*26441Ssam 				if(p->forw->op!=CBR) {
56*26441Ssam 					delnode(p); redunm++; nchange++; break;
57*26441Ssam 				} else {
58*26441Ssam 					p->op=TST; p->pop=0;
59*26441Ssam 					while(*p->code++ != ',');
60*26441Ssam 					redunm++; nchange++;
61*26441Ssam 					goto case_tst;
62*26441Ssam 				}
63*26441Ssam 		}
64*26441Ssam 		repladdr(p);
65*26441Ssam 		r = isreg(regs[RT1]);
66*26441Ssam 		r1 = isreg(regs[RT2]);
67*26441Ssam 		dest(regs[RT2],p->subop, 1);
68*26441Ssam 		if ((regs[ACC][0]) && equstr(regs[RT2],regs[ACC]+1)) {
69*26441Ssam                 *(short *)(regs[ACC]) = 0;}
70*26441Ssam 
71*26441Ssam 		if (r>=0) {
72*26441Ssam 			if (r1>=0) {
73*26441Ssam 				if (r == r1 && p->forw->op!=CBR) {
74*26441Ssam 					delnode(p); redunm++; nchange++; break;
75*26441Ssam 				}
76*26441Ssam 				if(regs[r][0])
77*26441Ssam 					savereg(r1, regs[r]+1, p->subop);
78*26441Ssam 			} else savereg(r, regs[RT2], p->subop);
79*26441Ssam 		} else if (r1>=0) savereg(r1, regs[RT1], p->subop);
80*26441Ssam 		else setcon(regs[RT1], regs[RT2], p->subop);
81*26441Ssam 		break;
82*26441Ssam 
83*26441Ssam /* .rx,.wx or .rx,.rx,.wx */
84*26441Ssam 	case ADD:
85*26441Ssam 	case SUB:
86*26441Ssam 	case AND:
87*26441Ssam 	case OR:
88*26441Ssam 	case XOR:
89*26441Ssam 	case MUL:
90*26441Ssam 	case DIV:
91*26441Ssam #ifdef EMOD
92*26441Ssam 	case EDIV:
93*26441Ssam 	case EMOD:
94*26441Ssam #endif EMOD
95*26441Ssam 	case SHAL:
96*26441Ssam 	case SHAR:
97*26441Ssam 	case SHL:
98*26441Ssam 	case SHR:
99*26441Ssam 	case ADDA:
100*26441Ssam 	case SUBA:
101*26441Ssam /* .rx,.wx */
102*26441Ssam 	case MFPR:
103*26441Ssam 	case COM:
104*26441Ssam 	case NEG:
105*26441Ssam 		splitrand(p);
106*26441Ssam 		repladdr(p);
107*26441Ssam 		dest(lastrand,p->subop, p->op!=ADDA && p->op!=SUBA);
108*26441Ssam 		break;
109*26441Ssam 
110*26441Ssam /* .mx or .wx */
111*26441Ssam 	case STF:
112*26441Ssam 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
113*26441Ssam 			delnode(p);
114*26441Ssam 			nst++; nchange++; break;
115*26441Ssam 		}
116*26441Ssam 		savereg(ACC, p->code, p->subop);
117*26441Ssam 	case CLR:
118*26441Ssam 	case INC:
119*26441Ssam 	case DEC:
120*26441Ssam 	case CVFL:
121*26441Ssam 		dest(p->code,p->subop, 1);
122*26441Ssam 		if (p->op==CLR)
123*26441Ssam 			if ((r = isreg(p->code)) >= 0)
124*26441Ssam 				savereg(r, "$0", p->subop);
125*26441Ssam 			else
126*26441Ssam 				setcon("$0", p->code, p->subop);
127*26441Ssam 		break;
128*26441Ssam 
129*26441Ssam /* .rx */
130*26441Ssam 	case LDF:
131*26441Ssam 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
132*26441Ssam 			delnode(p);
133*26441Ssam 			nld++; nchange++; break;
134*26441Ssam 		}
135*26441Ssam 		savereg(ACC, p->code, p->subop);
136*26441Ssam 		goto case_tst;
137*26441Ssam 	case LNF:
138*26441Ssam 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
139*26441Ssam 			p->op = NEGF; p->pop = 0; p->code = 0;
140*26441Ssam 			regs[ACC][0] = 0;
141*26441Ssam 			break;
142*26441Ssam 		}
143*26441Ssam 	case CVLF:
144*26441Ssam 	case LDFD:
145*26441Ssam 	case ADDF:
146*26441Ssam 	case SUBF:
147*26441Ssam 	case MULF:
148*26441Ssam 	case DIVF:
149*26441Ssam 		regs[ACC][0] = 0;
150*26441Ssam 	case TST:
151*26441Ssam 	case_tst:
152*26441Ssam 	case PUSH:
153*26441Ssam 		splitrand(p);
154*26441Ssam 		lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */
155*26441Ssam 		repladdr(p);
156*26441Ssam 		lastrand=regs[RT1];
157*26441Ssam 		if (p->op==TST && equstr(lastrand, ccloc+1)
158*26441Ssam 		  && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop))) {
159*26441Ssam 			delnode(p); nrtst++; nchange++; break;
160*26441Ssam 		}
161*26441Ssam 		if (p->op==PUSH && p->subop!=LONG &&
162*26441Ssam 		 (isreg(lastrand)>=0 || *lastrand=='$')) {
163*26441Ssam 			p->subop = LONG;
164*26441Ssam 			p->pop = 0;
165*26441Ssam 			nchange++;
166*26441Ssam 		}
167*26441Ssam 		if (p->op==TST || p->op==PUSH)
168*26441Ssam 			setcc(lastrand,p->subop);
169*26441Ssam 		break;
170*26441Ssam 
171*26441Ssam /* .rx,.rx,.rx */
172*26441Ssam 	case PROBE:
173*26441Ssam 	case CASE:
174*26441Ssam /* .rx,.rx */
175*26441Ssam 	case MTPR:
176*26441Ssam 	case CALLS:
177*26441Ssam 	case CALLF:
178*26441Ssam 	case CMP:
179*26441Ssam 	case BIT:
180*26441Ssam 	case CMPF:
181*26441Ssam 	case CMPF2:
182*26441Ssam 		splitrand(p);
183*26441Ssam 		/* fool repladdr into doing right number of operands */
184*26441Ssam 		lastrand=byondrd(p);
185*26441Ssam 		if (p->op==CALLF || p->op==CALLS) clearreg();
186*26441Ssam 		else repladdr(p);
187*26441Ssam 	case TSTF:
188*26441Ssam 		ccloc[0]=0;
189*26441Ssam 	case PUSHD:
190*26441Ssam 		break;
191*26441Ssam 
192*26441Ssam /* acc only */
193*26441Ssam 	case CVDF:
194*26441Ssam 	case NEGF:
195*26441Ssam 	case SINF:
196*26441Ssam 	case COSF:
197*26441Ssam 	case ATANF:
198*26441Ssam 	case LOGF:
199*26441Ssam 	case SQRTF:
200*26441Ssam 	case EXPF:
201*26441Ssam 		regs[ACC][0] = 0;
202*26441Ssam 		break;
203*26441Ssam 
204*26441Ssam #ifndef EMOD
205*26441Ssam /* .rx,.rx,.wx,.wx */
206*26441Ssam 	case EDIV:
207*26441Ssam 		splitrand(p);
208*26441Ssam 		lastrand = regs[RT3];
209*26441Ssam 		repladdr(p);
210*26441Ssam 		dest(regs[RT3], p->subop, 1);
211*26441Ssam 		dest(regs[RT4], p->subop, 0);
212*26441Ssam 		break;
213*26441Ssam #endif EMOD
214*26441Ssam 
215*26441Ssam /* .rx,.rx,.rx,wx */
216*26441Ssam 	case EMUL:
217*26441Ssam 		splitrand(p);
218*26441Ssam 		lastrand = regs[RT4];
219*26441Ssam 		repladdr(p);
220*26441Ssam 		dest(regs[RT4],QUAD, 1); /* fourth operand is a quad */
221*26441Ssam 		break;
222*26441Ssam 	case CBR:
223*26441Ssam 		if (p->subop>=JBC) {
224*26441Ssam 			splitrand(p);
225*26441Ssam 			lastrand=regs[RT3]; /* 2 operands can be optimized */
226*26441Ssam 			repladdr(p);
227*26441Ssam 			ccloc[0] = 0;
228*26441Ssam 		} else
229*26441Ssam 			reduncbr(p);
230*26441Ssam 		break;
231*26441Ssam 
232*26441Ssam 	case JBR:
233*26441Ssam 		redunbr(p);
234*26441Ssam 
235*26441Ssam 	default:
236*26441Ssam 		clearreg();
237*26441Ssam 	}
238*26441Ssam 	}
239*26441Ssam }
240*26441Ssam 
241*26441Ssam jumpsw()
242*26441Ssam {
243*26441Ssam 	register struct node *p, *p1, *pt;
244*26441Ssam 	register int t, nj;
245*26441Ssam 
246*26441Ssam 	t = 0;
247*26441Ssam 	nj = 0;
248*26441Ssam 	for (p=first.forw; p!=0; p = p->forw)
249*26441Ssam 		p->seq = ++t;
250*26441Ssam 	for (p=first.forw; p!=0; p = p1) {
251*26441Ssam 		p1 = p->forw;
252*26441Ssam 		if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
253*26441Ssam 		 && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) {
254*26441Ssam 			if (p->ref==p1->ref)
255*26441Ssam 				continue;
256*26441Ssam 			p->subop = revbr[p->subop];
257*26441Ssam 			p->pop=0;
258*26441Ssam 			pt = p1->ref;
259*26441Ssam 			p1->ref = p->ref;
260*26441Ssam 			p->ref = pt;
261*26441Ssam 			t = p1->labno;
262*26441Ssam 			p1->labno = p->labno;
263*26441Ssam 			p->labno = t;
264*26441Ssam #ifdef COPYCODE
265*26441Ssam 			if (p->labno == 0) {
266*26441Ssam 				pt = (struct node *)p1->code; p1->code = p->code; p->code = (char *)pt;
267*26441Ssam 			}
268*26441Ssam #endif
269*26441Ssam 			nrevbr++;
270*26441Ssam 			nj++;
271*26441Ssam 		}
272*26441Ssam 	}
273*26441Ssam 	return(nj);
274*26441Ssam }
275*26441Ssam 
276*26441Ssam addaob()
277*26441Ssam {
278*26441Ssam 	register struct node *p, *p1, *p2, *p3;
279*26441Ssam 
280*26441Ssam 	for (p = &first; (p1 = p->forw)!=0; p = p1) {
281*26441Ssam 	if (p->op==INC && p->subop==LONG) {
282*26441Ssam 		if (p1->op==LABEL && p1->refc==1 && p1->forw->op==CMP && p1->forw->subop==LONG
283*26441Ssam 		  && (p2=p1->forw->forw)->op==CBR && p2->subop==JLE
284*26441Ssam 		  && (p3=p2->ref->back)->op==JBR && p3->subop==0 && p3->ref==p1
285*26441Ssam 		  && p3->forw->op==LABEL && p3->forw==p2->ref) {
286*26441Ssam 			/* change	INC LAB: CMP	to	LAB: INC CMP */
287*26441Ssam 			p->back->forw=p1; p1->back=p->back;
288*26441Ssam 			p->forw=p1->forw; p1->forw->back=p;
289*26441Ssam 			p->back=p1; p1->forw=p;
290*26441Ssam 			p1=p->forw;
291*26441Ssam 			/* adjust beginning value by 1 */
292*26441Ssam 			p2=alloc(sizeof first); p2->op = DEC; p2->subop = LONG;
293*26441Ssam 			p2->pop=0;
294*26441Ssam 			p2->forw=p3; p2->back=p3->back; p3->back->forw=p2;
295*26441Ssam 			p3->back=p2; p2->code=p->code; p2->labno=0;
296*26441Ssam 		}
297*26441Ssam 		if (p1->op==CMP && p1->subop==LONG &&
298*26441Ssam 		  (p2=p1->forw)->op==CBR && p2->forw->op!=CBR) {
299*26441Ssam 			register char *cp1,*cp2;
300*26441Ssam 			splitrand(p1); if (!equstr(p->code,regs[RT1])) continue;
301*26441Ssam 			if (p2->subop==JLE || p2->subop==JLT) {
302*26441Ssam 				if (p2->subop==JLE) p->op = AOBLEQ; else p->op = AOBLSS; p->subop = 0;
303*26441Ssam 				cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */
304*26441Ssam 				cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */
305*26441Ssam 				p->pop=0; newcode(p);
306*26441Ssam 				p->labno = p2->labno; delnode(p2); delnode(p1); naob++;
307*26441Ssam 			}
308*26441Ssam 		}
309*26441Ssam 	}
310*26441Ssam 	}
311*26441Ssam }
312*26441Ssam 
313*26441Ssam ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */
314*26441Ssam 	register int log;
315*26441Ssam 	if (n==0 || n&(n-1)) return(-1); log=0;
316*26441Ssam 	for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}
317*26441Ssam }
318*26441Ssam 
319*26441Ssam equop(p1, p2)
320*26441Ssam register struct node *p1, *p2;
321*26441Ssam {
322*26441Ssam 	register char *cp1, *cp2;
323*26441Ssam 
324*26441Ssam 	if (p1->op != p2->op || p1->subop != p2->subop)
325*26441Ssam 		return(0);
326*26441Ssam 	if (p1->op>0 && p1->op<MOV)
327*26441Ssam 		return(0);
328*26441Ssam 	if (p1->op==MOVA && p1->labno!=p2->labno) return(0);
329*26441Ssam 	cp1 = p1->code;
330*26441Ssam 	cp2 = p2->code;
331*26441Ssam 	if (cp1==0 && cp2==0)
332*26441Ssam 		return(1);
333*26441Ssam 	if (cp1==0 || cp2==0)
334*26441Ssam 		return(0);
335*26441Ssam 	while (*cp1 == *cp2++)
336*26441Ssam 		if (*cp1++ == 0)
337*26441Ssam 			return(1);
338*26441Ssam 	return(0);
339*26441Ssam }
340*26441Ssam 
341*26441Ssam delnode(p) register struct node *p; {
342*26441Ssam 	p->back->forw = p->forw;
343*26441Ssam 	p->forw->back = p->back;
344*26441Ssam }
345*26441Ssam 
346*26441Ssam decref(p)
347*26441Ssam register struct node *p;
348*26441Ssam {
349*26441Ssam 	if (p && --p->refc <= 0) {
350*26441Ssam 		nrlab++; nchange++;
351*26441Ssam 		delnode(p);
352*26441Ssam 	}
353*26441Ssam }
354*26441Ssam 
355*26441Ssam struct node *
356*26441Ssam nonlab(ap)
357*26441Ssam struct node *ap;
358*26441Ssam {
359*26441Ssam 	register struct node *p;
360*26441Ssam 
361*26441Ssam 	p = ap;
362*26441Ssam 	while (p && p->op==LABEL)
363*26441Ssam 		p = p->forw;
364*26441Ssam 	return(p);
365*26441Ssam }
366*26441Ssam 
367*26441Ssam clearuse() {
368*26441Ssam 	register struct node **i;
369*26441Ssam 	for (i=uses+NUSE; i>uses;) *--i=0;
370*26441Ssam 	useacc = 0;
371*26441Ssam }
372*26441Ssam 
373*26441Ssam clearreg() {
374*26441Ssam 	register char **i;
375*26441Ssam 	for (i=regs+NREG+1; i>regs;){ **--i=0; **i=0; }
376*26441Ssam 	conloc[0] = 0; ccloc[0] = 0;
377*26441Ssam }
378*26441Ssam 
379*26441Ssam savereg(ai, s, type)
380*26441Ssam register char *s;
381*26441Ssam {
382*26441Ssam 	register char *p, *sp;
383*26441Ssam 
384*26441Ssam 	sp = p = regs[ai];
385*26441Ssam 	/* if any indexing, must be parameter or local */
386*26441Ssam 	/* indirection (as in "*-4(fp)") is ok, however */
387*26441Ssam 	*p++ = type;
388*26441Ssam 	if (*s=='*' || *s=='$')
389*26441Ssam 		*p++ = *s++;
390*26441Ssam 	if (natural(s))
391*26441Ssam 		strcpy(p, s);
392*26441Ssam 	else {*sp = 0; return;}
393*26441Ssam }
394*26441Ssam 
395*26441Ssam dest(s,type, ccflg)
396*26441Ssam register char *s;
397*26441Ssam {
398*26441Ssam 	register int i;
399*26441Ssam 
400*26441Ssam 	if ((i = isreg(s)) >= 0) {
401*26441Ssam 		*(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */
402*26441Ssam 		if (DOUBLE==(type&0xF) || DOUBLE==((type>>4)&0xF) || type==QUAD)
403*26441Ssam 			*(short *)(regs[i+1]) = 0;
404*26441Ssam 	}
405*26441Ssam 	for (i=NREG; --i>=0;)
406*26441Ssam 		if (regs[i][1]=='*' && equstr(s, regs[i]+2))
407*26441Ssam 			*(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */
408*26441Ssam 	while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */
409*26441Ssam 		*(short *)(regs[i]) = 0;
410*26441Ssam 
411*26441Ssam 	if (!natural(s)) {/* wild store, everything except constants vanishes */
412*26441Ssam 		for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0;
413*26441Ssam 		conloc[0] = 0; ccloc[0] = 0;
414*26441Ssam 	} else {
415*26441Ssam 		if(ccflg)setcc(s,type); /* natural destinations set condition codes */
416*26441Ssam 		if (equstr(s, conloc))
417*26441Ssam 			conloc[0] = 0;
418*26441Ssam 	}
419*26441Ssam }
420*26441Ssam 
421*26441Ssam splitrand(p) struct node *p; {
422*26441Ssam /* separate operands at commas, set up 'regs' and 'lastrand' */
423*26441Ssam register char *p1, *p2; register char **preg;
424*26441Ssam 
425*26441Ssam 	preg=regs+RT1;
426*26441Ssam 	if (p1=p->code) while (*p1) {
427*26441Ssam 		lastrand=p2= *preg++;
428*26441Ssam 		while (*p1) if (','==(*p2++= *p1++)) {--p2; break;}
429*26441Ssam 		*p2=0;
430*26441Ssam 	}
431*26441Ssam 	while (preg<(regs+RT1+5)) *(*preg++)=0;
432*26441Ssam }
433*26441Ssam 
434*26441Ssam compat(have, want)
435*26441Ssam register int have, want;
436*26441Ssam {
437*26441Ssam 	register int hsrc, hdst;
438*26441Ssam 	extern int bitsize[];
439*26441Ssam 
440*26441Ssam 	if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */
441*26441Ssam 	hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc;
442*26441Ssam 	if (want>=QUAD)
443*26441Ssam 		return(bitsize[hdst]==bitsize[want] && bitsize[hsrc]==bitsize[want]);
444*26441Ssam 	return(hsrc==want && hdst>=want && hdst<QUAD);
445*26441Ssam }
446*26441Ssam 
447*26441Ssam equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}
448*26441Ssam 
449*26441Ssam findrand(as, type)
450*26441Ssam char *as;
451*26441Ssam {
452*26441Ssam 	register char **i;
453*26441Ssam 	for (i = regs+NREG; --i>=regs;) {
454*26441Ssam 		if (**i && equstr(*i+1, as) && compat(**i,type))
455*26441Ssam 			return(i-regs);
456*26441Ssam 	}
457*26441Ssam 	return(-1);
458*26441Ssam }
459*26441Ssam 
460*26441Ssam isreg(s)
461*26441Ssam register char *s;
462*26441Ssam {
463*26441Ssam 	if (*s++!='r' || !isdigit(*s++)) return(-1);
464*26441Ssam 	if (*s==0) return(*--s-'0');
465*26441Ssam 	if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0');
466*26441Ssam 	return(-1);
467*26441Ssam }
468*26441Ssam 
469*26441Ssam /*
470*26441Ssam check()
471*26441Ssam {
472*26441Ssam 	register struct node *p, *lp;
473*26441Ssam 
474*26441Ssam 	lp = &first;
475*26441Ssam 	for (p=first.forw; p!=0; p = p->forw) {
476*26441Ssam 		if (p->back != lp)
477*26441Ssam 			abort(-1);
478*26441Ssam 		lp = p;
479*26441Ssam 	}
480*26441Ssam }
481*26441Ssam */
482*26441Ssam 
483*26441Ssam newcode(p) struct node *p; {
484*26441Ssam 	register char *p1,*p2,**preg;
485*26441Ssam 
486*26441Ssam 	preg=regs+RT1; p2=line;
487*26441Ssam 	while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';}
488*26441Ssam 	*--p2=0;
489*26441Ssam 	p->code=copy(line);
490*26441Ssam }
491*26441Ssam 
492*26441Ssam repladdr(p)
493*26441Ssam struct node *p;
494*26441Ssam {
495*26441Ssam 	register int r;
496*26441Ssam 	register char *p1;
497*26441Ssam 	register char **preg;
498*26441Ssam 	register int nrepl;
499*26441Ssam 
500*26441Ssam 	preg=regs+RT1; nrepl=0;
501*26441Ssam 	while (lastrand!=(p1= *preg++))
502*26441Ssam 		if (0<=(r=findrand(p1,p->subop))) {
503*26441Ssam 			*p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0;
504*26441Ssam 			nchange++; nrepl++; nsaddr++;
505*26441Ssam 		}
506*26441Ssam 	if (nrepl) newcode(p);
507*26441Ssam }
508*26441Ssam 
509*26441Ssam /* conditional branches which are never/always taken */
510*26441Ssam reduncbr(p)
511*26441Ssam register struct node *p;
512*26441Ssam {
513*26441Ssam 	register struct node *p1;
514*26441Ssam 	register char *ap1, *ap2;
515*26441Ssam 
516*26441Ssam 	p1 = p->back;
517*26441Ssam 	if (p1->op==CMP) {
518*26441Ssam 		splitrand(p1);
519*26441Ssam 		ap1 = findcon(regs[RT1], p1->subop);
520*26441Ssam 		ap2 = findcon(regs[RT2], p1->subop);
521*26441Ssam 	} else {
522*26441Ssam 		if(!ccloc[0])
523*26441Ssam 			return;
524*26441Ssam 		ap1 = findcon(ccloc+1, ccloc[0]);
525*26441Ssam 		ap2 = "$0";
526*26441Ssam 	}
527*26441Ssam 	switch (compare(p->subop, ap1, ap2)) {
528*26441Ssam 	case 0:		/* branch never taken */
529*26441Ssam 		delnode(p);
530*26441Ssam 		nredunj++;
531*26441Ssam 		nchange++;
532*26441Ssam 		decref(p->ref);
533*26441Ssam 		if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) {
534*26441Ssam 			delnode(p1);
535*26441Ssam 			nrtst++;
536*26441Ssam 		}
537*26441Ssam 		break;
538*26441Ssam 	case 1:		/* branch always taken */
539*26441Ssam 		p->op = JBR;
540*26441Ssam 		p->subop = 0;
541*26441Ssam 		p->pop = 0;
542*26441Ssam 		nchange++;
543*26441Ssam 		if(nonlab(p->ref)->op!=CBR && (p1->op==TST || p1->op==CMP)) {
544*26441Ssam 			delnode(p1);
545*26441Ssam 			nrtst++;
546*26441Ssam 		}
547*26441Ssam 	}
548*26441Ssam }
549*26441Ssam 
550*26441Ssam /* a jump to a redundant compare (start of a 'for') */
551*26441Ssam redunbr(p)
552*26441Ssam register struct node *p;
553*26441Ssam {
554*26441Ssam 	register struct node *p1;
555*26441Ssam 	register char *ap1, *ap2;
556*26441Ssam 
557*26441Ssam 	if ((p1 = p->ref) == 0)
558*26441Ssam 		return;
559*26441Ssam 	p1 = nonlab(p1);
560*26441Ssam 	if (p1->op==TST || p1->op==CMP)
561*26441Ssam 		splitrand(p1);
562*26441Ssam 	else
563*26441Ssam 		return;
564*26441Ssam 	if (p1->forw->op==CBR) {
565*26441Ssam 		ap1 = findcon(regs[RT1], p1->subop);
566*26441Ssam 		if (p1->op==TST)
567*26441Ssam 			ap2 = "$0";
568*26441Ssam 		else
569*26441Ssam 			ap2 = findcon(regs[RT2], p1->subop);
570*26441Ssam 		p1 = p1->forw;
571*26441Ssam 		if (compare(p1->subop, ap1, ap2) > 0) {
572*26441Ssam 			nredunj++;
573*26441Ssam 			nchange++;
574*26441Ssam 			decref(p->ref);
575*26441Ssam 			p->ref = p1->ref;
576*26441Ssam 			p->labno = p1->labno;
577*26441Ssam #ifdef COPYCODE
578*26441Ssam 			if (p->labno == 0)
579*26441Ssam 				p->code = p1->code;
580*26441Ssam 			if (p->ref)
581*26441Ssam #endif
582*26441Ssam 				p->ref->refc++;
583*26441Ssam 		}
584*26441Ssam 	} else if (p1->op==TST && equstr(regs[RT1],ccloc+1) &&
585*26441Ssam 			equtype(ccloc[0],p1->subop)) {
586*26441Ssam 		p1=insertl(p1->forw); decref(p->ref); p->ref=p1;
587*26441Ssam 		nrtst++; nchange++;
588*26441Ssam 	}
589*26441Ssam }
590*26441Ssam 
591*26441Ssam char *
592*26441Ssam findcon(p, type)
593*26441Ssam 	register char *p;
594*26441Ssam {
595*26441Ssam 	register int r;
596*26441Ssam 
597*26441Ssam 	if (*p=='$')
598*26441Ssam 		return(p);
599*26441Ssam 	if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
600*26441Ssam 		return(regs[r]+1);
601*26441Ssam 	if (equstr(p, conloc))
602*26441Ssam 		return(conval+1);
603*26441Ssam 	return(p);
604*26441Ssam }
605*26441Ssam 
606*26441Ssam /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
607*26441Ssam compare(op, acp1, acp2)
608*26441Ssam char *acp1, *acp2;
609*26441Ssam {
610*26441Ssam 	register char *cp1, *cp2;
611*26441Ssam 	register int n1, n2, sign;
612*26441Ssam 
613*26441Ssam 	cp1 = acp1;
614*26441Ssam 	cp2 = acp2;
615*26441Ssam 	if (*cp1++ != '$' || *cp2++ != '$')
616*26441Ssam 		return(-1);
617*26441Ssam 	n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
618*26441Ssam 	while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';}
619*26441Ssam 	n1 *= sign;
620*26441Ssam 	n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
621*26441Ssam 	while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';}
622*26441Ssam 	n2 *= sign;
623*26441Ssam 	if (*cp1=='+')
624*26441Ssam 		cp1++;
625*26441Ssam 	if (*cp2=='+')
626*26441Ssam 		cp2++;
627*26441Ssam 	do {
628*26441Ssam 		if (*cp1++ != *cp2)
629*26441Ssam 			return(-1);
630*26441Ssam 	} while (*cp2++);
631*26441Ssam 	switch(op) {
632*26441Ssam 
633*26441Ssam 	case JEQ:
634*26441Ssam 		return(n1 == n2);
635*26441Ssam 	case JNE:
636*26441Ssam 		return(n1 != n2);
637*26441Ssam 	case JLE:
638*26441Ssam 		return(n1 <= n2);
639*26441Ssam 	case JGE:
640*26441Ssam 		return(n1 >= n2);
641*26441Ssam 	case JLT:
642*26441Ssam 		return(n1 < n2);
643*26441Ssam 	case JGT:
644*26441Ssam 		return(n1 > n2);
645*26441Ssam 	case JLO:
646*26441Ssam 		return((unsigned)n1 < (unsigned)n2);
647*26441Ssam 	case JHI:
648*26441Ssam 		return((unsigned)n1 > (unsigned)n2);
649*26441Ssam 	case JLOS:
650*26441Ssam 		return((unsigned)n1 <= (unsigned)n2);
651*26441Ssam 	case JHIS:
652*26441Ssam 		return((unsigned)n1 >= (unsigned)n2);
653*26441Ssam 	}
654*26441Ssam 	return(-1);
655*26441Ssam }
656*26441Ssam 
657*26441Ssam setcon(cv, cl, type)
658*26441Ssam register char *cv, *cl;
659*26441Ssam {
660*26441Ssam 	register char *p;
661*26441Ssam 
662*26441Ssam 	if (*cv != '$')
663*26441Ssam 		return;
664*26441Ssam 	if (!natural(cl))
665*26441Ssam 		return;
666*26441Ssam 	p = conloc;
667*26441Ssam 	while (*p++ = *cl++);
668*26441Ssam 	p = conval;
669*26441Ssam 	*p++ = type;
670*26441Ssam 	while (*p++ = *cv++);
671*26441Ssam }
672*26441Ssam 
673*26441Ssam setcc(ap,type)
674*26441Ssam char *ap;
675*26441Ssam {
676*26441Ssam 	register char *p, *p1;
677*26441Ssam 
678*26441Ssam 	p = ap;
679*26441Ssam 	if (!natural(p)) {
680*26441Ssam 		ccloc[0] = 0;
681*26441Ssam 		return;
682*26441Ssam 	}
683*26441Ssam 	p1 = ccloc;
684*26441Ssam 	*p1++ = type;
685*26441Ssam 	while (*p1++ = *p++);
686*26441Ssam }
687*26441Ssam 
688*26441Ssam indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
689*26441Ssam 	while (*p) if (*p++=='[') return(1);
690*26441Ssam 	return(0);
691*26441Ssam }
692*26441Ssam 
693*26441Ssam natural(p)
694*26441Ssam register char *p;
695*26441Ssam {/* 1->simple local, parameter, global, or register; 0->otherwise */
696*26441Ssam 
697*26441Ssam 	if (*p=='*' || *p=='(' || *p=='$')
698*26441Ssam 		return(0);
699*26441Ssam 	while (*p++);
700*26441Ssam 	p--;
701*26441Ssam 	if (*--p==']' || *p==')' &&
702*26441Ssam 	 !(*(p-2)=='f' || fortflg && (*--p=='1' || *p=='2') && *--p=='1'))
703*26441Ssam 		return(0);
704*26441Ssam 	return(1);
705*26441Ssam }
706*26441Ssam 
707*26441Ssam /*
708*26441Ssam ** Tell if an argument is most likely static.
709*26441Ssam */
710*26441Ssam 
711*26441Ssam isstatic(cp)
712*26441Ssam register char	*cp;
713*26441Ssam {
714*26441Ssam 	if (*cp == '_' || *cp == 'L')
715*26441Ssam 		return (1);
716*26441Ssam 	return (0);
717*26441Ssam }
718