Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20110812192440

Diff

Diff from 1.276 to:

Annotations

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

Annotated File View

plunky
1.276
1 /*      $Id: reader.c,v 1.276 2011/08/12 19:24:40 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;
mickey
1.258
74 int x2debugudebugodebug;
ragge
1.103
75 int thisline;
ragge
1.72
76 int fregs;
ragge
1.123
77 int p2autooffp2maxautooff;
ragge
1.1
78
ragge
1.72
79 NODE *nodepole;
ragge
1.197
80 FILE *prfil;
ragge
1.238
81 struct interpass prepole;
ragge
1.23
82
ragge
1.37
83 void saveip(struct interpass *ip);
ragge
1.243
84 void deltemp(NODE *pvoid *);
ragge
1.232
85 static void cvtemps(struct interpass *ipoleint opint off);
ragge
1.72
86 NODE *store(NODE *);
ragge
1.242
87 static void fixxasm(struct p2env *);
ragge
1.65
88
ragge
1.72
89 static void gencode(NODE *pint cookie);
ragge
1.216
90 static void genxasm(NODE *p);
ragge
1.271
91 static void afree(void);
ragge
1.69
92
ragge
1.246
93 struct p2env p2env;
ragge
1.121
94
ragge
1.246
95 int
96 getlab2(void)
97 {
98         extern int getlab(void);
99         int rv = getlab();
100 #ifdef PCC_DEBUG
101         if (p2env.epp->ip_lblnum != rv)
102                 comperr("getlab2 error: %d != %d"p2env.epp->ip_lblnumrv);
103 #endif
104         p2env.epp->ip_lblnum++;
105         return rv;
106 }
ragge
1.241
107
ragge
1.26
108 #ifdef PCC_DEBUG
ragge
1.241
109 static int *lbldef, *lbluse;
ragge
1.26
110 static void
ragge
1.243
111 cktree(NODE *pvoid *arg)
ragge
1.26
112 {
ragge
1.241
113         int i;
114
ragge
1.26
115         if (p->n_op > MAXOP)
ragge
1.218
116                 cerror("%p) op %d slipped through"pp->n_op);
ragge
1.273
117 #ifndef FIELDOPS
118         if (p->n_op == FLD)
119                 cerror("%p) FLD slipped through"p);
120 #endif
ragge
1.199
121         if (BTYPE(p->n_type) > MAXTYPES)
ragge
1.218
122                 cerror("%p) type %x slipped through"pp->n_type);
ragge
1.241
123         if (p->n_op == CBRANCH) {
124                  if (!logop(p->n_left->n_op))
125                         cerror("%p) not logop branch"p);
gmcgarry
1.251
126                 i = (int)p->n_right->n_lval;
ragge
1.242
127                 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
ragge
1.241
128                         cerror("%p) label %d outside boundaries %d-%d",
ragge
1.242
129                             pip2env.ipp->ip_lblnump2env.epp->ip_lblnum);
130                 lbluse[i-p2env.ipp->ip_lblnum] = 1;
ragge
1.241
131         }
ragge
1.47
132         if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
ragge
1.218
133                 cerror("%p) asgop %d slipped through"pp->n_op);
ragge
1.241
134         if (p->n_op == TEMP &&
ragge
1.242
135             (regno(p) < p2env.ipp->ip_tmpnum || regno(p) >= p2env.epp->ip_tmpnum))
ragge
1.241
136                 cerror("%p) temporary %d outside boundaries %d-%d",
ragge
1.242
137                     pregno(p), p2env.ipp->ip_tmpnump2env.epp->ip_tmpnum);
ragge
1.249
138         if (p->n_op == GOTO && p->n_left->n_op == ICON) {
gmcgarry
1.251
139                 i = (int)p->n_left->n_lval;
ragge
1.242
140                 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
ragge
1.241
141                         cerror("%p) label %d outside boundaries %d-%d",
ragge
1.242
142                             pip2env.ipp->ip_lblnump2env.epp->ip_lblnum);
143                 lbluse[i-p2env.ipp->ip_lblnum] = 1;
ragge
1.241
144         }
145 }
146
147 /*
148  * Check that the trees are in a suitable state for pass2.
149  */
150 static void
ragge
1.244
151 sanitychecks(struct p2env *p2e)
ragge
1.241
152 {
153         struct interpass *ip;
154         int i;
155 #ifdef notyet
156         TMPMARK();
157 #endif
ragge
1.244
158         lbldef = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
159         lbluse = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
ragge
1.241
160
ragge
1.242
161         DLIST_FOREACH(ip, &p2env.ipoleqelem) {
ragge
1.241
162                 if (ip->type == IP_DEFLAB) {
163                         i = ip->ip_lbl;
ragge
1.244
164                         if (i < p2e->ipp->ip_lblnum || i >= p2e->epp->ip_lblnum)
ragge
1.241
165                                 cerror("label %d outside boundaries %d-%d",
ragge
1.244
166                                     ip2e->ipp->ip_lblnump2e->epp->ip_lblnum);
167                         lbldef[i-p2e->ipp->ip_lblnum] = 1;
ragge
1.241
168                 }
169                 if (ip->type == IP_NODE)
ragge
1.243
170                         walkf(ip->ip_nodecktree0);
ragge
1.241
171         }
ragge
1.244
172         for (i = 0i < (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum); i++)
ragge
1.241
173                 if (lbluse[i] != 0 && lbldef[i] == 0)
174                         cerror("internal label %d not defined",
ragge
1.244
175                             i + p2e->ipp->ip_lblnum);
ragge
1.241
176
177 #ifdef notyet
178         TMPFREE();
179 #endif
ragge
1.26
180 }
181 #endif
ragge
1.8
182
ragge
1.130
183 /*
ragge
1.244
184  * Look if a temporary comes from a on-stack argument, in that case
185  * use the already existing stack position instead of moving it to
186  * a new place, and remove the move-to-temp statement.
187  */
188 static int
ragge
1.274
189 stkarg(int tnrint (*soff)[2])
ragge
1.244
190 {
191         struct p2env *p2e = &p2env;
192         struct interpass *ip;
193         NODE *p;
194
ragge
1.248
195         ip = DLIST_NEXT((struct interpass *)p2e->ippqelem);
196         while (ip->type != IP_DEFLAB/* search for first DEFLAB */
197                 ip = DLIST_NEXT(ipqelem);
198
ragge
1.244
199         ip = DLIST_NEXT(ipqelem); /* first NODE */
200
201         for (; ip->type != IP_DEFLABip = DLIST_NEXT(ipqelem)) {
202                 if (ip->type != IP_NODE)
203                         continue;
204
205                 p = ip->ip_node;
ragge
1.247
206                 if (p->n_op == XASM)
207                         continue/* XXX - hack for x86 PIC */
ragge
1.264
208 #ifdef notdef
ragge
1.244
209                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
210                         comperr("temparg");
211 #endif
ragge
1.264
212                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
213                         continue/* unknown tree */
214
ragge
1.244
215                 if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL)
216                         continue/* arg in register */
217                 if (tnr != regno(p->n_left))
218                         continue/* wrong assign */
219                 p = p->n_right;
220                 if (p->n_op == UMUL &&
221                     p->n_left->n_op == PLUS &&
222                     p->n_left->n_left->n_op == REG &&
ragge
1.274
223                     p->n_left->n_right->n_op == ICON) {
224                         soff[0][0] = regno(p->n_left->n_left);
225                         soff[0][1] = (int)p->n_left->n_right->n_lval;
226                 } else if (p->n_op == OREG) {
227                         soff[0][0] = regno(p);
228                         soff[0][1] = (int)p->n_lval;
229                 } else
ragge
1.244
230                         comperr("stkarg: bad arg");
231                 tfree(ip->ip_node);
232                 DLIST_REMOVE(ipqelem);
233                 return 1;
234         }
235         return 0;
236 }
237
238 /*
239  * See if an ADDROF is somewhere inside the expression tree.
240  * If so, fill in the offset table.
241  */
242 static void
243 findaof(NODE *pvoid *arg)
244 {
ragge
1.274
245         int (*aof)[2] = arg;
ragge
1.244
246         int tnr;
247
ragge
1.263
248         if (p->n_op != ADDROF || p->n_left->n_op != TEMP)
ragge
1.244
249                 return;
250         tnr = regno(p->n_left);
ragge
1.274
251         if (aof[tnr][0])
ragge
1.244
252                 return/* already gotten stack address */
253         if (stkarg(tnr, &aof[tnr]))
254                 return/* argument was on stack */
ragge
1.274
255         aof[tnr][0] = FPREG;
256         aof[tnr][1] = BITOOR(freetemp(szty(p->n_left->n_type)));
ragge
1.244
257 }
258
259 /*
ragge
1.89
260  * Check if a node has side effects.
261  */
262 static int
263 isuseless(NODE *n)
264 {
265         switch (n->n_op) {
ragge
1.216
266         case XASM:
ragge
1.89
267         case FUNARG:
268         case UCALL:
269         case UFORTCALL:
270         case FORCE:
271         case ASSIGN:
272         case CALL:
273         case FORTCALL:
274         case CBRANCH:
275         case RETURN:
276         case GOTO:
277         case STCALL:
278         case USTCALL:
279         case STASG:
280         case STARG:
281                 return 0;
282         default:
283                 return 1;
284         }
285 }
286
ragge
1.130
287 /*
288  * Delete statements with no meaning (like a+b; or 513.4;)
289  */
ragge
1.238
290 NODE *
ragge
1.89
291 deluseless(NODE *p)
292 {
293         struct interpass *ip;
294         NODE *l, *r;
295
296         if (optype(p->n_op) == LTYPE) {
297                 nfree(p);
298                 return NULL;
299         }
300         if (isuseless(p) == 0)
301                 return p;
302
303         if (optype(p->n_op) == UTYPE) {
304                 l = p->n_left;
305                 nfree(p);
306                 return deluseless(l);
307         }
308
309         /* Be sure that both leaves may be valid */
310         l = deluseless(p->n_left);
311         r = deluseless(p->n_right);
312         nfree(p);
313         if (l && r) {
ragge
1.201
314                 ip = ipnode(l);
315                 DLIST_INSERT_AFTER(&prepoleipqelem);
ragge
1.89
316                 return r;
317         } else if (l)
318                 return l;
319         else if (r)
320                 return r;
321         return NULL;
322 }
323
ragge
1.172
324 /*
325  * Receives interpass structs from pass1.
326  */
327 void
328 pass2_compile(struct interpass *ip)
329 {
ragge
1.260
330         void deljumps(struct p2env *);
ragge
1.244
331         struct p2env *p2e = &p2env;
ragge
1.274
332         int (*addrp)[2];
ragge
1.245
333         MARK mark;
ragge
1.244
334
ragge
1.172
335         if (ip->type == IP_PROLOG) {
ragge
1.244
336                 memset(p2e0sizeof(struct p2env));
337                 p2e->ipp = (struct interpass_prolog *)ip;
338                 DLIST_INIT(&p2e->ipoleqelem);
ragge
1.172
339         }
ragge
1.244
340         DLIST_INSERT_BEFORE(&p2e->ipoleipqelem);
ragge
1.172
341         if (ip->type != IP_EPILOG)
342                 return;
343
344 #ifdef PCC_DEBUG
345         if (e2debug) {
346                 printf("Entering pass2\n");
ragge
1.244
347                 printip(&p2e->ipole);
ragge
1.172
348         }
349 #endif
ragge
1.174
350
ragge
1.271
351         afree();
ragge
1.244
352         p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipoleqelem);
353         p2maxautooff = p2autooff = p2e->epp->ipp_autos;
ragge
1.174
354
ragge
1.241
355 #ifdef PCC_DEBUG
ragge
1.244
356         sanitychecks(p2e);
ragge
1.241
357 #endif
ragge
1.244
358         myreader(&p2e->ipole); /* local massage of input */
ragge
1.174
359
ragge
1.244
360         /*
361          * Do initial modification of the trees.  Two loops;
362          * - first, search for ADDROF of TEMPs, these must be
363          *   converterd to OREGs on stack.
364          * - second, do the actual conversions, in case of not xtemps
365          *   convert all temporaries to stack references.
366          */
ragge
1.245
367         markset(&mark);
ragge
1.244
368         if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) {
ragge
1.274
369                 addrp = tmpcalloc(sizeof(*addrp) *
ragge
1.244
370                     (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum));
371                 addrp -= p2e->ipp->ip_tmpnum;
372         } else
373                 addrp = NULL;
374         if (xtemps) {
375                 DLIST_FOREACH(ip, &p2e->ipoleqelem) {
376                         if (ip->type == IP_NODE)
377                                 walkf(ip->ip_nodefindaofaddrp);
378                 }
379         }
ragge
1.246
380         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.244
381                 if (ip->type == IP_NODE)
382                         walkf(ip->ip_nodedeltempaddrp);
ragge
1.245
383         markfree(&mark);
ragge
1.244
384
385 #ifdef PCC_DEBUG
386         if (e2debug) {
387                 printf("Efter ADDROF/TEMP\n");
388                 printip(&p2e->ipole);
389         }
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
plunky
1.275
413         if (xssa && xtemps && xdeljumps)
ragge
1.260
414                 deljumps(p2e);
415
ragge
1.244
416         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.172
417                 emit(ip);
418 }
419
ragge
1.124
420 void
ragge
1.125
421 emit(struct interpass *ip)
ragge
1.124
422 {
gmcgarry
1.208
423         NODE *p, *r;
424         struct optab *op;
ragge
1.149
425         int o;
ragge
1.124
426
ragge
1.125
427         switch (ip->type) {
428         case IP_NODE:
429                 p = ip->ip_node;
ragge
1.124
430
ragge
1.149
431                 nodepole = p;
ragge
1.180
432                 canon(p); /* may convert stuff after genregs */
ragge
1.240
433                 if (c2debug > 1) {
434                         printf("emit IP_NODE:\n");
435                         fwalk(pe2print0);
436                 }
ragge
1.124
437                 switch (p->n_op) {
438                 case CBRANCH:
439                         /* Only emit branch insn if RESCC */
gmcgarry
1.208
440                         /* careful when an OPLOG has been elided */
441                         if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) {
442                                 op = &table[TBLIDX(p->n_left->n_left->n_su)];
443                                 r = p->n_left;
444                         } else {
445                                 op = &table[TBLIDX(p->n_left->n_su)];
446                                 r = p;
447                         }
448                         if (op->rewrite & RESCC) {
ragge
1.124
449                                 o = p->n_left->n_op;
gmcgarry
1.208
450                                 gencode(rFORCC);
ragge
1.124
451                                 cbgen(op->n_right->n_lval);
gmcgarry
1.208
452                         } else {
453                                 gencode(rFORCC);
454                         }
ragge
1.124
455                         break;
456                 case FORCE:
ragge
1.151
457                         gencode(p->n_leftINREGS);
ragge
1.124
458                         break;
ragge
1.216
459                 case XASM:
460                         genxasm(p);
461                         break;
ragge
1.124
462                 default:
463                         if (p->n_op != REG || p->n_type != VOID/* XXX */
464                                 gencode(pFOREFF); /* Emit instructions */
465                 }
466
ragge
1.125
467                 tfree(p);
468                 break;
ragge
1.124
469         case IP_PROLOG:
470                 prologue((struct interpass_prolog *)ip);
471                 break;
472         case IP_EPILOG:
473                 eoftn((struct interpass_prolog *)ip);
ragge
1.174
474                 p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
ragge
1.124
475                 break;
476         case IP_DEFLAB:
477                 deflab(ip->ip_lbl);
478                 break;
479         case IP_ASM:
gmcgarry
1.229
480                 printf("%s"ip->ip_asm);
ragge
1.124
481                 break;
482         default:
ragge
1.216
483                 cerror("emit %d"ip->type);
ragge
1.124
484         }
ragge
1.123
485 }
ragge
1.124
486
ragge
1.30
487 #ifdef PCC_DEBUG
ragge
1.1
488 char *cnames[] = {
489         "SANY",
490         "SAREG",
491         "SBREG",
ragge
1.153
492         "SCREG",
493         "SDREG",
ragge
1.1
494         "SCC",
495         "SNAME",
496         "SCON",
497         "SFLD",
498         "SOREG",
499         "STARNM",
500         "STARREG",
501         "INTEMP",
502         "FORARG",
503         "SWADD",
504         0,
ragge
1.72
505 };
ragge
1.1
506
ragge
1.2
507 /*
508  * print a nice-looking description of cookie
509  */
ragge
1.70
510 char *
ragge
1.2
511 prcook(int cookie)
512 {
ragge
1.70
513         static char buf[50];
ragge
1.1
514         int iflag;
515
ragge
1.70
516         if (cookie & SPECIAL) {
517                 switch (cookie) {
518                 case SZERO:
519                         return "SZERO";
520                 case SONE:
521                         return "SONE";
522                 case SMONE:
523                         return "SMONE";
524                 default:
ragge
1.200
525                         snprintf(bufsizeof(buf), "SPECIAL+%d"cookie & ~SPECIAL);
ragge
1.70
526                         return buf;
ragge
1.1
527                 }
ragge
1.70
528         }
ragge
1.1
529
530         flag = 0;
ragge
1.70
531         buf[0] = 0;
532         for (i = 0cnames[i]; ++i) {
533                 if (cookie & (1<<i)) {
534                         if (flag)
ragge
1.200
535                                 strlcat(buf"|"sizeof(buf));
ragge
1.1
536                         ++flag;
ragge
1.200
537                         strlcat(bufcnames[i], sizeof(buf));
ragge
1.1
538                 }
ragge
1.70
539         }
540         return buf;
541 }
ragge
1.30
542 #endif
ragge
1.1
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.265
573                 if (p2->n_op == ICON && p2->n_lval == 0 && *p2->n_name == 0 &&
ragge
1.256
574                     (dope[p1->n_op] & (FLOFLG|DIVFLG|SIMPFLG|SHFFLG))) {
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;
gmcgarry
1.251
647                 p1->n_label = (int)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 */
gmcgarry
1.250
665 #if 0
666                 geninsn(p->n_left1 << p->n_label);
667 #endif
ragge
1.216
668                 break;
669
ragge
1.69
670         default:
ragge
1.174
671                 comperr("geninsn: bad op %s, node %p"opst[o], p);
ragge
1.69
672         }
ragge
1.236
673         if (rv == FFAIL && !q)
ragge
1.160
674                 comperr("Cannot generate code, node %p op %s"p,opst[p->n_op]);
675         if (rv == FRETRY)
676                 goto again;
ragge
1.236
677 #ifdef PCC_DEBUG
678         if (odebug) {
679                 printf("geninsn(%p, %s) rv %d\n"pprcook(cookie), rv);
680                 fwalk(pe2print0);
681         }
682 #endif
ragge
1.153
683         return rv;
ragge
1.69
684 }
685
ragge
1.72
686 /*
687  * Store a given subtree in a temporary location.
688  * Return an OREG node where it is located.
689  */
690 NODE *
691 store(NODE *p)
ragge
1.2
692 {
ragge
1.130
693         extern struct interpass *storesave;
694         struct interpass *ip;
695         NODE *q, *r;
696         int s;
ragge
1.49
697
ragge
1.130
698         s = BITOOR(freetemp(szty(p->n_type)));
699         q = mklnode(OREGsFPREGp->n_type);
700         r = mklnode(OREGsFPREGp->n_type);
701         ip = ipnode(mkbinode(ASSIGNqpp->n_type));
702
ragge
1.149
703         storesave = ip;
ragge
1.72
704         return r;
ragge
1.8
705 }
ragge
1.1
706
ragge
1.170
707 #ifdef PCC_DEBUG
708 #define CDEBUG(x) if (c2debug) printf x
709 #else
710 #define CDEBUG(x)
711 #endif
712
ragge
1.69
713 /*
ragge
1.188
714  * Do a register-register move if necessary.
ragge
1.270
715  * Called if a RLEFT or RRIGHT is found.
ragge
1.188
716  */
717 static void
718 ckmove(NODE *pNODE *q)
719 {
ragge
1.270
720         struct optab *t = &table[TBLIDX(p->n_su)];
721         int reg;
722
ragge
1.189
723         if (q->n_op != REG || p->n_reg == -1)
ragge
1.188
724                 return/* no register */
ragge
1.270
725
726         /* do we have a need for special reg? */
727         if (t->needs & NSPECIAL)
728                 reg = rspecial(tp->n_left == q ? NLEFT : NRIGHT);
729         else
730                 reg = DECRA(p->n_reg0);
731
732         if (reg < 0 || reg == DECRA(q->n_reg0))
ragge
1.188
733                 return/* no move necessary */
ragge
1.270
734
ragge
1.190
735         CDEBUG(("rmove: node %p, %s -> %s\n"prnames[DECRA(q->n_reg0)],
ragge
1.270
736             rnames[reg]));
737         rmove(DECRA(q->n_reg0), regp->n_type);
738         q->n_reg = q->n_rval = reg;
ragge
1.188
739 }
740
741 /*
742  * Rewrite node to register after instruction emit.
ragge
1.75
743  */
744 static void
gmcgarry
1.224
745 rewrite(NODE *pint dorewriteint cookie)
ragge
1.75
746 {
ragge
1.79
747         NODE *l, *r;
748         int o;
749
ragge
1.80
750         l = getlr(p'L');
751         r = getlr(p'R');
ragge
1.79
752         o = p->n_op;
ragge
1.75
753         p->n_op = REG;
ragge
1.76
754         p->n_lval = 0;
ragge
1.95
755         p->n_name = "";
ragge
1.158
756
ragge
1.257
757         if (o == ASSIGN || o == STASG) {
ragge
1.190
758                 /* special rewrite care */
759                 int reg = DECRA(p->n_reg0);
ragge
1.191
760 #define TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
ragge
1.190
761                 if (p->n_reg == -1)
762                         ;
ragge
1.191
763                 else if (TL(l) && (DECRA(l->n_reg0) == reg))
ragge
1.190
764                         ;
ragge
1.191
765                 else if (TL(r) && (DECRA(r->n_reg0) == reg))
ragge
1.190
766                         ;
ragge
1.191
767                 else if (TL(l))
ragge
1.190
768                         rmove(DECRA(l->n_reg0), regp->n_type);
ragge
1.191
769                 else if (TL(r))
ragge
1.190
770                         rmove(DECRA(r->n_reg0), regp->n_type);
771 #if 0
772                 else
773                         comperr("rewrite");
774 #endif
ragge
1.191
775 #undef TL
ragge
1.190
776         }
ragge
1.79
777         if (optype(o) != LTYPE)
778                 tfree(l);
779         if (optype(o) == BITYPE)
780                 tfree(r);
gmcgarry
1.224
781         if (dorewrite == 0)
ragge
1.190
782                 return;
mickey
1.205
783         CDEBUG(("rewrite: %p, reg %s\n"p,
784             p->n_reg == -1"<none>" : rnames[DECRA(p->n_reg0)]));
ragge
1.187
785         p->n_rval = DECRA(p->n_reg0);
ragge
1.75
786 }
787
ragge
1.228
788 #ifndef XASM_TARGARG
789 #define XASM_TARGARG(x,y) 0
790 #endif
791
ragge
1.216
792 /*
793  * printout extended assembler.
794  */
795 void
796 genxasm(NODE *p)
797 {
798         NODE *q, **nary;
799         int n = 1o = 0;
800         char *w;
801
ragge
1.228
802         if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) {
803                 for (q = p->n_leftq->n_op == CMq = q->n_left)
804                         n++;
ragge
1.254
805                 nary = tmpcalloc(sizeof(NODE *)*(n+1));
ragge
1.228
806                 o = n;
807                 for (q = p->n_leftq->n_op == CMq = q->n_left) {
808                         gencode(q->n_right->n_leftINREGS);
809                         nary[--o] = q->n_right;
810                 }
811                 gencode(q->n_leftINREGS);
812                 nary[--o] = q;
813         } else
814                 nary = 0;
ragge
1.216
815
816         w = p->n_name;
817         putchar('\t');
818         while (*w != 0) {
819                 if (*w == '%') {
ragge
1.225
820                         if (w[1] == '%')
821                                 putchar('%');
ragge
1.228
822                         else if (XASM_TARGARG(wnary))
823                                 ; /* handled by target */
ragge
1.225
824                         else if (w[1] < '0' || w[1] > (n + '0'))
ragge
1.228
825                                 uerror("bad xasm arg number %c"w[1]);
ragge
1.253
826                         else {
827                                 if (w[1] == (n + '0'))
828                                         q = nary[(int)w[1]-'0' - 1]; /* XXX */
829                                 else
830                                         q = nary[(int)w[1]-'0'];
831                                 adrput(stdoutq->n_left);
832                         }
ragge
1.216
833                         w++;
ragge
1.228
834                 } else if (*w == '\\') { /* Always 3-digit octal */
835                         int num = *++w - '0';
836                         num = (num << 3) + *++w - '0';
837                         num = (num << 3) + *++w - '0';
838                         putchar(num);
ragge
1.216
839                 } else
840                         putchar(*w);
841                 w++;
842         }
843         putchar('\n');
844 }
845
ragge
1.271
846 /*
847  * Allocate temporary registers for use while emitting this table entry.
848  */
849 static void
850 allo(NODE *pstruct optab *q)
851 {
852         extern int stktemp;
853         int in = ncnt(q->needs);
854
855         for (i = 0i < NRESCi++)
856                 if (resc[i].n_op != FREE)
857                         comperr("allo: used reg");
858         if (n == 0 && (q->needs & NTMASK) == 0)
859                 return;
860         for (i = 0i < n+1i++) {
861                 resc[i].n_op = REG;
862                 resc[i].n_type = p->n_type/* XXX should be correct type */
863                 resc[i].n_rval = DECRA(p->n_regi);
864                 resc[i].n_su = p->n_su/* ??? */
865         }
ragge
1.272
866         if (i > NRESC)
867                 comperr("allo: too many allocs");
ragge
1.271
868         if (q->needs & NTMASK) {
869                 resc[i].n_op = OREG;
870                 resc[i].n_lval = stktemp;
871                 resc[i].n_rval = FPREG;
872                 resc[i].n_su = p->n_su/* ??? */
873                 resc[i].n_name = "";
874         }
875 }
876
877 static void
878 afree(void)
879 {
880         int i;
881
882         for (i = 0i < NRESCi++)
883                 resc[i].n_op = FREE;
884 }
885
ragge
1.69
886 void
ragge
1.72
887 gencode(NODE *pint cookie)
ragge
1.69
888 {
889         struct optab *q = &table[TBLIDX(p->n_su)];
ragge
1.188
890         NODE *p1, *l, *r;
ragge
1.190
891         int o = optype(p->n_op);
ragge
1.240
892 #ifdef F