ic_aux.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /* $Id$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. */
  6. /* I N T E R M E D I A T E C O D E
  7. *
  8. * I C _ A U X . C
  9. */
  10. #include <em_pseu.h>
  11. #include <em_spec.h>
  12. #include <em_mnem.h>
  13. #include "../share/types.h"
  14. #include "../share/global.h"
  15. #include "../share/debug.h"
  16. #include "../share/def.h"
  17. #include "../share/aux.h"
  18. #include "ic.h"
  19. #include "ic_io.h"
  20. #include "ic_lookup.h"
  21. #include "../share/alloc.h"
  22. #include "ic_aux.h"
  23. /* opr_size */
  24. offset opr_size(instr)
  25. short instr;
  26. {
  27. switch(instr) {
  28. case op_loe:
  29. case op_ste:
  30. case op_ine:
  31. case op_dee:
  32. case op_zre:
  33. return (offset) ws;
  34. case op_lde:
  35. case op_sde:
  36. return (offset) 2*ws;
  37. case op_lae:
  38. case op_fil:
  39. case op_gto:
  40. return (offset) UNKNOWN_SIZE;
  41. default:
  42. error("illegal operand of opr_size: %d", instr);
  43. }
  44. /* NOTREACHED */
  45. }
  46. /* dblockdef */
  47. STATIC offset argsize(arg)
  48. arg_p arg;
  49. {
  50. /* Compute the size (in bytes) that the given initializer
  51. * will occupy.
  52. */
  53. offset s;
  54. argb_p argb;
  55. switch(arg->a_type) {
  56. case ARGOFF:
  57. /* See if value fits in a short */
  58. if ((short) arg->a_a.a_offset == arg->a_a.a_offset) {
  59. return ws;
  60. } else {
  61. return 2*ws;
  62. }
  63. case ARGINSTRLAB:
  64. case ARGOBJECT:
  65. case ARGPROC:
  66. return ps; /* pointer size */
  67. case ARGSTRING:
  68. /* strings are partitioned into pieces */
  69. s = 0;
  70. for (argb = &arg->a_a.a_string; argb != (argb_p) 0;
  71. argb = argb->ab_next) {
  72. s += argb->ab_index;
  73. }
  74. return s;
  75. case ARGICN:
  76. case ARGUCN:
  77. case ARGFCN:
  78. return arg->a_a.a_con.ac_length;
  79. default:
  80. assert(FALSE);
  81. }
  82. /* NOTREACHED */
  83. }
  84. STATIC offset blocksize(pseudo,args)
  85. byte pseudo;
  86. arg_p args;
  87. {
  88. /* Determine the number of bytes of a datablock */
  89. arg_p arg;
  90. offset sum;
  91. switch(pseudo) {
  92. case DHOL:
  93. case DBSS:
  94. if (args->a_type != ARGOFF) {
  95. error("offset expected");
  96. }
  97. return args->a_a.a_offset;
  98. case DCON:
  99. case DROM:
  100. sum = 0;
  101. for (arg = args; arg != (arg_p) 0; arg = arg->a_next) {
  102. /* Add the sizes of all initializers */
  103. sum += argsize(arg);
  104. }
  105. return sum;
  106. default:
  107. assert(FALSE);
  108. }
  109. /* NOTREACHED */
  110. }
  111. STATIC arg_p copy_arg(arg)
  112. arg_p arg;
  113. {
  114. /* Copy one argument */
  115. arg_p new;
  116. assert(arg->a_type == ARGOFF);
  117. new = newarg(ARGOFF);
  118. new->a_a.a_offset = arg->a_a.a_offset;
  119. return new;
  120. }
  121. STATIC arg_p copy_rom(args)
  122. arg_p args;
  123. {
  124. /* Make a copy of the values of a rom,
  125. * provided that the rom contains only integer values,
  126. */
  127. arg_p arg, arg2, argh;
  128. for (arg = args; arg != (arg_p) 0; arg = arg->a_next) {
  129. if (arg->a_type != ARGOFF) {
  130. return (arg_p) 0;
  131. }
  132. }
  133. /* Now make the copy */
  134. arg2 = argh = copy_arg(args);
  135. for (arg = args->a_next; arg != (arg_p) 0; arg = arg->a_next) {
  136. arg2->a_next = copy_arg(arg);
  137. arg2 = arg2->a_next;
  138. }
  139. return argh;
  140. }
  141. dblockdef(db,n,lnp)
  142. dblock_p db;
  143. int n;
  144. line_p lnp;
  145. {
  146. /* Process a data block defining occurrence */
  147. byte m;
  148. switch(n) {
  149. case ps_hol:
  150. m = DHOL;
  151. break;
  152. case ps_bss:
  153. m = DBSS;
  154. break;
  155. case ps_con:
  156. m = DCON;
  157. break;
  158. case ps_rom:
  159. m = DROM;
  160. break;
  161. default:
  162. assert(FALSE);
  163. }
  164. db->d_pseudo = m;
  165. db->d_size = blocksize(m, ARG(lnp));
  166. if (m == DROM) {
  167. /* We keep the values of a rom block in the data block
  168. * table if the values consist of integers only.
  169. */
  170. db->d_values = copy_rom(ARG(lnp));
  171. }
  172. }
  173. /* combine */
  174. combine(db,l1,l2,pseu)
  175. dblock_p db;
  176. line_p l1,l2;
  177. byte pseu;
  178. {
  179. /* Combine two successive ROMs/CONs (without a data label
  180. * in between into a single ROM. E.g.:
  181. * xyz
  182. * rom 3,6,9,12
  183. * rom 7,0,2
  184. * is changed into:
  185. * xyz
  186. * rom 3,6,9,12,7,0,2
  187. */
  188. arg_p v;
  189. db->d_size += blocksize(pseu,ARG(l2));
  190. /* db is the data block that was already assigned to the
  191. * first rom/con. The second one is not assigned a new
  192. * data block of course, as the two are combined into
  193. * one instruction.
  194. */
  195. if (pseu == DROM && db->d_values != (arg_p) 0) {
  196. /* The values contained in a ROM are only copied
  197. * to the data block if they may be useful to us
  198. * (e.g. they certainly may not be strings). In our
  199. * case it means that both ROMs must have useful
  200. * arguments.
  201. */
  202. for (v = db->d_values; v->a_next != (arg_p) 0; v = v->a_next);
  203. /* The first rom contained useful arguments. v now points to
  204. * its last argument. Append the arguments of the second
  205. * rom to this list. If the second rom has arguments that are
  206. * not useful, throw away the entire list (we want to copy
  207. * everything or nothing).
  208. */
  209. if ((v->a_next = copy_rom(ARG(l2))) == (arg_p) 0) {
  210. oldargs(db->d_values);
  211. db->d_values = (arg_p) 0;
  212. }
  213. }
  214. for (v = ARG(l1); v->a_next != (arg_p) 0; v = v->a_next);
  215. /* combine the arguments of both instructions. */
  216. v->a_next = ARG(l2);
  217. ARG(l2) = (arg_p) 0;
  218. }
  219. /* arglist */
  220. STATIC arg_string(length,abp)
  221. offset length;
  222. register argb_p abp;
  223. {
  224. while (length--) {
  225. if (abp->ab_index == NARGBYTES)
  226. abp = abp->ab_next = newargb();
  227. abp->ab_contents[abp->ab_index++] = readchar();
  228. }
  229. }
  230. line_p arglist(n)
  231. int n;
  232. {
  233. line_p lnp;
  234. register arg_p ap,*app;
  235. bool moretocome;
  236. offset length;
  237. /*
  238. * creates an arglist with n elements
  239. * if n == 0 the arglist is variable and terminated by sp_cend
  240. */
  241. lnp = newline(OPLIST);
  242. app = &ARG(lnp);
  243. moretocome = TRUE;
  244. do {
  245. switch(table2()) {
  246. default:
  247. error("unknown byte in arglist");
  248. case CSTX1:
  249. tabval2 = (offset) tabval;
  250. case CSTX2:
  251. *app = ap = newarg(ARGOFF);
  252. ap->a_a.a_offset = tabval2;
  253. app = &ap->a_next;
  254. break;
  255. case ILBX:
  256. *app = ap = newarg(ARGINSTRLAB);
  257. ap->a_a.a_instrlab = instr_lab((short) tabval);
  258. app = &ap->a_next;
  259. break;
  260. case DLBX:
  261. *app = ap = newarg(ARGOBJECT);
  262. ap->a_a.a_obj = object(string,(offset) 0, (offset) 0);
  263. /* The size of the object is unknown */
  264. app = &ap->a_next;
  265. break;
  266. case sp_pnam:
  267. *app = ap = newarg(ARGPROC);
  268. ap->a_a.a_proc = proclookup(string,OCCURRING);
  269. app = &ap->a_next;
  270. break;
  271. case VALX1:
  272. tabval2 = (offset) tabval;
  273. case VALX2:
  274. *app = ap = newarg(ARGOBJECT);
  275. ap->a_a.a_obj = object(string, tabval2, (offset) 0);
  276. app = &ap->a_next;
  277. break;
  278. case sp_scon:
  279. *app = ap = newarg(ARGSTRING);
  280. length = get_off();
  281. arg_string(length,&ap->a_a.a_string);
  282. app = &ap->a_next;
  283. break;
  284. case sp_icon:
  285. *app = ap = newarg(ARGICN);
  286. goto casecon;
  287. case sp_ucon:
  288. *app = ap = newarg(ARGUCN);
  289. goto casecon;
  290. case sp_fcon:
  291. *app = ap = newarg(ARGFCN);
  292. casecon:
  293. length = get_int();
  294. ap->a_a.a_con.ac_length = (short) length;
  295. arg_string(get_off(),&ap->a_a.a_con.ac_con);
  296. app = &ap->a_next;
  297. break;
  298. case sp_cend:
  299. moretocome = FALSE;
  300. }
  301. if (n && (--n) == 0)
  302. moretocome = FALSE;
  303. } while (moretocome);
  304. return(lnp);
  305. }
  306. /* is_datalabel */
  307. bool is_datalabel(l)
  308. line_p l;
  309. {
  310. VL(l);
  311. return (l->l_instr == (byte) ps_sym);
  312. }
  313. /* block_of_lab */
  314. dblock_p block_of_lab(ident)
  315. char *ident;
  316. {
  317. dblock_p dbl;
  318. /* Find the datablock with the given name.
  319. * Used for defining occurrences.
  320. */
  321. dbl = symlookup(ident,DEFINING);
  322. VD(dbl);
  323. if (dbl->d_pseudo != DUNKNOWN) {
  324. error("identifier %s redeclared", ident);
  325. }
  326. return dbl;
  327. }
  328. /* object */
  329. STATIC obj_p make_object(dbl,off,size)
  330. dblock_p dbl;
  331. offset off;
  332. offset size;
  333. {
  334. /* Allocate an obj struct with the given attributes
  335. * (if it did not exist already).
  336. * Return a pointer to the found or newly created object struct.
  337. */
  338. obj_p obj, prev, new;
  339. /* See if the object was already present in the object list
  340. * of the given datablock. If it is not yet present, find
  341. * the right place to insert the new object. Note that
  342. * the objects are sorted by offset.
  343. */
  344. prev = (obj_p) 0;
  345. for (obj = dbl->d_objlist; obj != (obj_p) 0; obj = obj->o_next) {
  346. if (obj->o_off >= off) {
  347. break;
  348. }
  349. prev = obj;
  350. }
  351. /* Note that the data block may contain several objects
  352. * with the required offset; we also want the size to
  353. * be the right one.
  354. */
  355. while (obj != (obj_p) 0 && obj->o_off == off) {
  356. if (obj->o_size == UNKNOWN_SIZE) {
  357. obj->o_size = size;
  358. return obj;
  359. } else {
  360. if (size == UNKNOWN_SIZE || obj->o_size == size) {
  361. return obj;
  362. /* This is the right one */
  363. } else {
  364. prev = obj;
  365. obj = obj->o_next;
  366. }
  367. }
  368. }
  369. /* Allocate a new object */
  370. new = newobject();
  371. new->o_id = ++lastoid; /* create a unique object id */
  372. new->o_off = off;
  373. new->o_size = size;
  374. new->o_dblock = dbl;
  375. /* Insert the new object */
  376. if (prev == (obj_p) 0) {
  377. dbl->d_objlist = new;
  378. } else {
  379. prev->o_next = new;
  380. }
  381. new->o_next = obj;
  382. return new;
  383. }
  384. obj_p object(ident,off,size)
  385. char *ident;
  386. offset off;
  387. offset size;
  388. {
  389. dblock_p dbl;
  390. /* Create an object struct (if it did not yet exist)
  391. * for the object with the given size and offset
  392. * within the datablock of the given name.
  393. */
  394. dbl = (ident == (char *) 0 ? hol0_db : symlookup(ident, OCCURRING));
  395. VD(dbl);
  396. return(make_object(dbl,off,size));
  397. }