ic_aux.c 8.8 KB

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