Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20081203070840

Diff

Diff from 1.248 to:

Annotations

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

Annotated File View

ragge
1.248
1 /*      $Id: reader.c,v 1.248 2008/12/03 07:08:40 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;
ragge
1.9
77 int x2debug;
ragge
1.1
78 int udebug = 0;
ragge
1.103
79 int thisline;
ragge
1.72
80 int fregs;
ragge
1.123
81 int p2autooffp2maxautooff;
ragge
1.1
82
ragge
1.72
83 NODE *nodepole;
ragge
1.197
84 FILE *prfil;
ragge
1.238
85 struct interpass prepole;
ragge
1.23
86
ragge
1.37
87 void saveip(struct interpass *ip);
ragge
1.243
88 void deltemp(NODE *pvoid *);
ragge
1.232
89 static void cvtemps(struct interpass *ipoleint opint off);
ragge
1.72
90 NODE *store(NODE *);
ragge
1.242
91 static void fixxasm(struct p2env *);
ragge
1.65
92
ragge
1.72
93 static void gencode(NODE *pint cookie);
ragge
1.216
94 static void genxasm(NODE *p);
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);
125                 i = 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.241
137         if (p->n_op == GOTO) {
138                 i = 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.244
207 #ifdef PCC_DEBUG
208                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
209                         comperr("temparg");
210 #endif
211                 if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL)
212                         continue/* arg in register */
213                 if (tnr != regno(p->n_left))
214                         continue/* wrong assign */
215                 p = p->n_right;
216                 if (p->n_op == UMUL &&
217                     p->n_left->n_op == PLUS &&
218                     p->n_left->n_left->n_op == REG &&
219                     p->n_left->n_right->n_op == ICON)
220                         *soff = p->n_left->n_right->n_lval;
221                 else if (p->n_op == OREG)
222                         *soff = p->n_lval;
223                 else
224                         comperr("stkarg: bad arg");
225                 tfree(ip->ip_node);
226                 DLIST_REMOVE(ipqelem);
227                 return 1;
228         }
229         return 0;
230 }
231
232 /*
233  * See if an ADDROF is somewhere inside the expression tree.
234  * If so, fill in the offset table.
235  */
236 static void
237 findaof(NODE *pvoid *arg)
238 {
239         int *aof = arg;
240         int tnr;
241
242         if (p->n_op != ADDROF)
243                 return;
244         tnr = regno(p->n_left);
245         if (aof[tnr])
246                 return/* already gotten stack address */
247         if (stkarg(tnr, &aof[tnr]))
248                 return/* argument was on stack */
249         aof[tnr] = BITOOR(freetemp(szty(p->n_left->n_type)));
250 }
251
252 /*
ragge
1.89
253  * Check if a node has side effects.
254  */
255 static int
256 isuseless(NODE *n)
257 {
258         switch (n->n_op) {
ragge
1.216
259         case XASM:
ragge
1.89
260         case FUNARG:
261         case UCALL:
262         case UFORTCALL:
263         case FORCE:
264         case ASSIGN:
265         case CALL:
266         case FORTCALL:
267         case CBRANCH:
268         case RETURN:
269         case GOTO:
270         case STCALL:
271         case USTCALL:
272         case STASG:
273         case STARG:
274                 return 0;
275         default:
276                 return 1;
277         }
278 }
279
ragge
1.130
280 /*
281  * Delete statements with no meaning (like a+b; or 513.4;)
282  */
ragge
1.238
283 NODE *
ragge
1.89
284 deluseless(NODE *p)
285 {
286         struct interpass *ip;
287         NODE *l, *r;
288
289         if (optype(p->n_op) == LTYPE) {
290                 nfree(p);
291                 return NULL;
292         }
293         if (isuseless(p) == 0)
294                 return p;
295
296         if (optype(p->n_op) == UTYPE) {
297                 l = p->n_left;
298                 nfree(p);
299                 return deluseless(l);
300         }
301
302         /* Be sure that both leaves may be valid */
303         l = deluseless(p->n_left);
304         r = deluseless(p->n_right);
305         nfree(p);
306         if (l && r) {
ragge
1.201
307                 ip = ipnode(l);
308                 DLIST_INSERT_AFTER(&prepoleipqelem);
ragge
1.89
309                 return r;
310         } else if (l)
311                 return l;
312         else if (r)
313                 return r;
314         return NULL;
315 }
316
ragge
1.172
317 /*
318  * Receives interpass structs from pass1.
319  */
320 void
321 pass2_compile(struct interpass *ip)
322 {
ragge
1.244
323         struct p2env *p2e = &p2env;
324         int *addrp;
ragge
1.245
325         MARK mark;
ragge
1.244
326
ragge
1.172
327         if (ip->type == IP_PROLOG) {
ragge
1.244
328                 memset(p2e0sizeof(struct p2env));
329                 p2e->ipp = (struct interpass_prolog *)ip;
330                 DLIST_INIT(&p2e->ipoleqelem);
ragge
1.172
331         }
ragge
1.244
332         DLIST_INSERT_BEFORE(&p2e->ipoleipqelem);
ragge
1.172
333         if (ip->type != IP_EPILOG)
334                 return;
335
336 #ifdef PCC_DEBUG
337         if (e2debug) {
338                 printf("Entering pass2\n");
ragge
1.244
339                 printip(&p2e->ipole);
ragge
1.172
340         }
341 #endif
ragge
1.174
342
ragge
1.244
343         p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipoleqelem);
344         p2maxautooff = p2autooff = p2e->epp->ipp_autos;
ragge
1.174
345
ragge
1.241
346 #ifdef PCC_DEBUG
ragge
1.244
347         sanitychecks(p2e);
ragge
1.241
348 #endif
ragge
1.244
349         myreader(&p2e->ipole); /* local massage of input */
ragge
1.174
350
ragge
1.244
351         /*
352          * Do initial modification of the trees.  Two loops;
353          * - first, search for ADDROF of TEMPs, these must be
354          *   converterd to OREGs on stack.
355          * - second, do the actual conversions, in case of not xtemps
356          *   convert all temporaries to stack references.
357          */
ragge
1.245
358         markset(&mark);
ragge
1.244
359         if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) {
360                 addrp = tmpcalloc(sizeof(int) *
361                     (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum));
362                 addrp -= p2e->ipp->ip_tmpnum;
363         } else
364                 addrp = NULL;
365         if (xtemps) {
366                 DLIST_FOREACH(ip, &p2e->ipoleqelem) {
367                         if (ip->type == IP_NODE)
368                                 walkf(ip->ip_nodefindaofaddrp);
369                 }
370         }
ragge
1.246
371         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.244
372                 if (ip->type == IP_NODE)
373                         walkf(ip->ip_nodedeltempaddrp);
ragge
1.245
374         markfree(&mark);
ragge
1.244
375
376 #ifdef PCC_DEBUG
377         if (e2debug) {
378                 printf("Efter ADDROF/TEMP\n");
379                 printip(&p2e->ipole);
380         }
381 #endif
382
383 #if 0
384         DLIST_FOREACH(ip, &p2e->ipoleqelem) {
ragge
1.172
385                 if (ip->type != IP_NODE)
386                         continue;
387                 if (xtemps == 0)
ragge
1.243
388                         walkf(ip->ip_nodedeltemp0);
ragge
1.172
389         }
ragge
1.244
390 #endif
391
ragge
1.201
392         DLIST_INIT(&prepoleqelem);
ragge
1.244
393         DLIST_FOREACH(ip, &p2e->ipoleqelem) {
ragge
1.172
394                 if (ip->type != IP_NODE)
395                         continue;
396                 canon(ip->ip_node);
ragge
1.201
397                 if ((ip->ip_node = deluseless(ip->ip_node)) == NULL) {
ragge
1.172
398                         DLIST_REMOVE(ipqelem);
ragge
1.201
399                 } else while (!DLIST_ISEMPTY(&prepoleqelem)) {
gmcgarry
1.224
400                         struct interpass *tipp;
ragge
1.201
401
gmcgarry
1.224
402                         tipp = DLIST_NEXT(&prepoleqelem);
403                         DLIST_REMOVE(tippqelem);
404                         DLIST_INSERT_BEFORE(iptippqelem);
ragge
1.201
405                 }
ragge
1.172
406         }
407
ragge
1.244
408         fixxasm(p2e); /* setup for extended asm */
ragge
1.216
409
ragge
1.244
410         optimize(p2e);
411         ngenregs(p2e);
ragge
1.172
412
ragge
1.244
413         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.172
414                 emit(ip);
415 }
416
ragge
1.124
417 void
ragge
1.125
418 emit(struct interpass *ip)
ragge
1.124
419 {
gmcgarry
1.208
420         NODE *p, *r;
421         struct optab *op;
ragge
1.149
422         int o;
ragge
1.124
423
ragge
1.125
424         switch (ip->type) {
425         case IP_NODE:
426                 p = ip->ip_node;
ragge
1.124
427
ragge
1.149
428                 nodepole = p;
ragge
1.180
429                 canon(p); /* may convert stuff after genregs */
ragge
1.240
430                 if (c2debug > 1) {
431                         printf("emit IP_NODE:\n");
432                         fwalk(pe2print0);
433                 }
ragge
1.124
434                 switch (p->n_op) {
435                 case CBRANCH:
436                         /* Only emit branch insn if RESCC */
gmcgarry
1.208
437                         /* careful when an OPLOG has been elided */
438                         if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) {
439                                 op = &table[TBLIDX(p->n_left->n_left->n_su)];
440                                 r = p->n_left;
441                         } else {
442                                 op = &table[TBLIDX(p->n_left->n_su)];
443                                 r = p;
444                         }
445                         if (op->rewrite & RESCC) {
ragge
1.124
446                                 o = p->n_left->n_op;
gmcgarry
1.208
447                                 gencode(rFORCC);
ragge
1.124
448                                 cbgen(op->n_right->n_lval);
gmcgarry
1.208
449                         } else {
450                                 gencode(rFORCC);
451                         }
ragge
1.124
452                         break;
453                 case FORCE:
ragge
1.151
454                         gencode(p->n_leftINREGS);
ragge
1.124
455                         break;
ragge
1.216
456                 case XASM:
457                         genxasm(p);
458                         break;
ragge
1.124
459                 default:
460                         if (p->n_op != REG || p->n_type != VOID/* XXX */
461                                 gencode(pFOREFF); /* Emit instructions */
462                 }
463
ragge
1.125
464                 tfree(p);
465                 break;
ragge
1.124
466         case IP_PROLOG:
467                 prologue((struct interpass_prolog *)ip);
468                 break;
469         case IP_EPILOG:
470                 eoftn((struct interpass_prolog *)ip);
ragge
1.174
471                 p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
ragge
1.124
472                 break;
473         case IP_DEFLAB:
474                 deflab(ip->ip_lbl);
475                 break;
476         case IP_ASM:
gmcgarry
1.229
477                 printf("%s"ip->ip_asm);
ragge
1.124
478                 break;
479         default:
ragge
1.216
480                 cerror("emit %d"ip->type);
ragge
1.124
481         }
ragge
1.123
482 }
ragge
1.124
483
ragge
1.30
484 #ifdef PCC_DEBUG
ragge
1.1
485 char *cnames[] = {
486         "SANY",
487         "SAREG",
488         "SBREG",
ragge
1.153
489         "SCREG",
490         "SDREG",
ragge
1.1
491         "SCC",
492         "SNAME",
493         "SCON",
494         "SFLD",
495         "SOREG",
496         "STARNM",
497         "STARREG",
498         "INTEMP",
499         "FORARG",
500         "SWADD",
501         0,
ragge
1.72
502 };
ragge
1.1
503
ragge
1.2
504 /*
505  * print a nice-looking description of cookie
506  */
ragge
1.70
507 char *
ragge
1.2
508 prcook(int cookie)
509 {
ragge
1.70
510         static char buf[50];
ragge
1.1
511         int iflag;
512
ragge
1.70
513         if (cookie & SPECIAL) {
514                 switch (cookie) {
515                 case SZERO:
516                         return "SZERO";
517                 case SONE:
518                         return "SONE";
519                 case SMONE:
520                         return "SMONE";
521                 default:
ragge
1.200
522                         snprintf(bufsizeof(buf), "SPECIAL+%d"cookie & ~SPECIAL);
ragge
1.70
523                         return buf;
ragge
1.1
524                 }
ragge
1.70
525         }
ragge
1.1
526
527         flag = 0;
ragge
1.70
528         buf[0] = 0;
529         for (i = 0cnames[i]; ++i) {
530                 if (cookie & (1<<i)) {
531                         if (flag)
ragge
1.200
532                                 strlcat(buf"|"sizeof(buf));
ragge
1.1
533                         ++flag;
ragge
1.200
534                         strlcat(bufcnames[i], sizeof(buf));
ragge
1.1
535                 }
ragge
1.70
536         }
537         return buf;
538 }
ragge
1.1
539
ragge
1.30
540 #endif
ragge
1.1
541
542 int odebug = 0;
543
ragge
1.151
544 int
ragge
1.69
545 geninsn(NODE *pint cookie)
546 {
ragge
1.71
547         NODE *p1, *p2;
ragge
1.236
548         int qorv = 0;
ragge
1.69
549
550 #ifdef PCC_DEBUG
551         if (odebug) {
ragge
1.70
552                 printf("geninsn(%p, %s)\n"pprcook(cookie));
ragge
1.69
553                 fwalk(pe2print0);
554         }
555 #endif
556
ragge
1.236
557         q = cookie & QUIET;
558         cookie &= ~QUIET/* XXX - should not be necessary */
559
ragge
1.69
560 again:  switch (o = p->n_op) {
ragge
1.71
561         case EQ:
562         case NE:
563         case LE:
564         case LT:
565         case GE:
566         case GT:
567         case ULE:
568         case ULT:
569         case UGE:
570         case UGT:
gmcgarry
1.208
571                 p1 = p->n_left;
572                 p2 = p->n_right;
ragge
1.210
573                 if (p2->n_op == ICON && p2->n_lval == 0 &&
574                     optype(p1->n_op) == BITYPE) {
ragge
1.236
575 #ifdef mach_pdp11 /* XXX all targets? */
576                         if ((rv = geninsn(p1FORCC|QUIET)) != FFAIL)
577                                 break;
578 #else
579                         if (findops(p1FORCC) > 0)
gmcgarry
1.208
580                                 break;
ragge
1.236
581 #endif
gmcgarry
1.208
582                 }
ragge
1.159
583                 rv = relops(p);
584                 break;
ragge
1.71
585
ragge
1.69
586         case PLUS:
587         case MINUS:
588         case MUL:
589         case DIV:
590         case MOD:
591         case AND:
592         case OR:
593         case ER:
594         case LS:
595         case RS:
ragge
1.151
596                 rv = findops(pcookie);
597                 break;
ragge
1.77
598
ragge
1.69
599         case ASSIGN:
ragge
1.236
600 #ifdef FINDMOPS
601                 if ((rv = findmops(pcookie)) != FFAIL)
602                         break;
603                 /* FALLTHROUGH */
604 #endif
ragge
1.174
605         case STASG:
ragge
1.151
606                 rv = findasg(pcookie);
607                 break;
ragge
1.159
608
ragge
1.178
609         case UMUL/* May turn into an OREG */
ragge
1.179
610                 rv = findumul(pcookie);
611                 break;
612
ragge
1.69
613         case REG:
ragge
1.144
614         case TEMP:
ragge
1.72
615         case NAME:
ragge
1.71
616         case ICON:
ragge
1.213
617         case FCON:
ragge
1.69
618         case OREG:
ragge
1.152
619                 rv = findleaf(pcookie);
620                 break;
ragge
1.69
621
ragge
1.172
622         case STCALL:
623         case CALL:
624                 /* CALL arguments are handled special */
625                 for (p1 = p->n_rightp1->n_op == CMp1 = p1->n_left)
ragge
1.239
626                         (void)geninsn(p1->n_rightFOREFF);
627                 (void)geninsn(p1FOREFF);
ragge
1.172
628                 /* FALLTHROUGH */
ragge
1.206
629         case FLD:
ragge
1.86
630         case COMPL:
ragge
1.85
631         case UMINUS:
ragge
1.71
632         case PCONV:
633         case SCONV:
ragge
1.198
634 /*      case INIT: */
ragge
1.70
635         case GOTO:
636         case FUNARG:
ragge
1.172
637         case STARG:
ragge
1.72
638         case UCALL:
ragge
1.103
639         case USTCALL:
ragge
1.207
640         case ADDROF:
ragge
1.155
641                 rv = finduni(pcookie);
642                 break;
ragge
1.69
643
ragge
1.71
644         case CBRANCH:
645                 p1 = p->n_left;
646                 p2 = p->n_right;
647                 p1->n_label = p2->n_lval;
ragge
1.239
648                 (void)geninsn(p1FORCC);
ragge
1.187
649                 p->n_su = 0;
ragge
1.71
650                 break;
651
ragge
1.187
652         case FORCE/* XXX needed? */
ragge
1.239
653                 (void)geninsn(p->n_leftINREGS);
ragge
1.187
654                 p->n_su = 0/* su calculations traverse left */
ragge
1.71
655                 break;
656
ragge
1.216
657         case XASM:
658                 for (p1 = p->n_leftp1->n_op == CMp1 = p1->n_left)
ragge
1.239
659                         (void)geninsn(p1->n_rightFOREFF);
660                 (void)geninsn(p1FOREFF);
ragge
1.216
661                 break;  /* all stuff already done? */
662
663         case XARG:
664                 /* generate code for correct class here */
ragge
1.221
665 //              geninsn(p->n_left, 1 << p->n_label);
ragge
1.216
666                 break;
667
ragge
1.69
668         default:
ragge
1.174
669                 comperr("geninsn: bad op %s, node %p"opst[o], p);
ragge
1.69
670         }
ragge
1.236
671         if (rv == FFAIL && !q)
ragge
1.160
672                 comperr("Cannot generate code, node %p op %s"p,opst[p->n_op]);
673         if (rv == FRETRY)
674                 goto again;
ragge
1.236
675 #ifdef PCC_DEBUG
676         if (odebug) {
677                 printf("geninsn(%p, %s) rv %d\n"pprcook(cookie), rv);
678                 fwalk(pe2print0);
679         }
680 #endif
ragge
1.153
681         return rv;
ragge
1.69
682 }
683
ragge
1.72
684 /*
685  * Store a given subtree in a temporary location.
686  * Return an OREG node where it is located.
687  */
688 NODE *
689 store(NODE *p)
ragge
1.2
690 {
ragge
1.130
691         extern struct interpass *storesave;
692         struct interpass *ip;
693         NODE *q, *r;
694         int s;
ragge
1.49
695
ragge
1.130
696         s = BITOOR(freetemp(szty(p->n_type)));
697         q = mklnode(OREGsFPREGp->n_type);
698         r = mklnode(OREGsFPREGp->n_type);
699         ip = ipnode(mkbinode(ASSIGNqpp->n_type));
700
ragge
1.149
701         storesave = ip;
ragge
1.72
702         return r;
ragge
1.8
703 }
ragge
1.1
704
ragge
1.170
705 #ifdef PCC_DEBUG
706 #define CDEBUG(x) if (c2debug) printf x
707 #else
708 #define CDEBUG(x)
709 #endif
710
ragge
1.69
711 /*
ragge
1.188
712  * Do a register-register move if necessary.
713  */
714 static void
715 ckmove(NODE *pNODE *q)
716 {
ragge
1.189
717         if (q->n_op != REG || p->n_reg == -1)
ragge
1.188
718                 return/* no register */
719         if (DECRA(p->n_reg0) == DECRA(q->n_reg0))
720                 return/* no move necessary */
ragge
1.190
721         CDEBUG(("rmove: node %p, %s -> %s\n"prnames[DECRA(q->n_reg0)],
722             rnames[DECRA(p->n_reg0)]));
ragge
1.188
723         rmove(DECRA(q->n_reg0), DECRA(p->n_reg0), p->n_type);
724         q->n_reg = q->n_rval = DECRA(p->n_reg0);
725 }
726
727 /*
728  * Rewrite node to register after instruction emit.
ragge
1.75
729  */
730 static void
gmcgarry
1.224
731 rewrite(NODE *pint dorewriteint cookie)
ragge
1.75
732 {
ragge
1.79
733         NODE *l, *r;
734         int o;
735
ragge
1.80
736         l = getlr(p'L');
737         r = getlr(p'R');
ragge
1.79
738         o = p->n_op;
ragge
1.75
739         p->n_op = REG;
ragge
1.76
740         p->n_lval = 0;
ragge
1.95
741         p->n_name = "";
ragge
1.158
742
ragge
1.190
743         if (o == ASSIGN) {
744                 /* special rewrite care */
745                 int reg = DECRA(p->n_reg0);
ragge
1.191
746 #define TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
ragge
1.190
747                 if (p->n_reg == -1)
748                         ;
ragge
1.191
749                 else if (TL(l) && (DECRA(l->n_reg0) == reg))
ragge
1.190
750                         ;
ragge
1.191
751                 else if (TL(r) && (DECRA(r->n_reg0) == reg))
ragge
1.190
752                         ;
ragge
1.191
753                 else if (TL(l))
ragge
1.190
754                         rmove(DECRA(l->n_reg0), regp->n_type);
ragge
1.191
755                 else if (TL(r))
ragge
1.190
756                         rmove(DECRA(r->n_reg0), regp->n_type);
757 #if 0
758                 else
759                         comperr("rewrite");
760 #endif
ragge
1.191
761 #undef TL
ragge
1.190
762         }
ragge
1.79
763         if (optype(o) != LTYPE)
764                 tfree(l);
765         if (optype(o) == BITYPE)
766                 tfree(r);
gmcgarry
1.224
767         if (dorewrite == 0)
ragge
1.190
768                 return;
mickey
1.205
769         CDEBUG(("rewrite: %p, reg %s\n"p,
770             p->n_reg == -1"<none>" : rnames[DECRA(p->n_reg0)]));
ragge
1.187
771         p->n_rval = DECRA(p->n_reg0);
ragge
1.75
772 }
773
ragge
1.228
774 #ifndef XASM_TARGARG
775 #define XASM_TARGARG(x,y) 0
776 #endif
777
ragge
1.216
778 /*
779  * printout extended assembler.
780  */
781 void
782 genxasm(NODE *p)
783 {
784         NODE *q, **nary;
785         int n = 1o = 0;
786         char *w;
787
ragge
1.228
788         if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) {
789                 for (q = p->n_leftq->n_op == CMq = q->n_left)
790                         n++;
791                 nary = tmpalloc(sizeof(NODE *)*n);
792                 o = n;
793                 for (q = p->n_leftq->n_op == CMq = q->n_left) {
794                         gencode(q->n_right->n_leftINREGS);
795                         nary[--o] = q->n_right;
796                 }
797                 gencode(q->n_leftINREGS);
798                 nary[--o] = q;
799         } else
800                 nary = 0;
ragge
1.216
801
802         w = p->n_name;
803         putchar('\t');
804         while (*w != 0) {
805                 if (*w == '%') {
ragge
1.225
806                         if (w[1] == '%')
807                                 putchar('%');
ragge
1.228
808                         else if (XASM_TARGARG(wnary))
809                                 ; /* handled by target */
ragge
1.225
810                         else if (w[1] < '0' || w[1] > (n + '0'))
ragge
1.228
811                                 uerror("bad xasm arg number %c"w[1]);
ragge
1.216
812                         else
ragge
1.221
813                                 adrput(stdoutnary[(int)w[1]-'0']->n_left);
ragge
1.216
814                         w++;
ragge
1.228
815                 } else if (*w == '\\') { /* Always 3-digit octal */
816                         int num = *++w - '0';
817                         num = (num << 3) + *++w - '0';
818                         num = (num << 3) + *++w - '0';
819                         putchar(num);
ragge
1.216
820                 } else
821                         putchar(*w);
822                 w++;
823         }
824         putchar('\n');
825 }
826
ragge
1.69
827 void
ragge
1.72
828 gencode(NODE *pint cookie)
ragge
1.69
829 {
830         struct optab *q = &table[TBLIDX(p->n_su)];
ragge
1.188
831         NODE *p1, *l, *r;
ragge
1.190
832         int o = optype(p->n_op);
ragge
1.240
833 #ifdef FINDMOPS
834         int ismops = (p->n_op == ASSIGN && (p->n_flags & 1));
835 #endif
ragge
1.188
836
837         l = p->n_left;
838         r = p->n_right;
ragge
1.69
839
ragge
1.186
840         if (TBLIDX(p->n_su) == 0) {
841                 if (o == BITYPE && (p->n_su & DORIGHT))
ragge
1.188
842                         gencode(r0);
ragge
1.185
843                 if (optype(p->n_op) != LTYPE)
ragge
1.188
844                         gencode(l0);
ragge
1.186
845                 if (o == BITYPE && !(p->n_su & DORIGHT))
ragge
1.188
846                         gencode(r0);
ragge
1.185
847                 return;
848         }
ragge
1.69
849
ragge
1.170
850         CDEBUG(("gencode: node %p\n"p));
851
852         if (p->n_op == REG && DECRA(p->n_reg0) == p->n_rval)
ragge
1.156
853                 return/* meaningless move to itself */
ragge
1.175
854
855         if (callop(p->n_op))
856                 lastcall(p); /* last chance before function args */
857         if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL) {
858                 /* Print out arguments first */
ragge
1.188
859                 for (p1 = rp1->n_op == CMp1 = p1->n_left)
ragge
1.175
860                         gencode(p1->n_rightFOREFF);
861                 gencode(p1FOREFF);
ragge
1.190
862                 o = UTYPE/* avoid going down again */
ragge
1.175
863         }
864
ragge
1.190
865         if (o == BITYPE && (p->n_su & DORIGHT)) {
ragge
1.188
866                 gencode(rINREGS);
867                 if (q->rewrite & RRIGHT)
868                         ckmove(pr);
869         }
ragge
1.190
870         if (o != LTYPE) {
ragge
1.188
871                 gencode(lINREGS);
ragge
1.240
872 #ifdef FINDMOPS
873                 if (ismops)
874                         ;
875                 else
876 #endif
877                      if (q->rewrite & RLEFT)
ragge
1.188
878                         ckmove(pl);
879         }
ragge
1.190
880         if (o == BITYPE && !(p->n_su & DORIGHT)) {
ragge
1.188
881                 gencode(rINREGS);
882                 if (q->rewrite & RRIGHT)
883                         ckmove(pr);
884         }
ragge
1.185
885
ragge
1.236
886 #ifdef FINDMOPS
ragge
1.240
887         if (ismops) {
ragge
1.236
888                 /* reduce right tree to make expand() work */
889                 if (optype(r->n_op) != LTYPE) {
ragge
1.240
890                         p->n_op = r->n_op;
ragge
1.236
891                         r = tcopy(r->n_right);
892                         tfree(p->n_right);
893                         p->n_right = r;
894                 }