|
@@ -0,0 +1,847 @@
|
|
|
+/*
|
|
|
+ * (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 ;
|
|
|
+}
|