Pristine Ack-5.5
[Ack-5.5.git] / util / opt / tes.c
1 #ifndef NORCSID
2 static char rcsid[] = "$Id: tes.c,v 1.6 1994/06/24 10:41:04 ceriel Exp $";
3 #endif
4 /*
5  * This file contains the main part of the top element size computation phase. 
6  *
7  * Author: Hans van Eck. 
8  */
9
10 #include <stdio.h>
11 #include <em_spec.h>
12 #include <em_mnem.h>
13 #include <em_pseu.h>
14 #include "param.h"
15 #include "assert.h"
16 #include "types.h"
17 #include "tes.h"
18 #include "alloc.h"
19 #include "proinf.h"
20 #include "line.h"
21 #include "ext.h"
22 #include "pop_push.h"
23
24 extern char *pop_push[];
25 extern char flow_tab[];
26
27 #define NON_CONTINUABLE(i)      (flow_tab[i]&JUMP)
28 #define ISABRANCH(i)            (flow_tab[i]&HASLABEL)
29 #define ISCONDBRANCH(i)         (flow_tab[i]&CONDBRA)
30
31 #define INSTR(lnp)      (lnp->l_instr & BMASK)
32 #define TYPE(lnp)       lnp->l_optyp
33 #define SHORT(lnp)      lnp->l_a.la_short
34 #define MINI(lnp)       ((lnp->l_optyp & BMASK) - Z_OPMINI)
35
36 #define IS_MINI(lnp)    (lnp->l_optyp >= OPMINI)
37 #define IS_LOC(l)       (l!=(line_p) 0 && INSTR(l)==op_loc && IS_MINI(l))
38
39 int state;
40 static int stacktop = 0;
41
42 init_state()
43 {
44         stacktop = 0;
45         state = KNOWN;
46 }
47
48 tes_pseudos()
49 {
50         register line_p lp;
51
52         for (lp = pseudos; lp != (line_p)0; lp = lp->l_next) {
53                 switch(INSTR(lp)) {
54                 case ps_con:
55                 case ps_rom:
56                         if (lp->l_optyp == OPLIST) {
57                                 register arg_p ap = lp->l_a.la_arg;
58
59                                 while (ap != (arg_p) 0) {
60                                         if (ap->a_typ == ARGNUM) {
61                                                 assign_label(ap->a_a.a_np->n_repl);
62                                         }
63                                         ap = ap->a_next;
64                                 }
65                         } else if (lp->l_optyp == OPNUMLAB)
66                                 assign_label(lp->l_a.la_np->n_repl);
67                 }
68         }
69 }
70
71 tes_instr(lnp, x, y)
72 line_p lnp, x, y;
73 {
74         char *s;
75         register instr = INSTR(lnp);
76         register int arg, argdef;
77         int neg = 0;
78
79         if (instr == op_lab) {
80                 do_inst_label(lnp);
81                 return;
82         }
83         if (instr < sp_fmnem || instr > sp_lmnem) {
84                 return;
85         }
86
87         if (state == NOTREACHED) return;        /* What else ? */
88         s = pop_push[instr];
89
90         if (*s != '0') {
91                 while (*s != '\0') {
92                         neg = (*s++ == '-');
93
94                         if (TYPE(lnp) == OPSHORT) {
95                                 arg = SHORT(lnp);
96                                 if (arg < wordsize) arg = wordsize;
97                                 argdef = TRUE;
98                         } else if (IS_MINI(lnp)) {
99                                 arg = MINI(lnp);
100                                 if (arg > 0 && arg < wordsize) arg = wordsize;
101                                 if (arg < 0 && -arg < wordsize) arg = -wordsize;
102                                 argdef = TRUE;
103                         } else {
104                                 argdef = FALSE;
105                         }
106                         switch (*s++) {
107                         case 'w': stacktop = wordsize; break;
108                         case 'd': stacktop = wordsize * 2; break;
109                         case 'p': stacktop = pointersize; break;
110                         case 'a':
111                                 if (argdef == FALSE || instr == op_ass) {
112                                         stacktop = 0;
113                                 } else {
114                                         stacktop = arg;
115                                 }
116                                 break;
117                         case 'x':
118                                 if (IS_LOC(x)) {
119                                         arg = MINI(x);
120                                         if (arg < wordsize) arg = wordsize;
121                                         stacktop = arg;
122                                 } else {
123                                         stacktop = 0;
124                                 }
125                                 break;
126                         case 'y':
127                                 if (IS_LOC(y)) {
128                                         arg = MINI(y);
129                                         if (arg < wordsize) arg = wordsize;
130                                         stacktop = arg;
131                                 } else {
132                                         stacktop = 0;
133                                 }
134                                 break;
135                         case '?':
136                                 stacktop = 0;
137                                 break;
138                         default:
139                                 assert(FALSE);
140                         }
141                 }
142                 /*
143                  * When the last argument was negative, the element size
144                  * must be negated.  This is to catch 'asp -4'.
145                  */
146                 if (neg) stacktop = -stacktop;
147         }
148
149         if (stacktop < 0) stacktop = 0;
150
151         if (ISABRANCH(instr)) do_inst_label(lnp);
152         if (NON_CONTINUABLE(instr)) {
153                 state = NOTREACHED;
154                 stacktop = 0;
155         }
156 }
157
158 assign_label(label)
159 register num_p label;
160 {
161         if (label->n_flags & NUMSET) {
162                 if (state == NOTREACHED || stacktop > label->n_size) {
163                         stacktop = label->n_size;
164                 } else if ( stacktop < label->n_size) {
165                         label->n_size = stacktop;
166                 }
167         } else {
168                 label->n_size = stacktop;
169                 label->n_flags |= NUMSET;
170         }
171 }
172
173 do_inst_label(lnp)      /* (re-)install a label */
174 line_p lnp;
175 {
176         num_p label = lnp->l_a.la_np->n_repl;
177         int instr = INSTR(lnp);
178
179         assign_label(label);
180
181         if (instr == op_lab) {
182                 if (state == NOTREACHED)  {
183                 } else {
184                         label->n_flags |= NUMFALLTHROUGH;
185                 }
186         } else if (ISCONDBRANCH(instr)) {       /* conditional branch */
187                 label->n_flags |= NUMCOND;
188         }
189         state = KNOWN;
190 }