1 /* $Id: parser.c,v 1.7 1994/06/24 10:30:38 ceriel Exp $ */
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".
22 typedef struct class *class_p;
39 #include "classdefs.h"
40 /* The file classdefs.h contains the table classtab. It is
41 * generated automatically from the file classdefs.src.
44 STATIC bool classes(instr,src_out,res_out)
46 int *src_out, *res_out;
48 /* Determine the classes of the given instruction */
52 if (instr < sp_fmnem || instr > sp_lmnem) return FALSE;
54 if (c->src_class == NOCLASS) return FALSE;
55 *src_out = c->src_class;
56 *res_out = c->res_class;
62 STATIC bool uses_arg(class)
65 /* See if a member of the given class uses
85 STATIC bool uses_2args(class)
88 /* See if a member of the given class uses
92 return class == CLASS10;
96 STATIC bool parse_locs(l,c1_out,c2_out)
98 offset *c1_out, *c2_out;
100 if (INSTR(l) == op_loc && INSTR(PREV(l)) == op_loc) {
101 *c1_out = off_set(l);
102 *c2_out = off_set(PREV(l));
110 STATIC bool check_args(l,src_class,res_class,arg1_out,arg2_out)
112 int src_class,res_class;
113 offset *arg1_out, *arg2_out;
115 /* Several EM instructions have an argument
116 * giving the size of the operand(s) of
117 * the instruction. E.g. a 'adi 4' is a 4-byte
118 * addition. The size may also be put on the
119 * stack. In this case we give up our
120 * efforts to recognize the parameter expression.
121 * Some instructions (e.g. CIU) use 2 arguments
122 * that are both on the stack. In this case we
123 * check if both arguments are LOCs (the usual case),
127 if (uses_2args(src_class) || uses_2args(res_class)) {
128 return parse_locs(PREV(l),arg1_out,arg2_out);
130 if (uses_arg(src_class) || uses_arg(res_class)) {
131 if (TYPE(l) == OPSHORT) {
132 *arg1_out = (offset) SHORT(l);
135 if (TYPE(l) == OPOFFSET) {
136 *arg1_out = OFFSET(l);
142 return TRUE; /* no argument needed */
147 STATIC offset nrbytes(class,arg1,arg2)
151 /* Determine the number of bytes of the given
152 * arguments and class.
179 return (arg1 < ws ? ws : arg1);
188 STATIC attrib(l,expect_out,srcb_out,resb_out)
190 offset *expect_out, *srcb_out, *resb_out;
192 /* Determine a number of attributes of an EM
193 * instruction appearing in an expression.
194 * If it is something we don't
195 * expect in such expression (e.g. a store)
196 * expect_out is set to FALSE. Else we
197 * determine the number of bytes popped from
198 * the stack by the instruction and the
199 * number of bytes pushed on the stack as
203 int src_class,res_class;
206 if (l == (line_p) 0 || !classes(INSTR(l),&src_class,&res_class) ||
207 !check_args(l,src_class,res_class,&arg1,&arg2)) {
211 *srcb_out = nrbytes(src_class,arg1,arg2);
212 *resb_out = nrbytes(res_class,arg1,arg2);
218 bool parse(l,nbytes,l_out,level,action0)
224 /* This is a recursive descent parser for
226 * It tries to recognize EM code that loads exactly
227 * 'nbytes' bytes on the stack.
228 * 'l' is the last instruction of this code.
229 * As EM is essentially postfix, this instruction
230 * can be regarded as the root node of an expression
231 * tree. The EM code is traversed from right to left,
232 * i.e. top down. On success, TRUE is returned and
233 * 'l_out' will point to the first instruction
234 * of the recognized code. On toplevel, when an
235 * expression has been recognized, the procedure-parameter
236 * 'action0' is called, with parameters: the first and
237 * last instruction of the expression and the number of
241 offset more, expected, sourcebytes,resultbytes;
244 more = nbytes; /* #bytes to be recognized */
246 attrib(l,&expected,&sourcebytes,&resultbytes);
247 /* Get the attributes of EM instruction 'l'.
248 * 'expected' denotes if it is something we can use;
249 * 'sourcebytes' and 'resultbytes' are the number of
250 * bytes popped resp. pushed by the instruction
251 * (e.g. 'adi 2' pops 4 bytes and pushes 2 bytes).
253 if (!expected || (more -= resultbytes) < 0) return FALSE;
254 if (sourcebytes == 0) {
255 /* a leaf of the expression tree */
258 if (!parse(PREV(l),sourcebytes,&lnp,level+1,action0)) {
264 (*action0) (lnp,l,resultbytes);
268 /* Now we've recognized a number of expressions that
269 * together push nbytes on the stack.