BSD 3 development
authorJohn Reiser <jfr@ucbvax.Berkeley.EDU>
Fri, 30 Nov 1979 03:00:27 +0000 (19:00 -0800)
committerJohn Reiser <jfr@ucbvax.Berkeley.EDU>
Fri, 30 Nov 1979 03:00:27 +0000 (19:00 -0800)
Work on file usr/src/cmd/as/ascode.c
Work on file usr/src/cmd/as/asexpr.c
Work on file usr/src/cmd/as/asexpr.h
Work on file usr/src/cmd/as/asjxxx.c
Work on file usr/src/cmd/as/asmain.c
Work on file usr/src/cmd/as/asparse.c
Work on file usr/src/cmd/as/asscan.h
Work on file usr/src/cmd/as/assyms.c
Work on file usr/src/cmd/as/assyms.h
Work on file usr/src/cmd/as/astoks.h

Synthesized-from: 3bsd

usr/src/cmd/as/ascode.c [new file with mode: 0644]
usr/src/cmd/as/asexpr.c [new file with mode: 0644]
usr/src/cmd/as/asexpr.h [new file with mode: 0644]
usr/src/cmd/as/asjxxx.c [new file with mode: 0644]
usr/src/cmd/as/asmain.c [new file with mode: 0644]
usr/src/cmd/as/asparse.c [new file with mode: 0644]
usr/src/cmd/as/asscan.h [new file with mode: 0644]
usr/src/cmd/as/assyms.c [new file with mode: 0644]
usr/src/cmd/as/assyms.h [new file with mode: 0644]
usr/src/cmd/as/astoks.h [new file with mode: 0644]

