Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20110812192024

Diff

Diff from 1.275 to:

Annotations

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

Annotated File View

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