2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
12 static char rcs_id[] = "$Id: ass30.c,v 2.8 1994/06/24 10:15:08 ceriel Exp $" ;
13 static char rcs_ip[] = RCS_IP ;
16 short opt_line ; /* max_line_no - # lines removed from end
17 after perfoming exc's.
18 Used to estimate the distance in # of
22 ** Determine the exact instruction length & format where possible, and the
23 ** the upper and lower limits otherwise. Enter limits in labeltable
27 register line_t *lnp, *rev_lnp;
30 int min_l, max_l, min_bytes;
36 opt_line= line_num ; hol_err_line=0 ;
37 min_bytes = max_bytes = 0; rev_lnp= lnp_cast 0 ;
38 for (lnp = pstate.s_fline ; lnp ; opt_line--, line_num-- ) {
40 insno = ctrunc(lnp->instr_num);
43 last_line = line_num ;
44 line_num = lnp->ad.ad_ln.ln_first ;
45 opt_line -= lnp->ad.ad_ln.ln_extra ;
46 lnp->ad.ad_ln.ln_first= last_line ;
50 lbp->l_defined = SEEN;
51 lbp->l_min = min_bytes;
52 lbp->l_max = max_bytes;
55 if ( lnp->type1==CONST && (em_flag[insno]&EM_PAR)==PAR_G ) {
57 if (lnp->ad.ad_i >= holsize) {
58 hol_err_line= line_num ;
60 lnp->ad.ad_i += holbase;
63 if ( lnp->type1>=VALLOW && (em_flag[insno]&EM_PAR)==PAR_G ) {
65 pstate.s_fline= lnp->l_next ;
67 pstate.s_fline->instr_num= insno ;
68 pstate.s_fline->ad.ad_i=
69 VAL1(lnp->type1)+holbase ;
71 (unsigned)linesize[VALLOW]) ;
73 if ( VAL1(lnp->type1) >= holsize) {
74 hol_err_line= line_num ;
78 if ( !valid(lnp) ) fatal("Invalid operand") ;
80 determine_props(lnp, &min_l, &max_l);
81 min_bytes += min_l; max_bytes += max_l;
84 tmp_lnp= lnp->l_next ;
85 lnp->l_next= rev_lnp ; rev_lnp= lnp ;
88 pstate.s_fline= rev_lnp ;
90 line_num= hol_err_line ;
91 werror("address exceeds holsize") ;
97 ** Determine the format that should be used for each instruction,
98 ** depending on its offsets
101 determine_props(lnp, min_len, max_len)
103 int *min_len, *max_len;
107 register char *f_off, *l_off ;
110 insno=ctrunc(lnp->instr_num) ;
111 val=parval(lnp,&defined) ;
113 switch(em_flag[insno]&EM_PAR) {
116 f_off = findnop(insno) ;
119 /* We want the maximum address that is a multiple
121 Assumption: there is no shortie for
122 intr max_word_multiple
123 where intr is a instruction allowing parameters
124 that are not a word multiple (PAR_G).
126 f_off = findfit(insno, maxadr&(~(wordsize-1))) ;
129 f_off = findfit(insno, (cons_t)0) ;
130 l_off = findfit(insno, val ) ;
131 if ( f_off != l_off ) {
132 *min_len=oplength(*f_off) ;
133 *max_len=oplength(*l_off) ;
134 lnp->opoff = NO_OFF ;
140 f_off = findfit(insno,val) ;
143 *min_len = *max_len = oplength(*f_off) ;
146 char *findfit(instr,val) int instr ; cons_t val ; {
147 register char *currc,*endc ;
148 int found, flags, number ;
151 endc = opindex[instr+1] ;
152 for ( currc=opindex[instr], found=0 ;
153 !found && currc<endc ; currc++ ) {
155 flags=ctrunc(*currc++) ;
156 switch ( flags&OPTYPE ) {
161 number=ctrunc(*++currc) ;
163 found = opfit(flags, number, val, em_flag[instr]&EM_PAR ) ;
165 if ( !found ) fatal("Cannot find interpreter opcode") ;
169 char *findnop(instr) int instr ; {
170 register char *currc,*endc ;
172 endc = opindex[instr+1] ;
173 for ( currc=opindex[instr] ; currc<endc ; currc++ ) {
174 switch ( ctrunc(*currc)&OPTYPE ) {
183 fatal("Cannot find interpreter opcode") ;
187 int opfit(flag,number,val,i_flag)
188 int i_flag,flag,number ; cons_t val ; {
189 /* Number is invalid if flag does not contain MINI or SHORT */
190 switch ( flag&OPRANGE ) {
192 if ( val<0 ) return 0 ;
195 if ( val>=0 ) return 0 ;
199 if ( val%wordsize ) return 0 ;
203 if ( val==0 ) return 0 ;
206 switch ( flag&OPTYPE ) {
208 if ( val<0 ) val = -1-val ;
209 return val>=0 && val<number ;
211 if ( val<0 ) val = -1-val ;
212 return val>=0 && val<number*256 ;
214 return val>=0 && val<=65535L &&
215 ( i_flag!=PAR_G || val<=maxadr ) ;
217 return val>= -32768 && val<=32767 ;
221 fatal("illegal OPTYPE value") ;
226 int oplength(flag) int flag ; {
230 if ( flag&OPESC ) cnt++ ;
231 switch( flag&OPTYPE ) {
233 case OPMINI : break ;
235 case OPSHORT : cnt++ ; break ;
237 case OP16 : cnt+=2 ; break ;
238 case OP32 : cnt+=5 ; break ;
239 case OP64 : cnt+=9 ; break ;
245 ** return estimation of value of parameter
247 cons_t parval(lnp,defined)
252 register locl_t *lbp;
253 register glob_t *gbp;
259 default: if ( type>=VALLOW && type<=VALHIGH )
261 error("bad type during parval");
264 return(lnp->ad.ad_i);
271 gbp =lnp->ad.ad_df.df_gp ;
272 offs=lnp->ad.ad_df.df_i ;
274 if(gbp->g_status&DEF)
275 return(gbp->g_val.g_addr+offs);
283 default:error("bad pass in parval");
286 switch(lbp->l_defined) {
287 default : fatal("Illegal local label") ;
289 error("Undefined local label") ;
290 lbp->l_defined= NOTPRESENT ;
294 return max_bytes - lbp->l_min ;
296 /* l_min contains line_num
299 return (lbp->l_min - opt_line -1 ) * maxinsl ;
301 case 4: if(lbp->l_defined == YES)
302 return(lbp->l_min-prog_size-maxinsl);
303 return max_bytes - lbp->l_max- prog_size;
304 case 5: if (lbp->l_defined == YES )
314 return(lnp->ad.ad_pp->p_num);
318 int valid(lnp) register line_t *lnp ; {
323 if ( type>=VALLOW && type<=VALHIGH ) {
326 } else if ( type==CONST ) val = lnp->ad.ad_i ;
327 switch ( em_flag[ctrunc(lnp->instr_num)]&EM_PAR ) {
329 return type==MISSING ;
331 if ( type!=CONST ) return FALSE;
332 if ( val>maxint && val<=maxunsig ) {
333 lnp->ad.ad_i = val -maxunsig -1 ;
337 if ( type!=CONST ) return FALSE;
338 if ( val>maxdint && val<=maxdunsig ) {
339 lnp->ad.ad_i = val -maxdunsig -1 ;
346 return type==CONST && val>=0 ;
348 return type==CONST || type==GLOSYM || type==GLOOFF ;
350 if ( type==MISSING ) return TRUE ;
352 return type==CONST && val>0 && val%wordsize==0 ;
354 return type==CONST && val>=0 && val%wordsize==0 ;
356 return type==CONST && val>=0 &&
357 ( val >= wordsize ? val%wordsize : wordsize%val ) == 0 ;
359 return type==PROCNAME ;
361 return type==LOCSYM ;
363 return type==CONST && val>=0 && val<=3 ;
365 fatal("Unknown parameter type") ;