From f101f434ec64281683da53863bdf785548937c6e Mon Sep 17 00:00:00 2001 From: Tom London Date: Tue, 23 Jan 1979 22:17:30 -0500 Subject: [PATCH] Bell 32V development Work on file usr/src/cmd/c2/c2.h Work on file usr/src/cmd/c2/c20.c Work on file usr/src/cmd/c2/c21.c Work on file usr/src/cmd/c2/c22.c Co-Authored-By: John Reiser Synthesized-from: 32v --- usr/src/cmd/c2/c2.h | 159 +++++++ usr/src/cmd/c2/c20.c | 657 +++++++++++++++++++++++++++++ usr/src/cmd/c2/c21.c | 955 +++++++++++++++++++++++++++++++++++++++++++ usr/src/cmd/c2/c22.c | 300 ++++++++++++++ 4 files changed, 2071 insertions(+) create mode 100644 usr/src/cmd/c2/c2.h create mode 100644 usr/src/cmd/c2/c20.c create mode 100644 usr/src/cmd/c2/c21.c create mode 100644 usr/src/cmd/c2/c22.c diff --git a/usr/src/cmd/c2/c2.h b/usr/src/cmd/c2/c2.h new file mode 100644 index 0000000000..6f3798c020 --- /dev/null +++ b/usr/src/cmd/c2/c2.h @@ -0,0 +1,159 @@ +/* @(#)c2.h 1.13 78/09/23 16:37:28 */ +/* + * Header for object code improver + */ + +#define JBR 1 +#define CBR 2 +#define JMP 3 +#define LABEL 4 +#define DLABEL 5 +#define EROU 7 +#define JSW 9 +#define MOV 10 +#define CLR 11 +#define INC 12 +#define DEC 13 +#define TST 14 +#define PUSH 15 +#define CVT 16 +#define CMP 17 +#define ADD 18 +#define SUB 19 +#define BIT 20 +#define BIC 21 +#define BIS 22 +#define XOR 23 +#define COM 24 +#define NEG 25 +#define MUL 26 +#define DIV 27 +#define ASH 28 +#define EXTV 29 +#define EXTZV 30 +#define INSV 31 +#define CALLS 32 +#define RET 33 +#define CASE 34 +#define SOB 35 +#define TEXT 36 +#define DATA 37 +#define BSS 38 +#define ALIGN 39 +#define END 40 +#define MOVZ 41 +#define WGEN 42 +#define SOBGEQ 43 +#define SOBGTR 44 +#define AOBLEQ 45 +#define AOBLSS 46 +#define ACB 47 +#define MOVA 48 +#define PUSHA 49 +#define LGEN 50 +#define SET 51 + +#define JEQ 0 +#define JNE 1 +#define JLE 2 +#define JGE 3 +#define JLT 4 +#define JGT 5 +/* rearranged for unsigned branches so that jxxu = jxx + 6 */ +#define JLOS 8 +#define JHIS 9 +#define JLO 10 +#define JHI 11 + +#define JBC 12 +#define JBS 13 +#define JLBC 14 +#define JLBS 15 +#define JBCC 16 +#define JBSC 17 +#define JBCS 18 +#define JBSS 19 + +#define BYTE 1 +#define WORD 2 +#define LONG 3 +#define FLOAT 4 +#define DOUBLE 5 +#define QUAD 6 +#define OP2 7 +#define OP3 8 +#define OPB 9 +#define OPX 10 + +#define T(a,b) (a|((b)<<8)) +#define U(a,b) (a|((b)<<4)) + +struct optab { + char opstring[7]; + short opcode; +} optab[]; + +struct node { + char op; + char subop; + short refc; + struct node *forw; + struct node *back; + struct node *ref; + char *code; + struct optab *pop; + short labno; + short seq; +}; + +struct { + short combop; +}; + +char line[512]; +struct node first; +char *curlp; +int nbrbr; +int nsaddr; +int redunm; +int iaftbr; +int njp1; +int nrlab; +int nxjump; +int ncmot; +int nrevbr; +int loopiv; +int nredunj; +int nskip; +int ncomj; +int nsob; +int nrtst; +int nbj; +int nfield; + +int nchange; +int isn; +int debug; +char *lasta; +char *lastr; +char *firstr; +char revbr[]; +#define NREG 12 +char *regs[NREG+5]; /* 0-11, 4 for operands, 1 for running off end */ +char conloc[20]; +char conval[20]; +char ccloc[20]; + +#define RT1 12 +#define RT2 13 +#define RT3 14 +#define RT4 15 +#define LABHS 127 + +struct { char lbyte; }; + +char *copy(); +long getnum(); +struct node *codemove(); +struct node *insertl(); +struct node *nonlab(); diff --git a/usr/src/cmd/c2/c20.c b/usr/src/cmd/c2/c20.c new file mode 100644 index 0000000000..2c4d1a4c3e --- /dev/null +++ b/usr/src/cmd/c2/c20.c @@ -0,0 +1,657 @@ +# +char C20[] = {"@(#)c20.c 1.27 78/10/23 14:06:38"}; /* sccs ident */ +/* + * C object code improver + */ + +#include "c2.h" +#include +#include + +char _sibuf[BUFSIZ], _sobuf[BUFSIZ]; +int ioflag; +int isn = 20000; +struct optab *oplook(); +struct optab *getline(); + +struct node * +alloc(an) +{ + register int n; + register char *p; + + n = an; + n++; + n &= ~01; + if (lasta+n >= lastr) { + if (sbrk(2000) == -1) { + fprintf(stderr, "Optimizer: out of space\n"); + exit(1); + } + lastr += 2000; + } + p = lasta; + lasta += n; + return(p); +} + +main(argc, argv) +char **argv; +{ + register int niter, maxiter, isend; + int nflag,infound; + + nflag = 0; infound=0; argc--; argv++; + while (argc>0) {/* get flags */ + if (**argv=='+') debug++; + else if (**argv=='-') { + if ((*argv)[1]=='i') ioflag++; else nflag++; + } else if (infound==0) { + if (freopen(*argv, "r", stdin) ==NULL) { + fprintf(stderr,"C2: can't find %s\n", *argv); + exit(1); + } + setbuf(stdin,_sibuf); ++infound; + } else if (freopen(*argv, "w", stdout) ==NULL) { + fprintf(stderr,"C2: can't create %s\n", *argv); + exit(1); + } + setbuf(stdout,_sobuf); + argc--; argv++; + } + lasta = lastr = sbrk(2); + opsetup(); + lasta = firstr = lastr = alloc(0); + maxiter = 0; + do { + isend = input(); + niter = 0; + bmove(); + do { + refcount(); + do { + iterate(); + clearreg(); + niter++; + } while (nchange); + comjump(); + rmove(); + } while (nchange || jumpsw()); + addsob(); + output(); + if (niter > maxiter) + maxiter = niter; + lasta = firstr; + } while (isend); + if (nflag) { + fprintf(stderr,"%d iterations\n", maxiter); + fprintf(stderr,"%d jumps to jumps\n", nbrbr); + fprintf(stderr,"%d inst. after jumps\n", iaftbr); + fprintf(stderr,"%d jumps to .+1\n", njp1); + fprintf(stderr,"%d redundant labels\n", nrlab); + fprintf(stderr,"%d cross-jumps\n", nxjump); + fprintf(stderr,"%d code motions\n", ncmot); + fprintf(stderr,"%d branches reversed\n", nrevbr); + fprintf(stderr,"%d redundant moves\n", redunm); + fprintf(stderr,"%d simplified addresses\n", nsaddr); + fprintf(stderr,"%d loops inverted\n", loopiv); + fprintf(stderr,"%d redundant jumps\n", nredunj); + fprintf(stderr,"%d common seqs before jmp's\n", ncomj); + fprintf(stderr,"%d skips over jumps\n", nskip); + fprintf(stderr,"%d sob's added\n", nsob); + fprintf(stderr,"%d redundant tst's\n", nrtst); + fprintf(stderr,"%d jump on bit\n", nbj); + fprintf(stderr,"%d field operations\n", nfield); + fprintf(stderr,"%dK core\n", ((unsigned)lastr+01777) >> 10); + } + fflush(stdout); exit(0); +} + +input() +{ + register struct node *p, *lastp; + struct optab *op; register char *cp1; + static struct optab F77JSW = {".long", T(JSW,1)}; + + lastp = &first; + for (;;) { + top: + op = getline(); + if (debug && op==0) fprintf(stderr,"? %s\n",line); + switch (op->opcode&0377) { + + case LABEL: + p = alloc(sizeof first); + if (line[0] == 'L') { + p->combop = LABEL; + p->labno = getnum(line+1); + if (isn<=p->labno) isn=1+p->labno; + p->code = 0; + } else { + p->combop = DLABEL; + p->labno = 0; + p->code = copy(line); + } + break; + + case LGEN: + if (*curlp!='L') goto std; + op= &F77JSW; + case JBR: + if (op->opcode==T(JBR,RET)) goto std; + case CBR: + case JMP: + case JSW: + case SOBGEQ: case SOBGTR: case AOBLEQ: case AOBLSS: case ACB: + p = alloc(sizeof first); + p->combop = op->opcode; p->code=0; cp1=curlp; + if (*cp1!='L' || 0==(p->labno = getnum(cp1+1))) {/* jbs, etc.? */ + while (*cp1++); while (*--cp1!=',' && cp1!=curlp); + if (cp1==curlp || *++cp1!='L' || 0==(p->labno=getnum(cp1+1))) + p->labno = 0; + else *--cp1=0; + p->code = copy(curlp); + } + if (isn<=p->labno) isn=1+p->labno; + break; + + case MOVA: + p=alloc(sizeof first); + p->combop=op->opcode; p->code=0; cp1=curlp; + if (*cp1++=='L') { + while (*cp1++!=','); *--cp1=0; + if (0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1); + else {*cp1=','; p->code=copy(curlp);} + } else p->code=copy(--cp1); + break; + + case SET: + printf("%s\n",line); goto top; + + case BSS: + case DATA: + for (;;) { + printf("%s%c",line,(op->opcode==LABEL ? ':' : '\n')); + if (op->opcode==TEXT) goto top; + if (END==(op=getline())->opcode) {/* dangling .data is bad for you */ + printf(".text\n"); + break; + } + } + + std: + default: + p = alloc(sizeof first); + p->combop = op->opcode; + p->labno = 0; + p->code = copy(curlp); + break; + + } + p->forw = 0; + p->back = lastp; + p->pop = op; + lastp->forw = p; + lastp = p; + p->ref = 0; + if (p->op==CASE) { + char *lp; int ncase; + lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1); + if (LABEL!=(getline())->opcode) abort(-2); + do { + if (WGEN!=(getline())->opcode) abort(-3); + p = alloc(sizeof first); p->combop = JSW; p->code = 0; + lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1); + if (isn<=p->labno) isn=1+p->labno; + p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p; + p->ref = 0; p->pop=0; + } while (--ncase>=0); + } + if (op->opcode==EROU) + return(1); + if (op->opcode==END) + return(0); + } +} + +struct optab * +getline() +{ + register char *lp; + register c; + static struct optab OPLABEL={"",LABEL}; + static struct optab OPEND={"",END}; + + lp = line; + while (EOF!=(c=getchar()) && isspace(c)); + while (EOF!=c) { + if (c==':') { + *lp++ = 0; + return(&OPLABEL); + } + if (c=='\n') { + *lp++ = 0; + return(oplook()); + } + *lp++ = c; + c = getchar(); + } + *lp++ = 0; + return(&OPEND); +} + +long +getnum(p) +register char *p; +{ + register c; int neg; register long n; + + n = 0; neg=0; if (*p=='-') {++neg; ++p;} + while (isdigit(c = *p++)) { + c -= '0'; n *= 10; if (neg) n -= c; else n += c; + } + if (*--p != 0) + return(0); + return(n); +} + +output() +{ + register struct node *t; + int casebas; + + t = &first; + while (t = t->forw) switch (t->op) { + + case END: + return; + + case LABEL: + printf("L%d:", t->labno); + continue; + + case DLABEL: + printf("%s:", t->code); + continue; + + case CASE: + casebas=0; + + default: std: + if (t->pop==0) {/* must find it */ + register struct optab *p; + for (p=optab; p->opstring[0]; ++p) + if (p->opcode==t->combop) {t->pop=p; break;} + } + printf("%s", t->pop->opstring); + if (t->code) printf("\t%s", t->code); + if (t->labno!=0) printf("%cL%d\n", + (t->code ? ',' : '\t'), + t->labno); + else printf("\n"); + continue; + + case MOVA: + if (t->labno==0) goto std; + printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code); + continue; + + case JSW: + if (t->subop!=0) {/* F77JSW */ + printf(".long\tL%d\n",t->labno); continue; + } + if (casebas==0) printf("L%d:\n",casebas=isn++); + printf(".word L%d-L%d\n", t->labno, casebas); + continue; + + } +} + +char * +copy(ap) +char *ap; +{ + register char *p, *np; + char *onp; + register n; + int na; + + na = nargs(); + p = ap; + n = 0; + if (*p==0) + return(0); + do + n++; + while (*p++); + if (na>1) { + p = (&ap)[1]; + while (*p++) + n++; + } + onp = np = alloc(n); + p = ap; + while (*np++ = *p++); + if (na>1) { + p = (&ap)[1]; + np--; + while (*np++ = *p++); + } + return(onp); +} + +#define OPHS 560 +struct optab *ophash[OPHS]; + +opsetup() +{ + register struct optab *optp, **ophp; + register int i,t; + + for(i=NREG+5;--i>=0;) regs[i]=alloc(20); + for (optp = optab; optp->opstring[0]; optp++) { + t=7; i=0; while (--t>=0) i+= i+optp->opstring[t]; + ophp = &ophash[i % OPHS]; + while (*ophp++) { +/* fprintf(stderr,"\ncollision: %d %s %s", +/* ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring); +*/ + if (ophp > &ophash[OPHS]) + ophp = ophash; + } + *--ophp = optp; + } +} + +struct optab * +oplook() +{ + register struct optab *optp,**ophp; + register char *p,*p2; + register int t; + char tempop[20]; + static struct optab OPNULL={"",0}; + + for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p; + while (isspace(*p2)) ++p2; curlp=p2; + t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS]; + while (optp = *ophp) { + if (equstr(tempop,optp->opstring)) return(optp); + if ((++ophp) >= &ophash[OPHS]) ophp = ophash; + } + curlp = line; + return(&OPNULL); +} + +refcount() +{ + register struct node *p, *lp; + struct node *labhash[LABHS]; + register struct node **hp; + + for (hp = labhash; hp < &labhash[LABHS];) + *hp++ = 0; + for (p = first.forw; p!=0; p = p->forw) + if (p->op==LABEL) { + labhash[p->labno % LABHS] = p; + p->refc = 0; + } + for (p = first.forw; p!=0; p = p->forw) { + if (p->op==JBR || p->op==CBR || p->op==JSW + || p->op==SOBGEQ || p->op==SOBGTR || p->op==AOBLEQ || p->op==AOBLSS + || p->op==ACB || (p->op==MOVA && p->labno!=0)) { + p->ref = 0; + lp = labhash[p->labno % LABHS]; + if (lp==0 || p->labno!=lp->labno) + for (lp = first.forw; lp!=0; lp = lp->forw) { + if (lp->op==LABEL && p->labno==lp->labno) + break; + } + if (lp) { + hp = nonlab(lp)->back; + if (hp!=lp) { + p->labno = hp->labno; + lp = hp; + } + p->ref = lp; + lp->refc++; + } + } + } + for (p = first.forw; p!=0; p = p->forw) + if (p->op==LABEL && p->refc==0 + && (lp = nonlab(p))->op && lp->op!=JSW) + decref(p); +} + +iterate() +{ + register struct node *p, *rp, *p1; + + nchange = 0; + for (p = first.forw; p!=0; p = p->forw) { + if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { + rp = nonlab(p->ref); + if (rp->op==JBR && rp->labno && p->labno!=rp->labno) { + nbrbr++; + p->labno = rp->labno; + decref(p->ref); + rp->ref->refc++; + p->ref = rp->ref; + nchange++; + } + } + if (p->op==CBR && (p1 = p->forw)->combop==JBR) {/* combop: RET problems */ + rp = p->ref; + do + rp = rp->back; + while (rp->op==LABEL); + if (rp==p1) { + decref(p->ref); + p->ref = p1->ref; + p->labno = p1->labno; + p1->forw->back = p; + p->forw = p1->forw; + p->subop = revbr[p->subop]; + p->pop=0; + nchange++; + nskip++; + } + } + if (p->op==JBR || p->op==JMP) { + while (p->forw && p->forw->op!=LABEL && p->forw->op!=DLABEL + && p->forw->op!=EROU && p->forw->op!=END + && p->forw->op!=ALIGN + && p->forw->op!=0 && p->forw->op!=DATA) { + nchange++; + iaftbr++; + if (p->forw->ref) + decref(p->forw->ref); + p->forw = p->forw->forw; + p->forw->back = p; + } + rp = p->forw; + while (rp && rp->op==LABEL) { + if (p->ref == rp) { + p->back->forw = p->forw; + p->forw->back = p->back; + p = p->back; + decref(rp); + nchange++; + njp1++; + break; + } + rp = rp->forw; + } + xjump(p); + p = codemove(p); + } + } +} + +xjump(p1) +register struct node *p1; +{ + register struct node *p2, *p3; + int nxj; + + nxj = 0; + if ((p2 = p1->ref)==0) + return(0); + for (;;) { + while ((p1 = p1->back) && p1->op==LABEL); + while ((p2 = p2->back) && p2->op==LABEL); + if (!equop(p1, p2) || p1==p2) + return(nxj); + p3 = insertl(p2); + p1->combop = JBR; + p1->pop=0; + p1->ref = p3; + p1->labno = p3->labno; + p1->code = 0; + nxj++; + nxjump++; + nchange++; + } +} + +struct node * +insertl(op) +register struct node *op; +{ + register struct node *lp; + + if (op->op == LABEL) { + op->refc++; + return(op); + } + if (op->back->op == LABEL) { + op = op->back; + op->refc++; + return(op); + } + lp = alloc(sizeof first); + lp->combop = LABEL; + lp->labno = isn++; + lp->ref = 0; + lp->code = 0; + lp->refc = 1; + lp->back = op->back; + lp->forw = op; + op->back->forw = lp; + op->back = lp; + return(lp); +} + +struct node * +codemove(ap) +struct node *ap; +{ + register struct node *p1, *p2, *p3; + struct node *t, *tl; + int n; + + p1 = ap; + if (p1->op!=JBR || (p2 = p1->ref)==0) + return(p1); + while (p2->op == LABEL) + if ((p2 = p2->back) == 0) + return(p1); + if (p2->op!=JBR && p2->op!=JMP) + goto ivloop; + p2 = p2->forw; + p3 = p1->ref; + while (p3) { + if (p3->op==JBR || p3->op==JMP) { + if (p1==p3) + return(p1); + ncmot++; + nchange++; + p1->back->forw = p2; + p1->forw->back = p3; + p2->back->forw = p3->forw; + p3->forw->back = p2->back; + p2->back = p1->back; + p3->forw = p1->forw; + decref(p1->ref); + return(p2); + } else + p3 = p3->forw; + } + return(p1); +ivloop: + if (p1->forw->op!=LABEL) + return(p1); + p3 = p2 = p2->forw; + n = 16; + do { + if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) + return(p1); + } while (p3->op!=CBR || p3->labno!=p1->forw->labno); + do + if ((p1 = p1->back) == 0) + return(ap); + while (p1!=p3); + p1 = ap; + tl = insertl(p1); + p3->subop = revbr[p3->subop]; + p3->pop=0; + decref(p3->ref); + p2->back->forw = p1; + p3->forw->back = p1; + p1->back->forw = p2; + p1->forw->back = p3; + t = p1->back; + p1->back = p2->back; + p2->back = t; + t = p1->forw; + p1->forw = p3->forw; + p3->forw = t; + p2 = insertl(p1->forw); + p3->labno = p2->labno; + p3->ref = p2; + decref(tl); + if (tl->refc<=0) + nrlab--; + loopiv++; + nchange++; + return(p3); +} + +comjump() +{ + register struct node *p1, *p2, *p3; + + for (p1 = first.forw; p1!=0; p1 = p1->forw) + if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1 || p1->subop==RET)) + for (p3 = p1->forw; p3!=0; p3 = p3->forw) + if (p3->op==JBR && p3->ref == p2) + backjmp(p1, p3); +} + +backjmp(ap1, ap2) +struct node *ap1, *ap2; +{ + register struct node *p1, *p2, *p3; + + p1 = ap1; + p2 = ap2; + for(;;) { + while ((p1 = p1->back) && p1->op==LABEL); + p2 = p2->back; + if (equop(p1, p2)) { + p3 = insertl(p1); + p2->back->forw = p2->forw; + p2->forw->back = p2->back; + p2 = p2->forw; + decref(p2->ref); + p2->combop = JBR; /* to handle RET */ + p2->pop=0; + p2->labno = p3->labno; + p2->ref = p3; + nchange++; + ncomj++; + } else + return; + } +} diff --git a/usr/src/cmd/c2/c21.c b/usr/src/cmd/c2/c21.c new file mode 100644 index 0000000000..00b97409dc --- /dev/null +++ b/usr/src/cmd/c2/c21.c @@ -0,0 +1,955 @@ +# +char C21[] = {"@(#)c21.c 1.59 79/01/20 11:07:52"}; /* sccs ident */ +/* + * C object code improver-- second part + */ + +#include "c2.h" +#include +#include + +#define NUSE 6 +int ioflag; +int biti[NUSE] = {1,2,4,8,16,32}; +int bitsize[4] = {0,8,16,32}; /* index by type codes */ +int pos,siz; long f; /* for bit field communication */ +struct node *uses[NUSE]; /* for backwards flow analysis */ +char *lastrand; /* last operand of instruction */ +struct node *bflow(); +struct node *bicopt(); +char *findcon(); + +redun3(p,split) register struct node *p; int split; { +/* check for 3 addr instr which should be 2 addr */ + if (OP3==((p->subop>>4)&0xF)) { + if (split) splitrand(p); + if (equstr(regs[RT1],regs[RT3]) + && (p->op==ADD || p->op==MUL || p->op==BIS || p->op==XOR)) { + register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t; + } + if (equstr(regs[RT2],regs[RT3])) { + p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0; + lastrand=regs[RT2]; *regs[RT3]=0; return(1); + } + } return(0); +} + +bmove() { + register struct node *p, *lastp; register char *cp1,*cp2; register int r; + refcount(); + for (p=lastp= &first; 0!=(p=p->forw); lastp=p); + clearreg(); clearuse(); + for (p=lastp; p!= &first; p=p->back) { + if (debug) { + for (r=NUSE;--r>=0;) if (uses[r]) printf("%d: %s\n",r,uses[r]->code); + printf("-\n"); + } + if (OP3==((p->subop>>4)&0xF) && 0!=redun3(p,1)) {newcode(p); redunm++;} + switch (p->op) { + case LABEL: case DLABEL: + if (p->back && p->back->op==JBR && p->back->subop!=RET) + for (r=NUSE; --r>=0;) if (uses[r] && regs[r][0]!= -1) + p->ref=(struct node *) (((int)p->ref)|biti[r]); + case CALLS: case 0: + clearuse(); break; + case SUB: + if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; + if (*cp1++!='$') goto std; splitrand(p); + if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ + char buf[50]; cp2=buf; *cp2++='-'; + cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; + cp1="(fp),"; while (*cp2++= *cp1++); --cp2; + cp1=regs[RT3]; while (*cp2++= *cp1++); + p->code=copy(buf); p->combop=T(MOVA,LONG); p->pop=0; + } else if (*cp1++=='-' && 0<=(r=getnum(cp1))) { + p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1; + } goto std; + case ADD: + if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; + if (*cp1++!='$') goto std; splitrand(p); + if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ + cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; + cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=','; + p->combop=T(MOVA,LONG); p->pop=0; + } else if (*cp1++=='-' && 0<=(r=getnum(cp1))) { + p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1; + } + case CASE: + default: std: + p=bflow(p); break; + case JBR: + if (p->subop==RET) {uses[0]=p; regs[0][0]= -1; break;} + else if (p->ref->ref!=0) for (r=NUSE;--r>=0;) + if (biti[r] & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;} + case CBR: case JMP: case EROU: case JSW: + case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ; + } + } +} + +rmove() +{ + register struct node *p, *lastp; + register int r; + int r1; + + clearreg(); + for (p=first.forw; p!=0; p = p->forw) { + lastp=p; + if (debug) { + for (r=0; r>4, regs[r]+1); + } + printf("-\n"); + } + switch (p->op) { + + case CVT: + splitrand(p); goto mov; + + case MOV: + splitrand(p); + if ((r = findrand(regs[RT1],p->subop)) >= 0) { + if (r == isreg(regs[RT2]) && p->forw->op!=CBR) { + delnode(p); redunm++; break; + } + } + mov: + repladdr(p); + r = isreg(regs[RT1]); + r1 = isreg(regs[RT2]); + dest(regs[RT2],p->subop); + if (r >= 0) + if (r1 >= 0) savereg(r1, regs[r]+1, p->subop); + else savereg(r, regs[RT2], p->subop); + else + if (r1 >= 0) savereg(r1, regs[RT1], p->subop); + else setcon(regs[RT1], regs[RT2], p->subop); + break; + +/* .rx,.wx */ + case COM: + case NEG: +/* .rx,.wx or .rx,.rx,.wx */ + case ADD: + case SUB: + case BIC: + case BIS: + case XOR: + case MUL: + case DIV: + case ASH: + case MOVZ: +/* .rx,.rx,.rx,.wx */ + case EXTV: + case EXTZV: + case INSV: + splitrand(p); + repladdr(p); + dest(lastrand,p->subop); + if (p->op==INSV) ccloc[0]=0; + break; + +/* .mx or .wx */ + case CLR: + case INC: + case DEC: + splitrand(p); + dest(lastrand,p->subop); + if (p->op==CLR) + if ((r = isreg(regs[RT1])) >= 0) + savereg(r, "$0", p->subop); + else + setcon("$0", regs[RT1], p->subop); + break; + +/* .rx */ + case TST: + case PUSH: + splitrand(p); + lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */ + repladdr(p); + if (p->op==TST && equstr(lastrand=regs[RT1], ccloc+1) + && equtype(ccloc[0],p->subop) &&!source(lastrand)) { + delnode(p); p = p->back; nrtst++; nchange++; + } + setcc(lastrand,p->subop); + break; + +/* .rx,.rx,.rx */ + case CASE: +/* .rx,.rx */ + case CALLS: + case CMP: + case BIT: + splitrand(p); + /* fool repladdr into doing right number of operands */ + if (p->op!=CASE) lastrand=regs[RT3]; else lastrand=regs[RT4]; + repladdr(p); + if (p->op==CALLS) clearreg(); + if (p->op==BIT) bitopt(p); + ccloc[0]=0; break; + + case CBR: + if (p->subop>=JBC) {/* 2 operands can be optimized */ + splitrand(p); lastrand=regs[RT3]; repladdr(p); + } + ccloc[0] = 0; + break; + + case JBR: + redunbr(p); + +/* .wx,.bb */ + case SOB: + + default: + clearreg(); + } + } +} + +char * +byondrd(p) register struct node *p; { +/* return pointer to register which is "beyond last read/modify operand" */ + if (OP2==(p->subop>>4)) return(regs[RT3]); + switch (p->op) { + case PUSHA: + case TST: case INC: case DEC: case PUSH: return(regs[RT2]); + case BIT: case CMP: case CALLS: return(regs[RT3]); + case CASE: return(regs[RT4]); + } + return(lastrand); +} + +struct node * +bflow(p) register struct node *p; { + register char *cp1,*cp2,**preg; register int r; + splitrand(p); + if (0<=(r=isreg(lastrand)) && rop!=PUSH && + uses[r]==p->forw && p->subop && equtype(regs[r][0],p->subop)) { + if (regs[r][1]!=0) {/* send directly to destination */ + if (p->op==INC || p->op==DEC) { + if (p->op==DEC) p->op=SUB; else p->op=ADD; + p->subop=(OP2<<4)+(p->subop&0xF); /* use 2 now, convert to 3 later */ + p->pop=0; + cp1=lastrand; cp2=regs[RT2]; while (*cp2++= *cp1++); /* copy reg */ + cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; + } + cp1=regs[r]+1; cp2=lastrand; + if (OP2==(p->subop>>4)) {/* use 3 operand form of instruction */ + p->pop=0; + p->subop += (OP3-OP2)<<4; lastrand=cp2=regs[RT3]; + } + while (*cp2++= *cp1++); + if (p->op==MOVA && p->forw->op==PUSH) { + p->op=PUSHA; *regs[RT2]=0; p->pop=0; + } + delnode(p->forw); + redun3(p,0); + newcode(p); redunm++; uses[r]=0; *(short *)(regs[r])=0; + } else if (p->op==MOV && p->forw->op!=EXTV && p->forw->op!=EXTZV) { + /* superfluous fetch */ + int nmatch; + char src[20]; cp2=src; cp1=regs[RT1]; while (*cp2++= *cp1++); + splitrand(p->forw); lastrand=byondrd(p->forw); nmatch=0; + for (preg=regs+RT1;*preg!=lastrand;preg++) if (r==isreg(*preg)) { + cp2= *preg; cp1=src; while (*cp2++= *cp1++); ++nmatch; + } + if (nmatch==1) { + if (OP2==(p->forw->subop>>4) && equstr(src,regs[RT2])) { + p->forw->pop=0; + p->forw->subop += (OP3-OP2)<<4; cp1=regs[RT3]; + *cp1++='r'; *cp1++=r+'0'; *cp1=0; + } + delnode(p); p=p->forw; + redun3(p,0); + newcode(p); redunm++; uses[r]=0; *(short *)(regs[r])=0; + } + } + } + /* adjust 'lastrand' past any 'read' or 'modify' operands. */ + lastrand=byondrd(p); + /* a 'write' clobbers the register. */ + if (0<=(r=isreg(lastrand)) && rsubop>>4) && 0<=(r=isreg(regs[RT2])) && rop==BIC) {p=bicopt(p); splitrand(p); lastrand=byondrd(p);} + if (p->op==BIS) bixprep(p,JBSS); + /* now look for 'read' or 'modify' (read & write) uses */ + preg=regs+RT1; + while (*(cp1= *preg++)) { + /* check for r */ + if (lastrand!=cp1 && 0<=(r=isreg(cp1)) && rsubop; + if (p->op==MOV || p->op==PUSH) { + if (p->op==PUSH) cp1="-(sp)"; else cp1=regs[RT2]; + while (*cp2++= *cp1++); + } else *cp2++=0; + continue; + } + /* check for (r),(r)+,-(r),[r] */ + do if (*cp1=='(' || *cp1=='[') {/* get register number */ + char t; + cp2= ++cp1; while (*++cp1!=')' && *cp1!=']'); t= *cp1; *cp1=0; + if (0<=(r=isreg(cp2)) && rcombop==T(MOV,LONG)) { + if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { + cp1=p->code; while (*cp1++!=','); p->code= --cp1; + } + p->combop=T(MOVA,LONG); ++p->code; p->pop=0; + } else if (p->combop==T(PUSH,LONG)) { + p->combop=T(PUSHA,LONG); ++p->code; p->pop=0; + } else if ((p->combop&0xFFFF)==T(ADD,U(LONG,OP3)) + && 0<=(r=isreg(regs[RT2]))) { + cp1=cp2=p->code; ++cp1; + do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; + do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; + if (!equstr(regs[RT3],"-(sp)")) p->combop=T(MOVA,BYTE); + else {p->combop=T(PUSHA,BYTE); *cp2=0;} + if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;} + p->pop=0; + } + } + return(p); +} + +ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */ + register int log; + if (n==0 || n&(n-1)) return(-1); log=0; + for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);} +} + +bitopt(p) register struct node *p; { + /* change "bitx $,a" followed by JEQ or JNE + /* into JBC or JBS. watch out for I/O registers. (?) + /* assumes that 'splitrand' has already been called. + */ + register char *cp1,*cp2; int b; + cp1=regs[RT1]; cp2=regs[RT2]; + if (*cp1++!='$' || !okio(cp2) || p->forw->op!=CBR || p->forw->subop&-2 || + 0>(b=ispow2(getnum(cp1))) || p->subop!=BYTE && indexa(cp2)) return; + if (b>=bitsize[p->subop]) {/* you dummy! */ + if (source(cp2)) {/* side effect: auto increment or decrement */ + p->pop=0; + p->op=TST; --cp1; while (*cp1++= *cp2++); + regs[RT2][0]=0; newcode(p); + } else delnode(p); + p = p->forw; + if (p->subop==JEQ) {p->combop=JBR; p->pop=0;} + else delnode(p); + nchange++; nbj++; return; + } + if (cp1=p->forw->code) {/* destination is not an internal label */ + cp2=regs[RT3]; while (*cp2++= *cp1++); + } + if (b==0 && (p->subop==LONG || !indexa(regs[RT2]))) {/* JLB optimization, ala BLISS */ + cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); + cp2=regs[RT2]; cp1=regs[RT3]; while (*cp2++= *cp1++); + *(regs[RT3])=0; p->forw->subop += JLBC-JBC; + p->forw->pop=0; + } else { + cp1=regs[RT1]+1; + if (b>9) *cp1++= b/10 +'0'; *cp1++= b%10 +'0'; *cp1=0; /* $ */ + } + nbj++; newcode(p); p->combop = p->forw->combop+((JBC-JEQ)<<8); + p->labno = p->forw->labno; delnode(p->forw); + p->pop=0; +} + +isfield(n) register long n; {/* -1 -> no; else -> position of low bit */ + register int pos; register long t; + t= ((n-1)|n) +1; + if (n!=0 && (0==t || 0==n || 0<=ispow2(t))) { + pos=0; while(!(n&1)) {n >>= 1; ++pos;} return(pos); + } else return(-1); +} + +bixprep(p,bix) register struct node *p; { +/* initial setup, single-bit checking for bisopt, bicopt. +/* return: 0->don't bother any more; 1->worthwhile trying +*/ + register char *cp1,*cp2; + splitrand(p); cp1=regs[RT1]; cp2=regs[RT2]; + if (*cp1++!='$' || 0>(pos=isfield(f=getnum(cp1))) + || !okio(cp2) || indexa(cp2) || source(cp2) || !okio(lastrand)) return(0); + f |= f-1; if (++f==0) siz=32-pos; else siz=ispow2(f)-pos; + if (siz==1 && pos>5 && (p->subop>>4)==OP2 && (p->subop&0xF)!=BYTE + && possubop&0xF]) { + p->ref = insertl(p->forw); p->combop = CBR | (bix<<8); + p->pop=0; + p->labno = p->ref->labno; + if (pos>9) {*cp1++= pos/10 +'0'; pos %= 10;} + *cp1++=pos+'0'; *cp1=0; newcode(p); nbj++; return(0); + } + return(1); +} + + +struct node * +bicopt(p) register struct node *p; { +/* use field operations or MOVZ if possible. done as part of 'bflow'. +*/ + register char *cp1,*cp2; int r; + char src[50]; + if (!bixprep(p,JBCC)) return(p); + if (f<=0) {/* the BIC isolates low order bits */ + siz=pos; pos=0; + if ((p->subop&0xF)==LONG && *(regs[RT2])!='$') {/* result of EXTZV is long */ + /* save source of BICL in 'src' */ + cp1=regs[RT2]; cp2=src; while (*cp2++= *cp1++); + if (p->back->op==ASH) {/* try for more */ + splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT3]; + if (*cp1++=='$' && *(regs[RT2])!='$' && !indexa(regs[RT2]) + && 0>(f=getnum(cp1)) && equstr(src,cp2) + && 0<=(r=isreg(cp2)) && rback); + } + } + if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */ + splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2]; + if (equstr(src,cp2) && okio(cp1) && !indexa(cp1) + && 0<=(r=isreg(cp2)) && rback->subop&0xF]>=(pos+siz) + && bitsize[p->back->subop>>4]>=(pos+siz)) {/* good CVT */ + cp1=regs[RT1]; cp2=src; while (*cp2++= *cp1++); + delnode(p->back); + } + } + /* 'pos', 'siz' known; source of field is in 'src' */ + splitrand(p); /* retrieve destination of BICL */ + if (siz==8 && pos==0) { + p->combop = T(MOVZ,U(BYTE,LONG)); + sprintf(line,"%s,%s",src,lastrand); + } else { + p->combop = T(EXTZV,LONG); + sprintf(line,"$%d,$%d,%s,%s",pos,siz,src,lastrand); + } + p->pop=0; + p->code = copy(line); nfield++; return(p); + }/* end EXTZV possibility */ + }/* end low order bits */ +/* unfortunately, INSV clears the condition codes, thus cannot be used */ +/* else {/* see if BICL2 of positive field should be INSV $0 */ +/* if (p->subop==(LONG | (OP2<<4)) && 6<=(pos+siz)) { +/* p->combop = INSV; +/* sprintf(line,"$0,$%d,$%d,%s",pos,siz,lastrand); +/* p->code = copy(line); nfield++; return(p); +/* } +/* } +*/ + return(p); +} + +jumpsw() +{ + register struct node *p, *p1; + register t; + int nj; + + t = 0; + nj = 0; + for (p=first.forw; p!=0; p = p->forw) + p->seq = ++t; + for (p=first.forw; p!=0; p = p1) { + p1 = p->forw; + if (p->op == CBR && p1->op==JBR && p->ref && p1->ref + && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) { + if (p->ref==p1->ref) + continue; + p->subop = revbr[p->subop]; + p->pop=0; + t = p1->ref; + p1->ref = p->ref; + p->ref = t; + t = p1->labno; + p1->labno = p->labno; + p->labno = t; + nrevbr++; + nj++; + } + } + return(nj); +} + +addsob() +{ + register struct node *p, *p1, *p2, *p3; + + for (p = &first; (p1 = p->forw)!=0; p = p1) { + if (p->combop==T(DEC,LONG) && p1->op==CBR) { + if (abs(p->seq - p1->ref->seq) > 12) continue; + if (p1->subop==JGE || p1->subop==JGT) { + if (p1->subop==JGE) p->combop=SOBGEQ; else p->combop=SOBGTR; + p->pop=0; + p->labno = p1->labno; delnode(p1); nsob++; + } + } else if (p->combop==T(INC,LONG)) { + if (p1->op==LABEL && p1->refc==1 && p1->forw->combop==T(CMP,LONG) + && (p2=p1->forw->forw)->combop==T(CBR,JLE) + && (p3=p2->ref->back)->combop==JBR && p3->ref==p1 + && p3->forw->op==LABEL && p3->forw==p2->ref) { + /* change INC LAB: CMP to LAB: INC CMP */ + p->back->forw=p1; p1->back=p->back; + p->forw=p1->forw; p1->forw->back=p; + p->back=p1; p1->forw=p; + p1=p->forw; + /* adjust beginning value by 1 */ + p2=alloc(sizeof first); p2->combop=T(DEC,LONG); + p2->pop=0; + p2->forw=p3; p2->back=p3->back; p3->back->forw=p2; + p3->back=p2; p2->code=p->code; p2->labno=0; + } + if (p1->combop==T(CMP,LONG) && (p2=p1->forw)->op==CBR) { + register char *cp1,*cp2; + splitrand(p1); if (!equstr(p->code,regs[RT1])) continue; + if (abs(p->seq - p2->ref->seq)>12) {/* outside byte displ range */ + if (p2->subop!=JLE) continue; + p->combop=T(ACB,LONG); + cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */ + cp2=regs[RT2]; cp1="$1"; while (*cp2++= *cp1++); /* increment */ + cp2=regs[RT3]; cp1=p->code; while (*cp2++= *cp1++); /* index */ + p->pop=0; newcode(p); + p->labno = p2->labno; delnode(p2); delnode(p1); nsob++; + } else if (p2->subop==JLE || p2->subop==JLT) { + if (p2->subop==JLE) p->combop=AOBLEQ; else p->combop=AOBLSS; + cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */ + cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */ + p->pop=0; newcode(p); + p->labno = p2->labno; delnode(p2); delnode(p1); nsob++; + } + } + } + } +} + +abs(x) +{ + return(x<0? -x: x); +} + +equop(p1, p2) +register struct node *p1; +struct node *p2; +{ + register char *cp1, *cp2; + + if (p1->combop != p2->combop) + return(0); + if (p1->op>0 && p1->opop==MOVA && p1->labno!=p2->labno) return(0); + cp1 = p1->code; + cp2 = p2->code; + if (cp1==0 && cp2==0) + return(1); + if (cp1==0 || cp2==0) + return(0); + while (*cp1 == *cp2++) + if (*cp1++ == 0) + return(1); + return(0); +} + +delnode(p) register struct node *p; { + p->back->forw = p->forw; + p->forw->back = p->back; +} + +decref(p) +register struct node *p; +{ + if (p && --p->refc <= 0) { + nrlab++; + delnode(p); + } +} + +struct node * +nonlab(ap) +struct node *ap; +{ + register struct node *p; + + p = ap; + while (p && p->op==LABEL) + p = p->forw; + return(p); +} + +clearuse() { + register struct node **i; + for (i=uses+NUSE; i>uses;) *--i=0; +} + +clearreg() { + register short **i; + for (i=regs+NREG; i>regs;) **--i=0; + conloc[0] = 0; ccloc[0] = 0; +} + +savereg(ai, s, type) +register char *s; +{ + register char *p, *sp; + + sp = p = regs[ai]; + if (source(s)) /* side effects in addressing */ + return; + /* if any indexing, must be parameter or local */ + /* indirection (as in "*-4(fp)") is ok, however */ + *p++ = type; + while (*p++ = *s) + if (*s=='[' || *s++=='(' && *s!='a' && *s!='f') {*sp = 0; return;} +} + +dest(s,type) +register char *s; +{ + register int i; + + source(s); /* handle addressing side effects */ + if ((i = isreg(s)) >= 0) { + *(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */ + if (DOUBLE==(type&0xF) || DOUBLE==((type>>4)&0xF)) + *(short *)(regs[i+1]) = 0; /* clobber two at once */ + } + for (i=NREG; --i>=0;) + if (regs[i][1]=='*' && equstr(s, regs[i]+2)) + *(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */ + while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */ + *(short *)(regs[i]) = 0; + if (!natural(s)) {/* wild store, everything except constants vanishes */ + for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0; + conloc[0] = 0; ccloc[0] = 0; + } else setcc(s,type); /* natural destinations set condition codes */ +} + +splitrand(p) struct node *p; { +/* separate operands at commas, set up 'regs' and 'lastrand' */ +register char *p1, *p2; register char **preg; +preg=regs+RT1; +if (p1=p->code) while (*p1) { + lastrand=p2= *preg++; + while (*p1) if (','==(*p2++= *p1++)) {--p2; break;} + *p2=0; +} +while (preg<(regs+RT1+5)) *(*preg++)=0; +} + +compat(have, want) { +register int hsrc, hdst; +if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */ +hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc; +/* last term prevents floats, doubles from satisfying a request for an int */ +return(hsrc>=want && hdst>=want && !((want>=FLOAT) ^ (hdst>=FLOAT))); +} + +equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));} + +findrand(as, type) +char *as; +{ + register char **i; + for (i = regs+NREG; --i>=regs;) { + if (**i && equstr(*i+1, as) && compat(**i,type)) + return(i-regs); + } + return(-1); +} + +isreg(s) +register char *s; +{ + if (*s++!='r' || !isdigit(*s++)) return(-1); + if (*s==0) return(*--s-'0'); + if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0'); + return(-1); +} + +check() +{ + register struct node *p, *lp; + + lp = &first; + for (p=first.forw; p!=0; p = p->forw) { + if (p->back != lp) + abort(-1); + lp = p; + } +} + +source(ap) +char *ap; +{ + register char *p1, *p2; + + p1 = ap; + p2 = p1; + if (*p1==0) + return(0); + while (*p2++ && *(p2-1)!='['); + if (*p1=='-' && *(p1+1)=='(' + || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='(' + || *(p2-2)=='+') { + while (*p1 && *p1++!='r'); + if (isdigit(*p1++)) + if (isdigit(*p1)) *(short *)(regs[10+*p1-'0'])=0; + else *(short *)(regs[*--p1-'0'])=0; + return(1); + } + return(0); +} + +newcode(p) struct node *p; { + register char *p1,*p2,**preg; + preg=regs+RT1; p2=line; + while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';} + *--p2=0; + p->code=copy(line); +} + +repladdr(p) +struct node *p; +{ + register r; + register char *p1, *p2; + char **preg; int nrepl; + + preg=regs+RT1; nrepl=0; + while (lastrand!=(p1= *preg++)) + if (!source(p1) && 0<=(r=findrand(p1,p->subop))) { + *p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0; + nrepl++; nsaddr++; + } + if (nrepl) newcode(p); +} + +/* movedat() +/* { +/* register struct node *p1, *p2; +/* struct node *p3; +/* register seg; +/* struct node data; +/* struct node *datp; +/* +/* if (first.forw == 0) +/* return; +/* datp = &data; +/* for (p1 = first.forw; p1!=0; p1 = p1->forw) { +/* if (p1->op == DATA) { +/* p2 = p1->forw; +/* while (p2 && p2->op!=TEXT) +/* p2 = p2->forw; +/* if (p2==0) +/* break; +/* p3 = p1->back; +/* p1->back->forw = p2->forw; +/* p2->forw->back = p3; +/* p2->forw = 0; +/* datp->forw = p1; +/* p1->back = datp; +/* p1 = p3; +/* datp = p2; +/* } +/* } +/* if (data.forw) { +/* datp->forw = first.forw; +/* first.forw->back = datp; +/* data.forw->back = &first; +/* first.forw = data.forw; +/* } +/* seg = -1; +/* for (p1 = first.forw; p1!=0; p1 = p1->forw) { +/* if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) { +/* if (p1->op == seg || p1->forw&&p1->forw->op==seg) { +/* p1->back->forw = p1->forw; +/* p1->forw->back = p1->back; +/* p1 = p1->back; +/* continue; +/* } +/* seg = p1->op; +/* } +/* } +/* } +*/ + +redunbr(p) +register struct node *p; +{ + register struct node *p1; + register char *ap1; + char *ap2; + + if ((p1 = p->ref) == 0) + return; + p1 = nonlab(p1); + if (p1->op==TST) { + splitrand(p1); + savereg(RT2, "$0", p1->subop); + } else if (p1->op==CMP) + splitrand(p1); + else + return; + if (p1->forw->op==CBR) { + ap1 = findcon(RT1, p1->subop); + ap2 = findcon(RT2, p1->subop); + p1 = p1->forw; + if (compare(p1->subop, ap1, ap2)) { + nredunj++; + nchange++; + decref(p->ref); + p->ref = p1->ref; + p->labno = p1->labno; + p->ref->refc++; + } + } else if (p1->op==TST && equstr(regs[RT1],ccloc+1) && + equtype(ccloc[0],p1->subop)) { + p1=insertl(p1->forw); decref(p->ref); p->ref=p1; + nrtst++; nchange++; + } +} + +char * +findcon(i, type) +{ + register char *p; + register r; + + p = regs[i]; + if (*p=='$') + return(p); + if ((r = isreg(p)) >= 0 && compat(regs[r][0],type)) + return(regs[r]+1); + if (equstr(p, conloc)) + return(conval+1); + return(p); +} + +compare(op, acp1, acp2) +char *acp1, *acp2; +{ + register char *cp1, *cp2; + register n1; + int n2; int sign; + + cp1 = acp1; + cp2 = acp2; + if (*cp1++ != '$' || *cp2++ != '$') + return(0); + n1 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;} + while (isdigit(*cp2)) {n1 *= 10; n1 += (*cp2++ - '0')*sign;} + n2 = n1; + n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;} + while (isdigit(*cp1)) {n1 *= 10; n1 += (*cp1++ - '0')*sign;} + if (*cp1=='+') + cp1++; + if (*cp2=='+') + cp2++; + do { + if (*cp1++ != *cp2) + return(0); + } while (*cp2++); + cp1 = n1; + cp2 = n2; + switch(op) { + + case JEQ: + return(cp1 == cp2); + case JNE: + return(cp1 != cp2); + case JLE: + return(((int)cp1) <= ((int)cp2)); + case JGE: + return(((int)cp1) >= ((int)cp2)); + case JLT: + return(((int)cp1) < ((int)cp2)); + case JGT: + return(((int)cp1) > ((int)cp2)); + case JLO: + return(cp1 < cp2); + case JHI: + return(cp1 > cp2); + case JLOS: + return(cp1 <= cp2); + case JHIS: + return(cp1 >= cp2); + } + return(0); +} + +setcon(cv, cl, type) +register char *cv, *cl; +{ + register char *p; + + if (*cv != '$') + return; + if (!natural(cl)) + return; + p = conloc; + while (*p++ = *cl++); + p = conval; + *p++ = type; + while (*p++ = *cv++); +} + +equstr(p1, p2) +register char *p1, *p2; +{ + do { + if (*p1++ != *p2) + return(0); + } while (*p2++); + return(1); +} + +setcc(ap,type) +char *ap; +{ + register char *p, *p1; + + p = ap; + if (!natural(p)) { + ccloc[0] = 0; + return; + } + p1 = ccloc; + *p1++ = type; + while (*p1++ = *p++); +} + +okio(p) register char *p; {/* 0->probable I/O space address; 1->not */ + if (ioflag && (!natural(p) || 0>getnum(p))) return(0); + return(1); +} + +indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */ + while (*p) if (*p++=='[') return(1); + return(0); +} + +natural(p) +register char *p; +{/* 1->simple local, parameter, global, or register; 0->otherwise */ + if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(' || *p=='$'&&getnum(p+1)) + return(0); + while (*p++); + p--; + if (*--p=='+' || *p==']' || *p==')' && *(p-2)!='a' && *(p-2)!='f') + return(0); + return(1); +} diff --git a/usr/src/cmd/c2/c22.c b/usr/src/cmd/c2/c22.c new file mode 100644 index 0000000000..f3ff3f420e --- /dev/null +++ b/usr/src/cmd/c2/c22.c @@ -0,0 +1,300 @@ +#include "c2.h" +char c22[] = "@(#)c22.c 1.5 78/09/23 16:37:33"; +#define readonly + +readonly char revbr[] = { + JNE, JEQ, JGT, JLT, JGE, JLE, + JNE, JEQ, JHI, JLO, JHIS, JLOS, + JBS, JBC, JLBS, JLBC, JBSC, JBCC, JBSS, JBCS }; + +/* cursed be the preprocessor, whose impotence and stupidity +/* prevented this table being macro-generated from ../as/instrs +*/ + +readonly struct optab optab[] = { +"jbr",JBR, +"jeql",T(CBR,JEQ), +"jneq",T(CBR,JNE), +"jleq",T(CBR,JLE), +"jgeq",T(CBR,JGE), +"jlss",T(CBR,JLT), +"jgtr",T(CBR,JGT), +"jbc",T(CBR,JBC), +"jbs",T(CBR,JBS), +"jlequ",T(CBR,JLOS), +"jgequ",T(CBR,JHIS), +"jlssu",T(CBR,JLO), +"jgtru",T(CBR,JHI), +"jlbc",T(CBR,JLBC), +"jlbs",T(CBR,JLBS), +"jbcc",T(CBR,JBCC), +"jbsc",T(CBR,JBSC), +"jbcs",T(CBR,JBCS), +"jbss",T(CBR,JBSS), +"acbb",T(ACB,BYTE), +"acbd",T(ACB,DOUBLE), +"acbf",T(ACB,FLOAT), +"acbl",T(ACB,LONG), +"acbw",T(ACB,WORD), +"addb2",T(ADD,U(BYTE,OP2)), +"addb3",T(ADD,U(BYTE,OP3)), +"addd2",T(ADD,U(DOUBLE,OP2)), +"addd3",T(ADD,U(DOUBLE,OP3)), +"addf2",T(ADD,U(FLOAT,OP2)), +"addf3",T(ADD,U(FLOAT,OP3)), +"addl2",T(ADD,U(LONG,OP2)), +"addl3",T(ADD,U(LONG,OP3)), +"addw2",T(ADD,U(WORD,OP2)), +"addw3",T(ADD,U(WORD,OP3)), +"aobleq",AOBLEQ, +"aoblss",AOBLSS, +"ashl",T(ASH,LONG), +"ashq",T(ASH,QUAD), +"bbc",T(CBR,JBC), +"bbcc",T(CBR,JBCC), +"bbcci",T(CBR,JBCC), +"bbcs",T(CBR,JBCS), +"bbs",T(CBR,JBS), +"bbsc",T(CBR,JBSC), +"bbss",T(CBR,JBSS), +"bbssi",T(CBR,JBSS), +"bcc",T(CBR,JHIS), +"bcs",T(CBR,JLO), +"beql",T(CBR,JEQ), +"beqlu",T(CBR,JEQ), +"bgeq",T(CBR,JGE), +"bgequ",T(CBR,JHIS), +"bgtr",T(CBR,JGT), +"bgtru",T(CBR,JHI), +"bicb2",T(BIC,U(BYTE,OP2)), +"bicb3",T(BIC,U(BYTE,OP3)), +"bicl2",T(BIC,U(LONG,OP2)), +"bicl3",T(BIC,U(LONG,OP3)), +"bicw2",T(BIC,U(WORD,OP2)), +"bicw3",T(BIC,U(WORD,OP3)), +"bisb2",T(BIS,U(BYTE,OP2)), +"bisb3",T(BIS,U(BYTE,OP3)), +"bisl2",T(BIS,U(LONG,OP2)), +"bisl3",T(BIS,U(LONG,OP3)), +"bisw2",T(BIS,U(WORD,OP2)), +"bisw3",T(BIS,U(WORD,OP3)), +"bitb",T(BIT,BYTE), +"bitl",T(BIT,LONG), +"bitw",T(BIT,WORD), +"blbs",T(CBR,JLBS), +"blbc",T(CBR,JLBC), +"bleq",T(CBR,JLE), +"blequ",T(CBR,JLOS), +"blss",T(CBR,JLT), +"blssu",T(CBR,JLO), +"bneq",T(CBR,JNE), +"bnequ",T(CBR,JNE), +"brb",JBR, +"brw",JBR, +"bvc",T(CBR,0), +"bvs",T(CBR,0), +"callg",CALLS, +"calls",CALLS, +"caseb",T(CASE,BYTE), +"casel",T(CASE,LONG), +"casew",T(CASE,WORD), +"clrb",T(CLR,BYTE), +"clrd",T(CLR,DOUBLE), +"clrf",T(CLR,FLOAT), +"clrl",T(CLR,LONG), +"clrq",T(CLR,QUAD), +"clrw",T(CLR,WORD), +"cmpb",T(CMP,BYTE), +"cmpd",T(CMP,DOUBLE), +"cmpf",T(CMP,FLOAT), +"cmpl",T(CMP,LONG), +"cmpw",T(CMP,WORD), +"cvtbd",T(CVT,U(BYTE,DOUBLE)), +"cvtbf",T(CVT,U(BYTE,FLOAT)), +"cvtbl",T(CVT,U(BYTE,LONG)), +"cvtbw",T(CVT,U(BYTE,WORD)), +"cvtdb",T(CVT,U(DOUBLE,BYTE)), +"cvtdf",T(CVT,U(DOUBLE,FLOAT)), +"cvtdl",T(CVT,U(DOUBLE,LONG)), +"cvtdw",T(CVT,U(DOUBLE,WORD)), +"cvtfb",T(CVT,U(FLOAT,BYTE)), +"cvtfd",T(CVT,U(FLOAT,DOUBLE)), +"cvtfl",T(CVT,U(FLOAT,LONG)), +"cvtfw",T(CVT,U(FLOAT,WORD)), +"cvtlb",T(CVT,U(LONG,BYTE)), +"cvtld",T(CVT,U(LONG,DOUBLE)), +"cvtlf",T(CVT,U(LONG,FLOAT)), +"cvtlw",T(CVT,U(LONG,WORD)), +"cvtrdl",T(CVT,U(DOUBLE,LONG)), +"cvtrfl",T(CVT,U(FLOAT,LONG)), +"cvtwb",T(CVT,U(WORD,BYTE)), +"cvtwd",T(CVT,U(WORD,DOUBLE)), +"cvtwf",T(CVT,U(WORD,FLOAT)), +"cvtwl",T(CVT,U(WORD,LONG)), +"decb",T(DEC,BYTE), +"decl",T(DEC,LONG), +"decw",T(DEC,WORD), +"divb2",T(DIV,U(BYTE,OP2)), +"divb3",T(DIV,U(BYTE,OP3)), +"divd2",T(DIV,U(DOUBLE,OP2)), +"divd3",T(DIV,U(DOUBLE,OP3)), +"divf2",T(DIV,U(FLOAT,OP2)), +"divf3",T(DIV,U(FLOAT,OP3)), +"divl2",T(DIV,U(LONG,OP2)), +"divl3",T(DIV,U(LONG,OP3)), +"divw2",T(DIV,U(WORD,OP2)), +"divw3",T(DIV,U(WORD,OP3)), +"extv",T(EXTV,LONG), +"extzv",T(EXTZV,LONG), +"incb",T(INC,BYTE), +"incl",T(INC,LONG), +"incw",T(INC,WORD), +"insv",T(INSV,-1), +"jmp",JMP, +"mcomb",T(COM,BYTE), +"mcoml",T(COM,LONG), +"mcomw",T(COM,WORD), +"mnegb",T(NEG,BYTE), +"mnegd",T(NEG,DOUBLE), +"mnegf",T(NEG,FLOAT), +"mnegl",T(NEG,LONG), +"mnegw",T(NEG,WORD), +"movab",T(MOVA,BYTE), +"movad",T(MOVA,DOUBLE), +"movaf",T(MOVA,FLOAT), +"moval",T(MOVA,LONG), +"movaq",T(MOVA,QUAD), +"movaw",T(MOVA,WORD), +"movb",T(MOV,BYTE), +"movd",T(MOV,DOUBLE), +"movf",T(MOV,FLOAT), +"movl",T(MOV,LONG), +"movq",T(MOV,QUAD), +"movw",T(MOV,WORD), +"movzbl",T(MOVZ,U(BYTE,LONG)), +"movzbw",T(MOVZ,U(BYTE,WORD)), +"movzwl",T(MOVZ,U(WORD,LONG)), +"mulb2",T(MUL,U(BYTE,OP2)), +"mulb3",T(MUL,U(BYTE,OP3)), +"muld2",T(MUL,U(DOUBLE,OP2)), +"muld3",T(MUL,U(DOUBLE,OP3)), +"mulf2",T(MUL,U(FLOAT,OP2)), +"mulf3",T(MUL,U(FLOAT,OP3)), +"mull2",T(MUL,U(LONG,OP2)), +"mull3",T(MUL,U(LONG,OP3)), +"mulw2",T(MUL,U(WORD,OP2)), +"mulw3",T(MUL,U(WORD,OP3)), +"pushab",T(PUSHA,BYTE), +"pushad",T(PUSHA,DOUBLE), +"pushaf",T(PUSHA,FLOAT), +"pushal",T(PUSHA,LONG), +"pushaq",T(PUSHA,QUAD), +"pushaw",T(PUSHA,WORD), +"pushl",T(PUSH,LONG), +"ret",T(JBR,RET), +"sobgeq",SOBGEQ, +"sobgtr",SOBGTR, +"subb2",T(SUB,U(BYTE,OP2)), +"subb3",T(SUB,U(BYTE,OP3)), +"subd2",T(SUB,U(DOUBLE,OP2)), +"subd3",T(SUB,U(DOUBLE,OP3)), +"subf2",T(SUB,U(FLOAT,OP2)), +"subf3",T(SUB,U(FLOAT,OP3)), +"subl2",T(SUB,U(LONG,OP2)), +"subl3",T(SUB,U(LONG,OP3)), +"subw2",T(SUB,U(WORD,OP2)), +"subw3",T(SUB,U(WORD,OP3)), +"tstb",T(TST,BYTE), +"tstd",T(TST,DOUBLE), +"tstf",T(TST,FLOAT), +"tstl",T(TST,LONG), +"tstw",T(TST,WORD), +"xorb2",T(XOR,U(BYTE,OP2)), +"xorb3",T(XOR,U(BYTE,OP3)), +"xorl2",T(XOR,U(LONG,OP2)), +"xorl3",T(XOR,U(LONG,OP3)), +"xorw2",T(XOR,U(WORD,OP2)), +"xorw3",T(XOR,U(WORD,OP3)), +".globl",EROU, +".text",TEXT, +".data",DATA, +".bss",BSS, +".align",ALIGN, +".word",WGEN, +".long",LGEN, +".set",SET, +".end",END, +"adawi",0, +"addp4",0, +"addp6",0, +"adwc",0, +"ashp",0, +"bicpsw",0, +"bispsw",0, +"bpt",0, +"bsbb",0, +"bsbw",0, +"chme",0, +"chmk",0, +"chms",0, +"chmu",0, +"cmpc3",0, +"cmpc5",0, +"cmpp3",0, +"cmpp4",0, +"cmpv",0, +"cmpzv",0, +"crc",0, +"cvtlp",0, +"cvtpl",0, +"cvttp",0, +"cvtpt",0, +"cvtps",0, +"cvtsp",0, +"divp",0, +"editpc",0, +"ediv",0, +"emodd",0, +"emodf",0, +"emul",0, +"ffc",0, +"ffs",0, +"halt",0, +"index",0, +"insque",0, +"jsb",0, +"ldpctx",0, +"locc",0, +"matchc",0, +"mfpr",0, +"movc3",0, +"movc5",0, +"movp",0, +"movpsl",0, +"movtc",0, +"movtuc",0, +"mtpr",0, +"mulp",0, +"nop",0, +"polyd",0, +"polyf",0, +"popr",0, +"prober",0, +"probew",0, +"pushr",0, +"rei",0, +"remque",0, +"rotl",0, +"rsb",0, +"sbwc",0, +"scanc",0, +"skpc",0, +"spanc",0, +"subp4",0, +"subp6",0, +"svpctx",0, +"xfc",0, +"escd",0, +"esce",0, +"escf",0, + 0, 0}; -- 2.20.1