123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- *
- */
- #include "ass00.h"
- #include "assex.h"
- #include "ip_spec.h"
- #ifndef NORCSID
- static char rcs_id[] = "$Id$" ;
- static char rcs_ip[] = RCS_IP ;
- #endif
- short opt_line ; /* max_line_no - # lines removed from end
- after perfoming exc's.
- Used to estimate the distance in # of
- instructions.
- */
- /*
- ** Determine the exact instruction length & format where possible, and the
- ** the upper and lower limits otherwise. Enter limits in labeltable
- */
- pass_3()
- {
- register line_t *lnp, *rev_lnp;
- line_t *tmp_lnp;
- locl_t *lbp;
- int min_l, max_l, min_bytes;
- short last_line ;
- short hol_err_line ;
- register insno ;
- pass = 3;
- opt_line= line_num ; hol_err_line=0 ;
- min_bytes = max_bytes = 0; rev_lnp= lnp_cast 0 ;
- for (lnp = pstate.s_fline ; lnp ; opt_line--, line_num-- ) {
- pstate.s_fline= lnp;
- insno = ctrunc(lnp->instr_num);
- switch( insno ) {
- case sp_fpseu :
- last_line = line_num ;
- line_num = lnp->ad.ad_ln.ln_first ;
- opt_line -= lnp->ad.ad_ln.ln_extra ;
- lnp->ad.ad_ln.ln_first= last_line ;
- break ;
- case sp_ilb1 :
- lbp = lnp->ad.ad_lp;
- lbp->l_defined = SEEN;
- lbp->l_min = min_bytes;
- lbp->l_max = max_bytes;
- break ;
- default:
- if ( lnp->type1==CONST && (em_flag[insno]&EM_PAR)==PAR_G ) {
- if (holbase != 0) {
- if (lnp->ad.ad_i >= holsize) {
- hol_err_line= line_num ;
- }
- lnp->ad.ad_i += holbase;
- }
- } else
- if ( lnp->type1>=VALLOW && (em_flag[insno]&EM_PAR)==PAR_G ) {
- if (holbase != 0) {
- pstate.s_fline= lnp->l_next ;
- newline(CONST) ;
- pstate.s_fline->instr_num= insno ;
- pstate.s_fline->ad.ad_i=
- VAL1(lnp->type1)+holbase ;
- freearea((area_t)lnp,
- (unsigned)linesize[VALLOW]) ;
- lnp= pstate.s_fline ;
- if ( VAL1(lnp->type1) >= holsize) {
- hol_err_line= line_num ;
- }
- }
- }
- if ( !valid(lnp) ) fatal("Invalid operand") ;
- determine_props(lnp, &min_l, &max_l);
- min_bytes += min_l; max_bytes += max_l;
- break ;
- }
- tmp_lnp= lnp->l_next ;
- lnp->l_next= rev_lnp ; rev_lnp= lnp ;
- lnp= tmp_lnp ;
- }
- pstate.s_fline= rev_lnp ;
- if ( hol_err_line ) {
- line_num= hol_err_line ;
- werror("address exceeds holsize") ;
- }
- }
- /*
- ** Determine the format that should be used for each instruction,
- ** depending on its offsets
- */
- determine_props(lnp, min_len, max_len)
- line_t *lnp;
- int *min_len, *max_len;
- {
- cons_t val ;
- register int insno ;
- register char *f_off, *l_off ;
- char defined ;
- insno=ctrunc(lnp->instr_num) ;
- val=parval(lnp,&defined) ;
- if ( !defined ) {
- switch(em_flag[insno]&EM_PAR) {
- case PAR_NO:
- case PAR_W:
- f_off = findnop(insno) ;
- break ;
- case PAR_G:
- /* We want the maximum address that is a multiple
- of the wordsize.
- Assumption: there is no shortie for
- intr max_word_multiple
- where intr is a instruction allowing parameters
- that are not a word multiple (PAR_G).
- */
- f_off = findfit(insno, maxadr&(~(wordsize-1))) ;
- break ;
- case PAR_B:
- f_off = findfit(insno, (cons_t)0) ;
- l_off = findfit(insno, val ) ;
- if ( f_off != l_off ) {
- *min_len=oplength(*f_off) ;
- *max_len=oplength(*l_off) ;
- lnp->opoff = NO_OFF ;
- return ;
- }
- break ;
- }
- } else {
- f_off = findfit(insno,val) ;
- }
- lnp->opoff = f_off ;
- *min_len = *max_len = oplength(*f_off) ;
- }
- char *findfit(instr,val) int instr ; cons_t val ; {
- register char *currc,*endc ;
- int found, flags, number ;
- char *opc ;
- endc = opindex[instr+1] ;
- for ( currc=opindex[instr], found=0 ;
- !found && currc<endc ; currc++ ) {
- opc = currc ;
- flags=ctrunc(*currc++) ;
- switch ( flags&OPTYPE ) {
- case OPNO :
- continue ;
- case OPMINI :
- case OPSHORT :
- number=ctrunc(*++currc) ;
- }
- found = opfit(flags, number, val, em_flag[instr]&EM_PAR ) ;
- }
- if ( !found ) fatal("Cannot find interpreter opcode") ;
- return opc ;
- }
- char *findnop(instr) int instr ; {
- register char *currc,*endc ;
- endc = opindex[instr+1] ;
- for ( currc=opindex[instr] ; currc<endc ; currc++ ) {
- switch ( ctrunc(*currc)&OPTYPE ) {
- case OPNO :
- return currc ;
- case OPSHORT :
- case OPMINI :
- currc++ ;
- }
- currc++ ;
- }
- fatal("Cannot find interpreter opcode") ;
- /* NOTREACHED */
- }
- int opfit(flag,number,val,i_flag)
- int i_flag,flag,number ; cons_t val ; {
- /* Number is invalid if flag does not contain MINI or SHORT */
- switch ( flag&OPRANGE ) {
- case OP_POS :
- if ( val<0 ) return 0 ;
- break ;
- case OP_NEG :
- if ( val>=0 ) return 0 ;
- break ;
- }
- if ( flag&OPWORD ) {
- if ( val%wordsize ) return 0 ;
- val /= wordsize ;
- }
- if ( flag&OPNZ ) {
- if ( val==0 ) return 0 ;
- val-- ;
- }
- switch ( flag&OPTYPE ) {
- case OPMINI :
- if ( val<0 ) val = -1-val ;
- return val>=0 && val<number ;
- case OPSHORT :
- if ( val<0 ) val = -1-val ;
- return val>=0 && val<number*256 ;
- case OP16U:
- return val>=0 && val<=65535L &&
- ( i_flag!=PAR_G || val<=maxadr ) ;
- case OP16 :
- return val>= -32768 && val<=32767 ;
- case OP32 :
- return TRUE ;
- default :
- fatal("illegal OPTYPE value") ;
- /* NOTREACHED */
- }
- }
- int oplength(flag) int flag ; {
- int cnt ;
- cnt=1 ;
- if ( flag&OPESC ) cnt++ ;
- switch( flag&OPTYPE ) {
- case OPNO :
- case OPMINI : break ;
- case OP8 :
- case OPSHORT : cnt++ ; break ;
- case OP16U:
- case OP16 : cnt+=2 ; break ;
- case OP32 : cnt+=5 ; break ;
- case OP64 : cnt+=9 ; break ;
- }
- return cnt ;
- }
- /*
- ** return estimation of value of parameter
- */
- cons_t parval(lnp,defined)
- line_t *lnp;
- char *defined;
- {
- register int type;
- register locl_t *lbp;
- register glob_t *gbp;
- cons_t offs ;
- *defined = TRUE ;
- type = lnp->type1;
- switch(type) {
- default: if ( type>=VALLOW && type<=VALHIGH )
- return VAL1(type) ;
- error("bad type during parval");
- break;
- case CONST:
- return(lnp->ad.ad_i);
- case GLOSYM:
- case GLOOFF:
- if ( type!=GLOOFF) {
- gbp = lnp->ad.ad_gp;
- offs= 0 ;
- } else {
- gbp =lnp->ad.ad_df.df_gp ;
- offs=lnp->ad.ad_df.df_i ;
- }
- if(gbp->g_status&DEF)
- return(gbp->g_val.g_addr+offs);
- else {
- *defined = FALSE ;
- return offs ;
- }
- case LOCSYM:
- lbp = lnp->ad.ad_lp;
- switch(pass) {
- default:error("bad pass in parval");
- case 3:
- *defined = FALSE;
- switch(lbp->l_defined) {
- default : fatal("Illegal local label") ;
- case NO :
- error("Undefined local label") ;
- lbp->l_defined= NOTPRESENT ;
- case NOTPRESENT:
- return max_bytes;
- case SEEN :
- return max_bytes - lbp->l_min ;
- case YES :
- /* l_min contains line_num
- adjusted for exc's.
- */
- return (lbp->l_min - opt_line -1 ) * maxinsl ;
- }
- case 4: if(lbp->l_defined == YES)
- return(lbp->l_min-prog_size-maxinsl);
- return max_bytes - lbp->l_max- prog_size;
- case 5: if (lbp->l_defined == YES )
- return lbp->l_min ;
- *defined = FALSE ;
- break ;
- }
- break;
- case MISSING:
- *defined = FALSE ;
- break;
- case PROCNAME:
- return(lnp->ad.ad_pp->p_num);
- }
- return(0);
- }
- int valid(lnp) register line_t *lnp ; {
- cons_t val ;
- int type ;
- type = lnp->type1 ;
- if ( type>=VALLOW && type<=VALHIGH ) {
- val= VAL1(type) ;
- type= CONST ;
- } else if ( type==CONST ) val = lnp->ad.ad_i ;
- switch ( em_flag[ctrunc(lnp->instr_num)]&EM_PAR ) {
- case PAR_NO:
- return type==MISSING ;
- case PAR_C:
- if ( type!=CONST ) return FALSE;
- if ( val>maxint && val<=maxunsig ) {
- lnp->ad.ad_i = val -maxunsig -1 ;
- }
- return TRUE ;
- case PAR_D:
- if ( type!=CONST ) return FALSE;
- if ( val>maxdint && val<=maxdunsig ) {
- lnp->ad.ad_i = val -maxdunsig -1 ;
- }
- return TRUE ;
- case PAR_L:
- case PAR_F:
- return type==CONST ;
- case PAR_N:
- return type==CONST && val>=0 ;
- case PAR_G:
- return type==CONST || type==GLOSYM || type==GLOOFF ;
- case PAR_W:
- if ( type==MISSING ) return TRUE ;
- case PAR_S:
- return type==CONST && val>0 && val%wordsize==0 ;
- case PAR_Z:
- return type==CONST && val>=0 && val%wordsize==0 ;
- case PAR_O:
- return type==CONST && val>=0 &&
- ( val >= wordsize ? val%wordsize : wordsize%val ) == 0 ;
- case PAR_P:
- return type==PROCNAME ;
- case PAR_B:
- return type==LOCSYM ;
- case PAR_R:
- return type==CONST && val>=0 && val<=3 ;
- default:
- fatal("Unknown parameter type") ;
- /* NOTREACHED */
- }
- }
|