Bell 32V development
authorTom London <tbl@research.uucp>
Wed, 24 Jan 1979 03:17:30 +0000 (22:17 -0500)
committerTom London <tbl@research.uucp>
Wed, 24 Jan 1979 03:17:30 +0000 (22:17 -0500)
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 <jfr@research.uucp>
Synthesized-from: 32v

usr/src/cmd/c2/c2.h [new file with mode: 0644]
usr/src/cmd/c2/c20.c [new file with mode: 0644]
usr/src/cmd/c2/c21.c [new file with mode: 0644]
usr/src/cmd/c2/c22.c [new file with mode: 0644]

diff --git a/usr/src/cmd/c2/c2.h b/usr/src/cmd/c2/c2.h
new file mode 100644 (file)
index 0000000..6f3798c
--- /dev/null
@@ -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 (file)
index 0000000..2c4d1a4
--- /dev/null
@@ -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 <stdio.h>
+#include <ctype.h>
+
+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 (file)
index 0000000..00b9740
--- /dev/null
@@ -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 <stdio.h>
+#include <ctype.h>
+
+#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<NREG; r++)
+                       if (regs[r][0]) {
+                               r1=regs[r][0];
+                               printf("%d: %d%d %s\n", r, r1&0xF, r1>>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)) && r<NUSE && p->op!=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)) && r<NUSE
+         || OP2==(p->subop>>4) && 0<=(r=isreg(regs[RT2])) && r<NUSE)
+               {uses[r]=0; *(short *)(regs[r])=0;}
+       if (p->op==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)) && r<NUSE && uses[r]==0) {
+                       uses[r]=p; cp2=regs[r]; *cp2++=p->subop;
+                       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)) && r<NUSE && (uses[r]==0 || uses[r]==p)) {
+                               uses[r]=p; regs[r][0]=(*--cp2=='[' ? OPX<<4 : OPB<<4);
+                       }
+                       *cp1=t;
+               } while (*++cp1);
+       }
+       /* pushax or movax possibility? */
+       cp1=regs[RT1];
+       if (*cp1++=='$'
+         && (*cp1=='_' || *cp1=='L' || (*cp1++=='v' && *cp1=='.'))
+         && natural(regs[RT1])) {
+               if (p->combop==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 $<power_of_2>,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; /* $<bit_number> */
+       }
+       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
+         && pos<bitsize[p->subop&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)) && r<NUSE && uses[r]==0) {/* a good ASH */
+                                       pos -= f; cp1=regs[RT2]; cp2=src; while (*cp2++= *cp1++);
+                                       delnode(p->back);
+                               }
+                       }
+                       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)) && r<NUSE && uses[r]==0
+                                 && bitsize[p->back->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->op<MOV)
+               return(0);
+       if (p1->op==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 (file)
index 0000000..f3ff3f4
--- /dev/null
@@ -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};