diff --git a/usr/src/cmd/as/ascode.c b/usr/src/cmd/as/ascode.c
new file mode 100644 (file)
index 0000000..cd33244
--- /dev/null
@@ -0,0 +1,274 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#include <stdio.h>
+#include "as.h"
+#include "assyms.h"
+
+insout(op, ap, nact)
+       struct arg *ap;
+{
+       int jxxflg;
+
+       op &= 0xFF;
+       jxxflg = nact;
+       if (nact < 0)
+               nact = -nact;
+       if (passno!=2) {
+               register struct arg     *ap2;
+               register struct instab  *ip;
+               int                     i,nexp;
+               ip = itab[op];
+               nexp = ip->nargs;
+               if (nact < nexp)
+                       yyerror("Too few arguments");
+               if (nact > nexp) {
+                       yyerror("Too many arguments");
+                       nact = nexp;
+               }
+               /*
+                *      Check argument compatability with instruction template
+                */
+               for (ap2 = ap+nact, i = nact; --i >= 0;)
+                       argcompat(--ap2, ip->argtype[i], i);
+       }
+       if (jxxflg < 0)
+               ijxout(op, ap, nact);
+       else putins(op, ap, nact);
+}
+
+argcompat(act, exp, i)
+       struct arg *act;
+       int exp,i;
+{
+       register        at,atm;
+
+       at = act->atype;
+       atm = at & AMASK;
+
+       if ((exp & ACCA) && (atm == AREG)) {
+               yyerror("arg %d, addressing a register",i);
+               return;
+       }
+       if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) {
+               yyerror("arg %d, modifying a constant",i);
+               return;
+       }
+       if (at & AINDX) {
+               if (act->areg2==017) {
+                       yyerror("arg %d, PC used as index",i);
+                       return;
+               }
+               if (atm==AREG) {
+                       yyerror("arg %d, indexing the register file",i);
+                       return;
+               }
+               if (atm==AIMM) {
+                       yyerror("arg %d, indexing a constant",i);
+                       return;
+               }
+               if (((atm==ADECR) || (atm==AINCR)) && (act->areg1==act->areg2)) {
+                       yyerror("arg %d, indexing with modified register",i);
+                       return;
+               }
+       }
+}
+
+int d124 =     {4};
+int len124[] =         {0,LEN1,LEN2,0,LEN4};
+char mod124[] = {0,0x00,0x20,0,0x40};
+
+putins(op, ap, n)
+       /*
+        *      n had better be positive
+        */
+       register struct arg *ap;
+{
+       register struct exp     *xp;
+       register int            a;
+       int                     i,xtrab;
+
+       if (passno!=2) {
+               dotp->xvalue += n+1;    /* 1 for the opcode, at least 1 per arg */
+               for (i=0; i<n; i++,ap++) {/* some args take more than 1 byte */
+                       a=ap->atype;
+                       if (a & AINDX)
+                               dotp->xvalue++;
+                       switch (a&~(AINDX|ASTAR)) {
+                               case AEXP: {
+                                       a = itab[op]->argtype[i];
+                                       if (a == ACCB+TYPB)
+                                               break;
+                                       if (a==ACCB+TYPW){
+                                               dotp->xvalue++;
+                                               break;
+                                       }
+                                       dotp->xvalue += ap->dispsize;
+                                       break;
+                               }
+                               case ADISP: {
+                                       xp=ap->xp;
+                                       if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){
+                                               dotp->xvalue += ap->dispsize;
+                                               break;
+                                       }
+                                       if (xp->xvalue==0 && !(a&ASTAR))
+                                               break;
+                                       dotp->xvalue++;
+                                       if ((xp->xvalue<MINBYTE) || (xp->xvalue>MAXBYTE))
+                                               dotp->xvalue++;
+                                       if ((xp->xvalue<MINWORD) || (xp->xvalue>MAXWORD))
+                                               dotp->xvalue += 2;
+                                       break;
+                               }
+                               case AIMM: {
+                                       if (ap->atype&ASTAR) a=TYPL;
+                                       else {
+                                               xp = ap->xp;
+                                               if ((xp->xtype&XTYPE)==XABS && !(xp->xtype&XFORW)
+                                                       && xp->xvalue>=0 && xp->xvalue<=63) 
+                                                               break;
+                                               a = itab[op]->argtype[i];
+                                               if (a&ACCA)
+                                                       a = TYPL;
+                                               else
+                                                       a &= TYPMASK;
+                                       }
+                                       switch (a) {
+                                               case TYPD:
+                                               case TYPF:
+                                                       if (slitflt(xp))
+                                                               break;
+                                                       if (a==TYPF)
+                                                               dotp->xvalue -= 4;
+                                               case TYPQ: 
+                                                       dotp->xvalue += 4;
+                                               case TYPL:
+                                                       dotp->xvalue += 2;
+                                               case TYPW: 
+                                                       dotp->xvalue++;
+                                               case TYPB: 
+                                                       dotp->xvalue++;
+                                       }       /*end of the switch on a*/
+                               }       /*end of case AIMM*/
+                       }       /*end of the switch on the type*/
+               }       /*end of looping for all arguments*/
+               return;
+       }       /*end of it being time for pass 1*/
+       /*
+        *      PASS2 HERE
+        */
+
+       outb(op); /* the opcode */
+       for (i=0; i<n; i++,ap++) {/* now for the arguments */
+               a=ap->atype;
+               xp=ap->xp;
+               xtrab=0;
+               if (a&AINDX) {
+                       { outb(0x40 | ap->areg2); }
+                       a &= ~AINDX;
+               }
+               if (a&ASTAR) {
+                       ap->areg1 |= 0x10;
+                       a &= ~ASTAR;
+               }
+               switch (a) {
+                       case AREG:              /* %r */
+                               ap->areg1 |= 0x50;
+                               break; 
+                       case ABASE:             /* (%r) */
+                               ap->areg1 |= 0x60;
+                               break; 
+                       case ADECR:             /* -(%r) */
+                               ap->areg1 |= 0x70;
+                               break; 
+                       case AINCR:             /* (%r) */
+                               ap->areg1 |= 0x80;
+                               break;
+                       case AEXP: {/* expr */
+                               a = itab[op]->argtype[i];
+                               if (a == ACCB+TYPB) {
+                                       ap->areg1 = a = 
+                                               xp->xvalue - (dotp->xvalue + 1);
+                                       if (a<MINBYTE || a>MAXBYTE)
+                                               yyerror("Branch too far"); break;
+                               }
+                               if (a == ACCB+TYPW) {
+                                       ap->areg1 = a = xp->xvalue
+                                               -= dotp->xvalue + 2;
+                                       xp->xtype = XABS;
+                                       if (a<MINWORD || a>MAXWORD) 
+                                               yyerror("Branch too far");
+                                       xp->xvalue = a>>8;
+                                       xtrab = LEN1;
+                                       break;
+                               }
+                               /* reduces to expr(pc) mode */
+                               ap->areg1 |= (0xAF + mod124[ap->dispsize]);
+                               xtrab = len124[ap->dispsize]+PCREL;
+                               break;
+                       }
+                       case ADISP: {/* expr(%r) */
+                               ap->areg1 |= 0xA0;
+                               if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){
+                                       ap->areg1 += mod124[ap->dispsize];
+                                       xtrab=len124[ap->dispsize];
+                                       break;
+                               }
+                               if (xp->xvalue==0 && !(ap->areg1&0x10)) {
+                                       ap->areg1 ^= 0xC0;
+                                       break;
+                               }
+                               xtrab=LEN1;
+                               if ((xp->xvalue<MINBYTE) || (xp->xvalue>MAXBYTE)){
+                                       ap->areg1 += 0x20;
+                                       xtrab=LEN2;
+                               }
+                               if ((xp->xvalue<MINWORD) || (xp->xvalue>MAXWORD)){
+                                       ap->areg1 += 0x20;
+                                       xtrab=LEN4;
+                               }
+                               break;
+                       }
+                       case AIMM: { /* $expr */
+                               if (ap->atype&ASTAR)
+                                       a=TYPL;
+                               else {
+                                       if (    ( (xp->xtype&XTYPE) == XABS) 
+                                           && !(xp->xtype&XFORW)
+                                           &&  (xp->xvalue >= 0)
+                                           &&  (xp->xvalue <= 63) ) {
+                                               ap->areg1 = xp->xvalue;
+                                               break;
+                                       }
+                                       a = itab[op]->argtype[i];
+                                       if (a&ACCA)
+                                               a=TYPL;
+                                       else
+                                               a &= TYPMASK;
+                               }
+                               ap->areg1 |= 0x8F;
+                               switch (a) {
+                                       case TYPD:
+                                       case TYPF:
+                                               if (slitflt(xp)){
+                                                       ap->areg1=extlitflt(xp);
+                                                       break;
+                                               }
+                                               if (a==TYPF) { 
+                                                       xtrab = LEN4;
+                                                       break;
+                                               }
+                                       case TYPQ: xtrab = LEN8; break;
+                                       case TYPL: xtrab = LEN4; break;
+                                       case TYPW: xtrab = LEN2; break;
+                                       case TYPB: xtrab = LEN1; break;
+                               }
+                       }       /*end of the switch on AIMM*/
+               }       /*end of the switch on a*/
+               /*
+                *      use the first byte to describe the argument
+                */
+               outb(ap->areg1);
+               if (xtrab) 
+                       outrel(&xp->xvalue, xtrab, xp->xtype, xp->xname);
+       }       /*end of the for to pick up all arguments*/
+}
diff --git a/usr/src/cmd/as/asexpr.c b/usr/src/cmd/as/asexpr.c
new file mode 100644 (file)
index 0000000..e8aa886
--- /dev/null
@@ -0,0 +1,296 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#include <stdio.h>
+#include "as.h"
+#include "asexpr.h"
+
+/*
+ * Tables for combination of operands.
+ */
+
+/*
+ *     table for +
+ */
+readonly char pltab[6][6] = {
+/*             UND     ABS     TXT     DAT     BSS     EXT */
+
+/*UND*/                XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
+/*ABS*/                XUNDEF, XABS,   XTEXT,  XDATA,  XBSS,   XXTRN,
+/*TXT*/                XUNDEF, XTEXT,  ERR,    ERR,    ERR,    ERR,
+/*DAT*/                XUNDEF, XDATA,  ERR,    ERR,    ERR,    ERR,
+/*BSS*/                XUNDEF, XBSS,   ERR,    ERR,    ERR,    ERR,
+/*EXT*/                XUNDEF, XXTRN,  ERR,    ERR,    ERR,    ERR,
+};
+
+/*
+ *     table for -
+ */
+readonly char mintab[6][6] = {
+/*             UND     ABS     TXT     DAT     BSS     EXT */
+
+/*UND*/                XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
+/*ABS*/                XUNDEF, XABS,   ERR,    ERR,    ERR,    ERR,
+/*TXT*/                XUNDEF, XTEXT,  XABS,   ERR,    ERR,    ERR,
+/*DAT*/                XUNDEF, XDATA,  ERR,    XABS,   ERR,    ERR,
+/*BSS*/                XUNDEF, XBSS,   ERR,    ERR,    XABS,   ERR,
+/*EXT*/                XUNDEF, XXTRN,  ERR,    ERR,    ERR,    ERR,
+};
+
+/* 
+ *     table for other operators
+ */
+readonly char othtab[6][6] = {
+/*             UND     ABS     TXT     DAT     BSS     EXT */
+
+/*UND*/                XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
+/*ABS*/                XUNDEF, XABS,   ERR,    ERR,    ERR,    ERR,
+/*TXT*/                XUNDEF, ERR,    ERR,    ERR,    ERR,    ERR,
+/*DAT*/                XUNDEF, ERR,    ERR,    ERR,    ERR,    ERR,
+/*BSS*/                XUNDEF, ERR,    ERR,    ERR,    ERR,    ERR,
+/*EXT*/                XUNDEF, ERR,    ERR,    ERR,    ERR,    ERR,
+};
+
+struct exp *
+combine(op, exp1, exp2)
+       register struct exp *exp1, *exp2;
+{
+       register        e1_type, e2_type;
+       register        type;
+
+       lastnam=0;                      /* kludge for jxxx instructions */
+
+       e1_type = exp1->xtype&XTYPE;
+       e2_type = exp2->xtype&XTYPE;
+
+       if (exp1->xtype==XXTRN+XUNDEF)
+               e1_type = XTXRN;
+       if (exp2->xtype==XXTRN+XUNDEF)
+               e2_type = XTXRN;
+       if (passno==1)
+               if (exp1->xloc!=exp2->xloc && e1_type==e2_type)
+                       e1_type = e2_type = XTXRN;      /* error on != loc ctrs */
+       e1_type >>= 1;          /*dispost of the external (XXTRN) bit*/
+       e2_type >>= 1;
+
+       switch (op) {
+       case PLUS:
+               exp1->xvalue += exp2->xvalue;
+               type = pltab[e1_type][e2_type];
+               break;
+       case MINUS:
+               exp1->xvalue -= exp2->xvalue;
+               type = mintab[e1_type][e2_type];
+               break;
+       case IOR:
+               exp1->xvalue |= exp2->xvalue;
+               goto comm;
+       case XOR:
+               exp1->xvalue ^= exp2->xvalue;
+               goto comm;
+       case AND:
+               exp1->xvalue &= exp2->xvalue;
+               goto comm;
+       case ORNOT:
+               exp1->xvalue |= ~exp2->xvalue;
+               goto comm;
+       case LSH:
+               exp1->xvalue <<= exp2->xvalue;
+               goto comm;
+       case RSH:
+               exp1->xvalue >>= exp2->xvalue;
+               goto comm;
+       case TILDE:
+               exp1->xvalue |= ~ exp2->xvalue;
+               goto comm;
+       case MUL:
+               exp1->xvalue *= exp2->xvalue;
+               goto comm;
+       case DIV:
+               if (exp2->xvalue == 0)
+                       yyerror("Divide check");
+               else
+                       exp1->xvalue /= exp2->xvalue;
+               goto comm;
+       case REGOP:
+               if (exp2->xvalue == 0)
+                       yyerror("Divide check (modulo)");
+               else
+                       exp1->xvalue %= exp2->xvalue;
+               goto comm;
+       
+       comm:
+               type = othtab[e1_type][e2_type];
+               break;
+       default:
+               yyerror("Internal error: unknown operator");
+       }
+
+       if (e2_type==(XTXRN>>1))
+               exp1->xname = exp2->xname;
+       exp1->xtype = type | (
+                       (exp1->xtype|exp2->xtype) & (XFORW|XXTRN) );
+       if (type==ERR)
+               yyerror("Relocation error");
+       return(exp1);
+}
+
+buildtokensets()
+{
+#define clobber(val, set) tokensets[(val)] |= (set)
+
+       clobber(SEMI,   LINSTBEGIN);
+       clobber(NL,     LINSTBEGIN);
+
+       clobber(NAME,   YUKKYEXPRBEG + LINSTBEGIN);
+       clobber(INSTn,  YUKKYEXPRBEG);
+       clobber(INST0,  YUKKYEXPRBEG);
+       clobber(REG,    YUKKYEXPRBEG);
+
+       clobber(INT,    SAFEEXPRBEG);
+       clobber(FLTNUM, SAFEEXPRBEG);
+
+       clobber(PLUS,   ADDOPS);
+       clobber(MINUS,  ADDOPS + EBEGOPS);
+
+       clobber(LP,     EBEGOPS);
+
+       clobber(IOR,    BOOLOPS);
+       clobber(XOR,    BOOLOPS);
+       clobber(AND,    BOOLOPS);
+       clobber(ORNOT,  BOOLOPS);
+
+       clobber(TILDE,  MULOPS + EBEGOPS);
+       clobber(LSH,    MULOPS);
+       clobber(RSH,    MULOPS);
+       clobber(MUL,    MULOPS);
+       clobber(DIV,    MULOPS);
+       clobber(REGOP,  MULOPS);        /* % */
+}
+
+/*
+ *     We keep the current token class in this global variable, so 
+ *     the recursive descent expression analyzers can talk amongst
+ *     themselves, and so that we may use the macros shift and shift over
+ */
+
+extern int     yylval;         /*the value of the lexical value*/
+extern struct  exp     *xp;    /*the next free expression slot*/
+
+static int     val;
+int exprparse(inval, backexpr) /*return the value the read head is sitting on*/
+       int     inval;
+       struct  exp **backexpr;
+{
+       register struct exp *lexpr;
+       int     op;
+
+       val = inval;
+       lexpr = boolterm();
+       while (INTOKSET(val, ADDOPS)){
+               op = val;
+               shift;
+               lexpr = combine(op, lexpr, boolterm());
+       }
+       *backexpr = lexpr;
+       return(val);
+}
+
+struct exp *boolterm()
+{
+       register        struct exp *lexpr;
+       int     op;
+
+       lexpr = term();
+       while(INTOKSET(val, BOOLOPS)){
+               op = val;
+               shift;
+               lexpr = combine(op, lexpr, term());
+       }
+       return(lexpr);
+}
+
+struct exp *term()
+{
+       register        struct  exp     *lexpr;
+       int             op;
+
+       lexpr = factor();
+       while(INTOKSET(val, MULOPS)){
+               op = val;
+               shift;
+               lexpr = combine(op, lexpr, factor());
+       }
+       return(lexpr);
+}
+
+struct exp *factor()
+{
+       struct  exp *lexpr;
+       int             op;
+       extern          int     droppedLP;      /*called exprparse after consuming an LP*/
+
+       if (val == LP || droppedLP){
+               if (droppedLP)
+                       droppedLP = 0;
+               else
+                       shift;          /*the LP*/
+               val = exprparse(val, &lexpr);
+               if (val != RP)
+                       yyerror("right parenthesis expected");
+               else
+                       shift;
+       } else
+       if (INTOKSET(val, YUKKYEXPRBEG)){
+               lexpr = yukkyexpr(val, yylval);
+               shift;
+       }
+       else if (INTOKSET(val, SAFEEXPRBEG)){
+               lexpr = (struct exp *)yylval;
+               shift;
+       }
+       else if ( (val == TILDE) || (val == MINUS) ){
+               op = val;
+               shift;
+               lexpr = xp++;
+               lexpr->xtype = XABS;
+               lexpr->xvalue = 0;
+               lexpr = combine(op, lexpr, factor());
+       }
+       else {
+               yyerror("Bad expression syntax");
+               lexpr = xp++;
+               lexpr->xtype = XABS;
+               lexpr->xvalue = 0;
+       }
+       return(lexpr);
+}
+
+struct exp *yukkyexpr(val, np)
+       int     val;
+       register        np;
+{
+       register        struct exp *locxp;
+       extern          int     exprisname;     /*last factor is a name*/
+
+       exprisname = 0;
+       locxp = xp++;
+       if (val == NAME){
+               exprisname++;
+               locxp->xtype = ((struct symtab *)np)->type;
+               if (( ((struct symtab *)np)->type&XTYPE)==XUNDEF) { /*forward*/
+                       locxp->xname = (struct symtab *)np;
+                       locxp->xvalue = 0;
+                       if (passno==1)
+                               ((struct symtab *)np)->type |= XFORW;
+               } else {        /*otherwise, just get the value*/
+                       locxp->xvalue = ((struct symtab *)np)->value;
+                       locxp->xname = NULL;
+               }
+       } else {        /*INSTn or INST0 or REG*/
+               locxp->xtype = XABS;
+               locxp->xvalue = ( (int)np) & 0xFF;
+               locxp->xloc = 0;
+               locxp->xname = NULL;
+       }
+
+       return(locxp);
+}
diff --git a/usr/src/cmd/as/asexpr.h b/usr/src/cmd/as/asexpr.h
new file mode 100644 (file)
index 0000000..45aca48
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *     Definitions to parse tokens
+ */
+
+#define ERROR(string)          yyerror(string); goto errorfix
+
+#define peekahead (*tokptr)
+
+#define shift                  val = yylex()
+#define advance        shift
+
+#define shiftover(token)       if (val != token) { \
+                                       yyerror("token expected"); \
+                                       goto errorfix; \
+                               } \
+                               shift
+
+#define advanceover    shiftover
+
+/*
+ *     To speed up the expression processing, we class the input tokens
+ *     into various sets.
+ *
+ *     We don't call the recursive descent expression analyzer if we can
+ *     determine by looking at the next token after the first token in
+ *     an expression that the expression is simple (name, integer or floating
+ *     point value).  Expressions with operators are parsed using the recursive
+ *     descent method.
+ */
+
+/*
+ *     Functional forwards for expression utility routines
+ */
+struct exp     *combine();
+struct exp     *boolterm();
+struct exp     *term();
+struct exp     *factor();
+struct exp     *yukkyexpr();
+
+/*
+ *     The set definitions
+ */
+
+char   tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
+
+#define LINSTBEGIN     01      /*SEMI, NL, NAME*/
+#define        EBEGOPS         02      /*LP, MINUS, TILDE*/
+#define        YUKKYEXPRBEG    04      /*NAME, INSTn, INST0, REG, DOT*/
+#define        SAFEEXPRBEG     010     /*INT, FLTNUM*/
+#define ADDOPS         020     /*PLUS, MINUS*/
+#define        BOOLOPS         040     /*IOR, XOR, AND*/
+#define MULOPS         0100    /*LSH, RSH, MUL, DIV, TILDE*/
+
+#define        INTOKSET(val, set)      (tokensets[(val)] & (set) )
+
+#define expr(xp, val) { \
+       if ( (!INTOKSET(val, EBEGOPS)) && (!INTOKSET(peekahead, ADDOPS+BOOLOPS+MULOPS))) { \
+               if (INTOKSET(val, YUKKYEXPRBEG)) xp = yukkyexpr(val, yylval); \
+               else xp = (struct exp *) yylval; \
+               shift; \
+       } else { \
+               val = exprparse(val, ptrloc1xp); \
+               xp = loc1xp; \
+       } \
+    }
+
+/*
+ *     Registers can be either of the form r0...pc, or
+ *     of the form % <expression>
+ *     NOTE:   Reizers documentation on the assembler says that it
+ *     can be of the form r0 + <expression>.. That's not true.
+ *
+ *     NOTE:   Reizer's yacc grammar would seem to allow an expression
+ *     to be: (This is undocumented)
+ *             a)      a register
+ *             b)      an Instruction (INSTn or INST0)
+ */
+
+#define findreg(regno) \
+       if (val == REG) { \
+               regno = yylval; \
+               shift; \
+       } else \
+       if (val == REGOP) { \
+               shift;  /*over the REGOP*/ \
+               val = funnyreg(val, ptrregno); \
+       } \
+       else { ERROR ("register expected"); }
diff --git a/usr/src/cmd/as/asjxxx.c b/usr/src/cmd/as/asjxxx.c
new file mode 100644 (file)
index 0000000..ab12699
--- /dev/null
@@ -0,0 +1,448 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#include       <stdio.h>
+#include       "as.h"
+#include       "assyms.h"
+
+#define JBR 0x11
+#define BRW 0x31
+
+/*
+ *     The number of bytes to add if the jxxx must be "exploded"
+ *     into the long form
+ */
+#define        JBRFSIZE        1       /*goes to brw*/
+#define JXXXFSIZE      3       /*goes to brb, brw <byte> <byte> */
+
+/*
+ *     These variables are filled by asscan.c with the
+ *     last name encountered (a pointer buried in the intermediate file),
+ *     and the last jxxx symbol table entry encountered.
+ */
+struct         symtab  *lastnam;
+struct symtab  *lastjxxx;
+
+/*
+ *     Handle jxxx instructions
+ */
+ijxout(op,ap,nact)
+       struct arg *ap;
+{
+       if (passno == 1){
+               /*
+                *      READ THIS BEFORE LOOKING AT jxxxfix()
+                *
+                *      Record the jxxx in a special symbol table entry
+                */
+               register struct symtab *jumpfrom;
+
+               /*
+                *      We assume the MINIMAL length
+                */
+               putins(op,ap,nact); 
+               jumpfrom = lastjxxx;
+               jumpfrom->tag = JXACTIVE;
+               jumpfrom->jxbump = 0;
+               if (op == JBR)
+                       jumpfrom->jxfear = JBRFSIZE;
+               else
+                       jumpfrom->jxfear = JXXXFSIZE;
+#ifdef DJXXX
+               jumpfrom->jxline = lineno;
+#endif
+               if (lastnam == 0)
+                       yyerror("jxxx destination not a label");
+               jumpfrom->dest = lastnam;
+               jumpfrom->type = dotp->xtype;   /*only TEXT or DATA*/
+               jumpfrom->index = dotp-usedot;
+               /*
+                *      value ALWAYS (ALWAYS!!!) indexes the next instruction
+                *      after the jump, even in the jump must be exploded
+                *      (bumped)
+                */
+               jumpfrom->value = dotp->xvalue;
+               njxxx++;
+       } else {/* pass2, resolve */
+               /*
+                *      READ THIS AFTER LOOKING AT jxxxfix()
+                */
+               register long           oxvalue;
+               register struct exp     *xp; 
+               register struct symtab  *tunnel;
+               register struct arg     *aplast;
+
+               aplast = ap + nact - 1;
+               xp = aplast->xp;
+               if (lastjxxx->tag == JXTUNNEL){
+                       lastjxxx->tag = JXINACTIVE;
+                       tunnel = lastjxxx->dest;
+                       xp->xvalue = tunnel->value      /*index of instruction following*/
+                                   - 3                 /* size of brw + word*/
+                                   + ( ( (tunnel->jxfear == JBRFSIZE) &&
+                                         (tunnel->jxbump == 0))?1:0);
+                                                       /*non bumped branch byteis only 2 back*/
+               }
+               if (lastjxxx->jxbump == 0){     /*wasn't bumped, so is short form*/
+                       putins(op, ap, nact);
+               } else {
+                       if (op != JBR){ /*branch reverse conditional byte over 
+                                         branch unconditional word*/
+                               oxvalue = xp->xvalue;
+                               xp->xvalue = lastjxxx->value;
+                               putins(op^1, ap, nact);
+                               xp->xvalue = oxvalue;
+                       }
+                       putins(BRW, aplast, 1);
+               }
+       }
+}      /*end of ijxout*/
+
+jalign(xp, sp)
+       register struct exp *xp;
+       register struct symtab *sp;
+{
+       register        int     mask;
+       if (xp->xtype != XABS || xp->xvalue < 0 || xp->xvalue > 16) {
+               yyerror("Illegal `align' argument");
+               return;
+       }
+       flushfield(NBPW/4);
+       if (passno == 1) {
+               sp->tag = JXALIGN;
+               sp->jxfear = (1 << xp->xvalue) - 1;
+#ifdef DJXXX
+               sp->jxline = lineno;
+#endif
+               sp->type = dotp->xtype;
+               sp->index = dotp-usedot;
+               /*
+                *      We guess that the align will take up at least one
+                *      byte in the code output.  We will correct for this
+                *      initial high guess when we explode (bump) aligns
+                *      when we fix the jxxxes.  We must do this guess
+                *      so that the symbol table is sorted correctly
+                *      and labels declared to fall before the align
+                *      really get their, instead of guessing zero size
+                *      and have the label (incorrectly) fall after the jxxx.
+                *      This is a quirk of our requirement that indices into
+                *      the code stream point to the next byte following
+                *      the logical entry in the symbol table
+                */
+               dotp->xvalue += 1;
+               sp->value = dotp->xvalue;
+               njxxx++;
+       } else {
+               mask = (1 << xp->xvalue) - 1;
+               while (dotp->xvalue & mask){
+                       outb(0);
+               }
+       }
+}
+
+/*
+ *     Pass 1.5, resolve jxxx instructions and .align in .text
+ */
+jxxxfix() 
+{
+       register struct symtab  *jumpfrom;
+                struct symtab  **cojumpfrom, *ubjumpfrom;
+       register struct symtab  *dest;
+       register struct symtab  *intdest;       /*intermediate dest*/
+       register struct symtab  **cointdest, *ubintdest;
+
+       register struct symtab  *tunnel;
+                int            displ,nchange;
+                int            badjxalign;     /*if jump across an align*/
+                int            stillactives;   /*if still active jxxxes*/
+                int            segno;          /*current segment number*/
+                int            topono;         /*which iteration in the topo sort*/
+       register unsigned char  tag;
+       /*
+        *      consider each segment in turn...
+        */
+       for (segno = 0; segno < NLOC + NLOC; segno++){
+           badjxalign = 0;             /*done on a per segment basis*/
+           /*
+            *  Do a lazy topological sort.
+            */
+           for (topono = 1, nchange = 1; nchange != 0; topono++){
+#ifdef DEBUG
+               if (debug)
+                       printf("\nSegment %d, topo iteration %d\n",
+                               segno, topono);
+#endif
+               nchange = 0;
+               stillactives = 0;
+               /*
+                *      We keep track of one possible tunnel location.
+                *      A tunnel will eventually be an unconditional
+                *      branch to the same place that another jxxx
+                *      will want to branch to.  We will turn a
+                *      branch conditional/unconditional (word) that would
+                *      have to get bumped because its destination is too
+                *      far away, into a branch conditional/unconditional
+                *      byte to the tunnel branch conditional/unconditional.
+                *      Of course, the tunnel must branch to the same place
+                *      as we want to go.
+                */
+               tunnel = 0;     /*initially, no tunnel*/
+               SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom, ubjumpfrom, ++){
+                       tag = jumpfrom->tag;
+                       if (tag <= IGNOREBOUND)
+                               continue;       /*just an ordinary symbol*/
+                       if (tag == JXALIGN){
+                               tunnel = 0;     /*avoid tunneling across a flex alocation*/
+                               continue;       /*we take care of these later*/
+                       }
+                       if (   jumpfrom->jxfear == JBRFSIZE     /*unconditional*/
+                           || (   tag == JXINACTIVE            /*inactive bumped*/
+                               && (jumpfrom->jxbump != 0)
+                              )
+                          ) tunnel = jumpfrom;
+                       if (tag != JXACTIVE)
+                               continue;
+                       dest = jumpfrom->dest;
+                       if (jumpfrom->index != dest->index){
+                               yyerror("Intersegment jxxx");
+                               continue;
+                       }
+                       displ = dest->value - jumpfrom->value;
+                       if (displ < MINBYTE || displ > MAXBYTE) {
+                               /*
+                                *      This is an immediate lose!
+                                *
+                                *      We first attempt to tunnel
+                                *      by finding an intervening jump that
+                                *      has  the same destination.
+                                *      The tunnel is always the first preceeding
+                                *      jxxx instruction, so the displacement
+                                *      to the tunnel is less than zero, and
+                                *      its relative position will be unaffected
+                                *      by future jxxx expansions.
+                                */
+                               if (    (jumpfrom->jxfear > JBRFSIZE)
+                                    && (tunnel) 
+                                    && (tunnel->dest == jumpfrom->dest)        
+                                    && (tunnel->index == jumpfrom->index)
+                                    && (tunnel->value - jumpfrom->value >=
+                                               MINBYTE + JXXXFSIZE)
+                                  ) {
+                                               /*
+                                                *      tunnelling is OK
+                                                */
+                                               jumpfrom->dest = tunnel;
+                                               /*
+                                                * no bumping needed, this
+                                                * is now effectively inactive
+                                                * but must be remembered
+                                                */
+                                               jumpfrom->tag = JXTUNNEL;
+#ifdef DEBUG
+                                               if(debug)
+                                               printf("Tunnel from %s from line %d\n",
+                                                       jumpfrom->name, lineno);
+#endif
+#ifdef METRIC
+                                               jxxxtunnel++;
+#endif
+                                               continue;
+                               } else {        /*tunneling not possible*/
+                                       /*
+                                        *      since this will be turned
+                                        *      into a bumped jump, we can
+                                        *      use the unconditional jump
+                                        *      as a tunnel
+                                        */
+                                       tunnel = jumpfrom;
+                                       jumpfrom->tag = JXNOTYET;
+                                       ++nchange;
+                                       continue;
+                               }
+                       }       /*end of immediate lose*/
+                       /*
+                        *      Do a forward search for an intervening jxxx
+                        */
+                       if (displ >= 0) {
+                               SEGITERATE(segno, cojumpfrom + 1,0,cointdest,
+                                               intdest, ubintdest, ++){
+                                       if (intdest->value > dest->value) 
+                                               break; /* beyond destination */
+                                       if (intdest->tag <= JXQUESTIONABLE)
+                                               continue;       /*frozen solid*/
+                                       if (intdest->tag == JXALIGN){
+                                               jumpfrom->jxoveralign = 1;
+                                               badjxalign++;
+                                       }
+                                       /*
+                                        *      we assume the worst case
+                                        *      for unfrozen jxxxxes
+                                        */
+                                       displ += intdest->jxfear;
+                               }
+                               if (displ <= MAXBYTE){
+                                       /*
+                                        *      the worst possible conditions
+                                        *      can't hurt us, so forget about
+                                        *      this jump
+                                        */
+                                       jumpfrom->tag = JXINACTIVE;
+                               } else {
+                                       stillactives++;
+                               }
+                       } else {
+                       /*
+                        *      backward search for intervening jxxx
+                        */
+                               SEGITERATE(segno, cojumpfrom - 1,1,cointdest,
+                                 intdest, ubintdest, --){
+                                       if (intdest->value <= dest->value) 
+                                               break; /* beyond destination */
+                                       if (intdest->tag <= JXQUESTIONABLE)
+                                               continue;       /*frozen solid*/
+                                       if (intdest->tag == JXALIGN){
+                                               jumpfrom->jxoveralign = 1;
+                                               badjxalign++;
+                                       }
+                                       displ -= intdest->jxfear; 
+                               }
+                               if (displ >= MINBYTE) {
+                                       jumpfrom->tag = JXINACTIVE;
+                               } else {
+                                       stillactives++;
+                               }
+                       }       /*end of backwards search*/
+               }       /*end of iterating through all symbols in this seg*/
+
+               if (nchange == 0) {
+                       /*
+                        *      Now, if there are still active jxxx entries,
+                        *      we are partially deadlocked.  We can leave
+                        *      these jxxx entries in their assumed short jump
+                        *      form, as all initial displacement calcualtions
+                        *      are hanging on unresolved jxxx instructions
+                        *      that might explode into a long form, causing
+                        *      other jxxxes jumping across the first set of
+                        *      jxxxes to explode, etc.
+                        *      However, if a jxxx jumps across a .align,
+                        *      we assume the worst for the deadlock cycle,
+                        *      and resolve all of them towards the long
+                        *      jump.
+                        *      Currently, the C compiler does not produce
+                        *      jumps across aligns, as aligns are only used
+                        *      in data segments, or in text segments to align
+                        *      functions.
+                        */
+                       if (stillactives){
+#ifdef METRIC
+                               jxdeadlock++;
+#endif
+                               SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom,
+                                   ubjumpfrom, ++){
+                                       if (jumpfrom->tag == JXACTIVE){
+                                               jumpfrom->tag =
+                                                 badjxalign?JXNOTYET:JXINACTIVE;
+                                       }
+                               }
+                               if (badjxalign){
+                                       jxxxbump(segno, 0);
+#ifdef METRIC
+                                       nbadjxsegs++;
+#endif
+                               }
+                       }
+                       /*
+                        *      Handle  all of the .align s
+                        */
+                       SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom,
+                          ubjumpfrom, ++){
+                           if (jumpfrom->tag == JXALIGN){
+                               /*
+                                *      Predict the true displacement
+                                *      needed, irregardless of the
+                                *      fact that we guessed 1
+                                */
+                               displ = (jumpfrom->value - 1) & (unsigned)jumpfrom->jxfear;
+                               if (displ == 0){        /*no virtual displacement*/
+                                       jumpfrom->jxfear = -1;
+                               } else {
+                                       jumpfrom->jxfear = (jumpfrom->jxfear + 1) - displ;
+                                       /*
+                                        *      assert jumpfrom->jxfear > 0
+                                        */
+                                       if (jumpfrom->jxfear == 1){
+                                               /*our prediction was correct*/
+                                               continue;
+                                       }
+                                       /*
+                                        *      assert jumpfrom->jxfear > 1
+                                        */
+                                       jumpfrom->jxfear -= 1;  /*correct guess*/
+                               }
+                               /*
+                                *      assert jumpfrom->jxfear = -1, +1...2**n-1
+                                */
+                               jumpfrom->tag = JXNOTYET;       /*signal*/
+                               jxxxbump(segno, cojumpfrom);
+                               jumpfrom->tag = JXINACTIVE;
+                               /*
+                                *      Assert jxfrom->jxvalue indexes the first
+                                *      code byte after the added bytes, and
+                                *      has n low order zeroes.
+                                */
+                         }
+                       }       /*end of walking through each segment*/
+               }       /*end of no changes */
+               else {  /*changes, and still have to try another pass*/
+                       jxxxbump(segno, 0);
+               }
+          }    /*end of doing the topologic sort*/
+       }       /*end of iterating through all segments*/
+}      /*end of jxxxfix*/
+
+/*
+ *     Go through the symbols in a given segment number,
+ *     and see which entries are jxxx entries that have
+ *     been logically "exploded" (expanded), but for which
+ *     the value of textually following symbols has not been
+ *     increased
+ */
+
+jxxxbump(segno, starthint)
+       int     segno;
+       struct  symtab **starthint;
+{
+       register        struct  symtab  **cosp, *sp;
+       register        struct  symtab          *ub;
+       register        int     cum_bump;
+       register        unsigned        char    tag;
+
+#ifdef METRIC
+       jxxxiterate++;
+#endif
+       cum_bump = 0;
+       SEGITERATE(segno, starthint, 0, cosp, sp, ub, ++){
+               tag = sp->tag;
+               if (tag == JXNOTYET){
+#ifdef DEBUG
+                       if (debug){
+                       if (sp->dest != 0)
+                               printf("Explode jump to %s on line %d\n",
+                                       sp->dest->name, lineno);
+                       else
+                               printf("Explode an align!\n");
+                       }
+#endif
+                       sp->tag = JXINACTIVE;
+                       sp->jxbump = 1;
+                       cum_bump += sp->jxfear;
+               }
+               /*
+                *      Only bump labels and jxxxes. Ignored entries can
+                *      be incremented, as they are thrown away later on.
+                *      Stabds are given their final value in the second 
+                *      pass.
+                */
+               if (tag >= OKTOBUMP)    /*only bump labels and jxxxes and floating stabs*/
+                       sp->value += cum_bump;
+       }
+       usedot[segno].xvalue += cum_bump;
+}
diff --git a/usr/src/cmd/as/asmain.c b/usr/src/cmd/as/asmain.c
new file mode 100644 (file)
index 0000000..ed03351
--- /dev/null
@@ -0,0 +1,485 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#include <stdio.h>
+#include <signal.h>
+
+#include "as.h"
+#include "assyms.h"
+#include "asexpr.h"
+#include "asscan.h"
+
+int    curlen;
+/*
+ *     variables to manage the assembly input
+ */
+char   *dotsname;      /*the current file name; managed by the parser*/
+int    lineno;         /*current line number; managed by the parser*/
+int    silent;         /*don't complain about any errors*/
+int    savelabels;     /*write the labels to the a.out file*/
+
+#ifdef DEBUG
+int    debug;
+int    toktrace;
+#endif
+
+long   datbase;
+
+char   *endcore;               /*where to get more symbol space*/
+
+struct hdr hdr = {
+       0410, 0, 0, 0, 0, 0, 0, 0,
+};
+
+#ifndef vax
+struct {short hiword; short loword;}; /* stupid fp-11 */
+#else
+#define writel(p,n,f) fwrite( (long) p, sizeof (long), n, f)
+#endif
+
+char           *tmpn1;
+char           *tmpn2;
+char           *tmpn3;
+
+struct exp     usedot[NLOC+NLOC];
+
+FILE           *usefile[NLOC+NLOC];
+FILE           *rusefile[NLOC+NLOC];
+char           sibuf[TOKBUFLG];                /*buffer used for all input*/
+char           sobuf[TOKBUFLG];                /*buffer used for all output*/
+                                               /*except stdout and relfil*/
+char           stdoutbuf[BUFSIZ];              /*stdout buffer*/
+
+extern int     njxxx;          /*number of jumpxxx  instructs*/
+extern int     d124;           /*allocate 1,2 or 4 bytes for unknowns*/
+
+int delexit();
+
+char           *innames[32];   /*names of the files being assembled*/
+int            ninfiles;       /*how many interesting files there are*/
+
+main(argc, argv)
+       int     argc;
+       char    **argv;
+{
+       int             locindex;
+       long            v;
+       char            *outfile = "a.out";
+       int             filestep;
+       char            *cp;
+
+       setbuf(stdout, stdoutbuf);
+       ninfiles = 0;
+       silent = 0;
+       useVM = 0;
+#ifdef DEBUG
+       debug = 0;
+#endif
+       /*
+        *      Give the error processor something to complain about
+        *      if there is an error processing an argument
+        */
+       dotsname = "<argv error>";
+       while (argc > 1) {
+               if (argv[1][0] == '-'){
+                       cp = argv[1] + 1;
+                       /*
+                        *      We can throw away single minus signs, so
+                        *      that make scripts for the PDP 11 assembler work
+                        *      on this assembler too
+                        */
+                       while (*cp){    
+                               switch(*cp++){
+                                default:
+                                       yyerror("Unknown flag: %c", *--cp);
+                                       cp++;
+                                       break;
+                                case 'd':
+                                       d124 = *cp++ - '0';
+                                       if ( (d124 != 1) && (d124 != 2) && 
+                                            (d124 != 4)){
+                                               yyerror("-d[124] only");
+                                               exit(1);
+                                       }
+                                       break;
+                                case 'o':
+                                       if (argc < 3){
+                                               yyerror("-o what???");
+                                               exit(1);
+                                       }
+                                       outfile = argv[2];
+                                       argc -= 2;
+                                       argv += 2;
+                                       goto nextarg;
+
+                                case 'V':
+                                       useVM = 1;
+                                       break;
+#ifdef fooiearg
+                                case 'M':
+                                       if (argc < 3){
+                                               yyerror("Mode what?");
+                                               exit(1);
+                                       }
+                                       hdr.magic = 0;
+                                       cp = argv[2];
+                                       while (*cp && ('0' <= *cp) && (*cp <= '7'))
+                                               hdr.magic = hdr.magic<<3 + *cp++ - '0';
+                                       argc -= 2;
+                                       argv += 2;
+                                       goto nextarg;
+                                case 'W':      silent = 1;
+                                       break;
+#endif
+
+#ifdef DEBUG
+                                case 'D':      debug = 1;
+                                       break;
+                                case 'T':      toktrace = 1;
+                                       break;
+#endif
+#ifdef METRIC
+                                case 'C':      outcounters = 1;
+                                       break;
+#endif
+                                case 'L':      savelabels = 1;
+                                       break;
+                               }       /*end of the switch*/
+                       }       /*end of pulling out all arguments*/
+               }       /*end of a flag argument*/
+               else {  /*file name*/
+                       if (ninfiles > 32){
+                               yyerror("More than 32 file names");
+                               exit(3);
+                       }
+                       innames[ninfiles++] = argv[1];
+               }
+               --argc; ++argv;
+          nextarg:;
+       }       /*end of looking at all of the arguments*/
+                                
+       if (anyerrs)
+               exit(1);
+
+       endcore = (char *)sbrk(0);
+
+       /*
+        *      Install symbols in the table
+        */
+       symtabinit();
+       syminstall();
+       /*
+        *      mark usedot: first NLOC slots for named text segments,
+        *      the next for named data segments.
+        */
+       for (locindex=0; locindex<NLOC; locindex++) {
+               usedot[locindex].xtype = XTEXT;
+               usedot[locindex+NLOC].xtype = XDATA;
+       }
+
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, delexit);
+
+       tmpn1 = (char *)mktemp("/tmp/asXXXXX");
+       tmpfil = fopen(tmpn1, "w");
+       if (tmpfil==NULL) {
+               yyerror("Bad pass 1 temporary file for writing %s", tmpn1);
+               delexit();
+       }
+       setbuf(tmpfil,sobuf);
+
+       inittmpfile();
+       buildtokensets();               /*sets to implement expression lookahead*/
+
+       if (ninfiles == 0){             /*take the input from stdin directly*/
+               setbuf(stdin, sibuf);
+               lineno = 1;
+               dotsname = "<stdin>";
+
+               yyparse();
+       } else {                /*we have the names tanked*/
+               for (filestep = 0; filestep < ninfiles; filestep++){
+                       new_dot_s(innames[filestep]);
+                       if (freopen(innames[filestep], "r", stdin) == NULL) {
+                               yyerror( "Can't open source file %s\n",
+                                       innames[filestep]);
+                               exit(2);
+                       }
+                       setbuf(stdin,sibuf);
+
+                       yyparse();
+               }
+       }
+
+       closetmpfile();         /*kick out the last buffered intermediate text*/
+
+       if (anyerrs)
+               delexit();
+
+       /*
+        *      Pass 1.5
+        */
+       sortsymtab();
+
+#ifdef DEBUG
+       if (debug)
+               dumpsymtab();
+#endif
+
+       jxxxfix();
+
+#ifdef DEBUG
+       if (debug)
+               dumpsymtab();
+#endif
+
+#ifdef METRIC
+       lgtmpfile = ftell(tmpfil);
+#endif
+
+       fclose(tmpfil);
+       tmpfil = fopen(tmpn1, "r");
+       if (tmpfil==NULL) {
+               yyerror("Bad pass 2 temporary file for reading %s", tmpn1);
+               delexit();
+       }
+       setbuf(tmpfil,sibuf);
+
+       /*
+        *      round and assign text segment origins 
+        */
+       tsize = 0;
+       for (locindex=0; locindex<NLOC; locindex++) {
+               v = round(usedot[locindex].xvalue, FW);
+               usedot[locindex].xvalue = tsize;
+               tsize += v;
+       }
+       /*
+        *      round and assign data segment origins 
+        */
+       datbase = round(tsize, PAGRND);
+       for (locindex=0; locindex<NLOC; locindex++) {
+               v = round(usedot[NLOC+locindex].xvalue, FW);
+               usedot[NLOC+locindex].xvalue = datbase+dsize;
+               dsize += v;
+       }
+
+       hdr.bsize = dsize;
+
+       /*
+        *      Assign final values to symbols
+        */
+       freezesymtab();
+       stabfix();
+
+       hdr.bsize -= dsize;
+
+       txtfil = fopen(outfile, "w");
+       if (txtfil==NULL) {
+               yyerror("Cannot create %s", outfile);
+               delexit();
+       }
+       setbuf(txtfil,sobuf);
+
+       usefile[0] = txtfil;
+
+       tmpn2 = (char *)mktemp("/tmp/aaatXXXXX");
+       tmpn3 = (char *)mktemp("/tmp/abatXXXXX");
+
+       relfil = fopen(tmpn3, "w");
+       if (relfil==NULL) {
+               yyerror("Bad temp file for writing extra text segments %s", tmpn3);
+               delexit();
+       }
+       rusefile[0] = relfil;
+
+       hdr.tsize = tsize;
+       hdr.dsize = dsize;
+       hdr.ssize = sizesymtab();
+       /*
+        *      hdr.trsize, hdr.drsize set by outrel 
+        */
+
+       /* *************** PASS 2 **************** */
+
+       writel(&hdr,8,txtfil);
+       tsize = 0;
+       dsize = 0;
+       lineno = 1;
+       dotp = &usedot[0];
+#ifdef DEBUG
+       if (debug)
+               printf("\n\n\n\t\tPASS 2\n\n\n\n");
+#endif
+       passno = 2;
+       inittmpfile();
+
+       yyparse();
+
+       closetmpfile();
+
+       /*
+        *      round csects to FW 
+        */
+       for (locindex=0; locindex<NLOC; locindex++) {
+               if (usefile[locindex]) {
+                       txtfil=usefile[locindex];
+                       dotp= &usedot[locindex];
+                       while (usedot[locindex].xvalue & FW)
+                               outb(0);
+                       if (locindex>0)
+                               fclose(usefile[locindex]);
+                       fclose(rusefile[locindex]);
+               }
+               if (usefile[NLOC+locindex]) {
+                       txtfil = usefile[NLOC+locindex]; 
+                       dotp= &usedot[locindex+NLOC];
+                       relfil = rusefile[NLOC+locindex];
+                       while (usedot[locindex+NLOC].xvalue & FW)
+                               outb(0);
+                       fclose(txtfil);
+                       fclose(relfil);
+               }
+       }
+
+       txtfil = usefile[0];
+       /*
+        *      append csect text onto text for csect 0 
+        */
+       for (locindex=1; locindex<NLOC+NLOC; locindex++) {
+               char    buffer[BUFSIZ];
+               if (usefile[locindex]) {
+                       tmpn2[TMPC] = locindex+'a';
+                       relfil = fopen(tmpn2, "r");
+                       if (relfil==NULL) {
+                               yyerror("cannot reopen temp");
+                               continue;
+                       }
+                       while (!feof(relfil))
+                               fwrite(buffer, 1,
+                                       fread(buffer, 1, BUFSIZ, relfil),
+                                       txtfil);
+                       fclose(relfil);
+               }
+       }
+       /*
+        *      append relocation info onto text 
+        */
+       for (locindex=0; locindex<NLOC+NLOC; locindex++) {
+               char    buffer[BUFSIZ];
+               if (rusefile[locindex]) {
+                       tmpn3[TMPC] = locindex+'a';
+                       relfil = fopen(tmpn3, "r");
+                       if (relfil==NULL) {
+                               yyerror("cannot reopen temp");
+                               continue;
+                       }
+                       while (!feof(relfil))
+                               fwrite(buffer, 1, 
+                                      fread(buffer, 1, BUFSIZ, relfil),
+                                      txtfil);
+                       fclose(relfil);
+               }
+       }
+
+       symwrite(txtfil);
+       /*
+        *      Go back and patch up rsize
+        */
+       fseek(txtfil,0L,0);
+       writel(&hdr,8,txtfil);
+
+       delete();
+
+       if (anyerrs==0 && orgwarn)
+               yyerror("Caution: absolute origins.\n");
+#ifdef METRIC
+       pcounters();
+#endif
+       exit(anyerrs!=0);
+}      /*end of main*/
+
+
+delexit()
+{
+       delete();
+#ifdef METRIC
+       pcounters();
+#endif
+       exit(1);
+}
+
+sawabort()
+{
+       char    buffer[BUFSIZ];
+#ifdef METRIC
+       pcounters();
+#endif
+       while (!feof(stdin))
+               fread(buffer, 1, BUFSIZ, stdin);
+       delete();
+       exit(1);        /*although the previous pass will also exit non zero*/
+}
+
+delete()
+{
+       register locindex;
+
+       if (tmpn1)
+               unlink(tmpn1);
+       for (locindex=0; locindex<NLOC+NLOC; locindex++) {
+               if (tmpn2) {
+                       tmpn2[TMPC] = locindex+'a';
+                       unlink(tmpn2);
+               }
+               if (tmpn3) {
+                       tmpn3[TMPC] = locindex+'a';
+                       unlink(tmpn3);
+               }
+       }
+}
+#ifdef METRIC
+pcounters()
+{
+       int     i;
+       struct {
+               long    p_user;
+               long    p_sys;
+               long    c_user;
+               long    c_sys;
+       } tbuffer;
+
+       if (!outcounters) return;
+       printf("Assembly of files: ");
+       if (innames[0] == 0)
+               printf("<Standard Input.>\n");
+       else {
+               for (i = 0; i<ninfiles; i++)
+                       printf("%s ", innames[i]);
+               printf("\n");
+       }
+       if (useVM)
+               printf("Using ");
+       else
+               printf("NOT using ");
+       printf("Virtual Memory for the interpass temporary file.\n");
+       printf("%d hashing collsions\n", nhcollisions);
+       printf("%d hash table accesses\n", nhashed);
+       printf("%d values entered in the hash table\n", nentered);
+       printf("%d byte length of the temporary file\n", lgtmpfile);
+       printf("%d symbols in the symbol table\n", nsyms);
+       printf("%d labels in the symbol table\n", nlabels);
+       printf("%d forgotten symbols\n", nforgotten);
+       printf("%d iterations through all symbols to remove jxxxes\n",
+                       jxxxiterate);
+       printf("%d jumps resolved via tunnelling\n", jxxxtunnel);
+       if (jxdeadlock)
+               printf("%d DEADLOCKED JXXXentries: Resolved by %s jumping\n",
+                       jxdeadlock, nbadjxsegs == 0 ? "short" : "long");
+       if (nbadjxsegs)
+               printf("%d Segments with jxxx over aligns.\n",
+                       nbadjxsegs);
+       times(&tbuffer);
+       printf("%1.2fu 1.2fs\n",
+               ((float)tbuffer.p_user)/60.0,
+               ((float)tbuffer.p_sys)/60.0);
+}
+#endif
diff --git a/usr/src/cmd/as/asparse.c b/usr/src/cmd/as/asparse.c
new file mode 100644 (file)
index 0000000..18f0804
--- /dev/null
@@ -0,0 +1,944 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#include <stdio.h>
+#include <a.out.h>
+#include "as.h"
+#include "asexpr.h"
+#include "asscan.h"
+#include "assyms.h"
+
+extern struct  exp     usedot[];/*information on the dot for each seg*/
+struct exp     *dotp = &usedot[0];     /*current dot*/
+int    anyerrs;
+
+int    passno  = 1;
+
+FILE   *tmpfil;
+FILE   *relfil;                /*relocation info sent here*/
+FILE   *txtfil;                /*text (for any text #) sent here*/
+
+int    hshused;                /*hash slots consumed */
+long   tsize;
+long   dsize;
+
+long   bitfield;
+int    bitoff;
+
+/*
+ *     The following three variables are communication between various
+ *     modules to special case a number of things.  They are properly
+ *     categorized as hacks.
+ */
+struct symtab *lastnam;        /*last name seen by the lexical analyzer*/
+int    exprisname;             /*last factor in an expression was a name*/
+int    droppedLP;              /*one is analyzing an expression beginning with*/
+                               /*a left parenthesis, which has already been*/
+                               /*shifted. (Used to parse (<expr>)(rn)*/
+
+char   yytext[NCPS+2];
+static char    Dotsname[32];
+
+struct exp     *xp;            /*next free expression slot, used by expr.c*/
+
+int    yylval;                 /*the lexical value; sloppy typing*/
+
+extern         ptrall tokptr;  /*points to current token being eaten*/
+extern int     d124;
+
+int    yyparse()
+{
+       register        struct  exp     *locxp;
+                       /*
+                        *      loc1xp and ptrloc1xp are used in the
+                        *      expression lookahead
+                        */
+                       struct  exp     *loc1xp;        /*must be non register*/
+                       struct  exp     **ptrloc1xp = & loc1xp;
+                       struct  exp     *pval;          /*hacking expr:expr*/
+
+       register        struct  symtab  *np;
+       register        int             argcnt;
+
+       register        int             val;            /*what yylex gives*/
+       register        int             auxval;         /*saves val*/
+
+       register        struct  arg     *ap;            /*first free argument*/
+
+                       struct  symtab  *p;
+       register        struct  symtab  *stpt;
+
+                       struct  strdesc *stringp;       /*handles string lists*/
+
+                       int             regno;          /*handles arguments*/
+                       int             *ptrregno = &regno;
+                       int             sawmul;         /*saw * */
+                       int             sawindex;       /*saw [rn]*/
+                       int             sawsize;
+                       int             seg_type;       /*the kind of segment: data or text*/
+                       int             seg_number;     /*the segment number*/
+                       long            space_value;    /*how much .space needs*/
+
+                       int             field_width;    /*how wide a field is to be*/
+                       int             field_value;    /*the value to stuff in a field*/
+                       char            *stabname;      /*name of stab dealing with*/
+                       ptrall          stabstart;      /*where the stab starts in the buffer*/
+
+       xp = explist;
+       ap = arglist;
+
+       val = yylex();
+       while (val != PARSEEOF){
+               while (INTOKSET(val, LINSTBEGIN)){
+                       if (val == NL){
+                               lineno++;
+                               shift;
+                       } else
+                       if (val == SEMI) 
+                               shift;
+                       else {  /*its a name, so we have a label (hopefully*/
+                               if (val != NAME){
+                                       ERROR("Name expected for a label");
+                               }
+                               np = (struct symtab *)yylval;
+                               shiftover(NAME);
+                               shiftover(COLON);
+                               flushfield(NBPW/4);
+                               if ((np->type&XTYPE)!=XUNDEF) {
+                                       if(  (np->type&XTYPE)!=dotp->xtype 
+                                          || np->value!=dotp->xvalue
+                                          || (  (passno==1)
+                                              &&(np->index != dotp->xloc)
+                                             )
+                                         ){
+#ifndef DEBUG
+                                               if (np->name[0] != 'L')
+#endif
+                                               {
+                                                       yyerror("%.8s redefined", np->name);
+#ifdef DEBUG
+                                                       printf("name.value=%d, dotp->xvalue=%d\n",
+                                                       np->value, dotp->xvalue);
+#endif
+                                               }
+                                       }
+                               }
+                               np->type &= ~(XTYPE|XFORW);
+                               np->type |= dotp->xtype;
+                               np->value = dotp->xvalue;
+                               if (passno == 1){
+                                       np->index = dotp-usedot;
+                                       if (np->name[0] == 'L'){
+                                               nlabels++;
+                                       }
+                                       np->tag = LABELID;
+                               }
+                       }       /*end of this being a label*/
+               }       /*end of to consuming all labels, NLs and SEMIS */ 
+
+               xp = explist;
+               ap = arglist;
+
+               /*
+                *      process the INSTRUCTION body
+                */
+           switch(val){
+               default:
+                       ERROR("Unrecognized instruction or directive");
+
+               case IABORT:
+                       shift;
+                       sawabort();
+                       /*NOTREACHED*/
+                       break;
+
+               case PARSEEOF:
+                       tokptr -= sizeof(toktype);
+                       *tokptr++ = VOID;
+                       tokptr[1] = VOID;
+                       tokptr[2] = PARSEEOF;
+                       break;
+               
+               case IFILE:
+                       shift;
+                       stringp = (struct strdesc *)yylval;
+                       shiftover(STRING);
+                       dotsname = &Dotsname[0];
+                       movestr(dotsname, stringp->str,
+                               stringp->str_lg >= 32? 32 :stringp->str_lg);
+                       dotsname[stringp->str_lg] = '\0';
+#ifdef DEBUG
+                       if (debug)
+                               printf("(from parser) Now considered to be in file %s\n",
+                                       dotsname);
+#endif
+                       break;
+               
+               case ILINENO:
+                       shift;          /*over the ILINENO*/
+                       expr(locxp, val);
+                       lineno = locxp->xvalue;
+#ifdef DEBUG
+                       if (debug)
+                               printf("Now considered to be on line number %d\n",
+                               lineno);
+#endif
+                       break;
+
+               case ISET: {    /* .set  <name> , <expr> */
+                       shift;
+                       np = (struct symtab *)yylval;
+                       shiftover(NAME);
+                       shiftover(CM);
+                       expr(locxp, val);
+                       np->type &= (XXTRN|XFORW);
+                       np->type |= locxp->xtype&(XTYPE|XFORW);
+                       np->value = locxp->xvalue;
+                       if (passno==1)
+                               np->index = locxp->xloc;
+                       if ((locxp->xtype&XTYPE) == XUNDEF)
+                               yyerror("Illegal set?");
+                       break;
+               }       /*end of case ISET*/
+
+               case ILSYM: {   /*.lsym name , expr */
+                       shift;
+                       np = (struct symtab *)yylval;
+                       shiftover(NAME);
+                       shiftover(CM);
+                       expr(locxp, val);
+                       /*
+                        *      Build the unique occurance of the
+                        *      symbol.
+                        *      The character scanner will have
+                        *      already entered it into the symbol
+                        *      table, but we should remove it
+                        */
+                       if (passno == 1){
+                               stpt = (struct symtab *)symalloc();
+                               movestr(stpt->name, np->name, NCPS);
+                               np->tag = OBSOLETE;     /*invalidate original */
+                               nforgotten++;
+                               np = stpt;
+                               if (locxp->xtype != XABS) 
+                                       ("Illegal lsym");
+                               np->value=locxp->xvalue;
+                               np->type=XABS;
+                               np->tag = ILSYM;
+                       }
+                       break;
+               }       /*end of case ILSYM*/
+
+               case IGLOBAL: { /*.globl <name> */
+                       shift;
+                       np = (struct symtab *)yylval;
+                       shiftover(NAME);
+                       np->type |= XXTRN;
+                       break;
+               }       /*end of case IGLOBAL*/
+
+               case IDATA:     /*.data [ <expr> ] */
+               case ITEXT: {   /*.text [ <expr> ] */
+                       seg_type = -val;
+                       shift;
+                       if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
+                               expr(locxp, val);
+                               seg_type = -seg_type;   /*now, it is positive*/
+                       }
+
+                       if (seg_type < 0) {     /*there wasn't an associated expr*/
+                               seg_number = 0;
+                               seg_type = -seg_type;
+                       } else {
+                               if (locxp->xtype != XABS || (seg_number=locxp->xvalue) >= NLOC) {
+                                       yyerror("illegal location counter");
+                                       seg_number = 0;
+                               }
+                       }
+                       if (seg_type == IDATA)
+                               seg_number += NLOC;
+                       flushfield(NBPW/4);
+                       dotp = &usedot[seg_number];
+                       if (passno==2) {        /* go salt away in pass 2*/
+                               if (usefile[seg_number] == NULL) {
+                                       tmpn2[TMPC] = 'a'+seg_number;
+                                       if ((usefile[seg_number] =
+                                          fopen(tmpn2, "w"))==NULL) {
+                                               yyerror("cannot create temp %s", tmpn2);
+                                               delexit();
+                                       }
+
+                                       tmpn3[TMPC] = 'a'+seg_number;
+                                       if ((rusefile[seg_number] =
+                                          fopen(tmpn3, "w"))==NULL) {
+
+                                               yyerror("cannot create temp %s",
+                                                  tmpn3);
+                                       }
+                               }
+                               txtfil = usefile[seg_number];
+                               relfil = rusefile[seg_number];
+                       }
+
+                       break;
+               }       /*end of case .TEXT and .DATA*/
+
+               /*
+                *      Storage filler directives:
+                *
+                *      .byte   [<exprlist>]
+                *
+                *      exprlist:  empty | exprlist outexpr
+                *      outexpr:   <expr> | <expr> : <expr>
+                */
+               case IBYTE:     curlen = NBPW/4; goto elist;
+
+               case IINT:
+               case ILONG:     curlen = NBPW;   goto elist;
+
+               case IWORD: {   
+                       curlen = NBPW/2;
+                  elist:
+                       seg_type = val;
+                       shift;
+
+                       /*
+                        *      This processes an expression list 
+                        */
+                       if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
+                               do{
+                                       /*
+                                        *      expression list consists of a list of :
+                                        *      <expr>
+                                        *      <expr> : <expr> 
+                                        *              (pack expr2 into expr1 bits
+                                        */
+                                       expr(locxp, val);
+                                       /*
+                                        *      now, pointing at the next token
+                                        */
+                                       if (val == COLON){
+                                               shiftover(COLON);
+                                               expr(pval, val);
+                                               if (locxp->xtype != XABS)
+                                                 yyerror("Width not absolute");
+                                               field_width = locxp->xvalue;
+                                               locxp = pval;
+                                               if (bitoff + field_width >
+                                                 curlen)
+                                                       flushfield(curlen);
+                                               if (field_width > curlen)
+                                                       yyerror("Expression crosses field boundary");
+                                       } /*value being colon*/
+                                       else {
+                                               field_width = curlen;
+                                               flushfield(curlen);
+                                       }
+
+                                        if ((locxp->xtype&XTYPE)!=XABS) {
+                                               if (bitoff)
+                                                       yyerror("Illegal relocation in field");
+                                               field_width=LEN1+!PCREL;
+                                               if (curlen==NBPW)
+                                                       field_width = LEN4 + !PCREL;
+                                               if (curlen==NBPW/2)
+                                                       field_width = LEN2 + !PCREL;
+                                               /*
+                                                *      Save relocation information for this non absolute
+                                                *      symbol:
+                                                *      pass 1: saves enough space for the value, and
+                                                *              fixes dotp.
+                                                *      pass 2: writes the address info in ld compatable
+                                                *              format onto one of the relfiles
+                                                */
+                                               outrel(&locxp->xvalue,
+                                                       field_width,
+                                                       locxp->xtype,
+                                                       locxp->xname);
+                                       } else {
+                                               field_value = locxp->xvalue & ( (1L << field_width)-1);
+                                               bitfield |= field_value << bitoff;
+                                               bitoff += field_width;
+                                       }
+                                       if ( auxval = (val == CM)) shift;
+                               } while (auxval);
+                       }       /*existed an expression  at all*/
+
+                       flushfield(curlen);
+                       if ( ( curlen == NBPW/4) && bitoff)
+                               dotp->xvalue ++;
+                       break;
+               }       /*end of case IBYTE, IWORD, ILONG, IINT*/
+               
+               case ISPACE: {  /* .space <expr> */
+                       shift;
+                       expr(locxp, val);
+                       if (locxp->xtype != XABS)
+                               yyerror("Space size not absolute");
+                       space_value = locxp->xvalue;
+                 ospace:
+                       flushfield(NBPW/4);
+                       while (space_value > 96){
+                               outs(strbuf[2].str, 96);
+                               space_value -= 96;
+                       }
+                       outs(strbuf[2].str, space_value);
+                       break;
+               }       /*end of case ISPACE*/
+               
+               case IASCII:    /* .ascii [ <stringlist> ] */
+               case IASCIZ: {  /* .asciz [ <stringlist> ] */
+                       auxval = val;
+                       shift;
+
+                       /*
+                        *      Code to consume a string list
+                        *
+                        *      stringlist: empty | STRING | stringlist STRING
+                        */
+                       while (val ==  STRING){
+                               flushfield(NBPW/4);
+                               if (bitoff)
+                                 dotp->xvalue++;
+                               stringp = (struct strdesc *)yylval;
+                               outs(stringp->str, stringp->str_lg);
+                               shift;          /*over the STRING*/
+                               if (val == CM)  /*could be a split string*/
+                                       shift;
+                       }
+
+                       if (auxval == IASCIZ){
+                               flushfield(NBPW/4);
+                               outb(0);
+                       }
+                       break;
+               }       /*end of case IASCII and IASIZ*/
+                       
+               case IORG: {    /* .org <expr> */
+                       shift;
+                       expr(locxp, val);
+
+                       if (locxp->xtype==XABS)
+                               orgwarn++;
+                       else if (locxp->xtype!=dotp->xtype)
+                               yyerror("Illegal expression to set origin");
+                       space_value = locxp->xvalue - dotp->xvalue;
+                       if (space_value < 0)
+                               yyerror("Backwards 'org'");
+                       goto ospace;
+                       break;
+               }       /*end of case IORG*/
+               
+               /*
+                *
+                *      Process stabs.  Stabs are created only by the f77
+                *      and the C compiler with the -g flag set.
+                *      We only look at the stab ONCE, during pass 1, and
+                *      virtually remove the stab from the intermediate file
+                *      so it isn't seen during pass2.  This makes for some
+                *      hairy processing to handle labels occuring in
+                *      stab entries, but since most expressions in the
+                *      stab are integral we save lots of time in the second
+                *      pass by not looking at the stabs.
+                *      A stab that is tagged floating will be bumped during
+                *      the jxxx resolution phase.  A stab tagged fixed will
+                *      not be be bumped.
+                *
+                *      .stab:  Old fashioned stabs
+                *      .stabn: For stabs without names
+                *      .stabs: For stabs with string names
+                *      .stabd: For stabs for line numbers or bracketing,
+                *              without a string name, without
+                *              a final expression.  The value of the
+                *              final expression is taken to be  the current
+                *              location counter, and is patched by the 2nd pass
+                *
+                *      .stab{<expr>,}*8,<expr>, <expr>, <expr>, <expr>
+                *      .stabn           <expr>, <expr>, <expr>, <expr>
+                *      .stabs   STRING, <expr>, <expr>, <expr>, <expr>
+                *      .stabd           <expr>, <expr>, <expr> # . 
+                */
+               case ISTAB: {
+                       stabname = ".stab";
+                       if (passno == 2)        goto errorfix;
+                       stpt = (struct symtab *)yylval;
+                       /*
+                        *      Make a pointer to the .stab slot.
+                        *      There is a pointer in the way (stpt), and
+                        *      tokptr points to the next token.
+                        */
+                       stabstart = tokptr;
+                       (char *)stabstart -= sizeof(struct symtab *);
+                       (char *)stabstart -= sizeof(toktype);
+                       shift;
+                       for (argcnt = 0; argcnt < 8; argcnt++){
+                               expr(locxp, val);
+                               stpt->name[argcnt] = locxp->xvalue;
+                               shiftover(CM);
+                       }
+                 tailstab:
+                       expr(locxp, val);
+                       if (! (locxp->xvalue & STABTYPS)){
+                               yyerror("Invalid type in %s",stabname);
+                               goto errorfix;
+                       }
+                       stpt->ptype = locxp->xvalue;
+                       shiftover(CM);
+                       expr(locxp, val);
+                       stpt->other = locxp->xvalue;
+                       shiftover(CM);
+                       expr(locxp, val);
+                       stpt->desc = locxp->xvalue;
+                       shiftover(CM);
+                       exprisname = 0;
+                       expr(locxp, val);
+                       p = locxp->xname;
+                       if (p == NULL) {        /*absolute expr to begin with*/
+                               stpt->value = locxp->xvalue;
+                               stpt->index = dotp - usedot;
+                               if (exprisname){
+                                       switch(stpt->ptype){
+                                               case N_GSYM:
+                                               case N_FNAME:
+                                               case N_RSYM:
+                                               case N_SSYM:
+                                               case N_LSYM:
+                                               case N_PSYM:
+                                               case N_BCOMM:
+                                               case N_ECOMM:
+                                               case N_LENG:
+                                                       stpt->tag = STABFIXED;
+                                                       break;
+                                               default:
+                                                       stpt->tag = STABFLOATING;
+                                                       break;
+                                       }
+                               } else
+                                       stpt->tag = STABFIXED;
+                       }
+                       else {          /*really have a name*/
+                               stpt->dest = locxp->xname;
+                               stpt->index = p->index;
+                               stpt->type = p->type | STABFLAG;
+                               /*
+                                *      We will assign a more accruate
+                                *      guess of locxp's location when
+                                *      we sort the symbol table
+                                *      The final value of value is
+                                *      given by stabfix()
+                                */
+                               stpt->tag = STABFLOAT;
+#ifdef DSTAB
+                               printf("FORWARD REF FOR %s...\n", stabname);
+                               printf("value (xname) = %x value(value(xname) = %x\n",
+                                       stpt->dest,stpt->dest->value);
+                               printf("name: %.8s\n\n",
+                                       (stpt->dest)->name);
+#endif
+                       }
+                       /*
+                        *      tokptr now points at one token beyond
+                        *      the current token stored in val and yylval,
+                        *      which are the next tokens after the end of
+                        *      this .stab directive.  This next token must
+                        *      be either a SEMI or NL, so is of width just
+                        *      one.  Therefore, to point to the next token
+                        *      after the end of this stab, just back up one..
+                        */
+                       buildskip(stabstart, (char *)tokptr - sizeof(toktype));
+                       break;  /*end of the .stab*/
+               }       /*end of ISTAB*/
+               
+               case ISTABDOT:  {
+                       stabname = ".stabd";
+                       stpt = (struct symtab *)yylval;
+                       /*
+                        *      We clobber everything after the
+                        *      .stabd and its pointer... we MUST
+                        *      be able to get back to this .stabd
+                        *      so that we can resolve its final value
+                        */
+                       stabstart = tokptr;
+                       shift;          /*over the ISTABDOT*/
+                       if (passno == 1){
+                               expr(locxp, val);
+                               if (! (locxp->xvalue & STABTYPS)){
+                                       yyerror("Invalid type in .stabd");
+                                       goto errorfix;
+                               }
+                               stpt->ptype = locxp->xvalue;
+                               shiftover(CM);
+                               expr(locxp, val);
+                               stpt->other = locxp->xvalue;
+                               shiftover(CM);
+                               expr(locxp, val);
+                               stpt->desc = locxp->xvalue;
+                               /*
+                                *
+                                *      Now, clobber everything but the
+                                *      .stabd pseudo and the pointer
+                                *      to its symbol table entry
+                                *      tokptr points to the next token,
+                                *      build the skip up to this
+                                */
+                               buildskip(stabstart, (toktype *)tokptr - sizeof(toktype));
+                       }
+                       /*
+                        *      pass 1: Assign a good guess for its position
+                        *              (ensures they are sorted into right place)/
+                        *      pass 2: Fix the actual value
+                        */
+                       stpt->value = dotp->xvalue;
+                       stpt->index = dotp - usedot;
+                       stpt->tag = STABFLOAT;  /*although it has no effect in pass 2*/
+                       break;
+               }       /*end of case ISTABDOT*/
+
+               case ISTABNONE:         stabname = ".stabn"; goto shortstab;
+
+               case ISTABSTR: {        stabname = ".stabs";
+                  shortstab:
+                       auxval = val;
+                       if (passno == 2) goto errorfix;
+                       stpt = (struct symtab *)yylval;
+                       stabstart = tokptr;
+                       (char *)stabstart -= sizeof(struct symtab *);
+                       (char *)stabstart -= sizeof(toktype);
+                       shift;
+                       if (auxval == ISTABSTR){
+                               stringp = (struct strdesc *)yylval;
+                               shiftover(STRING);
+                               auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg;
+                               shiftover(CM);
+                       } else {
+                               stringp = &(strbuf[2]);
+                               auxval = NCPS;
+                       }
+                       movestr(stpt->name, stringp->str, auxval);
+                       goto tailstab;
+                       break;
+               }       /*end of case ISTABSTR and ISTABN*/
+               
+               case ICOMM:     /* .comm  <name> , <expr> */
+               case ILCOMM: {  /* .lcomm <name> , <expr> */
+                       auxval = val;
+                       shift;
+                       np = (struct symtab *)yylval;
+                       shiftover(NAME);
+                       shiftover(CM);
+                       expr(locxp, val);
+
+                       if (locxp->xtype != XABS)
+                               yyerror("comm size not absolute");
+                       if (passno==1 && (np->type&XTYPE)!=XUNDEF)
+                               yyerror("Redefinition of %.8s", np->name);
+                       if (passno==1) {
+                               np->value = locxp->xvalue;
+                               if (auxval == ICOMM)
+                                       np->type |= XXTRN;
+                               else {
+                                       np->type &= ~XTYPE;
+                                       np->type |= XBSS;
+                               }
+                       }
+                       break;
+               }       /*end of case ICOMM and ILCOMM*/
+               
+               case IALIGN: {          /* .align <expr> */
+                       stpt = (struct symtab *)yylval;
+                       shift;
+                       expr(locxp, val);
+                       jalign(locxp, stpt);
+                       break;
+               }       /*end of case IALIGN*/
+               
+               case INST0: {           /* instructions w/o arguments*/
+                       insout(yylval, 0, 0);
+                       shift;  
+                       break;
+               }       /*end of case INST0*/
+               
+               case INSTn:             /* instructions with arguments*/
+               case IJXXX: {           /* UNIX style jump instructions */
+                       auxval = val;
+                       seg_type = yylval;
+                       /*
+                        *      Code to process an argument list
+                        */
+                       ap = arglist;
+                       xp = explist;   /*must be set before bring in the first token*/
+
+                       shift;          /*and bring in the first token for the arg list*/
+
+                       for (argcnt = 1; argcnt <= 6; argcnt++, ap++){
+                               /*
+                                *      code to process an argument proper
+                                */
+                           sawindex  = sawmul = sawsize = 0;
+                           {
+                               switch(val) {
+
+                                  default: {
+                                     disp:
+                                       if( !(INTOKSET(val,
+                                                EBEGOPS
+                                               +YUKKYEXPRBEG
+                                               +SAFEEXPRBEG)) ) {
+                                               ERROR("expression expected");
+                                       }
+                                       expr(ap->xp,val);
+                                 overdisp:
+                                       if ( val == LP || sawsize){
+                                               shiftover(LP);
+                                               findreg(regno);
+                                               shiftover(RP);
+                                               ap->atype = ADISP;
+                                               ap->areg1 = regno;
+                                       } else {
+                                               ap->atype = AEXP;
+                                               ap->areg1 = 0;
+                                       }
+                                       goto index;
+                                  }    /*end of the default action*/
+
+                                  case SIZESPEC: {
+                                    sizespec:
+                                       sawsize = yylval;
+                                       shift;
+                                       goto disp;
+                                  }
+
+                                  case REG:
+                                  case REGOP: {
+                                       findreg(regno);
+                                       ap->atype = AREG;
+                                       ap->areg1 = regno;
+                                       break;
+                                  }    /*end of case REG*/
+                                   
+                                  case MUL: {
+                                       sawmul = 1;
+                                       shift;
+                                       if (val == LP) goto base;
+                                       if (val == LITOP) goto imm;
+                                       if (val == SIZESPEC) goto sizespec;
+                                       if (INTOKSET(val,
+                                                EBEGOPS
+                                               +YUKKYEXPRBEG
+                                               +SAFEEXPRBEG)) goto disp;
+                                       ERROR("expression, '(' or '$' expected");
+                                       break;
+                                  }    /*end of case MUL*/
+
+                                  case LP: {
+                                    base:
+                                       shift;  /*consume the LP*/
+                                       /*
+                                        *      hack the ambiguity of
+                                        *      movl (expr) (rn), ...
+                                        *      note that (expr) could also
+                                        *      be (rn) (by special hole in the
+                                        *      grammar), which we ensure
+                                        *      means register indirection, instead
+                                        *      of an expression with value n
+                                        */
+                                       if (val != REG && val != REGOP){
+                                               droppedLP = 1;
+                                               val = exprparse(val, &(ap->xp));
+                                               droppedLP = 0;
+                                               goto overdisp;
+                                       }
+                                       findreg(regno);
+                                       shiftover(RP);
+                                       if (val == PLUS){
+                                               shift;
+                                               ap->atype = AINCR;
+                                       } else
+                                               ap->atype = ABASE;
+                                       ap->areg1 = regno;
+                                       goto index;
+                                  }    /*end of case LP*/
+
+                                  case LITOP: {
+                                     imm:
+                                       shift;
+                                       expr(locxp, val);
+                                       ap->atype = AIMM;
+                                       ap->areg1 = 0;
+                                       ap->xp = locxp;
+                                       goto index;
+                                  }    /*end of case LITOP*/
+
+                                  case MP: {
+                                       shift;  /* -(reg) */
+                                       findreg(regno);
+                                       shiftover(RP);
+                                       ap->atype = ADECR;
+                                       ap->areg1 = regno;
+                         index:                        /*look for [reg] */
+                                       if (val == LB){
+                                               shift;
+                                               findreg(regno);
+                                               shiftover(RB);
+                                               sawindex = 1;
+                                               ap->areg2 = regno;
+                                       }
+                                       break;
+                                    }          /*end of case MP*/
+
+                               }       /*end of the switch to process an arg*/
+                           }   /*end of processing an argument*/
+
+                           if (sawmul){
+                                       /*
+                                        * Make a concession for *(%r)
+                                        * meaning *0(%r) 
+                                        */
+                                       if (ap->atype == ABASE) {
+                                               ap->atype = ADISP;
+                                               xp->xtype = XABS;
+                                               xp->xvalue = 0;
+                                               xp->xloc = 0;
+                                               ap->xp = xp++;
+                                       }
+                                       ap->atype |= ASTAR;
+                                       sawmul = 0;
+                           }
+                           if (sawindex){
+                               ap->atype |= AINDX;
+                               sawindex = 0;
+                           }
+                           ap->dispsize = sawsize == 0 ? d124 : sawsize;
+                               if (val != CM) break;
+                               shiftover(CM);
+                       }       /*processing all the arguments*/
+
+                       if (argcnt > 6){
+                               yyerror("More than 6 arguments");
+                               goto errorfix;
+                       }
+
+                       insout(seg_type, arglist,
+                               auxval == INSTn ? argcnt : - argcnt);
+                       break;
+               }       /*end of case INSTn and IJXXX*/
+               
+               case IFLOAT:    curlen = 4;     goto floatlist;
+
+               case IDOUBLE: {
+                       curlen = 8;
+                 floatlist:    
+                       /*
+                        *      eat a list of floating point numbers
+                        */
+                       shift;
+                       if (val == FLTNUM){
+                               do{
+                                       if (val == CM) shift;
+                                       if (val != FLTNUM) {
+                                         ERROR("floating number expected");
+                                       }
+                                       dotp->xvalue += curlen;
+                                       if (passno == 2)
+                                          fwrite(
+                                            &(((struct exp *)yylval)->doubval.dvalue),
+                                            1, curlen, txtfil);
+                                       shift;
+                               } while (val == CM);
+                       }
+                       break;
+               }       /*end of case IFLOAT and IDOUBLE*/
+
+           }   /*end of the switch for looking at each reserved word*/
+
+               /*
+                *      If got here, then one has no syntax errors!
+                */
+               continue;
+
+               /*
+                *      got here by either requesting to skip to the
+                *      end of this statement, or by erroring out and
+                *      wanting to apply panic mode recovery
+                */
+          errorfix: {
+#ifdef DEBUG
+               if (debug)
+                       printf("Discarding tokens from here:\n");
+#endif
+                               while (    (val != NL) 
+                                       && (val != SEMI) 
+                                       && (val != PARSEEOF)
+                                     ){
+#ifdef DEBUG
+                                       if (debug)
+                                               printf("****>>>>\t");
+#endif
+                                       shift;
+                               }
+                               if (val == NL)
+                                       lineno++;
+#ifdef DEBUG
+               if (debug)
+                       printf("To here.\n");
+#endif
+                       shift;
+                    }
+
+       }       /*end of the loop to read the entire file, line by line*/
+
+
+}      /*end of yyparse*/
+       
+/*
+ *     Process a register declaration of the form
+ *     % <expr>
+ *
+ *     Note:
+ *             The scanner has already processed funny registers of the form
+ *     %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
+ *     preceding zero digit).  If there was any space between the % and
+ *     the digit, the scanner wouldn't have recognized it, so we
+ *     hack it out here.
+ */
+int funnyreg(val, regnoback)           /*what the read head will sit on*/
+       int     val;                    /*what the read head is sitting on*/
+       int     *regnoback;             /*call by return*/
+{
+       register        struct  exp *locxp;
+                       struct  exp *loc1xp;
+                       struct  exp **ptrloc1xp = & loc1xp;
+
+       expr(locxp, val);       /*and leave the current read head with value*/
+       if ( (passno == 2) &&
+           (   locxp->xtype & XTYPE != XABS
+            || locxp->xvalue < 0
+            || locxp->xvalue >= 16 
+           )
+         ){
+               yyerror("Illegal register");
+               return(0);
+       }
+       *regnoback = locxp->xvalue;
+       return(val);
+} 
+
+/* VARARGS 1*/
+yyerror(s, a1, a2)
+       char    *s;
+{
+       FILE            *sink;
+
+#ifdef DEBUG
+       sink = stdout;
+#else
+       sink = stderr;
+#endif
+
+       if (anyerrs == 0 && ! silent) 
+               fprintf(sink, "Assembler:\n");
+       anyerrs++;
+       if (silent) return;
+       
+       fprintf(sink, "\"%s\", line %d: ", dotsname, lineno);
+       fprintf(sink, s, a1, a2);
+       fprintf(sink, "\n");
+}
diff --git a/usr/src/cmd/as/asscan.h b/usr/src/cmd/as/asscan.h
new file mode 100644 (file)
index 0000000..71e8d4c
--- /dev/null
@@ -0,0 +1,118 @@
+/* Copyright (c) 1979 Regents of the University of California */
+
+/*
+ *     The character scanner is called to fill up one token buffer
+ *
+ *     In the first pass, the tokens in this buffer may be overwriten
+ *     to eliminate .stabs, and to change fully assemblable instructions
+ *     into ascii strings.  However, once the tokens are filled up by the
+ *     character scanner, they are used in both the first and the second
+ *     pass.  Holes created by .stab removal and preassembly are replaced
+ *     with 'skip' tokens that direct the second pass to ignore the
+ *     following tokens.
+ *
+ *     While the first pass could write a second version of the intermediate
+ *     file and really purge the .stabs and such, the buffering required
+ *     to do this seems to be too complex and too slow.
+ */
+
+#define TOKBUFLG               2*BUFSIZ
+#define MAXVAX                 32              
+#define SAFETY                 2*NCPS
+
+#define AVAILTOKS              TOKBUFLG -\
+               sizeof(short) -\
+               sizeof (struct tokbufdesc *) -\
+               MAXVAX - SAFETY
+
+struct tokbufdesc{
+       short           tok_count;              /*absolute byte length*/
+       struct          tokbufdesc *tok_next;
+       char            toks[AVAILTOKS];
+       char            bufovf[MAXVAX + SAFETY];
+};
+
+/*
+ *     All variables handling these resources are local to astmpfil.c;
+ *     we must have the structure defnitions here so that
+ *     asscan.c can touch the stuff in a token buffer
+ */
+
+/*
+ *     Definitions for handling tokens in the intermediate file
+ *     buffers.
+ *
+ *     We want to have the compiler produce the efficient auto increment
+ *     instruction for stepping through the buffer of tokens.  We must
+ *     fool the type checker into thinking that a pointer can point
+ *     to various size things.
+ */
+
+typedef char toktype;
+
+typedef char *ptrall;                  /*all uses will be type cast*/
+typedef short lgtype;                  /*for storing length of strings or skiping*/
+/*
+ *     defintions for putting various typed values
+ *     into the intermediate buffers
+ *     ptr will ALWAYS be of type ptrall
+ */
+
+#define        pchar(ptr,val)          *ptr++  = val
+#define        puchar(ptr,val)         *ptr++  = val
+
+#define        pshort(ptr,val)         *(short *)ptr=val,      ptr += sizeof(short)
+#define        pushort(ptr,val)        *(unsigned short *)ptr=val, ptr += sizeof(short)
+#define        pint(ptr,val)           *(int *)ptr  = val,     ptr += sizeof(int)
+#define        puint(ptr,val)          *(unsigned int *)ptr=val, ptr += sizeof(int)
+#define        plong(ptr,val)          *(long *)ptr  = val,    ptr += sizeof(long)
+#define        pulong(ptr,val)         *(unsigned long *)ptr=val,ptr += sizeof(long)
+#define        pfloat(ptr,val)         *(float *)ptr  = val,   ptr += sizeof (float)
+#define        pdouble(ptr,val)        *(double *)ptr  = val,  ptr += sizeof (double)
+#define        pptr(ptr,val)           *(int *)ptr  = (val),   ptr += sizeof(ptrall)
+#define        ptoken(ptr,val)         *ptr++  = val
+#define        pstrlg(ptr,val)         *(lgtype *)ptr  = val,  ptr += sizeof(short)
+#define        pskiplg(ptr,val)        *(lgtype *)ptr  = val,  ptr += sizeof(short)
+
+#define        gchar(val, ptr)         val = *ptr++
+#define        guchar(val, ptr)        val = *ptr++
+
+#define        gshort(val, ptr)        val = *(short *)ptr , ptr += sizeof (short)
+#define        gushort(val, ptr)       val = *(unsigned short *)ptr , ptr += sizeof (short)
+#define        gint(val, ptr)          val = *(int *)ptr, ptr += sizeof (int)
+#define        guint(val, ptr)         val = *(unsigend int *)ptr, ptr += sizeof (int)
+#define        glong(val, ptr)         val = *(long *)ptr, ptr += sizeof (long)
+#define        gulong(val, ptr)        val = *(unsigned long *)ptr, ptr += sizeof (long)
+#define        gfloat(val, ptr)        val = *(float *)ptr, ptr += sizeof (float)
+#define        gdouble(val, ptr)       val = *(double *)ptr, ptr += sizeof (double)
+#define        gptr(val, ptr)          val = *(int *)ptr, ptr += sizeof (ptrall)
+#define        gtoken(val, ptr)        val = *ptr++
+#define        gstrlg(val, ptr)        val = *(lgtype *)ptr, ptr += sizeof (short)
+#define        gskiplg(val, ptr)       val = *(lgtype *)ptr, ptr += sizeof (short)
+
+
+ptrall tokptr; /*the next token to consume, call by copy*/
+ptrall tokub;  /*current upper bound in the current buffer*/
+
+/*
+ *     Strings are known for their characters and for their length.
+ *     We cannot use a normal zero termination byte, because strings
+ *     can contain anything.
+ *
+ *     We have two "strings", so that an input string that is too long can be
+ *     split across two string buffers, and not confuse the yacc grammar.
+ *     (This is probably superflous)
+ *
+ *     We have a third string of nulls so that the .skip can be 
+ *     handled in the same way as strings.
+ */
+#define MAXSTRLG       127
+
+struct strdesc{
+       char            str_lg;
+       char            str[MAXSTRLG];
+};
+
+struct         strdesc         strbuf[3];
+struct         strdesc         *strptr;        /*points to the current string*/
+int                    strno;          /*the current string being filled*/
diff --git a/usr/src/cmd/as/assyms.c b/usr/src/cmd/as/assyms.c
new file mode 100644 (file)
index 0000000..fe26204
--- /dev/null
@@ -0,0 +1,529 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#include <stdio.h>
+#include "as.h"
+#include "assyms.h"
+
+struct allocbox        *allochead;
+struct allocbox        *alloctail;
+struct symtab          *nextsym;
+struct allocbox        *newbox;
+char                   *namebuffer;
+int                    symsleft;
+
+symtabinit()
+{
+       allochead = 0;
+       alloctail = 0;
+       nextsym = 0;
+       symsleft = 0;
+}
+
+/*
+ *     Install all known instructions in the symbol table
+ */
+syminstall()
+{
+       register        struct  instab  *ip;
+       register        struct  symtab  **hp;
+       register        char    *p1, *p2;
+
+       for (ip=instab; ip->name[0]!=0; ip++) {
+               p1 = ip->name;
+               p2 = yytext;
+               while (*p2++ = *p1++);
+               hp = lookup(0);         /* 0 => don't install this*/
+               if (*hp==NULL) {
+                       *hp = (struct symtab *)ip;
+                       if (   (ip->tag!=INSTn)
+                           && (ip->tag!=INST0)
+                           && (ip->tag!=0))
+                               continue; /* was pseudo-op */
+                       itab[ip->opcode & 0xFF] = ip;
+               }
+       }
+}      /*end of syminstall*/
+
+
+/*
+ *     Assign final values to symbols,
+ *     and overwrite the index field with its relative position in
+ *     the symbol table we give to the loader.
+ */
+extern struct hdr hdr;
+
+freezesymtab()
+{
+       register        struct  symtab  *sp;
+                               long    bs;
+       register        int     relpos = 0;
+#ifdef SORTEDOUTPUT
+       register        struct  symtab  **cosp;
+#else
+       register        struct  symtab          *ubsp;
+       register        struct  allocbox        *allocwalk;
+#endif
+
+#ifdef SORTEDOUTPUT
+       SYMITERATE(cosp, sp)
+#else
+       DECLITERATE(allocwalk, sp, ubsp)
+#endif
+       {
+               if (sp->tag >= IGNOREBOUND)
+                       continue;               /*totally ignore jxxx entries */
+               /*
+                *      Ignore stabs, but give them a symbol table index
+                */
+               if (sp->type & STABFLAG)
+                       goto assignindex;
+               if ((sp->type&XTYPE)==XUNDEF)
+                       sp->type = XXTRN+XUNDEF;
+               else if ((sp->type&XTYPE)==XDATA)
+                       sp->value += usedot[sp->index].xvalue;
+               else if ((sp->type&XTYPE)==XTEXT)
+                       sp->value += usedot[sp->index].xvalue;
+               else if ((sp->type&XTYPE)==XBSS) {
+                       bs = sp->value;
+                       sp->value = hdr.bsize + datbase;
+                       hdr.bsize += bs;
+               }
+          assignindex:
+               if (    (sp->name[0] != 'L')
+                    || (sp->tag != LABELID)
+                    || savelabels
+                    )                  /*then, we will write it later on*/
+                               sp->index = relpos++;
+       }
+}
+
+
+
+/*
+ *     For all of the stabs that had their final value undefined during pass 1
+ *     and during pass 2 assign a final value.
+ *     We have already given stab entrys a initial approximation
+ *     when we constsructed the sorted symbol table.
+ *     Iteration order doesn't matter.
+ */
+stabfix() {
+       register struct symtab *sp, **cosp;
+       register struct symtab *p;
+       
+       SYMITERATE(cosp, sp){
+               if(sp->ptype && (sp->type & STABFLAG)) {        
+                       p = sp->dest;   
+                       sp->value = p->value;   
+                       sp->index = p->index;
+                       sp->type = p->type;
+#ifdef DSTAB
+                       printf("STABFIX: %s (old %s) to %d offsets %d %d\n",
+                               sp->name, p->name, sp->value, sp, p);
+#endif
+               }
+       }
+}
+
+char *Calloc(number, size)
+       int     number, size;
+{
+       register        char *newstuff;
+       newstuff = (char *)sbrk(number*size);
+       if ((int)newstuff == -1){
+               yyerror("Ran out of Memory");
+               delexit();
+       }
+       return(newstuff);
+}
+
+struct symtab * symalloc()
+{
+       if (symsleft == 0){
+               register        int     *p;
+
+               newbox = (struct allocbox *)Calloc(1,ALLOCQTY);
+               symsleft = SYMDALLOP;
+               nextsym = &newbox->symslots[0];
+               namebuffer = &newbox->symnames[0];
+               p = (int *)(&newbox->symnames[SYMDALLOP * NCPS]);
+               while ( p > (int *)newbox){
+                       *--p = 0;
+               }
+               if (alloctail == 0){
+                       allochead = alloctail = newbox;
+               } else {
+                       alloctail->nextalloc = newbox;
+                       alloctail = newbox;
+               }
+       }
+       --symsleft;
+       ++nsyms;
+       nextsym->name = namebuffer;
+       namebuffer += NCPS;
+       return(nextsym++);
+}
+
+symcmp(pptr, qptr)
+       struct symtab **pptr, **qptr;
+{
+       register struct symtab *p = *pptr;
+       register struct symtab *q = *qptr;
+       if (p->index < q->index)
+               return(-1);
+       if (p->index > q->index)
+               return(1);
+       if (p->value < q->value)
+               return(-1);
+       if (p->value > q->value)
+               return(1);
+       /*
+        *      Force jxxx entries to virtually preceed labels defined
+        *      to follow the jxxxx instruction, so that bumping the
+        *      jxxx instruction correctly fixes up the following labels
+        */
+       if (p->tag >= IGNOREBOUND)      /*p points to a jxxx*/
+               return(-1);             
+       if (q->tag >= IGNOREBOUND)
+               return(1);
+       /*
+        *      both are now just plain labels; the relative order doesn't
+        *      matter.  Both can't be jxxxes, as they would have different
+        *      values.
+        */
+       return(0);                      
+}      /*end of symcmp*/
+
+/*
+ *     We construct the auxiliary table of pointers, symptrs and
+ *     symdelim
+ *     We also assign preliminary values to stab entries that did not yet
+ *     have an absolute value (because they initially referred to
+ *     forward references). We don't worry about .stabds, as they
+ *     already have an estimated final value
+ */
+
+sortsymtab()
+{
+       register        struct  symtab  *sp;
+       register        struct  symtab  **cowalk;
+       register        struct  allocbox        *allocwalk;
+                       struct  symtab  *ubsp;
+                               int     segno;
+                               int     slotno;
+                               int     symsin; /*number put into symptrs*/
+
+       symptrs =  (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
+       /*
+        *      Allocate one word at the beginning of the symptr array
+        *      so that backwards scans through the symptr array will
+        *      work correctly while scanning through the zeroth segment
+        */
+       *symptrs++ = 0;
+       cowalk = symptrs;
+       symsin = 0;
+       DECLITERATE(allocwalk, sp, ubsp) {
+               if (sp->ptype && (sp->type &STABFLAG)){
+                       sp->value = sp->dest->value;
+                       sp->index = sp->dest->index;
+               }
+               if (symsin >= nsyms)
+                       yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
+               *cowalk++ = sp;
+               symsin++;
+       }
+       if (symsin != nsyms)
+               yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
+                       symsin, nsyms);
+       symptrub = &symptrs[nsyms ];
+       qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
+       symdelim[0] = symptrs;
+       for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
+            segno < NLOC + NLOC;
+            segno++, slotno++){
+               for (; sp && sp->index == segno; sp = *++cowalk);
+               symdelim[slotno] = cowalk;      /*forms the ub delimeter*/
+       }
+}      /*end of sortsymtab*/
+
+#ifdef DEBUG
+dumpsymtab()
+{
+       register        int     segno;
+       register        struct symtab *sp, **cosp, *ub;
+       char            *tagstring();
+
+       printf("Symbol Table dump:\n");
+       for (segno = 0; segno < NLOC + NLOC; segno++){
+               printf("Segment number: %d\n", segno);
+               SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
+                       printf("\tSeg: %d \"%8.8s\" value: %d index: %d tag %s\n",
+                               segno, sp->name, sp->value, sp->index, tagstring(sp->tag));
+                       printf("\t\ttype: %d jxbump %d jxfear: %d\n",
+                               sp->type, sp->jxbump, sp->jxfear);
+               }
+               printf("\n\n");
+       }
+}
+
+static char tagbuff[4];
+
+char *tagstring(tag)
+       unsigned        char    tag;
+{
+       switch(tag){
+               case JXACTIVE:          return("active");
+               case JXNOTYET:          return("notyet");
+               case JXALIGN:           return("align");
+               case JXQUESTIONABLE:    return("jxquestionable");
+               case JXINACTIVE:        return("inactive");
+               case JXTUNNEL:          return("tunnel");
+               case OBSOLETE:          return("obsolete");
+               case IGNOREBOUND:       return("ignorebound");
+               case STABFLOATING:      return("stabfloating");
+               case STABFIXED:         return("stabfixed");
+               case LABELID:           return("labelid");
+               case OKTOBUMP:          return("oktobump");
+               case ISET:              return("iset");
+               case ILSYM:             return("ilsym");
+               default:                sprintf(tagbuff,"%d", tag);
+                                       return(tagbuff);
+       }
+}
+#endif
+
+#define        HASHCLOGGED     (NHASH * 3 ) / 4
+
+struct symtab **lookup(instflg)
+       int     instflg;                /* 0: don't install */
+{
+       register int            ihash;
+       register struct symtab  **hp;
+       register char           *p1, *p2;
+       register        int     i;
+
+#ifdef METRIC
+       nhashed++;
+#endif
+
+       /*
+        *      All strings passed in in yytext had better have
+        *      a trailing null.  Strings are placed in yytext for
+        *      hashing by syminstall() and yylex()
+        */
+       for (ihash = 0, p1 = yytext ; *p1; ihash <<= 2, ihash += *p1++);
+       ihash += p1[-1] << 5;
+       ihash %= NHASH;
+       if (ihash < 0) ihash += NHASH;
+       hp = &hshtab[ihash];
+       ihash = 1;              /*now, it counts the number of times we rehash*/
+       while (*hp) {
+               p1 = yytext;
+               p2 = (*hp)->name;
+               for (i = 0; (i<NCPS) && *p1; i++)
+                       if (*p1++ != *p2++)
+                               goto no;
+               if (i >= NCPS)          /*both symbols are maximal length*/
+                       return(hp);
+               if (*p2 == 0)   /*assert *p1 == 0*/
+                       return(hp);
+           no:
+#ifdef METRIC
+               nhcollisions++;
+#endif
+               hp += ihash;
+               ihash += 2;
+               if (hp >= &hshtab[NHASH])
+                       hp -= NHASH;
+       }
+       if(++hshused >= HASHCLOGGED) {
+               yyerror("Symbol table overflow");
+               delexit();
+       }
+       if (instflg) {
+#ifdef METRIC
+               nentered++;
+#endif
+               *hp = symalloc();
+               p1 = yytext;
+               p2 = (*hp)->name;
+               while (*p2++ = *p1++);
+       }
+       return(hp);
+}      /*end of symlook*/
+
+#ifdef vax
+#define writel(p,n,f) fwrite((long)p, sizeof (long), n, f)
+#else
+writel(p,n,f)
+       long *p;
+       FILE *f;
+{
+       while (n--) {
+               fwrite(&(*p).loword,2,1,f);
+               fwrite(&(*p).hiword,2,1,f);
+               p++;
+       }
+}
+#endif
+
+int reflen[] = {0,0,1,1,2,2,4,4,8,8};
+
+/*
+ *     Save the relocation information
+ */
+outrel(pval,reftype,reltype,xsym)
+       long            *pval;
+       register int    reftype,reltype;
+       struct symtab   *xsym;
+{
+
+/*
+ *     reftype: PCREL or not, plus length LEN1, LEN2, LEN4, LEN8
+ *     reltype: csect ("segment") number (XTEXT, XDATA, ...) associated with 'val'
+ *     xsym: symbol table pointer
+ */
+       long ts;
+       char tc;
+       long tl;
+       short t;
+       if (passno!=2) {
+               dotp->xvalue += reflen[reftype];
+               return;
+       }
+       if (bitoff&07)
+               yyerror("Padding error");
+       reltype &= ~XFORW;
+       if (reltype == XUNDEF)
+               yyerror("Undefined reference");
+       if (reltype != XABS || reftype & PCREL) {
+               /* write the address portion of a relocation datum */
+               if (dotp >= &usedot[NLOC]) {
+                       hdr.drsize += sizeof(dotp->xvalue) + 3 + sizeof tc;
+                       tl = dotp->xvalue-datbase;
+                       writel(&tl,1,relfil);
+               } else {
+                       hdr.trsize += sizeof(dotp->xvalue) + 3 + sizeof tc;
+                       writel(&dotp->xvalue,1,relfil);
+               }
+               /* write the properties portion of a relocation datum */
+               if (reltype == XXTRN+XUNDEF) {
+                       ts = (xsym->index);
+                       tc = (XXTRN<<3) | (reftype-LEN1);
+               } else if ((reltype&XTYPE) == XUNDEFO) {
+                       ts = (xsym->index);
+                       tc = ((XXTRN+2)<<3) | (reftype-LEN1);
+               } else  {
+                       ts = (reltype);
+                       tc = (reftype-LEN1);
+               }
+               fwrite((char *)&ts, 3, 1, relfil);
+               fwrite(&tc, sizeof(tc), 1, relfil);
+       }
+       /* write the raw ("unrelocated") value to the text file */
+       t = reflen[reftype];
+       dotp->xvalue += t;
+       if (reftype & PCREL)
+               *pval -= dotp->xvalue;
+#ifdef vax
+       fwrite(pval,1,t,txtfil);
+#else
+       if (t>2) {
+               fwrite(&((*pval).loword),1,2,txtfil);
+               fwrite(&((*pval).hiword),1,t-2,txtfil);
+       } else fwrite(&((*pval).loword),1,t,txtfil);
+#endif
+}
+
+
+/*
+ *     Write out n symbols to file f, beginning at p
+ *     ignoring symbols that are obsolete, jxxx instructions, and
+ *     possibly, labels
+ */
+
+int sizesymtab()
+{
+       struct symtab *sp;
+
+#define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
+
+       return (
+               (  NCPS
+                + sizeof (sp->ptype)
+                + sizeof (sp->other)
+                + sizeof (sp->desc)
+                + sizeof (sp->value)
+               ) 
+               *       NOUTSYMS
+       );
+}
+
+symwrite(f)
+       FILE *f;
+{
+       int     symsout;                        /*those actually written*/
+       int     symsdesired = NOUTSYMS;
+       register        struct  symtab *sp, *ub;
+#ifdef SORTEDOUTPUT
+       int     segno;
+       register        struct  symtab          **copointer;
+#else
+       register        struct  allocbox        *allocwalk;
+#endif
+
+#ifdef SORTEDOUTPUT
+       for (segno = 0, symsout = 0; segno < NLOC + NLOC; segno++)
+               SEGITERATE(segno, 0, 0, copointer, sp, ub, ++)
+#else
+       symsout = 0;
+       DECLITERATE(allocwalk, sp, ub)
+#endif
+       {
+               if (sp->tag >= IGNOREBOUND) 
+                       continue;
+               if ((sp->name[0] == 'L') && (sp->tag == LABELID) && !savelabels)
+                       continue;
+               symsout++;
+               fwrite(sp->name, NCPS, 1, f);
+               sp->type &= ~XFORW;
+               fwrite((sp->ptype) ? (char *)(&(sp->ptype)) : (char *)(&(sp->type)),
+                       sizeof(char), 1, f);
+       /*
+        *      WATCH OUT.  THIS DEPENDS THAT THE ALLOCATION OF
+        *      the four fields ptype, other, desc and value are
+        *      contiguous.  This may have to be changed!
+        *      This is safe (as of 2-Nov-79).
+        */
+               fwrite(&(sp->other),
+                       sizeof (sp->other)
+                      + sizeof (sp->desc)
+                      + sizeof (sp->value), 1, f
+               );
+#ifdef fooie
+#ifdef vax
+               fwrite(&(sp->name[0]), sizeof(symtab[0].name), 1, f);
+               fwrite(sp->ptype ? &(sp->ptype) : &(sp->type),
+                       sizeof(symtab[0].type), 1, f);
+               fwrite(&(sp->other), sizeof(symtab[0].other), 1, f);
+               fwrite(&(sp->desc), sizeof(symtab[0].desc), 1, f);
+               fwrite(&(sp->value), sizeof(symtab[0].value), 1, f);
+#else
+               writel(&(p->value), 1, f);
+#endif
+#endif
+       }
+       if (symsout != symsdesired)
+               yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
+                       symsout, symsdesired);
+}
+
+Flushfield(n)
+       register int n;
+{
+       while (n>0) {
+               outb(bitfield);
+               bitfield >>= 8;
+               n -= 8;
+       }
+       bitoff=0;
+       bitfield=0;
+}
diff --git a/usr/src/cmd/as/assyms.h b/usr/src/cmd/as/assyms.h
new file mode 100644 (file)
index 0000000..915fa65
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (c) 1979 Regents of the University of California */
+/*
+ *     To speed up walks through symbols defined in a particular
+ *     segment, we buil up a table of pointers into the symbol table
+ *     and a table of delimiters for each segment.  The delimiter for
+ *     the particular segment points to the first word in that segment.
+ */
+
+struct symtab  **symptrs;              /*dynamically allocated*/
+struct symtab  **symdelim[NLOC + NLOC + 1];
+struct symtab  *hshtab[NHASH];
+struct symtab  **symptrub;
+       int     nsyms;                  /*number in the symbol table*/
+       int     njxxx;                  /*the number of jxxx entries in the table*/
+       int     nforgotten;             /*how many entries erroneously entered*/
+       int     nlabels;                /*how many labels in the symbol table*/
+       int     hshused;                /*how many hash slots used*/
+
+#define SEGITERATE(segno, start, end, copointer, walkpointer, ubpointer, direction) \
+       for(copointer = start == 0? symdelim[segno]:start,\
+           ubpointer = end == 0 ? *symdelim[segno+1] : *(symdelim[segno]-1),\
+           walkpointer = *copointer;\
+           walkpointer != ubpointer;\
+           walkpointer = * direction copointer)
+
+#define SYMITERATE(copointer, walkpointer) \
+       for(copointer = symptrs, \
+           walkpointer = *copointer; \
+           copointer < symptrub; \
+           walkpointer = * ++ copointer)
+/*
+ *     Symbols are allocated in non contiguous chunks by extending
+ *     the data area.  This way, it is extremely easy to
+ *     allow virtual memory temporary files, change the length
+ *     of NCPS, and allows for a much more flexible storage
+ *     allocation
+ */
+
+#define SYMDALLOP      200
+struct         allocbox{
+       struct          allocbox        *nextalloc;
+       struct          symtab          symslots[SYMDALLOP];
+       char                            symnames[SYMDALLOP * NCPS];
+};
+
+extern struct  allocbox        *allochead;
+extern struct  allocbox        *alloctail;
+extern struct  symtab          *nextsym;
+extern struct  allocbox        *newbox;
+extern char                    *namebuffer;
+extern int                     symsleft;
+
+#define ALLOCQTY       sizeof (struct allocbox)
+/*
+ *     Iterate through all symbols in the symbol table in declaration
+ *     order
+ */
+#define DECLITERATE(allocwalk, walkpointer, ubpointer) \
+       for(allocwalk = allochead; \
+           allocwalk != 0; \
+           allocwalk = allocwalk->nextalloc) \
+               for (walkpointer = &allocwalk->symslots[0],\
+                       ubpointer = &allocwalk->symslots[SYMDALLOP], \
+                       ubpointer = ubpointer > ( (struct symtab *)alloctail) \
+                                ? nextsym : ubpointer ;\
+                    walkpointer < ubpointer; \
+                    walkpointer++ )
diff --git a/usr/src/cmd/as/astoks.h b/usr/src/cmd/as/astoks.h
new file mode 100644 (file)
index 0000000..aa5c086
--- /dev/null
@@ -0,0 +1,107 @@
+/* Copyright (c) 1979 Regents of the University of California */
+/*
+ *     Message to the wary:  The order of tokens has been
+ *     hand optimized and assigned to that all switch statements
+ *     are implemented by a casel instruction on the VAX. 
+ *     there are 4 switch statements that have to be worried about:
+ *     l)      Per character switch in the character scanner (scan_dot_s)
+ *     2)      Per token switch in the buffer manager (yylex)
+ *     3)      Per keyword switch in the parser (yyparse)
+ *     4)      Leading token switch for argments to opcodes
+ *     
+ *     You can't just add new tokens willy-nilly; make sure that you
+ *     add them into the proper order!
+ */
+# define FIRSTTOKEN    0
+
+/*
+ *     Tokens between ISPACE and INSTn are used by the per keyword switch
+ */
+# define ISPACE        1
+# define IBYTE                 2
+# define IWORD                 3
+# define IINT          4
+# define ILONG                 5
+# define IDATA                 6
+# define IGLOBAL       7
+# define ISET          8
+# define ITEXT                 9
+# define ICOMM                 10
+# define ILCOMM        11
+# define IFLOAT        12
+# define IDOUBLE       13
+# define IORG          14
+# define IASCII        15
+# define IASCIZ        16
+# define ILSYM                 17
+# define IFILE                 18
+# define ILINENO       19
+# define IABORT        20
+/*
+ *     Tokens between ISTAB and REG are used in the per token switch
+ */
+# define ISTAB                 23
+# define ISTABSTR      24
+# define ISTABNONE     25
+# define ISTABDOT      26
+# define IJXXX                 27
+# define IALIGN        28
+# define INST0                 29
+# define INSTn                 30
+
+# define PARSEEOF      32
+# define ILINESKIP     33
+# define VOID          34
+# define SKIP          35
+# define INT           36
+# define FLTNUM                37
+# define NAME          38
+# define STRING                39
+/*
+ *     Tokens between SIZESPEC and REGOP are used in the instruction
+ *     argument switch
+ */
+# define SIZESPEC      41
+# define REG           42
+# define MUL           43
+# define LITOP         44
+# define LP            45
+# define MP            46
+/*     
+ *     Tokens between REGOP and DIV are used in the per character switch
+ */
+# define NEEDSBUF      48      /*signal refilling the input buffer*/
+# define REGOP         49      /*the percent sign*/
+# define NL            50
+# define SCANEOF       51
+# define BADCHAR       52
+# define SP            53
+# define ALPH          54
+# define DIG           55
+# define SQ            56
+# define DQ            57
+# define SH            58
+# define LSH           59
+# define RSH           60
+# define MINUS         61
+# define SIZEQUOTE     62
+/*
+ *     Tokens between XOR and RP are used at random (primarily by the
+ *     expression analyzer), and not used in any switch
+ */
+# define XOR           64
+# define DIV           65
+
+# define SEMI          66
+# define COLON         67
+# define PLUS          68
+# define IOR           69 
+# define AND           70
+# define TILDE         71
+# define ORNOT         72
+# define CM            73
+# define LB            74
+# define RB            75
+# define RP            76
+
+# define LASTTOKEN     80