Research V7 development
authorDennis Ritchie <dmr@research.uucp>
Thu, 3 May 1979 05:53:54 +0000 (00:53 -0500)
committerDennis Ritchie <dmr@research.uucp>
Thu, 3 May 1979 05:53:54 +0000 (00:53 -0500)
Work on file usr/src/cmd/c/c02.c
Work on file usr/src/cmd/c/c20.c
Work on file usr/src/cmd/c/c21.c
Work on file usr/src/cmd/c/table.s

Synthesized-from: v7

usr/src/cmd/c/c02.c [new file with mode: 0644]
usr/src/cmd/c/c20.c [new file with mode: 0644]
usr/src/cmd/c/c21.c [new file with mode: 0644]
usr/src/cmd/c/table.s [new file with mode: 0644]

diff --git a/usr/src/cmd/c/c02.c b/usr/src/cmd/c/c02.c
new file mode 100644 (file)
index 0000000..8decd43
--- /dev/null
@@ -0,0 +1,792 @@
+#
+/* C compiler
+ *
+ *
+ */
+
+#include "c0.h"
+
+/*
+ * Process a single external definition
+ */
+extdef()
+{
+       register o;
+       int sclass, scflag, *cb;
+       struct hshtab typer;
+       register struct hshtab *ds;
+
+       if(((o=symbol())==EOFC) || o==SEMI)
+               return;
+       peeksym = o;
+       sclass = 0;
+       blklev = 0;
+       if (getkeywords(&sclass, &typer)==0) {
+               sclass = EXTERN;
+               if (peeksym!=NAME)
+                       goto syntax;
+       }
+       scflag = 0;
+       if (sclass==DEFXTRN) {
+               scflag++;
+               sclass = EXTERN;
+       }
+       if (sclass!=EXTERN && sclass!=STATIC && sclass!=TYPEDEF)
+               error("Illegal storage class");
+       do {
+               defsym = 0;
+               paraml = 0;
+               parame = 0;
+               if (sclass==TYPEDEF) {
+                       decl1(TYPEDEF, &typer, 0, NULL);
+                       continue;
+               }
+               decl1(EXTERN, &typer, 0, NULL);
+               if ((ds=defsym)==0)
+                       return;
+               funcsym = ds;
+               if ((ds->type&XTYPE)==FUNC) {
+                       if ((peeksym=symbol())==LBRACE || peeksym==KEYW
+                        || (peeksym==NAME && csym->hclass==TYPEDEF)) {
+                               funcblk.type = decref(ds->type);
+                               funcblk.strp = ds->strp;
+                               setinit(ds);
+                               outcode("BS", SYMDEF, sclass==EXTERN?ds->name:"");
+                               cfunc();
+                               return;
+                       }
+                       if (paraml)
+                               error("Inappropriate parameters");
+               } else if ((o=symbol())==COMMA || o==SEMI) {
+                       peeksym = o;
+                       o = (length(ds)+ALIGN) & ~ALIGN;
+                       if (sclass==STATIC) {
+                               setinit(ds);
+                               outcode("BSBBSBN", SYMDEF, "", BSS, NLABEL, ds->name, SSPACE, o);
+                       } else if (scflag)
+                               outcode("BSN", CSPACE, ds->name, o);
+               } else {
+                       if (o!=ASSIGN)
+                               peeksym = o;
+                       setinit(ds);
+                       if (sclass==EXTERN)
+                               outcode("BS", SYMDEF, ds->name);
+                       outcode("BBS", DATA, NLABEL, ds->name);
+                       cb = funcbase;
+                       if (cinit(ds, 1, sclass) & ALIGN)
+                               outcode("B", EVEN);
+                       if (maxdecl > cb)
+                               cb = maxdecl;
+                       funcbase = cb;
+               }
+       } while ((o=symbol())==COMMA);
+       if (o==SEMI)
+               return;
+syntax:
+       if (o==RBRACE) {
+               error("Too many }'s");
+               peeksym = 0;
+               return;
+       }
+       error("External definition syntax");
+       errflush(o);
+       statement();
+}
+
+/*
+ * Process a function definition.
+ */
+cfunc()
+{
+       register int *cb;
+       register sloc;
+
+       sloc = isn;
+       isn =+ 2;
+       outcode("BBS", PROG, RLABEL, funcsym->name);
+       if (proflg)
+               outcode("BN", PROFIL, isn++);
+       cb = curbase;
+       regvar = 5;
+       autolen = STAUTO;
+       maxauto = STAUTO;
+       blklev = 1;
+       declist(ARG);
+       outcode("B", SAVE);
+       funchead();
+       branch(sloc);
+       label(sloc+1);
+       retlab = isn++;
+       blklev = 0;
+       if ((peeksym = symbol()) != LBRACE)
+               error("Compound statement required");
+       statement();
+       outcode("BNB", LABEL, retlab, RETRN);
+       label(sloc);
+       outcode("BN", SETSTK, -maxauto);
+       branch(sloc+1);
+       if (cb < maxdecl)
+               cb = maxdecl;
+       curbase = funcbase = cb;
+}
+
+/*
+ * Process the initializers for an external definition.
+ */
+cinit(anp, flex, sclass)
+struct hshtab *anp;
+{
+       register struct phshtab *np;
+       register nel, ninit;
+       int width, isarray, o, brace, realtype, *cb;
+       struct tnode *s;
+
+       cb = funcbase;
+       np = gblock(sizeof(*np));
+       funcbase = curbase;
+       cpysymb(np, anp);
+       realtype = np->type;
+       isarray = 0;
+       if ((realtype&XTYPE) == ARRAY)
+               isarray++;
+       else
+               flex = 0;
+       width = length(np);
+       nel = 1;
+       /*
+        * If it's an array, find the number of elements.
+        * temporarily modify to look like kind of thing it's
+        * an array of.
+        */
+       if (sclass==AUTO)
+               if (isarray || realtype==STRUCT)
+                       error("No auto. aggregate initialization");
+       if (isarray) {
+               np->type = decref(realtype);
+               np->subsp++;
+               if (width==0 && flex==0)
+                       error("0-length row: %.8s", anp->name);
+               o = length(np);
+               /* nel = ldiv(0, width, o); */
+               nel = (unsigned)width/o;
+               width = o;
+       }
+       brace = 0;
+       if ((peeksym=symbol())==LBRACE && (isarray || np->type!=STRUCT)) {
+               peeksym = -1;
+               brace++;
+       }
+       ninit = 0;
+       do {
+               if ((o=symbol())==RBRACE)
+                       break;
+               peeksym = o;
+               if (o==STRING && realtype==ARRAY+CHAR) {
+                       if (sclass==AUTO)
+                               error("No strings in automatic");
+                       peeksym = -1;
+                       putstr(0, flex?10000:nel);
+                       ninit =+ nchstr;
+                       o = symbol();
+                       break;
+               } else if (np->type==STRUCT) {
+                       strinit(np, sclass);
+               } else if ((np->type&ARRAY)==ARRAY || peeksym==LBRACE)
+                       cinit(np, 0, sclass);
+               else {
+                       initflg++;
+                       s = tree();
+                       initflg = 0;
+                       if (np->hflag&FFIELD)
+                               error("No field initialization");
+                       *cp++ = nblock(np);
+                       *cp++ = s;
+                       build(ASSIGN);
+                       if (sclass==AUTO||sclass==REG)
+                               rcexpr(*--cp);
+                       else if (sclass==ENUMCON) {
+                               if (s->op!=CON)
+                                       error("Illegal enum constant for %.8s", anp->name);
+                               anp->hoffset = s->value;
+                       } else
+                               rcexpr(block(INIT,np->type,NULL,NULL,(*--cp)->tr2));
+               }
+               ninit++;
+               if ((ninit&077)==0 && sclass==EXTERN)
+                       outcode("BS", SYMDEF, "");
+       } while ((o=symbol())==COMMA && (ninit<nel || brace || flex));
+       if (brace==0 || o!=RBRACE)
+               peeksym = o;
+       /*
+        * If there are too few initializers, allocate
+        * more storage.
+        * If there are too many initializers, extend
+        * the declared size for benefit of "sizeof"
+        */
+       if (ninit<nel && sclass!=AUTO)
+               outcode("BN", SSPACE, (nel-ninit)*width);
+       else if (ninit>nel) {
+               if (flex && nel==0) {
+                       np->subsp[-1] = ninit;
+               } else
+                       error("Too many initializers: %.8s", anp->name);
+               nel = ninit;
+       }
+       curbase = funcbase = cb;
+       return(nel*width);
+}
+
+/*
+ * Initialize a structure
+ */
+strinit(np, sclass)
+struct tnode *np;
+{
+       register struct hshtab **mlp;
+       static zerloc;
+       register int o, brace;
+
+       if ((mlp = np->strp->memlist)==NULL) {
+               mlp = &zerloc;
+               error("Undefined structure initialization");
+       }
+       brace = 0;
+       if ((o = symbol()) == LBRACE)
+               brace++;
+       else
+               peeksym = o;
+       do {
+               if ((o=symbol()) == RBRACE)
+                       break;
+               peeksym = o;
+               if (*mlp==0) {
+                       error("Too many structure initializers");
+                       cinit(&funcblk, 0, sclass);
+               } else
+                       cinit(*mlp++, 0, sclass);
+               if (*mlp ==  &structhole) {
+                       outcode("B", EVEN);
+                       mlp++;
+               }
+       } while ((o=symbol())==COMMA && (*mlp || brace));
+       if (sclass!=AUTO && sclass!=REG) {
+               if (*mlp)
+                       outcode("BN", SSPACE, np->strp->ssize - (*mlp)->hoffset);
+               outcode("B", EVEN);
+       }
+       if (o!=RBRACE || brace==0)
+               peeksym = o;
+}
+
+/*
+ * Mark already initialized
+ */
+setinit(anp)
+struct hshtab *anp;
+{
+       register struct hshtab *np;
+
+       np = anp;
+       if (np->hflag&FINIT)
+               error("%s multiply defined", np->name);
+       np->hflag =| FINIT;
+}
+
+/*
+ * Process one statement in a function.
+ */
+statement()
+{
+       register o, o1, o2;
+       int o3;
+       struct tnode *np;
+       int sauto, sreg;
+
+stmt:
+       switch(o=symbol()) {
+
+       case EOFC:
+               error("Unexpected EOF");
+       case SEMI:
+               return;
+
+       case LBRACE:
+               sauto = autolen;
+               sreg = regvar;
+               blockhead();
+               while (!eof) {
+                       if ((o=symbol())==RBRACE) {
+                               autolen = sauto;
+                               if (sreg!=regvar)
+                                       outcode("BN", SETREG, sreg);
+                               regvar = sreg;
+                               blkend();
+                               return;
+                       }
+                       peeksym = o;
+                       statement();
+               }
+               error("Missing '}'");
+               return;
+
+       case KEYW:
+               switch(cval) {
+
+               case GOTO:
+                       if (o1 = simplegoto())
+                               branch(o1);
+                       else 
+                               dogoto();
+                       goto semi;
+
+               case RETURN:
+                       doret();
+                       goto semi;
+
+               case IF:
+                       np = pexpr();
+                       o2 = 0;
+                       if ((o1=symbol())==KEYW) switch (cval) {
+                       case GOTO:
+                               if (o2=simplegoto())
+                                       goto simpif;
+                               cbranch(np, o2=isn++, 0);
+                               dogoto();
+                               label(o2);
+                               goto hardif;
+
+                       case RETURN:
+                               if (nextchar()==';') {
+                                       o2 = retlab;
+                                       goto simpif;
+                               }
+                               cbranch(np, o1=isn++, 0);
+                               doret();
+                               label(o1);
+                               o2++;
+                               goto hardif;
+
+                       case BREAK:
+                               o2 = brklab;
+                               goto simpif;
+
+                       case CONTIN:
+                               o2 = contlab;
+                       simpif:
+                               chconbrk(o2);
+                               cbranch(np, o2, 1);
+                       hardif:
+                               if ((o=symbol())!=SEMI)
+                                       goto syntax;
+                               if ((o1=symbol())==KEYW && cval==ELSE) 
+                                       goto stmt;
+                               peeksym = o1;
+                               return;
+                       }
+                       peeksym = o1;
+                       cbranch(np, o1=isn++, 0);
+                       statement();
+                       if ((o=symbol())==KEYW && cval==ELSE) {
+                               o2 = isn++;
+                               branch(o2);
+                               label(o1);
+                               statement();
+                               label(o2);
+                               return;
+                       }
+                       peeksym = o;
+                       label(o1);
+                       return;
+
+               case WHILE:
+                       o1 = contlab;
+                       o2 = brklab;
+                       label(contlab = isn++);
+                       cbranch(pexpr(), brklab=isn++, 0);
+                       statement();
+                       branch(contlab);
+                       label(brklab);
+                       contlab = o1;
+                       brklab = o2;
+                       return;
+
+               case BREAK:
+                       chconbrk(brklab);
+                       branch(brklab);
+                       goto semi;
+
+               case CONTIN:
+                       chconbrk(contlab);
+                       branch(contlab);
+                       goto semi;
+
+               case DO:
+                       o1 = contlab;
+                       o2 = brklab;
+                       contlab = isn++;
+                       brklab = isn++;
+                       label(o3 = isn++);
+                       statement();
+                       label(contlab);
+                       contlab = o1;
+                       if ((o=symbol())==KEYW && cval==WHILE) {
+                               cbranch(tree(), o3, 1);
+                               label(brklab);
+                               brklab = o2;
+                               goto semi;
+                       }
+                       goto syntax;
+
+               case CASE:
+                       o1 = conexp();
+                       if ((o=symbol())!=COLON)
+                               goto syntax;
+                       if (swp==0) {
+                               error("Case not in switch");
+                               goto stmt;
+                       }
+                       if(swp>=swtab+SWSIZ) {
+                               error("Switch table overflow");
+                       } else {
+                               swp->swlab = isn;
+                               (swp++)->swval = o1;
+                               label(isn++);
+                       }
+                       goto stmt;
+
+               case SWITCH:
+                       o1 = brklab;
+                       brklab = isn++;
+                       np = pexpr();
+                       chkw(np, -1);
+                       rcexpr(block(RFORCE,0,NULL,NULL,np));
+                       pswitch();
+                       brklab = o1;
+                       return;
+
+               case DEFAULT:
+                       if (swp==0)
+                               error("Default not in switch");
+                       if (deflab)
+                               error("More than 1 'default'");
+                       if ((o=symbol())!=COLON)
+                               goto syntax;
+                       label(deflab = isn++);
+                       goto stmt;
+
+               case FOR:
+                       o1 = contlab;
+                       o2 = brklab;
+                       contlab = isn++;
+                       brklab = isn++;
+                       if (o=forstmt())
+                               goto syntax;
+                       label(brklab);
+                       contlab = o1;
+                       brklab = o2;
+                       return;
+
+               case ELSE:
+                       error("Inappropriate 'else'");
+                       statement();
+                       return;
+               }
+               error("Unknown keyword");
+               goto syntax;
+
+       case NAME:
+               if (nextchar()==':') {
+                       peekc = 0;
+                       o1 = csym;
+                       if (o1->hclass>0) {
+                               if (o1->hblklev==0) {
+                                       pushdecl(o1);
+                                       o1->hoffset = 0;
+                               } else {
+                                       defsym = o1;
+                                       redec();
+                                       goto stmt;
+                               }
+                       }
+                       o1->hclass = STATIC;
+                       o1->htype = ARRAY;
+                       o1->hflag =| FLABL;
+                       if (o1->hoffset==0)
+                               o1->hoffset = isn++;
+                       label(o1->hoffset);
+                       goto stmt;
+               }
+       }
+       peeksym = o;
+       rcexpr(tree());
+
+semi:
+       if ((o=symbol())==SEMI)
+               return;
+syntax:
+       error("Statement syntax");
+       errflush(o);
+}
+
+/*
+ * Process a for statement.
+ */
+forstmt()
+{
+       register int l, o, sline;
+       int sline1, *ss;
+       struct tnode *st;
+
+       if ((o=symbol()) != LPARN)
+               return(o);
+       if ((o=symbol()) != SEMI) {             /* init part */
+               peeksym = o;
+               rcexpr(tree());
+               if ((o=symbol()) != SEMI)
+                       return(o);
+       }
+       label(contlab);
+       if ((o=symbol()) != SEMI) {             /* test part */
+               peeksym = o;
+               cbranch(tree(), brklab, 0);
+               if ((o=symbol()) != SEMI)
+                       return(o);
+       }
+       if ((peeksym=symbol()) == RPARN) {      /* incr part */
+               peeksym = -1;
+               statement();
+               branch(contlab);
+               return(0);
+       }
+       l = contlab;
+       contlab = isn++;
+       st = tree();
+       sline = line;
+       if ((o=symbol()) != RPARN)
+               return(o);
+       ss = funcbase;
+       funcbase = curbase;
+       statement();
+       sline1 = line;
+       line = sline;
+       label(contlab);
+       rcexpr(st);
+       line = sline1;
+       if (ss < maxdecl)
+               ss = maxdecl;
+       curbase = funcbase = ss;
+       branch(l);
+       return(0);
+}
+
+/*
+ * A parenthesized expression,
+ * as after "if".
+ */
+struct tnode *
+pexpr()
+{
+       register o, t;
+
+       if ((o=symbol())!=LPARN)
+               goto syntax;
+       t = tree();
+       if ((o=symbol())!=RPARN)
+               goto syntax;
+       return(t);
+syntax:
+       error("Statement syntax");
+       errflush(o);
+       return(0);
+}
+
+/*
+ * The switch statement, which involves collecting the
+ * constants and labels for the cases.
+ */
+pswitch()
+{
+       register struct swtab *cswp, *sswp;
+       int dl, swlab;
+
+       cswp = sswp = swp;
+       if (swp==0)
+               cswp = swp = swtab;
+       branch(swlab=isn++);
+       dl = deflab;
+       deflab = 0;
+       statement();
+       branch(brklab);
+       label(swlab);
+       if (deflab==0)
+               deflab = brklab;
+       outcode("BNN", SWIT, deflab, line);
+       for (; cswp < swp; cswp++)
+               outcode("NN", cswp->swlab, cswp->swval);
+       outcode("0");
+       label(brklab);
+       deflab = dl;
+       swp = sswp;
+}
+
+/*
+ * funchead is called at the start of each function
+ * to process the arguments, which have been linked in a list.
+ * This list is necessary because in
+ * f(a, b) float b; int a; ...
+ * the names are seen before the types.
+ */
+/*
+ * Structure resembling a block for a register variable.
+ */
+struct hshtab  hreg    { REG, 0, 0, NULL, NULL, 0 };
+struct tnode   areg    { NAME, 0, NULL, NULL, &hreg};
+funchead()
+{
+       register pl;
+       register struct hshtab *cs;
+       struct tnode *bstack[2];
+
+       pl = STARG;
+       while(paraml) {
+               parame->hoffset = 0;
+               cs = paraml;
+               paraml = paraml->hoffset;
+               if (cs->htype==FLOAT)
+                       cs->htype = DOUBLE;
+               cs->hoffset = pl;
+               if ((cs->htype&XTYPE) == ARRAY) {
+                       cs->htype =- (ARRAY-PTR);       /* set ptr */
+                       cs->subsp++;            /* pop dims */
+               }
+               pl =+ rlength(cs);
+               if (cs->hclass==AREG && (hreg.hoffset=goodreg(cs))>=0) {
+                       bstack[0] = &areg;
+                       bstack[1] = nblock(cs);
+                       cp = &bstack[2];
+                       areg.type = cs->htype;
+                       cs->hclass = AUTO;
+                       build(ASSIGN);
+                       rcexpr(bstack[0]);
+                       cs->hoffset = hreg.hoffset;
+                       cs->hclass = REG;
+               } else
+                       cs->hclass = AUTO;
+               prste(cs);
+       }
+       for (cs=hshtab; cs<hshtab+HSHSIZ; cs++) {
+               if (cs->name[0] == '\0')
+                       continue;
+               if (cs->hclass == ARG || cs->hclass==AREG)
+                       error("Not an argument: %.8s", cs->name);
+       }
+       outcode("BN", SETREG, regvar);
+}
+
+blockhead()
+{
+       register r;
+
+       r = regvar;
+       blklev++;
+       declist(0);
+       if (r != regvar)
+               outcode("BN", SETREG, regvar);
+}
+
+/*
+ * After the end of a block, delete local
+ * symbols; save those that are external.
+ * Also complain about undefined labels.
+ */
+blkend()
+{
+       register struct hshtab *cs, *ncs;
+       struct hshtab *endcs;
+       register i;
+
+       blklev--;
+       for (cs=hshtab; cs->name[0] && cs<hshtab+HSHSIZ-1; ++cs)
+               ;
+       endcs = cs;
+       do  if (cs->name[0]) {
+               if (cs->hblklev <= blklev)
+                       continue;
+               if ((cs->hclass!=EXTERN || blklev!=0)
+                && ((cs->hflag&FLABL)==0 || blklev==0)) {
+                       if (cs->hclass==0)
+                               error("%.8s undefined", cs->name);
+                       if ((ncs = cs->hpdown)==NULL) {
+                               cs->name[0] = '\0';
+                               hshused--;
+                               cs->hflag =& FKEYW;
+                       } else {
+                               cpysymb(cs, ncs);
+                       }
+                       continue;
+               }
+               /*
+                * Retained name; must rehash.
+                */
+               for (i=0; i<NCPS; i++)
+                       symbuf[i] = cs->name[i];
+               mossym = cs->hflag&FMOS;
+               lookup();
+               if ((ncs=csym) != cs) {
+                       cs->name[0] = '\0';
+                       hshused--;
+                       i = ncs->hflag;
+                       cpysymb(ncs, cs);
+                       ncs->hflag =| i&FKEYW;
+                       cs->hflag =& FKEYW;
+               }
+               if (ncs->hblklev>1 || (ncs->hblklev>0 && ncs->hclass==EXTERN))
+                       ncs->hblklev--;
+       } while ((cs = (cs<&hshtab[HSHSIZ-1])? ++cs: hshtab) != endcs);
+}
+
+/*
+ * write out special definitions of local symbols for
+ * benefit of the debugger.  None of these are used
+ * by the assembler except to save them.
+ */
+prste(acs)
+struct hshtab *acs;
+{
+       register struct hshtab *cs;
+       register nkind;
+
+       cs = acs;
+       switch (cs->hclass) {
+       case REG:
+               nkind = RNAME;
+               break;
+
+       case AUTO:
+               nkind = ANAME;
+               break;
+
+       case STATIC:
+               nkind = SNAME;
+               break;
+
+       default:
+               return;
+
+       }
+       outcode("BSN", nkind, cs->name, cs->hoffset);
+}
+
+/*
+ * In case of error, skip to the next
+ * statement delimiter.
+ */
+errflush(ao)
+{
+       register o;
+
+       o = ao;
+       while(o>RBRACE) /* ; { } */
+               o = symbol();
+       peeksym  = o;
+}
diff --git a/usr/src/cmd/c/c20.c b/usr/src/cmd/c/c20.c
new file mode 100644 (file)
index 0000000..8bee9fe
--- /dev/null
@@ -0,0 +1,695 @@
+#
+/*
+ *      C object code improver
+ */
+
+#include "c2.h"
+
+struct optab optab[] {
+       "jbr",  JBR,
+       "jeq",  CBR | JEQ<<8,
+       "jne",  CBR | JNE<<8,
+       "jle",  CBR | JLE<<8,
+       "jge",  CBR | JGE<<8,
+       "jlt",  CBR | JLT<<8,
+       "jgt",  CBR | JGT<<8,
+       "jlo",  CBR | JLO<<8,
+       "jhi",  CBR | JHI<<8,
+       "jlos", CBR | JLOS<<8,
+       "jhis", CBR | JHIS<<8,
+       "jmp",  JMP,
+       ".globl",EROU,
+       "mov",  MOV,
+       "clr",  CLR,
+       "com",  COM,
+       "inc",  INC,
+       "dec",  DEC,
+       "neg",  NEG,
+       "tst",  TST,
+       "asr",  ASR,
+       "asl",  ASL,
+       "sxt",  SXT,
+       "cmp",  CMP,
+       "add",  ADD,
+       "sub",  SUB,
+       "bit",  BIT,
+       "bic",  BIC,
+       "bis",  BIS,
+       "mul",  MUL,
+       "ash",  ASH,
+       "xor",  XOR,
+       ".text",TEXT,
+       ".data",DATA,
+       ".bss", BSS,
+       ".even",EVEN,
+       "movf", MOVF,
+       "movof",MOVOF,
+       "movfo",MOVFO,
+       "addf", ADDF,
+       "subf", SUBF,
+       "divf", DIVF,
+       "mulf", MULF,
+       "clrf", CLRF,
+       "cmpf", CMPF,
+       "negf", NEGF,
+       "tstf", TSTF,
+       "cfcc", CFCC,
+       "sob",  SOB,
+       "jsr",  JSR,
+       ".end", END,
+       0,      0};
+
+char   revbr[] { JNE, JEQ, JGT, JLT, JGE, JLE, JHIS, JLOS, JHI, JLO };
+int    isn     = 20000;
+int    lastseg = -1;
+
+main(argc, argv)
+char **argv;
+{
+       register int niter, maxiter, isend;
+       extern end;
+       int nflag;
+
+       if (argc>1 && argv[1][0]=='+') {
+               argc--;
+               argv++;
+               debug++;
+       }
+       nflag = 0;
+       if (argc>1 && argv[1][0]=='-') {
+               argc--;
+               argv++;
+               nflag++;
+       }
+       if (argc>1) {
+               if (freopen(argv[1], "r", stdin) == NULL) {
+                       fprintf(stderr, "C2: can't find %s\n", argv[1]);
+                       exit(1);
+               }
+       }
+       if (argc>2) {
+               if (freopen(argv[2], "w", stdout) == NULL) {
+                       fprintf(stderr, "C2: can't create %s\n", argv[2]);
+                       exit(1);
+               }
+       }
+       lasta = firstr = lastr = sbrk(2);
+       maxiter = 0;
+       opsetup();
+       do {
+               isend = input();
+               movedat();
+               niter = 0;
+               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 .+2\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 literals eliminated\n", nlit);
+               fprintf(stderr, "%dK core\n", (((int)lastr+01777)>>10)&077);
+       }
+       exit(0);
+}
+
+input()
+{
+       register struct node *p, *lastp;
+       register int oper;
+
+       lastp = &first;
+       for (;;) {
+               oper = getline();
+               switch (oper&0377) {
+       
+               case LABEL:
+                       p = (struct node *)alloc(sizeof first);
+                       if (line[0] == 'L') {
+                               p->op = LABEL;
+                               p->subop = 0;
+                               p->labno = getnum(line+1);
+                               p->code = 0;
+                       } else {
+                               p->op = DLABEL;
+                               p->subop = 0;
+                               p->labno = 0;
+                               p->code = copy(1, line);
+                       }
+                       break;
+       
+               case JBR:
+               case CBR:
+               case JMP:
+               case JSW:
+                       p = (struct node *)alloc(sizeof first);
+                       p->op = oper&0377;
+                       p->subop = oper>>8;
+                       if (*curlp=='L' && (p->labno = getnum(curlp+1)))
+                               p->code = 0;
+                       else {
+                               p->labno = 0;
+                               p->code = copy(1, curlp);
+                       }
+                       break;
+
+               default:
+                       p = (struct node *)alloc(sizeof first);
+                       p->op = oper&0377;
+                       p->subop = oper>>8;
+                       p->labno = 0;
+                       p->code = copy(1, curlp);
+                       break;
+
+               }
+               p->forw = 0;
+               p->back = lastp;
+               lastp->forw = p;
+               lastp = p;
+               p->ref = 0;
+               if (oper==EROU)
+                       return(1);
+               if (oper==END)
+                       return(0);
+       }
+}
+
+getline()
+{
+       register char *lp;
+       register c;
+
+       lp = line;
+       while ((c = getchar())==' ' || c=='\t')
+               ;
+       do {
+               if (c==':') {
+                       *lp++ = 0;
+                       return(LABEL);
+               }
+               if (c=='\n') {
+                       *lp++ = 0;
+                       return(oplook());
+               }
+               if (lp >= &line[LSIZE-2]) {
+                       fprintf(stderr, "C2: Sorry, input line too long\n");
+                       exit(1);
+               }
+               *lp++ = c;
+       } while ((c = getchar()) != EOF);
+       *lp++ = 0;
+       return(END);
+}
+
+getnum(ap)
+char *ap;
+{
+       register char *p;
+       register n, c;
+
+       p = ap;
+       n = 0;
+       while ((c = *p++) >= '0' && c <= '9')
+               n = n*10 + c - '0';
+       if (*--p != 0)
+               return(0);
+       return(n);
+}
+
+output()
+{
+       register struct node *t;
+       register struct optab *oper;
+       register int byte;
+
+       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 TEXT:
+       case DATA:
+       case BSS:
+               lastseg = t->op;
+
+       default:
+               if ((byte = t->subop) == BYTE)
+                       t->subop = 0;
+               for (oper = optab; oper->opstring!=0; oper++) 
+                       if ((oper->opcode&0377) == t->op
+                        && (oper->opcode>>8) == t->subop) {
+                               printf("%s", oper->opstring);
+                               if (byte==BYTE)
+                                       printf("b");
+                               break;
+                       }
+               if (t->code) {
+                       reducelit(t);
+                       printf("\t%s\n", t->code);
+               } else if (t->op==JBR || t->op==CBR)
+                       printf("\tL%d\n", t->labno);
+               else
+                       printf("\n");
+               continue;
+
+       case JSW:
+               printf("L%d\n", t->labno);
+               continue;
+
+       case SOB:
+               printf("sob     %s", t->code);
+               if (t->labno)
+                       printf(",L%d", t->labno);
+               printf("\n");
+               continue;
+
+       case 0:
+               if (t->code)
+                       printf("%s", t->code);
+               printf("\n");
+               continue;
+       }
+}
+
+/*
+ * Notice addresses of the form
+ * $xx,xx(r)
+ * and replace them with (pc),xx(r)
+ *     -- Thanx and a tip of the Hatlo hat to Bliss-11.
+ */
+reducelit(at)
+struct node *at;
+{
+       register char *c1, *c2;
+       char *c2s;
+       register struct node *t;
+
+       t = at;
+       if (*t->code != '$')
+               return;
+       c1 = t->code;
+       while (*c1 != ',')
+               if (*c1++ == '\0')
+                       return;
+       c2s = c1;
+       c1++;
+       if (*c1=='*')
+               c1++;
+       c2 = t->code+1;
+       while (*c1++ == *c2++);
+       if (*--c1!='(' || *--c2!=',')
+               return;
+       t->code = copy(2, "(pc)", c2s);
+       nlit++;
+}
+
+char *
+copy(na, ap)
+char *ap;
+{
+       register char *p, *np;
+       char *onp;
+       register n;
+
+       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);
+}
+
+opsetup()
+{
+       register struct optab *optp, **ophp;
+       register char *p;
+
+       for (optp = optab; p = optp->opstring; optp++) {
+               ophp = &ophash[(((p[0]<<3)+(p[1]<<1)+p[2])&077777) % OPHS];
+               while (*ophp++)
+                       if (ophp > &ophash[OPHS])
+                               ophp = ophash;
+               *--ophp = optp;
+       }
+}
+
+oplook()
+{
+       register struct optab *optp;
+       register char *lp, *np;
+       static char tmpop[32];
+       struct optab **ophp;
+
+       if (line[0]=='\0') {
+               curlp = line;
+               return(0);
+       }
+       np = tmpop;
+       for (lp = line; *lp && *lp!=' ' && *lp!='\t';)
+               *np++ = *lp++;
+       *np++ = 0;
+       while (*lp=='\t' || *lp==' ')
+               lp++;
+       curlp = lp;
+       ophp = &ophash[(((tmpop[0]<<3)+(tmpop[1]<<1)+tmpop[2])&077777) % OPHS];
+       while (optp = *ophp) {
+               np = optp->opstring;
+               lp = tmpop;
+               while (*lp == *np++)
+                       if (*lp++ == 0)
+                               return(optp->opcode);
+               if (*lp++=='b' && *lp++==0 && *--np==0)
+                       return(optp->opcode + (BYTE<<8));
+               ophp++;
+               if (ophp >= &ophash[OPHS])
+                       ophp = ophash;
+       }
+       if (line[0]=='L') {
+               lp = &line[1];
+               while (*lp)
+                       if (*lp<'0' || *lp++>'9')
+                               return(0);
+               curlp = line;
+               return(JSW);
+       }
+       curlp = line;
+       return(0);
+}
+
+refcount()
+{
+       register struct node *p, *lp;
+       static struct node *labhash[LABHS];
+       register struct node **hp, *tp;
+
+       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->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) {
+                               tp = nonlab(lp)->back;
+                               if (tp!=lp) {
+                                       p->labno = tp->labno;
+                                       lp = tp;
+                               }
+                               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)->op==JBR) {
+                       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];
+                               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!=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;
+                       }
+               }
+               if (p->op==JBR || p->op==JMP) {
+                       xjump(p);
+                       p = codemove(p);
+               }
+       }
+}
+
+xjump(p1)
+register struct node *p1;
+{
+       register struct node *p2, *p3;
+
+       if ((p2 = p1->ref)==0)
+               return;
+       for (;;) {
+               while ((p1 = p1->back) && p1->op==LABEL);
+               while ((p2 = p2->back) && p2->op==LABEL);
+               if (!equop(p1, p2) || p1==p2)
+                       return;
+               p3 = insertl(p2);
+               p1->op = JBR;
+               p1->subop = 0;
+               p1->ref = p3;
+               p1->labno = p3->labno;
+               p1->code = 0;
+               nxjump++;
+               nchange++;
+       }
+}
+
+struct node *
+insertl(oldp)
+register struct node *oldp;
+{
+       register struct node *lp;
+
+       if (oldp->op == LABEL) {
+               oldp->refc++;
+               return(oldp);
+       }
+       if (oldp->back->op == LABEL) {
+               oldp = oldp->back;
+               oldp->refc++;
+               return(oldp);
+       }
+       lp = (struct node *)alloc(sizeof first);
+       lp->op = LABEL;
+       lp->subop = 0;
+       lp->labno = isn++;
+       lp->ref = 0;
+       lp->code = 0;
+       lp->refc = 1;
+       lp->back = oldp->back;
+       lp->forw = oldp;
+       oldp->back->forw = lp;
+       oldp->back = lp;
+       return(lp);
+}
+
+struct node *
+codemove(p)
+struct node *p;
+{
+       register struct node *p1, *p2, *p3;
+       struct node *t, *tl;
+       int n;
+
+       p1 = p;
+       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(p);
+       while (p1!=p3);
+       p1 = p;
+       tl = insertl(p1);
+       p3->subop = revbr[p3->subop];
+       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)
+                       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->labno = p3->labno;
+                       p2->ref = p3;
+                       nchange++;
+                       ncomj++;
+               } else
+                       return;
+       }
+}
diff --git a/usr/src/cmd/c/c21.c b/usr/src/cmd/c/c21.c
new file mode 100644 (file)
index 0000000..267c824
--- /dev/null
@@ -0,0 +1,791 @@
+#
+/*
+ * C object code improver-- second part
+ */
+
+#include "c2.h"
+
+rmove()
+{
+       register struct node *p;
+       register int r;
+       register  r1, flt;
+
+       for (p=first.forw; p!=0; p = p->forw) {
+       flt = 0;
+       switch (p->op) {
+
+       case MOVF:
+       case MOVFO:
+       case MOVOF:
+               flt = NREG;
+
+       case MOV:
+               if (p->subop==BYTE)
+                       goto dble;
+               dualop(p);
+               if ((r = findrand(regs[RT1], flt)) >= 0) {
+                       if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR
+                          && p->forw->op!=SXT
+                          && p->forw->op!=CFCC) {
+                               p->forw->back = p->back;
+                               p->back->forw = p->forw;
+                               redunm++;
+                               continue;
+                       }
+               }
+               if (equstr(regs[RT1], "$0")) {
+                       p->op = CLR;
+                       strcpy(regs[RT1], regs[RT2]);
+                       regs[RT2][0] = 0;
+                       p->code = copy(1, regs[RT1]);
+                       goto sngl;
+               }
+               repladdr(p, 0, flt);
+               r = isreg(regs[RT1]);
+               r1 = isreg(regs[RT2]);
+               dest(regs[RT2], flt);
+               if (r >= 0)
+                       if (r1 >= 0)
+                               savereg(r1+flt, regs[r+flt]);
+                       else
+                               savereg(r+flt, regs[RT2]);
+               else
+                       if (r1 >= 0)
+                               savereg(r1+flt, regs[RT1]);
+                       else
+                               setcon(regs[RT1], regs[RT2]);
+               source(regs[RT1]);
+               setcc(regs[RT2]);
+               continue;
+
+       case ADDF:
+       case SUBF:
+       case DIVF:
+       case MULF:
+               flt = NREG;
+               goto dble;
+
+       case ADD:
+       case SUB:
+       case BIC:
+       case BIS:
+       case MUL:
+       case DIV:
+       case ASH:
+       dble:
+               dualop(p);
+               if (p->op==BIC && (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777"))) {
+                       p->op = CLR;
+                       strcpy(regs[RT1], regs[RT2]);
+                       regs[RT2][0] = 0;
+                       p->code = copy(1, regs[RT1]);
+                       goto sngl;
+               }
+               if ((p->op==BIC || p->op==BIS) && equstr(regs[RT1], "$0")) {
+                       if (p->forw->op!=CBR) {
+                               p->back->forw = p->forw;
+                               p->forw->back = p->back;
+                               continue;
+                       }
+               }
+               repladdr(p, 0, flt);
+               source(regs[RT1]);
+               dest(regs[RT2], flt);
+               if (p->op==DIV && (r = isreg(regs[RT2])>=0))
+                       regs[r+1][0] = 0;
+               ccloc[0] = 0;
+               continue;
+
+       case CLRF:
+       case NEGF:
+               flt = NREG;
+
+       case CLR:
+       case COM:
+       case INC:
+       case DEC:
+       case NEG:
+       case ASR:
+       case ASL:
+       case SXT:
+               singop(p);
+       sngl:
+               dest(regs[RT1], flt);
+               if (p->op==CLR && flt==0)
+                       if ((r = isreg(regs[RT1])) >= 0)
+                               savereg(r, "$0");
+                       else
+                               setcon("$0", regs[RT1]);
+               ccloc[0] = 0;
+               continue;
+
+       case TSTF:
+               flt = NREG;
+
+       case TST:
+               singop(p);
+               repladdr(p, 0, flt);
+               source(regs[RT1]);
+               if (equstr(regs[RT1], ccloc)) {
+                       p->back->forw = p->forw;
+                       p->forw->back = p->back;
+                       p = p->back;
+                       nrtst++;
+                       nchange++;
+               }
+               continue;
+
+       case CMPF:
+               flt = NREG;
+
+       case CMP:
+       case BIT:
+               dualop(p);
+               source(regs[RT1]);
+               source(regs[RT2]);
+               if(p->op==BIT) {
+                       if (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777")) {
+                               p->op = TST;
+                               strcpy(regs[RT1], regs[RT2]);
+                               regs[RT2][0] = 0;
+                               p->code = copy(1, regs[RT1]);
+                               nchange++;
+                               nsaddr++;
+                       } else if (equstr(regs[RT2], "$-1") || equstr(regs[RT2], "$177777")) {
+                               p->op = TST;
+                               regs[RT2][0] = 0;
+                               p->code = copy(1, regs[RT1]);
+                               nchange++;
+                               nsaddr++;
+                       }
+                       if (equstr(regs[RT1], "$0")) {
+                               p->op = TST;
+                               regs[RT2][0] = 0;
+                               p->code = copy(1, regs[RT1]);
+                               nchange++;
+                               nsaddr++;
+                       } else if (equstr(regs[RT2], "$0")) {
+                               p->op = TST;
+                               strcpy(regs[RT1], regs[RT2]);
+                               regs[RT2][0] = 0;
+                               p->code = copy(1, regs[RT1]);
+                               nchange++;
+                               nsaddr++;
+                       }
+               }
+               repladdr(p, 1, flt);
+               ccloc[0] = 0;
+               continue;
+
+       case CBR:
+               if (p->back->op==TST || p->back->op==CMP) {
+                       if (p->back->op==TST) {
+                               singop(p->back);
+                               savereg(RT2, "$0");
+                       } else
+                               dualop(p->back);
+                       r = compare(p->subop, findcon(RT1), findcon(RT2));
+                       if (r==0) {
+                               p->back->back->forw = p->forw;
+                               p->forw->back = p->back->back;
+                               decref(p->ref);
+                               p = p->back->back;
+                               nchange++;
+                       } else if (r>0) {
+                               p->op = JBR;
+                               p->subop = 0;
+                               p->back->back->forw = p;
+                               p->back = p->back->back;
+                               p = p->back;
+                               nchange++;
+                       }
+               }
+       case CFCC:
+               ccloc[0] = 0;
+               continue;
+
+       case JBR:
+               redunbr(p);
+
+       default:
+               clearreg();
+       }
+       }
+}
+
+jumpsw()
+{
+       register struct node *p, *p1;
+       register t;
+       register struct node *tp;
+       int nj;
+
+       t = 0;
+       nj = 0;
+       for (p=first.forw; p!=0; p = p->forw)
+               p->refc = ++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->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) {
+                       if (p->ref==p1->ref)
+                               continue;
+                       p->subop = revbr[p->subop];
+                       tp = p1->ref;
+                       p1->ref = p->ref;
+                       p->ref = tp;
+                       t = p1->labno;
+                       p1->labno = p->labno;
+                       p->labno = t;
+                       nrevbr++;
+                       nj++;
+               }
+       }
+       return(nj);
+}
+
+addsob()
+{
+       register struct node *p, *p1;
+
+       for (p = &first; (p1 = p->forw)!=0; p = p1) {
+               if (p->op==DEC && isreg(p->code)>=0
+                && p1->op==CBR && p1->subop==JNE) {
+                       if (p->refc < p1->ref->refc)
+                               continue;
+                       if (toofar(p1))
+                               continue;
+                       p->labno = p1->labno;
+                       p->op = SOB;
+                       p->subop = 0;
+                       p1->forw->back = p;
+                       p->forw = p1->forw;
+                       nsob++;
+               }
+       }
+}
+
+toofar(p)
+struct node *p;
+{
+       register struct node *p1;
+       int len;
+
+       len = 0;
+       for (p1 = p->ref; p1 && p1!=p; p1 = p1->forw)
+               len += ilen(p1);
+       if (len < 128)
+               return(0);
+       return(1);
+}
+
+ilen(p)
+register struct node *p;
+{
+       register l;
+
+       switch (p->op) {
+       case LABEL:
+       case DLABEL:
+       case TEXT:
+       case EROU:
+       case EVEN:
+               return(0);
+
+       case CBR:
+               return(6);
+
+       default:
+               dualop(p);
+               return(2 + adrlen(regs[RT1]) + adrlen(regs[RT2]));
+       }
+}
+
+adrlen(s)
+register char *s;
+{
+       if (*s == 0)
+               return(0);
+       if (*s=='r')
+               return(0);
+       if (*s=='(' && *(s+1)=='r')
+               return(0);
+       if (*s=='-' && *(s+1)=='(')
+               return(0);
+       return(2);
+}
+
+abs(x)
+{
+       return(x<0? -x: x);
+}
+
+equop(ap1, p2)
+struct node *ap1, *p2;
+{
+       register char *cp1, *cp2;
+       register struct node *p1;
+
+       p1 = ap1;
+       if (p1->op!=p2->op || p1->subop!=p2->subop)
+               return(0);
+       if (p1->op>0 && p1->op<MOV)
+               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);
+}
+
+decref(p)
+register struct node *p;
+{
+       if (--p->refc <= 0) {
+               nrlab++;
+               p->back->forw = p->forw;
+               p->forw->back = p->back;
+       }
+}
+
+struct node *
+nonlab(p)
+struct node *p;
+{
+       while (p && p->op==LABEL)
+               p = p->forw;
+       return(p);
+}
+
+char *
+alloc(n)
+register n;
+{
+       register char *p;
+
+       n++;
+       n &= ~01;
+       if (lasta+n >= lastr) {
+               if (sbrk(2000) == (char *)-1) {
+                       fprintf(stderr, "C Optimizer: out of space\n");
+                       exit(1);
+               }
+               lastr += 2000;
+       }
+       p = lasta;
+       lasta += n;
+       return(p);
+}
+
+clearreg()
+{
+       register int i;
+
+       for (i=0; i<2*NREG; i++)
+               regs[i][0] = '\0';
+       conloc[0] = 0;
+       ccloc[0] = 0;
+}
+
+savereg(ai, as)
+char *as;
+{
+       register char *p, *s, *sp;
+
+       sp = p = regs[ai];
+       s = as;
+       if (source(s))
+               return;
+       while (*p++ = *s) {
+               if (s[0]=='(' && s[1]=='r' && s[2]<'5') {
+                       *sp = 0;
+                       return;
+               }
+               if (*s++ == ',')
+                       break;
+       }
+       *--p = '\0';
+}
+
+dest(as, flt)
+char *as;
+{
+       register char *s;
+       register int i;
+
+       s = as;
+       source(s);
+       if ((i = isreg(s)) >= 0)
+               regs[i+flt][0] = 0;
+       for (i=0; i<NREG+NREG; i++)
+               if (*regs[i]=='*' && equstr(s, regs[i]+1))
+                       regs[i][0] = 0;
+       while ((i = findrand(s, flt)) >= 0)
+               regs[i][0] = 0;
+       while (*s) {
+               if ((*s=='(' && (*(s+1)!='r' || *(s+2)!='5')) || *s++=='*') {
+                       for (i=0; i<NREG+NREG; i++) {
+                               if (regs[i][0] != '$')
+                                       regs[i][0] = 0;
+                               conloc[0] = 0;
+                       }
+                       return;
+               }
+       }
+}
+
+singop(ap)
+struct node *ap;
+{
+       register char *p1, *p2;
+
+       p1 = ap->code;
+       p2 = regs[RT1];
+       while (*p2++ = *p1++);
+       regs[RT2][0] = 0;
+}
+
+
+dualop(ap)
+struct node *ap;
+{
+       register char *p1, *p2;
+       register struct node *p;
+
+       p = ap;
+       p1 = p->code;
+       p2 = regs[RT1];
+       while (*p1 && *p1!=',')
+               *p2++ = *p1++;
+       *p2++ = 0;
+       p2 = regs[RT2];
+       *p2 = 0;
+       if (*p1++ !=',')
+               return;
+       while (*p2++ = *p1++);
+}
+
+findrand(as, flt)
+char *as;
+{
+       register int i;
+       for (i = flt; i<NREG+flt; i++) {
+               if (equstr(regs[i], as))
+                       return(i);
+       }
+       return(-1);
+}
+
+isreg(as)
+char *as;
+{
+       register char *s;
+
+       s = as;
+       if (s[0]=='r' && s[1]>='0' && s[1]<='4' && s[2]==0)
+               return(s[1]-'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();
+               lp = p;
+       }
+}
+
+source(ap)
+char *ap;
+{
+       register char *p1, *p2;
+
+       p1 = ap;
+       p2 = p1;
+       if (*p1==0)
+               return(0);
+       while (*p2++);
+       if (*p1=='-' && *(p1+1)=='('
+        || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='('
+        || *(p2-2)=='+') {
+               while (*p1 && *p1++!='r');
+               if (*p1>='0' && *p1<='4')
+                       regs[*p1 - '0'][0] = 0;
+               return(1);
+       }
+       return(0);
+}
+
+repladdr(p, f, flt)
+struct node *p;
+{
+       register r;
+       int r1;
+       register char *p1, *p2;
+       static char rt1[50], rt2[50];
+
+       if (f)
+               r1 = findrand(regs[RT2], flt);
+       else
+               r1 = -1;
+       r = findrand(regs[RT1], flt);
+       if (r1 >= NREG)
+               r1 -= NREG;
+       if (r >= NREG)
+               r -= NREG;
+       if (r>=0 || r1>=0) {
+               p2 = regs[RT1];
+               for (p1 = rt1; *p1++ = *p2++;);
+               if (regs[RT2][0]) {
+                       p1 = rt2;
+                       *p1++ = ',';
+                       for (p2 = regs[RT2]; *p1++ = *p2++;);
+               } else
+                       rt2[0] = 0;
+               if (r>=0) {
+                       rt1[0] = 'r';
+                       rt1[1] = r + '0';
+                       rt1[2] = 0;
+                       nsaddr++;
+               }
+               if (r1>=0) {
+                       rt2[1] = 'r';
+                       rt2[2] = r1 + '0';
+                       rt2[3] = 0;
+                       nsaddr++;
+               }
+               p->code = copy(2, rt1, rt2);
+       }
+}
+
+movedat()
+{
+       register struct node *p1, *p2;
+       struct node *p3;
+       register seg;
+       struct node data;
+       struct node *datp;
+
+       if (first.forw == 0)
+               return;
+       if (lastseg != TEXT && lastseg != -1) {
+               p1 = (struct node *)alloc(sizeof(first));
+               p1->op = lastseg;
+               p1->subop = 0;
+               p1->code = NULL;
+               p1->forw = first.forw;
+               p1->back = &first;
+               first.forw->back = p1;
+               first.forw = p1;
+       }
+       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 = lastseg;
+       for (p1 = first.forw; p1!=0; p1 = p1->forw) {
+               if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) {
+                       if (p2 = p1->forw) {
+                               if (p2->op==TEXT||p2->op==DATA||p2->op==BSS)
+                                       p1->op  = p2->op;
+                       }
+                       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) {
+               singop(p1);
+               savereg(RT2, "$0");
+       } else if (p1->op==CMP)
+               dualop(p1);
+       else
+               return;
+       if (p1->forw->op!=CBR)
+               return;
+       ap1 = findcon(RT1);
+       ap2 = findcon(RT2);
+       p1 = p1->forw;
+       if (compare(p1->subop, ap1, ap2)>0) {
+               nredunj++;
+               nchange++;
+               decref(p->ref);
+               p->ref = p1->ref;
+               p->labno = p1->labno;
+               p->ref->refc++;
+       }
+}
+
+char *
+findcon(i)
+{
+       register char *p;
+       register r;
+
+       p = regs[i];
+       if (*p=='$')
+               return(p);
+       if ((r = isreg(p)) >= 0)
+               return(regs[r]);
+       if (equstr(p, conloc))
+               return(conval);
+       return(p);
+}
+
+compare(oper, cp1, cp2)
+register char *cp1, *cp2;
+{
+       register unsigned n1, n2;
+
+       if (*cp1++ != '$' || *cp2++ != '$')
+               return(-1);
+       n1 = 0;
+       while (*cp2 >= '0' && *cp2 <= '7') {
+               n1 <<= 3;
+               n1 += *cp2++ - '0';
+       }
+       n2 = n1;
+       n1 = 0;
+       while (*cp1 >= '0' && *cp1 <= '7') {
+               n1 <<= 3;
+               n1 += *cp1++ - '0';
+       }
+       if (*cp1=='+')
+               cp1++;
+       if (*cp2=='+')
+               cp2++;
+       do {
+               if (*cp1++ != *cp2)
+                       return(-1);
+       } while (*cp2++);
+       switch(oper) {
+
+       case JEQ:
+               return(n1 == n2);
+       case JNE:
+               return(n1 != n2);
+       case JLE:
+               return((int)n1 <= (int)n2);
+       case JGE:
+               return((int)n1 >= (int)n2);
+       case JLT:
+               return((int)n1 < (int)n2);
+       case JGT:
+               return((int)n1 > (int)n2);
+       case JLO:
+               return(n1 < n2);
+       case JHI:
+               return(n1 > n2);
+       case JLOS:
+               return(n1 <= n2);
+       case JHIS:
+               return(n1 >= n2);
+       }
+       return(-1);
+}
+
+setcon(ar1, ar2)
+char *ar1, *ar2;
+{
+       register char *cl, *cv, *p;
+
+       cl = ar2;
+       cv = ar1;
+       if (*cv != '$')
+               return;
+       if (!natural(cl))
+               return;
+       p = conloc;
+       while (*p++ = *cl++);
+       p = conval;
+       while (*p++ = *cv++);
+}
+
+equstr(ap1, ap2)
+char *ap1, *ap2;
+{
+       char *p1, *p2;
+
+       p1 = ap1;
+       p2 = ap2;
+       do {
+               if (*p1++ != *p2)
+                       return(0);
+       } while (*p2++);
+       return(1);
+}
+
+setcc(ap)
+char *ap;
+{
+       register char *p, *p1;
+
+       p = ap;
+       if (!natural(p)) {
+               ccloc[0] = 0;
+               return;
+       }
+       p1 = ccloc;
+       while (*p1++ = *p++);
+}
+
+natural(ap)
+char *ap;
+{
+       register char *p;
+
+       p = ap;
+       if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(')
+               return(0);
+       while (*p++);
+       p--;
+       if (*--p == '+' || *p ==')' && *--p != '5')
+               return(0);
+       return(1);
+}
diff --git a/usr/src/cmd/c/table.s b/usr/src/cmd/c/table.s
new file mode 100644 (file)
index 0000000..f8ead47
--- /dev/null
@@ -0,0 +1,1601 @@
+/
+/ c code tables-- compile to register
+/
+
+.globl _regtab
+
+.data
+_regtab=.
+       106.;   cr106
+       30.;    cr70
+       31.;    cr70
+       32.;    cr32
+       33.;    cr32
+       37.;    cr37
+       38.;    cr37
+       98.;    cr100
+       99.;    cr100
+       80.;    cr80
+       40.;    cr40
+       41.;    cr40    / - like +
+       42.;    cr42
+       43.;    cr43
+       14.;    cr43
+       44.;    cr43
+       45.;    cr45
+       46.;    cr40
+       55.;    cr40
+       48.;    cr40
+       49.;    cr49
+       70.;    cr70
+       71.;    cr70
+       72.;    cr72
+       73.;    cr73
+       74.;    cr74
+       75.;    cr75
+       76.;    cr72
+       78.;    cr70
+       85.;    cr70
+       79.;    cr79
+       102.;   cr102
+       51.;    cr51
+       52.;    cr52
+       56.;    cr56
+       57.;    cr57
+       58.;    cr58
+       59.;    cr59
+       91.;    cr91
+       82.;    cr82
+       83.;    cr82
+       84.;    cr82
+       86.;    cr86
+       87.;    cr86
+       88.;    cr86
+       16.;    cr16
+       92.;    cr92
+       17.;    cr43
+       18.;    cr74
+       109.; cr109
+       0
+.text
+
+/ goto
+cr102:
+%a,n
+       jmp     A1
+
+%n*,n
+       F*
+       jmp     #1(R)
+
+/ call
+cr100:
+%a,n
+       jsr     pc,IA1
+
+%n*,n
+       F*
+       jsr     pc,#1(R)
+
+%n,n
+       F
+       jsr     pc,(R)
+
+/ addressible
+cr106:
+%z,n
+       clr     R
+
+%zf,n
+       clrf    R
+
+%a,n
+%ad,n
+       movB1   A1,R
+
+%af,n
+       movof   A1,R
+
+%n*,n
+%nd*,n
+       F*
+       movB1   #1(R),R
+
+%nf*,n
+       F*
+       movof   #1(R),R
+
+%al,n
+       mov     A1+,R+
+       mov     A1,R
+
+%nl*,n
+       F*
+       mov     #1+2(R),R+
+       mov     #1(R),R
+
+%n,n
+       F
+
+/ ++,-- postfix
+cr32:
+%a,1
+       movB1   A1',R
+       I'B1    A1''
+
+%aw,n
+       mov     A1',R
+       I       A2,A1''
+
+%e*,1
+       F1*
+       movB1   #1(R1),R
+       I'B1    #1(R1)
+
+%n*,1
+       F*
+       movB1   #1(R),-(sp)
+       I'B1    #1(R)
+       movB1   (sp)+,R
+
+%ew*,n
+       F1*
+       mov     #1(R1),R
+       I       A2,#1(R1)
+
+%nw*,n
+       F*
+       mov     #1(R),-(sp)
+       I       A2,#1(R)
+       mov     (sp)+,R
+
+%al,1
+       F
+       I       $1,A1+
+       V       A1
+
+%el*,1
+       F1*
+       mov     #1+2(R1),R+
+       mov     #1(R1),R
+       I       $1,#1+2(R1)
+       V       #1(R1)
+
+%nl*,1
+       F*
+       mov     #1+2(R),-(sp)
+       mov     #1(R),-(sp)
+       I       $1,#1+2(R)
+       V       #1(R)
+       mov     (sp)+,R
+       mov     (sp)+,R+
+
+/ - unary, ~
+cr37:
+%n,n
+%nf,n
+       F
+       IBF     R
+
+%nl,n
+       F
+       I       R
+       I       R+
+       V       R
+
+/ =
+cr80:
+%a,n
+%ad,nf
+       S
+       movB1   R,A1
+
+%af,nf
+       S
+       movfo   R,A1
+
+%nd*,af
+       F*
+       S
+       movf    R,#1(R)
+
+%n*,aw
+       F*
+       movB1   A2,#1(R)
+       movB1   #1(R),R
+
+%nf*,af
+       F*
+       S
+       movfo   R,#1(R)
+
+%n*,e
+       F*
+       S1
+       movB1   R1,#1(R)
+       movB1   R1,R
+
+%ed*,nf
+       S
+       F1*
+       movf    R,#1(R1)
+
+%ef*,nf
+       S
+       F1*
+       movfo   R,#1(R1)
+
+%n*,n
+%nd*,nf
+       FS*
+       S
+       movB1   R,*(sp)+
+
+%nf*,nf
+       FS*
+       S
+       movfo   R,*(sp)+
+
+%al,nl
+       S
+       mov     R+,A1+
+       mov     R,A1
+
+%el*,nl
+       S
+       F1*
+       mov     R+,2+#1(R1)
+       mov     R,#1(R1)
+
+%nl*,nl
+       FS*
+       S
+       mov     R,*(sp)
+       add     $2,(sp)
+       mov     R+,*(sp)+
+
+/ field assign, value in reg.
+cr16:
+%a,n
+       S
+       bicB1   Z,A1'
+       bisB1   R,A1''
+
+%e*,n
+%      [fas1]
+
+%n*,n
+       SS
+       F*
+       bicB1   Z,#1(R)
+       bisB1   (sp),#1(R)
+       mov     (sp)+,R
+
+/ +, -, |, &~, <<
+cr40:
+%n,z
+       F
+
+%n,1
+       F
+       I'      R
+
+%[add1:]
+%n,aw
+%nf,ad
+       F
+       IB2     A2,R
+
+%[add2:]
+%n,ew*
+%nf,ed*
+       F
+       S1*
+       IB2     #2(R1),R
+
+%[add3:]
+%n,e
+%nf,ef
+       F
+       S1
+       IBF     R1,R
+
+%[add4:]
+%n,nw*
+%nf,nd*
+       SS*
+       F
+       IB2     *(sp)+,R
+
+%[add5:]
+%n,n
+%nf,nf
+       SS
+       F
+       IBF     (sp)+,R
+
+%nl,c
+%nl,au
+       F
+       I       A2,R+
+       V       R
+
+%nl,eu
+       F
+       S1
+       I       R1,R+
+       V       R
+
+%nl,al
+       F
+       I       A2,R
+       I       A2+,R+
+       V       R
+
+%[addl1:]
+%nl,el
+       F
+       S1
+       I       R1+,R+
+       V       R
+       I       R1,R
+
+%[addl2:]
+%nl,nl
+       SS
+       F
+       I       (sp)+,R
+       I       (sp)+,R+
+       V       R
+
+/ ^ -- xor
+cr49:
+%n,e
+%      [add3]
+
+%n,n
+       FS
+       S
+       xor     R,(sp)
+       mov     (sp)+,R
+
+%nl,el
+%      [addl1]
+
+%nl,nl
+       SS
+       F
+       I       R,(sp)
+       mov     (sp)+,R
+       I       R+,(sp)
+       mov     (sp)+,R+
+
+/ >> (all complicated cases taken care of by << -)
+cr45:
+%n,1
+       F
+       asr     R
+
+/ * -- R must be odd on integers
+cr42:
+%n,aw
+%nf,ad
+%      [add1]
+
+%n,ew*
+%nf,ed*
+%      [add2]
+
+%n,e
+%nf,ef
+%      [add3]
+
+%n,n
+%nf,nf
+%      [add5]
+
+/ / R must be odd on integers
+cr43:
+%n,aw
+       F
+       T
+       I       A2,R-
+
+%n,ew*
+       F
+       T
+       S1*
+       I       #2(R1),R-
+
+%n,e
+       F
+       T
+       S1
+       I       R1,R-
+
+%n,n
+       SS
+       F
+       T
+       I       (sp)+,R-
+
+%nf,ad
+%      [add1]
+
+%nf,ed*
+%      [add2]
+
+%nf,ef
+%      [add3]
+
+%nf,nf
+%      [add5]
+
+/ =+, =-, =|, =&~
+cr70:
+%[addq1:]
+%aw,aw
+       I       A2,A1'
+       mov     A1'',R
+
+%[addq1a:]
+%a,aw
+%ad,ad
+       movB1   A1',R
+       IBF     A2,R
+       movB1   R,A1''
+
+%[addq2:]
+%aw,nw*
+       S*
+       I       #2(R),A1'
+       mov     A1'',R
+
+%[addq3:]
+%aw,n
+       S
+       I       R,A1'
+       mov     A1'',R
+
+%[addq4:]
+%ew*,nw*
+       S*
+       F1*
+       I       #2(R),#1(R1)
+       mov     #1(R1),R
+
+%[addq4a:]
+%ad,ef
+       movf    A1',R
+       S1
+       IBF     R1,R
+       movf    R,A1''
+
+%[addq5:]
+%a,n
+%ad,nf
+       SS
+       movB1   A1',R
+       IBF     (sp)+,R
+       movB1   R,A1''
+
+%[addq6:]
+%af,nf
+       SS
+       movof   A1',R
+       IBF     (sp)+,R
+       movfo   R,A1''
+
+%[addq7:]
+%ew*,n
+       S
+       F1*
+       I       R,#1(R1)
+       mov     #1(R1),R
+
+%[addq8:]
+%nw*,n
+       SS
+       F*
+       I       (sp)+,#1(R)
+       mov     #1(R),R
+
+%[addq9:]
+%n*,n
+       FS*
+       SS
+       movB1   *2(sp),R
+       IBF     (sp)+,R
+       movB1   R,*(sp)+
+
+%[addq9a:]
+%nd*,nf
+       SS
+       F*
+       movB1   #1(R),R
+       IBF     (sp)+,R
+       movB1   R,#1(R)
+
+%[addq10:]
+%nf*,nf
+       SS
+       F*
+       movof   #1(R),R1
+       IBF     (sp)+,R1
+       movfo   R1,#1(R)
+       movf    R1,R
+
+%al,c
+       I       A2,A1+
+       V       A1
+       F
+
+%al,al
+       I       A2+,A1+
+       V       A1
+       I       A2,A1
+       F
+
+%al,nl
+       S
+       I       R+,A1+
+       V       A1
+       I       R,A1
+       F
+
+%nl*,c
+       F*
+       I       A2,#1+2(R)
+       V       #1(R)
+       mov     #1+2(R),R+
+       mov     #1(R),R
+
+%nl*,al
+       F*
+       I       A2+,#1+2(R)
+       V       #1(R)
+       I       A2,#1(R)
+       mov     #1+2(R),R+
+       mov     #1(R),R
+
+%nl*,nl
+       SS
+       F*
+       I       (sp)+,#1(R)
+       I       (sp)+,#1+2(R)
+       V       #1(R)
+       mov     #1+2(R),R+
+       mov     #1(R),R
+
+/ =*, =<< (for integer multiply, R must be odd)
+cr72:
+%a,aw
+%ad,ad
+%      [addq1a]
+
+%ad,ef
+%      [addq4a]
+
+%a,n
+%ad,nf
+%      [addq5]
+
+%af,nf
+%      [addq6]
+
+%n*,n
+%      [addq9]
+
+%nd*,nf
+%      [addq9a]
+
+%nf*,nf
+%      [addq10]
+
+/ =/ ;  R must be odd on integers
+cr73:
+%a,aw
+       movB1   A1',R
+       V       R-
+       IBF     A2,R-
+       movB1   R-,A1''
+
+%a,n
+       SS
+       movB1   A1',R
+       V       R-
+       I       (sp)+,R-
+       movB1   R-,A1''
+
+%e*,n
+       SS
+       F1*
+       movB1   #1(R1),R
+       V       R-
+       I       (sp)+,R-
+       movB1   R-,#1(R1)
+
+%n*,n
+       FS*
+       SS
+       movB1   *2(sp),R
+       V       R-
+       I       (sp)+,R-
+       movB1   R-,*(sp)+
+
+%ad,ad
+%      [addq1a]
+
+%ad,ef
+%      [addq4a]
+
+%ad,nf
+%      [addq5]
+
+%af,nf
+%      [addq6]
+
+%nd*,nf
+%      [addq9a]
+
+%nf*,nf
+%      [addq10]
+
+/ =mod; R must be odd on integers
+cr74:
+%a,aw
+       movB1   A1',R
+       V       R-
+       I       A2,R-
+       movB1   R,A1''
+
+%a,n
+       SS
+       movB1   A1',R
+       V       R-
+       I       (sp)+,R-
+       movB1   R,A1''
+
+%e*,n
+       SS
+       F1*
+       movB1   #1(R1),R
+       V       R-
+       I       (sp)+,R-
+       movB1   R,#1(R1)
+
+%n*,n
+       FS*
+       SS
+       movB1   *2(sp),R
+       V       R-
+       I       (sp)+,R-
+       mov     R,*(sp)+
+
+/ =^ -- =xor
+cr79:
+%aw,n
+%      [addq3]
+
+%ab,n
+       SS
+       movb    A1',R
+       xor     R,(sp)
+       mov     (sp)+,R
+       movb    R,A1''
+
+%n*,n
+       FS*
+       movB1   *(sp),-(sp)
+       S
+       xor     R,(sp)
+       movB1   (sp)+,R
+       movB1   R,*(sp)+
+
+/ =>> (all complicated cases done by =<< -)
+cr75:
+%a,1
+       asrB1   A1'
+       movB1   A1'',R
+
+%n*,1
+       F*
+       asrB1   #1(R)
+       movB1   #1(R),R
+
+/ << for longs
+cr91:
+%nl,aw
+%      [add1]
+
+%nl,ew*
+%      [add2]
+
+%nl,e
+%      [add3]
+
+%nl,nw*
+%      [add4]
+
+%nl,n
+%      [add5]
+
+/ int -> float
+cr51:
+%aw,n
+       movif   A1,R
+
+%nw*,n
+       F*
+       movif   #1(R),R
+
+%n,n
+       F
+       movif   R,R
+
+/ float, double -> int
+cr52:
+%nf,n
+       F
+       movfi   R,R
+
+/ double (float) to long
+cr56:
+%nf,n
+       F
+       setl
+       movfi   R,-(sp)
+       mov     (sp)+,R
+       mov     (sp)+,R+
+       seti
+
+/ long to double
+cr57:
+%al,n
+       setl
+       movif   A1,R
+       seti
+
+%nl*,n
+       F*
+       setl
+       movif   #1(R),R
+       seti
+
+%nl,n
+       FS
+       setl
+       movif   (sp)+,R
+       seti
+
+/ integer to long
+cr58:
+%eu,n
+       F1!
+       clr     R
+
+%nu,n
+       F
+       mov     R,R1
+       clr     R
+
+%e,n
+       F1!
+       sxt     R
+
+%n,n
+       F
+       mov     R,R1
+       sxt     R
+
+/ long to integer
+cr59:
+%al,n
+       mov     A1+,R
+
+%nl*,n
+       F*
+       mov     #1+2(R),R
+
+/ *, /, remainder for longs.
+cr82:
+%nl,nl
+       SS
+       FS
+       jsr     pc,I
+       add     $10,sp
+
+/ =*, =/, =rem for longs
+/ Operands of the form &x op y, so stack space is known.
+cr86:
+%n,nl
+       SS
+       FS
+       jsr     pc,I
+       add     $6,sp
+
+/ convert integer to character (sign extend)
+cr109:
+%n,n
+       F
+       movb    R,R
+
+/
+/ c code tables -- compile for side effects.
+/ Also set condition codes properly (except for ++, --)
+/
+
+.globl _efftab
+
+.data
+_efftab=.
+       30.;    ci70
+       31.;    ci70
+       32.;    ci70
+       33.;    ci70
+       80.;    ci80
+       70.;    ci70
+       71.;    ci70    / - like +
+       78.;    ci78
+       79.;    ci79
+       85.;    ci78
+       75.;    ci75
+       76.;    ci76
+       16.;    ci16
+       116.;   ci116
+       0
+.text
+
+/ =
+ci80:
+%[move1:]
+%a,z
+%ad,zf
+       I'B1    A1
+
+%[move2:]
+%n*,z
+%nd*,zf
+       F*
+       I'B1    #1(R)
+
+%[move3:]
+%a,aw
+%ab,a
+       IBE     A2,A1
+
+%[move4:]
+%ab,n*
+%a,nw*
+       S*
+       IBE     #2(R),A1
+
+%[move5:]
+%a,n
+       S
+       IB1     R,A1
+
+%[move6:]
+%n*,aw
+%nb*,a
+       F*
+       IBE     A2,#1(R)
+
+%[move7:]
+%n*,ew*
+%nb*,e*
+       F*
+       S1*
+       IBE     #2(R1),#1(R)
+
+%[move8:]
+%n*,e
+       F*
+       S1
+       IB1     R1,#1(R)
+
+%[move9:]
+%e*,nw*
+%eb*,n*
+       S*
+       F1*
+       IBE     #2(R),#1(R1)
+
+%[move10:]
+%e*,n
+       S
+       F1*
+       IB1     R,#1(R1)
+
+%[move11:]
+%n*,nw*
+%nb*,n*
+       FS*
+       S*
+       IBE     #2(R),*(sp)+
+
+%[move12:]
+%n*,n
+       FS*
+       S
+       IB1     R,*(sp)+
+
+%aw,nf
+       S
+       movfi   R,A1
+
+%ew*,nf
+       S
+       F1*
+       movfi   R,#1(R1)
+
+%al,z
+       clr     A1
+       clr     A1+
+
+%nl*,z
+       F*
+       clr     #1(R)
+       clr     2+#1(R)
+
+%[move13a:]
+%al,aw
+       I       A2,A1+
+       V       A1
+
+%al,nw*
+       S*
+       mov     #2(R),A1+
+       V       A1
+
+%al,n
+       S
+       mov     R,A1+
+       V       A1
+
+%al,nf
+       S
+       setl
+       movfi   R,A1
+       seti
+
+%el*,nf
+       S
+       F1*
+       setl
+       movfi   R,#1(R1)
+       seti
+
+%[move13:]
+%al,al
+       I       A2,A1
+       I       A2+,A1+
+       V       A1
+
+%[move14:]
+%al,nl*
+       S*
+       I       #2(R),A1
+       I       #2+2(R),A1+
+       V       A1
+
+%[move15:]
+%al,nl
+       S
+       I       R,A1
+       I       R+,A1+
+       V       A1
+
+%[move14a:]
+%nl*,aw
+       F*
+       I       A2,#1+2(R)
+       V       #1(R)
+
+%[move16a:]
+%nl*,al
+       F*
+       I       A2+,#1+2(R)
+       V       #1(R)
+       I       A2,#1(R)
+
+%[move16:]
+%el*,nl
+       S
+       F1*
+       I       R+,#1+2(R1)
+       V       #1(R1)
+       I       R,#1(R1)
+
+%nl*,n
+       SS
+       F*
+       mov     (sp)+,#1+2(R)
+       V       #1(R)
+
+%[move17:]
+%nl*,nl
+       SS
+       F*
+       I       (sp)+,#1(R)
+       I       (sp)+,#1+2(R)
+       V       #1(R)
+
+/ =| and =& ~
+ci78:
+%a,aw
+%ab,a
+%      [move3]
+
+%a,n
+%      [move5]
+
+%n*,aw
+%nb*,a
+%      [move6]
+
+%n*,ew*
+%nb*,e*
+%      [move7]
+
+%n*,e
+%      [move8]
+
+%e*,nw*
+%eb*,n*
+%      [move9]
+
+%e*,n
+%      [move10]
+
+%n*,nw*
+%nb*,n*
+%      [move11]
+
+%n*,n
+%      [move12]
+
+%al,c
+%al,au
+%      [move13a]
+
+%al,al
+%      [move13]
+
+%al,nl*
+%      [move14]
+
+%al,nl
+%      [move15]
+
+%nl*,c
+%      [move14a]
+
+%nl*,al
+%      [move16a]
+
+%el*,nl
+%      [move16]
+
+%nl*,nl
+%      [move17]
+
+/ =^
+ci79:
+%al,nl
+%      [move15]
+
+%el*,nl
+%      [move16]
+
+%nl*,nl
+       FS*
+       S
+       I       R,*(sp)
+       mov     (sp)+,R
+       I       R+,2(R)
+
+/ =+
+ci70:
+%n*,z
+%a,z
+
+%a,1
+       I'B1    A1
+
+%aw,aw
+%      [move3]
+
+%aw,nw*
+%      [move4]
+
+%aw,n
+%      [move5]
+
+%n*,1
+%      [move2]
+
+%ew*,nw*
+%      [move9]
+
+%a,nw*
+       S*
+       movB1   A1',R1
+       I       #2(R),R1
+       movB1   R1,A1''
+
+%a,n
+       S
+       movB1   A1',R1
+       I       R,R1
+       movB1   R1,A1''
+
+%ew*,n
+%      [move10]
+
+%nw*,n
+%      [move12]
+
+%n*,n
+       SS
+       F*
+       movB1   #1(R),R1
+       I       (sp)+,R1
+       movB1   R1,#1(R)
+
+%al,c
+%al,au
+%      [move13a]
+
+%al,al
+%      [move13]
+
+%al,nl*
+%      [move14]
+
+%al,nl
+%      [move15]
+
+%nl*,c
+%nl*,au
+%      [move14a]
+
+%nl*,al
+%      [move16a]
+
+%el*,nl
+%      [move16]
+
+%nl*,nl
+%      [move17]
+
+/ =>> (all harder cases handled by =<< -)
+ci75:
+%a,1
+       asrB1   A1
+
+%n*,1
+       F*
+       asrB1   #1(R)
+
+/ =<<
+ci76:
+%a,1
+       aslB1   A1
+
+%n*,1
+       F*
+       aslB1   #1(R)
+
+%r,aw
+       ash     A2,A1
+
+%r,nw*
+       S*
+       ash     #2(R),A1
+
+%r,n
+       S
+       ash     R,A1
+
+/ =<< for longs
+cr92:
+%al,aw
+       F
+       ashc    A2,R
+       mov     R,A1
+       mov     R+,A1+
+
+%al,n
+       SS
+       F
+       ashc    (sp)+,R
+       mov     R,A1
+       mov     R+,A1+
+
+%nl*,n
+       FS*
+       SS
+       mov     2(sp),R
+       mov     2(R),R+
+       mov     (R),R
+       ashc    (sp)+,R
+       mov     R,*(sp)
+       add     $2,(sp)
+       mov     R+,*(sp)+
+
+/ field = ...
+ci16:
+%a,a
+       bicB1   Z,A1'
+       bisB1   A2,A1''
+
+%a,n
+       S
+       bicB1   Z,A1'
+       bisB1   R,A1''
+
+%n*,a
+       F*
+       bicB1   Z,#1(R)
+       bisB1   A2,#1(R)
+
+%[fas1:]
+%e*,n
+       S
+       F1*
+       bicB1   Z,#1(R1)
+       bisB1   R,#1(R1)
+
+%n*,e
+       F*
+       S1
+       bicB1   Z,#1(R)
+       bisB1   R1,#1(R)
+
+%n*,n
+       SS
+       F*
+       bicB1   Z,#1(R)
+       bisB1   (sp)+,#1(R)
+
+/
+/ c code tables-- set condition codes
+/
+
+.globl _cctab
+
+.data
+_cctab=.
+       106.;   cc60
+       28.;    rest
+       55.;    rest
+       34.;    rest
+       35.;    rest
+       36.;    rest
+       37.;    rest
+       40.;    rest
+       41.;    rest
+       42.;    rest
+       43.;    rest
+       81.;    cc81    / & as in "if ((a&b)==0)"
+       48.;    rest
+       60.;    cc60
+       61.;    cc60
+       62.;    cc60
+       63.;    cc60
+       64.;    cc60
+       65.;    cc60
+       66.;    cc60
+       67.;    cc60
+       68.;    cc60
+       69.;    cc60
+       72.;    rest
+       73.;    rest
+       79.;    rest
+       0
+.text
+
+/ relationals
+cc60:
+%a,z
+%ad,zf
+%      [move1]
+
+%af,z
+       movof   A1,R
+
+%n*,z
+%nd*,zf
+%      [move2]
+
+%nf*,z
+       F*
+       movof   #1(R),R
+
+%n,z
+%nf,zf
+       FC
+
+%aw,aw
+%ab,ab
+%      [move3]
+
+%nw*,aw
+%nb*,ab
+%      [move6]
+
+%n,aw
+%nf,ad
+%      [add1]
+
+%nw*,ew*
+%nb*,eb*
+%      [move7]
+
+%nw*,e
+%      [move8]
+
+%n,ew*
+%nf,ed*
+%      [add2]
+
+%n,e
+%nf,ef
+%      [add3]
+
+%nw*,nw*
+%nb*,nb*
+%      [move11]
+
+%nw*,n
+%      [move12]
+
+%n,n
+%nf,nf
+%      [add5]
+
+%al,z
+       tst     A1
+       X0
+       tst     A1+
+       X1
+
+%al,c
+%al,au
+       tst     A1
+       X0
+       cmp     A1+,A2
+       X1
+
+%[lcmp1:]
+%al,al
+       I       A1,A2
+       X0
+       I       A1+,A2+
+       X1
+
+%nl*,z
+       F*
+       tst     #1(R)
+       X0
+       tst     #1+2(R)
+       X1
+
+%nl*,c
+%nl*,au
+       F*
+       tst     #1(R)
+       X0
+       cmp     #1+2(R),A2
+       X1
+
+%[lcmp2:]
+%nl*,al
+       F*
+       I       #1(R),A2
+       X0
+       I       #1+2(R),A2+
+       X1
+
+%nl,z
+       F
+       tst     R
+       X0
+       tst     R+
+       X1
+
+%nl,c
+%nl,au
+       F
+       tst     R
+       X0
+       cmp     R+,A2
+       X1
+
+%[lcmp3:]
+%nl,al
+       F
+       I       R,A2
+       X0
+       I       R+,A2+
+       X1
+
+%[lcmp4:]
+%nl*,el*
+       F*
+       S1*
+       I       #1(R),#2(R1)
+       X0
+       I       #1+2(R),#2+2(R1)
+       X1
+
+%[lcmp5:]
+%nl,el*
+       F
+       S1*
+       I       R,#2(R1)
+       X0
+       I       R+,#2+2(R1)
+       X1
+
+%[lcmp6:]
+%nl,nl
+       FS
+       S
+       mov     R,-(sp)
+       mov     4(sp),R
+       mov     (sp)+,2(sp)
+       I       (sp)+,(sp)+
+       X0
+       I       R,R+
+       X1
+
+/ & as in "if ((a&b) ==0)"
+cc81:
+%a,a
+%      [move3]
+
+%n*,a
+%      [move6]
+
+%n,a
+%      [add1]
+
+%n,e
+%      [add3]
+
+%n,n
+%      [add5]
+
+%al,c
+%al,au
+       /bit    $0,A1
+       /X0
+       bit     A2,A1+
+       X1
+
+%nl*,c
+%nl*,au
+       F*
+       /bit    $0,#2(R)
+       /X0
+       bit     A2,#2+2(R)
+       X1
+
+%al,al
+%      [lcmp1]
+
+%nl*,al
+%      [lcmp2]
+
+%nl,al
+%      [lcmp3]
+
+%nl*,el*
+%      [lcmp4]
+
+%nl,el*
+%      [lcmp5]
+
+%nl,nl
+%      [lcmp6]
+
+%nl,c
+%nl,au
+       F
+       /bit    $0,R
+       /X0
+       bit     A2,R+
+       X1
+
+/ set codes right
+rest:
+%n,n
+%nf,nf
+       H
+
+/
+/ c code tables-- expression to -(sp)
+/
+
+.globl _sptab
+
+.data
+_sptab=.
+       106.;   cs106
+       40.;    cs40
+       41.;    cs40
+       55.;    cs40
+       48.;    cs40
+       58.;    cs58
+       56.;    cs56
+       0
+.text
+
+/ name
+cs106:
+%z,n
+%zf,n
+       clrB1   -(sp)
+
+%aw,n
+       mov     A1,-(sp)
+
+%nw*,n
+       F*
+       mov     #1(R),-(sp)
+
+%al,n
+       mov     A1+,-(sp)
+       mov     A1,-(sp)
+
+/ +, -, |, &~
+cs40:
+%a,1
+       FS
+       I'      (sp)
+
+%a,aw
+       FS
+       I       A2,(sp)
+
+%a,nw*
+       FS
+       S*
+       I       #2(R),(sp)
+
+%a,n
+       FS
+       S
+       I       R,(sp)
+
+/ integer to long
+cs58:
+%nu,n
+       FS
+       clr     -(sp)
+
+%n,n
+       FS
+       sxt     -(sp)
+
+/ float to long
+cs56:
+%nf,n
+       F
+       setl
+       movfi   R,-(sp)
+       seti
+
+/ setup for structure assign
+ci116:
+%n,e
+       F!
+       S1!
+
+%n,n
+       SS
+       F!
+       mov     (sp)+,r1
+