Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20120926183857

Diff

Diff from 1.282 to:

Annotations

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

Annotated File View

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