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