Pristine Ack-5.5
[Ack-5.5.git] / util / ass / ass30.c
1 /*
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".
4  *
5  */
6
7 #include        "ass00.h"
8 #include        "assex.h"
9 #include        "ip_spec.h"
10
11 #ifndef NORCSID
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 ;
14 #endif
15
16 short           opt_line ;      /* max_line_no - # lines removed from end
17                                    after perfoming exc's.
18                                    Used to estimate the distance in # of
19                                    instructions.
20                                 */
21 /*
22 ** Determine the exact instruction length & format where possible, and the
23 ** the upper and lower limits otherwise. Enter limits in labeltable
24 */
25 pass_3()
26 {
27         register line_t *lnp, *rev_lnp;
28         line_t   *tmp_lnp;
29         locl_t   *lbp;
30         int      min_l, max_l, min_bytes;
31         short    last_line ;
32         short    hol_err_line ;
33         register insno ;
34
35         pass = 3;
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-- ) {
39                 pstate.s_fline= lnp;
40                 insno = ctrunc(lnp->instr_num);
41                 switch( insno ) {
42                 case sp_fpseu :
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 ;
47                         break ;
48                 case sp_ilb1 :
49                         lbp = lnp->ad.ad_lp;
50                         lbp->l_defined = SEEN;
51                         lbp->l_min = min_bytes;
52                         lbp->l_max = max_bytes;
53                         break ;
54                 default:
55                 if ( lnp->type1==CONST && (em_flag[insno]&EM_PAR)==PAR_G ) {
56                         if (holbase != 0) {
57                                 if (lnp->ad.ad_i >= holsize) {
58                                                 hol_err_line= line_num ;
59                                 }
60                                 lnp->ad.ad_i += holbase;
61                         }
62                 } else
63                 if ( lnp->type1>=VALLOW && (em_flag[insno]&EM_PAR)==PAR_G ) {
64                         if (holbase != 0) {
65                                 pstate.s_fline= lnp->l_next ;
66                                 newline(CONST) ;
67                                 pstate.s_fline->instr_num= insno ;
68                                 pstate.s_fline->ad.ad_i=
69                                         VAL1(lnp->type1)+holbase ;
70                                 freearea((area_t)lnp,
71                                         (unsigned)linesize[VALLOW]) ;
72                                 lnp= pstate.s_fline ;
73                                 if ( VAL1(lnp->type1) >= holsize) {
74                                         hol_err_line= line_num ;
75                                 }
76                         }
77                 }
78                 if ( !valid(lnp) ) fatal("Invalid operand") ;
79
80                 determine_props(lnp, &min_l, &max_l);
81                 min_bytes += min_l; max_bytes += max_l;
82                 break ;
83                 }
84                 tmp_lnp= lnp->l_next ;
85                 lnp->l_next= rev_lnp ; rev_lnp= lnp ;
86                 lnp= tmp_lnp ;
87         }
88         pstate.s_fline= rev_lnp ;
89         if ( hol_err_line ) {
90                 line_num= hol_err_line ;
91                 werror("address exceeds holsize") ;
92         }
93 }
94
95
96 /*
97 ** Determine the format that should be used for each instruction,
98 ** depending on its offsets
99 */
100
101 determine_props(lnp, min_len, max_len)
102         line_t *lnp;
103         int    *min_len, *max_len;
104 {
105         cons_t  val ;
106         register int insno ;
107         register char *f_off, *l_off ;
108         char defined ;
109
110         insno=ctrunc(lnp->instr_num) ;
111         val=parval(lnp,&defined) ;
112         if ( !defined ) {
113                 switch(em_flag[insno]&EM_PAR) {
114                 case PAR_NO:
115                 case PAR_W:
116                         f_off = findnop(insno) ;
117                         break ;
118                 case PAR_G:
119                         /* We want the maximum address that is a multiple
120                            of the wordsize.
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).
125                         */
126                         f_off = findfit(insno, maxadr&(~(wordsize-1))) ;
127                         break ;
128                 case PAR_B:
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 ;
135                                 return ;
136                         }
137                         break ;
138                 }
139         } else {
140                 f_off = findfit(insno,val) ;
141         }
142         lnp->opoff = f_off ;
143         *min_len = *max_len = oplength(*f_off) ;
144 }
145
146 char *findfit(instr,val) int instr ; cons_t val ; {
147         register char *currc,*endc ;
148         int found, flags, number ;
149         char *opc ;
150
151         endc = opindex[instr+1] ;
152         for ( currc=opindex[instr], found=0 ;
153                 !found && currc<endc ; currc++ ) {
154                 opc = currc ;
155                 flags=ctrunc(*currc++) ;
156                 switch ( flags&OPTYPE ) {
157                 case OPNO :
158                         continue ;
159                 case OPMINI :
160                 case OPSHORT :
161                         number=ctrunc(*++currc) ;
162                 }
163                 found = opfit(flags, number, val, em_flag[instr]&EM_PAR ) ;
164         }
165         if ( !found ) fatal("Cannot find interpreter opcode") ;
166         return opc ;
167 }
168
169 char *findnop(instr) int instr ; {
170         register char *currc,*endc ;
171
172         endc = opindex[instr+1] ;
173         for ( currc=opindex[instr] ; currc<endc ; currc++ ) {
174                 switch ( ctrunc(*currc)&OPTYPE ) {
175                 case OPNO :
176                         return currc ;
177                 case OPSHORT :
178                 case OPMINI :
179                         currc++ ;
180                 }
181                 currc++ ;
182         }
183         fatal("Cannot find interpreter opcode") ;
184         /* NOTREACHED */
185 }
186
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 ) {
191         case OP_POS :
192                 if ( val<0 ) return 0 ;
193                 break ;
194         case OP_NEG :
195                 if ( val>=0 ) return 0 ;
196                 break ;
197         }
198         if ( flag&OPWORD ) {
199                 if ( val%wordsize ) return 0 ;
200                 val /= wordsize ;
201         }
202         if ( flag&OPNZ ) {
203                 if ( val==0 ) return 0 ;
204                 val-- ;
205         }
206         switch ( flag&OPTYPE ) {
207         case OPMINI :
208                 if ( val<0 ) val = -1-val ;
209                 return val>=0 && val<number ;
210         case OPSHORT :
211                 if ( val<0 ) val = -1-val ;
212                 return val>=0 && val<number*256 ;
213         case OP16U:
214                 return val>=0 && val<=65535L &&
215                        ( i_flag!=PAR_G || val<=maxadr ) ;
216         case OP16 :
217                 return val>= -32768 && val<=32767 ;
218         case OP32 :
219                 return TRUE ;
220         default :
221                 fatal("illegal OPTYPE value") ;
222                 /* NOTREACHED */
223         }
224 }
225
226 int oplength(flag) int flag ; {
227         int cnt ;
228
229         cnt=1 ;
230         if ( flag&OPESC ) cnt++ ;
231         switch( flag&OPTYPE ) {
232         case OPNO    :
233         case OPMINI  : break ;
234         case OP8     :
235         case OPSHORT : cnt++ ; break ;
236         case OP16U:
237         case OP16    : cnt+=2 ; break ;
238         case OP32    : cnt+=5 ; break ;
239         case OP64    : cnt+=9 ; break ;
240         }
241         return cnt ;
242 }
243
244 /*
245 ** return estimation of value of parameter
246 */
247 cons_t parval(lnp,defined)
248         line_t *lnp;
249         char *defined;
250 {
251         register int    type;
252         register locl_t *lbp;
253         register glob_t *gbp;
254         cons_t   offs ;
255
256         *defined = TRUE ;
257         type = lnp->type1;
258         switch(type) {
259                 default: if ( type>=VALLOW && type<=VALHIGH )
260                                  return VAL1(type) ;
261                          error("bad type during parval");
262                          break;
263                 case CONST:
264                         return(lnp->ad.ad_i);
265                 case GLOSYM:
266                 case GLOOFF:
267                         if ( type!=GLOOFF) {
268                                 gbp = lnp->ad.ad_gp;
269                                 offs= 0 ;
270                         } else {
271                                 gbp =lnp->ad.ad_df.df_gp ;
272                                 offs=lnp->ad.ad_df.df_i ;
273                         }
274                         if(gbp->g_status&DEF)
275                                 return(gbp->g_val.g_addr+offs);
276                         else {
277                                 *defined = FALSE ;
278                                 return offs ;
279                         }
280                 case LOCSYM:
281                         lbp = lnp->ad.ad_lp;
282                         switch(pass) {
283                         default:error("bad pass in parval");
284                         case 3:
285                                 *defined = FALSE;
286                                 switch(lbp->l_defined) {
287                                 default : fatal("Illegal local label") ;
288                                 case NO :
289                                         error("Undefined local label") ;
290                                         lbp->l_defined= NOTPRESENT ;
291                                 case NOTPRESENT:
292                                         return max_bytes;
293                                 case SEEN :
294                                         return max_bytes - lbp->l_min ;
295                                 case YES :
296                                         /* l_min contains line_num
297                                            adjusted for exc's.
298                                         */
299                         return (lbp->l_min - opt_line -1 ) * maxinsl ;
300                                 }
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 )
305                                         return lbp->l_min ;
306                                 *defined = FALSE ;
307                                 break ;
308                         }
309                         break;
310                 case MISSING:
311                         *defined = FALSE ;
312                         break;
313                 case PROCNAME:
314                         return(lnp->ad.ad_pp->p_num);
315         }
316         return(0);
317 }
318 int valid(lnp) register line_t *lnp ; {
319         cons_t val ;
320         int type ;
321
322         type = lnp->type1 ;
323         if ( type>=VALLOW && type<=VALHIGH ) {
324                 val= VAL1(type) ;
325                 type= CONST ;
326         } else if ( type==CONST ) val = lnp->ad.ad_i ;
327         switch ( em_flag[ctrunc(lnp->instr_num)]&EM_PAR ) {
328         case PAR_NO:
329                 return type==MISSING ;
330         case PAR_C:
331                 if ( type!=CONST ) return FALSE;
332                 if ( val>maxint && val<=maxunsig ) {
333                         lnp->ad.ad_i = val -maxunsig -1 ;
334                 }
335                 return TRUE ;
336         case PAR_D:
337                 if ( type!=CONST ) return FALSE;
338                 if ( val>maxdint && val<=maxdunsig ) {
339                         lnp->ad.ad_i = val -maxdunsig -1 ;
340                 }
341                 return TRUE ;
342         case PAR_L:
343         case PAR_F:
344                 return type==CONST ;
345         case PAR_N:
346                 return type==CONST && val>=0 ;
347         case PAR_G:
348                 return type==CONST || type==GLOSYM || type==GLOOFF ;
349         case PAR_W:
350                 if ( type==MISSING ) return TRUE ;
351         case PAR_S:
352                 return type==CONST && val>0 && val%wordsize==0 ;
353         case PAR_Z:
354                 return type==CONST && val>=0 && val%wordsize==0 ;
355         case PAR_O:
356                 return type==CONST && val>=0 &&
357                     ( val >= wordsize ? val%wordsize : wordsize%val ) == 0 ;
358         case PAR_P:
359                 return type==PROCNAME ;
360         case PAR_B:
361                 return type==LOCSYM ;
362         case PAR_R:
363                 return type==CONST && val>=0 && val<=3 ;
364         default:
365                 fatal("Unknown parameter type") ;
366                 /* NOTREACHED */
367         }
368 }