Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20141011095021

Diff

Diff from 1.290 to:

Annotations

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

Annotated File View

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