Initial revision
This commit is contained in:
parent
3e78acff56
commit
28be8af452
537
util/ass/ass00.c
Normal file
537
util/ass/ass00.c
Normal file
|
@ -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 ; argno<argc ; argno++ ) {
|
||||
if ( argv[argno][0] == '-' && LC(argv[argno][1]) == 's') {
|
||||
getsizes(&argv[argno][2]);
|
||||
break ;
|
||||
}
|
||||
}
|
||||
/* A piece of the interpreter's stack frame is used as
|
||||
free area initially */
|
||||
freearea( (area_t) workspace, (unsigned) sizeof workspace ) ;
|
||||
getcore();
|
||||
init_files();
|
||||
init_vars();
|
||||
while ( --argc )
|
||||
argument(*++argv);
|
||||
finish_up();
|
||||
exit(nerrors!=0);
|
||||
}
|
||||
|
||||
getcore() {
|
||||
register size_t *p;
|
||||
size_t bytes;
|
||||
register unsigned n ;
|
||||
register char *base ;
|
||||
|
||||
/*
|
||||
* xglobs[] should be located in front of mglobs[], see upd_reloc()
|
||||
*/
|
||||
|
||||
p = oursize; n = 0;
|
||||
n += (bytes.n_glab = p->n_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(inpoff<libeof)
|
||||
get8();
|
||||
if(odd(libeof)) /* archive entries are evensized */
|
||||
if (fgetc(ifile) == EOF) /* except maybe the last one */
|
||||
;
|
||||
}
|
||||
|
||||
init_vars() {
|
||||
|
||||
/*
|
||||
* A small collection of variables is initialized.
|
||||
* This occurs only for those that couldn't be initialized
|
||||
* at compile-time.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
init_files() {
|
||||
|
||||
/*
|
||||
* The temporary files on which text and data are kept
|
||||
* during assembly are set up here.
|
||||
*/
|
||||
#ifdef CPM
|
||||
unlink("????????.$$$");
|
||||
tfile=fopen("TFILE.$$$", "w");
|
||||
dfile=fopen("DFILE.$$$", "w");
|
||||
rtfile=fopen("RTFILE.$$$", "w");
|
||||
rdfile=fopen("RDFILE.$$$", "w");
|
||||
#else
|
||||
/*
|
||||
* The function tmpfil() returns a file-descriptor
|
||||
* of a file that is valid for reading and writing.
|
||||
* It has the nice property of generating truly unique names.
|
||||
*/
|
||||
|
||||
tfile=fdopen(tmpfil(),"w") ;
|
||||
dfile=fdopen(tmpfil(),"w") ;
|
||||
rtfile=fdopen(tmpfil(),"w") ;
|
||||
rdfile=fdopen(tmpfil(),"w") ;
|
||||
#endif
|
||||
}
|
||||
|
||||
initproc() {
|
||||
|
||||
/*
|
||||
* Called at the start of assembly of every procedure.
|
||||
*/
|
||||
|
||||
stat_t *prevstate ;
|
||||
|
||||
prevstate= pst_cast getarea(sizeof pstate) ;
|
||||
*prevstate= pstate ;
|
||||
pstate.s_prevstat= prevstate ;
|
||||
pstate.s_curpro= prp_cast 0 ;
|
||||
pstate.s_fline= lnp_cast 0 ;
|
||||
pstate.s_fdata= l_data ;
|
||||
pstate.s_locl = (locl_t (*)[])
|
||||
getarea(LOCLABSIZE * sizeof (*(pstate.s_locl))[0]);
|
||||
zero(chp_cast pstate.s_locl,
|
||||
LOCLABSIZE * (unsigned) sizeof (*(pstate.s_locl))[0]);
|
||||
if ( memflg>2 ) 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; p<limit; p++) {
|
||||
if (p->p_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; p<limit; p++) {
|
||||
p->p_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);
|
||||
}
|
246
util/ass/ass00.h
Normal file
246
util/ass/ass00.h
Normal file
|
@ -0,0 +1,246 @@
|
|||
#include <stdio.h>
|
||||
#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 */
|
||||
};
|
Loading…
Reference in a new issue