ass30.c 8.2 KB

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