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