parser.c 5.7 KB

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