Pristine Ack-5.5
[Ack-5.5.git] / mach / proto / ncg / compute.c
1 #ifndef NORCSID
2 static char rcsid[] = "$Id: compute.c,v 0.16 1994/06/24 13:27:05 ceriel Exp $";
3 #endif
4
5 #include "assert.h"
6 #include "param.h"
7 #include "tables.h"
8 #include "types.h"
9 #include <cgg_cg.h>
10 #include "data.h"
11 #include "result.h"
12 #include "glosym.h"
13 #include "extern.h"
14 #ifdef USE_TES
15 #include "label.h"
16 #endif
17
18 /*
19  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
20  * See the copyright notice in the ACK home directory, in the file "Copyright".
21  *
22  * Author: Hans van Staveren
23  */
24
25 #define LLEAF 01
26 #define LDEF  02
27 #define RLEAF 04
28 #define RDEF  010
29 #define LLDEF LLEAF|LDEF
30 #define RLDEF RLEAF|RDEF
31
32 char opdesc[] = {
33         0,                      /* EX_TOKFIELD */
34         0,                      /* EX_ARG */
35         0,                      /* EX_CON */
36         0,                      /* EX_ALLREG */
37         LLDEF|RLDEF,            /* EX_SAMESIGN */
38         LLDEF|RLDEF,            /* EX_SFIT */
39         LLDEF|RLDEF,            /* EX_UFIT */
40         0,                      /* EX_ROM */
41         LLDEF|RLDEF,            /* EX_NCPEQ */
42         LLDEF|RLDEF,            /* EX_SCPEQ */
43         LLDEF|RLDEF,            /* EX_RCPEQ */
44         LLDEF|RLDEF,            /* EX_NCPNE */
45         LLDEF|RLDEF,            /* EX_SCPNE */
46         LLDEF|RLDEF,            /* EX_RCPNE */
47         LLDEF|RLDEF,            /* EX_NCPGT */
48         LLDEF|RLDEF,            /* EX_NCPGE */
49         LLDEF|RLDEF,            /* EX_NCPLT */
50         LLDEF|RLDEF,            /* EX_NCPLE */
51         LLDEF,                  /* EX_OR2 */
52         LLDEF,                  /* EX_AND2 */
53         LLDEF|RLDEF,            /* EX_PLUS */
54         LLDEF|RLDEF,            /* EX_CAT */
55         LLDEF|RLDEF,            /* EX_MINUS */
56         LLDEF|RLDEF,            /* EX_TIMES */
57         LLDEF|RLDEF,            /* EX_DIVIDE */
58         LLDEF|RLDEF,            /* EX_MOD */
59         LLDEF|RLDEF,            /* EX_LSHIFT */
60         LLDEF|RLDEF,            /* EX_RSHIFT */
61         LLDEF,                  /* EX_NOT */
62         LLDEF,                  /* EX_COMP */
63         0,                      /* EX_COST */
64         0,                      /* EX_STRING */
65         LLEAF,                  /* EX_DEFINED */
66         0,                      /* EX_SUBREG */
67         LLDEF,                  /* EX_TOSTRING */
68         LLDEF,                  /* EX_UMINUS */
69         0,                      /* EX_REG */
70         0,                      /* EX_LOWW */
71         0,                      /* EX_HIGHW */
72         LLDEF,                  /* EX_INREG */
73         LLDEF,                  /* EX_REGVAR */
74         LLDEF|RLDEF,            /* EX_OR */
75         LLDEF|RLDEF,            /* EX_XOR */
76         LLDEF|RLDEF,            /* EX_AND */
77         0,                      /* EX_ISROM */
78 #ifdef USE_TES
79         0,                      /* EX_TOPELTSIZE */
80         0,                      /* EX_FALLTHROUGH */
81 #endif
82 };
83
84 string salloc(),strcpy(),strcat();
85
86 string mycat(s1,s2) register string s1,s2; {
87         register string s;
88
89         if (s1==0 || *s1=='\0') return(s2);
90         if (s2==0 || *s2=='\0') return(s1);
91         s=salloc(strlen(s1)+strlen(s2)+1);
92         strcpy(s,s1);
93         strcat(s,"+");
94         strcat(s,s2);
95         return(s);
96 }
97
98 string mystrcpy(s) register string s; {
99         register string r;
100
101         r=salloc(strlen(s));
102         strcpy(r,s);
103         return(r);
104 }
105
106 char digstr[21][15];
107
108 string tostring(n) register word n; {
109         char buf[25];
110
111         if (n>=-20 && n<=20 && (n&1)==0) {
112                 if (digstr[((int)n>>1)+10][0]==0)
113                         sprintf(digstr[((int)n>>1)+10],WRD_FMT,n);
114                 return(digstr[((int)n>>1)+10]);
115         }
116         sprintf(buf,WRD_FMT,n);
117         return(mystrcpy(buf));
118 }
119
120 compute(node, presult) register node_p node; register result_t *presult; {
121         result_t leaf1,leaf2;
122         register token_p tp;
123         int desc;
124         long mask,tmp;
125         int i,tmpreg;
126         glosym_p gp;
127
128         presult->e_typ = EV_UNDEF;
129         desc=opdesc[node->ex_operator];
130         if (desc&LLEAF) {
131                 compute(&enodes[node->ex_lnode], &leaf1);
132                 if (desc&LDEF && leaf1.e_typ==EV_UNDEF)
133                         return;
134         }
135         if (desc&RLEAF) {
136                 compute(&enodes[node->ex_rnode], &leaf2);
137                 if (desc&RDEF && leaf2.e_typ==EV_UNDEF)
138                         return;
139         }
140         presult->e_typ=EV_INT;
141         switch(node->ex_operator) {
142         default:        assert(FALSE);
143         case EX_TOKFIELD:
144                 if (node->ex_lnode==0)
145                         if (curtoken) tp = curtoken;
146                         else tp = &fakestack[stackheight-1];
147                 else    tp = &fakestack[stackheight-node->ex_lnode];
148                 switch(presult->e_typ = tokens[tp->t_token].t_type[node->ex_rnode-1]) {
149                 default:
150                         assert(FALSE);
151                 case EV_INT:
152                         presult->e_v.e_con = tp->t_att[node->ex_rnode-1].aw;
153                         break;
154                 case EV_ADDR:
155                         presult->e_v.e_addr = tp->t_att[node->ex_rnode-1].aa;
156                         break;
157                 case EV_REG:
158                         presult->e_v.e_reg = tp->t_att[node->ex_rnode-1].ar;
159                         break;
160                 }
161                 return;
162         case EX_ARG:
163                 *presult = dollar[node->ex_lnode-1];
164                 return;
165         case EX_CON:
166                 presult->e_typ = EV_INT;
167                 presult->e_v.e_con = ((long) node->ex_rnode << 16) | ((long)node->ex_lnode&0xffff);
168                 return;
169         case EX_REG:
170                 presult->e_typ = EV_REG;
171                 presult->e_v.e_reg = node->ex_lnode;
172                 return;
173         case EX_ALLREG:
174                 presult->e_typ = EV_REG;
175                 presult->e_v.e_reg = allreg[node->ex_lnode-1];
176 #if MAXMEMBERS!=0
177                 if (node->ex_rnode!=0)
178                         presult->e_v.e_reg = machregs[presult->e_v.e_reg].
179                                 r_members[node->ex_rnode-1];
180 #endif
181                 return;
182         case EX_SAMESIGN:
183         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
184                 presult->e_typ = EV_INT;
185                 if (leaf1.e_v.e_con>=0)
186                         presult->e_v.e_con= leaf2.e_v.e_con>=0;
187                 else
188                         presult->e_v.e_con= leaf2.e_v.e_con<0;
189                 return;
190         case EX_SFIT:
191         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
192                 mask = 0xFFFFFFFFL;
193                 for (i=0;i<leaf2.e_v.e_con-1;i++)
194                         mask &= ~(1<<i);
195                 tmp = leaf1.e_v.e_con&mask;
196                 presult->e_v.e_con = tmp==0||tmp==mask;
197                 return;
198         case EX_UFIT:
199         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
200                 mask = 0xFFFFFFFFL;
201                 for (i=0;i<leaf2.e_v.e_con;i++)
202                         mask &= ~(1<<i);
203                 presult->e_v.e_con = (leaf1.e_v.e_con&mask)==0;
204                 return;
205         case EX_ROM:
206                 assert(node->ex_rnode>=0 &&node->ex_rnode<MAXROM);
207                 leaf2=dollar[node->ex_lnode];
208                 presult->e_typ = EV_UNDEF;
209                 if (leaf2.e_typ != EV_ADDR)
210                         return;
211                 if (leaf2.e_v.e_addr.ea_off!=0)
212                         return;
213                 gp = lookglo(leaf2.e_v.e_addr.ea_str);
214                 if (gp == (glosym_p) 0)
215                         return;
216                 if ((gp->gl_rom[MAXROM]&(1<<node->ex_rnode))==0)
217                         return;
218                 presult->e_typ = EV_INT;
219                 presult->e_v.e_con = gp->gl_rom[node->ex_rnode];
220                 return;
221         case EX_ISROM:
222                 leaf2=dollar[node->ex_lnode];
223                 if (leaf2.e_typ != EV_ADDR)
224                         presult->e_v.e_con = 0;
225                 else
226                         presult->e_v.e_con = lookglo(leaf2.e_v.e_addr.ea_str) != 0;
227                 return;
228         case EX_LOWW:
229                 presult->e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper&0xFFFF;
230                 return;
231         case EX_HIGHW:
232                 presult->e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper>>16;
233                 return;
234         case EX_NCPEQ:
235         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
236                 presult->e_v.e_con = leaf1.e_v.e_con==leaf2.e_v.e_con;
237                 return;
238         case EX_SCPEQ:
239         assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
240                 presult->e_v.e_con =
241                     (strcmp(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str)==0 &&
242                     leaf1.e_v.e_addr.ea_off==leaf2.e_v.e_addr.ea_off);
243                 return;
244         case EX_RCPEQ:
245         assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
246                 presult->e_v.e_con = leaf1.e_v.e_reg==leaf2.e_v.e_reg;
247                 return;
248         case EX_NCPNE:
249         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
250                 presult->e_v.e_con = leaf1.e_v.e_con!=leaf2.e_v.e_con;
251                 return;
252         case EX_SCPNE:
253         assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
254                 presult->e_v.e_con =
255                     !(strcmp(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str)==0 &&
256                     leaf1.e_v.e_addr.ea_off==leaf2.e_v.e_addr.ea_off);
257                 return;
258         case EX_RCPNE:
259         assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
260                 presult->e_v.e_con = leaf1.e_v.e_reg!=leaf2.e_v.e_reg;
261                 return;
262         case EX_NCPGT:
263         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
264                 presult->e_v.e_con = leaf1.e_v.e_con>leaf2.e_v.e_con;
265                 return;
266         case EX_NCPGE:
267         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
268                 presult->e_v.e_con = leaf1.e_v.e_con>=leaf2.e_v.e_con;
269                 return;
270         case EX_NCPLT:
271         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
272                 presult->e_v.e_con = leaf1.e_v.e_con<leaf2.e_v.e_con;
273                 return;
274         case EX_NCPLE:
275         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
276                 presult->e_v.e_con = leaf1.e_v.e_con<=leaf2.e_v.e_con;
277                 return;
278         case EX_OR2:
279         assert(leaf1.e_typ == EV_INT);
280                 if (leaf1.e_v.e_con==0) {
281                         compute(&enodes[node->ex_rnode], presult);
282                 }
283                 else    *presult = leaf1;
284                 return;
285         case EX_AND2:
286         assert(leaf1.e_typ == EV_INT);
287                 if (leaf1.e_v.e_con!=0) {
288                         compute(&enodes[node->ex_rnode], presult);
289                 }
290                 else    *presult = leaf1;
291                 return;
292         case EX_PLUS:
293         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
294                 presult->e_v.e_con=leaf1.e_v.e_con+leaf2.e_v.e_con;
295                 return;
296         case EX_CAT:
297         assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
298                 presult->e_typ = EV_ADDR;
299                 presult->e_v.e_addr.ea_str = mycat(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str);
300                 presult->e_v.e_addr.ea_off = leaf1.e_v.e_addr.ea_off+leaf2.e_v.e_addr.ea_off;
301                 return;
302         case EX_MINUS:
303         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
304                 presult->e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con;
305                 return;
306         case EX_OR:
307         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
308                 presult->e_v.e_con = leaf1.e_v.e_con | leaf2.e_v.e_con;
309                 return;
310         case EX_XOR:
311         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
312                 presult->e_v.e_con = leaf1.e_v.e_con ^ leaf2.e_v.e_con;
313                 return;
314         case EX_AND:
315         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
316                 presult->e_v.e_con = leaf1.e_v.e_con & leaf2.e_v.e_con;
317                 return;
318         case EX_TIMES:
319         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
320                 presult->e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con;
321                 return;
322         case EX_DIVIDE:
323         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
324                 presult->e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con;
325                 return;
326         case EX_MOD:
327         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
328                 presult->e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con;
329                 return;
330         case EX_LSHIFT:
331         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
332                 presult->e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con;
333                 return;
334         case EX_RSHIFT:
335         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
336                 presult->e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con;
337                 return;
338         case EX_NOT:
339         assert(leaf1.e_typ == EV_INT);
340                 presult->e_v.e_con = !leaf1.e_v.e_con;
341                 return;
342         case EX_COMP:
343         assert(leaf1.e_typ == EV_INT);
344                 presult->e_v.e_con = ~leaf1.e_v.e_con;
345                 return;
346         case EX_STRING:
347                 presult->e_typ = EV_ADDR;
348                 presult->e_v.e_addr.ea_str = codestrings[node->ex_lnode];
349                 presult->e_v.e_addr.ea_off = 0;
350                 return;
351         case EX_DEFINED:
352                 presult->e_v.e_con=leaf1.e_typ!=EV_UNDEF;
353                 return;
354         case EX_SUBREG:
355                 presult->e_typ = EV_REG;
356                 if (node->ex_lnode==0)
357                         if (curtoken) tp = curtoken;
358                         else tp = &fakestack[stackheight-1];
359                 else    tp = &fakestack[stackheight-node->ex_lnode];
360                 assert(tp->t_token == -1);
361                 tmpreg= tp->t_att[0].ar;
362 #if MAXMEMBERS!=0
363                 if (node->ex_rnode)
364                         tmpreg=machregs[tmpreg].r_members[node->ex_rnode-1];
365 #endif
366                 presult->e_v.e_reg=tmpreg;
367                 return;
368         case EX_TOSTRING:
369         assert(leaf1.e_typ == EV_INT);
370                 presult->e_typ = EV_ADDR;
371                 presult->e_v.e_addr.ea_str = "";
372                 presult->e_v.e_addr.ea_off = leaf1.e_v.e_con;
373                 return;
374 #ifdef REGVARS
375         case EX_INREG:
376         assert(leaf1.e_typ == EV_INT);
377                 presult->e_v.e_con = isregtyp((long) leaf1.e_v.e_con);
378                 return;
379         case EX_REGVAR:
380         assert(leaf1.e_typ == EV_INT);
381                 i = isregvar((long) leaf1.e_v.e_con);
382                 if (i<=0)  {
383                         presult->e_typ = EV_UNDEF;
384                         return;
385                 }
386                 presult->e_typ = EV_REG;
387                 presult->e_v.e_reg=i;
388                 return;
389 #endif
390         case EX_UMINUS:
391         assert(leaf1.e_typ == EV_INT);
392                 presult->e_v.e_con = -leaf1.e_v.e_con;
393                 return;
394 #ifdef USE_TES
395         case EX_TOPELTSIZE:                     /* Hans, new */
396             { register label_p lbl;
397
398                 lbl = get_label(saveemp[node->ex_lnode].em_u.em_ioper);
399                 if (lbl != (label_p)0) {
400                     presult->e_v.e_con = lbl->lb_height;
401                 } else {
402                     presult->e_v.e_con = 0;
403                 }
404                 return;
405             }
406         case EX_FALLTHROUGH:                    /* Hans, new */
407             { register label_p lbl;
408
409                 lbl = get_label(saveemp[node->ex_lnode].em_u.em_ioper);
410                 if (lbl != (label_p)0) {
411                     presult->e_v.e_con = lbl->lb_fallthrough;
412                 } else presult->e_v.e_con = 0;
413                 return;
414             }
415 #endif
416         }
417 }