From: keie Date: Thu, 12 Jul 1984 12:48:33 +0000 (+0000) Subject: Initial revision X-Git-Tag: release-5-5~6216 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=28be8af452a145cf414bc6ed664ff88812df93c6;p=ack.git Initial revision --- diff --git a/util/ass/ass00.c b/util/ass/ass00.c new file mode 100644 index 000000000..3234b1e24 --- /dev/null +++ b/util/ass/ass00.c @@ -0,0 +1,537 @@ +#include "ass00.h" +#include "assex.h" + +/* + * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. + * + * This product is part of the Amsterdam Compiler Kit. + * + * Permission to use, sell, duplicate or disclose this software must be + * obtained in writing. Requests for such permissions may be sent to + * + * Dr. Andrew S. Tanenbaum + * Wiskundig Seminarium + * Vrije Universiteit + * Postbox 7161 + * 1007 MC Amsterdam + * The Netherlands + * + */ + +/* +** Main routine of EM1-assembler/loader +*/ + +main(argc, argv) + int argc; + char **argv; +{ + /* + * Usage: ass [-[d][p][m][u]] [-s(s/m/l)] [ [file] [flag] ] ... + * The d flag can be repeated several times, resulting in more + * debugging information. + */ +#ifdef EM_WSIZE + char workspace[2000] ; +#else + char workspace[6000] ; +#endif + register char *cp ; + register int argno ; + + progname = argv[0]; + for ( cp=argv[0] ; *cp ; ) if ( *cp++ == '/' ) progname= cp; + for ( argno=1 ; argnon_glab * (sizeof *xglobs)); + n += (bytes.n_mlab = p->n_mlab * (sizeof *mglobs)); + n += (bytes.n_mproc = p->n_mproc * (sizeof *mprocs)); + n += (bytes.n_xproc = p->n_xproc * (sizeof *xprocs)); + n += (bytes.n_proc = p->n_proc * (sizeof *proctab)); + base = getarea(n); + zero(base,n); + xglobs = gbp_cast base; base += bytes.n_glab; + mglobs = gbp_cast base; base += bytes.n_mlab; + mprocs = prp_cast base; base += bytes.n_mproc; + xprocs = prp_cast base; base += bytes.n_xproc; + proctab = ptp_cast base; base += bytes.n_proc; +} + +getsizes(str) char *str; { + + /* + * accepts -ss (small), -sm (medium), -sl (large) + */ + + switch(LC(*str)) { + default:error("bad size option %s",str); + case 's': oursize = &sizes[0]; break; + case 'm': oursize = &sizes[1]; break; + case 'l': oursize = &sizes[2]; break; + } +} + +char oflag; + +argument(arg) char *arg; { + register w; + + /* + * This routine decides what to do with each argument. + * It recognises flags and modules. + * Furthermore, it knows a library when it sees it and + * call archive() to split it apart. + */ + + if (oflag) { + eout = arg; + oflag=0; + return; + } + if(*arg == '-') { + flags(arg); + return; + } + curfile = arg; /* for error messages etc. */ + if ((ifile = fopen(arg,"r")) == NULL) { + error("can't open %s",arg); + return; + } + inpoff = 2; + if ((w = (unsigned)get16()) == sp_magic ) + read_compact(); + else if (w == ARMAG) { + archmode = TRUE; + archive(); + archmode = FALSE; + } else + error("%s: bad format",arg); + if (fclose(ifile) == EOF) + ; +} + +/* +** process flag arguments +*/ + +static int memflg ; + +flags(arg) + char *arg; +{ + register char *argp; + register on; + + argp = arg; + while (*++argp) + { + switch(LC(*argp)) + { + case 'd': d_flag++;break; + case 'r': r_flag++;break; + case 's': return ; /* s-flag is already scanned */ +#ifdef MEMUSE + case 'm': memflg++ ; break ; +#endif + case 'p': ++procflag;break; +#ifdef DUMP + case 'u': ++c_flag;break; +#endif + case 'o': ++oflag; break; + case 'w': ++wflag; break; +#ifdef JOHAN + case 'j': ++jflag; break; +#endif + case '-': + case '+': + on = (*argp == '+'); + while (*++argp) switch(LC(*argp)) { + case 't': if (on) intflags |= 01; + else intflags &= ~01; + break; + case 'p': if (on) intflags |= 02; + else intflags &= ~02; + break; + case 'f': if (on) intflags |= 04; + else intflags &= ~04; + break; + case 'c': if (on) intflags |= 010; + else intflags &= ~010; + case 'e': if (on) intflags |= 040; + else intflags &= ~040; + break; + default: + error("bad interpreter option %s",argp); + } + --argp; + break; + default: + error("bad flag %s",argp); + break; + } + } +} + +do_proc() { + /* One procedure has been read and will be processed. + * + * NOTE: The numbers of the passes, 1 3 4 and 5, are a remainder + * of ancient times. + */ + + dump(1); if ( memflg>2 )memuse(); + pass_3(); dump(3); + pass_4(); dump(4); + pass_5(); if ( memflg>2 ) memuse() ; + endproc(); if ( memflg>1 ) memuse() ; +} + +archive() { + register i; + register char *p; + + /* + * Read a library. + * The format of the libary used is that of a UNIX/V7(PDP)-archive. + * + * NOTE: If it was allowed for an archive to contain + * obligatory modules as well as optionals, + * it would not be possible to speed up things a bit + * by stopping when all references are resolved. + * This is the only reason. + */ + + for(;;) { + if (unresolved == 0) { /* no use for this library anymore */ + return; + } + p = chp_cast &archhdr; + if ((i = fgetc(ifile))==EOF ) { + return; + } + *p++ = i; + for (i=1;i< sizeof archhdr.ar_name; i++) + *p++ = get8(); + for (i=0;i<8;i++) get8(); + archhdr.ar_size= ((long)get16()<<16) ; + archhdr.ar_size+= (unsigned)get16(); + inpoff = 0; libeof = archhdr.ar_size; + /* + * UNIX archiveheader is read now, now process the contents + * of it. Note that recursive archives are not implemented. + * + * The variable libeof is used by get8() to check + * whether or not we try to pass the library-boundary. + */ + if ( get16() == sp_magic ) { + read_compact(); + } else + error("bad archive entry"); + skipentry(); + libeof = 0; + } /* up to the next entry */ +} + +skipentry() { + + /* + * for some reason the rest of this library entry needs to be + * skipped. Do that now. + */ + while(inpoff2 ) memuse() ; +} + +endproc() { + /* Throw the contents of the line and local label table away */ + register line_t *lnp1; + register locl_t *lbhead,*lbp,*lbp_next; + register kind ; + register stat_t *prevstate; + + while ( lnp1= pstate.s_fline ) { + pstate.s_fline= lnp1->l_next ; + kind= lnp1->type1 ; + if ( kind>VALLOW ) kind=VALLOW ; + freearea((area_t)lnp1,(unsigned)linesize[kind]) ; + } + prevstate= pstate.s_prevstat ; + if ( prevstate!= pst_cast 0 ) { + for ( lbhead= *pstate.s_locl; + lbhead<&(*pstate.s_locl)[LOCLABSIZE] ; lbhead++ ) { + for ( lbp=lbhead; lbp!= lbp_cast 0; lbp= lbp_next ) { + lbp_next= lbp->l_chain; + freearea((area_t)lbp,(unsigned)sizeof *lbp) ; + } + } + pstate= *prevstate ; + freearea((area_t)prevstate,(unsigned)sizeof *prevstate) ; + } +} + +init_module() { + + /* + * Called at the start of every module. + */ + + holbase = 0; + line_num = 1; + mod_sizes = 0; +} + +end_module() { + + /* + * Finish a module. + * Work to be done is mainly forgetting of local names, + * and remembering of those that will live during assembly. + */ + + align(wordsize) ; + setmode(DATA_NUL); + dump(100); + enmd_pro(); + enmd_glo(); + if ( memflg ) memuse() ; +} + +enmd_pro() { + register proc_t *p,*limit; + + /* + * Check that all local procedures have been defined, + * and forget them immediately thereafter. + */ + + limit = &mprocs[oursize->n_mproc]; + for (p=mprocs; pp_name[0] == 0) + continue; + if ((p->p_status&DEF)==0) + error("undefined local procedure '%s'",p->p_name); + } + zero(chp_cast mprocs,(limit-mprocs)* (unsigned)sizeof *mprocs); + + /* Clobber all flags indicating that external procedures + * were used in this module. + */ + + limit = &xprocs[oursize->n_xproc]; + for (p=xprocs; pp_status &= ~EXT ; + } +} + +enmd_glo() { + register glob_t *mg,*xg,*limit; + + /* + * Tougher then enmd_pro(). + * Check all the symbols used in this module that are + * not to be forgotten immediately. + * A difficulty arises here: + * In the tables textreloc[] and datareloc[] + * pointers are used to identify the symbols concerned. + * These pointers point into mglobs[]. + * Since at the end of assembly only the value of xglobs[] + * is defined, these pointers have to be changed. + * upd_reloc() takes care of this. + */ + + limit = &mglobs[oursize->n_mlab]; + for ( mg = mglobs; mg < limit; mg++) { + if (mg->g_name[0] == 0) + continue; + if ((mg->g_status&(EXT|DEF))==0) + error("undefined local symbol '%s'",glostring(mg)); + if ((mg->g_status&EXT)==0) + continue; + xg = xglolookup(mg->g_name,ENTERING); + switch(xg->g_status&(EXT|DEF)) { + case 0: /* new symbol */ + if((mg->g_status&DEF)==0) + ++unresolved; + break; + case EXT: /* already used but not defined */ + if(mg->g_status&DEF) { + --unresolved; + } + break; + } + xg->g_status |= mg->g_status; + if (mg->g_status&DEF) + xg->g_val.g_addr = mg->g_val.g_addr; + else + mg->g_val.g_gp = xg; /* used by upd_reloc */ + } /* up to the next symbol */ + upd_reloc(); + zero(chp_cast mglobs,(limit-mglobs)*(unsigned) sizeof *mglobs); +} + +finish_up() +{ + /* + * Almost done. Check for unresolved references, + * make the e.out file and stop. + */ + +#ifdef JOHAN + if ( jflag ) return ; +#endif +#ifdef DUMP + c_print(); +#endif + check_def(); + if ( nerrors==0 ) copyout(); +} + +#ifdef DUMP +c_print() { + if ( ! c_flag ) return ; + c_dprint("primary",opcnt1) ; + c_dprint("secondary",opcnt2) ; + c_dprint("extra long",opcnt3) ; +} + +c_dprint(str,cnt) char *str,*cnt ; { + register int first,curr ; + printf("unused %s opcodes\n",str) ; + for ( first= -1 , curr=0 ; curr<=256 ; curr++ ) { + if ( curr==256 || cnt[curr] ) { + if ( first!= -1 ) { + if ( first+1 == curr ) { + printf("%3d\n",first ) ; + } else { + printf("%3d..%3d\n",first,curr-1) ; + } + first= -1 ; + } + } else { + if ( first== -1 ) first=curr ; + } + } +} +#endif + +check_def() { + register proc_t *p; + register glob_t *g; + register count; + + /* + * Check for unresolved references. + * NOTE: The occurring of unresolved references is not fatal, + * although the use of the e.out file after this + * occurring must be strongly discouraged. + * Every use of the symbols concerned is undefined. + */ + + if (unresolved) { + printf("Unresolved references\n Procedures:\n"); + count = oursize->n_xproc; + for (p = xprocs; count--; p++) + if (p->p_name[0] && (p->p_status&DEF)==0) + printf(" %s\n",p->p_name); + printf(" Data:\n"); + count = oursize->n_glab; + for (g = xglobs; count--; g++) + if (g->g_name[0] && (g->g_status&DEF)==0) + printf(" %s\n",glostring(g)); + } +} + +ertrap() { /* trap routine to drain input in case of compile errors */ + + if (fileno(ifile)== 0) + while (fgetc(ifile) != EOF) + ; + exit(1); +} diff --git a/util/ass/ass00.h b/util/ass/ass00.h new file mode 100644 index 000000000..375ba9751 --- /dev/null +++ b/util/ass/ass00.h @@ -0,0 +1,246 @@ +#include +#include "../../h/em_spec.h" +#include "../../h/as_spec.h" +#include "../../h/em_flag.h" +#include "../../h/arch.h" +#include "../../h/local.h" + +/* + * compile time options + */ + +/* #define DUMP 1 /* dump between passes */ +/* #define TIMING 1 /* some timing measurements */ +/* #define JOHAN 1 /* dump the loaded instructions */ +/* #define MEMUSE 1 /* print memory usage statistics */ + +#ifndef DUMP +#define dump(x) /* nothing */ +#endif + +#ifndef TIMING +#define timing() /* nothing */ +#endif + +#ifndef MEMUSE +#define memuse() /* nothing */ +#endif + +/* Used to clear the upper byte(s) of characters. + Not nessecary if your C-compiler does not sign-extend char's +*/ + +#ifdef CPM +# define LC(ch) ( ((ch)<'A' | (ch)>'Z' ) ? (ch) : ((ch)-('A'-'a'))) +#else +# define LC(ch) (ch) +#endif + +#define ctrunc(val) ( (val)&0377 ) + +#define odd(n) ((n)&1) /* Boolean odd function */ + +#define lnp_cast (line_t *) +#define gbp_cast (glob_t *) +#define lbp_cast (locl_t *) +#define prp_cast (proc_t *) +#define ptp_cast (ptab_t *) +#define rlp_cast (relc_t *) +#define pst_cast (stat_t *) +#define chp_cast (char *) +#define ipp_cast (int **) +#define iip_cast (int *) +#define int_cast (int ) + +typedef struct lines line_t; +typedef struct loc_label locl_t; +typedef struct glob_label glob_t; +typedef struct rel relc_t; +typedef struct procstat stat_t; +typedef struct sizes size_t; +typedef struct ar_hdr arch_t; +typedef struct procs proc_t; +typedef struct proctab ptab_t; +typedef char * area_t; +typedef long cons_t; + +typedef union { + cons_t ad_i; + locl_t *ad_lp; + glob_t *ad_gp; + proc_t *ad_pp; + struct sad_ln { + short ln_extra; + short ln_first; + } ad_ln ; + struct sad_df { + cons_t df_i; + glob_t *df_gp; + } ad_df; +} addr_u; + +typedef union { + cons_t rel_i; + locl_t *rel_lp; + glob_t *rel_gp; +} rel_u; + +#define FOFFSET long /* offset into file */ + +/* + * Global variables and definitions for EM1-assembler/loader + */ + +#define DEFINING 0 /* parameters for glolookup */ +#define OCCURRING 1 +#define INTERNING 2 +#define EXTERNING 3 +#define SEARCHING 4 +#define ENTERING 5 + +#define PRO_OCC 0 /* parameters for prolookup */ +#define PRO_DEF 1 +#define PRO_INT 2 +#define PRO_EXT 3 + +#define TRUE 1 +#define FALSE 0 + +#define IDLENGTH 8 /* length of glo's and pro's */ +#define MAXSTRING 200 /* Maximum string length accepted */ +#define LOCLABSIZE 128 /* size of local label hash table */ + /* may not be smaller */ +#define ABSSIZE 8 + +struct lines { + char instr_num; /* index into mnemon[] */ + char type1; /* see below */ + line_t *l_next; /* next in chain */ + char *opoff; /* pointer into opchoice[] */ + addr_u ad; /* depending on type, various pointers */ +}; + +/* contents of type1 */ +#define MISSING 0 /* no operand */ +#define CONST 1 /* ad contains operand */ +#define PROCNAME 2 /* ad contains struct procs pointer */ +#define GLOSYM 3 /* ad contains pointer into mproc[] */ +#define LOCSYM 4 /* ad contains pointer into locs[] */ +#define GLOOFF 5 /* ad contains CONST and GLOSYM in ad_df */ +#define LINES 6 /* Line number setting, only param of pseudo*/ +#define VALLOW 7 /* value's between LOW and HIGH are x-MID */ +#define VALMID 50 +#define VALHIGH 127 /* to avoid sign extension problems */ + +#define VAL1(x) ((x)-VALMID) + +/* Used to indicate a invalid contents of opoff */ +#define NO_OFF ((char *)-1) + +/* The structure containing procedure pertinent data */ +/* Used for environment stacking for nested PRO's */ + +struct procstat { + line_t *s_fline; /* points to first line of procedure */ + locl_t (*s_locl)[]; /* pointer to local labels */ + proc_t *s_curpro; /* identifies current procedure */ + relc_t *s_fdata; /* last datareloc before procedure */ + stat_t *s_prevstat; /* backward chain of nested procedures */ +} ; + +struct loc_label { + locl_t *l_chain; /* The next label with same low order bits */ + char l_hinum; /* high bits of number of label */ + char l_defined; /* see below */ + int l_min,l_max; /* boundaries of value */ +}; + +/* contents of l_defined */ +#define EMPTY 0 /* Empty slot */ +#define NO 1 /* not defined yet */ +#define YES 2 /* defined */ +#define SEEN 3 /* intermediate state */ +#define NOTPRESENT 4 /* Undefined and error message given */ + +struct glob_label { + char g_name[IDLENGTH+1]; /* name + null-byte */ + char g_status; /* see below */ + union { + cons_t g_addr; /* value if status&DEF */ + struct glob_label *g_gp; /* ref. to xglobs */ + } g_val ; +}; + +#define glostring(gl) ((gl)->g_name) + +/* contents of g_status */ +#define DEF 01 /* defined */ +#define OCC 02 /* used */ +#define EXT 04 /* external */ + +struct rel { /* for relocation tables */ + relc_t *r_next; /* chain */ + FOFFSET r_off; /* offset in text/data of word to relocate */ + rel_u r_val; /* constant or pointer to global symbol */ + int r_typ; /* different use in text or data */ +}; + +/* + * When used with textrelocation r_typ contains the flag bits as defined + * in ip_spec.h together with the RELMNS bit if r_val contains an integer + */ + +#define RELMNS 020000 /* indicates integer i.s.o. glob */ + +/* Contents of r_typ when used with data relocation */ +#define RELNULL 0 +#define RELGLO 1 +#define RELHEAD 2 +#define RELLOC 3 +#define RELADR 4 + +/* modes of data output */ +#define DATA_NUL 0 +#define DATA_REP 1 +#define DATA_CONST 2 +#define DATA_BSS 3 +#define DATA_DPTR 4 +#define DATA_IPTR 5 +#define DATA_ICON 6 +#define DATA_UCON 7 +#define DATA_FCON 8 +#define DATA_BYTES 9 + +/* name of procedure to be called first */ +#define MAIN "m_a_i_n" + +/* headers of datablocks written */ +#define HEADREP 0 +#define HEADBSS 1 +#define HEADBYTE 2 +#define HEADCONST 3 +#define HEADDPTR 4 +#define HEADIPTR 5 +#define HEADICON 6 +#define HEADUCON 7 +#define HEADFCON 8 + +#define NDEFAULT 3 /* number of different sizes available */ +struct sizes { + int n_mlab; /* # of global labels per module */ + int n_glab; /* # of extern global labels */ + int n_mproc; /* # of local procs per module */ + int n_xproc; /* # of external procs */ + int n_proc; /* total # of procedures */ +}; + +struct procs { /* format of mprocs[] and xprocs[] */ + char p_name[IDLENGTH+1]; /* name + 1 null-byte */ + char p_status; /* same bits as g_status except REL */ + int p_num; /* unique procedure descriptor */ +}; + +struct proctab { + cons_t pr_off; /* distance from pb */ + cons_t pr_loc; /* number of bytes locals */ +};