Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20150104184104

Diff

Diff from 1.292 to:

Annotations

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

Annotated File View

ragge
1.291
1 /*      $Id: reader.c,v 1.292 2015/01/04 18:41:04 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 */
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
ragge
1.291
882         int ismops = (p->n_op == ASSIGN && (p->n_su & ISMOPS));
ragge
1.240
883 #endif
ragge
1.188
884
885