*** empty log message ***
authorsater <none@none>
Tue, 8 Jan 1985 15:34:54 +0000 (15:34 +0000)
committersater <none@none>
Tue, 8 Jan 1985 15:34:54 +0000 (15:34 +0000)
25 files changed:
mach/proto/ncg/assert.h [new file with mode: 0644]
mach/proto/ncg/codegen.c [new file with mode: 0644]
mach/proto/ncg/compute.c [new file with mode: 0644]
mach/proto/ncg/data.h [new file with mode: 0644]
mach/proto/ncg/equiv.c [new file with mode: 0644]
mach/proto/ncg/equiv.h [new file with mode: 0644]
mach/proto/ncg/extern.h [new file with mode: 0644]
mach/proto/ncg/fillem.c [new file with mode: 0644]
mach/proto/ncg/gencode.c [new file with mode: 0644]
mach/proto/ncg/glosym.c [new file with mode: 0644]
mach/proto/ncg/glosym.h [new file with mode: 0644]
mach/proto/ncg/main.c [new file with mode: 0644]
mach/proto/ncg/move.c [new file with mode: 0644]
mach/proto/ncg/nextem.c [new file with mode: 0644]
mach/proto/ncg/param.h [new file with mode: 0644]
mach/proto/ncg/reg.c [new file with mode: 0644]
mach/proto/ncg/regvar.c [new file with mode: 0644]
mach/proto/ncg/regvar.h [new file with mode: 0644]
mach/proto/ncg/result.h [new file with mode: 0644]
mach/proto/ncg/salloc.c [new file with mode: 0644]
mach/proto/ncg/state.c [new file with mode: 0644]
mach/proto/ncg/state.h [new file with mode: 0644]
mach/proto/ncg/subr.c [new file with mode: 0644]
mach/proto/ncg/types.h [new file with mode: 0644]
mach/proto/ncg/var.c [new file with mode: 0644]

