-#
-/* %Z%%M% %R%.%L% %D% %T% */
+/* Copyright (c) 1980 Regents of the University of California */
+/* "@(#)as.h 4.8 11/5/80" */
+#ifdef VMS
+# define vax 1
+# define VAX 1
+#endif VMS
+
+#include <sys/types.h>
+#ifdef UNIX
+
+#ifdef FLEXNAMES
+# include <a.out.h>
+# include <stab.h>
+#else not FLEXNAMES
+# define ONLIST
+# include "a.out.h"
+# include <stab.h>
+#endif FLEXNAMES
+
+#endif UNIX
+#ifdef VMS
+
+#ifdef UNIXDEVEL
+# include <a.out.h>
+#else not UNIXDEVEL
+# include <aout.h>
+#endif not UNIXDEVEL
+
+#endif VMS
+
#define readonly
-#define NINST 300
-#define NSYM 3000
-#define NHASH (NSYM+1)
-#define NLOC 4 /* number of location ctrs */
-#define NCPS 8
+#define NINST 300
+
+#define NEXP 20 /* max number of expr. terms per instruction */
+#define NARG 6 /* max number of args per instruction */
+#define NHASH 1103 /* hash table is dynamically extended */
+#define TNAMESIZE 32 /* maximum length of temporary file names */
+#define NLOC 4 /* number of location ctrs */
+
+#ifdef UNIX
+# ifndef FLEXNAMES
+# ifndef NCPS
+# define NCPS 8 /* number of characters per symbol*/
+# endif
+# else
+# ifdef NCPS
+# undef NCPS
+# endif
+# define NCPS BUFSIZ /* needed to allocate yytext */
+# endif
+# endif UNIX
+
+# ifdef VMS
+# ifdef NCPS
+# undef NCPS
+# endif NCPS
+# define NCPS 15
+# endif VMS
/*
* Symbol types
#define XTEXT 0x4
#define XDATA 0x6
#define XBSS 0x8
-#define XDATAO 0xA
-#define XBSSO 0xC
-#define XTEXTO 0xE
-#define XABSO 0x10
-#define XUNDEFO 0x12
-#define XTXRN 0xA
#define XXTRN 0x1
#define XTYPE 0x1E
#define XFORW 0x20 /* Was forward-referenced when undefined */
#define ERR (-1)
-#define NBPW 32
+#define NBPW 32 /* Bits per word */
#define AMASK 017
/*
* Actual argument syntax types
*/
-#define AREG 1 /* %r */
-#define ABASE 2 /* (%r) */
-#define ADECR 3 /* -(%r) */
-#define AINCR 4 /* (%r)+ */
-#define ADISP 5 /* expr(%r) */
-#define AEXP 6 /* expr */
-#define AIMM 7 /* $ expr */
-#define ASTAR 8 /* * */
-#define AINDX 16 /* [%r] */
+#define AREG 1 /* %r */
+#define ABASE 2 /* (%r) */
+#define ADECR 3 /* -(%r) */
+#define AINCR 4 /* (%r)+ */
+#define ADISP 5 /* expr(%r) */
+#define AEXP 6 /* expr */
+#define AIMM 7 /* $ expr */
+#define ASTAR 8 /* * */
+#define AINDX 16 /* [%r] */
/*
- * Argument access types
+ * Argument access types used to test validity of operands to operators
*/
-#define ACCA (8<<3) /* address only */
-#define ACCR (1<<3) /* read */
-#define ACCW (2<<3) /* write */
-#define ACCM (3<<3) /* modify */
-#define ACCB (4<<3) /* branch displacement */
-#define ACCI (5<<3) /* XFC code */
+#define ACCR (1<<3) /* read */
+#define ACCW (2<<3) /* write */
+#define ACCB (4<<3) /* branch displacement */
+#define ACCA (8<<3) /* address only */
+#define ACCM (ACCR | ACCW) /* modify */
+#define ACCI (ACCB | ACCR) /* XFC code */
+
+#define ACCESSMASK (ACCA | ACCR | ACCW | ACCB) /* the mask */
/*
- * Argument data types
+ * Argument data types
+ * Also used to tell outrel what it is relocating
+ * (possibly in combination with RELOC_PCREL and TYPNONE)
*/
-#define TYPB 0 /* byte */
-#define TYPW 1 /* word */
-#define TYPL 2 /* long */
-#define TYPQ 3 /* quad */
-#define TYPF 4 /* floating */
-#define TYPD 5 /* double floating */
+#define TYPB 0 /* byte */
+#define TYPW 1 /* word */
+#define TYPL 2 /* long */
+#define TYPQ 3 /* quad */
+#define TYPF 4 /* floating */
+#define TYPD 5 /* double floating */
+#define TYPNONE 6 /* when nothing */
+#define RELOC_PCREL 8 /* implicit argument to outrel; ==> PCREL */
+
+#define TYPMASK 7
-#define TYPMASK 7
+/*
+ * reference types for loader
+ */
+#define PCREL 1
+#define LEN1 2
+#define LEN2 4
+#define LEN4 6
+#define LEN8 8
-/* reference types for loader */
-#define PCREL 1
-#define LEN1 2
-#define LEN2 4
-#define LEN4 6
-#define LEN8 8
+extern int reflen[]; /* {LEN*+PCREL} ==> number of bytes */
+extern int lgreflen[]; /* {LEN*+PCREL} ==> lg number of bytes */
+extern int len124[]; /* {1,2,4,8} ==> {LEN1, LEN2, LEN4, LEN8} */
+extern char mod124[]; /* {1,2,4,8} ==> {bits to construct operands */
+extern int type_124[]; /* {1,2,4,8} ==> {TYPB, TYPW, TYPL, TYPQ} */
+extern int ty_NORELOC[]; /* {TYPB..TYPD} ==> {1 if relocation not OK */
+extern int ty_LEN[]; /* {TYPB..TYPD} ==> {LEN1..LEN8} */
+extern int ty_nbyte[]; /* {TYPB..TYPD} ==> {1,2,4,8} */
+extern int ty_nlg[]; /* {TYPB..TYPD} ==> lg{1,2,4,8} */
-#define TMPC 7
+#define TMPC 7
#define HW 01
#define FW 03
#define DW 07
-#define PAGRND 0x1FFL
+#ifdef UNIX
+# include <pagsiz.h>
+#endif UNIX
+
+#ifdef VMS
+# define PAGRND 0x1FFL
+#endif VMS
#define round(x,y) (((x)+(y)) & ~(y))
#define STABTYPS 0340
+#define STABFLAG 0200
+
+/*
+ * Follows are the definitions for the symbol table tags, which are
+ * all unsigned characters..
+ * High value tags are generated by the asembler for internal
+ * use.
+ * Low valued tags are the parser coded tokens the scanner returns.
+ * There are several pertinant bounds in this ordering:
+ * a) Symbols greater than JXQUESTIONABLE
+ * are used by the jxxx bumper, indicating that
+ * the symbol table entry is a jxxx entry
+ * that has yet to be bumped.
+ * b) Symbols greater than IGNOREBOUND are not
+ * bequeathed to the loader; they are truly
+ * for assembler internal use only.
+ * c) Symbols greater than OKTOBUMP represent
+ * indices into the program text that should
+ * be changed in preceeding jumps or aligns
+ * must get turned into their long form.
+ */
-struct symtab {
- char name[NCPS];
- char type;
- char tag;
- short index;
- long value;
- char ptype;
- char other;
- short desc;
+#define TAGMASK 0xFF
+
+# define JXACTIVE 0xFF /*jxxx size unknown*/
+# define JXNOTYET 0xFE /*jxxx size known, but not yet expanded*/
+# define JXALIGN 0xFD /*align jxxx entry*/
+# define JXINACTIVE 0xFC /*jxxx size known and expanded*/
+
+#define JXQUESTIONABLE 0xFB
+
+# define JXTUNNEL 0xFA /*jxxx that jumps to another*/
+# define OBSOLETE 0xF9 /*erroneously entered symbol*/
+
+#define IGNOREBOUND 0xF8 /*symbols greater than this are ignored*/
+# define STABFLOATING 0xF7
+# define LABELID 0xF6
+
+#define OKTOBUMP 0xF5
+# define STABFIXED 0xF4
+
+/*
+ * astoks.h contains reserved word codings the parser should
+ * know about
+ */
+#include "astoks.h"
+
+/*
+ * The structure for one symbol table entry.
+ * Symbol table entries are used for both user defined symbols,
+ * and symbol slots generated to create the jxxx jump from
+ * slots.
+ * Caution: the instructions are stored in a shorter version
+ * of the struct symtab, using all fields in sym_nm and
+ * tag. The fields used in sym_nm are carefully redeclared
+ * in struct Instab and struct instab (see below).
+ * If struct nlist gets changed, then Instab and instab may
+ * have to be changed.
+ */
+
+struct symtab{
+ struct nlist s_nm;
+ u_char s_tag; /* assembler tag */
+ u_char s_ptype; /* if tag == NAME */
+ u_char s_jxoveralign; /* if a JXXX, jumped over align */
+ short s_index; /* which segment */
+ struct symtab *s_dest; /* if JXXX, where going to */
+#ifdef DJXXX
+ short s_jxline; /* source line of the jump from */
+#endif
};
+/*
+ * Redefinitions of the fields in symtab for
+ * use when the symbol table entry marks a jxxx instruction.
+ */
+#define s_jxbump s_ptype /* tag == JX..., how far to expand */
+#define s_jxfear s_desc /* how far needs to be bumped */
+/*
+ * Redefinitions of fields in the struct nlist for symbols so that
+ * one saves typing, and so that they conform
+ * with the old naming conventions.
+ */
+#ifdef FLEXNAMES
+#define s_name s_nm.n_un.n_name /* name pointer */
+#define s_nmx s_nm.n_un.n_strx /* string table index */
+#else not FLEXNAMES
+#define s_name s_nm.n_name
+#endif
+#define s_type s_nm.n_type /* type of the symbol */
+#define s_other s_nm.n_other /* other information for sdb */
+#define s_desc s_nm.n_desc /* type descriptor */
+#define s_value s_nm.n_value /* value of the symbol, or sdb delta */
-struct instab {
- char name[NCPS];
- char opcode; /* must have same offset as symtab.type */
- char tag; /* yacc-coded nargs (INST0, ...) or token # (IALIGN, ...) */
- char nargs;
- char argtyp[6];
+struct instab{
+ struct nlist s_nm; /* instruction name, type (opcode) */
+ u_char s_tag;
+ char s_pad[3]; /* round to 20 bytes */
+};
+/*
+ * The fields nm.n_desc and nm.n_value total 6 bytes; this is
+ * just enough for the 6 bytes describing the argument types.
+ * We use a macro to define access to these 6 bytes, assuming that
+ * they are allocated adjacently.
+ * IF THE FORMAT OF STRUCT nlist CHANGES, THESE MAY HAVE TO BE CHANGED.
+ *
+ * Instab is cleverly declared to look very much like the combination of
+ * a struct symtab and a struct nlist.
+ */
+struct Instab{
+#ifdef FLEXNAMES
+ char *I_name;
+#else not FLEXNAMES
+ char I_name[NCPS];
+#endif
+ u_char I_opcode;
+ char I_nargs;
+ char I_args[6];
+ u_char I_s_tag;
+ char I_pad[3]; /* round to 20 bytes */
};
+/*
+ * Redefinitions of fields in the struct nlist for instructions so that
+ * one saves typing, and conforms to the old naming conventions
+ */
+#define i_opcode s_nm.n_type /* use the same field as symtab.type */
+#define i_nargs s_nm.n_other /* number of arguments */
+#define fetcharg(ptr, n) ((struct Instab *)ptr)->I_args[n]
-struct arg {
- char atype;
- char areg1;
- char areg2;
- struct exp *xp;
+struct arg { /*one argument to an instruction*/
+ char a_atype;
+ char a_areg1;
+ char a_areg2;
+ char a_dispsize; /*usually d124, unless have B^, etc*/
+ struct exp *a_xp;
};
struct exp {
- char xtype;
- char xloc;
- long xvalue;
- long yvalue; /* 2nd half of double floating */
- struct symtab *xname;
+ long e_xvalue; /* MUST be the first field (look at union Double) */
+ long e_yvalue; /* MUST be second field; least sig word of a double */
+ char e_xtype;
+ char e_xloc;
+ struct symtab *e_xname;
+};
+
+#define doub_MSW e_xvalue
+#define doub_LSW e_yvalue
+
+union Double {
+ struct{
+ long doub_MSW;
+ long doub_LSW;
+ } dis_dvalue;
+ double dvalue;
+};
+
+struct Quad {
+ long quad_low_long;
+ long quad_high_long;
};
-struct hdr {
- long magic;
- long tsize;
- long dsize;
- long bsize;
- long ssize;
- long entry;
- long trsize;
- long drsize;
+/*
+ * Magic layout macros
+ */
+#define MINBYTE -128
+#define MAXBYTE 127
+#define MINWORD -32768
+#define MAXWORD 32767
+
+#define LITFLTMASK 0x000043F0 /*really magic*/
+/*
+ * Is the floating point double word in xp a
+ * short literal floating point number?
+ */
+#define slitflt(xp) \
+ ( (xp->doub_LSW == 0) \
+ && ( (xp->doub_MSW & LITFLTMASK) \
+ == xp->doub_MSW) )
+/*
+ * If it is a slitflt, then extract the 6 interesting bits
+ */
+#define extlitflt(xp) \
+ xp->doub_MSW >> 4
+
+ extern struct arg arglist[NARG]; /*building operands in instructions*/
+ extern struct exp explist[NEXP]; /*building up a list of expressions*/
+ extern struct exp *xp; /*current free expression*/
+ /*
+ * Communication between the scanner and the jxxx handlers.
+ * lastnam: the last name seen on the input
+ * lastjxxx: pointer to the last symbol table entry for
+ * a jump from
+ */
+ extern struct symtab *lastnam;
+ extern struct symtab *lastjxxx;
+
+#ifdef VMS
+ extern char *vms_obj_ptr; /* object buffer pointer */
+ extern char sobuf[]; /* object buffer */
+ extern int objfil; /* VMS object file descriptor */
+#endif VMS
+
+ /*
+ * Lgensym is used to make up funny names for local labels.
+ * lgensym[i] is the current funny number to put after
+ * references to if, lgensym[i]-1 is for ib.
+ * genref[i] is set when the label is referenced before
+ * it is defined (i.e. 2f) so that we can be sure these
+ * labels are always defined to avoid weird diagnostics
+ * from the loader later.
+ */
+ extern int lgensym[10];
+ extern char genref[10];
+
+ extern char tmpn1[TNAMESIZE]; /* Interpass temporary */
+ extern struct exp *dotp; /* the current dot location */
+ extern int loctr;
+
+ extern struct exec hdr; /* a.out header */
+ extern u_long tsize; /* total text size */
+ extern u_long dsize; /* total data size */
+ extern u_long trsize; /* total text relocation size */
+ extern u_long drsize; /* total data relocation size */
+ extern u_long datbase; /* base of the data segment */
+ /*
+ * Bitoff and bitfield keep track of the packing into
+ * bytes mandated by the expression syntax <expr> ':' <expr>
+ */
+ extern int bitoff;
+ extern long bitfield;
+
+ /*
+ * The lexical analyzer builds up symbols in yytext. Lookup
+ * expects its argument in this buffer
+ */
+ extern char yytext[NCPS+2]; /* text buffer for lexical */
+ /*
+ * Variables to manage the input assembler source file
+ */
+ extern int lineno; /*the line number*/
+ extern char *dotsname; /*the name of the as source*/
+
+ extern FILE *tmpfil; /* interpass communication*/
+
+ extern int passno; /* 1 or 2 */
+
+ extern int anyerrs; /*errors assembling arguments*/
+ extern int silent; /*don't mention the errors*/
+ extern int savelabels; /*save labels in a.out*/
+ extern int orgwarn; /* questionable origin ? */
+ extern int useVM; /*use virtual memory temp file*/
+ extern int jxxxJUMP; /*use jmp instead of brw for jxxx */
+ extern int readonlydata; /*initialized data into text space*/
+#ifdef DEBUG
+ extern int debug;
+ extern int toktrace;
+#endif
+ /*
+ * Information about the instructions
+ */
+ extern struct instab *itab[NINST]; /*maps opcodes to instructions*/
+ extern readonly struct Instab instab[];
+
+ extern int curlen; /*current literal storage size*/
+ extern int d124; /*current pointer storage size*/
+
+ struct symtab **lookup(); /*argument in yytext*/
+ struct symtab *symalloc();
+
+#define outb(val) {dotp->e_xvalue++; if (passno==2) bputc((val), (txtfil));}
+
+#define outs(cp, lg) dotp->e_xvalue += (lg); if (passno == 2) bwrite((cp), (lg), (txtfil))
+
+/*
+ * Most of the time, the argument to flushfield is a power of two constant,
+ * the calculations involving it can be optimized to shifts.
+ */
+#define flushfield(n) if (bitoff != 0) Flushfield( ( (bitoff+n-1) /n ) * n)
+
+/*
+ * The biobuf structure and associated routines are used to write
+ * into one file at several places concurrently. Calling bopen
+ * with a biobuf structure sets it up to write ``biofd'' starting
+ * at the specified offset. You can then use ``bwrite'' and/or ``bputc''
+ * to stuff characters in the stream, much like ``fwrite'' and ``fputc''.
+ * Calling bflush drains all the buffers and MUST be done before exit.
+ */
+struct biobuf {
+ short b_nleft; /* Number free spaces left in b_buf */
+/* Initialize to be less than BUFSIZ initially, to boundary align in file */
+ char *b_ptr; /* Next place to stuff characters */
+ char b_buf[BUFSIZ]; /* The buffer itself */
+ off_t b_off; /* Current file offset */
+ struct biobuf *b_link; /* Link in chain for bflush() */
};
+#define bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \
+ : bflushc(b, c))
+#define BFILE struct biobuf
+
+ extern BFILE *biobufs; /* head of the block I/O buffer chain */
+ extern int biofd; /* file descriptor for block I/O file */
+ extern off_t boffset; /* physical position in logical file */
-struct symtab *symtab;
-struct symtab *hshtab[NHASH];
-struct arg arglist[6];
-struct exp explist[20];
-extern int lineno;
-extern int hshused;
-extern int usrname;
-extern int lclname;
-extern struct symtab *nextsym;
-extern struct exp usedot[NLOC+NLOC];
-extern FILE *usefile[NLOC+NLOC];
-extern FILE *rusefile[NLOC+NLOC];
-extern char *tmpn2;
-extern char *tmpn3;
-extern struct exp *dotp;
-extern int loctr;
-extern long tsize;
-extern long dsize;
-extern long datbase;
-extern int bitoff;
-extern long bitfield;
-extern char yytext[NCPS+2];
-extern FILE *txtfil;
-extern FILE *tmpfil;
-extern FILE *relfil;
-extern int passno;
-extern int argcnt;
-extern int anyerrs;
-extern int *brptr;
-struct instab *itab[NINST];
-struct instab instab[];
-int curlen;
-int gindex;
-int orgwarn;
-struct symtab **lookup();
-struct exp *combine();
+ /*
+ * For each of the named .text .data segments
+ * (introduced by .text <expr>), we maintain
+ * the current value of the dot, and the BFILE where
+ * the information for each of the segments is placed
+ * during the second pass.
+ */
+ extern struct exp usedot[NLOC + NLOC];
+ extern BFILE *usefile[NLOC + NLOC];
+ extern BFILE *txtfil;/* file for text and data: into usefile */
+ /*
+ * Relocation information for each segment is accumulated
+ * seperately from the others. Writing the relocation
+ * information is logically viewed as writing to one
+ * relocation saving file for each segment; physically
+ * we have a bunch of buffers allocated internally that
+ * contain the relocation information.
+ */
+ struct relbufdesc *rusefile[NLOC + NLOC];
+ struct relbufdesc *relfil;