Pristine Ack-5.5
[Ack-5.5.git] / util / ego / cs / cs_partit.c
1 /* $Id: cs_partit.c,v 1.6 1994/06/24 10:22:34 ceriel Exp $ */
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 /* Functions to partition the huge set of EM-instructions. */
7
8 #include <em_mnem.h>
9 #include <em_pseu.h>
10 #include <em_reg.h>
11 #include <em_spec.h>
12 #include "../share/types.h"
13 #include "../share/aux.h"
14 #include "../share/debug.h"
15 #include "../share/global.h"
16 #include "cs.h"
17 #include "cs_stack.h"
18
19 #define XXX     (-1)
20 #define ARGW    0
21 #define WS      1
22 #define PS      2
23 #define FEF     3
24 #define FIF     4
25 #define CVT     5
26
27 #define ANY     0
28 #define PTR     1
29 #define FLT     2
30
31 STATIC struct {
32     byte i_group;   /* Group of instruction. */
33     byte i_op1;         /* Indication of size of operand of unary operator. */
34                         /* Idem for 1st operand of binary operator. */
35     byte i_op2;         /* Idem for 2nd operand of binary operator. */
36     byte i_av;          /* Idem for result of operators. */
37     byte i_regtype;     /* ANY, PTR, FLT. */
38 } info[] = {
39                 XXX,            XXX,    XXX,    XXX,    XXX,
40 /* aar */       TERNAIR_OP,     XXX,    XXX,    PS,     PTR,
41 /* adf */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   FLT,
42 /* adi */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
43 /* adp */       EXPENSIVE_LOAD, XXX,    XXX,    XXX,    PTR,
44 /* ads */       BINAIR_OP,      PS,     ARGW,   PS,     PTR,
45 /* adu */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
46 /* and */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
47 /* asp */       FIDDLE_STACK,   XXX,    XXX,    XXX,    XXX,
48 /* ass */       FIDDLE_STACK,   XXX,    XXX,    XXX,    XXX,
49 /* beq */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
50 /* bge */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
51 /* bgt */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
52 /* ble */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
53 /* blm */       HOPELESS,       XXX,    XXX,    XXX,    XXX,
54 /* bls */       HOPELESS,       XXX,    XXX,    XXX,    XXX,
55 /* blt */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
56 /* bne */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
57 /* bra */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
58 /* cai */       SIDE_EFFECTS,   XXX,    XXX,    XXX,    XXX,
59 /* cal */       SIDE_EFFECTS,   XXX,    XXX,    XXX,    XXX,
60 /* cff */       TERNAIR_OP,     XXX,    XXX,    CVT,    FLT,
61 /* cfi */       TERNAIR_OP,     XXX,    XXX,    CVT,    ANY,
62 /* cfu */       TERNAIR_OP,     XXX,    XXX,    CVT,    ANY,
63 /* cif */       TERNAIR_OP,     XXX,    XXX,    CVT,    FLT,
64 /* cii */       TERNAIR_OP,     XXX,    XXX,    CVT,    ANY,
65 /* ciu */       TERNAIR_OP,     XXX,    XXX,    CVT,    ANY,
66 /* cmf */       BINAIR_OP,      ARGW,   ARGW,   WS,     ANY,
67 /* cmi */       BINAIR_OP,      ARGW,   ARGW,   WS,     ANY,
68 /* cmp */       BINAIR_OP,      PS,     PS,     WS,     ANY,
69 /* cms */       BINAIR_OP,      ARGW,   ARGW,   WS,     ANY,
70 /* cmu */       BINAIR_OP,      ARGW,   ARGW,   WS,     ANY,
71 /* com */       UNAIR_OP,       ARGW,   XXX,    ARGW,   ANY,
72 /* csa */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
73 /* csb */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
74 /* cuf */       TERNAIR_OP,     XXX,    XXX,    CVT,    FLT,
75 /* cui */       TERNAIR_OP,     XXX,    XXX,    CVT,    ANY,
76 /* cuu */       TERNAIR_OP,     XXX,    XXX,    CVT,    ANY,
77 /* dch */       UNAIR_OP,       PS,     XXX,    PS,     PTR,
78 /* dec */       UNAIR_OP,       WS,     XXX,    WS,     ANY,
79 /* dee */       KILL_ENTITY,    XXX,    XXX,    XXX,    XXX,
80 /* del */       KILL_ENTITY,    XXX,    XXX,    XXX,    XXX,
81 /* dup */       FIDDLE_STACK,   XXX,    XXX,    XXX,    XXX,
82 /* dus */       FIDDLE_STACK,   XXX,    XXX,    XXX,    XXX,
83 /* dvf */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   FLT,
84 /* dvi */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
85 /* dvu */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
86 /* exg */       FIDDLE_STACK,   XXX,    XXX,    XXX,    XXX,
87 /* fef */       UNAIR_OP,       ARGW,   XXX,    FEF,    XXX,
88 /* fif */       BINAIR_OP,      ARGW,   ARGW,   FIF,    XXX,
89 /* fil */       IGNORE,         XXX,    XXX,    XXX,    XXX,
90 /* gto */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
91 /* inc */       UNAIR_OP,       WS,     XXX,    WS,     ANY,
92 /* ine */       KILL_ENTITY,    XXX,    XXX,    XXX,    XXX,
93 /* inl */       KILL_ENTITY,    XXX,    XXX,    XXX,    XXX,
94 /* inn */       BINAIR_OP,      ARGW,   WS,     WS,     ANY,
95 /* ior */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
96 /* lae */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
97 /* lal */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
98 /* lar */       LOAD_ARRAY,     XXX,    XXX,    XXX,    ANY,
99 /* ldc */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
100 /* lde */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
101 /* ldf */       EXPENSIVE_LOAD, XXX,    XXX,    XXX,    ANY,
102 /* ldl */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
103 /* lfr */       FIDDLE_STACK,   XXX,    XXX,    XXX,    XXX,
104 /* lil */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
105 /* lim */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
106 /* lin */       IGNORE,         XXX,    XXX,    XXX,    XXX,
107 /* lni */       IGNORE,         XXX,    XXX,    XXX,    XXX,
108 /* loc */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
109 /* loe */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
110 /* lof */       EXPENSIVE_LOAD, XXX,    XXX,    XXX,    ANY,
111 /* loi */       EXPENSIVE_LOAD, XXX,    XXX,    XXX,    ANY,
112 /* lol */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
113 /* lor */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
114 /* los */       FIDDLE_STACK,   XXX,    XXX,    XXX,    XXX,
115 /* lpb */       UNAIR_OP,       PS,     XXX,    PS,     PTR,
116 /* lpi */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
117 /* lxa */       EXPENSIVE_LOAD, XXX,    XXX,    XXX,    PTR,
118 /* lxl */       EXPENSIVE_LOAD, XXX,    XXX,    XXX,    PTR,
119 /* mlf */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   FLT,
120 /* mli */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
121 /* mlu */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
122 /* mon */       HOPELESS,       XXX,    XXX,    XXX,    XXX,
123 /* ngf */       UNAIR_OP,       ARGW,   XXX,    ARGW,   FLT,
124 /* ngi */       UNAIR_OP,       ARGW,   XXX,    ARGW,   ANY,
125 /* nop */       HOPELESS,       XXX,    XXX,    XXX,    XXX,
126 /* rck */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
127 /* ret */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
128 /* rmi */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
129 /* rmu */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
130 /* rol */       BINAIR_OP,      ARGW,   WS,     ARGW,   ANY,
131 /* ror */       BINAIR_OP,      ARGW,   WS,     ARGW,   ANY,
132 /* rtt */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
133 /* sar */       STORE_ARRAY,    XXX,    XXX,    XXX,    XXX,
134 /* sbf */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   FLT,
135 /* sbi */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
136 /* sbs */       BINAIR_OP,      PS,     PS,     ARGW,   ANY,
137 /* sbu */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
138 /* sde */       STORE_DIRECT,   XXX,    XXX,    XXX,    XXX,
139 /* sdf */       STORE_INDIR,    XXX,    XXX,    XXX,    XXX,
140 /* sdl */       STORE_DIRECT,   XXX,    XXX,    XXX,    XXX,
141 /* set */       UNAIR_OP,       WS,     XXX,    ARGW,   ANY,
142 /* sig */       FIDDLE_STACK,   XXX,    XXX,    XXX,    XXX,
143 /* sil */       STORE_INDIR,    XXX,    XXX,    XXX,    XXX,
144 /* sim */       STORE_DIRECT,   XXX,    XXX,    XXX,    XXX,
145 /* sli */       BINAIR_OP,      ARGW,   WS,     ARGW,   ANY,
146 /* slu */       BINAIR_OP,      ARGW,   WS,     ARGW,   ANY,
147 /* sri */       BINAIR_OP,      ARGW,   WS,     ARGW,   ANY,
148 /* sru */       BINAIR_OP,      ARGW,   WS,     ARGW,   ANY,
149 /* ste */       STORE_DIRECT,   XXX,    XXX,    XXX,    XXX,
150 /* stf */       STORE_INDIR,    XXX,    XXX,    XXX,    XXX,
151 /* sti */       STORE_INDIR,    XXX,    XXX,    XXX,    XXX,
152 /* stl */       STORE_DIRECT,   XXX,    XXX,    XXX,    XXX,
153 /* str */       HOPELESS,       XXX,    XXX,    XXX,    XXX,
154 /* sts */       HOPELESS,       XXX,    XXX,    XXX,    XXX,
155 /* teq */       UNAIR_OP,       WS,     XXX,    WS,     ANY,
156 /* tge */       UNAIR_OP,       WS,     XXX,    WS,     ANY,
157 /* tgt */       UNAIR_OP,       WS,     XXX,    WS,     ANY,
158 /* tle */       UNAIR_OP,       WS,     XXX,    WS,     ANY,
159 /* tlt */       UNAIR_OP,       WS,     XXX,    WS,     ANY,
160 /* tne */       UNAIR_OP,       WS,     XXX,    WS,     ANY,
161 /* trp */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
162 /* xor */       BINAIR_OP,      ARGW,   ARGW,   ARGW,   ANY,
163 /* zeq */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
164 /* zer */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
165 /* zge */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
166 /* zgt */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
167 /* zle */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
168 /* zlt */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
169 /* zne */       BBLOCK_END,     XXX,    XXX,    XXX,    XXX,
170 /* zre */       KILL_ENTITY,    XXX,    XXX,    XXX,    XXX,
171 /* zrf */       SIMPLE_LOAD,    XXX,    XXX,    XXX,    XXX,
172 /* zrl */       KILL_ENTITY,    XXX,    XXX,    XXX,    XXX
173 };
174
175 #define GROUP(n)        (info[n].i_group)
176 #define OP1SIZE(l)      (info[INSTR(l)].i_op1)
177 #define OP2SIZE(l)      (info[INSTR(l)].i_op2)
178 #define AVSIZE(l)       (info[INSTR(l)].i_av)
179 #define REGTYPE(n)      (info[n].i_regtype)
180
181 int instrgroup(lnp)
182         line_p lnp;
183 {
184         if (INSTR(lnp) == op_lor && SHORT(lnp) == 1) {
185                 /* We can't do anything with the stackpointer. */
186                 return FIDDLE_STACK;
187         }
188         if (INSTR(lnp) < sp_fmnem || INSTR(lnp) > sp_lmnem) {
189                 VI((short) INSTR(lnp));
190                 return IGNORE;
191         }
192         return GROUP(INSTR(lnp));
193 }
194
195 bool stack_group(instr)
196         int instr;
197 {
198         /* Is this an instruction that only does something to the top of
199          * the stack?
200          */
201         switch (GROUP(instr)) {
202                 case SIMPLE_LOAD:
203                 case EXPENSIVE_LOAD:
204                 case LOAD_ARRAY:
205                 case UNAIR_OP:
206                 case BINAIR_OP:
207                 case TERNAIR_OP:
208                         return TRUE;
209                 default:
210                         return FALSE;
211         }
212 }
213
214 STATIC offset argw(lnp)
215         line_p lnp;
216 {
217         /* Some EM-instructions have their argument either on the same line,
218          * or on top of the stack. We give up when the argument is on top of
219          * the stack.
220          */
221         struct token dummy;
222
223         if (TYPE(lnp) != OPNO) {
224                 return off_set(lnp);
225         } else {
226                 Pop(&dummy, (offset) ws);
227                 return UNKNOWN_SIZE;
228         }
229 }
230
231 offset op11size(lnp)
232         line_p lnp;
233 {
234         /* Returns the size of the first argument of
235          * the unary operator in lnp.
236          */
237
238         switch (OP1SIZE(lnp)) {
239                 case ARGW:
240                         return argw(lnp);
241                 case WS:
242                         return ws;
243                 case PS:
244                         return ps;
245                 default:
246                         assert(FALSE);
247         }
248         /* NOTREACHED */
249 }
250
251 offset op12size(lnp)
252         line_p lnp;
253 {
254         /* Same for first of binary. */
255
256         switch (OP1SIZE(lnp)) {
257                 case ARGW:
258                         return argw(lnp);
259                 case PS:
260                         return ps;
261                 default:
262                         assert(FALSE);
263         }
264         /* NOTREACHED */
265 }
266
267 offset op22size(lnp)
268         line_p lnp;
269 {
270         switch (OP2SIZE(lnp)) {
271                 case ARGW:
272                         return argw(lnp);
273                 case WS:
274                         return ws;
275                 case PS:
276                         return ps;
277                 default:
278                         assert(FALSE);
279         }
280         /* NOTREACHED */
281 }
282
283 /* Ternary operators are op_aar and conversions between types and/or sizes. */
284
285 offset op13size(lnp)
286         line_p lnp;
287 {
288         /* When the instruction is a conversion, the size of the first
289          * operand is the value of the second operand.
290          * We only handle the most likely case, namely that the second operand
291          * was pushed by a loc-instruction.
292          */
293         if (INSTR(lnp) == op_aar) return ps;
294
295         if (lnp->l_prev != (line_p) 0 &&
296             lnp->l_prev->l_prev != (line_p) 0 &&
297             INSTR(lnp->l_prev->l_prev) == op_loc
298            )
299                 return off_set(lnp->l_prev->l_prev);
300         else
301                 return UNKNOWN_SIZE;
302 }
303
304 offset op23size(lnp)
305         line_p lnp;
306 {
307         if (INSTR(lnp) == op_aar)
308                 return argw(lnp);
309         else
310                 return ws;
311 }
312
313 offset op33size(lnp)
314         line_p lnp;
315 {
316         if (INSTR(lnp) == op_aar)
317                 return ps;
318         else
319                 return ws;
320 }
321
322 offset avsize(lnp)
323         line_p lnp;
324 {
325         /* Returns the size of the result of the instruction in lnp.
326          * If the instruction is a conversion this size is given on the stack.
327          * We only handle the case that this value was pushed by a loc.
328          */
329         offset size;
330
331         switch (AVSIZE(lnp)) {
332                 case ARGW:
333                         return argw(lnp);
334                 case WS:
335                         return ws;
336                 case PS:
337                         return ps;
338                 case FEF:
339                         if ((size = argw(lnp)) != UNKNOWN_SIZE)
340                                 return size + ws;
341                         else
342                                 return UNKNOWN_SIZE;
343                 case FIF:
344                         if ((size = argw(lnp)) != UNKNOWN_SIZE)
345                                 return size + size;
346                         else
347                                 return UNKNOWN_SIZE;
348                 case CVT:
349                         if (lnp->l_prev != (line_p) 0 &&
350                             INSTR(lnp->l_prev) == op_loc
351                            )
352                                 return off_set(lnp->l_prev);
353                         else
354                                 return UNKNOWN_SIZE;
355                 default:
356                         assert(FALSE);
357                         break;
358         }
359         /* NOTREACHED */
360 }
361
362 int regtype(instr)
363         byte instr;
364 {
365         switch (REGTYPE(instr & BMASK)) {
366                 case ANY:
367                         return reg_any;
368                 case PTR:
369                         return reg_pointer;
370                 case FLT:
371                         return reg_float;
372                 default:
373                         assert(FALSE);
374         }
375         /* NOTREACHED */
376 }