parser.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. #include <stdio.h>
  7. #include <em_spec.h>
  8. #include <em_mnem.h>
  9. #include "types.h"
  10. #include "debug.h"
  11. #include "alloc.h"
  12. #include "global.h"
  13. #include "lset.h"
  14. #include "aux.h"
  15. struct class {
  16. byte src_class;
  17. byte res_class;
  18. };
  19. typedef struct class *class_p;
  20. #define NOCLASS 0
  21. #define CLASS1 1
  22. #define CLASS2 2
  23. #define CLASS3 3
  24. #define CLASS4 4
  25. #define CLASS5 5
  26. #define CLASS6 6
  27. #define CLASS7 7
  28. #define CLASS8 8
  29. #define CLASS9 9
  30. #define CLASS10 10
  31. #define CLASS11 11
  32. #define CLASS12 12
  33. #include "classdefs.h"
  34. /* The file classdefs.h contains the table classtab. It is
  35. * generated automatically from the file classdefs.src.
  36. */
  37. STATIC bool classes(instr,src_out,res_out)
  38. int instr;
  39. int *src_out, *res_out;
  40. {
  41. /* Determine the classes of the given instruction */
  42. class_p c;
  43. if (instr < sp_fmnem || instr > sp_lmnem) return FALSE;
  44. c = &classtab[instr];
  45. if (c->src_class == NOCLASS) return FALSE;
  46. *src_out = c->src_class;
  47. *res_out = c->res_class;
  48. return TRUE;
  49. }
  50. STATIC bool uses_arg(class)
  51. int class;
  52. {
  53. /* See if a member of the given class uses
  54. * an argument.
  55. */
  56. switch(class) {
  57. case CLASS1:
  58. case CLASS2:
  59. case CLASS3:
  60. case CLASS4:
  61. case CLASS11:
  62. case CLASS12:
  63. return TRUE;
  64. default:
  65. return FALSE;
  66. }
  67. /* NOTREACHED */
  68. }
  69. STATIC bool uses_2args(class)
  70. int class;
  71. {
  72. /* See if a member of the given class uses
  73. * 2 arguments.
  74. */
  75. return class == CLASS10;
  76. }
  77. STATIC bool parse_locs(l,c1_out,c2_out)
  78. line_p l;
  79. offset *c1_out, *c2_out;
  80. {
  81. if (INSTR(l) == op_loc && INSTR(PREV(l)) == op_loc) {
  82. *c1_out = off_set(l);
  83. *c2_out = off_set(PREV(l));
  84. return TRUE;
  85. }
  86. return FALSE;
  87. }
  88. STATIC bool check_args(l,src_class,res_class,arg1_out,arg2_out)
  89. line_p l;
  90. int src_class,res_class;
  91. offset *arg1_out, *arg2_out;
  92. {
  93. /* Several EM instructions have an argument
  94. * giving the size of the operand(s) of
  95. * the instruction. E.g. a 'adi 4' is a 4-byte
  96. * addition. The size may also be put on the
  97. * stack. In this case we give up our
  98. * efforts to recognize the parameter expression.
  99. * Some instructions (e.g. CIU) use 2 arguments
  100. * that are both on the stack. In this case we
  101. * check if both arguments are LOCs (the usual case),
  102. * else we give up.
  103. */
  104. if (uses_2args(src_class) || uses_2args(res_class)) {
  105. return parse_locs(PREV(l),arg1_out,arg2_out);
  106. }
  107. if (uses_arg(src_class) || uses_arg(res_class)) {
  108. if (TYPE(l) == OPSHORT) {
  109. *arg1_out = (offset) SHORT(l);
  110. return TRUE;
  111. } else {
  112. if (TYPE(l) == OPOFFSET) {
  113. *arg1_out = OFFSET(l);
  114. } else {
  115. return FALSE;
  116. }
  117. }
  118. }
  119. return TRUE; /* no argument needed */
  120. }
  121. STATIC offset nrbytes(class,arg1,arg2)
  122. int class;
  123. offset arg1,arg2;
  124. {
  125. /* Determine the number of bytes of the given
  126. * arguments and class.
  127. */
  128. switch(class) {
  129. case CLASS1:
  130. return arg1;
  131. case CLASS2:
  132. return 2 * arg1;
  133. case CLASS3:
  134. return arg1 + ws;
  135. case CLASS4:
  136. return arg1 + ps;
  137. case CLASS5:
  138. return ws;
  139. case CLASS6:
  140. return 2 * ws;
  141. case CLASS7:
  142. return ps;
  143. case CLASS8:
  144. return 2 * ps;
  145. case CLASS9:
  146. return 0;
  147. case CLASS10:
  148. return arg2 + 2*ws;
  149. case CLASS11:
  150. return arg1 + 2*ps;
  151. case CLASS12:
  152. return (arg1 < ws ? ws : arg1);
  153. default:
  154. assert(FALSE);
  155. }
  156. return 0;
  157. }
  158. STATIC attrib(l,expect_out,srcb_out,resb_out)
  159. line_p l;
  160. offset *expect_out, *srcb_out, *resb_out;
  161. {
  162. /* Determine a number of attributes of an EM
  163. * instruction appearing in an expression.
  164. * If it is something we don't
  165. * expect in such expression (e.g. a store)
  166. * expect_out is set to FALSE. Else we
  167. * determine the number of bytes popped from
  168. * the stack by the instruction and the
  169. * number of bytes pushed on the stack as
  170. * result.
  171. */
  172. int src_class,res_class;
  173. offset arg1, arg2;
  174. if (l == (line_p) 0 || !classes(INSTR(l),&src_class,&res_class) ||
  175. !check_args(l,src_class,res_class,&arg1,&arg2)) {
  176. *expect_out = FALSE;
  177. } else {
  178. *expect_out = TRUE;
  179. *srcb_out = nrbytes(src_class,arg1,arg2);
  180. *resb_out = nrbytes(res_class,arg1,arg2);
  181. }
  182. }
  183. bool parse(l,nbytes,l_out,level,action0)
  184. line_p l, *l_out;
  185. offset nbytes;
  186. int level;
  187. int (*action0) ();
  188. {
  189. /* This is a recursive descent parser for
  190. * EM expressions.
  191. * It tries to recognize EM code that loads exactly
  192. * 'nbytes' bytes on the stack.
  193. * 'l' is the last instruction of this code.
  194. * As EM is essentially postfix, this instruction
  195. * can be regarded as the root node of an expression
  196. * tree. The EM code is traversed from right to left,
  197. * i.e. top down. On success, TRUE is returned and
  198. * 'l_out' will point to the first instruction
  199. * of the recognized code. On toplevel, when an
  200. * expression has been recognized, the procedure-parameter
  201. * 'action0' is called, with parameters: the first and
  202. * last instruction of the expression and the number of
  203. * bytes recognized.
  204. */
  205. offset more, expected, sourcebytes,resultbytes;
  206. line_p lnp = 0;
  207. more = nbytes; /* #bytes to be recognized */
  208. while (more > 0) {
  209. attrib(l,&expected,&sourcebytes,&resultbytes);
  210. /* Get the attributes of EM instruction 'l'.
  211. * 'expected' denotes if it is something we can use;
  212. * 'sourcebytes' and 'resultbytes' are the number of
  213. * bytes popped resp. pushed by the instruction
  214. * (e.g. 'adi 2' pops 4 bytes and pushes 2 bytes).
  215. */
  216. if (!expected || (more -= resultbytes) < 0) return FALSE;
  217. if (sourcebytes == 0) {
  218. /* a leaf of the expression tree */
  219. lnp = l;
  220. } else {
  221. if (!parse(PREV(l),sourcebytes,&lnp,level+1,action0)) {
  222. return FALSE;
  223. }
  224. }
  225. if (level == 0) {
  226. /* at toplevel */
  227. (*action0) (lnp,l,resultbytes);
  228. }
  229. l = PREV(lnp);
  230. }
  231. /* Now we've recognized a number of expressions that
  232. * together push nbytes on the stack.
  233. */
  234. *l_out = lnp;
  235. return TRUE;
  236. }