1 /* $Id: local2.c,v 1.102 2008/11/22 16:12:25 ragge Exp $ */
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 # define putstr(s) fputs((s), stdout)
35 void acon(FILE *, NODE
*p
);
37 void genargs(NODE
*p
);
42 static int regoff
[16];
47 printf(LABFMT
":\n", label
);
51 prologue(struct interpass_prolog
*ipp
)
56 printf(" .globl %s\n", ipp
->ipp_name
);
57 printf("%s:\n", ipp
->ipp_name
);
59 if (addto
>= AUTOINIT
/SZCHAR
)
60 addto
-= AUTOINIT
/SZCHAR
;
61 addto
/= SZINT
/SZCHAR
; /* use words here */
62 printf(" push %s,%s\n",rnames
[STKREG
], rnames
[FPREG
]);
63 printf(" move %s,%s\n", rnames
[FPREG
],rnames
[STKREG
]);
65 for (i
= ipp
->ipp_regs
[0], j
= 0; i
; i
>>= 1, j
++) {
70 printf(" addi %s,0%o\n", rnames
[STKREG
], addto
);
72 for (i
= ipp
->ipp_regs
[0], j
= 0; i
; i
>>= 1, j
++) {
74 printf(" movem %s,%d(%s)\n",
75 rnames
[j
], regoff
[j
], rnames
[STKREG
]);
80 eoftn(struct interpass_prolog
*ipp
)
84 if (ipp
->ipp_ip
.ip_lbl
== 0)
85 return; /* no code needs to be generated */
86 for (i
= ipp
->ipp_regs
[0], j
= 0; i
; i
>>= 1, j
++) {
88 printf(" move %s,%d(%s)\n",
89 rnames
[j
], regoff
[j
], rnames
[STKREG
]);
91 printf(" move %s,%s\n", rnames
[STKREG
], rnames
[FPREG
]);
92 printf(" pop %s,%s\n", rnames
[STKREG
], rnames
[FPREG
]);
93 printf(" popj %s,\n", rnames
[STKREG
]);
98 prologue(int regs
, int autos
)
103 if (regs
< 0 || autos
< 0) {
105 * non-optimized code, jump to epilogue for code generation.
109 printf(" jrst L%d\n", ftlab1
);
110 printf("L%d:\n", ftlab2
);
113 * We here know what register to save and how much to
116 autos
= autos
+ (SZINT
-1);
117 addto
= (autos
- AUTOINIT
)/SZINT
+ (MAXRVAR
-regs
);
118 if (addto
|| gflag
) {
119 printf(" push %s,%s\n",rnames
[017], rnames
[016]);
120 printf(" move %s,%s\n", rnames
[016],rnames
[017]);
121 for (i
= regs
; i
< MAXRVAR
; i
++) {
122 int db
= ((i
+1) < MAXRVAR
);
123 printf(" %smovem %s,0%o(%s)\n",
125 rnames
[i
+1], i
+1-regs
, rnames
[016]);
130 printf(" addi %s,0%o\n", rnames
[017], addto
);
140 eoftn(int regs
, int autos
, int retlab
)
142 register OFFSZ spoff
; /* offset from stack pointer */
145 spoff
= autos
+ (SZINT
-1);
146 if (spoff
>= AUTOINIT
)
149 /* return from function code */
150 printf("L%d:\n", retlab
);
151 if (gflag
|| isoptim
== 0 || autos
!= AUTOINIT
|| regs
!= MAXRVAR
) {
152 for (i
= regs
; i
< MAXRVAR
; i
++) {
153 int db
= ((i
+1) < MAXRVAR
);
154 printf(" %smove %s,0%o(%s)\n", db
? "d" : "",
155 rnames
[i
+1], i
+1-regs
, rnames
[016]);
159 printf(" move %s,%s\n", rnames
[017], rnames
[016]);
160 printf(" pop %s,%s\n", rnames
[017], rnames
[016]);
162 printf(" popj %s,\n", rnames
[017]);
166 printf("L%d:\n", ftlab1
);
167 printf(" push %s,%s\n", rnames
[017], rnames
[016]);
168 printf(" move %s,%s\n", rnames
[016], rnames
[017]);
169 for (i
= regs
; i
< MAXRVAR
; i
++) {
170 int db
= ((i
+1) < MAXRVAR
);
171 printf(" %smovem %s,0%o(%s)\n", db
? "d" : "",
172 rnames
[i
+1], i
+1-regs
, rnames
[016]);
178 printf(" addi %s,0%llo\n", rnames
[017], spoff
);
179 printf(" jrst L%d\n", ftlab2
);
181 printf(" .set " LABFMT
",0%o\n", offlab
, MAXRVAR
-regs
);
182 offarg
= isoptim
= 0;
195 hopcode(int f
, int o
)
197 cerror("hopcode: f %d %d", f
, o
);
201 rnames
[] = { /* keyed to register number tokens */
202 "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7",
203 "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
204 "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7",
205 "%10", "%11", "%12", "%13", "%14", "%15",
218 return(SZSHORT
/SZCHAR
);
221 return(SZDOUBLE
/SZCHAR
);
227 return(SZINT
/SZCHAR
);
231 return SZLONGLONG
/SZCHAR
;
234 if (!ISPTR(p
->n_type
))
235 cerror("tlen type %d not pointer");
236 return SZPOINT(0)/SZCHAR
;
251 * Extract the higher 36 bits from a longlong.
256 CONSZ hval
= (lval
>> 35) & 03777777777LL;
258 if ((hval
& 03000000000LL) == 03000000000LL) {
259 hval
|= 0777000000000LL;
260 } else if ((hval
& 03000000000LL) == 02000000000LL) {
261 hval
&= 01777777777LL;
262 hval
|= 0400000000000LL;
268 * Do a binary comparision, and jump accordingly.
275 int isscon
= 0, iscon
= p
->n_right
->n_op
== ICON
;
277 if (o
< EQ
|| o
> GT
)
278 cerror("bad binary conditional branch: %s", opst
[o
]);
280 if (iscon
&& p
->n_right
->n_name
[0] != 0) {
281 printf(" cam%s ", binskip
[negrel
[o
-EQ
]-EQ
]);
282 adrput(stdout
, getlr(p
, 'L'));
285 adrput(stdout
, getlr(p
, 'R'));
287 printf("\n jrst L%d\n", p
->n_label
);
291 isscon
= p
->n_right
->n_lval
>= 0 &&
292 p
->n_right
->n_lval
< 01000000;
294 printf(" ca%c%s ", iscon
&& isscon
? 'i' : 'm',
295 binskip
[negrel
[o
-EQ
]-EQ
]);
296 adrput(stdout
, getlr(p
, 'L'));
298 if (iscon
&& (isscon
== 0)) {
300 adrput(stdout
, getlr(p
, 'R'));
303 adrput(stdout
, getlr(p
, 'R'));
304 printf("\n jrst L%d\n", p
->n_label
);
308 * Compare byte/word pointers.
309 * XXX - do not work for highest bit set in address
314 printf(" rot "); adrput(stdout
, getlr(p
, 'L')); printf(",6\n");
315 printf(" rot "); adrput(stdout
, getlr(p
, 'R')); printf(",6\n");
320 * Do a binary comparision of two long long, and jump accordingly.
321 * XXX - can optimize for constants.
327 int iscon
= p
->n_right
->n_op
== ICON
;
328 int m
= 0; /* XXX gcc */
330 if (o
< EQ
|| o
> GT
)
331 cerror("bad long long conditional branch: %s", opst
[o
]);
333 /* Special strategy for equal/not equal */
334 if (o
== EQ
|| o
== NE
) {
338 upput(getlr(p
, 'L'), SZLONG
);
342 upput(getlr(p
, 'R'), SZLONG
);
345 printf("\n jrst L%d\n", o
== EQ
? m
: p
->n_label
);
346 printf(" cam%c ", o
== EQ
? 'n' : 'e');
347 adrput(stdout
, getlr(p
, 'L'));
351 adrput(stdout
, getlr(p
, 'R'));
354 printf("\n jrst L%d\n", p
->n_label
);
359 /* First test highword */
360 printf(" cam%ce ", o
== GT
|| o
== GE
? 'l' : 'g');
361 adrput(stdout
, getlr(p
, 'L'));
365 adrput(stdout
, getlr(p
, 'R'));
368 printf("\n jrst L%d\n", p
->n_label
);
372 adrput(stdout
, getlr(p
, 'L'));
376 adrput(stdout
, getlr(p
, 'R'));
379 printf("\n jrst L%d\n", m
= getlab2());
381 /* Test lowword. Only works with pdp10 format for longlongs */
382 printf(" cam%c%c ", o
== GT
|| o
== GE
? 'l' : 'g',
383 o
== LT
|| o
== GT
? 'e' : ' ');
384 upput(getlr(p
, 'L'), SZLONG
);
388 upput(getlr(p
, 'R'), SZLONG
);
391 printf("\n jrst L%d\n", p
->n_label
);
396 * Print the correct instruction for constants.
401 CONSZ val
= p
->n_right
->n_lval
;
402 int reg
= p
->n_left
->n_rval
;
404 /* Only numeric constant */
405 if (p
->n_right
->n_name
[0] == '\0') {
407 printf("movei %s,0", rnames
[reg
]);
408 } else if ((val
& 0777777000000LL) == 0) {
409 printf("movei %s,0%llo", rnames
[reg
], val
);
410 } else if ((val
& 0777777) == 0) {
411 printf("hrlzi %s,0%llo", rnames
[reg
], val
>> 18);
413 printf("move %s,[ .long 0%llo]", rnames
[reg
],
414 szty(p
->n_right
->n_type
) > 1 ? val
:
415 val
& 0777777777777LL);
417 /* Can have more tests here, hrloi etc */
420 printf("xmovei %s,%s", rnames
[reg
], p
->n_right
->n_name
);
422 printf("+" CONFMT
, val
);
427 * Return true if the constant can be bundled in an instruction (immediate).
432 if (p
->n_name
[0] != '\0')
434 if ((p
->n_lval
& 0777777000000ULL) != 0)
440 * Emit a halfword or byte instruction, from OREG to REG.
441 * Sign extension must also be done here.
446 CONSZ off
= p
->n_lval
;
447 TWORD type
= p
->n_type
;
449 int issigned
= !ISUNSIGNED(type
);
450 int ischar
= type
== CHAR
|| type
== UCHAR
;
451 int reg1
= getlr(p
, '1')->n_rval
;
453 if (off
< 0) { /* argument, use move instead */
455 } else if (off
== 0 && p
->n_name
[0] == 0) {
456 printf(" ldb %s,%s\n", rnames
[reg1
], rnames
[reg
]);
457 /* XXX must sign extend here even if not necessary */
460 printf(" lsh %s,033\n", rnames
[reg1
]);
461 printf(" ash %s,-033\n", rnames
[reg1
]);
464 printf(" hrre %s,%s\n",
465 rnames
[reg1
], rnames
[reg1
]);
470 if (off
>= 0700000000000LL && p
->n_name
[0] != '\0') {
472 /* reg contains index integer */
474 // cerror("emitshort !istreg");
475 printf(" adjbp %s,[ .long 0%llo+%s ]\n",
476 rnames
[reg
], off
, p
->n_name
);
478 adrput(stdout
, getlr(p
, '1'));
479 printf(",%s\n", rnames
[reg
]);
483 adrput(stdout
, getlr(p
, '1'));
485 printf(",[ .long 0%02o11%02o%06o ]\n",
486 (int)(27-(9*(off
&3))), reg
, (int)off
/4);
488 printf(",%s\n", rnames
[reg
]);
489 signe
: if (issigned
) {
491 adrput(stdout
, getlr(p
, '1'));
492 printf(",033\n ash ");
493 adrput(stdout
, getlr(p
, '1'));
498 printf(" h%cr%c ", off
& 1 ? 'r' : 'l',
499 issigned
? 'e' : 'z');
501 p
->n_lval
/= (ischar
? 4 : 2);
502 adrput(stdout
, getlr(p
, '1'));
504 adrput(stdout
, getlr(p
, 'L'));
509 * Store a short from a register. Destination is a OREG.
515 CONSZ off
= l
->n_lval
;
517 int ischar
= BTYPE(p
->n_type
) == CHAR
|| BTYPE(p
->n_type
) == UCHAR
;
519 if (l
->n_op
== NAME
) {
522 adrput(stdout
, getlr(p
, 'R'));
523 printf(",[ .long 0%02o%010o+%s ]\n",
524 070+((int)off
&3), (int)(off
/4), l
->n_name
);
527 printf(" hr%cm ", off
& 1 ? 'r' : 'l');
529 adrput(stdout
, getlr(p
, 'R'));
531 adrput(stdout
, getlr(p
, 'L'));
536 if (off
|| reg
== FPREG
) { /* Can emit halfword instructions */
537 if (off
< 0) { /* argument, use move instead */
541 adrput(stdout
, getlr(p
, '1'));
542 printf(",[ .long 0%02o11%02o%06o ]\n",
543 (int)(27-(9*(off
&3))), reg
, (int)off
/4);
546 printf(" hr%cm ", off
& 1 ? 'r' : 'l');
549 adrput(stdout
, getlr(p
, 'R'));
551 adrput(stdout
, getlr(p
, 'L'));
554 adrput(stdout
, getlr(p
, 'R'));
565 * Multiply a register with a constant.
570 NODE
*r
= p
->n_right
;
572 if (r
->n_lval
>= 0 && r
->n_lval
<= 0777777) {
574 adrput(stdout
, getlr(p
, 'L'));
575 printf(",0%llo\n", r
->n_lval
);
578 adrput(stdout
, getlr(p
, 'L'));
579 printf(",[ .long 0%llo ]\n", r
->n_lval
& 0777777777777LL);
584 * Divide a register with a constant.
589 NODE
*r
= p
->n_right
;
591 if (r
->n_lval
>= 0 && r
->n_lval
<= 0777777) {
593 adrput(stdout
, getlr(p
, '1'));
594 printf(",0%llo\n", r
->n_lval
);
597 adrput(stdout
, getlr(p
, '1'));
598 printf(",[ .long 0%llo ]\n", r
->n_lval
& 0777777777777LL);
603 * move a constant into a register.
609 * Trick: If this is an unnamed constant, just move it directly,
610 * otherwise use xmovei to get section number.
612 if (p
->n_name
[0] == '\0' || p
->n_lval
> 0777777) {
616 adrput(stdout
, getlr(p
, '1'));
621 adrput(stdout
, getlr(p
, '1'));
622 printf(",%s", p
->n_name
);
624 printf("+0%llo", p
->n_lval
);
635 if (p
->n_lval
>= 0700000000000LL) {
636 /* converted to pointer in clocal() */
640 if (p
->n_lval
== 0 && p
->n_name
[0] == '\0') {
644 if (BTYPE(p
->n_type
) == CHAR
|| BTYPE(p
->n_type
) == UCHAR
)
645 cz
= (p
->n_lval
/4) | ((p
->n_lval
& 3) << 30);
647 cz
= (p
->n_lval
/2) | (((p
->n_lval
& 1) + 5) << 30);
648 cz
|= 0700000000000LL;
650 if (p
->n_name
[0] != '\0')
651 printf("+%s", p
->n_name
);
657 char *c
= 0; /* XXX gcc */
660 case EQ
: c
= "e"; break;
661 case NE
: c
= "n"; break;
662 case LE
: c
= "le"; break;
663 case LT
: c
= "l"; break;
664 case GT
: c
= "g"; break;
665 case GE
: c
= "ge"; break;
673 zzzcode(NODE
*p
, int c
)
679 case 'A': /* ildb right arg */
680 adrput(stdout
, p
->n_left
->n_left
);
683 case 'B': /* remove from stack after subroutine call */
685 printf(" subi %%17,0%o\n", p
->n_qual
);
692 case 'D': /* Find out which type of const load insn to use */
694 cerror("zzzcode not ICON");
695 if (p
->n_name
[0] == '\0') {
696 if ((p
->n_lval
<= 0777777) && (p
->n_lval
> 0))
698 else if ((p
->n_lval
& 0777777) == 0)
706 case 'E': /* Print correct constant expression */
707 if (p
->n_name
[0] == '\0') {
708 if ((p
->n_lval
<= 0777777) && (p
->n_lval
> 0)){
709 printf("0%llo", p
->n_lval
);
710 } else if ((p
->n_lval
& 0777777) == 0) {
711 printf("0%llo", p
->n_lval
>> 18);
714 printf("[ .long -0%llo]", -p
->n_lval
);
716 printf("[ .long 0%llo]", p
->n_lval
);
720 printf("[ .long %s]", p
->n_name
);
722 printf("[ .long %s+0%llo]",
723 p
->n_name
, p
->n_lval
);
727 case 'G': /* structure argument */
728 printf(" addl %%17,0%o\n", p
->n_stsize
/(SZINT
/SZCHAR
));
737 * Print long long expression.
739 hval
= gethval(p
->n_lval
);
740 printf("[ .long 0%llo,0%llo", hval
,
741 (p
->n_lval
& 0377777777777LL) | (hval
& 0400000000000LL));
742 if (p
->n_name
[0] != '\0')
743 printf("+%s", p
->n_name
);
747 case 'F': /* Print an "opsimp" instruction based on its const type */
748 hopcode(oneinstr(p
->n_right
) ? 'C' : 'R', p
->n_op
);
751 case 'H': /* Print a small constant */
753 printf("0%llo", p
->n_lval
& 0777777);
756 case 'Q': /* two-param long long comparisions */
760 case 'R': /* two-param conditionals */
797 if (p
->n_right
->n_op
!= OREG
|| p
->n_right
->n_lval
!= 0)
798 comperr("bad Zg oreg");
799 printf("%s", rnames
[p
->n_right
->n_rval
]);
803 case '1': /* double upput */
811 case 'i': /* Write instruction for short load from name */
813 printf(" h%cr%c %s,%s+" CONFMT
"\n",
814 l
->n_lval
& 1 ? 'r' : 'l',
815 ISUNSIGNED(p
->n_type
) ? 'z' : 'e',
816 rnames
[getlr(p
, '1')->n_rval
],
817 l
->n_name
, l
->n_lval
>> 1);
821 cerror("zzzcode %c", c
);
825 /* set up temporary registers */
829 fregs
= 7; /* 7 free regs on PDP10 (1-7) */
840 fldexpand(NODE
*p
, int cookie
, char **cp
)
848 register int o
= p
->n_op
;
850 return (o
== REG
|| o
== NAME
|| o
== ICON
||
851 (o
== OREG
&& (!R2TEST(p
->n_rval
) || tlen(p
) == 1)));
854 /* INTEMP shapes must not contain any temporary registers */
862 shumul(NODE
*p
, int order
)
868 printf("shumul(%p)\n", p
);
869 eprint(p
, 0, &val
, &val
);
874 if (o
== NAME
|| (o
== OREG
&& !R2TEST(p
->n_rval
)) || o
== ICON
)
880 (p
->n_left
->n_op
== REG
&& p
->n_right
->n_op
== ICON
) &&
881 p
->n_right
->n_name
[0] == '\0') {
908 if (ISPTR(p
->n_type
) &&
909 ISPTR(DECREF(p
->n_type
))) {
924 cerror("adrcon: val %llo\n", val
);
928 conput(FILE *fp
, NODE
*p
)
932 if (p
->n_lval
!= 0) {
934 if (p
->n_name
[0] != '\0')
937 if (p
->n_name
[0] != '\0')
938 printf("%s", p
->n_name
);
939 if (p
->n_name
[0] == '\0' && p
->n_lval
== 0)
944 putstr(rnames
[p
->n_rval
]);
948 cerror("illegal conput");
960 * Write out the upper address, like the upper register of a 2-register
961 * reference, or the next memory location.
964 upput(NODE
*p
, int size
)
970 putstr(rnames
[p
->n_rval
+ size
]);
980 printf(CONFMT
, p
->n_lval
>> (36 * size
));
983 cerror("upput bad op %d size %d", p
->n_op
, size
);
988 adrput(FILE *fp
, NODE
*p
)
991 /* output an address, with offsets, from p */
999 if (p
->n_name
[0] != '\0')
1000 fputs(p
->n_name
, fp
);
1002 fprintf(fp
, "+" CONFMT
, p
->n_lval
& 0777777777777LL);
1008 if (R2TEST(r
)) { /* double indexing */
1016 if (p
->n_lval
!= 0 || p
->n_name
[0] != '\0')
1018 if (R2UPK1(r
) != 100)
1019 printf("(%s)", rnames
[R2UPK1(r
)]);
1022 printf("[%s]", rnames
[R2UPK2(r
)]);
1027 cerror("adrput: unwanted double indexing: r %o", r
);
1028 if (p
->n_rval
!= FPREG
&& p
->n_lval
< 0 && p
->n_name
[0]) {
1029 fprintf(fp
, "%s", p
->n_name
);
1031 fprintf(fp
, "(%s)", rnames
[p
->n_rval
]);
1034 if (p
->n_lval
< 0 && p
->n_rval
== FPREG
&& offarg
) {
1035 p
->n_lval
-= offarg
-2; acon(fp
, p
); p
->n_lval
+= offarg
-2;
1036 } else if (p
->n_lval
!= 0)
1038 if (p
->n_name
[0] != '\0')
1039 fprintf(fp
, "%s%s", p
->n_lval
? "+" : "", p
->n_name
);
1040 if (p
->n_lval
> 0 && p
->n_rval
== FPREG
&& offlab
)
1041 fprintf(fp
, "+" LABFMT
, offlab
);
1042 if (p
->n_lval
< 0 && p
->n_rval
== FPREG
&& offarg
)
1043 fprintf(fp
, "(017)");
1045 fprintf(fp
, "(%s)", rnames
[p
->n_rval
]);
1048 /* addressable value of the constant */
1049 if (p
->n_lval
> 0) {
1051 if (p
->n_name
[0] != '\0')
1054 if (p
->n_name
[0] != '\0')
1055 fprintf(fp
, "%s", p
->n_name
);
1058 if (p
->n_name
[0] == '\0' && p
->n_lval
== 0)
1063 fputs(rnames
[p
->n_rval
], fp
);
1067 cerror("illegal address, op %d", p
->n_op
);
1074 * print out a constant
1077 acon(FILE *fp
, NODE
*p
)
1079 if (p
->n_lval
< 0 && p
->n_lval
> -0777777777777ULL)
1080 fprintf(fp
, "-" CONFMT
, -p
->n_lval
);
1082 fprintf(fp
, CONFMT
, p
->n_lval
);
1085 /* printf conditional and unconditional branches */
1087 cbgen(int o
,int lab
)
1092 * Do some local optimizations that must be done after optim is called.
1095 optim2(NODE
*p
, void *arg
)
1101 /* Remove redundant PCONV's */
1104 m
= BTYPE(p
->n_type
);
1105 ml
= BTYPE(l
->n_type
);
1106 if ((m
== INT
|| m
== LONG
|| m
== LONGLONG
|| m
== FLOAT
||
1107 m
== DOUBLE
|| m
== STRTY
|| m
== UNIONTY
||
1108 m
== UNSIGNED
|| m
== ULONG
|| m
== ULONGLONG
) &&
1109 (ml
== INT
|| ml
== LONG
|| ml
== LONGLONG
|| ml
== FLOAT
||
1110 ml
== DOUBLE
|| ml
== STRTY
|| ml
== UNIONTY
||
1111 ml
== UNSIGNED
|| ml
== ULONG
||
1112 ml
== ULONGLONG
) && ISPTR(l
->n_type
)) {
1117 if (ISPTR(DECREF(p
->n_type
)) &&
1118 (l
->n_type
== INCREF(STRTY
))) {
1123 if (ISPTR(DECREF(l
->n_type
)) &&
1124 (p
->n_type
== INCREF(INT
) ||
1125 p
->n_type
== INCREF(STRTY
) ||
1126 p
->n_type
== INCREF(UNSIGNED
))) {
1133 /* Add constands, similar to the one in optim() */
1134 if (op
== PLUS
&& p
->n_right
->n_op
== ICON
) {
1136 if (l
->n_op
== PLUS
&& l
->n_right
->n_op
== ICON
&&
1137 (p
->n_right
->n_name
[0] == '\0' ||
1138 l
->n_right
->n_name
[0] == '\0')) {
1139 l
->n_right
->n_lval
+= p
->n_right
->n_lval
;
1140 if (l
->n_right
->n_name
[0] == '\0')
1141 l
->n_right
->n_name
= p
->n_right
->n_name
;
1148 /* Convert "PTR undef" (void *) to "PTR uchar" */
1149 /* XXX - should be done in MI code */
1150 if (BTYPE(p
->n_type
) == VOID
)
1151 p
->n_type
= (p
->n_type
& ~BTMASK
) | UCHAR
;
1153 if ((p
->n_type
== (PTR
|CHAR
) || p
->n_type
== (PTR
|UCHAR
))
1154 && p
->n_lval
== 0 && p
->n_name
[0] != '\0')
1155 p
->n_lval
= 0700000000000LL;
1156 if ((p
->n_type
== (PTR
|SHORT
) || p
->n_type
== (PTR
|USHORT
))
1157 && p
->n_lval
== 0 && p
->n_name
[0] != '\0')
1158 p
->n_lval
= 0750000000000LL;
1161 if ((p
->n_left
->n_type
== (PTR
|CHAR
) ||
1162 p
->n_left
->n_type
== (PTR
|UCHAR
)) &&
1163 (p
->n_right
->n_type
== (PTR
|CHAR
) ||
1164 p
->n_right
->n_type
== (PTR
|UCHAR
))) {
1168 l
->n_left
= p
->n_right
;
1173 l
->n_left
= p
->n_left
;
1180 myreader(struct interpass
*ipole
)
1182 struct interpass
*ip
;
1184 DLIST_FOREACH(ip
, ipole
, qelem
) {
1185 if (ip
->type
!= IP_NODE
)
1187 walkf(ip
->ip_node
, optim2
, 0);
1191 printf("myreader final tree:\n");
1197 * Remove some PCONVs after OREGs are created.
1200 pconv2(NODE
*p
, void *arg
)
1204 if (p
->n_op
== PLUS
) {
1205 if (p
->n_type
== (PTR
|SHORT
) || p
->n_type
== (PTR
|USHORT
)) {
1206 if (p
->n_right
->n_op
!= ICON
)
1208 if (p
->n_left
->n_op
!= PCONV
)
1210 if (p
->n_left
->n_left
->n_op
!= OREG
)
1212 q
= p
->n_left
->n_left
;
1216 * This will be converted to another OREG later.
1225 walkf(p
, pconv2
, 0);
1232 myoptim(struct interpass
*ip
)
1237 * Return a class suitable for a specific type.
1242 return (szty(t
) == 2 ? CLASSB
: CLASSA
);
1248 TWORD t
= p
->n_type
;
1250 if (t
== STRTY
|| t
== UNIONTY
)
1251 return p
->n_stsize
/(SZINT
/SZCHAR
);
1256 * Calculate argument sizes.
1265 if (p
->n_op
!= CALL
&& p
->n_op
!= FORTCALL
&& p
->n_op
!= STCALL
)
1267 for (p
= p
->n_right
; p
->n_op
== CM
; p
= p
->n_left
)
1268 if (p
->n_right
->n_op
!= ASSIGN
)
1269 size
+= argsiz(p
->n_right
);
1270 if (p
->n_op
!= ASSIGN
)
1272 op
->n_qual
= size
; /* XXX */
1276 rmove(int s
, int d
, TWORD t
)
1278 printf(" %smove %s,%s\n",
1279 (s
> 017 ? "d" : ""), rnames
[d
], rnames
[s
]);
1283 * For class c, find worst-case displacement of the number of
1284 * registers in the array r[] indexed by class.
1287 COLORMAP(int c
, int *r
)
1293 /* there are 13 classa, so min 6 classb are needed to block */
1294 num
= r
[CLASSB
] * 2;
1298 /* 7 classa may block all classb */
1299 num
= r
[CLASSB
] + r
[CLASSA
];
1302 comperr("COLORMAP");
1303 return 0; /* XXX gcc */
1307 * Target-dependent command-line options.
1314 * Do something target-dependent for xasm arguments.
1315 * Supposed to find target-specific constraints and rewrite them.
1318 myxasm(struct interpass
*ip
, NODE
*p
)