Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110504180232

Diff

Diff from 1.271 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/mip/reader.c

Annotated File View

ragge
1.271
1 /*      $Id: reader.c,v 1.271 2011/05/04 18:02:32 ragge Exp $   */
ragge
1.72
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
ragge
1.31
29 /*
30  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  *
36  * Redistributions of source code and documentation must retain the above
37  * copyright notice, this list of conditions and the following disclaimer.
38  * Redistributions in binary form must reproduce the above copyright
39  * notice, this list of conditionsand the following disclaimer in the
40  * documentation and/or other materials provided with the distribution.
41  * All advertising materials mentioning features or use of this software
42  * must display the following acknowledgement:
43  *      This product includes software developed or owned by Caldera
44  *      International, Inc.
45  * Neither the name of Caldera International, Inc. nor the names of other
46  * contributors may be used to endorse or promote products derived from
47  * this software without specific prior written permission.
48  *
49  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
50  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
51  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
54  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
58  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
59  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
60  * POSSIBILITY OF SUCH DAMAGE.
61  */
ragge
1.1
62
ragge
1.123
63 /*
ragge
1.236
64  * Everything is entered via pass2_compile().  No functions are 
65  * allowed to recurse back into pass2_compile().
ragge
1.123
66  */
67
ragge
1.1
68 # include "pass2.h"
69
ragge
1.70
70 #include <string.h>
ragge
1.71
71 #include <stdarg.h>
ragge
1.94
72 #include <stdlib.h>
ragge
1.70
73
ragge
1.1
74 /*      some storage declarations */
75 int nrecur;
76 int lflag;
mickey
1.258
77 int x2debugudebugodebug;
ragge
1.103
78 int thisline;
ragge
1.72
79 int fregs;
ragge
1.123
80 int p2autooffp2maxautooff;
ragge
1.1
81
ragge
1.72
82 NODE *nodepole;
ragge
1.197
83 FILE *prfil;
ragge
1.238
84 struct interpass prepole;
ragge
1.23
85
ragge
1.37
86 void saveip(struct interpass *ip);
ragge
1.243
87 void deltemp(NODE *pvoid *);
ragge
1.232
88 static void cvtemps(struct interpass *ipoleint opint off);
ragge
1.72
89 NODE *store(NODE *);
ragge
1.242
90 static void fixxasm(struct p2env *);
ragge
1.65
91
ragge
1.72
92 static void gencode(NODE *pint cookie);
ragge
1.216
93 static void genxasm(NODE *p);
ragge
1.271
94 static void afree(void);
ragge
1.69
95
ragge
1.246
96 struct p2env p2env;
ragge
1.121
97
ragge
1.246
98 int
99 getlab2(void)
100 {
101         extern int getlab(void);
102         int rv = getlab();
103 #ifdef PCC_DEBUG
104         if (p2env.epp->ip_lblnum != rv)
105                 comperr("getlab2 error: %d != %d"p2env.epp->ip_lblnumrv);
106 #endif
107         p2env.epp->ip_lblnum++;
108         return rv;
109 }
ragge
1.241
110
ragge
1.26
111 #ifdef PCC_DEBUG
ragge
1.241
112 static int *lbldef, *lbluse;
ragge
1.26
113 static void
ragge
1.243
114 cktree(NODE *pvoid *arg)
ragge
1.26
115 {
ragge
1.241
116         int i;
117
ragge
1.26
118         if (p->n_op > MAXOP)
ragge
1.218
119                 cerror("%p) op %d slipped through"pp->n_op);
ragge
1.199
120         if (BTYPE(p->n_type) > MAXTYPES)
ragge
1.218
121                 cerror("%p) type %x slipped through"pp->n_type);
ragge
1.241
122         if (p->n_op == CBRANCH) {
123                  if (!logop(p->n_left->n_op))
124                         cerror("%p) not logop branch"p);
gmcgarry
1.251
125                 i = (int)p->n_right->n_lval;
ragge
1.242
126                 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
ragge
1.241
127                         cerror("%p) label %d outside boundaries %d-%d",
ragge
1.242
128                             pip2env.ipp->ip_lblnump2env.epp->ip_lblnum);
129                 lbluse[i-p2env.ipp->ip_lblnum] = 1;
ragge
1.241
130         }
ragge
1.47
131         if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
ragge
1.218
132                 cerror("%p) asgop %d slipped through"pp->n_op);
ragge
1.241
133         if (p->n_op == TEMP &&
ragge
1.242
134             (regno(p) < p2env.ipp->ip_tmpnum || regno(p) >= p2env.epp->ip_tmpnum))
ragge
1.241
135                 cerror("%p) temporary %d outside boundaries %d-%d",
ragge
1.242
136                     pregno(p), p2env.ipp->ip_tmpnump2env.epp->ip_tmpnum);
ragge
1.249
137         if (p->n_op == GOTO && p->n_left->n_op == ICON) {
gmcgarry
1.251
138                 i = (int)p->n_left->n_lval;
ragge
1.242
139                 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
ragge
1.241
140                         cerror("%p) label %d outside boundaries %d-%d",
ragge
1.242
141                             pip2env.ipp->ip_lblnump2env.epp->ip_lblnum);
142                 lbluse[i-p2env.ipp->ip_lblnum] = 1;
ragge
1.241
143         }
144 }
145
146 /*
147  * Check that the trees are in a suitable state for pass2.
148  */
149 static void
ragge
1.244
150 sanitychecks(struct p2env *p2e)
ragge
1.241
151 {
152         struct interpass *ip;
153         int i;
154 #ifdef notyet
155         TMPMARK();
156 #endif
ragge
1.244
157         lbldef = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
158         lbluse = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
ragge
1.241
159
ragge
1.242
160         DLIST_FOREACH(ip, &p2env.ipoleqelem) {
ragge
1.241
161                 if (ip->type == IP_DEFLAB) {
162                         i = ip->ip_lbl;
ragge
1.244
163                         if (i < p2e->ipp->ip_lblnum || i >= p2e->epp->ip_lblnum)
ragge
1.241
164                                 cerror("label %d outside boundaries %d-%d",
ragge
1.244
165                                     ip2e->ipp->ip_lblnump2e->epp->ip_lblnum);
166                         lbldef[i-p2e->ipp->ip_lblnum] = 1;
ragge
1.241
167                 }
168                 if (ip->type == IP_NODE)
ragge
1.243
169                         walkf(ip->ip_nodecktree0);
ragge
1.241
170         }
ragge
1.244
171         for (i = 0i < (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum); i++)
ragge
1.241
172                 if (lbluse[i] != 0 && lbldef[i] == 0)
173                         cerror("internal label %d not defined",
ragge
1.244
174                             i + p2e->ipp->ip_lblnum);
ragge
1.241
175
176 #ifdef notyet
177         TMPFREE();
178 #endif
ragge
1.26
179 }
180 #endif
ragge
1.8
181
ragge
1.130
182 /*
ragge
1.244
183  * Look if a temporary comes from a on-stack argument, in that case
184  * use the already existing stack position instead of moving it to
185  * a new place, and remove the move-to-temp statement.
186  */
187 static int
188 stkarg(int tnrint *soff)
189 {
190         struct p2env *p2e = &p2env;
191         struct interpass *ip;
192         NODE *p;
193
ragge
1.248
194         ip = DLIST_NEXT((struct interpass *)p2e->ippqelem);
195         while (ip->type != IP_DEFLAB/* search for first DEFLAB */
196                 ip = DLIST_NEXT(ipqelem);
197
ragge
1.244
198         ip = DLIST_NEXT(ipqelem); /* first NODE */
199
200         for (; ip->type != IP_DEFLABip = DLIST_NEXT(ipqelem)) {
201                 if (ip->type != IP_NODE)
202                         continue;
203
204                 p = ip->ip_node;
ragge
1.247
205                 if (p->n_op == XASM)
206                         continue/* XXX - hack for x86 PIC */
ragge
1.264
207 #ifdef notdef
ragge
1.244
208                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
209                         comperr("temparg");
210 #endif
ragge
1.264
211                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
212                         continue/* unknown tree */
213
ragge
1.244
214                 if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL)
215                         continue/* arg in register */
216                 if (tnr != regno(p->n_left))
217                         continue/* wrong assign */
218                 p = p->n_right;
219                 if (p->n_op == UMUL &&
220                     p->n_left->n_op == PLUS &&
221                     p->n_left->n_left->n_op == REG &&
222                     p->n_left->n_right->n_op == ICON)
gmcgarry
1.251
223                         *soff = (int)p->n_left->n_right->n_lval;
ragge
1.244
224                 else if (p->n_op == OREG)
gmcgarry
1.251
225                         *soff = (int)p->n_lval;
ragge
1.244
226                 else
227                         comperr("stkarg: bad arg");
228                 tfree(ip->ip_node);
229                 DLIST_REMOVE(ipqelem);
230                 return 1;
231         }
232         return 0;
233 }
234
235 /*
236  * See if an ADDROF is somewhere inside the expression tree.
237  * If so, fill in the offset table.
238  */
239 static void
240 findaof(NODE *pvoid *arg)
241 {
242         int *aof = arg;
243         int tnr;
244
ragge
1.263
245         if (p->n_op != ADDROF || p->n_left->n_op != TEMP)
ragge
1.244
246                 return;
247         tnr = regno(p->n_left);
248         if (aof[tnr])
249                 return/* already gotten stack address */
250         if (stkarg(tnr, &aof[tnr]))
251                 return/* argument was on stack */
252         aof[tnr] = BITOOR(freetemp(szty(p->n_left->n_type)));
253 }
254
255 /*
ragge
1.89
256  * Check if a node has side effects.
257  */
258 static int
259 isuseless(NODE *n)
260 {
261         switch (n->n_op) {
ragge
1.216
262         case XASM:
ragge
1.89
263         case FUNARG:
264         case UCALL:
265         case UFORTCALL:
266         case FORCE:
267         case ASSIGN:
268         case CALL:
269         case FORTCALL:
270         case CBRANCH:
271         case RETURN:
272         case GOTO:
273         case STCALL:
274         case USTCALL:
275         case STASG:
276         case STARG:
277                 return 0;
278         default:
279                 return 1;
280         }
281 }
282
ragge
1.130
283 /*
284  * Delete statements with no meaning (like a+b; or 513.4;)
285  */
ragge
1.238
286 NODE *
ragge
1.89
287 deluseless(NODE *p)
288 {
289         struct interpass *ip;
290         NODE *l, *r;
291
292         if (optype(p->n_op) == LTYPE) {
293                 nfree(p);
294                 return NULL;
295         }
296         if (isuseless(p) == 0)
297                 return p;
298
299         if (optype(p->n_op) == UTYPE) {
300                 l = p->n_left;
301                 nfree(p);
302                 return deluseless(l);
303         }
304
305         /* Be sure that both leaves may be valid */
306         l = deluseless(p->n_left);
307         r = deluseless(p->n_right);
308         nfree(p);
309         if (l && r) {
ragge
1.201
310                 ip = ipnode(l);
311                 DLIST_INSERT_AFTER(&prepoleipqelem);
ragge
1.89
312                 return r;
313         } else if (l)
314                 return l;
315         else if (r)
316                 return r;
317         return NULL;
318 }
319
ragge
1.172
320 /*
321  * Receives interpass structs from pass1.
322  */
323 void
324 pass2_compile(struct interpass *ip)
325 {
ragge
1.260
326         void deljumps(struct p2env *);
ragge
1.244
327         struct p2env *p2e = &p2env;
328         int *addrp;
ragge
1.245
329         MARK mark;
ragge
1.244
330
ragge
1.172
331         if (ip->type == IP_PROLOG) {
ragge
1.244
332                 memset(p2e0sizeof(struct p2env));
333                 p2e->ipp = (struct interpass_prolog *)ip;
334                 DLIST_INIT(&p2e->ipoleqelem);
ragge
1.172
335         }
ragge
1.244
336         DLIST_INSERT_BEFORE(&p2e->ipoleipqelem);
ragge
1.172
337         if (ip->type != IP_EPILOG)
338                 return;
339
340 #ifdef PCC_DEBUG
341         if (e2debug) {
342                 printf("Entering pass2\n");
ragge
1.244
343                 printip(&p2e->ipole);
ragge
1.172
344         }
345 #endif
ragge
1.174
346
ragge
1.271
347         afree();
ragge
1.244
348         p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipoleqelem);
349         p2maxautooff = p2autooff = p2e->epp->ipp_autos;
ragge
1.174
350
ragge
1.241
351 #ifdef PCC_DEBUG
ragge
1.244
352         sanitychecks(p2e);
ragge
1.241
353 #endif
ragge
1.244
354         myreader(&p2e->ipole); /* local massage of input */
ragge
1.174
355
ragge
1.244
356         /*
357          * Do initial modification of the trees.  Two loops;
358          * - first, search for ADDROF of TEMPs, these must be
359          *   converterd to OREGs on stack.
360          * - second, do the actual conversions, in case of not xtemps
361          *   convert all temporaries to stack references.
362          */
ragge
1.245
363         markset(&mark);
ragge
1.244
364         if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) {
365                 addrp = tmpcalloc(sizeof(int) *
366                     (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum));
367                 addrp -= p2e->ipp->ip_tmpnum;
368         } else
369                 addrp = NULL;
370         if (xtemps) {
371                 DLIST_FOREACH(ip, &p2e->ipoleqelem) {
372                         if (ip->type == IP_NODE)
373                                 walkf(ip->ip_nodefindaofaddrp);
374                 }
375         }
ragge
1.246
376         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.244
377                 if (ip->type == IP_NODE)
378                         walkf(ip->ip_nodedeltempaddrp);
ragge
1.245
379         markfree(&mark);
ragge
1.244
380
381 #ifdef PCC_DEBUG
382         if (e2debug) {
383                 printf("Efter ADDROF/TEMP\n");
384                 printip(&p2e->ipole);
385         }
386 #endif
387
ragge
1.201
388         DLIST_INIT(&prepoleqelem);
ragge
1.244
389         DLIST_FOREACH(ip, &p2e->ipoleqelem) {
ragge
1.172
390                 if (ip->type != IP_NODE)
391                         continue;
392                 canon(ip->ip_node);
ragge
1.201
393                 if ((ip->ip_node = deluseless(ip->ip_node)) == NULL) {
ragge
1.172
394                         DLIST_REMOVE(ipqelem);
ragge
1.201
395                 } else while (!DLIST_ISEMPTY(&prepoleqelem)) {
gmcgarry
1.224
396                         struct interpass *tipp;
ragge
1.201
397
gmcgarry
1.224
398                         tipp = DLIST_NEXT(&prepoleqelem);
399                         DLIST_REMOVE(tippqelem);
400                         DLIST_INSERT_BEFORE(iptippqelem);
ragge
1.201
401                 }
ragge
1.172
402         }
403
ragge
1.244
404         fixxasm(p2e); /* setup for extended asm */
ragge
1.216
405
ragge
1.244
406         optimize(p2e);
407         ngenregs(p2e);
ragge
1.172
408
ragge
1.260
409         if (xssaflag && xtemps && xdeljumps)
410                 deljumps(p2e);
411
ragge
1.244
412         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.172
413                 emit(ip);
414 }
415
ragge
1.124
416 void
ragge
1.125
417 emit(struct interpass *ip)
ragge
1.124
418 {
gmcgarry
1.208
419         NODE *p, *r;
420         struct optab *op;
ragge
1.149
421         int o;
ragge
1.124
422
ragge
1.125
423         switch (ip->type) {
424         case IP_NODE:
425                 p = ip->ip_node;
ragge
1.124
426
ragge
1.149
427                 nodepole = p;
ragge
1.180
428                 canon(p); /* may convert stuff after genregs */
ragge
1.240
429                 if (c2debug > 1) {
430                         printf("emit IP_NODE:\n");
431                         fwalk(pe2print0);
432                 }
ragge
1.124
433                 switch (p->n_op) {
434                 case CBRANCH:
435                         /* Only emit branch insn if RESCC */
gmcgarry
1.208
436                         /* careful when an OPLOG has been elided */
437                         if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) {
438                                 op = &table[TBLIDX(p->n_left->n_left->n_su)];
439                                 r = p->n_left;
440                         } else {
441                                 op = &table[TBLIDX(p->n_left->n_su)];
442                                 r = p;
443                         }
444                         if (op->rewrite & RESCC) {
ragge
1.124
445                                 o = p->n_left->n_op;
gmcgarry
1.208
446                                 gencode(rFORCC);
ragge
1.124
447                                 cbgen(op->n_right->n_lval);
gmcgarry
1.208
448                         } else {
449                                 gencode(rFORCC);
450                         }
ragge
1.124
451                         break;
452                 case FORCE:
ragge
1.151
453                         gencode(p->n_leftINREGS);
ragge
1.124
454                         break;
ragge
1.216
455                 case XASM:
456                         genxasm(p);
457                         break;
ragge
1.124
458                 default:
459                         if (p->n_op != REG || p->n_type != VOID/* XXX */
460                                 gencode(pFOREFF); /* Emit instructions */
461                 }
462
ragge
1.125
463                 tfree(p);
464                 break;
ragge
1.124
465         case IP_PROLOG:
466                 prologue((struct interpass_prolog *)ip);
467                 break;
468         case IP_EPILOG:
469                 eoftn((struct interpass_prolog *)ip);
ragge
1.174
470                 p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
ragge
1.124
471                 break;
472         case IP_DEFLAB:
473                 deflab(ip->ip_lbl);
474                 break;
475         case IP_ASM:
gmcgarry
1.229
476                 printf("%s"ip->ip_asm);
ragge
1.124
477                 break;
478         default:
ragge
1.216
479                 cerror("emit %d"ip->type);
ragge
1.124
480         }
ragge
1.123
481 }
ragge
1.124
482
ragge
1.30
483 #ifdef PCC_DEBUG
ragge
1.1
484 char *cnames[] = {
485         "SANY",
486         "SAREG",
487         "SBREG",
ragge
1.153
488         "SCREG",
489         "SDREG",
ragge
1.1
490         "SCC",
491         "SNAME",
492         "SCON",
493         "SFLD",
494         "SOREG",
495         "STARNM",
496         "STARREG",
497         "INTEMP",
498         "FORARG",
499         "SWADD",
500         0,
ragge
1.72
501 };
ragge
1.1
502
ragge
1.2
503 /*
504  * print a nice-looking description of cookie
505  */
ragge
1.70
506 char *
ragge
1.2
507 prcook(int cookie)
508 {
ragge
1.70
509         static char buf[50];
ragge
1.1
510         int iflag;
511
ragge
1.70
512         if (cookie & SPECIAL) {
513                 switch (cookie) {
514                 case SZERO:
515                         return "SZERO";
516                 case SONE:
517                         return "SONE";
518                 case SMONE:
519                         return "SMONE";
520                 default:
ragge
1.200
521                         snprintf(bufsizeof(buf), "SPECIAL+%d"cookie & ~SPECIAL);
ragge
1.70
522                         return buf;
ragge
1.1
523                 }
ragge
1.70
524         }
ragge
1.1
525
526         flag = 0;
ragge
1.70
527         buf[0] = 0;
528         for (i = 0cnames[i]; ++i) {
529                 if (cookie & (1<<i)) {
530                         if (flag)
ragge
1.200
531                                 strlcat(buf"|"sizeof(buf));
ragge
1.1
532                         ++flag;
ragge
1.200
533                         strlcat(bufcnames[i], sizeof(buf));
ragge
1.1
534                 }
ragge
1.70
535         }
536         return buf;
537 }
ragge
1.30
538 #endif
ragge
1.1
539
ragge
1.151
540 int
ragge
1.69
541 geninsn(NODE *pint cookie)
542 {
ragge
1.71
543         NODE *p1, *p2;
ragge
1.236
544         int qorv = 0;
ragge
1.69
545
546 #ifdef PCC_DEBUG
547         if (odebug) {
ragge
1.70
548                 printf("geninsn(%p, %s)\n"pprcook(cookie));
ragge
1.69
549                 fwalk(pe2print0);
550         }
551 #endif
552
ragge
1.236
553         q = cookie & QUIET;
554         cookie &= ~QUIET/* XXX - should not be necessary */
555
ragge
1.69
556 again:  switch (o = p->n_op) {
ragge
1.71
557         case EQ:
558         case NE:
559         case LE:
560         case LT:
561         case GE:
562         case GT:
563         case ULE:
564         case ULT:
565         case UGE:
566         case UGT:
gmcgarry
1.208
567                 p1 = p->n_left;
568                 p2 = p->n_right;
ragge
1.265
569                 if (p2->n_op == ICON && p2->n_lval == 0 && *p2->n_name == 0 &&
ragge
1.256
570                     (dope[p1->n_op] & (FLOFLG|DIVFLG|SIMPFLG|SHFFLG))) {
ragge
1.236
571 #ifdef mach_pdp11 /* XXX all targets? */
572                         if ((rv = geninsn(p1FORCC|QUIET)) != FFAIL)
573                                 break;
574 #else
575                         if (findops(p1FORCC) > 0)
gmcgarry
1.208
576                                 break;
ragge
1.236
577 #endif
gmcgarry
1.208
578                 }
ragge
1.159
579                 rv = relops(p);
580                 break;
ragge
1.71
581
ragge
1.69
582         case PLUS:
583         case MINUS:
584         case MUL:
585         case DIV:
586         case MOD:
587         case AND:
588         case OR:
589         case ER:
590         case LS:
591         case RS:
ragge
1.151
592                 rv = findops(pcookie);
593                 break;
ragge
1.77
594
ragge
1.69
595         case ASSIGN:
ragge
1.236
596 #ifdef FINDMOPS
597                 if ((rv = findmops(pcookie)) != FFAIL)
598                         break;
599                 /* FALLTHROUGH */
600 #endif
ragge
1.174
601         case STASG:
ragge
1.151
602                 rv = findasg(pcookie);
603                 break;
ragge
1.159
604
ragge
1.178
605         case UMUL/* May turn into an OREG */
ragge
1.179
606                 rv = findumul(pcookie);
607                 break;
608
ragge
1.69
609         case REG:
ragge
1.144
610         case TEMP:
ragge
1.72
611         case NAME:
ragge
1.71
612         case ICON:
ragge
1.213
613         case FCON:
ragge
1.69
614         case OREG:
ragge
1.152
615                 rv = findleaf(pcookie);
616                 break;
ragge
1.69
617
ragge
1.172
618         case STCALL:
619         case CALL:
620                 /* CALL arguments are handled special */
621                 for (p1 = p->n_rightp1->n_op == CMp1 = p1->n_left)
ragge
1.239
622                         (void)geninsn(p1->n_rightFOREFF);
623                 (void)geninsn(p1FOREFF);
ragge
1.172
624                 /* FALLTHROUGH */
ragge
1.206
625         case FLD:
ragge
1.86
626         case COMPL:
ragge
1.85
627         case UMINUS:
ragge
1.71
628         case PCONV:
629         case SCONV:
ragge
1.198
630 /*      case INIT: */
ragge
1.70
631         case GOTO:
632         case FUNARG:
ragge
1.172
633         case STARG:
ragge
1.72
634         case UCALL:
ragge
1.103
635         case USTCALL:
ragge
1.207
636         case ADDROF:
ragge
1.155
637                 rv = finduni(pcookie);
638                 break;
ragge
1.69
639
ragge
1.71
640         case CBRANCH:
641                 p1 = p->n_left;
642                 p2 = p->n_right;
gmcgarry
1.251
643                 p1->n_label = (int)p2->n_lval;
ragge
1.239
644                 (void)geninsn(p1FORCC);
ragge
1.187
645                 p->n_su = 0;
ragge
1.71
646                 break;
647
ragge
1.187
648         case FORCE/* XXX needed? */
ragge
1.239
649                 (void)geninsn(p->n_leftINREGS);
ragge
1.187
650                 p->n_su = 0/* su calculations traverse left */
ragge
1.71
651                 break;
652
ragge
1.216
653         case XASM:
654                 for (p1 = p->n_leftp1->n_op == CMp1 = p1->n_left)
ragge
1.239
655                         (void)geninsn(p1->n_rightFOREFF);
656                 (void)geninsn(p1FOREFF);
ragge
1.216
657                 break;  /* all stuff already done? */
658
659         case XARG:
660                 /* generate code for correct class here */
gmcgarry
1.250
661 #if 0
662                 geninsn(p->n_left1 << p->n_label);
663 #endif
ragge
1.216
664                 break;
665
ragge
1.69
666         default:
ragge
1.174
667                 comperr("geninsn: bad op %s, node %p"opst[o], p);
ragge
1.69
668         }
ragge
1.236
669         if (rv == FFAIL && !q)
ragge
1.160
670                 comperr("Cannot generate code, node %p op %s"p,opst[p->n_op]);
671         if (rv == FRETRY)
672                 goto again;
ragge
1.236
673 #ifdef PCC_DEBUG
674         if (odebug) {
675                 printf("geninsn(%p, %s) rv %d\n"pprcook(cookie), rv);
676                 fwalk(pe2print0);
677         }
678 #endif
ragge
1.153
679         return rv;
ragge
1.69
680 }
681
ragge
1.72
682 /*
683  * Store a given subtree in a temporary location.
684  * Return an OREG node where it is located.
685  */
686 NODE *
687 store(NODE *p)
ragge
1.2
688 {
ragge
1.130
689         extern struct interpass *storesave;
690         struct interpass *ip;
691         NODE *q, *r;
692         int s;
ragge
1.49
693
ragge
1.130
694         s = BITOOR(freetemp(szty(p->n_type)));
695         q = mklnode(OREGsFPREGp->n_type);
696         r = mklnode(OREGsFPREGp->n_type);
697         ip = ipnode(mkbinode(ASSIGNqpp->n_type));
698
ragge
1.149
699         storesave = ip;
ragge
1.72
700         return r;
ragge
1.8
701 }
ragge
1.1
702
ragge
1.170
703 #ifdef PCC_DEBUG
704 #define CDEBUG(x) if (c2debug) printf x
705 #else
706 #define CDEBUG(x)
707 #endif
708
ragge
1.69
709 /*
ragge
1.188
710  * Do a register-register move if necessary.
ragge
1.270
711  * Called if a RLEFT or RRIGHT is found.
ragge
1.188
712  */
713 static void
714 ckmove(NODE *pNODE *q)
715 {
ragge
1.270
716         struct optab *t = &table[TBLIDX(p->n_su)];
717         int reg;
718
ragge
1.189
719         if (q->n_op != REG || p->n_reg == -1)
ragge
1.188
720                 return/* no register */
ragge
1.270
721
722         /* do we have a need for special reg? */
723         if (t->needs & NSPECIAL)
724                 reg = rspecial(tp->n_left == q ? NLEFT : NRIGHT);
725         else
726                 reg = DECRA(p->n_reg0);
727
728         if (reg < 0 || reg == DECRA(q->n_reg0))
ragge
1.188
729                 return/* no move necessary */
ragge
1.270
730
ragge
1.190
731         CDEBUG(("rmove: node %p, %s -> %s\n"prnames[DECRA(q->n_reg0)],
ragge
1.270
732             rnames[reg]));
733         rmove(DECRA(q->n_reg0), regp->n_type);
734         q->n_reg = q->n_rval = reg;
ragge
1.188
735 }
736
737 /*
738  * Rewrite node to register after instruction emit.
ragge
1.75
739  */
740 static void
gmcgarry
1.224
741 rewrite(NODE *pint dorewriteint cookie)
ragge
1.75
742 {
ragge
1.79
743         NODE *l, *r;
744         int o;
745
ragge
1.80
746         l = getlr(p'L');
747         r = getlr(p'R');
ragge
1.79
748         o = p->n_op;
ragge
1.75
749         p->n_op = REG;
ragge
1.76
750         p->n_lval = 0;
ragge
1.95
751         p->n_name = "";
ragge
1.158
752
ragge
1.257
753         if (o == ASSIGN || o == STASG) {
ragge
1.190
754                 /* special rewrite care */
755                 int reg = DECRA(p->n_reg0);
ragge
1.191
756 #define TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
ragge
1.190
757                 if (p->n_reg == -1)
758                         ;
ragge
1.191
759                 else if (TL(l) && (DECRA(l->n_reg0) == reg))
ragge
1.190
760                         ;
ragge
1.191
761                 else if (TL(r) && (DECRA(r->n_reg0) == reg))
ragge
1.190
762                         ;
ragge
1.191
763                 else if (TL(l))
ragge
1.190
764                         rmove(DECRA(l->n_reg0), regp->n_type);
ragge
1.191
765                 else if (TL(r))
ragge
1.190
766                         rmove(DECRA(r->n_reg0), regp->n_type);
767 #if 0
768                 else
769                         comperr("rewrite");
770 #endif
ragge
1.191
771 #undef TL
ragge
1.190
772         }
ragge
1.79
773         if (optype(o) != LTYPE)
774                 tfree(l);
775         if (optype(o) == BITYPE)
776                 tfree(r);
gmcgarry
1.224
777         if (dorewrite == 0)
ragge
1.190
778                 return;
mickey
1.205
779         CDEBUG(("rewrite: %p, reg %s\n"p,
780             p->n_reg == -1"<none>" : rnames[DECRA(p->n_reg0)]));
ragge
1.187
781         p->n_rval = DECRA(p->n_reg0);
ragge
1.75
782 }
783
ragge
1.228
784 #ifndef XASM_TARGARG
785 #define XASM_TARGARG(x,y) 0
786 #endif
787
ragge
1.216
788 /*
789  * printout extended assembler.
790  */
791 void
792 genxasm(NODE *p)
793 {
794         NODE *q, **nary;
795         int n = 1o = 0;
796         char *w;
797
ragge
1.228
798         if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) {
799                 for (q = p->n_leftq->n_op == CMq = q->n_left)
800                         n++;
ragge
1.254
801                 nary = tmpcalloc(sizeof(NODE *)*(n+1));
ragge
1.228
802                 o = n;
803                 for (q = p->n_leftq->n_op == CMq = q->n_left) {
804                         gencode(q->n_right->n_leftINREGS);
805                         nary[--o] = q->n_right;
806                 }
807                 gencode(q->n_leftINREGS);
808                 nary[--o] = q;
809         } else
810                 nary = 0;
ragge
1.216
811
812         w = p->n_name;
813         putchar('\t');
814         while (*w != 0) {
815                 if (*w == '%') {
ragge
1.225
816                         if (w[1] == '%')
817                                 putchar('%');
ragge
1.228
818                         else if (XASM_TARGARG(wnary))
819                                 ; /* handled by target */
ragge
1.225
820                         else if (w[1] < '0' || w[1] > (n + '0'))
ragge
1.228
821                                 uerror("bad xasm arg number %c"w[1]);
ragge
1.253
822                         else {
823                                 if (w[1] == (n + '0'))
824                                         q = nary[(int)w[1]-'0' - 1]; /* XXX */
825                                 else
826                                         q = nary[(int)w[1]-'0'];
827                                 adrput(stdoutq->n_left);
828                         }
ragge
1.216
829                         w++;
ragge
1.228
830                 } else if (*w == '\\') { /* Always 3-digit octal */
831                         int num = *++w - '0';
832                         num = (num << 3) + *++w - '0';
833                         num = (num << 3) + *++w - '0';
834                         putchar(num);
ragge
1.216
835                 } else
836                         putchar(*w);
837                 w++;
838         }
839         putchar('\n');
840 }
841
ragge
1.271
842 /*
843  * Allocate temporary registers for use while emitting this table entry.
844  */
845 static void
846 allo(NODE *pstruct optab *q)
847 {
848         extern int stktemp;
849         int in = ncnt(q->needs);
850
851         for (i = 0i < NRESCi++)
852                 if (resc[i].n_op != FREE)
853                         comperr("allo: used reg");
854         if (n == 0 && (q->needs & NTMASK) == 0)
855                 return;
856         for (i = 0i < n+1i++) {
857                 resc[i].n_op = REG;
858                 resc[i].n_type = p->n_type/* XXX should be correct type */
859                 resc[i].n_rval = DECRA(p->n_regi);
860                 resc[i].n_su = p->n_su/* ??? */
861         }
862         if (q->needs & NTMASK) {
863                 resc[i].n_op = OREG;
864                 resc[i].n_lval = stktemp;
865                 resc[i].n_rval = FPREG;
866                 resc[i].n_su = p->n_su/* ??? */
867                 resc[i].n_name = "";
868         }
869         if (i >= NRESC)
870                 comperr("allo: too many allocs");
871 }
872
873 static void
874 afree(void)
875 {
876         int i;
877
878         for (i = 0i < NRESCi++)
879                 resc[i].n_op = FREE;
880 }
881
ragge
1.69
882 void
ragge
1.72
883 gencode(NODE *pint cookie)
ragge
1.69
884 {
885         struct optab *q = &table[TBLIDX(p->n_su)];
ragge
1.188
886         NODE *p1, *l, *r;
ragge
1.190
887         int o = optype(p->n_op);
ragge
1.240
888 #ifdef FINDMOPS
889         int ismops = (p->n_op == ASSIGN && (p->n_flags & 1));
890 #endif
ragge
1.188
891
892         l = p->n_left;
893         r = p->n_right;
ragge
1.69
894
ragge
1.186
895         if (TBLIDX(p->n_su) == 0) {
896                 if (o == BITYPE && (p->n_su & DORIGHT))
ragge
1.188
897                         gencode(r0);
ragge
1.185
898                 if (optype(p->n_op) != LTYPE)
ragge