#ifndef NORCSID static char rcsid[] = "$Header$"; #endif #include #include "param.h" #include "types.h" #include "assert.h" #include "line.h" #include "lookup.h" #include "alloc.h" #include "proinf.h" #include "../../h/em_spec.h" #include "../../h/em_pseu.h" #include "../../h/em_flag.h" #include "../../h/em_mes.h" #include "ext.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 * * Author: Hans van Staveren */ static short tabval; /* temp store for shorts */ static offset tabval2; /* temp store for offsets */ static char string[IDL+1]; /* temp store for names */ /* * The next constants are close to sp_cend for fast switches */ #define INST 256 /* instruction: number in tabval */ #define PSEU 257 /* pseudo: number in tabval */ #define ILBX 258 /* label: number in tabval */ #define DLBX 259 /* symbol: name in string[] */ #define CSTX1 260 /* short constant: stored in tabval */ #define CSTX2 261 /* offset: value in tabval2 */ #define VALX1 262 /* symbol+short: in string[] and tabval */ #define VALX2 263 /* symbol+offset: in string[] and tabval2 */ #define ATEOF 264 /* bumped into end of file */ #define readbyte getchar short readshort() { register int l_byte, h_byte; l_byte = readbyte(); h_byte = readbyte(); if ( h_byte>=128 ) h_byte -= 256 ; return l_byte | (h_byte*256) ; } #ifdef LONGOFF offset readoffset() { register long l; register int h_byte; l = readbyte(); l |= ((unsigned) readbyte())*256 ; l |= readbyte()*256L*256L ; h_byte = readbyte() ; if ( h_byte>=128 ) h_byte -= 256 ; return l | (h_byte*256L*256*256L) ; } #endif draininput() { /* * called when MES ERR is encountered. * Drain input in case it is a pipe. */ while (getchar() != EOF) ; } short getint() { switch(table2()) { default: error("int expected"); case CSTX1: return(tabval); } } sym_p getsym(status) int status; { switch(table2()) { default: error("symbol expected"); case DLBX: return(symlookup(string,status,0)); case sp_pnam: return(symlookup(string,status,SYMPRO)); } } offset getoff() { switch (table2()) { default: error("offset expected"); case CSTX1: return((offset) tabval); #ifdef LONGOFF case CSTX2: return(tabval2); #endif } } make_string(n) int n; { register char *s; extern char *sprintf(); s=sprintf(string,".%u",n); assert(s == string); } inident() { register n; register char *p = string; register c; n = getint(); while (n--) { c = readbyte(); if (p<&string[IDL]) *p++ = c; } *p++ = 0; } int table3(n) int n; { switch (n) { case sp_ilb1: tabval = readbyte(); return(ILBX); case sp_ilb2: tabval = readshort(); return(ILBX); case sp_dlb1: make_string(readbyte()); return(DLBX); case sp_dlb2: make_string(readshort()); return(DLBX); case sp_dnam: inident(); return(DLBX); case sp_pnam: inident(); return(n); case sp_cst2: tabval = readshort(); return(CSTX1); #ifdef LONGOFF case sp_cst4: tabval2 = readoffset(); return(CSTX2); #endif case sp_doff: if (table2()!=DLBX) error("symbol expected"); switch(table2()) { default: error("offset expected"); case CSTX1: return(VALX1); #ifdef LONGOFF case CSTX2: return(VALX2); #endif } default: return(n); } } int table1() { register n; n = readbyte(); if (n == EOF) return(ATEOF); if ((n <= sp_lmnem) && (n >= sp_fmnem)) { tabval = n; return(INST); } if ((n <= sp_lpseu) && (n >= sp_fpseu)) { tabval = n; return(PSEU); } if ((n < sp_filb0 + sp_nilb0) && (n >= sp_filb0)) { tabval = n - sp_filb0; return(ILBX); } return(table3(n)); } int table2() { register n; n = readbyte(); if ((n < sp_fcst0 + sp_ncst0) && (n >= sp_fcst0)) { tabval = n - sp_zcst0; return(CSTX1); } return(table3(n)); } getlines() { register line_p lnp; register instr; for(;;) { linecount++; switch(table1()) { default: error("unknown instruction byte"); /* NOTREACHED */ case ATEOF: if (prodepth!=0) error("procedure unterminated at eof"); process(); return; case INST: tstinpro(); instr = tabval; break; case DLBX: lnp = newline(OPSYMBOL); lnp->l_instr = ps_sym; lnp->l_a.la_sp= symlookup(string,DEFINING,0); lnp->l_next = curpro.lastline; curpro.lastline = lnp; continue; case ILBX: tstinpro(); lnp = newline(OPNUMLAB); lnp->l_instr = op_lab; lnp->l_a.la_np = numlookup((unsigned) tabval); if (lnp->l_a.la_np->n_line != (line_p) 0) error("label %u multiple defined",(unsigned) tabval); lnp->l_a.la_np->n_line = lnp; lnp->l_next = curpro.lastline; curpro.lastline = lnp; continue; case PSEU: if(inpseudo(tabval)) return; continue; } /* * Now we have an instruction number in instr * There might be an operand, look for it */ if ((em_flag[instr-sp_fmnem]&EM_PAR)==PAR_NO) { lnp = newline(OPNO); } else switch(table2()) { default: error("unknown offset byte"); case sp_cend: lnp = newline(OPNO); break; case CSTX1: if ((em_flag[instr-sp_fmnem]&EM_PAR)!= PAR_B) { if (CANMINI(tabval)) lnp = newline(tabval+Z_OPMINI); else { lnp = newline(OPSHORT); lnp->l_a.la_short = tabval; } } else { lnp = newline(OPNUMLAB); lnp->l_a.la_np = numlookup((unsigned) tabval); } break; #ifdef LONGOFF case CSTX2: lnp = newline(OPOFFSET); lnp->l_a.la_offset = tabval2; break; #endif case ILBX: tstinpro(); lnp = newline(OPNUMLAB); lnp->l_a.la_np = numlookup((unsigned) tabval); break; case DLBX: lnp = newline(OPSYMBOL); lnp->l_a.la_sp = symlookup(string,OCCURRING,0); break; case sp_pnam: lnp = newline(OPSYMBOL); lnp->l_a.la_sp = symlookup(string,OCCURRING,SYMPRO); break; case VALX1: lnp = newline(OPSVAL); lnp->l_a.la_sval.lasv_sp = symlookup(string,OCCURRING,0); lnp->l_a.la_sval.lasv_short = tabval; break; #ifdef LONGOFF case VALX2: lnp = newline(OPLVAL); lnp->l_a.la_lval.lalv_sp = symlookup(string,OCCURRING,0); lnp->l_a.la_lval.lalv_offset = tabval2; break; #endif } lnp->l_instr = instr; lnp->l_next = curpro.lastline; curpro.lastline = lnp; } } argstring(length,abp) offset length; register argb_p abp; { while (length--) { if (abp->ab_index == NARGBYTES) abp = abp->ab_next = newargb(); abp->ab_contents[abp->ab_index++] = readbyte(); } } line_p arglist(n) int n; { line_p lnp; register arg_p ap,*app; bool moretocome; offset length; /* * creates an arglist with n elements * if n == 0 the arglist is variable and terminated by sp_cend */ lnp = newline(OPLIST); app = &lnp->l_a.la_arg; moretocome = TRUE; do { switch(table2()) { default: error("unknown byte in arglist"); case CSTX1: tabval2 = (offset) tabval; case CSTX2: *app = ap = newarg(ARGOFF); ap->a_a.a_offset = tabval2; app = &ap->a_next; break; case ILBX: tstinpro(); *app = ap = newarg(ARGNUM); ap->a_a.a_np = numlookup((unsigned) tabval); ap->a_a.a_np->n_flags |= NUMDATA; app = &ap->a_next; break; case DLBX: *app = ap = newarg(ARGSYM); ap->a_a.a_sp = symlookup(string,OCCURRING,0); app = &ap->a_next; break; case sp_pnam: *app = ap = newarg(ARGSYM); ap->a_a.a_sp = symlookup(string,OCCURRING,SYMPRO); app = &ap->a_next; break; case VALX1: tabval2 = (offset) tabval; case VALX2: *app = ap = newarg(ARGVAL); ap->a_a.a_val.av_sp = symlookup(string,OCCURRING,0); ap->a_a.a_val.av_offset = tabval2; app = &ap->a_next; break; case sp_scon: *app = ap = newarg(ARGSTR); length = getoff(); argstring(length,&ap->a_a.a_string); app = &ap->a_next; break; case sp_icon: *app = ap = newarg(ARGICN); goto casecon; case sp_ucon: *app = ap = newarg(ARGUCN); goto casecon; case sp_fcon: *app = ap = newarg(ARGFCN); casecon: length = getint(); ap->a_a.a_con.ac_length = (short) length; argstring(getoff(),&ap->a_a.a_con.ac_con); app = &ap->a_next; break; case sp_cend: moretocome = FALSE; } if (n && (--n) == 0) moretocome = FALSE; } while (moretocome); return(lnp); } offset aoff(ap,n) register arg_p ap; { while (n>0) { if (ap != (arg_p) 0) ap = ap->a_next; n--; } if (ap == (arg_p) 0) error("too few parameters"); if (ap->a_typ != ARGOFF) error("offset expected"); return(ap->a_a.a_offset); } int inpseudo(n) short n; { register line_p lnp,head,tail; short n1,n2; proinf savearea; #ifdef PSEUBETWEEN static int pcount=0; if (pcount++ >= PSEUBETWEEN && prodepth==0) { process(); pcount=0; } #endif switch(n) { default: error("unknown pseudo"); case ps_bss: case ps_hol: lnp = arglist(3); break; case ps_rom: case ps_con: lnp = arglist(0); break; case ps_ina: case ps_inp: case ps_exa: case ps_exp: lnp = newline(OPSYMBOL); lnp->l_a.la_sp = getsym(NOTHING); break; case ps_exc: n1 = getint(); n2 = getint(); if (n1 != 0 && n2 != 0) { tail = curpro.lastline; while (--n2) tail = tail->l_next; head = tail; while (n1--) head = head->l_next; lnp = tail->l_next; tail->l_next = head->l_next; head->l_next = curpro.lastline; curpro.lastline = lnp; } lnp = newline(OPNO); break; case ps_mes: lnp = arglist(0); switch((int) aoff(lnp->l_a.la_arg,0)) { case ms_err: draininput(); exit(-1); case ms_opt: nflag = TRUE; break; case ms_emx: wordsize = aoff(lnp->l_a.la_arg,1); pointersize = aoff(lnp->l_a.la_arg,2); #ifndef LONGOFF if (wordsize>2) error("This optimizer cannot handle wordsize>2"); #endif break; case ms_gto: curpro.gtoproc=1; /* Treat as empty mes ms_reg */ case ms_reg: tstinpro(); regvar(lnp->l_a.la_arg->a_next); oldline(lnp); lnp=newline(OPNO); n=ps_exc; /* kludge to force out this line */ break; } break; case ps_pro: if (prodepth>0) savearea = curpro; else process(); curpro.symbol = getsym(DEFINING); switch(table2()) { case sp_cend: curpro.localbytes = (offset) -1; break; case CSTX1: tabval2 = (offset) tabval; case CSTX2: curpro.localbytes = tabval2; break; default: error("bad second arg of PRO"); } prodepth++; curpro.gtoproc=0; if (prodepth>1) { register i; curpro.lastline = (line_p) 0; curpro.freg = (reg_p) 0; for(i=0;il_instr = n; lnp->l_next = curpro.lastline; curpro.lastline = lnp; return(0); } tstinpro() { if (prodepth==0) error("This is not allowed outside a procedure"); }