--- /dev/null
+/* 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*/
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/*
+ * 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"); }
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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 = ®no;
+ 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");
+}
--- /dev/null
+/* 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*/
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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++ )
--- /dev/null
+/* 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