Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20140601113352

Diff

Diff from 1.288 to:

Annotations

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

Annotated File View

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