1 /*        Id: local2.c,v 1.10 2015/06/29 18:49:36 ragge Exp           */
2 /*        $NetBSD: local2.c,v 1.1.1.3 2016/02/09 20:28:27 plunky Exp $          */
3 /*
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 # include "pass2.h"
29 # include <ctype.h>
30 # include <string.h>
31 
32 static int spcoff;
33 static int argsiz(NODE *p);
34 
35 void
deflab(int label)36 deflab(int label)
37 {
38           printf(LABFMT ":\n", label);
39 }
40 
41 void
prologue(struct interpass_prolog * ipp)42 prologue(struct interpass_prolog *ipp)
43 {
44           int addto;
45 
46 #ifdef LANG_F77
47           if (ipp->ipp_vis)
48                     printf("  .globl %s\n", ipp->ipp_name);
49           printf("%s:\n", ipp->ipp_name);
50 #endif
51           printf("jsr         r5,csv\n");
52           addto = p2maxautooff;
53           if (addto >= AUTOINIT/SZCHAR)
54                     addto -= AUTOINIT/SZCHAR;
55           if (addto & 1)
56                     addto++;
57           if (addto == 2)
58                     printf("tst         -(sp)\n");
59           else if (addto == 4)
60                     printf("cmp         -(sp),-(sp)\n");
61           else if (addto > 4)
62                     printf("sub         $%o,sp\n", addto);
63           spcoff = 0;
64 }
65 
66 void
eoftn(struct interpass_prolog * ipp)67 eoftn(struct interpass_prolog *ipp)
68 {
69           if (spcoff)
70                     comperr("spcoff == %d", spcoff);
71           if (ipp->ipp_ip.ip_lbl == 0)
72                     return; /* no code needs to be generated */
73           printf("jmp         cret\n");
74 }
75 
76 /*
77  * add/sub/...
78  *
79  * Param given:
80  */
81 void
hopcode(int f,int o)82 hopcode(int f, int o)
83 {
84           char *str;
85 
86           switch (o) {
87           case PLUS:
88                     str = "add";
89                     break;
90           case MINUS:
91                     str = "sub";
92                     break;
93           case AND:
94                     str = "and";
95                     break;
96           case OR:
97                     str = "or";
98                     break;
99           case ER:
100                     str = "xor";
101                     break;
102           default:
103                     comperr("hopcode2: %d", o);
104                     str = 0; /* XXX gcc */
105           }
106           printf("%s%c", str, f);
107 }
108 
109 /*
110  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
111  */
112 int
tlen(p)113 tlen(p) NODE *p;
114 {
115           switch(p->n_type) {
116                     case CHAR:
117                     case UCHAR:
118                               return(1);
119 
120                     case SHORT:
121                     case USHORT:
122                               return(SZSHORT/SZCHAR);
123 
124                     case DOUBLE:
125                               return(SZDOUBLE/SZCHAR);
126 
127                     case INT:
128                     case UNSIGNED:
129                     case LONG:
130                     case ULONG:
131                               return(SZINT/SZCHAR);
132 
133                     case LONGLONG:
134                     case ULONGLONG:
135                               return SZLONGLONG/SZCHAR;
136 
137                     default:
138                               if (!ISPTR(p->n_type))
139                                         comperr("tlen type %d not pointer");
140                               return SZPOINT(p->n_type)/SZCHAR;
141                     }
142 }
143 
144 /*
145  * Emit code to compare two long numbers.
146  */
147 static void
twolcomp(NODE * p)148 twolcomp(NODE *p)
149 {
150           int o = p->n_op;
151           int s = getlab2();
152           int e = p->n_label;
153           int cb1, cb2;
154 
155           if (o >= ULE)
156                     o -= (ULE-LE);
157           switch (o) {
158           case NE:
159                     cb1 = 0;
160                     cb2 = NE;
161                     break;
162           case EQ:
163                     cb1 = NE;
164                     cb2 = 0;
165                     break;
166           case LE:
167           case LT:
168                     cb1 = GT;
169                     cb2 = LT;
170                     break;
171           case GE:
172           case GT:
173                     cb1 = LT;
174                     cb2 = GT;
175                     break;
176 
177           default:
178                     cb1 = cb2 = 0; /* XXX gcc */
179           }
180           if (p->n_op >= ULE)
181                     cb1 += 2, cb2 += 2;
182           expand(p, 0, "cmp   AR,AL\n");
183           if (cb1) cbgen(cb1, s);
184           if (cb2) cbgen(cb2, e);
185         expand(p, 0, "cmp     UR,UL\n");
186         cbgen(p->n_op, e);
187         deflab(s);
188 }
189 
190 
191 /*
192  * Generate compare code for long instructions when right node is 0.
193  */
194 static void
lcomp(NODE * p)195 lcomp(NODE *p)
196 {
197           switch (p->n_op) {
198           case EQ:
199                     expand(p, FORCC, "tst         AL\n");
200                     printf("jne         1f\n");
201                     expand(p, FORCC, "tst         UL\n");
202                     cbgen(EQ, p->n_label);
203                     printf("1:\n");
204                     break;
205           case NE:
206                     expand(p, FORCC, "tst         AL\n");
207                     cbgen(NE, p->n_label);
208                     expand(p, FORCC, "tst         UL\n");
209                     cbgen(NE, p->n_label);
210                     break;
211           case GE:
212                     expand(p, FORCC, "tst         AL\n");
213                     cbgen(GE, p->n_label);
214                     break;
215           default:
216                     comperr("lcomp %p", p);
217           }
218 }
219 
220 void
zzzcode(NODE * p,int c)221 zzzcode(NODE *p, int c)
222 {
223           switch (c) {
224           case 'A': /* print out - if not first arg */
225                     if (spcoff || (p->n_type == FLOAT || p->n_type == DOUBLE))
226                               printf("-");
227                     spcoff += argsiz(p);
228                     break;
229 
230           case 'B': /* arg is pointer to block */
231                     expand(p->n_left, FOREFF, "mov          AL,ZA(sp)\n");
232                     expand(p->n_left, FOREFF, "sub          CR,(sp)\n");
233                     break;
234 
235           case 'C': /* subtract stack after call */
236                     spcoff -= p->n_qual;
237                     if (spcoff == 0 /* && !(p->n_flags & NLOCAL1) XXX FIXME */)
238                               p->n_qual -= 2;
239                     if (p->n_qual == 2)
240                               printf("tst         (sp)+\n");
241                     else if (p->n_qual == 4)
242                               printf("cmp         (sp)+,(sp)+\n");
243                     else if (p->n_qual > 2)
244                               printf("add         $%o,sp\n", (int)p->n_qual);
245                     break;
246 
247           case 'D': /* long comparisions */
248                     lcomp(p);
249                     break;
250 
251           case 'E': /* long move */
252                     rmove(p->n_right->n_reg, p->n_left->n_reg, p->n_type);
253                     break;
254 
255           case 'F': /* long comparision */
256                     twolcomp(p);
257                     break;
258 
259           case 'G': /* printout a subnode for post-inc */
260                     adrput(stdout, p->n_left->n_left);
261                     break;
262 
263           case 'H': /* arg with post-inc */
264                     expand(p->n_left->n_left, FOREFF, "mov  AL,ZA(sp)\n");
265                     expand(p->n_left->n_left, FOREFF, "inc  AL\n");
266                     break;
267 
268           case 'Q': /* struct assignment, no rv */
269                     printf("mov         $%o,", attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0)/2);
270                     expand(p, INAREG, "A1\n");
271                     printf("1:\n");
272                     expand(p, INAREG, "mov        (AR)+,(AL)+\n");
273                     expand(p, INAREG, "dec        A1\n");
274                     printf("jne         1b\n");
275                     break;
276 
277           case 'R': /* struct assignment with rv */
278                     printf("mov         $%o,", attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0)/2);
279                     expand(p, INAREG, "A1\n");
280                     expand(p, INAREG, "mov        AR,A2\n");
281                     printf("1:\n");
282                     expand(p, INAREG, "mov        (A2)+,(AL)+\n");
283                     expand(p, INAREG, "dec        A1\n");
284                     printf("jne         1b\n");
285                     break;
286 
287           case '1': /* lower part of double regs */
288                     p = getlr(p, '1');
289                     printf("r%c", rnames[p->n_rval][1]);
290                     break;
291 
292           default:
293                     comperr("zzzcode %c", c);
294           }
295 }
296 
297 /*ARGSUSED*/
298 int
rewfld(NODE * p)299 rewfld(NODE *p)
300 {
301           return(1);
302 }
303 
304 int canaddr(NODE *);
305 int
canaddr(NODE * p)306 canaddr(NODE *p)
307 {
308           int o = p->n_op;
309 
310           if (o==NAME || o==REG || o==ICON || o==OREG ||
311               (o==UMUL && shumul(p->n_left, STARNM|SOREG)))
312                     return(1);
313           return(0);
314 }
315 
316 /*
317  * Does the bitfield shape match?
318  */
319 int
flshape(NODE * p)320 flshape(NODE *p)
321 {
322           int o = p->n_op;
323 
324           if (o == OREG || o == REG || o == NAME)
325                     return SRDIR; /* Direct match */
326           if (o == UMUL && shumul(p->n_left, SOREG))
327                     return SROREG; /* Convert into oreg */
328           return SRREG; /* put it into a register */
329 }
330 
331 /* INTEMP shapes must not contain any temporary registers */
332 /* XXX should this go away now? */
333 int
shtemp(NODE * p)334 shtemp(NODE *p)
335 {
336           return 0;
337 #if 0
338           int r;
339 
340           if (p->n_op == STARG )
341                     p = p->n_left;
342 
343           switch (p->n_op) {
344           case REG:
345                     return (!istreg(p->n_rval));
346 
347           case OREG:
348                     r = p->n_rval;
349                     if (R2TEST(r)) {
350                               if (istreg(R2UPK1(r)))
351                                         return(0);
352                               r = R2UPK2(r);
353                     }
354                     return (!istreg(r));
355 
356           case UMUL:
357                     p = p->n_left;
358                     return (p->n_op != UMUL && shtemp(p));
359           }
360 
361           if (optype(p->n_op) != LTYPE)
362                     return(0);
363           return(1);
364 #endif
365 }
366 
367 static void
negcon(FILE * fp,int con)368 negcon(FILE *fp, int con)
369 {
370           if (con < 0)
371                     fprintf(fp, "-"), con = -con;
372           fprintf(fp, "%o", con & 0177777);
373 }
374 
375 void
adrcon(CONSZ val)376 adrcon(CONSZ val)
377 {
378           printf("$" CONFMT, val);
379 }
380 
381 void
conput(FILE * fp,NODE * p)382 conput(FILE *fp, NODE *p)
383 {
384           int val = p->n_lval;
385 
386           switch (p->n_op) {
387           case ICON:
388                     printf("$");
389                     if (p->n_name[0] != '\0') {
390                               fprintf(fp, "%s", p->n_name);
391                               if (val)
392                                         fprintf(fp, "+%o", val & 0177777);
393                     } else if (p->n_type == LONG || p->n_type == ULONG)
394                               negcon(fp, val >> 16);
395                     else
396                               negcon(fp, val);
397                     return;
398 
399           default:
400                     comperr("illegal conput, p %p", p);
401           }
402 }
403 
404 /*ARGSUSED*/
405 void
insput(NODE * p)406 insput(NODE *p)
407 {
408           comperr("insput");
409 }
410 
411 /*
412  * Write out the upper address, like the upper register of a 2-register
413  * reference, or the next memory location.
414  */
415 void
upput(NODE * p,int size)416 upput(NODE *p, int size)
417 {
418           size /= SZINT;
419           switch (p->n_op) {
420           case NAME:
421           case OREG:
422                     p->n_lval += size;
423                     adrput(stdout, p);
424                     p->n_lval -= size;
425                     break;
426           case REG:
427                     printf("r%c", rnames[p->n_rval][2]);
428                     break;
429           case ICON:
430                     /* On PDP11 upper value is low 16 bits */
431                     printf("$");
432                     negcon(stdout, p->n_lval & 0177777);
433                     break;
434           default:
435                     comperr("upput bad op %d size %d", p->n_op, size);
436           }
437 }
438 
439 /*
440  * output an address, with offsets, from p
441  */
442 void
adrput(FILE * io,NODE * p)443 adrput(FILE *io, NODE *p)
444 {
445           int r;
446 
447           if (p->n_op == FLD)
448                     p = p->n_left;
449 
450           switch (p->n_op) {
451           case NAME:
452                     if (p->n_name[0] != '\0') {
453                               fputs(p->n_name, io);
454                               if (p->n_lval != 0)
455                                         fprintf(io, "+%o", (int)(p->n_lval&0177777));
456                     } else
457                               negcon(io, p->n_lval);
458                     return;
459 
460           case OREG:
461                     r = p->n_rval;
462                     if (p->n_name[0])
463                               printf("%s%s", p->n_name, p->n_lval ? "+" : "");
464                     if (R2TEST(r) && R2UPK3(r) == 0)
465                               printf("*");
466                     if (p->n_lval)
467                               negcon(io, p->n_lval);
468                     if (R2TEST(r)) {
469                               fprintf(io, "(%s)", rnames[R2UPK1(r)]);
470                               if (R2UPK3(r) == 1)
471                                         fprintf(io, "+");
472                     } else
473                               fprintf(io, "(%s)", rnames[p->n_rval]);
474                     return;
475           case ICON:
476                     /* addressable value of the constant */
477                     conput(io, p);
478                     return;
479 
480           case REG:
481                     switch (p->n_type) {
482                     case LONG:
483                     case ULONG:
484                               fprintf(io, "r%c", rnames[p->n_rval][1]);
485                               break;
486                     default:
487                               fprintf(io, "%s", rnames[p->n_rval]);
488                     }
489                     return;
490 
491           case UMUL:
492                     if (tshape(p, STARNM)) {
493                               printf("*");
494                               adrput(io, p->n_left);
495                               break;
496                     }
497                     /* FALLTHROUGH */
498           default:
499                     comperr("illegal address, op %d, node %p", p->n_op, p);
500                     return;
501 
502           }
503 }
504 
505 static char *
506 ccbranches[] = {
507           "jeq",              /* jumpe */
508           "jne",              /* jumpn */
509           "jle",              /* jumple */
510           "jlt",              /* jumpl */
511           "jge",              /* jumpge */
512           "jgt",              /* jumpg */
513           "jlos",             /* jumple (jlequ) */
514           "jlo",              /* jumpl (jlssu) */
515           "jhis",             /* jumpge (jgequ) */
516           "jhi",              /* jumpg (jgtru) */
517 };
518 
519 
520 /*   printf conditional and unconditional branches */
521 void
cbgen(int o,int lab)522 cbgen(int o, int lab)
523 {
524           if (o < EQ || o > UGT)
525                     comperr("bad conditional branch: %s", opst[o]);
526           printf("%s          " LABFMT "\n", ccbranches[o-EQ], lab);
527 }
528 
529 #define   IS1CON(p) ((p)->n_op == ICON && (p)->n_lval == 1)
530 
531 /*
532  * Move postfix operators to the next statement, unless they are
533  * within a function call or a branch.
534  */
535 static void
cvtree(NODE * p,struct interpass * ip2)536 cvtree(NODE *p, struct interpass *ip2)
537 {
538           struct interpass *ip;
539           NODE *q;
540 
541           if (callop(p->n_op) || p->n_op == CBRANCH)
542                     return;
543 
544           if ((p->n_op == PLUS || p->n_op == MINUS) &&
545               IS1CON(p->n_right) && (q = p->n_left)->n_op == ASSIGN &&
546               treecmp(q->n_left, q->n_right->n_left) &&
547               IS1CON(q->n_right->n_right)) {
548                     if ((p->n_op == PLUS && q->n_right->n_op == MINUS) ||
549                         (p->n_op == MINUS && q->n_right->n_op == PLUS)) {
550                               nfree(p->n_right);
551                               *p = *q->n_left;
552                               if (optype(p->n_op) != LTYPE)
553                                         p->n_left = tcopy(p->n_left);
554                               ip = ipnode(q);
555                               DLIST_INSERT_AFTER(ip2, ip, qelem);
556                               return;
557                     }
558           }
559           if (optype(p->n_op) == BITYPE)
560                     cvtree(p->n_right, ip2);
561           if (optype(p->n_op) != LTYPE)
562                     cvtree(p->n_left, ip2);
563 }
564 
565 /*
566  * Convert AND to BIC.
567  */
568 static void
fixops(NODE * p,void * arg)569 fixops(NODE *p, void *arg)
570 {
571           static int fltwritten;
572 
573           if (!fltwritten && (p->n_type == FLOAT || p->n_type == DOUBLE)) {
574                     printf(".globl      fltused\n");
575                     fltwritten = 1;
576           }
577           switch (p->n_op) {
578           case AND:
579                     if (p->n_right->n_op == ICON) {
580                               p->n_right->n_lval = ((~p->n_right->n_lval) & 0177777);
581                     } else if (p->n_right->n_op == COMPL) {
582                               NODE *q = p->n_right->n_left;
583                               nfree(p->n_right);
584                               p->n_right = q;
585                     } else
586                               p->n_right = mkunode(COMPL, p->n_right, 0, p->n_type);
587                     break;
588           case RS:
589                     p->n_right = mkunode(UMINUS, p->n_right, 0, p->n_right->n_type);
590                     p->n_op = LS;
591                     break;
592           case EQ:
593           case NE: /* Hack not to clear bits if FORCC */
594                     if (p->n_left->n_op == AND)
595                               fixops(p->n_left, 0); /* Convert an extra time */
596                     break;
597           }
598 }
599 
600 void
myreader(struct interpass * ipole)601 myreader(struct interpass *ipole)
602 {
603           struct interpass *ip;
604 
605 #ifdef PCC_DEBUG
606           if (x2debug) {
607                     printf("myreader before\n");
608                     printip(ipole);
609           }
610 #endif
611           DLIST_FOREACH(ip, ipole, qelem) {
612                     if (ip->type != IP_NODE)
613                               continue;
614                     walkf(ip->ip_node, fixops, 0);
615                     canon(ip->ip_node); /* call it early */
616           }
617 #ifdef PCC_DEBUG
618           if (x2debug) {
619                     printf("myreader middle\n");
620                     printip(ipole);
621           }
622 #endif
623           DLIST_FOREACH(ip, ipole, qelem) {
624                     if (ip->type == IP_NODE)
625                               cvtree(ip->ip_node, ip);
626           }
627 #ifdef PCC_DEBUG
628           if (x2debug) {
629                     printf("myreader after\n");
630                     printip(ipole);
631           }
632 #endif
633 }
634 
635 /*
636  * Remove SCONVs where the left node is an OREG with a smaller type.
637  */
638 static void
delsconv(NODE * p,void * arg)639 delsconv(NODE *p, void *arg)
640 {
641 #if 0
642           NODE *l;
643 
644           if (p->n_op != SCONV || (l = p->n_left)->n_op != OREG)
645                     return;
646           if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == LONG) {
647                     p->n_op = OREG;
648                     p->n_lval = l->n_lval; /* high word */
649                     p->n_rval = l->n_rval;
650                     nfree(l);
651           }
652 #endif
653           /* Could do this for char etc. also */
654 }
655 
656 void
mycanon(NODE * p)657 mycanon(NODE *p)
658 {
659           walkf(p, delsconv, 0);
660 }
661 
662 void
myoptim(struct interpass * ip)663 myoptim(struct interpass *ip)
664 {
665 }
666 
667 void
rmove(int s,int d,TWORD t)668 rmove(int s, int d, TWORD t)
669 {
670           if (t < LONG || t > BTMASK) {
671                     printf("mov%s       %s,%s\n", t < SHORT ? "b" : "",
672                         rnames[s],rnames[d]); /* XXX char should be full reg? */
673           } else if (t == LONG || t == ULONG) {
674                     /* avoid trashing double regs */
675                     if (d > s)
676                               printf("mov     r%c,r%c\nmov    r%c,r%c\n",
677                                   rnames[s][2],rnames[d][2],
678                                   rnames[s][1],rnames[d][1]);
679                     else
680                               printf("mov         r%c,r%c\nmov        r%c,r%c\n",
681                                   rnames[s][1],rnames[d][1],
682                                   rnames[s][2],rnames[d][2]);
683           } else if (t == FLOAT || t == DOUBLE) {
684                     printf("movf        %s,%s\n", rnames[s],rnames[d]);
685           } else
686                     comperr("bad float rmove: %d %d %x", s, d, t);
687 
688 }
689 
690 /*
691  * For class c, find worst-case displacement of the number of
692  * registers in the array r[] indexed by class.
693  */
694 int
COLORMAP(int c,int * r)695 COLORMAP(int c, int *r)
696 {
697           switch (c) {
698           case CLASSA:
699                     return (r[CLASSB] * 2 + r[CLASSA]) < 5;
700           case CLASSB:
701                     if (r[CLASSB] > 1) return 0;
702                     if (r[CLASSB] == 1 && r[CLASSA] > 0) return 0;
703                     if (r[CLASSA] > 2) return 0;
704                     return 1;
705           case CLASSC:
706                     return r[CLASSC] < 8;
707           }
708           return 0;
709 }
710 
711 char *rnames[] = {
712           "r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc",
713           "r01", "r12", "r23", "r34", "XXX", "XXX", "XXX", "XXX",
714           "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "XXX", "XXX",
715 };
716 
717 /*
718  * Return a class suitable for a specific type.
719  */
720 int
gclass(TWORD t)721 gclass(TWORD t)
722 {
723           if (t < LONG || t > BTMASK)
724                     return CLASSA;
725           if (t == LONG || t == ULONG)
726                     return CLASSB;
727           if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
728                     return CLASSC;
729           comperr("gclass");
730           return CLASSD;
731 }
732 
733 static int
argsiz(NODE * p)734 argsiz(NODE *p)
735 {
736           TWORD t = p->n_type;
737 
738           if (t == LONG || t == ULONG || t == FLOAT)
739                     return 4;
740           if (t == DOUBLE)
741                     return 8;
742           if (t == STRTY || t == UNIONTY)
743                     return attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
744           return 2;
745 }
746 
747 /*
748  * Argument specialties.
749  */
750 void
lastcall(NODE * p)751 lastcall(NODE *p)
752 {
753           NODE *op = p;
754           int size = 0;
755 
756           /*
757            * Calculate arg sizes.
758            * Mark first arg not to have - before it.
759            */
760           p->n_qual = 0;
761           if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
762                     return;
763           for (p = p->n_right; p->n_op == CM; p = p->n_left) {
764                     p->n_right->n_qual = 0;
765                     size += argsiz(p->n_right);
766           }
767           p->n_qual = 0;
768           size += argsiz(p);
769           p = op->n_right;
770 
771           if (p->n_op == CM)
772                     p = p->n_right;
773 #if 0 /* XXX fixme */
774           if (p->n_type == FLOAT || p->n_type == DOUBLE ||
775               p->n_type == STRTY || p->n_type == UNIONTY)
776                     op->n_flags |= NLOCAL1;       /* Does not use stack slot */
777           else
778                     op->n_flags &= ~NLOCAL1;
779 #endif
780           op->n_qual = size; /* XXX */
781 }
782 
783 static int
is1con(NODE * p)784 is1con(NODE *p)
785 {
786           if (p->n_op == ICON && p->n_lval == 1)
787                     return 1;
788           return 0;
789 }
790 
791 /*
792  * Special shapes.
793  */
794 int
special(NODE * p,int shape)795 special(NODE *p, int shape)
796 {
797           CONSZ s;
798 
799           switch (shape) {
800           case SANDSCON:
801                     s = ~p->n_lval;
802                     if (s < 65536 || s > -65537)
803                               return SRDIR;
804                     break;
805           case SINCB: /* Check if subject for post-inc */
806                     if (p->n_op == ASSIGN && p->n_right->n_op == PLUS &&
807                         treecmp(p->n_left, p->n_right->n_left) &&
808                         is1con(p->n_right->n_right))
809                               return SRDIR;
810                     break;
811           case SARGSUB:
812                     if (p->n_op == MINUS && p->n_right->n_op == ICON &&
813                         p->n_left->n_op == REG)
814                               return SRDIR;
815                     break;
816           case SARGINC:
817                     if (p->n_op == MINUS && is1con(p->n_right))
818                               return special(p->n_left, SINCB);
819                     break;
820           }
821           return SRNOPE;
822 }
823 
824 /*
825  * Target-dependent command-line options.
826  */
827 void
mflags(char * str)828 mflags(char *str)
829 {
830 }
831 
832 /*
833  * Do something target-dependent for xasm arguments.
834  */
835 int
myxasm(struct interpass * ip,NODE * p)836 myxasm(struct interpass *ip, NODE *p)
837 {
838           return 0;
839 }
840 
841 int
fldexpand(NODE * p,int cookie,char ** cp)842 fldexpand(NODE *p, int cookie, char **cp)
843 {
844           return 0;
845 }
846 
847