diff --git a/mach/proto/ncg/assert.h b/mach/proto/ncg/assert.h
new file mode 100644 (file)
index 0000000..3cc93b8
--- /dev/null
@@ -0,0 +1,7 @@
+/* $Header$ */
+
+#ifndef NDEBUG
+#define assert(x) if(!(x)) badassertion("x",__FILE__,__LINE__)
+#else
+#define assert(x)      /* nothing */
+#endif
diff --git a/mach/proto/ncg/codegen.c b/mach/proto/ncg/codegen.c
new file mode 100644 (file)
index 0000000..b9e862c
--- /dev/null
@@ -0,0 +1,874 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "state.h"
+#include "equiv.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+#define ALLOW_NEXTEM   /* code generator is allowed new try of NEXTEM
+                          in exceptional cases */
+
+#define MAXPATTERN 5
+#define MAXREPLLEN 5    /* Max length of EM-replacement, should come from boot */
+
+byte startupcode[] = { DO_NEXTEM };
+
+byte *nextem();
+unsigned costcalc();
+unsigned docoerc();
+unsigned stackupto();
+string tostring();
+string ad2str();
+
+#ifdef NDEBUG
+#define DEBUG(string)
+#else
+#include <stdio.h>
+#define DEBUG(string) {if(Debug) fprintf(stderr,"%-*d%s\n",4*level,level,string);}
+#endif
+
+#define BROKE() {assert(origcp!=startupcode);DEBUG("BROKE");totalcost=INFINITY;goto doreturn;}
+#define CHKCOST() {if (totalcost>=costlimit) BROKE();}
+
+#ifdef TABLEDEBUG
+int tablelines[MAXTDBUG];
+int ntableline;
+int set_fd,set_size;
+short *set_val;
+char *set_flag;
+#endif
+
+unsigned codegen(codep,ply,toplevel,costlimit,forced) byte *codep; unsigned costlimit; {
+#ifndef NDEBUG
+       byte *origcp=codep;
+       static int level=0;
+#endif
+       unsigned totalcost = 0;
+       int inscoerc=0;
+       int procarg[2];
+#ifdef ALLOW_NEXTEM
+       int paniced;
+       char *savebp;
+#endif
+       state_t state;
+#define SAVEST savestatus(&state)
+#define RESTST restorestatus(&state)
+#define FREEST /* nothing */
+#ifdef TABLEDEBUG
+       extern char *tablename;
+#endif
+
+#ifndef NDEBUG
+       level++;
+       DEBUG("Entering codegen");
+#endif
+       for (;;) {
+       switch( (*codep++)&037 ) {
+    default:
+       assert(FALSE);
+       /* NOTREACHED */
+#ifdef TABLEDEBUG
+    case DO_DLINE: {
+       int n;
+
+       getint(n,codep);
+       tablelines[ntableline++] = n;
+       if (ntableline>=MAXTDBUG)
+               ntableline -= MAXTDBUG;
+       if (set_fd)
+               set_val[n>>4] &= ~(1<<(n&017));
+#ifndef NDEBUG
+       if (Debug)
+               fprintf(stderr,"code from \"%s\", line %d\n",tablename,n);
+#endif
+       break;
+    }
+#endif
+    case DO_NEXTEM: {
+       byte *bp;
+       int n;
+       unsigned mindistance,dist;
+       register i;
+       int cindex;
+       int npos,pos[MAXRULE];
+       unsigned mincost,t;
+
+       DEBUG("NEXTEM");
+       tokpatlen = 0;
+       nallreg=0;
+       if (toplevel) {
+               garbage_collect();
+               totalcost=0;
+       } else {
+               if (--ply <= 0)
+                       goto doreturn;
+       }
+       if (stackheight>MAXFSTACK-7) {
+#ifndef NDEBUG
+               if (Debug)
+                       fprintf(stderr,"Fakestack overflow threatens(%d), action ...\n",stackheight);
+#endif
+               totalcost += stackupto(&fakestack[6],ply,toplevel);
+       }
+#ifndef ALLOW_NEXTEM
+       bp = nextem(toplevel);
+#else
+       paniced=0;
+       savebp = nextem(toplevel);
+    panic:
+       bp = savebp;
+#endif
+       if (bp == 0) {
+               /*
+                * No pattern found, can be pseudo or error
+                * in table.
+                */
+               if (toplevel) {
+                       codep--;
+                       DEBUG("pseudo");
+                       dopseudo();
+               } else
+                       goto doreturn;
+       } else {
+#ifndef NDEBUG
+               chkregs();
+#endif
+               n = *bp++;
+               if (n==0) {     /* "procedure" */
+                       getint(i,bp);
+                       getint(procarg[0],bp);
+                       getint(procarg[1],bp);
+                       bp= &pattern[i];
+                       n = *bp++;
+                       DEBUG("PROC_CALL");
+               }
+               assert(n>0 && n<=MAXRULE);
+               if (n>1) {
+                       mindistance = MAXINT; npos=0;
+                       for(i=0;i<n;i++) {
+                               getint(cindex,bp);
+                               dist=distance(cindex);
+#ifndef NDEBUG
+if (Debug)
+       fprintf(stderr,"distance of pos %d is %u\n",i,dist);
+#endif
+                               if (dist<=mindistance) {
+                                       if (dist<mindistance) {
+                                               if(dist==0)
+                                                       goto gotit;
+                                               npos=0;
+                                               mindistance = dist;
+                                       }
+                                       pos[npos++] = cindex;
+                               }
+                       }
+                       assert(mindistance<MAXINT);
+                       if (npos>1) {
+                               /*
+                                * More than 1 tokenpattern is a candidate.
+                                * Decision has to be made by lookahead.
+                                */
+                               SAVEST;
+                               mincost = costlimit-totalcost+1;
+                               for(i=0;i<npos;i++) {
+                                       t=codegen(&coderules[pos[i]],ply,FALSE,mincost,0);
+#ifndef NDEBUG
+if (Debug)
+       fprintf(stderr,"mincost %u,cost %u,pos %d\n",mincost,t,i);
+#endif
+                                       if (t<mincost) {
+                                               mincost = t;
+                                               cindex = pos[i];
+                                       }
+                                       RESTST;
+                               }
+                               FREEST;
+                               if (totalcost+mincost>costlimit)
+                                       BROKE();
+                       } else {
+                               cindex = pos[0];
+                       }
+               } else {
+                       getint(cindex,bp);
+               }
+
+       gotit:
+               /*
+                * Now cindex contains the code-index of the best candidate
+                * so proceed to use it.
+                */
+               codep = &coderules[cindex];
+       }
+       break;
+    }
+    case DO_COERC: {
+       DEBUG("COERC");
+       tokpatlen=1;
+       inscoerc=1;
+       break;
+    }
+    case DO_XXMATCH:
+       DEBUG("XXMATCH");
+    case DO_XMATCH: {
+       register i;
+       int temp;
+
+       DEBUG("XMATCH");
+       tokpatlen=(codep[-1]>>5)&07;
+       for (i=0;i<tokpatlen;i++)
+               getint(temp,codep);
+       break;  /* match already checked by distance() */
+    }
+    case DO_MATCH: {
+       register i;
+       int j;
+       unsigned mincost,t;
+       token_p tp;
+       int size,lsize;
+       int tokexp[MAXPATTERN];
+       int nregneeded;
+       token_p regtp[MAXCREG];
+       c3_p regcp[MAXCREG];
+       rl_p regls[MAXCREG];
+       c3_p cp,findcoerc();
+       int sret;
+       int stackpad;
+       struct perm *tup,*ntup,*besttup,*tuples();
+
+       DEBUG("MATCH");
+       tokpatlen=(codep[-1]>>5)&07;
+       for(i=0;i<tokpatlen;i++)
+               getint(tokexp[i],codep);
+       tokexp[i] = 0;
+       tp = &fakestack[stackheight-1];
+       i=0;
+       while (i<tokpatlen && tp>=fakestack) {
+               size=tsize(tp);
+               while (i<tokpatlen && (lsize=ssize(tokexp[i]))<=size) {
+                       size -= lsize;
+                       i++;
+               }
+               if (i<tokpatlen && size!=0) {
+                       totalcost += stackupto(tp,ply,toplevel);
+                       CHKCOST();
+                       break;
+               }
+               tp--;
+       }
+       tp = &fakestack[stackheight-1];
+       i=0;
+       while (i<tokpatlen && tp >= fakestack) {
+               size = tsize(tp);
+               lsize= ssize(tokexp[i]);
+               if (size != lsize) {    /* find coercion */
+#ifdef MAXSPLIT
+                       sret = split(tp,&tokexp[i],ply,toplevel);
+                       if (sret==0) {
+#endif MAXSPLIT
+                               totalcost += stackupto(tp,ply,toplevel);
+                               CHKCOST();
+                               break;
+#ifdef MAXSPLIT
+                       }
+                       i += sret;
+#endif MAXSPLIT
+               } else
+                       i += 1;
+               tp--;
+       }
+    nextmatch:
+       tp = &fakestack[stackheight-1];
+       i=0; nregneeded = 0;
+       while (i<tokpatlen && tp>=fakestack) {
+               if (!match(tp,&machsets[tokexp[i]],0)) {
+                       cp = findcoerc(tp, &machsets[tokexp[i]]);
+#ifndef NDEBUG
+if (Debug>1) fprintf(stderr,"findcoerc returns %d at position %d\n",cp,i);
+#endif
+                       if (cp==0) {
+                               for (j=0;j<nregneeded;j++)
+                                       regtp[j] -= (tp-fakestack+1);
+                               totalcost += stackupto(tp,ply,toplevel);
+                               CHKCOST();
+                               break;
+                       } else {
+                               if (cp->c3_prop==0) {
+                                       totalcost+=docoerc(tp,cp,ply,toplevel,0);
+                                       CHKCOST();
+                               } else {
+#ifndef NDEBUG
+if(Debug>1) fprintf(stderr,"Register of type %d needed, remembering...\n",cp->c3_prop);
+#endif
+                                       assert(nregneeded<MAXCREG);
+                                       regtp[nregneeded] = tp;
+                                       regcp[nregneeded] = cp;
+                                       regls[nregneeded] = curreglist;
+                                       nregneeded++;
+                               }
+                       }
+               }
+               i++; tp--;
+       }
+       if (tokpatlen>stackheight) {
+#ifndef NDEBUG
+if(Debug>1) fprintf(stderr,"Pattern too long, %d with only %d items on stack\n",
+               tokpatlen,stackheight);
+#endif
+               stackpad = tokpatlen-stackheight;
+               for (j=stackheight-1;j>=0;j--)
+                       fakestack[j+stackpad] = fakestack[j];
+               for (j=0;j<stackpad;j++)
+                       fakestack[j].t_token=0;
+               stackheight += stackpad;
+               for (j=0;j<nregneeded;j++)
+                       regtp[j] += stackpad;
+               for (tp = &fakestack[stackpad-1];i<tokpatlen && tp>=fakestack;i++,tp--) {
+                       cp = findcoerc((token_p) 0, &machsets[tokexp[i]]);
+                       if (cp==0) {
+                               for (j=0;j<nregneeded;j++)
+                                       myfree(regls[j]);
+#ifndef ALLOW_NEXTEM
+                               assert(!toplevel);
+                               BROKE();
+#else
+                               assert(!(toplevel&&paniced));
+                               goto normalfailed;
+#endif
+                       }
+                       if (cp->c3_prop==0) {
+                               totalcost+=docoerc(tp,cp,ply,toplevel,0);
+                               CHKCOST();
+                       } else {
+                               assert(nregneeded<MAXCREG);
+                               regtp[nregneeded] = tp;
+                               regcp[nregneeded] = cp;
+                               regls[nregneeded] = curreglist;
+                               nregneeded++;
+                       }
+               }
+       } else
+               stackpad=0;
+       assert(i==tokpatlen);
+       if (nregneeded==0)
+               break;
+       SAVEST;
+       mincost=costlimit-totalcost+1;
+       tup = tuples(regls,nregneeded);
+       besttup=0;
+       for (; tup != 0; tup = ntup) {
+#ifndef NDEBUG
+if(Debug>1) fprintf(stderr,"Next tuple %d,%d,%d,%d\n",
+                       tup->p_rar[0],
+                       tup->p_rar[1],
+                       tup->p_rar[2],
+                       tup->p_rar[3]);
+#endif
+               ntup = tup->p_next;
+               for (i=0,t=0;i<nregneeded && t<mincost; i++)
+                       t += docoerc(regtp[i],regcp[i],ply,FALSE,tup->p_rar[i]);
+               if (t<mincost) {
+#ifndef NDEBUG
+                       if (Debug>2)
+                               fprintf(stderr,"Continuing match after coercions\n");
+#endif
+                       t += codegen(codep,ply,FALSE,mincost-t,0);
+               }
+               if (t<mincost) {
+                       mincost = t;
+                       besttup = tup;
+               } else
+                       myfree(tup);
+               RESTST;
+       }
+       FREEST;
+       for (i=0;i<nregneeded;i++)
+               myfree(regls[i]);
+       if (totalcost+mincost>costlimit) {
+               if (besttup)
+                       myfree(besttup);
+normalfailed:  if (stackpad!=tokpatlen) {
+                       if (stackpad) {
+                               if (costlimit<MAXINT)
+                                       BROKE();
+                               for (i=0;i<stackheight-stackpad;i++)
+                                       fakestack[i] = fakestack[i+stackpad];
+                               stackheight -= stackpad;
+                               totalcost += stackupto(&fakestack[stackheight-1],ply,toplevel);
+                       } else
+                               totalcost += stackupto(fakestack,ply,toplevel);
+                       CHKCOST();
+                       goto nextmatch;
+               }
+               totalcost += mincost;
+#ifndef ALLOW_NEXTEM
+               BROKE();
+#else
+               if (toplevel && !paniced) {
+                       stackheight=0;
+                       paniced++;
+                       DEBUG("PANIC!");
+                       goto panic;
+               } else
+                       BROKE();
+#endif
+       }
+       for (i=0;i<nregneeded;i++)
+               totalcost += docoerc(regtp[i],regcp[i],ply,toplevel,besttup->p_rar[i]);
+       myfree(besttup);
+       break;
+    }
+    case DO_REMOVE: {
+       int texpno,nodeno;
+       token_p tp;
+       struct reginfo *rp;
+
+       DEBUG("REMOVE");
+       if (codep[-1]&32) {
+               getint(texpno,codep);
+               getint(nodeno,codep);
+       } else {
+               getint(texpno,codep);
+               nodeno=0;
+       }
+       for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
+               if (match(tp,&machsets[texpno],nodeno)) {
+                       /* investigate possible coercion to register */
+                       totalcost += stackupto(tp,ply,toplevel);
+                       CHKCOST();
+                       break;
+               }
+       for (rp=machregs;rp<machregs+NREGS;rp++)
+               if (match(&rp->r_contents,&machsets[texpno],nodeno))
+                       rp->r_contents.t_token=0;
+       break;
+    }
+    case DO_RREMOVE: { /* register remove */
+       register i;
+       int nodeno;
+       token_p tp;
+       tkdef_p tdp;
+       result_t result;
+
+       getint(nodeno,codep);
+       result=compute(&enodes[nodeno]);
+       assert(result.e_typ==EV_REG);
+       for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
+               if (tp->t_token==-1) {
+                       if(tp->t_att[0].ar==result.e_v.e_reg)
+                               goto gotone;
+               } else {
+                       tdp = &tokens[tp->t_token];
+                       for(i=0;i<TOKENSIZE;i++)
+                               if (tdp->t_type[i]==EV_REG &&
+                                   tp->t_att[i].ar==result.e_v.e_reg)
+                                       goto gotone;
+               }
+       break;
+    gotone:
+       /* investigate possible coercion to register */
+       totalcost += stackupto(tp,ply,toplevel);
+       CHKCOST();
+       break;
+    }
+    case DO_DEALLOCATE: {
+       register i;
+       tkdef_p tdp;
+       int tinstno;
+       token_t token;
+
+       DEBUG("DEALLOCATE");
+       getint(tinstno,codep);
+       instance(tinstno,&token);
+       if (token.t_token==-1)
+               chrefcount(token.t_att[0].ar,-1,TRUE);
+       else {
+               tdp= &tokens[token.t_token];
+               for (i=0;i<TOKENSIZE;i++)
+                       if (tdp->t_type[i]==EV_REG)
+                               chrefcount(token.t_att[i].ar,-1,TRUE);
+       }
+       break;
+    }
+    case DO_REALLOCATE: {
+       struct reginfo *rp;
+
+       DEBUG("REALLOCATE");
+       for(rp=machregs+1;rp<machregs+NREGS;rp++)
+               if(rp->r_tcount) {
+                       rp->r_refcount -= rp->r_tcount;
+                       rp->r_tcount = 0;
+               }
+       break;
+    }
+    case DO_ALLOCATE: {
+       register i;
+       int j;
+       int tinstno;
+       int npos,npos2,pos[NREGS],pos2[NREGS];
+       unsigned mincost,t;
+       struct reginfo *rp,**rpp;
+       token_t token,mtoken,token2;
+       int propno;
+       int exactmatch;
+       int decision;
+
+       if (codep[-1]&32) {
+               getint(propno,codep);
+               getint(tinstno,codep);
+               DEBUG("ALLOCATE,INIT");
+       } else {
+               getint(propno,codep);
+               tinstno=0;
+               DEBUG("ALLOCATE,EMPTY");
+       }
+       instance(tinstno,&token);
+       if (!forced) {
+               do {
+                       npos=exactmatch=0;
+                       for(rpp=reglist[propno];rp= *rpp; rpp++)
+                               if (getrefcount(rp-machregs)==0) {
+                                       pos[npos++] = rp-machregs;
+                                       if (eqtoken(&rp->r_contents,&token))
+                                               exactmatch++;
+                               }
+                       /*
+                        * Now pos[] contains all free registers with desired
+                        * property. If none then some stacking has to take place.
+                        */
+                       if (npos==0) {
+                               if (stackheight<=tokpatlen) {
+                                       if (!toplevel) {
+                                               BROKE();
+                                       } else
+                                               fatal("No regs available");
+                               }
+                               totalcost += stackupto( &fakestack[0],ply,toplevel);
+                               CHKCOST();
+                       }
+               } while (npos==0);
+               if (!exactmatch) {
+                       npos2=npos;
+                       for(i=0;i<npos;i++)
+                               pos2[i]=pos[i];
+               } else {
+                       /*
+                        * Now we are reducing the number of possible registers.
+                        * We take only one equally likely register out of every
+                        * equivalence class as given by set of properties.
+                        */
+                       mtoken = token;
+                       npos2=0;
+                       for(i=0;i<npos;i++)
+                               if (eqtoken(&machregs[pos[i]].r_contents,&mtoken)) {
+                                       pos2[npos2++] = pos[i];
+                                       for(j=0;j<npos2-1;j++)
+                                               if (eqregclass(pos2[j],pos[i])) {
+                                                       npos2--;
+                                                       break;
+                                               }
+                               }
+               }
+               /*
+                * Now pos2[] contains all possibilities to try, if more than
+                * one, lookahead is necessary.
+                */
+               token2.t_token= -1;
+               for (i=1;i<TOKENSIZE;i++)
+                       token2.t_att[i].aw=0;
+               if (npos2==1)
+                       decision=pos2[0];
+               else {
+                       SAVEST;
+                       mincost=costlimit-totalcost+1;
+                       for(j=0;j<npos2;j++) {
+                               chrefcount(pos2[j],1,FALSE);
+                               token2.t_att[0].ar=pos2[j];
+                               allreg[nallreg++] = pos2[j];
+                               if (token.t_token != 0)
+                                       t=move(&token,&token2,ply,FALSE,mincost);
+                               else {
+                                       t = 0;
+                                       erasereg(pos2[j]);
+                               }
+                               if (t<mincost)
+                                       t += codegen(codep,ply,FALSE,mincost-t,0);
+                               if (t<mincost) {
+                                       mincost=t;
+                                       decision=pos2[j];
+                               }
+                               RESTST;
+                       }
+                       FREEST;
+                       if (totalcost+mincost>costlimit)
+                               BROKE();
+               }
+       } else {
+               decision = forced;
+               if (getrefcount(decision)!=0)
+                       BROKE();
+               token2.t_token = -1;
+       }
+       chrefcount(decision,1,FALSE);
+       token2.t_att[0].ar=decision;
+       if (token.t_token != 0) {
+               totalcost+=move(&token,&token2,ply,toplevel,MAXINT);
+               CHKCOST();
+       } else
+               erasereg(decision);
+       allreg[nallreg++]=decision;
+       break;
+    }
+    case DO_INSTR: {
+       register i;
+       int n;
+       int tinstno;
+       token_t token;
+       int stringno;
+
+       DEBUG("INSTR");
+       n=((codep[-1]>>5)&07);
+       getint(stringno,codep);
+       if (toplevel) {
+               swtxt();
+               if (stringno>10000) {
+                       assert(stringno== 10001 || stringno== 10002);
+                       genstr(procarg[stringno-10001]);
+               } else
+                       genstr(stringno);
+       }
+       for(i=0;i<n;i++) {
+               getint(tinstno,codep);
+               instance(tinstno,&token);
+               if (toplevel)
+                       prtoken(&token,i==0 ? ' ' : ',');
+               if (token.t_token>0)
+                       totalcost += tokens[token.t_token].t_cost.ct_space;
+       }
+       if (toplevel)
+               gennl();
+       break;          
+    }
+    case DO_MOVE: {
+       int tinstno;
+       token_t token,token2;
+
+       DEBUG("MOVE");
+       getint(tinstno,codep);
+       instance(tinstno,&token);
+       getint(tinstno,codep);
+       instance(tinstno,&token2);
+       totalcost += move(&token,&token2,ply,toplevel,costlimit-totalcost+1);
+       CHKCOST();
+       break;
+    }
+    case DO_TEST: {
+       int tinstno;
+       token_t token;
+
+       DEBUG("TEST");
+       getint(tinstno,codep);
+       instance(tinstno,&token);
+       totalcost += test(&token,ply,toplevel,costlimit-totalcost+1);
+       CHKCOST();
+       break;
+    }
+    case DO_SETCC: {
+       int tinstno;
+       token_t token;
+
+       DEBUG("SETCC");
+       getint(tinstno,codep);
+       instance(tinstno,&token);
+       setcc(&token);
+       break;
+    }
+    case DO_ERASE: {
+       int nodeno;
+       result_t result;
+
+       DEBUG("ERASE");
+       getint(nodeno,codep);
+       result=compute(&enodes[nodeno]);
+       assert(result.e_typ!=EV_INT && result.e_typ!=EV_ADDR);
+       if (result.e_typ==EV_REG)
+               erasereg(result.e_v.e_reg);
+       break;
+    }
+    case DO_TOKREPLACE: {
+       register i;
+       int tinstno;
+       int repllen;
+       token_t reptoken[MAXREPLLEN];
+
+       DEBUG("TOKREPLACE");
+       assert(stackheight>=tokpatlen);
+       repllen=(codep[-1]>>5)&07;
+#ifndef NDEBUG
+       if (Debug>2)
+               fprintf(stderr,"Stackheight=%d, tokpatlen=%d, repllen=%d %s\n",
+                       stackheight,tokpatlen,repllen,inscoerc ? "(inscoerc)":"");
+#endif
+       for(i=0;i<repllen;i++) {
+               getint(tinstno,codep);
+               instance(tinstno,&reptoken[i]);
+               tref(&reptoken[i],1);
+       }
+       for(i=0;i<tokpatlen;i++) {
+               if (!inscoerc)
+                       tref(&fakestack[stackheight-1],-1);
+               stackheight--;
+       }
+       for (i=0;i<repllen;i++) {
+               assert(stackheight<MAXFSTACK);
+               fakestack[stackheight++] = reptoken[i];
+       }
+       for(i=0;i<nallreg;i++)
+               chrefcount(allreg[i],-1,FALSE);
+       break;
+    }
+    case DO_EMREPLACE: {
+       register i;
+       int j;
+       int nodeno;
+       result_t result;
+       int emrepllen,eminstr;
+
+       DEBUG("EMREPLACE");
+       emrepllen=(codep[-1]>>5)&07;
+       j=emp-emlines;
+       if (emrepllen>j) {
+               assert(nemlines+emrepllen-j<MAXEMLINES);
+               for (i=nemlines;i>=0;i--)
+                       emlines[i+emrepllen-j] = emlines[i];
+               nemlines += emrepllen-j;
+               emp += emrepllen-j;
+       }
+       emp -= emrepllen;
+       for (i=0;i<emrepllen;i++) {
+               getint(eminstr,codep);
+               getint(nodeno,codep);
+               emp[i].em_instr = eminstr;
+               result = compute(&enodes[nodeno]);
+               switch(result.e_typ) {
+               default:
+                       assert(FALSE);
+               case 0:
+                       emp[i].em_optyp = OPNO;
+                       emp[i].em_soper = 0;
+                       break;
+               case EV_INT:
+                       emp[i].em_optyp = OPINT;
+                       emp[i].em_soper = tostring(result.e_v.e_con);
+                       emp[i].em_u.em_ioper = result.e_v.e_con;
+                       break;
+               case EV_ADDR:
+                       emp[i].em_optyp = OPSYMBOL;
+                       emp[i].em_soper = ad2str(result.e_v.e_addr);
+                       break;
+               }
+       }
+       if (!toplevel)
+               ply += emrepllen;
+       break;
+    }
+    case DO_COST: {
+       cost_t cost;
+
+       DEBUG("COST");
+       getint(cost.ct_space,codep);
+       getint(cost.ct_time,codep);
+       totalcost += costcalc(cost);
+       CHKCOST();
+       break;
+    }
+#ifdef REGVARS
+    case DO_PRETURN: {
+       if (toplevel) {
+               swtxt();
+               regreturn();    /* in mach.c */
+       }
+       break;
+    }
+#endif
+    case DO_RETURN:
+       DEBUG("RETURN");
+       assert(origcp!=startupcode);
+    doreturn:
+#ifndef NDEBUG
+       level--;
+#endif
+       return(totalcost);
+       }
+       }
+}
+
+readcodebytes() {
+#ifndef CODEINC
+       register fd;
+       extern int ncodebytes;
+
+       if ((fd=open("code",0))<0) {
+               error("Can't open code");
+       }
+       if (read(fd,coderules,ncodebytes)!=ncodebytes) {
+               error("Short read from code");
+       }
+       close(fd);
+#endif
+}
+
+#ifdef TABLEDEBUG
+initlset(f) char *f; {
+       extern char *myalloc();
+
+       set_flag = f;
+       if ((set_fd=open(f+1,2))<0)
+               error("Can't open %s rw",f+1);
+       read(set_fd,&set_size,sizeof(int));
+       set_val=( short *) myalloc(set_size);
+       read(set_fd,set_val,set_size);
+}
+
+termlset() {
+
+       if (set_fd) {
+               lseek(set_fd,(long) sizeof(int),0);
+               write(set_fd,set_val,set_size);
+               close(set_fd);
+               if (set_flag[0]=='u') {
+                       register i;
+                       
+                       fprintf(stderr,"Unused code rules:\n\n");
+                       for(i=0;i<8*set_size;i++)
+                               if(set_val[i>>4]&(1<<(i&017)))
+                                       fprintf(stderr,"\"%s\", line %d\n",tablename,i);
+               }
+       }
+}
+#endif
diff --git a/mach/proto/ncg/compute.c b/mach/proto/ncg/compute.c
new file mode 100644 (file)
index 0000000..4682fb7
--- /dev/null
@@ -0,0 +1,366 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "glosym.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+#define LLEAF 01
+#define LDEF  02
+#define RLEAF 04
+#define RDEF  010
+#define LLDEF LLEAF|LDEF
+#define RLDEF RLEAF|RDEF
+
+char opdesc[] = {
+       0,                      /* EX_TOKFIELD */
+       0,                      /* EX_ARG */
+       0,                      /* EX_CON */
+       0,                      /* EX_ALLREG */
+       LLDEF|RLDEF,            /* EX_SAMESIGN */
+       LLDEF|RLDEF,            /* EX_SFIT */
+       LLDEF|RLDEF,            /* EX_UFIT */
+       0,                      /* EX_ROM */
+       LLDEF|RLDEF,            /* EX_NCPEQ */
+       LLDEF|RLDEF,            /* EX_SCPEQ */
+       LLDEF|RLDEF,            /* EX_RCPEQ */
+       LLDEF|RLDEF,            /* EX_NCPNE */
+       LLDEF|RLDEF,            /* EX_SCPNE */
+       LLDEF|RLDEF,            /* EX_RCPNE */
+       LLDEF|RLDEF,            /* EX_NCPGT */
+       LLDEF|RLDEF,            /* EX_NCPGE */
+       LLDEF|RLDEF,            /* EX_NCPLT */
+       LLDEF|RLDEF,            /* EX_NCPLE */
+       LLDEF,                  /* EX_OR2 */
+       LLDEF,                  /* EX_AND2 */
+       LLDEF|RLDEF,            /* EX_PLUS */
+       LLDEF|RLDEF,            /* EX_CAT */
+       LLDEF|RLDEF,            /* EX_MINUS */
+       LLDEF|RLDEF,            /* EX_TIMES */
+       LLDEF|RLDEF,            /* EX_DIVIDE */
+       LLDEF|RLDEF,            /* EX_MOD */
+       LLDEF|RLDEF,            /* EX_LSHIFT */
+       LLDEF|RLDEF,            /* EX_RSHIFT */
+       LLDEF,                  /* EX_NOT */
+       LLDEF,                  /* EX_COMP */
+       0,                      /* EX_COST */
+       0,                      /* EX_STRING */
+       LLEAF,                  /* EX_DEFINED */
+       0,                      /* EX_SUBREG */
+       LLDEF,                  /* EX_TOSTRING */
+       LLDEF,                  /* EX_UMINUS */
+       0,                      /* EX_REG */
+       0,                      /* EX_LOWW */
+       0,                      /* EX_HIGHW */
+       LLDEF,                  /* EX_INREG */
+       LLDEF,                  /* EX_REGVAR */
+};
+
+string salloc(),strcpy(),strcat();
+
+string mycat(s1,s2) register string s1,s2; {
+       register string s;
+
+       if (s1==0) return(s2);
+       if (s2==0) return(s1);
+       s=salloc(strlen(s1)+strlen(s2)+1);
+       strcpy(s,s1);
+       strcat(s,"+");
+       strcat(s,s2);
+       return(s);
+}
+
+string mystrcpy(s) register string s; {
+       register string r;
+
+       r=salloc(strlen(s));
+       strcpy(r,s);
+       return(r);
+}
+
+char digstr[21][15];
+
+string tostring(n) register word n; {
+       char buf[25];
+
+       if (n>=-20 && n<=20 && (n&1)==0) {
+               if (digstr[(n>>1)+10][0]==0)
+                       sprintf(digstr[(n>>1)+10],WRD_FMT,n);
+               return(digstr[(n>>1)+10]);
+       }
+       sprintf(buf,WRD_FMT,n);
+       return(mystrcpy(buf));
+}
+
+result_t undefres= {EV_UNDEF};
+
+result_t compute(node) register node_p node; {
+       result_t leaf1,leaf2,result;
+       register token_p tp;
+       int desc;
+       long mask,tmp;
+       int i,tmpreg;
+       glosym_p gp;
+
+       desc=opdesc[node->ex_operator];
+       if (desc&LLEAF) {
+               leaf1 = compute(&enodes[node->ex_lnode]);
+               if (desc&LDEF && leaf1.e_typ==EV_UNDEF)
+                       return(undefres);
+       }
+       if (desc&RLEAF) {
+               leaf2 = compute(&enodes[node->ex_rnode]);
+               if (desc&RDEF && leaf2.e_typ==EV_UNDEF)
+                       return(undefres);
+       }
+       result.e_typ=EV_INT;
+       switch(node->ex_operator) {
+       default:        assert(FALSE);
+       case EX_TOKFIELD:
+               if (node->ex_lnode!=0)
+                       tp = &fakestack[stackheight-node->ex_lnode];
+               else
+                       tp = curtoken;
+               switch(result.e_typ = tokens[tp->t_token].t_type[node->ex_rnode-1]) {
+               default:
+                       assert(FALSE);
+               case EV_INT:
+                       result.e_v.e_con = tp->t_att[node->ex_rnode-1].aw;
+                       break;
+               case EV_ADDR:
+                       result.e_v.e_addr = tp->t_att[node->ex_rnode-1].aa;
+                       break;
+               case EV_REG:
+                       result.e_v.e_reg = tp->t_att[node->ex_rnode-1].ar;
+                       break;
+               }
+               return(result);
+       case EX_ARG:
+               return(dollar[node->ex_lnode-1]);
+       case EX_CON:
+               result.e_typ = EV_INT;
+               result.e_v.e_con = ((long) node->ex_rnode << 16) | ((long)node->ex_lnode&0xffff);
+               return(result);
+       case EX_REG:
+               result.e_typ = EV_REG;
+               result.e_v.e_reg = node->ex_lnode;
+               return(result);
+       case EX_ALLREG:
+               result.e_typ = EV_REG;
+               result.e_v.e_reg = allreg[node->ex_lnode-1];
+#if MAXMEMBERS!=0
+               if (node->ex_rnode!=0)
+                       result.e_v.e_reg = machregs[result.e_v.e_reg].
+                               r_members[node->ex_rnode-1];
+#endif
+               return(result);
+       case EX_SAMESIGN:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_typ = EV_INT;
+               if (leaf1.e_v.e_con>=0)
+                       result.e_v.e_con= leaf2.e_v.e_con>=0;
+               else
+                       result.e_v.e_con= leaf2.e_v.e_con<0;
+               return(result);
+       case EX_SFIT:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               mask = 0xFFFFFFFFL;
+               for (i=0;i<leaf2.e_v.e_con-1;i++)
+                       mask &= ~(1<<i);
+               tmp = leaf1.e_v.e_con&mask;
+               result.e_v.e_con = tmp==0||tmp==mask;
+               return(result);
+       case EX_UFIT:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               mask = 0xFFFFFFFFL;
+               for (i=0;i<leaf2.e_v.e_con;i++)
+                       mask &= ~(1<<i);
+               result.e_v.e_con = (leaf1.e_v.e_con&mask)==0;
+               return(result);
+       case EX_ROM:
+               assert(node->ex_rnode>=0 &&node->ex_rnode<MAXROM);
+               leaf2=dollar[node->ex_lnode];
+               if (leaf2.e_typ != EV_ADDR)
+                       return(undefres);
+               if (leaf2.e_v.e_addr.ea_off!=0)
+                       return(undefres);
+               gp = lookglo(leaf2.e_v.e_addr.ea_str);
+               if (gp == (glosym_p) 0)
+                       return(undefres);
+               if ((gp->gl_rom[MAXROM]&(1<<node->ex_rnode))==0)
+                       return(undefres);
+               result.e_v.e_con = gp->gl_rom[node->ex_rnode];
+               return(result);
+       case EX_LOWW:
+               result.e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper&0xFFFF;
+               return(result);
+       case EX_HIGHW:
+               result.e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper>>16;
+               return(result);
+       case EX_NCPEQ:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con==leaf2.e_v.e_con;
+               return(result);
+       case EX_SCPEQ:
+       assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
+               result.e_v.e_con =
+                   (strcmp(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str)==0 &&
+                   leaf1.e_v.e_addr.ea_off==leaf2.e_v.e_addr.ea_off);
+               return(result);
+       case EX_RCPEQ:
+       assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
+               result.e_v.e_con = leaf1.e_v.e_reg==leaf2.e_v.e_reg;
+               return(result);
+       case EX_NCPNE:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con!=leaf2.e_v.e_con;
+               return(result);
+       case EX_SCPNE:
+       assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
+               result.e_v.e_con =
+                   !(strcmp(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str)==0 &&
+                   leaf1.e_v.e_addr.ea_off==leaf2.e_v.e_addr.ea_off);
+               return(result);
+       case EX_RCPNE:
+       assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
+               result.e_v.e_con = leaf1.e_v.e_reg!=leaf2.e_v.e_reg;
+               return(result);
+       case EX_NCPGT:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con>leaf2.e_v.e_con;
+               return(result);
+       case EX_NCPGE:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con>=leaf2.e_v.e_con;
+               return(result);
+       case EX_NCPLT:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con<leaf2.e_v.e_con;
+               return(result);
+       case EX_NCPLE:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con<=leaf2.e_v.e_con;
+               return(result);
+       case EX_OR2:
+       assert(leaf1.e_typ == EV_INT);
+               if (leaf1.e_v.e_con==0)
+                       return(compute(&enodes[node->ex_rnode]));
+               return(leaf1);
+       case EX_AND2:
+       assert(leaf1.e_typ == EV_INT);
+               if (leaf1.e_v.e_con!=0)
+                       return(compute(&enodes[node->ex_rnode]));
+               return(leaf1);
+       case EX_PLUS:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con=leaf1.e_v.e_con+leaf2.e_v.e_con;
+               return(result);
+       case EX_CAT:
+       assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
+               result.e_typ = EV_ADDR;
+               result.e_v.e_addr.ea_str = mycat(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str);
+               result.e_v.e_addr.ea_off = leaf1.e_v.e_addr.ea_off+leaf2.e_v.e_addr.ea_off;
+               return(result);
+       case EX_MINUS:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con;
+               return(result);
+       case EX_TIMES:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con;
+               return(result);
+       case EX_DIVIDE:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con;
+               return(result);
+       case EX_MOD:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con;
+               return(result);
+       case EX_LSHIFT:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con;
+               return(result);
+       case EX_RSHIFT:
+       assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
+               result.e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con;
+               return(result);
+       case EX_NOT:
+       assert(leaf1.e_typ == EV_INT);
+               result.e_v.e_con = !leaf1.e_v.e_con;
+               return(result);
+       case EX_COMP:
+       assert(leaf1.e_typ == EV_INT);
+               result.e_v.e_con = ~leaf1.e_v.e_con;
+               return(result);
+       case EX_STRING:
+               result.e_typ = EV_ADDR;
+               result.e_v.e_addr.ea_str = codestrings[node->ex_lnode];
+               result.e_v.e_addr.ea_off = 0;
+               return(result);
+       case EX_DEFINED:
+               result.e_v.e_con=leaf1.e_typ!=EV_UNDEF;
+               return(result);
+       case EX_SUBREG:
+               result.e_typ = EV_REG;
+               tp= &fakestack[stackheight-node->ex_lnode];
+               assert(tp->t_token == -1);
+               tmpreg= tp->t_att[0].ar;
+#if MAXMEMBERS!=0
+               if (node->ex_rnode)
+                       tmpreg=machregs[tmpreg].r_members[node->ex_rnode-1];
+#endif
+               result.e_v.e_reg=tmpreg;
+               return(result);
+       case EX_TOSTRING:
+       assert(leaf1.e_typ == EV_INT);
+               result.e_typ = EV_ADDR;
+               result.e_v.e_addr.ea_str = 0;
+               result.e_v.e_addr.ea_off = leaf1.e_v.e_con;
+               return(result);
+#ifdef REGVARS
+       case EX_INREG:
+       assert(leaf1.e_typ == EV_INT);
+               if ((result.e_v.e_con = isregvar((long) leaf1.e_v.e_con))>0)
+                       result.e_v.e_con = machregs[result.e_v.e_con].r_size;
+               return(result);
+       case EX_REGVAR:
+       assert(leaf1.e_typ == EV_INT);
+               i = isregvar((long) leaf1.e_v.e_con);
+               if (i<=0) 
+                       return(undefres);
+               result.e_typ = EV_REG;
+               result.e_v.e_reg=i;
+               return(result);
+#endif
+       case EX_UMINUS:
+       assert(leaf1.e_typ == EV_INT);
+               result.e_v.e_con = -leaf1.e_v.e_con;
+               return(result);
+       }
+}
diff --git a/mach/proto/ncg/data.h b/mach/proto/ncg/data.h
new file mode 100644 (file)
index 0000000..809baeb
--- /dev/null
@@ -0,0 +1,64 @@
+/* $Header$ */
+
+typedef struct cost {
+       short ct_space;
+       short ct_time;
+} cost_t,*cost_p;
+
+typedef struct {
+       string ea_str;
+       word ea_off;
+} addr_t;
+
+typedef struct {
+       int     t_token;        /* kind of token, -1 for register */
+       union {
+               word aw;        /* integer type */
+               addr_t aa;      /* address type */
+               int ar;         /* register type */
+       } t_att[TOKENSIZE];
+} token_t,*token_p;
+
+struct reginfo {
+       int     r_repr;                 /* index in string table */
+       int     r_size;                 /* size in bytes */
+#if MAXMEMBERS!=0
+       int     r_members[MAXMEMBERS];  /* register contained within this reg */
+       short   r_clash[REGSETSIZE];    /* set of clashing registers */
+#endif
+       int     r_refcount;             /* Times in use */
+       token_t r_contents;             /* Current contents */
+       int     r_tcount;               /* Temporary count difference */
+};
+
+#if MAXMEMBERS!=0
+#define clash(a,b) ((machregs[a].r_clash[(b)>>4]&(1<<((b)&017)))!=0)
+#else
+#define clash(a,b) ((a)==(b))
+#endif
+
+typedef struct {
+       int     t_size;                 /* size in bytes */
+       cost_t  t_cost;                 /* cost in bytes and time */ 
+       byte    t_type[TOKENSIZE];      /* types of attributes, TT_??? */
+       int     t_format;               /* index of formatstring */
+} tkdef_t,*tkdef_p;
+
+struct emline {
+       int     em_instr;
+       int     em_optyp;
+       string  em_soper;
+       union {
+               word    em_ioper;
+               long    em_loper;
+       } em_u;
+};
+
+#define OPNO 0
+#define OPINT 1
+#define OPSYMBOL 2
+
+typedef struct {
+       int rl_n;       /* number in list */
+       int rl_list[NREGS];
+} rl_t,*rl_p;
diff --git a/mach/proto/ncg/equiv.c b/mach/proto/ncg/equiv.c
new file mode 100644 (file)
index 0000000..54a695a
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include "equiv.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+extern string myalloc();
+
+int rar[MAXCREG];
+rl_p *lar;
+int maxindex;
+int regclass[NREGS];
+struct perm *perms;
+
+struct perm *
+tuples(regls,nregneeded) rl_p *regls; {
+       int class=0;
+       register i,j;
+
+       /*
+        * First compute equivalence classes of registers.
+        */
+
+       for (i=0;i<NREGS;i++) {
+               regclass[i] = class++;
+               if (getrefcount(i) == 0) {
+                       for (j=0;j<i;j++) {
+                               if (eqregclass(i,j) &&
+                                   eqtoken(&machregs[i].r_contents,
+                                           &machregs[j].r_contents)) {
+                                       regclass[i] = regclass[j];
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Now create tuples through a recursive function
+        */
+
+       maxindex = nregneeded;
+       lar = regls;
+       perms = 0;
+       permute(0);
+       return(perms);
+}
+
+permute(index) {
+       register struct perm *pp;
+       register rl_p rlp;
+       register i,j;
+
+       if (index == maxindex) {
+               for (pp=perms; pp != 0; pp=pp->p_next) {
+                       for (i=0; i<maxindex; i++)
+                               if (regclass[rar[i]] != regclass[pp->p_rar[i]])
+                                       goto diff;
+                       for (i=0; i<maxindex; i++)
+                               for (j=0; j<i; j++)
+                                       if (clash(rar[i],rar[j]) !=
+                                           clash(pp->p_rar[i],pp->p_rar[j]))
+                                               goto diff;
+                       return;
+                   diff: ;
+               }
+               pp = (struct perm *) myalloc(sizeof ( *pp ));
+               pp->p_next = perms;
+               for (i=0; i<maxindex; i++)
+                       pp->p_rar[i] = rar[i];
+               perms = pp;
+       } else {
+               rlp=lar[index];
+               for (i=rlp->rl_n-1; i>=0; i--) {
+                       rar[index] = rlp->rl_list[i];
+                       permute(index+1);
+               }
+       }
+}
diff --git a/mach/proto/ncg/equiv.h b/mach/proto/ncg/equiv.h
new file mode 100644 (file)
index 0000000..f1dc6c8
--- /dev/null
@@ -0,0 +1,8 @@
+/* $Header$ */
+
+#define MAXCREG 4
+
+struct perm {
+       struct perm *p_next;
+       int p_rar[MAXCREG];
+};
diff --git a/mach/proto/ncg/extern.h b/mach/proto/ncg/extern.h
new file mode 100644 (file)
index 0000000..a50224e
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Header$ */
+
+extern int maxply;                      /* amount of lookahead allowed */
+extern int stackheight;                 /* # of tokens on fakestack */
+extern token_t fakestack[];             /* fakestack itself */
+extern int nallreg;                     /* number of allocated registers */
+extern int allreg[];                    /* array of allocated registers */
+extern token_p curtoken;                /* pointer to current token */
+extern result_t dollar[];               /* Values of $1,$2 etc.. */
+extern int nemlines;                    /* # of EM instructions in core */
+extern struct emline emlines[];         /* EM instructions itself */
+extern struct emline *emp;              /* pointer to current instr */
+extern struct emline *saveemp;         /* pointer to start of pattern */
+extern int tokpatlen;                   /* length of current stackpattern */
+extern rl_p curreglist;                 /* side effect of findcoerc() */
+#ifndef NDEBUG
+extern int Debug;                       /* on/off debug printout */
+#endif
+
+/*
+ * Next descriptions are external declarations for tables created
+ * by bootgram.
+ * All definitions are to be found in tables.c (Not for humans)
+ */
+
+extern byte coderules[];                /* pseudo code for cg itself */
+extern char stregclass[];               /* static register class */
+extern struct reginfo machregs[];       /* register info */
+extern tkdef_t tokens[];                /* token info */
+extern node_t enodes[];                 /* expression nodes */
+extern string codestrings[];            /* table of strings */
+extern set_t machsets[];                /* token expression table */
+extern inst_t tokeninstances[];         /* token instance description table */
+extern move_t moves[];                  /* move descriptors */
+extern test_t tests[];                  /* test descriptors */
+extern byte pattern[];                  /* EM patterns */
+extern int pathash[256];                /* Indices into previous */
+extern c1_t c1coercs[];                 /* coercions type 1 */
+#ifdef MAXSPLIT
+extern c2_t c2coercs[];                 /* coercions type 2 */
+#endif MAXSPLIT
+extern c3_t c3coercs[];                 /* coercions type 3 */
+extern struct reginfo **reglist[];     /* lists of registers per property */
+
+#define eqregclass(r1,r2) (stregclass[r1]==stregclass[r2])
+
+#ifdef REGVARS
+extern int nregvar[];                  /* # of register variables per type */
+extern int *rvnumbers[];               /* lists of numbers */
+#endif
diff --git a/mach/proto/ncg/fillem.c b/mach/proto/ncg/fillem.c
new file mode 100644 (file)
index 0000000..5e87991
--- /dev/null
@@ -0,0 +1,676 @@
+#ifndef NORCSID
+static char rcsid2[] = "$Header$";
+#endif
+
+#include <stdio.h>
+#include "assert.h"
+#include <em_spec.h>
+#include <em_pseu.h>
+#include <em_flag.h>
+#include <em_ptyp.h>
+#include <em_mes.h>
+#include "mach.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#ifdef REGVARS
+#include "regvar.h"
+#include <em_reg.h>
+#endif
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+#ifndef newplb                 /* retrofit for older mach.h */
+#define newplb newilb
+#endif
+
+#ifdef fmt_id
+#ifdef id_first
+It is an error to define both fmt_id and id_first.
+Read the documentation.
+#endif
+#endif
+
+#ifdef fmt_ilb
+#ifdef ilb_fmt
+It is an error to define both fmt_ilb and ilb_fmt.
+Read the documentation.
+#endif
+#endif
+
+/* segment types for switchseg() */
+#define SEGTXT          0
+#define SEGCON          1
+#define SEGROM          2
+#define SEGBSS          3
+
+long con();
+
+#define get8()  getc(emfile)
+
+#define MAXSTR 256
+
+FILE *emfile;
+extern FILE *codefile;
+
+int nextispseu,savetab1;
+int opcode;
+int offtyp;
+long argval;
+int dlbval;
+char str[MAXSTR],argstr[32],labstr[32];
+int strsiz;
+int holno=0;
+int procno=0;
+int curseg= -1;
+int part_size=0;
+word part_word=0;
+int endofprog=0;
+#ifdef REGVARS
+int regallowed=0;
+#endif
+
+extern char em_flag[];
+extern short em_ptyp[];
+extern long atol();
+extern double atof();
+
+#define sp_cstx sp_cst2
+
+string tostring();
+string holstr();
+string strarg();
+string mystrcpy();
+long get32();
+
+in_init(filename) char *filename; {
+
+       if ((emfile=freopen(filename,"r",stdin))==NULL)
+               error("Can't open %s",filename);
+       if (get16()!=sp_magic)
+               error("Bad format %s",filename);
+}
+
+in_finish() {
+}
+
+fillemlines() {
+       register int t,i;
+       register struct emline *lp;
+
+       while ((emlines+nemlines)-emp<MAXEMLINES-5) {
+               assert(nemlines<MAXEMLINES);
+               if (nextispseu) {
+                       emlines[nemlines].em_instr=0;
+                       return;
+               }
+               lp = &emlines[nemlines++];
+
+               switch(t=table1()) {
+               default:
+                       error("unknown instruction byte");
+               case sp_ilb1:
+               case sp_ilb2:
+               case sp_fpseu:
+               case sp_dlb1:
+               case sp_dlb2:
+               case sp_dnam:
+                       nextispseu=1; savetab1=t;
+                       nemlines--;
+                       lp->em_instr = 0;
+                       return;
+               case EOF:
+                       nextispseu=1; savetab1=t;
+                       endofprog=1;
+                       nemlines--;
+                       lp->em_instr = 0;
+                       return;
+               case sp_fmnem:
+                       lp->em_instr = opcode;
+                       break;
+               }
+               i=em_flag[lp->em_instr-sp_fmnem] & EM_PAR;
+               if ( i == PAR_NO ) {
+                       lp->em_optyp = OPNO;
+                       lp->em_soper = 0;
+                       continue;
+               }
+               t= em_ptyp[i];
+               t= getarg(t);
+               switch(i) {
+               case PAR_L:
+                       assert(t == sp_cstx);
+                       if (argval >= 0)
+                               argval += TEM_BSIZE;
+                       lp->em_optyp = OPINT;
+                       lp->em_u.em_ioper = argval;
+                       lp->em_soper = tostring((word) argval);
+                       continue;
+               case PAR_G:
+                       if (t != sp_cstx)
+                               break;
+                       lp->em_optyp = OPSYMBOL;
+                       lp->em_soper = holstr((word) argval);
+                       continue;
+               case PAR_B:
+                       t = sp_ilb2;
+                       break;
+               case PAR_D:
+                       assert(t == sp_cstx);
+                       lp->em_optyp = OPSYMBOL;
+                       lp->em_soper = strarg(t);
+                       lp->em_u.em_loper = argval;
+                       continue;
+               }
+               lp->em_soper = strarg(t);
+               if (t==sp_cend)
+                       lp->em_optyp = OPNO;
+               else if (t==sp_cstx) {
+                       lp->em_optyp = OPINT;
+                       lp->em_u.em_ioper = argval;
+               } else
+                       lp->em_optyp = OPSYMBOL;
+       }
+}
+
+dopseudo() {
+       register b,t;
+       register full n;
+       register long save;
+       word romcont[MAXROM+1];
+       int nromwords;
+       int rombit,rommask;
+       unsigned dummy,stackupto();
+
+       if (nextispseu==0 || nemlines>0)
+               error("No table entry for %d",emlines[0].em_instr);
+       nextispseu=0;
+       switch(savetab1) {
+       case sp_ilb1:
+       case sp_ilb2:
+               swtxt();
+               dummy = stackupto(&fakestack[stackheight-1],maxply,TRUE);
+               cleanregs();
+               strarg(savetab1);
+               newilb(argstr);
+#ifndef NDEBUG
+               { extern int Debug; extern char * strtdebug;
+               if (strcmp(strtdebug,argstr)==0)
+                       Debug = strtdebug[-2]-'0';
+               }
+#endif
+               return;
+       case sp_dlb1:
+       case sp_dlb2:
+       case sp_dnam:
+               strarg(savetab1);
+               savelab();
+               return;
+       case sp_fpseu:
+               break;
+       case EOF:
+               swtxt();
+               in_finish();
+               out_finish();
+               popstr(0);
+               tstoutput();
+               exit(0);
+       default:
+               error("Unknown opcode %d",savetab1);
+       }
+       switch (opcode) {
+       case ps_hol:
+               sprintf(labstr,hol_fmt,++holno);
+       case ps_bss:
+               getarg(cst_ptyp);
+               n = (full) argval;
+               t = getarg(val_ptyp);
+               save = argval;
+               getarg(cst_ptyp);
+               b = (int) argval;
+               argval = save;
+               bss(n,t,b);
+               break;
+       case ps_con:
+               switchseg(SEGCON);
+               dumplab();
+               con(getarg(val_ptyp));
+               while ((t = getarg(any_ptyp)) != sp_cend)
+                       con(t);
+               break;
+       case ps_rom:
+               switchseg(SEGROM);
+               xdumplab();
+               nromwords=0;
+               rommask=0;
+               rombit=1;
+               t=getarg(val_ptyp);
+               while (t!=sp_cend) {
+                       if (t==sp_cstx && nromwords<MAXROM) {
+                               romcont[nromwords] = (word) argval;
+                               rommask |= rombit;
+                       }
+                       nromwords++;
+                       rombit <<= 1;
+                       con(t);
+                       t=getarg(any_ptyp);
+               }
+               if (rommask != 0) {
+                       romcont[MAXROM]=rommask;
+                       enterglo(labstr,romcont);
+               }
+               labstr[0]=0;
+               break;
+       case ps_mes:
+               getarg(ptyp(sp_cst2));
+               if (argval == ms_emx) {
+                       getarg(ptyp(sp_cst2));
+                       if (argval != TEM_WSIZE)
+                               fatal("bad word size");
+                       getarg(ptyp(sp_cst2));
+                       if (argval != TEM_PSIZE)
+                               fatal("bad pointer size");
+                       if ( getarg(any_ptyp)!=sp_cend )
+                               fatal("too many parameters");
+#ifdef REGVARS
+               } else if (argval == ms_gto) {
+                       getarg(ptyp(sp_cend));
+                       if (!regallowed)
+                               error("mes 3 not allowed here");
+                       fixregvars(TRUE);
+                       regallowed=0;
+               } else if (argval == ms_reg) {
+                       long r_off;
+                       int r_size,r_type,r_score;
+                       struct regvar *linkreg();
+
+                       if (!regallowed)
+                               error("mes 3 not allowed here");
+                       if(getarg(ptyp(sp_cst2)|ptyp(sp_cend)) == sp_cend) {
+                               fixregvars(FALSE);
+                               regallowed=0;
+                       } else {
+                               r_off = argval;
+                               if (r_off >= 0)
+                                       r_off += TEM_BSIZE;
+                               getarg(ptyp(sp_cst2));
+                               r_size = argval;
+                               getarg(ptyp(sp_cst2));
+                               r_type = argval;
+                               if (r_type<reg_any || r_type>reg_float)
+                                       fatal("Bad type in register message");
+                               if(getarg(ptyp(sp_cst2)|ptyp(sp_cend)) == sp_cend)
+                                       r_score = 0;
+                               else {
+                                       r_score = argval;
+                                       if ( getarg(any_ptyp)!=sp_cend )
+                                               fatal("too many parameters");
+                               }
+                               tryreg(linkreg(r_off,r_size,r_type,r_score),r_type);
+                       }
+#endif
+               } else
+                       mes((word)argval);
+               break;
+       case ps_exa:
+               strarg(getarg(sym_ptyp));
+               ex_ap(argstr);
+               break;
+       case ps_ina:
+               strarg(getarg(sym_ptyp));
+               in_ap(argstr);
+               break;
+       case ps_exp:
+               strarg(getarg(ptyp(sp_pnam)));
+               ex_ap(argstr);
+               break;
+       case ps_inp:
+               strarg(getarg(ptyp(sp_pnam)));
+               in_ap(argstr);
+               break;
+       case ps_pro:
+               switchseg(SEGTXT);
+               procno++;
+               strarg(getarg(ptyp(sp_pnam)));
+               newplb(argstr);
+               getarg(cst_ptyp);
+               prolog((full)argval);
+#ifdef REGVARS
+               regallowed++;
+#endif
+               break;
+       case ps_end:
+               getarg(cst_ptyp | ptyp(sp_cend));
+               cleanregs();
+#ifdef REGVARS
+               unlinkregs();
+#endif
+               tstoutput();
+               break;
+       default:
+               error("No table entry for %d",savetab1);
+       }
+}
+
+/* ----- input ----- */
+
+int getarg(typset) {
+       register t,argtyp;
+
+       argtyp = t = table2();
+       if (t == EOF)
+               fatal("unexpected EOF");
+       t -= sp_fspec;
+       t = 1 << t;
+       if ((typset & t) == 0)
+               error("bad argument type %d",argtyp);
+       return(argtyp);
+}
+
+int table1() {
+       register i;
+
+       i = get8();
+       if (i < sp_fmnem+sp_nmnem && i >= sp_fmnem) {
+               opcode = i;
+               return(sp_fmnem);
+       }
+       if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) {
+               opcode = i;
+               return(sp_fpseu);
+       }
+       if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) {
+               argval = i - sp_filb0;
+               return(sp_ilb2);
+       }
+       return(table3(i));
+}
+
+int table2() {
+       register i;
+
+       i = get8();
+       if (i < sp_fcst0+sp_ncst0 && i >= sp_fcst0) {
+               argval = i - sp_zcst0;
+               return(sp_cstx);
+       }
+       return(table3(i));
+}
+
+int table3(i) {
+       word consiz;
+
+       switch(i) {
+       case sp_ilb1:
+               argval = get8();
+               break;
+       case sp_dlb1:
+               dlbval = get8();
+               break;
+       case sp_dlb2:
+               dlbval = get16();
+               break;
+       case sp_cst2:
+               i = sp_cstx;
+       case sp_ilb2:
+               argval = get16();
+               break;
+       case sp_cst4:
+               i = sp_cstx;
+               argval = get32();
+               break;
+       case sp_dnam:
+       case sp_pnam:
+       case sp_scon:
+               getstring();
+               break;
+       case sp_doff:
+               offtyp = getarg(sym_ptyp);
+               getarg(cst_ptyp);
+               break;
+       case sp_icon:
+       case sp_ucon:
+       case sp_fcon:
+               getarg(cst_ptyp);
+               consiz = (word) argval;
+               getstring();
+               argval = consiz;
+               break;
+       }
+       return(i);
+}
+
+int get16() {
+       register int l_byte, h_byte;
+
+       l_byte = get8();
+       h_byte = get8();
+       if ( h_byte>=128 ) h_byte -= 256 ;
+       return l_byte | (h_byte*256) ;
+}
+
+long get32() {
+       register long l;
+       register int h_byte;
+
+       l = get8();
+       l |= ((unsigned) get8())*256 ;
+       l |= get8()*256L*256L ;
+       h_byte = get8() ;
+       if ( h_byte>=128 ) h_byte -= 256 ;
+       return l | (h_byte*256L*256*256L) ;
+}
+
+getstring() {
+       register char *p;
+       register n;
+
+       getarg(cst_ptyp);
+       if (argval < 0 || argval > MAXSTR-1)
+               fatal("string/identifier too long");
+       strsiz = n = (int) argval;
+       p = str;
+       while (--n >= 0)
+               *p++ = get8();
+       *p++ = '\0';
+}
+
+char *strarg(t) {
+       register char *p;
+
+       switch (t) {
+       case sp_ilb1:
+       case sp_ilb2:
+#ifdef fmt_ilb
+               fmt_ilb(procno,((int) argval),argstr);
+#else
+               sprintf(argstr,ilb_fmt,procno,(int)argval);
+#endif
+               break;
+       case sp_dlb1:
+       case sp_dlb2:
+               sprintf(argstr,dlb_fmt,dlbval);
+               break;
+       case sp_cstx:
+               sprintf(argstr,cst_fmt,(full)argval);
+               break;
+       case sp_dnam:
+       case sp_pnam:
+#ifdef fmt_id
+               fmt_id(str,argstr);
+#else
+               p = argstr;
+               if (strsiz < 8 || str[0] == id_first)
+                       *p++ = id_first;
+               sprintf(p,"%.*s",strsiz,str);
+#endif
+               break;
+       case sp_doff:
+               strarg(offtyp);
+               for (p = argstr; *p; p++)
+                       ;
+               if (argval >= 0)
+                       *p++ = '+';
+               sprintf(p,off_fmt,(full)argval);
+               break;
+       case sp_cend:
+               return("");
+       }
+       return(mystrcpy(argstr));
+}
+
+bss(n,t,b) full n; {
+       register long s;
+
+       if (n % TEM_WSIZE)
+               fatal("bad BSS size");
+       if (b==0
+#ifdef BSS_INIT
+           || (t==sp_cstx && argval==BSS_INIT)
+#endif BSS_INIT
+               ) {
+               switchseg(SEGBSS);
+               newlbss(labstr,n);
+               labstr[0]=0;
+               return;
+       }
+       switchseg(SEGCON);
+       dumplab();
+       while (n > 0)
+               n -= (s = con(t));
+       if (s % TEM_WSIZE)
+               fatal("bad BSS initializer");
+}
+
+long con(t) {
+       register i;
+
+       strarg(t);
+       switch (t) {
+       case sp_ilb1:
+       case sp_ilb2:
+       case sp_pnam:
+               part_flush();
+               con_ilb(argstr);
+               return((long)TEM_PSIZE);
+       case sp_dlb1:
+       case sp_dlb2:
+       case sp_dnam:
+       case sp_doff:
+               part_flush();
+               con_dlb(argstr);
+               return((long)TEM_PSIZE);
+       case sp_cstx:
+               con_part(TEM_WSIZE,(word)argval);
+               return((long)TEM_WSIZE);
+       case sp_scon:
+               for (i = 0; i < strsiz; i++)
+                       con_part(1,(word) str[i]);
+               return((long)strsiz);
+       case sp_icon:
+       case sp_ucon:
+               if (argval > TEM_WSIZE) {
+                       part_flush();
+                       con_mult((word)argval);
+               } else {
+                       con_part((int)argval,(word)atol(str));
+               }
+               return(argval);
+       case sp_fcon:
+               part_flush();
+               con_float();
+               return(argval);
+       }
+       assert(FALSE);
+       /* NOTREACHED */
+}
+
+extern char *segname[];
+
+swtxt() {
+       switchseg(SEGTXT);
+}
+
+switchseg(s) {
+
+       if (s == curseg)
+               return;
+       part_flush();
+       if ((curseg = s) >= 0)
+               fprintf(codefile,"%s\n",segname[s]);
+}
+
+savelab() {
+       register char *p,*q;
+
+       part_flush();
+       if (labstr[0]) {
+               dlbdlb(argstr,labstr);
+               return;
+       }
+       p = argstr;
+       q = labstr;
+       while (*q++ = *p++)
+               ;
+}
+
+dumplab() {
+
+       if (labstr[0] == 0)
+               return;
+       assert(part_size == 0);
+       newdlb(labstr);
+       labstr[0] = 0;
+}
+
+xdumplab() {
+
+       if (labstr[0] == 0)
+               return;
+       assert(part_size == 0);
+       newdlb(labstr);
+}
+
+part_flush() {
+
+       /*
+        * Each new data fragment and each data label starts at
+        * a new target machine word
+        */
+       if (part_size == 0)
+               return;
+       con_cst(part_word);
+       part_size = 0;
+       part_word = 0;
+}
+
+string holstr(n) word n; {
+
+       sprintf(str,hol_off,n,holno);
+       return(mystrcpy(str));
+}
+
+
+/* ----- machine dependent routines ----- */
+
+#include        "mach.c"
diff --git a/mach/proto/ncg/gencode.c b/mach/proto/ncg/gencode.c
new file mode 100644 (file)
index 0000000..d2ee010
--- /dev/null
@@ -0,0 +1,143 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include <stdio.h>
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+string mystrcpy();
+
+FILE *codefile;
+
+out_init(filename) char *filename; {
+
+#ifndef NDEBUG
+       static char stderrbuff[BUFSIZ];
+
+    if (Debug) {
+       codefile = stderr;
+       if (!isatty(2))
+               setbuf(stderr,stderrbuff);
+    } else {
+#endif
+       if (filename == (char *) 0)
+               codefile = stdout;
+       else
+               if ((codefile=freopen(filename,"w",stdout))==NULL)
+                       error("Can't create %s",filename);
+#ifndef NDEBUG
+    }
+#endif
+}
+
+out_finish() {
+
+#ifndef NDEBUG
+       if (Debug)
+               fflush(stderr);
+       else
+#endif
+               fclose(codefile);
+#ifdef TABLEDEBUG
+       termlset();
+#endif
+}
+
+tstoutput() {
+
+       if (ferror(codefile))
+               error("Write error on output");
+}
+
+genstr(stringno) {
+
+       fputs(codestrings[stringno],codefile);
+}
+
+string ad2str(ad) addr_t ad; {
+       static char buf[100];
+
+       if (ad.ea_str==0)
+               ad.ea_str="";
+       sprintf(buf,"%s%c%ld",ad.ea_str,ad.ea_off>=0 ? '+' : ' ',(long)ad.ea_off);
+       return(mystrcpy(buf));
+}
+
+praddr(ad) addr_t ad; {
+
+       if (ad.ea_str==0)
+               fprintf(codefile,WRD_FMT,ad.ea_off);
+       else {
+               fprintf(codefile,"%s",ad.ea_str);
+               if (ad.ea_off<0)
+                       fprintf(codefile,WRD_FMT,ad.ea_off);            
+               else if(ad.ea_off>0) {
+                       fputc('+',codefile);
+                       fprintf(codefile,WRD_FMT,ad.ea_off);
+               }
+       }
+}
+
+gennl() {
+       fputc('\n',codefile);
+}
+
+prtoken(tp,leadingchar) token_p tp; {
+       register c;
+       register char *code;
+       register tkdef_p tdp;
+
+       fputc(leadingchar,codefile);
+       if (tp->t_token == -1) {
+               fprintf(codefile,"%s",codestrings[machregs[tp->t_att[0].ar].r_repr]);
+               return;
+       }
+       tdp = &tokens[tp->t_token];
+       assert(tdp->t_format != -1);
+       code = codestrings[tdp->t_format];
+       while ((c = *code++) != 0) {
+               if (c>=' ' && c<='~')
+                       fputc(c,codefile);
+               else {
+                       assert(c>0 && c<=TOKENSIZE);
+                       switch(tdp->t_type[c-1]) {
+                       default:
+                               assert(FALSE);
+                       case EV_INT:
+                               fprintf(codefile,WRD_FMT,tp->t_att[c-1].aw);
+                               break;
+                       case EV_ADDR:
+                               praddr(tp->t_att[c-1].aa);
+                               break;
+                       case EV_REG:
+                               fprintf(codefile,"%s",codestrings[machregs[tp->t_att[c-1].ar].r_repr]);
+                               break;
+                       }
+               }
+       }
+}
diff --git a/mach/proto/ncg/glosym.c b/mach/proto/ncg/glosym.c
new file mode 100644 (file)
index 0000000..cf8f029
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include "glosym.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+extern string myalloc();
+
+glosym_p glolist= (glosym_p) 0;
+
+enterglo(name,romp) string name; word *romp; {
+       register glosym_p gp;
+       register i;
+
+       gp = (glosym_p) myalloc(sizeof *gp);
+       gp->gl_next = glolist;
+       gp->gl_name = (string) myalloc(strlen(name)+1);
+       strcpy(gp->gl_name,name);
+       for (i=0;i<=MAXROM;i++)
+               gp->gl_rom[i] = romp[i];
+       glolist = gp;
+}
+
+glosym_p lookglo(name) string name; {
+       register glosym_p gp;
+
+       for (gp=glolist;gp != (glosym_p) 0; gp=gp->gl_next)
+               if (strcmp(gp->gl_name,name)==0)
+                       return(gp);
+       return((glosym_p) 0);
+}
diff --git a/mach/proto/ncg/glosym.h b/mach/proto/ncg/glosym.h
new file mode 100644 (file)
index 0000000..7fb4c7c
--- /dev/null
@@ -0,0 +1,9 @@
+/* $Header$ */
+
+typedef struct glosym {
+       struct glosym *gl_next;
+       string         gl_name;
+       word           gl_rom[MAXROM+1];
+} glosym_t,*glosym_p;
+
+glosym_p lookglo();
diff --git a/mach/proto/ncg/main.c b/mach/proto/ncg/main.c
new file mode 100644 (file)
index 0000000..f8f7d00
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "param.h"
+#include "tables.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+char *progname;
+extern char startupcode[];
+int maxply=1;
+#ifndef NDEBUG
+int Debug=0;
+char *strtdebug="";
+#endif
+
+extern int endofprog;
+
+main(argc,argv) char **argv; {
+       register unsigned n;
+       extern unsigned cc1,cc2,cc3,cc4;
+       unsigned ggd();
+
+       progname = argv[0];
+       while (--argc && **++argv == '-') {
+               switch(argv[0][1]) {
+#ifndef NDEBUG
+               case 'd':
+                       if ((Debug = argv[0][2]) != 0) {
+                               Debug -= '0';
+                               if (argv[0][3] == '@') {
+                                       Debug = 0;
+                                       strtdebug = &argv[0][4];
+                               }
+                       } else
+                               Debug++;
+                       break;
+#endif
+#ifdef TABLEDEBUG
+               case 'u':
+               case 'U':
+                       initlset(argv[0]+1);
+                       break;
+#endif
+               case 'p':
+                       maxply = atoi(argv[0]+2);
+                       break;
+               case 'w':       /* weight percentage for size */
+                       n=atoi(argv[0]+2);
+                       cc1 *= n;
+                       cc2 *= 50;
+                       cc3 *= (100-n);
+                       cc4 *= 50;
+                       n=ggd(cc1,cc2);
+                       cc1 /= n;
+                       cc2 /= n;
+                       n=ggd(cc3,cc4);
+                       cc3 /= n;
+                       cc4 /= n;
+                       break;
+               default:
+                       error("Unknown flag %c",argv[0][1]);
+               }
+       }
+       if (argc < 1 || argc > 2)
+               error("Usage: %s EMfile [ asfile ]",progname);
+       in_init(argv[0]);
+       out_init(argv[1]);
+       readcodebytes();
+       itokcost();
+       codegen(startupcode,maxply,TRUE,MAXINT,0);
+       error("Bombed out of codegen");
+}
+
+unsigned ggd(a,b) register unsigned a,b; {
+       register unsigned c;
+
+       do {
+               c = a%b; a=b; b=c;
+       } while (c!=0);
+       return(a);
+}
diff --git a/mach/proto/ncg/move.c b/mach/proto/ncg/move.c
new file mode 100644 (file)
index 0000000..4c2e7fa
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+unsigned costcalc();
+
+move(tp1,tp2,ply,toplevel,maxcost) token_p tp1,tp2; unsigned maxcost; {
+       register move_p mp;
+       register unsigned t;
+       register struct reginfo *rp;
+       tkdef_p tdp;
+       int i;
+       unsigned codegen();
+
+       if (eqtoken(tp1,tp2))
+               return(0);
+       if (tp2->t_token == -1) {
+               if (tp1->t_token == -1) {
+                       if (eqtoken(&machregs[tp1->t_att[0].ar].r_contents,
+                                   &machregs[tp2->t_att[0].ar].r_contents) &&
+                             machregs[tp1->t_att[0].ar].r_contents.t_token!=0)
+                               return(0);
+                       erasereg(tp2->t_att[0].ar);
+                       machregs[tp2->t_att[0].ar].r_contents =
+                         machregs[tp1->t_att[0].ar].r_contents ;
+
+               } else {
+                       if (eqtoken(&machregs[tp2->t_att[0].ar].r_contents,tp1))
+                               return(0);
+                       erasereg(tp2->t_att[0].ar);
+                       machregs[tp2->t_att[0].ar].r_contents = *tp1;
+               }
+               for (rp=machregs+1;rp<machregs+NREGS;rp++) {
+                       if (rp->r_contents.t_token == 0)
+                               continue;
+                       assert(rp->r_contents.t_token > 0);
+                       tdp = &tokens[rp->r_contents.t_token];
+                       for (i=0;i<TOKENSIZE;i++)
+                               if (tdp->t_type[i] == EV_REG &&
+                                   clash(rp->r_contents.t_att[i].ar,tp2->t_att[0].ar)) {
+                                       erasereg(rp-machregs);
+                                       break;
+                               }
+               }
+       } else if (tp1->t_token == -1) {
+               if (eqtoken(tp2,&machregs[tp1->t_att[0].ar].r_contents))
+                       return(0);
+               machregs[tp1->t_att[0].ar].r_contents = *tp2;
+       }
+       /*
+        * If we arrive here the move must really be executed
+        */
+       for (mp=moves;mp->m_set1>=0;mp++) {
+               if (!match(tp1,&machsets[mp->m_set1],mp->m_expr1))
+                       continue;
+               if (match(tp2,&machsets[mp->m_set2],mp->m_expr2))
+                       break;
+               /*
+                * Correct move rule is found
+                */
+       }
+       assert(mp->m_set1>=0);
+       /*
+        * To get correct interpretation of things like %[1]
+        * in move code we stack tp2 and tp1. This little trick
+        * saves a lot of testing in other places.
+        */
+
+       fakestack[stackheight] = *tp2;
+       fakestack[stackheight+1] = *tp1;
+       stackheight += 2;
+       t = codegen(&coderules[mp->m_cindex],ply,toplevel,maxcost,0);
+       stackheight -= 2;
+       return(t);
+}
+
+#define cocoreg machregs[0].r_contents
+
+setcc(tp) token_p tp; {
+
+       cocoreg = *tp;
+}
+
+test(tp,ply,toplevel,maxcost) token_p tp; unsigned maxcost; {
+       register test_p mp;
+       register unsigned t;
+       register struct reginfo *rp;
+       tkdef_p tdp;
+       int i;
+       unsigned codegen();
+
+       if (cocoreg.t_token!=0) {
+               if (eqtoken(tp,&cocoreg))
+                       return(0);
+               if (tp->t_token == -1) {
+                       if (eqtoken(&machregs[tp->t_att[0].ar].r_contents,&cocoreg))
+                               return(0);
+               }
+       }
+       /*
+        * If we arrive here the test must really be executed
+        */
+       for (mp=tests;mp->t_set>=0;mp++) {
+               if (match(tp,&machsets[mp->t_set],mp->t_expr))
+                       break;
+               /*
+                * Correct move rule is found
+                */
+       }
+       assert(mp->t_set>=0);
+       /*
+        * To get correct interpretation of things like %[1]
+        * in test code we stack tp. This little trick
+        * saves a lot of testing in other places.
+        */
+
+       fakestack[stackheight] = *tp;
+       stackheight++;
+       t = codegen(&coderules[mp->t_cindex],ply,toplevel,maxcost,0);
+       stackheight--;
+       return(t);
+}
diff --git a/mach/proto/ncg/nextem.c b/mach/proto/ncg/nextem.c
new file mode 100644 (file)
index 0000000..4b74b44
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include <em_spec.h>
+#include <em_flag.h>
+#include "assert.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+#ifndef NDEBUG
+#include <stdio.h>
+extern char em_mnem[][4];
+#endif
+
+byte *trypat(bp,len) register byte *bp; {
+       register patlen,i;
+       result_t result;
+
+       getint(patlen,bp);
+       if (len == 3) {
+               if (patlen < 3)
+                       return(0);
+       } else {
+               if (patlen != len)
+                       return(0);
+       }
+       for(i=0;i<patlen;i++)
+               if (emp[i].em_instr != (*bp++&BMASK))
+                       return(0);
+       for (i=0;i<patlen;i++)
+               if (emp[i].em_optyp==OPNO)
+                       dollar[i].e_typ=EV_UNDEF;
+               else if ((dollar[i].e_typ=argtyp(emp[i].em_instr))==EV_INT)
+                       dollar[i].e_v.e_con=emp[i].em_u.em_ioper;
+               else {
+                       dollar[i].e_v.e_addr.ea_str=emp[i].em_soper;
+                       dollar[i].e_v.e_addr.ea_off=0;
+               }
+       getint(i,bp);
+       if (i!=0) {
+               result = compute(&enodes[i]);
+               if (result.e_typ != EV_INT || result.e_v.e_con == 0)
+                       return(0);
+       }
+#ifndef NDEBUG
+       if (Debug) {
+               fprintf(stderr,"Matched:");
+               for (i=0;i<patlen;i++)
+                       fprintf(stderr," %3.3s",em_mnem[emp[i].em_instr-sp_fmnem]);
+               fprintf(stderr,"\n");
+       }
+#endif
+       saveemp = emp;
+       emp += patlen;
+       return(bp);
+}
+
+extern char em_flag[];
+
+argtyp(mn) {
+
+       switch(em_flag[mn-sp_fmnem]&EM_PAR) {
+       case PAR_W:
+       case PAR_S:
+       case PAR_Z:
+       case PAR_O:
+       case PAR_N:
+       case PAR_L:
+       case PAR_F:
+       case PAR_R:
+       case PAR_C:
+               return(EV_INT);
+       default:
+               return(EV_ADDR);
+       }
+}
+
+byte *nextem(toplevel) {
+       register i;
+       short hash[3];
+       register byte *bp;
+       byte *cp;
+       int index;
+       register struct emline *ep;
+
+       if (toplevel) {
+               if (nemlines && emp>emlines) {
+                       nemlines -= emp-emlines;
+                       for (i=0,ep=emlines;i<nemlines;i++)
+                               *ep++ = *emp++;
+                       emp=emlines;
+               }
+               fillemlines();
+       }
+       hash[0] = emp[0].em_instr;
+       hash[1] = (hash[0]<<4) ^ emp[1].em_instr;
+       hash[2] = (hash[1]<<4) ^ emp[2].em_instr;
+       for (i=2;i>=0;i--) {
+               index = pathash[hash[i]&BMASK];
+               while (index != 0) {
+                       bp = &pattern[index];
+                       if ( bp[PO_HASH] == (hash[i]>>8))
+                               if ((cp=trypat(&bp[PO_MATCH],i+1)) != 0)
+                                       return(cp);
+                       index = (bp[PO_NEXT]&BMASK) | (bp[PO_NEXT+1]<<8);
+               }
+       }
+       return(0);
+}
diff --git a/mach/proto/ncg/param.h b/mach/proto/ncg/param.h
new file mode 100644 (file)
index 0000000..073d0da
--- /dev/null
@@ -0,0 +1,20 @@
+/* $Header$ */
+
+#define BMASK 0377
+#define BSHIFT 8
+
+#define TRUE    1
+#define FALSE   0
+
+#define MAXINT 32767
+#define INFINITY (MAXINT+100)
+
+#define MAXROM 3
+
+/*
+ * Tunable constants
+ */
+
+#define MAXEMLINES 20
+#define MAXFSTACK 20
+#define MAXTDBUG 32
diff --git a/mach/proto/ncg/reg.c b/mach/proto/ncg/reg.c
new file mode 100644 (file)
index 0000000..fc3546c
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+chrefcount(regno,amount,tflag) {
+       register struct reginfo *rp;
+       register i;
+
+       rp= &machregs[regno];
+#if MAXMEMBERS!=0
+       if (rp->r_members[0]==0) {
+#endif
+               rp->r_refcount += amount;
+               if (tflag)
+                       rp->r_tcount += amount;
+               assert(rp->r_refcount >= 0);
+#if MAXMEMBERS!=0
+       } else
+               for (i=0;i<MAXMEMBERS;i++)
+                       if (rp->r_members[i]!=0)
+                               chrefcount(rp->r_members[i],amount,tflag);
+#endif
+}
+
+getrefcount(regno) {
+       register struct reginfo *rp;
+       register i,maxcount;
+
+       rp= &machregs[regno];
+#if MAXMEMBERS!=0
+       if (rp->r_members[0]==0)
+#endif
+               return(rp->r_refcount);
+#if MAXMEMBERS!=0
+       else {
+               maxcount=0;
+               for (i=0;i<MAXMEMBERS;i++)
+                       if (rp->r_members[i]!=0)
+                               maxcount=max(maxcount,getrefcount(rp->r_members[i]));
+               return(maxcount);
+       }
+#endif
+}
+
+erasereg(regno) {
+       register struct reginfo *rp;
+
+#if MAXMEMBERS==0
+       awayreg(regno);
+#else
+       for (rp=machregs+1;rp<machregs+NREGS;rp++)
+               if (rp->r_clash[regno>>4]&(1<<(regno&017)))
+                       awayreg(rp-machregs);
+#endif
+}
+
+awayreg(regno) {
+       register struct reginfo *rp;
+       register tkdef_p tdp;
+       register i;
+
+       rp = &machregs[regno];
+       rp->r_contents.t_token = 0;
+       for (i=0;i<TOKENSIZE;i++)
+               rp->r_contents.t_att[i].aw = 0;
+
+       /* Now erase recursively all registers containing
+        * something using this one
+        */
+       for (rp=machregs;rp<machregs+NREGS;rp++) {
+               if (rp->r_contents.t_token == -1) {
+                       if (rp->r_contents.t_att[0].ar == regno)
+                               erasereg(rp-machregs);
+               } else {
+                       tdp= & tokens[rp->r_contents.t_token];
+                       for (i=0;i<TOKENSIZE;i++)
+                               if (tdp->t_type[i] == EV_REG && 
+                                   rp->r_contents.t_att[i].ar == regno) {
+                                       erasereg(rp-machregs);
+                                       break;
+                               }
+               }
+       }
+}
+
+cleanregs() {
+       register struct reginfo *rp;
+       register i;
+
+       for (rp=machregs;rp<machregs+NREGS;rp++) {
+               rp->r_contents.t_token = 0;
+               for (i=0;i<TOKENSIZE;i++)
+                       rp->r_contents.t_att[i].aw = 0;
+       }
+}
+
+#ifndef NDEBUG
+inctcount(regno) {
+       register struct reginfo *rp;
+       register i;
+
+       rp = &machregs[regno];
+#if MAXMEMBERS!=0
+       if (rp->r_members[0] == 0) {
+#endif
+               rp->r_tcount++;
+#if MAXMEMBERS!=0
+       } else  {
+               for (i=0;i<MAXMEMBERS;i++)
+                       if (rp->r_members[i] != 0)
+                               inctcount(rp->r_members[i]);
+       }
+#endif
+}
+
+chkregs() {
+       register struct reginfo *rp;
+       register token_p tp;
+       register tkdef_p tdp;
+       int i;
+
+       for (rp=machregs+1;rp<machregs+NREGS;rp++) {
+               assert(rp->r_tcount==0);
+       }
+       for (tp=fakestack;tp<fakestack+stackheight;tp++) {
+               if (tp->t_token == -1)
+                       inctcount(tp->t_att[0].ar);
+               else {
+                       tdp = &tokens[tp->t_token];
+                       for (i=0;i<TOKENSIZE;i++)
+                               if (tdp->t_type[i]==EV_REG)
+                                       inctcount(tp->t_att[i].ar);
+               }
+       }
+#ifdef REGVARS
+#include <em_reg.h>
+       for(i=reg_any;i<=reg_float;i++) {
+               int j;
+               for(j=0;j<nregvar[i];j++)
+                       inctcount(rvnumbers[i][j]);
+       }
+#endif REGVARS
+       for (rp=machregs+1;rp<machregs+NREGS;rp++) {
+               assert(rp->r_refcount==rp->r_tcount);
+               rp->r_tcount=0;
+       }
+}
+#endif
diff --git a/mach/proto/ncg/regvar.c b/mach/proto/ncg/regvar.c
new file mode 100644 (file)
index 0000000..9805d0e
--- /dev/null
@@ -0,0 +1,151 @@
+#include "assert.h"
+#include "param.h"
+#include "tables.h"
+
+#ifdef REGVARS
+
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "regvar.h"
+#include <em_reg.h>
+#include "result.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+extern string myalloc();
+struct regvar *rvlist;
+
+struct regvar *
+linkreg(of,sz,tp,sc) long of; {
+       register struct regvar *rvlp;
+
+       rvlp= (struct regvar *) myalloc(sizeof *rvlp);
+       rvlp->rv_next = rvlist;
+       rvlist=rvlp;
+       rvlp->rv_off    = of;
+       rvlp->rv_size   = sz;
+       rvlp->rv_type   = tp;
+       rvlp->rv_score  = sc;
+       rvlp->rv_reg    = 0;    /* no register assigned yet */
+       return(rvlp);
+}
+
+tryreg(rvlp,typ) register struct regvar *rvlp; {
+       int score;
+       register i;
+       register struct regassigned *ra;
+       struct regvar *save;
+
+       if (typ != reg_any && nregvar[typ]!=0) {
+               if (machregs[rvnumbers[typ][0]].r_size!=rvlp->rv_size)
+                       score = -1;
+               else
+                       score = regscore(rvlp->rv_off,
+                                        rvlp->rv_size,
+                                        rvlp->rv_type,
+                                        rvlp->rv_score,
+                                        typ);  /* machine dependent */
+               ra = regassigned[typ];
+               if (score>ra[nregvar[typ]-1].ra_score) {
+                       save = ra[nregvar[typ]-1].ra_rv;
+                       for (i=nregvar[typ]-1;i>0 && ra[i-1].ra_score<score;i--)
+                               ra[i] = ra[i-1];
+                       ra[i].ra_rv = rvlp;
+                       ra[i].ra_score = score;
+                       if((rvlp=save)==0)
+                               return;
+               }
+       }
+       if (nregvar[reg_any]==0)
+               return;
+       if (machregs[rvnumbers[reg_any][0]].r_size!=rvlp->rv_size)
+               score = -1;
+       else
+               score = regscore(rvlp->rv_off,
+                                rvlp->rv_size,
+                                rvlp->rv_type,
+                                rvlp->rv_score,
+                                reg_any);      /* machine dependent */
+       ra = regassigned[reg_any];
+       if (score>ra[nregvar[reg_any]-1].ra_score) {
+               for (i=nregvar[reg_any]-1;i>0 && ra[i-1].ra_score<score;i--)
+                       ra[i] = ra[i-1];
+               ra[i].ra_rv = rvlp;
+               ra[i].ra_score = score;
+       }
+}
+
+fixregvars(saveall) {
+       register struct regvar *rv;
+       register rvtyp,i;
+       
+       swtxt();
+       i_regsave();    /* machine dependent initialization */
+       for (rvtyp=reg_any;rvtyp<=reg_float;rvtyp++) {
+           for(i=0;i<nregvar[rvtyp];i++)
+               if (saveall) {
+                       struct reginfo *rp;
+                       rp= &machregs[rvnumbers[rvtyp][i]];
+                       regsave(codestrings[rp->r_repr],(long)-TEM_WSIZE,rp->r_size);
+               } else if(regassigned[rvtyp][i].ra_score>0) {
+                       rv=regassigned[rvtyp][i].ra_rv;
+                       rv->rv_reg=rvnumbers[rvtyp][i];
+                       regsave(codestrings[machregs[rv->rv_reg].r_repr],
+                                   rv->rv_off,rv->rv_size);
+               }
+       }
+       f_regsave();
+}
+
+isregvar(off) long off; {
+       register struct regvar *rvlp;
+
+       for(rvlp=rvlist;rvlp!=0;rvlp=rvlp->rv_next)
+               if(rvlp->rv_off == off)
+                       return(rvlp->rv_reg);
+       return(-1);
+}
+
+unlinkregs() {
+       register struct regvar *rvlp,*t;
+       register struct regassigned *ra;
+       int rvtyp,i;
+
+       for(rvlp=rvlist;rvlp!=0;rvlp=t) {
+               t=rvlp->rv_next;
+               myfree(rvlp);
+       }
+       rvlist=0;
+       for (rvtyp=reg_any;rvtyp<=reg_float;rvtyp++) {
+           for(i=0;i<nregvar[rvtyp];i++) {
+               ra= &regassigned[rvtyp][i];
+               ra->ra_rv = 0;
+               ra->ra_score = 0;
+           }
+       }
+}
+
+#endif REGVARS
+
+/* nothing after this */
diff --git a/mach/proto/ncg/regvar.h b/mach/proto/ncg/regvar.h
new file mode 100644 (file)
index 0000000..716a68f
--- /dev/null
@@ -0,0 +1,19 @@
+/* $Header$ */
+
+struct regvar {
+       struct regvar  *rv_next;
+       long            rv_off;
+       int             rv_size;
+       int             rv_type;
+       int             rv_score;
+       int             rv_reg;
+};
+
+struct regassigned {
+       struct regvar  *ra_rv;
+       int             ra_score;
+};
+
+extern struct regvar *rvlist;
+extern int nregvar[];
+extern struct regassigned *regassigned[];
diff --git a/mach/proto/ncg/result.h b/mach/proto/ncg/result.h
new file mode 100644 (file)
index 0000000..15f9e8a
--- /dev/null
@@ -0,0 +1,19 @@
+/* $Header$ */
+
+struct result {
+       int     e_typ;          /* EV_INT,EV_REG,EV_STR */
+       union {
+               word e_con;
+               int e_reg;
+               addr_t e_addr;
+       } e_v;                  /* value */
+};
+
+#define EV_UNDEF 0
+#define EV_INT 1
+#define EV_REG 2
+#define EV_ADDR        3
+
+typedef struct result result_t;
+
+extern result_t compute();
diff --git a/mach/proto/ncg/salloc.c b/mach/proto/ncg/salloc.c
new file mode 100644 (file)
index 0000000..45377d4
--- /dev/null
@@ -0,0 +1,150 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+/*
+ * Package for string allocation and garbage collection.
+ * Call salloc(size) to get room for string.
+ * Every now and then call garbage_collect() from toplevel.
+ */
+
+#define MAXSTAB         500
+#define THRESHOLD       200
+
+char *stab[MAXSTAB];
+int nstab=0;
+string malloc();
+
+string myalloc(size) {
+       register string p;
+
+       p = (string) malloc(size);
+       if (p==0)
+               fatal("Out of memory");
+       return(p);
+}
+
+myfree(p) string p; {
+
+       free(p);
+}
+
+popstr(nnstab) {
+       register i;
+
+       for (i=nnstab;i<nstab;i++)
+               myfree(stab[i]);
+       nstab = nnstab;
+}
+
+char *salloc(size) {
+       register char *p;
+
+       if (nstab==MAXSTAB)
+               fatal("String table overflow");
+       p = myalloc(size+1);    /* extra room for terminating zero */
+       stab[nstab++] = p;
+       return(p);
+}
+
+compar(p1,p2) char **p1,**p2; {
+
+       assert(*p1 != *p2);
+       if (*p1 < *p2)
+               return(-1);
+       return(1);
+}
+
+garbage_collect() {
+       register i;
+       struct emline *emlp;
+       token_p tp;
+       tkdef_p tdp;
+       struct reginfo *rp;
+       register char **fillp,**scanp;
+       char used[MAXSTAB];     /* could be bitarray */
+
+       if (nstab<THRESHOLD)
+               return;
+       qsort(stab,nstab,sizeof (char *),compar);
+       for (i=0;i<nstab;i++)
+               used[i]= FALSE;
+       for(emlp=emlines;emlp<emlines+nemlines;emlp++)
+               chkstr(emlp->em_soper,used);
+       for (tp= fakestack;tp<&fakestack[stackheight];tp++) {
+               if (tp->t_token== -1)
+                       continue;
+               tdp = &tokens[tp->t_token];
+               for (i=0;i<TOKENSIZE;i++)
+                       if (tdp->t_type[i] == EV_ADDR)
+                               chkstr(tp->t_att[i].aa.ea_str,used);
+       }
+       for (rp= machregs+1; rp<machregs+NREGS; rp++) {
+               tp = &rp->r_contents;
+               assert(tp->t_token != -1);
+               tdp= &tokens[tp->t_token];
+               for (i=0;i<TOKENSIZE;i++)
+                       if (tdp->t_type[i] == EV_ADDR)
+                               chkstr(tp->t_att[i].aa.ea_str,used);
+       }
+       for (i=0;i<nstab;i++)
+               if (!used[i]) {
+                       myfree(stab[i]);
+                       stab[i]=0;
+               }
+       fillp=stab;
+       for (scanp=stab;scanp<stab+nstab;scanp++)
+               if (*scanp != 0)
+                       *fillp++ = *scanp;
+       nstab = fillp-stab;
+}
+
+chkstr(str,used) string str; char used[]; {
+       register low,middle,high;
+
+       low=0; high=nstab-1;
+       while (high>low) {
+               middle= (low+high)>>1;
+               if (str==stab[middle]) {
+                       used[middle]=1;
+                       return;
+               }
+               if (str<stab[middle])
+                       high = middle-1;
+               else
+                       low = middle+1;
+       }
+       if (low==high) {
+               if (str==stab[low]) {
+                       used[low]=1;
+               }
+               return;
+       }
+}
diff --git a/mach/proto/ncg/state.c b/mach/proto/ncg/state.c
new file mode 100644 (file)
index 0000000..4f7188c
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "state.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+extern int nstab;      /* salloc.c */
+
+savestatus(sp) register state_p sp; {
+
+       sp->st_sh = stackheight;
+       bmove((short *)fakestack,(short *)sp->st_fs,stackheight*sizeof(token_t));
+       sp->st_na = nallreg;
+       bmove((short *)allreg,(short *)sp->st_ar,nallreg*sizeof(int));
+       sp->st_ct = curtoken;
+       bmove((short *)dollar,(short *)sp->st_do,LONGESTPATTERN*sizeof(result_t));
+       bmove((short *)machregs,(short *)sp->st_mr,NREGS*sizeof(struct reginfo));
+       sp->st_ne = nemlines;
+       bmove((short *)emlines,(short *)sp->st_el,nemlines*sizeof(struct emline));
+       sp->st_em = emp;
+       sp->st_se = saveemp;
+       sp->st_tl = tokpatlen;
+       sp->st_ns = nstab;
+}
+
+restorestatus(sp) register state_p sp; {
+
+       stackheight = sp->st_sh;
+       bmove((short *)sp->st_fs,(short *)fakestack,stackheight*sizeof(token_t));
+       nallreg = sp->st_na;
+       bmove((short *)sp->st_ar,(short *)allreg,nallreg*sizeof(int));
+       curtoken = sp->st_ct;
+       bmove((short *)sp->st_do,(short *)dollar,LONGESTPATTERN*sizeof(result_t));
+       bmove((short *)sp->st_mr,(short *)machregs,NREGS*sizeof(struct reginfo));
+       nemlines = sp->st_ne;
+       bmove((short *)sp->st_el,(short *)emlines,nemlines*sizeof(struct emline));
+       emp = sp->st_em;
+       saveemp = sp->st_se;
+       tokpatlen = sp->st_tl;
+       popstr(sp->st_ns);
+}
+
+bmove(from,to,nbytes) register short *from,*to; register nbytes; {
+
+       if (nbytes<=0)
+               return;
+       assert(sizeof(short)==2 && (nbytes&1)==0);
+       nbytes>>=1;
+       do
+               *to++ = *from++;
+       while (--nbytes);
+}
diff --git a/mach/proto/ncg/state.h b/mach/proto/ncg/state.h
new file mode 100644 (file)
index 0000000..45e2ba4
--- /dev/null
@@ -0,0 +1,18 @@
+/* $Header$ */
+
+typedef struct state {
+       struct state *st_next;                  /* for linked list */
+       int st_sh;                              /* stackheight */
+       token_t st_fs[MAXFSTACK];               /* fakestack */
+       int st_na;                              /* nallreg */
+       int st_ar[MAXALLREG];                   /* allreg[] */
+       token_p st_ct;                          /* curtoken */
+       result_t st_do[LONGESTPATTERN];         /* dollar[] */
+       struct reginfo st_mr[NREGS];            /* machregs[] */
+       int st_ne;                              /* nemlines */
+       struct emline st_el[MAXEMLINES];        /* emlines[] */
+       struct emline *st_em;                   /* emp */
+       struct emline *st_se;                   /* saveemp */
+       int st_tl;                              /* tokpatlen */
+       int st_ns;                              /* nstab */
+} state_t,*state_p;
diff --git a/mach/proto/ncg/subr.c b/mach/proto/ncg/subr.c
new file mode 100644 (file)
index 0000000..b04086d
--- /dev/null
@@ -0,0 +1,617 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "assert.h"
+#include <stdio.h>
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+#include "extern.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+string myalloc();
+unsigned codegen();
+
+match(tp,tep,optexp) register token_p tp; register set_p tep; {
+       register bitno;
+       token_p ct;
+       result_t result;
+
+       if (tp->t_token == -1) {        /* register frame */
+               bitno = tp->t_att[0].ar;
+               if (tep->set_val[bitno>>4]&(1<<(bitno&017)))
+                       if (tep->set_val[0]&1 || getrefcount(tp->t_att[0].ar)<=1)
+                               goto oklabel;
+               return(0);
+       } else {                /* token frame */
+               bitno = tp->t_token+NREGS;
+               if ((tep->set_val[bitno>>4]&(1<<(bitno&017)))==0)
+                       return(0);
+       }
+    oklabel:
+       if (optexp==0)
+               return(1);
+       ct=curtoken;
+       curtoken=tp;
+       result=compute(&enodes[optexp]);
+       curtoken=ct;
+       return(result.e_v.e_con);
+}
+
+instance(instno,token) register token_p token; {
+       register inst_p inp;
+       int i;
+       register token_p tp;
+       struct reginfo *rp;
+       int regno;
+       result_t result;
+
+       if (instno==0) {
+               token->t_token = 0;
+               for(i=0;i<TOKENSIZE;i++)
+                       token->t_att[i].aw=0;
+               return;
+       }
+       inp= &tokeninstances[instno];
+       switch(inp->in_which) {
+       default:
+               assert(FALSE);
+       case IN_COPY:
+               tp= &fakestack[stackheight-inp->in_info[0]];
+               if (inp->in_info[1]==0) {
+                       *token = *tp;
+               } else {
+                       token->t_token= -1;
+#if MAXMEMBERS!=0
+                       assert(tp->t_token == -1);
+                       rp = &machregs[tp->t_att[0].ar];
+                       token->t_att[0].ar=rp->r_members[inp->in_info[1]-1];
+#else
+                       assert(FALSE);
+#endif
+               }
+               return;
+       case IN_MEMB:
+               tp= &fakestack[stackheight-inp->in_info[0]];
+               assert(inp->in_info[1]!=0);
+               assert(tp->t_token>0);
+               token->t_token= -1;
+               assert(tokens[tp->t_token].t_type[inp->in_info[1]-1] == EV_REG);
+               token->t_att[0].ar=tp->t_att[inp->in_info[1]-1].ar;
+               return;
+       case IN_RIDENT:
+               token->t_token= -1;
+               token->t_att[0].ar= inp->in_info[0];
+               return;
+       case IN_ALLOC:
+               token->t_token= -1;
+               regno=allreg[inp->in_info[0]];
+#if MAXMEMBERS!=0
+               if (inp->in_info[1])
+                       regno=machregs[regno].r_members[inp->in_info[1]-1];
+#endif
+               token->t_att[0].ar = regno;
+               return;
+#ifdef REGVARS
+       case IN_S_DESCR:
+       case IN_D_DESCR:
+               result=compute(&enodes[inp->in_info[1]]);
+               assert(result.e_typ==EV_INT);
+               if ((regno=isregvar(result.e_v.e_con)) > 0) {
+                       token->t_token = -1;
+                       token->t_att[0].ar = regno;
+                       for(i=1;i<TOKENSIZE;i++)
+                               token->t_att[i].aw = 0;
+                       return;
+               }
+               /* fall through */
+#endif
+       case IN_DESCR:
+               token->t_token=inp->in_info[0];
+               for (i=0;i<TOKENSIZE;i++)
+                       if (inp->in_info[i+1]==0) {
+                               assert(tokens[token->t_token].t_type[i]==0);
+                               token->t_att[i].aw=0;
+                       } else {
+                               result=compute(&enodes[inp->in_info[i+1]]);
+                               assert(tokens[token->t_token].t_type[i]==result.e_typ);
+                               if (result.e_typ==EV_INT)
+                                       token->t_att[i].aw=result.e_v.e_con;
+                               else if (result.e_typ==EV_ADDR)
+                                       token->t_att[i].aa= result.e_v.e_addr;
+                               else
+                                       token->t_att[i].ar=result.e_v.e_reg;
+                       }
+               return;
+       }
+}
+
+cinstance(instno,token,tp,regno) register token_p token,tp; {
+       register inst_p inp;
+       int i;
+       struct reginfo *rp;
+       result_t result;
+       int sh; /* saved stackheight */
+
+       assert(instno!=0);
+       inp= &tokeninstances[instno];
+       switch(inp->in_which) {
+       default:
+               assert(FALSE);
+       case IN_COPY:
+               assert(inp->in_info[0] == 1);
+               if (inp->in_info[1]==0) {
+                       *token = *tp;
+               } else {
+                       token->t_token= -1;
+#if MAXMEMBERS!=0
+                       assert(tp->t_token == -1);
+                       rp = &machregs[tp->t_att[0].ar];
+                       token->t_att[0].ar=rp->r_members[inp->in_info[1]-1];
+#else
+                       assert(FALSE);
+#endif
+               }
+               return;
+       case IN_MEMB:
+               assert(inp->in_info[0] == 1);
+               token->t_token= -1;
+               assert(tp->t_token>0);
+               assert(tokens[tp->t_token].t_type[inp->in_info[1]-1] == EV_REG);
+               token->t_att[0].ar=tp->t_att[inp->in_info[1]-1].ar;
+               return;
+       case IN_RIDENT:
+               token->t_token= -1;
+               token->t_att[0].ar= inp->in_info[0];
+               return;
+       case IN_ALLOC:
+               token->t_token= -1;
+               assert(inp->in_info[0]==0);
+#if MAXMEMBERS!=0
+               if (inp->in_info[1])
+                       regno=machregs[regno].r_members[inp->in_info[1]-1];
+#endif
+               token->t_att[0].ar = regno;
+               return;
+#ifdef REGVARS
+       case IN_S_DESCR:
+       case IN_D_DESCR:
+               result=compute(&enodes[inp->in_info[1]]);
+               assert(result.e_typ==EV_INT);
+               if ((regno=isregvar(result.e_v.e_con)) > 0) {
+                       token->t_token = -1;
+                       token->t_att[0].ar = regno;
+                       for(i=1;i<TOKENSIZE;i++)
+                               token->t_att[i].aw = 0;
+                       return;
+               }
+               /* fall through */
+#endif
+       case IN_DESCR:
+               sh = stackheight;
+               stackheight = tp - fakestack + 1;
+               token->t_token=inp->in_info[0];
+               for (i=0;i<TOKENSIZE;i++)
+                       if (inp->in_info[i+1]==0) {
+                               assert(tokens[token->t_token].t_type[i]==0);
+                               token->t_att[i].aw=0;
+                       } else {
+                               result=compute(&enodes[inp->in_info[i+1]]);
+                               assert(tokens[token->t_token].t_type[i]==result.e_typ);
+                               if (result.e_typ==EV_INT)
+                                       token->t_att[i].aw=result.e_v.e_con;
+                               else if (result.e_typ==EV_ADDR)
+                                       token->t_att[i].aa= result.e_v.e_addr;
+                               else
+                                       token->t_att[i].ar=result.e_v.e_reg;
+                       }
+               stackheight = sh;
+               return;
+       }
+}
+
+eqtoken(tp1,tp2) token_p tp1,tp2; {
+       register i;
+       register tkdef_p tdp;
+
+       if (tp1->t_token!=tp2->t_token)
+               return(0);
+       if (tp1->t_token==0)
+               return(1);
+       if (tp1->t_token==-1) {
+               if (tp1->t_att[0].ar!=tp2->t_att[0].ar)
+                       return(0);
+               return(1);
+       }
+       tdp = &tokens[tp1->t_token];
+       for (i=0;i<TOKENSIZE;i++)
+               switch(tdp->t_type[i]) {
+               default:
+                       return(1);
+               case EV_INT:
+                       if (tp1->t_att[i].aw != tp2->t_att[i].aw)
+                               return(0);
+                       break;
+               case EV_REG:
+                       if (tp1->t_att[i].ar != tp2->t_att[i].ar)
+                               return(0);
+                       break;
+               case EV_ADDR:
+                       if (strcmp(tp1->t_att[i].aa.ea_str, tp2->t_att[i].aa.ea_str))
+                               return(0);
+                       if (tp1->t_att[i].aa.ea_off!=tp2->t_att[i].aa.ea_off)
+                               return(0);
+                       break;
+               }
+       return(1);
+}
+
+distance(cindex) {
+       register char *bp;
+       register i;
+       register token_p tp;
+       int tokexp,tpl;
+       int expsize,toksize,exact;
+       int xsekt=0;
+
+       bp = &coderules[cindex];
+#ifndef NDEBUG
+       if (*bp==DO_DLINE) {
+               ++bp;
+               getint(i,bp);
+       }
+#endif
+       switch( (*bp)&037 ) {
+       default:
+               return(stackheight==0 ? 0 : 100);
+       case DO_MATCH:
+               break;
+       case DO_XXMATCH:
+               xsekt++;
+       case DO_XMATCH:
+               xsekt++;
+               break;
+       }
+       tpl= ((*bp++)>>5)&07;
+       if (stackheight < tpl) {
+               if (xsekt)
+                       return(MAXINT);
+               tpl = stackheight;
+       } else
+               if (stackheight != tpl && xsekt==2)
+                       return(MAXINT);
+       exact=0;
+       tp= &fakestack[stackheight-1];
+       for (i=0;i<tpl;i++,tp--) {
+               getint(tokexp,bp);
+               if (!match(tp, &machsets[tokexp], 0)) {
+                       if (xsekt)
+                               return(MAXINT);
+                       expsize = ssize(tokexp);
+                       toksize = tsize(tp);
+                       if (expsize>toksize)
+                               return(100);
+                       if (expsize<toksize)
+                               return(99-i);
+               } else
+                       exact++;
+       }
+       if (exact==tpl) {
+               if (xsekt)
+                       return(0);
+               return(10-exact);
+       }
+       return(20-exact);
+}
+
+unsigned costcalc(cost) cost_t cost; {
+       extern unsigned cc1,cc2,cc3,cc4;
+
+       return(cost.ct_space*cc1/cc2 + cost.ct_time*cc3/cc4);
+}
+
+ssize(tokexpno) {
+
+       return(machsets[tokexpno].set_size);
+}
+
+tsize(tp) register token_p tp; {
+
+       if (tp->t_token==-1)
+               return(machregs[tp->t_att[0].ar].r_size);
+       return(tokens[tp->t_token].t_size);
+}
+
+#ifdef MAXSPLIT
+instsize(tinstno,tp) token_p tp; {
+       inst_p inp;
+       struct reginfo *rp;
+
+       inp = &tokeninstances[tinstno];
+       switch(inp->in_which) {
+       default:
+               assert(FALSE);
+       case IN_COPY:
+               assert(inp->in_info[0]==1);
+#if MAXMEMBERS!=0
+               if (inp->in_info[1]==0)
+#endif
+                       return(tsize(tp));
+#if MAXMEMBERS!=0
+               else {
+                       assert(tp->t_token == -1);
+                       rp = &machregs[tp->t_att[0].ar];
+                       return(machregs[rp->r_members[inp->in_info[1]-1]].r_size);
+               }
+#endif
+       case IN_RIDENT:
+               return(machregs[inp->in_info[0]].r_size);
+       case IN_ALLOC:
+               assert(FALSE);  /* cannot occur in splitting coercion */
+       case IN_DESCR:
+       case IN_S_DESCR:
+       case IN_D_DESCR:
+               return(tokens[inp->in_info[0]].t_size);
+       }
+}
+#endif MAXSPLIT
+
+tref(tp,amount) register token_p tp; {
+       register i;
+       register tkdef_p tdp;
+
+       if (tp->t_token==-1)
+               chrefcount(tp->t_att[0].ar,amount,FALSE);
+       else {
+               tdp= &tokens[tp->t_token];
+               for(i=0;i<TOKENSIZE;i++)
+                       if (tdp->t_type[i]==EV_REG)
+                               chrefcount(tp->t_att[i].ar,amount,FALSE);
+       }
+}
+
+#define MAXSAVE 10
+
+#ifdef MAXSPLIT
+split(tp,ip,ply,toplevel) token_p tp; register int *ip; {
+       register c2_p cp;
+       token_t savestack[MAXSAVE];
+       int ok;
+       register i;
+       int diff;
+       token_p stp;
+       int tpl;
+
+       for (cp=c2coercs;cp->c2_texpno>=0; cp++) {
+               if (!match(tp,&machsets[cp->c2_texpno],0))
+                       continue;
+               ok=1;
+               for (i=0; ok && i<cp->c2_nsplit;i++) {
+                       if (ip[i]==0)
+                               goto found;
+                       if (instsize(cp->c2_repl[i],tp) != ssize(ip[i]))
+                               ok=0;
+               }
+               goto found;
+       }
+       return(0);
+found:
+       assert(stackheight+cp->c2_nsplit-1<MAXFSTACK);
+       stp = &fakestack[stackheight-1];
+       diff = stp - tp;
+       assert(diff<=MAXSAVE);
+       for (i=1;i<=diff;i++)
+               savestack[i-1] = tp[i];         /* save top of stack */
+       stackheight -= diff;
+       tpl = tokpatlen;
+       tokpatlen = 1;
+       codegen(&coderules[cp->c2_codep],ply,toplevel,MAXINT,0);
+       tokpatlen = tpl;
+       for (i=0;i<diff;i++)            /* restore top of stack */
+               fakestack[stackheight++] = savestack[i];
+       return(cp->c2_nsplit);
+}
+#endif MAXSPLIT
+
+unsigned docoerc(tp,cp,ply,toplevel,forced) token_p tp; register c3_p cp; {
+       token_t savestack[MAXSAVE];
+       token_p stp;
+       register int i,diff;
+       unsigned cost;
+       int tpl;        /* saved tokpatlen */
+
+       stp = &fakestack[stackheight-1];
+       diff = stp -tp;
+       assert(diff<=MAXSAVE);
+#ifndef NDEBUG
+       if (diff!=0 && Debug>1)
+               fprintf(stderr,"Saving %d items from fakestack\n",diff);
+#endif
+       for (i=1;i<=diff;i++)
+               savestack[i-1] = tp[i];
+       stackheight -= diff;
+       tpl = tokpatlen;
+       tokpatlen = 1;
+       cost = codegen(&coderules[cp->c3_codep],ply,toplevel,MAXINT,forced);
+       tokpatlen = tpl;
+#ifndef NDEBUG
+       if (diff!=0 && Debug>1)
+               fprintf(stderr,"Restoring %d items to fakestack(%d)\n",diff,stackheight);
+#endif
+       for (i=0;i<diff;i++)
+               fakestack[stackheight++] = savestack[i];
+       nallreg = 0;
+       return(cost);
+}
+
+unsigned stackupto(limit,ply,toplevel) token_p limit; {
+       token_t savestack[MAXFSTACK];
+       token_p stp;
+       int i,diff;
+       int tpl;        /* saved tokpatlen */
+       int nareg;      /* saved nareg */
+       int areg[MAXALLREG];
+       register c1_p cp;
+       register token_p tp;
+       unsigned totalcost=0;
+       struct reginfo *rp,**rpp;
+
+       for (tp=fakestack;tp<=limit;limit--) {
+               for (cp=c1coercs;cp->c1_texpno>=0; cp++) {
+                       if (match(tp,&machsets[cp->c1_texpno],cp->c1_expr)) {
+                               if (cp->c1_prop>=0) {
+                                       for (rpp=reglist[cp->c1_prop];
+                                              (rp = *rpp)!=0 &&
+                                              getrefcount(rp-machregs)!=0;
+                                                 rpp++)
+                                               ;
+                                       if (rp==0)
+                                               continue;
+                                               /* look for other possibility */
+                               }
+                               stp = &fakestack[stackheight-1];
+                               diff = stp -tp;
+                               assert(diff<=MAXFSTACK);
+                               for (i=1;i<=diff;i++)
+                                       savestack[i-1] = tp[i];
+                               stackheight -= diff;
+                               tpl = tokpatlen;
+                               tokpatlen = 1;
+                               nareg = nallreg;
+                               for (i=0;i<nareg;i++)
+                                       areg[i] = allreg[i];
+                               if (cp->c1_prop>=0) {
+                                       nallreg=1; allreg[0] = rp-machregs;
+                                       chrefcount(allreg[0],1,FALSE);
+                               } else 
+                                       nallreg=0;
+                               totalcost+= codegen(&coderules[cp->c1_codep],ply,toplevel,MAXINT,0);
+                               tokpatlen = tpl;
+                               for (i=0;i<diff;i++)
+                                       fakestack[stackheight++] = savestack[i];
+                               nallreg=nareg;
+                               for (i=0;i<nareg;i++)
+                                       allreg[i] = areg[i];
+                               goto contin;
+                       }
+               }
+               assert(FALSE);
+       contin: ;
+       }
+       return(totalcost);
+}
+
+c3_p findcoerc(tp,tep) token_p tp; set_p tep; {
+       register c3_p cp;
+       token_t rtoken;
+       register i;
+       register struct reginfo **rpp;
+
+       for (cp=c3coercs;cp->c3_texpno>=0; cp++) {
+               if (tp!=(token_p) 0) {
+                       if (cp->c3_texpno==0)
+                               continue;
+                       if (!match(tp,&machsets[cp->c3_texpno],cp->c3_expr))
+                               continue;
+               } else {
+                       if (cp->c3_texpno!=0)
+                               continue;
+               }
+               if (cp->c3_prop==0) {   /* no reg needed */
+                       cinstance(cp->c3_repl,&rtoken,tp,0);
+                       if (match(&rtoken,tep,0))
+                               return(cp);
+               } else {
+                       curreglist = (rl_p) myalloc(sizeof (rl_t));
+                       curreglist->rl_n = 0;
+                       for (rpp=reglist[cp->c3_prop];*rpp;rpp++) {
+                               i = *rpp - machregs;
+                               cinstance(cp->c3_repl,&rtoken,tp,i);
+                               if (match(&rtoken,tep,0))
+                                       curreglist->rl_list[curreglist->rl_n++] = i;
+                       }
+                       if (curreglist->rl_n != 0)
+                               return(cp);
+                       myfree(curreglist);
+               }
+       }
+       return(0);      /* nothing found */
+}
+
+itokcost() {
+       register tkdef_p tdp;
+
+       for(tdp=tokens+1;tdp->t_size!=0;tdp++)
+               tdp->t_cost.ct_space = costcalc(tdp->t_cost);
+}
+
+error(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; {
+
+       fatal(s,a1,a2,a3,a4,a5,a6,a7,a8);
+}
+
+fatal(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; {
+
+       fprintf(stderr,"Error: ");
+       fprintf(stderr,s,a1,a2,a3,a4,a5,a6,a7,a8);
+       fprintf(stderr,"\n");
+#ifdef TABLEDEBUG
+       ruletrace();
+#endif
+       out_finish();
+       abort();
+       exit(-1);
+}
+
+#ifdef TABLEDEBUG
+
+ruletrace() {
+       register i;
+       extern int tablelines[MAXTDBUG];
+       extern int ntableline;
+       extern char *tablename;
+
+       fprintf(stderr,"Last code rules used\n");
+       i=ntableline-1;
+       while(i!=ntableline) {
+               if (i<0)
+                       i += MAXTDBUG;
+               if (tablelines[i]!=0)
+                       fprintf(stderr,"\%d: \"%s\", line %d\n",i,tablename,tablelines[i]);
+               i--;
+       }
+}
+#endif
+
+#ifndef NDEBUG
+badassertion(asstr,file,line) char *asstr, *file; {
+
+       fatal("\"%s\", line %d:Assertion \"%s\" failed",file,line,asstr);
+}
+#endif
+
+max(a,b) {
+
+       return(a>b ? a : b);
+}
diff --git a/mach/proto/ncg/types.h b/mach/proto/ncg/types.h
new file mode 100644 (file)
index 0000000..ee66613
--- /dev/null
@@ -0,0 +1,27 @@
+/* $Header$ */
+
+#ifndef TEM_WSIZE
+TEM_WSIZE should be defined at this point
+#endif
+#ifndef TEM_PSIZE
+TEM_PSIZE should be defined at this point
+#endif
+#if TEM_WSIZE>4 || TEM_PSIZE>4
+Implementation will not be correct unless a long integer
+has more then 4 bytes of precision.
+#endif
+
+typedef char byte;
+typedef char * string;
+
+#if TEM_WSIZE>2 || TEM_PSIZE>2
+#define full            long
+#else
+#define full           int
+#endif
+
+#if TEM_WSIZE>2
+#define word long
+#else
+#define word int
+#endif
diff --git a/mach/proto/ncg/var.c b/mach/proto/ncg/var.c
new file mode 100644 (file)
index 0000000..6ba1d46
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef NORCSID
+static char rcsid[] = "$Header$";
+#endif
+
+#include "param.h"
+#include "tables.h"
+#include "types.h"
+#include <cgg_cg.h>
+#include "data.h"
+#include "result.h"
+
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ * Author: Hans van Staveren
+ */
+
+int stackheight = 0;
+token_t fakestack[MAXFSTACK];
+int nallreg = 0;
+int allreg[MAXALLREG];
+token_p curtoken = (token_p) 0;
+result_t dollar[LONGESTPATTERN];
+int nemlines =0;
+struct emline emlines[MAXEMLINES];
+struct emline *emp=emlines;
+struct emline *saveemp;
+int tokpatlen;
+rl_p curreglist;