ack/util/ass/assci.c
keie fe922d190d String initializer handling is changed.
Strings are now considered to be sequences of xU1's.
No alignment is done before or after the string other than the
alignment done for names and segment type switches.
1984-07-30 14:42:33 +00:00

855 lines
17 KiB
C

/*
* (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
*
*/
#include "ass00.h"
#include "assex.h"
#include "../../h/em_mes.h"
#include "../../h/em_pseu.h"
#include "../../h/em_ptyp.h"
/*
* read compact code and fill in tables
*/
static int tabval;
static cons_t argval;
static int oksizes; /* MES EMX,.,. seen */
static enum m_type { CON, ROM, HOLBSS } memtype ;
static int valtype; /* Transfer of type information between
valsize, inpseudo and putval
*/
int table3(i) {
switch(i) {
case sp_ilb1:
tabval = get8();
break;
case sp_dlb1:
make_string(get8());
i= sp_dnam;
break;
case sp_dlb2:
tabval = get16();
if ( tabval<0 ) {
error("illegal data label .%d",tabval);
tabval=0 ;
}
make_string(tabval);
i= sp_dnam;
break;
case sp_cst2:
argval = get16();
break;
case sp_ilb2:
tabval = get16();
if ( tabval<0 ) {
error("illegal instruction label %d",tabval);
tabval=0 ;
}
i = sp_ilb1;
break;
case sp_cst4:
i = sp_cst2;
argval = get32();
break;
case sp_dnam:
case sp_pnam:
inident();
break ;
case sp_scon:
getstring() ;
break;
case sp_doff:
getarg(sym_ptyp);
getarg(cst_ptyp);
break;
case sp_icon:
case sp_ucon:
case sp_fcon:
getarg(cst_ptyp);
consiz = argval;
if ( consiz<wordsize ?
wordsize%consiz!=0 : consiz%wordsize!=0 ) {
fatal("illegal object size") ;
}
getstring();
break;
}
return(i);
}
int get16() {
register int l_byte, h_byte;
l_byte = get8();
h_byte = get8();
if ( h_byte>=128 ) h_byte -= 256 ;
return l_byte | (h_byte*256) ;
}
int getu16() {
register int l_byte, h_byte;
l_byte = get8();
h_byte = get8();
return l_byte | (h_byte*256) ;
}
cons_t get32() {
register cons_t l;
register int h_byte;
l = get8(); l |= (unsigned)get8()*256 ; l |= get8()*256L*256L ;
h_byte = get8() ;
if ( h_byte>=128 ) h_byte -= 256 ;
return l | (h_byte*256L*256*256L) ;
}
int table1() {
register i;
i = xget8();
if (i < sp_fmnem+sp_nmnem && i >= sp_fmnem) {
tabval = i-sp_fmnem;
return(sp_fmnem);
}
if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) {
tabval = i;
return(sp_fpseu);
}
if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) {
tabval = i - sp_filb0;
return(sp_ilb1);
}
return(table3(i));
}
int table2() {
register i;
i = get8();
if (i < sp_fcst0+sp_ncst0 && i >= sp_fcst0) {
argval = i - sp_zcst0;
return(sp_cst2);
}
return(table3(i));
}
int getarg(typset) {
register t,argtyp;
argtyp = t = table2();
t -= sp_fspec;
t = 1 << t;
if ((typset & t) == 0)
error("bad argument type %d",argtyp);
return(argtyp);
}
cons_t getint() {
getarg(cst_ptyp);
return(argval);
}
glob_t *getlab(status) {
getarg(sym_ptyp);
return(glo2lookup(string,status));
}
char *getdig(str,number) char *str; register unsigned number; {
register int remain;
remain= number%10;
number /= 10;
if ( number ) str= getdig(str,number) ;
*str++ = '0'+remain ;
return str ;
}
make_string(n) unsigned n ; {
string[0] = '.';
*getdig(&string[1],n)= 0;
}
getstring() {
register char *p;
register n;
getarg(cst_ptyp);
if ( argval < 0 || argval >= MAXSTRING-1 )
fatal("string/identifier too long");
strlngth = n = argval;
p = string;
while (--n >= 0)
*p++ = get8();
*p = 0 ;
}
inident() {
getstring();
string[IDLENGTH] = '\0';
}
char *inproname() {
getarg(ptyp(sp_pnam));
return(string);
}
int needed() {
register glob_t *g;
register proc_t *p;
for(;;){
switch ( table2() ) {
case sp_dnam :
if (g = xglolookup(string,SEARCHING)) {
if ((g->g_status&DEF) != 0)
continue ;
} else continue ;
break ;
case sp_pnam :
p = searchproc(string,xprocs,oursize->n_xproc);
if (p->p_name[0]) {
if ((p->p_status & DEF) != 0)
continue ;
} else continue ;
break ;
default :
error("Unexpected byte after ms_ext") ;
case sp_cend :
return FALSE ;
}
while ( table2()!=sp_cend ) ;
return TRUE ;
}
}
cons_t valsize() {
switch(valtype=table2()) { /* valtype is used by putval and inpseudo */
case sp_cst2:
return wordsize ;
case sp_ilb1:
case sp_dnam:
case sp_doff:
case sp_pnam:
return ptrsize ;
case sp_scon:
return strlngth ;
case sp_fcon:
case sp_icon:
case sp_ucon:
return consiz ;
case sp_cend:
return 0 ;
default:
fatal("value expected") ;
/* NOTREACHED */
}
}
newline(type) {
register line_t *n_lnp ;
if ( type>VALLOW ) type=VALLOW ;
n_lnp = lnp_cast getarea((unsigned)linesize[type]) ;
n_lnp->l_next = pstate.s_fline ;
pstate.s_fline = n_lnp ;
n_lnp->type1 = type ;
n_lnp->opoff = NO_OFF ;
}
read_compact() {
/*
* read module in compact EM1 code
*/
init_module();
pass = 1;
eof_seen = 0;
do {
compact_line() ;
line_num++;
} while (!eof_seen) ;
endproc() ; /* Throw away unwanted garbage */
if ( mod_sizes ) end_module();
/* mod_sizes is only false for rejected library modules */
}
int compact_line() {
register instr_no ;
/*
* read one "line" of compact code.
*/
curglosym=0;
switch (table1()) {
default:
fatal("unknown byte at start of \"line\""); /* NOTREACHED */
case EOF:
eof_seen++ ;
while ( pstate.s_prevstat != pst_cast 0 ) {
error("missing end") ; do_proc() ;
}
return ;
case sp_fmnem:
if ( pstate.s_curpro == prp_cast 0) {
error("instruction outside procedure");
}
instr_no = tabval;
if ( (em_flag[instr_no]&EM_PAR)==PAR_NO ) {
newline(MISSING) ;
pstate.s_fline->instr_num= instr_no ;
return ;
}
/*
* This instruction should have an opcode, so read it after
* this switch.
*/
break;
case sp_dnam:
chkstart() ;
align(wordsize) ;
curglosym = glo2lookup(string,DEFINING);
curglosym->g_val.g_addr = databytes;
lastglosym = curglosym;
setline() ; line_num++ ;
if (table1() != sp_fpseu)
fatal("no pseudo after data label");
case sp_fpseu:
inpseudo(tabval);
setline() ;
return ;
case sp_ilb1:
newline(LOCSYM) ;
pstate.s_fline->ad.ad_lp = loclookup(tabval,DEFINING);
pstate.s_fline->instr_num = sp_ilb1;
return ;
}
/*
* Now process argument
*/
switch(table2()) {
default:
fatal("unknown byte at start of argument"); /*NOTREACHED*/
case sp_cst2:
if ( (em_flag[instr_no]&EM_PAR)==PAR_B ) {
/* value indicates a label */
newline(LOCSYM) ;
pstate.s_fline->ad.ad_lp=
loclookup((int)argval,OCCURRING) ;
} else {
if ( argval>=VAL1(VALLOW) && argval<=VAL1(VALHIGH)) {
newline(VALLOW) ;
pstate.s_fline->type1 = argval+VALMID ;
} else {
newline(CONST) ;
pstate.s_fline->ad.ad_i = argval;
pstate.s_fline->type1 = CONST;
}
}
break;
case sp_ilb1:
newline(LOCSYM) ;
pstate.s_fline->ad.ad_lp = loclookup(tabval,OCCURRING);
break;
case sp_dnam:
newline(GLOSYM) ;
pstate.s_fline->ad.ad_gp = glo2lookup(string,OCCURRING);
break;
case sp_pnam:
newline(PROCNAME) ;
pstate.s_fline->ad.ad_pp=prolookup(string,PRO_OCC);
break;
case sp_cend:
if ( (em_flag[instr_no]&EM_PAR)!=PAR_W ) {
fatal("missing operand") ;
}
newline(MISSING) ;
break ;
case sp_doff:
newline(GLOOFF) ;
pstate.s_fline->ad.ad_df.df_i = argval ;
pstate.s_fline->ad.ad_df.df_gp= glo2lookup(string,OCCURRING) ;
break ;
}
pstate.s_fline->instr_num= instr_no ;
return ;
}
inpseudo(instr_no) {
cons_t cst;
register proc_t *prptr;
cons_t objsize;
cons_t par1,par2;
register char *pars;
/*
* get operands of pseudo (if needed) and process it.
*/
switch ( ctrunc(instr_no) ) {
case ps_bss:
chkstart() ;
typealign(HOLBSS) ;
cst = getint(); /* number of bytes */
extbss(cst);
break;
case ps_hol:
chkstart() ;
typealign(HOLBSS) ;
holsize=getint();
holbase=databytes;
extbss(holsize);
break;
case ps_rom:
case ps_con:
chkstart() ;
typealign( ctrunc(instr_no)==ps_rom ? ROM : CON ) ;
while( (objsize=valsize())!=0 ) {
if ( valtype!=sp_scon) sizealign(objsize) ;
putval() ;
databytes+=objsize ;
}
break;
case ps_end:
prptr= pstate.s_curpro ;
if ( prptr == prp_cast 0 ) fatal("unexpected END") ;
proctab[prptr->p_num].pr_off = textbytes;
if (procflag) {
printf("%6lu\t%6lo\t%5d\t%-12s\t%s",
textbytes,textbytes,
prptr->p_num,prptr->p_name,curfile);
if (archmode)
printf("(%.14s)",archhdr.ar_name);
printf("\n");
}
par2 = proctab[prptr->p_num].pr_loc ;
if ( getarg(cst_ptyp|ptyp(sp_cend))==sp_cend ) {
if ( par2 == -1 ) {
fatal("size of local area unspecified") ;
}
} else {
if ( par2 != -1 && argval!=par2 ) {
fatal("inconsistent local area size") ;
}
proctab[prptr->p_num].pr_loc = argval ;
}
setline();
do_proc();
break;
case ps_mes:
switch( int_cast getint() ) {
case ms_err:
error("module with error") ; ertrap();
/* NOTREACHED */
case ms_emx:
if ( oksizes ) {
if ( wordsize!=getint() ) {
fatal("Inconsistent word size");
}
if ( ptrsize!=getint() ) {
fatal("Inconsistent pointer size");
}
} else {
oksizes++ ;
wordsize=getint();ptrsize=getint();
if ( wordsize!=2 && wordsize!=4 ) {
fatal("Illegal word size");
}
if ( ptrsize!=2 && ptrsize!=4 ) {
fatal("Illegal pointer size");
}
setsizes() ;
}
++mod_sizes ;
break;
case ms_src:
break;
case ms_flt:
intflags |= 020; break; /*floats used*/
case ms_ext:
if ( !needed() ) {
eof_seen++ ;
}
if ( line_num!=1 ) {
werror("mes ms_ext must be first pseudo") ;
}
return ;
}
while (table2() != sp_cend)
;
break;
case ps_exc:
par1 = getint();
par2 = getint();
if (par1 == 0 || par2 == 0)
break;
exchange((int)par2,(int)par1) ;
break;
case ps_exa:
getlab(EXTERNING);
break;
case ps_ina:
getlab(INTERNING);
break;
case ps_pro:
chkstart() ;
initproc();
pars = inproname();
if ( getarg(cst_ptyp|ptyp(sp_cend))==sp_cend ) {
par2 = -1 ;
} else {
par2 = argval ;
}
prptr = prolookup(pars,PRO_DEF);
proctab[prptr->p_num].pr_loc = par2;
pstate.s_curpro=prptr;
break;
case ps_inp:
prptr = prolookup(inproname(),PRO_INT);
break;
case ps_exp:
prptr = prolookup(inproname(),PRO_EXT);
break;
default:
fatal("unknown pseudo");
}
if ( !mod_sizes ) fatal("Missing size specification");
if ( databytes>maxadr ) error("Maximum data area size exceeded") ;
}
setline() {
/* Get line numbers correct */
if ( pstate.s_fline &&
ctrunc(pstate.s_fline->instr_num) == sp_fpseu ) {
/* Already one present */
pstate.s_fline->ad.ad_ln.ln_extra++ ;
} else {
newline(LINES) ;
pstate.s_fline->instr_num= sp_fpseu ;
pstate.s_fline->ad.ad_ln.ln_extra= 0 ;
pstate.s_fline->ad.ad_ln.ln_first= line_num ;
}
}
cons_t maxval(bits) int bits ; {
/* find the maximum positive value,
* fitting in 'bits' bits AND
* fitting in a 'cons_t' .
*/
cons_t val ;
val=1 ;
while ( bits-- ) {
val<<= 1 ;
if ( val<0 ) return ~val ;
}
return val-1 ;
}
setsizes() {
maxadr = maxval(8*ptrsize) ;
maxint = maxval(8*wordsize-1) ;
maxunsig = maxval(8*wordsize) ;
maxdint = maxval(2*8*wordsize-1) ;
maxdunsig = maxval(2*8*wordsize) ;
}
exchange(p1,p2) {
int size, line ;
int l_of_p1, l_of_p2, l_of_before ;
register line_t *t_lnp,*a_lnp, *b_lnp ;
/* Since the lines are linked backwards it is easy
* to count the number of lines backwards.
* Each instr counts for 1, each pseudo for ln_extra + 1.
* The line numbers in error messages etc. are INCORRECT
* If exc's are used.
*/
line= line_num ; size=0 ;
newline(LINES) ; a_lnp=pstate.s_fline ;
a_lnp->instr_num= sp_fpseu ;
a_lnp->ad.ad_ln.ln_first= line ;
a_lnp->ad.ad_ln.ln_extra= -1 ;
for ( ; a_lnp ; a_lnp= a_lnp->l_next ) {
line-- ;
switch ( ctrunc(a_lnp->instr_num) ) {
case sp_fpseu :
line= a_lnp->ad.ad_ln.ln_first ;
size += a_lnp->ad.ad_ln.ln_extra ;
break ;
case sp_ilb1 :
a_lnp->ad.ad_lp->l_min -= p2 ;
break ;
}
size++ ;
if ( size>=p1 ) break ;
}
if ( ( size-= p1 )>0 ) {
if ( ctrunc(a_lnp->instr_num) !=sp_fpseu ) {
fatal("EXC inconsistency") ;
}
doinsert(a_lnp,line,size-1) ;
a_lnp->ad.ad_ln.ln_extra -= size ;
size=0 ;
} else {
if( a_lnp) doinsert(a_lnp,line,-1) ;
}
b_lnp= a_lnp ;
while ( b_lnp ) {
b_lnp= b_lnp->l_next ;
line-- ;
switch ( ctrunc(b_lnp->instr_num) ) {
case sp_fpseu :
size += b_lnp->ad.ad_ln.ln_extra ;
line = b_lnp->ad.ad_ln.ln_first ;
break ;
case sp_ilb1 :
b_lnp->ad.ad_lp->l_min += p1 ;
break ;
}
size++ ;
if ( size>=p2 ) break ;
}
if ( !b_lnp ) { /* if a_lnp==0, so is b_lnp */
fatal("Cannot perform exchange") ;
}
if ( ( size-= p2 )>0 ) {
if ( ctrunc(b_lnp->instr_num) !=sp_fpseu ) {
fatal("EXC inconsistency") ;
}
doinsert(b_lnp,line,size-1) ;
b_lnp->ad.ad_ln.ln_extra -= size ;
} else {
doinsert(b_lnp,line,-1) ;
}
t_lnp = b_lnp->l_next ;
b_lnp->l_next = pstate.s_fline ;
pstate.s_fline= a_lnp->l_next ;
a_lnp->l_next=t_lnp ;
}
doinsert(lnp,first,extra) line_t *lnp ; {
/* Beware : s_fline will be clobbered and restored */
register line_t *t_lnp ;
t_lnp= pstate.s_fline;
pstate.s_fline= lnp->l_next ;
newline(LINES) ;
pstate.s_fline->instr_num= sp_fpseu ;
pstate.s_fline->ad.ad_ln.ln_first= first ;
pstate.s_fline->ad.ad_ln.ln_extra= extra ;
lnp->l_next= pstate.s_fline ;
pstate.s_fline= t_lnp; /* restore */
}
putval() {
switch(valtype){
case sp_cst2:
extconst(argval);
return ;
case sp_ilb1:
extloc(loclookup(tabval,OCCURRING));
return ;
case sp_dnam:
extglob(glo2lookup(string,OCCURRING),(cons_t)0);
return ;
case sp_doff:
extglob(glo2lookup(string,OCCURRING),argval);
return ;
case sp_pnam:
extpro(prolookup(string,PRO_OCC));
return ;
case sp_scon:
extstring() ;
return ;
case sp_fcon:
extxcon(DATA_FCON) ;
return ;
case sp_icon:
extvcon(DATA_ICON) ;
return ;
case sp_ucon:
extvcon(DATA_UCON) ;
return ;
default:
fatal("putval notreached") ;
/* NOTREACHED */
}
}
chkstart() {
static int absout = 0 ;
if ( absout ) return ;
if ( !oksizes ) fatal("missing size specification") ;
setmode(DATA_CONST) ;
extconst((cons_t)0) ;
databytes= wordsize ;
setmode(DATA_REP) ;
if ( wordsize<ABSSIZE ) {
register factor = ABSSIZE/wordsize - 1 ;
extadr( (cons_t) factor ) ;
databytes += factor * wordsize ;
}
absout++ ;
memtype= HOLBSS ;
}
typealign(new) enum m_type new ; {
if ( memtype==new ) return ;
align(wordsize);
memtype=new ;
}
sizealign(size) cons_t size ; {
align( size>wordsize ? wordsize : (int)size ) ;
}
align(size) int size ; {
while ( databytes%size ) {
setmode(DATA_BYTES) ;
ext8(0) ;
databytes++ ;
}
}
extconst(n) cons_t n ; {
setmode(DATA_CONST);
extword(n);
}
extbss(n) cons_t n ; {
cons_t objsize,amount ;
if ( n<=0 ) {
if ( n<0 ) werror("negative bss/hol size") ;
if ( table2()==sp_cend || table2()==sp_cend) {
werror("Unexpected end-of-line") ;
}
return ;
}
setmode(DATA_NUL) ; /* flush descriptor */
objsize= valsize();
if ( objsize==0 ) {
werror("Unexpected end-of-line");
return;
}
if ( n%objsize != 0 ) error("BSS/HOL incompatible sizes");
putval();
amount= n/objsize ;
if ( amount>1 ) {
setmode(DATA_REP);
extadr(amount-1) ;
}
databytes +=n ;
getarg(sp_cst2);
if ( argval<0 || argval>1 ) error("illegal last argument") ;
}
extloc(lbp) register locl_t *lbp; {
/*
* assemble a pointer constant from a local label.
* For example con *1
*/
setmode(DATA_IPTR);
data_reloc( chp_cast lbp,dataoff,RELLOC);
extadr((cons_t)0);
}
extglob(agbp,off) glob_t *agbp; cons_t off; {
register glob_t *gbp;
/*
* generate a word of data that is defined by a global symbol.
* Various relocation has to be prepared here in some cases
*/
gbp=agbp;
setmode(DATA_DPTR);
if ( gbp->g_status&DEF ) {
extadr(gbp->g_val.g_addr+off);
} else {
data_reloc( chp_cast gbp,dataoff,RELGLO);
extadr(off);
}
}
extpro(aprp) proc_t *aprp; {
/*
* generate a addres that is defined by a procedure descriptor.
*/
consiz= ptrsize ; setmode(DATA_UCON);
extarb((int)ptrsize,(long)(aprp->p_num));
}
extstring() {
register char *s;
register n ;
/*
* generate data for a string.
*/
for(n=strlngth,s=string ; n--; ) {
setmode(DATA_BYTES) ;
ext8(*s++);
}
return ;
}
extxcon(header) {
register char *s ;
register n;
/*
* generate data for a floating constant initialized by a string.
*/
setmode(header);
s = string ;
for (n=strlngth ; n-- ;) {
if ( *s==0 ) error("Zero byte in initializer") ;
ext8(*s++);
}
ext8(0);
return ;
}
extvcon(header) {
extern long atol() ;
/*
* generate data for a constant initialized by a string.
*/
setmode(header);
if ( consiz>4 ) {
error("Size of initializer exceeds loader capability") ;
}
extarb((int)consiz,atol(string)) ;
return ;
}