848 lines
17 KiB
C
848 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 ans 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) ;
|
|
}
|
|
|
|
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 *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 */
|
|
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 global 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 ) {
|
|
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) ;
|
|
}
|
|
|
|
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';
|
|
}
|
|
|
|
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,a_lnp->ad.ad_ln.ln_extra-size) ;
|
|
a_lnp->ad.ad_ln.ln_first += size ;
|
|
a_lnp->ad.ad_ln.ln_extra = size-1 ;
|
|
size=0 ;
|
|
b_lnp=a_lnp->l_next ;
|
|
} else {
|
|
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 ( ( size-= p2 )>0 ) {
|
|
if ( ctrunc(b_lnp->instr_num) !=sp_fpseu ) {
|
|
fatal("EXC inconsistency") ;
|
|
}
|
|
doinsert(b_lnp,line,b_lnp->ad.ad_ln.ln_extra-size) ;
|
|
b_lnp->ad.ad_ln.ln_first += size ;
|
|
b_lnp->ad.ad_ln.ln_extra = size-1 ;
|
|
} else {
|
|
doinsert(b_lnp,line,-1) ;
|
|
}
|
|
if ( !b_lnp ) { /* if a_lnp==0, so is b_lnp */
|
|
fatal("Cannot perform exchange") ;
|
|
}
|
|
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) ;
|
|
setmode(DATA_REP) ;
|
|
extadr( (cons_t) (ABSSIZE/wordsize-1) ) ;
|
|
absout++ ;
|
|
databytes = ABSSIZE ;
|
|
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 ; {
|
|
register unsigned gapsize ;
|
|
|
|
for ( gapsize= databytes%size ; gapsize ; gapsize-- ) {
|
|
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 ;
|
|
}
|