1 /* $Id: local2.c,v 1.41 2011/02/18 16:52:37 ragge Exp $ */
3 * Copyright (c) 2008 Michael Shalayeff
4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 printf(LABFMT
":\n", label
);
42 static int regoff
[MAXREGS
];
44 char *rbyte
[], *rshort
[], *rlong
[];
47 * Print out the prolog assembler.
48 * addto and regoff are already calculated.
51 prtprolog(struct interpass_prolog
*ipp
, int addto
)
55 /* XXX should look if there is any need to emit this */
56 printf("\tpushq %%rbp\n");
57 printf("\tmovq %%rsp,%%rbp\n");
58 addto
= (addto
+15) & ~15; /* 16-byte aligned */
60 printf("\tsubq $%d,%%rsp\n", addto
);
62 /* save permanent registers */
63 for (i
= 0; i
< MAXREGS
; i
++)
64 if (TESTBIT(ipp
->ipp_regs
, i
))
65 fprintf(stdout
, "\tmovq %s,-%d(%s)\n",
66 rnames
[i
], regoff
[i
], rnames
[FPREG
]);
70 * calculate stack size and offsets
73 offcalc(struct interpass_prolog
*ipp
)
78 if (addto
>= AUTOINIT
/SZCHAR
)
79 addto
-= AUTOINIT
/SZCHAR
;
80 for (i
= 0; i
< MAXREGS
; i
++)
81 if (TESTBIT(ipp
->ipp_regs
, i
)) {
82 addto
+= SZLONG
/SZCHAR
;
89 prologue(struct interpass_prolog
*ipp
)
93 ftype
= ipp
->ipp_type
;
97 printf(" .globl %s\n", ipp
->ipp_name
);
98 printf(" .align 16\n");
99 printf("%s:\n", ipp
->ipp_name
);
102 * We here know what register to save and how much to
105 addto
= offcalc(ipp
);
106 prtprolog(ipp
, addto
);
110 eoftn(struct interpass_prolog
*ipp
)
114 if (ipp
->ipp_ip
.ip_lbl
== 0)
115 return; /* no code needs to be generated */
117 /* return from function code */
118 for (i
= 0; i
< MAXREGS
; i
++)
119 if (TESTBIT(ipp
->ipp_regs
, i
))
120 fprintf(stdout
, " movq -%d(%s),%s\n",
121 regoff
[i
], rnames
[FPREG
], rnames
[i
]);
123 /* struct return needs special treatment */
124 if (ftype
== STRTY
|| ftype
== UNIONTY
) {
125 printf(" movl 8(%%ebp),%%eax\n");
127 printf(" ret $%d\n", 4);
133 printf("\t.size %s,.-%s\n", ipp
->ipp_name
, ipp
->ipp_name
);
143 hopcode(int f
, int o
)
164 comperr("hopcode2: %d", o
);
165 str
= 0; /* XXX gcc */
167 printf("%s%c", str
, f
);
171 * Return type size in bytes. Used by R2REGS, arg 2 to offset().
183 return(SZSHORT
/SZCHAR
);
186 return(SZDOUBLE
/SZCHAR
);
190 return(SZINT
/SZCHAR
);
196 return SZLONGLONG
/SZCHAR
;
199 if (!ISPTR(p
->n_type
))
200 comperr("tlen type %d not pointer");
201 return SZPOINT(p
->n_type
)/SZCHAR
;
206 * Compare two floating point numbers.
212 if (p
->n_left
->n_op
!= REG
)
213 comperr("bad compare %p\n", p
);
214 if ((p
->n_su
& DORIGHT
) == 0)
215 expand(p
, 0, " fxch\n");
216 expand(p
, 0, " fucomip %st(1),%st\n"); /* emit compare insn */
217 expand(p
, 0, " fstp %st(0)\n"); /* pop fromstack */
222 fldexpand(NODE
*p
, int cookie
, char **cp
)
226 if (p
->n_op
== ASSIGN
)
230 printf("%d", UPKFSZ(p
->n_rval
));
233 printf("%d", UPKFOFF(p
->n_rval
));
237 val
= (((((CONSZ
)1 << (UPKFSZ(p
->n_rval
)-1))-1)<<1)|1);
238 val
<<= UPKFOFF(p
->n_rval
);
239 if (p
->n_type
> UNSIGNED
)
240 printf("0x%llx", (**cp
== 'M' ? val
: ~val
));
242 printf("0x%llx", (**cp
== 'M' ? val
: ~val
)&0xffffffff);
245 comperr("fldexpand");
255 if (ISUNSIGNED(p
->n_right
->n_type
))
257 switch (p
->n_right
->n_type
) {
278 sz
-= UPKFSZ(p
->n_left
->n_rval
);
279 printf("\tshl%c $%d,", ch
, sz
);
280 adrput(stdout
, getlr(p
, 'D'));
281 printf("\n\tsar%c $%d,", ch
, sz
);
282 adrput(stdout
, getlr(p
, 'D'));
289 expand(p
, INAREG
, " leaq AL,%rdi\n");
290 if (p
->n_stsize
>= 8)
291 printf("\tmovl $%d,%%ecx\n\trep movsq\n", p
->n_stsize
>> 3);
300 #define E(x) expand(p, 0, x)
302 * Generate code to convert an unsigned long to xmm float/double.
311 E(" cvtsi2sZfq A1,A3\n");
318 E(" cvtsi2sZfq A2,A3\n");
319 E(" addsZf A3,A3\n");
324 * Generate code to convert an x87 long double to an unsigned long.
332 r
= getlr(p
, '1')->n_rval
;
334 E(" subq $16,%rsp\n");
335 E(" movl $0x5f000000,(%rsp)\n"); /* More than long can have */
337 if (p
->n_left
->n_op
== REG
) {
341 E(" fucomi %st(1), %st\n");
344 E(" fstp %st(1)\n"); /* Pop huge val from stack */
345 E(" fnstcw (%rsp)\n"); /* store cw */
346 E(" movw $0x0f3f,4(%rsp)\n");/* round towards 0 */
347 E(" fldcw 4(%rsp)\n"); /* new cw */
348 E(" fistpll 8(%rsp)\n"); /* save val */
349 E(" fldcw (%rsp)\n"); /* fetch old cw */
350 E(" movq 8(%rsp),A1\n");
356 E(" fsubp %st, %st(1)\n");
357 E(" fnstcw (%rsp)\n");
358 E(" movw $0x0f3f,4(%rsp)\n");
359 E(" fldcw 4(%rsp)\n");
360 E(" fistpll 8(%rsp)\n");
361 E(" fldcw (%rsp)\n");
362 E(" movabsq $0x8000000000000000,A1\n");
363 E(" xorq 8(%rsp),A1\n");
365 E("3: addq $16,%rsp\n");
369 * Generate code to convert an SSE float/double to an unsigned long.
374 if (p
->n_left
->n_type
== FLOAT
)
375 E(" movabsq $0x5f000000,A1\n");
377 E(" movabsq $0x43e0000000000000,A1\n");
379 E(" ucomisZg A3,AL\n");
381 E(" cvttsZg2siq AL,A1\n");
384 E(" subsZg A3,AL\n");
385 E(" cvttsZg2siq AL,A1\n");
386 E(" movabsq $0x8000000000000000,A2\n");
393 zzzcode(NODE
*p
, int c
)
400 case 'A': /* swap st0 and st1 if right is evaluated second */
401 if ((p
->n_su
& DORIGHT
) == 0) {
409 case 'B': /* ldouble to unsigned long cast */
413 case 'b': /* float/double to unsigned long cast */
417 case 'C': /* remove from stack after subroutine call */
419 if (p
->n_op
== UCALL
)
420 return; /* XXX remove ZC from UCALL */
422 printf(" addq $%d, %s\n", pr
, rnames
[RSP
]);
425 case 'E': /* Perform bitfield sign-extension */
429 case 'F': /* Structure argument */
430 printf(" subq $%d,%%rsp\n", p
->n_stsize
);
431 printf(" movq %%rsp,%%rsi\n");
435 case 'G': /* Floating point compare */
439 case 'j': /* convert unsigned long to f/d */
443 case 'M': /* Output sconv move, if needed */
445 /* XXX fixneed: regnum */
446 pr
= DECRA(p
->n_reg
, 0);
447 lr
= DECRA(l
->n_reg
, 0);
450 printf(" movb %s,%s\n", rbyte
[lr
], rbyte
[pr
]);
451 l
->n_rval
= l
->n_reg
= p
->n_reg
; /* XXX - not pretty */
454 case 'N': /* output long reg name */
455 printf("%s", rlong
[getlr(p
, '1')->n_rval
]);
458 case 'P': /* Put hidden argument in rdi */
459 printf("\tleaq -%d(%%rbp),%%rdi\n", stkpos
);
462 case 'Q': /* emit struct assign */
466 case 'R': /* print opname based on right type */
467 case 'L': /* print opname based on left type */
468 switch (getlr(p
, c
)->n_type
) {
469 case CHAR
: case UCHAR
: s
= 'b'; break;
470 case SHORT
: case USHORT
: s
= 'w'; break;
471 case INT
: case UNSIGNED
: s
= 'l'; break;
472 default: s
= 'q'; break;
477 case 'U': { /* output branch insn for ucomi */
478 static char *fpcb
[] = { "jz", "jnz", "jbe", "jc", "jnc", "ja" };
479 if (p
->n_op
< EQ
|| p
->n_op
> GT
)
480 comperr("bad fp branch");
481 if (p
->n_op
== NE
|| p
->n_op
== GT
|| p
->n_op
== GE
)
482 expand(p
, 0, " jp LC\n");
483 else if (p
->n_op
== EQ
)
485 printf(" %s ", fpcb
[p
->n_op
- EQ
]);
486 expand(p
, 0, "LC\n");
492 case '8': /* special reg name printout (64-bit) */
493 case '1': /* special reg name printout (32-bit) */
495 rt
= c
== '8' ? rnames
: rlong
;
496 printf("%s", rt
[l
->n_rval
]);
502 case 'f': /* float or double */
503 printf("%c", p
->n_type
== FLOAT
? 's' : 'd');
506 case 'q': /* int or long */
507 printf("%c", p
->n_left
->n_type
== LONG
? 'q' : ' ');
511 comperr("zzzcode %c", c
);
528 if (o
==NAME
|| o
==REG
|| o
==ICON
|| o
==OREG
||
529 (o
==UMUL
&& shumul(p
->n_left
, SOREG
)))
535 * Does the bitfield shape match?
542 if (o
== OREG
|| o
== REG
|| o
== NAME
)
543 return SRDIR
; /* Direct match */
544 if (o
== UMUL
&& shumul(p
->n_left
, SOREG
))
545 return SROREG
; /* Convert into oreg */
546 return SRREG
; /* put it into a register */
549 /* INTEMP shapes must not contain any temporary registers */
550 /* XXX should this go away now? */
558 if (p
->n_op
== STARG
)
563 return (!istreg(p
->n_rval
));
568 if (istreg(R2UPK1(r
)))
576 return (p
->n_op
!= UMUL
&& shtemp(p
));
579 if (optype(p
->n_op
) != LTYPE
)
588 printf("$" CONFMT
, val
);
592 conput(FILE *fp
, NODE
*p
)
594 long val
= p
->n_lval
;
598 if (p
->n_name
[0] != '\0') {
599 fprintf(fp
, "%s", p
->n_name
);
601 fprintf(fp
, "+%ld", val
);
603 fprintf(fp
, "%ld", val
);
607 comperr("illegal conput, p %p", p
);
619 * Write out the upper address, like the upper register of a 2-register
620 * reference, or the next memory location.
621 * XXX - not needed on amd64
624 upput(NODE
*p
, int size
)
630 fprintf(stdout
, "%%%s", &rnames
[p
->n_rval
][3]);
640 fprintf(stdout
, "$" CONFMT
, p
->n_lval
>> 32);
643 comperr("upput bad op %d size %d", p
->n_op
, size
);
648 adrput(FILE *io
, NODE
*p
)
652 /* output an address, with offsets, from p */
660 if (p
->n_name
[0] != '\0') {
662 fprintf(io
, CONFMT
"+", p
->n_lval
);
663 fprintf(io
, "%s(%%rip)", p
->n_name
);
665 fprintf(io
, CONFMT
, p
->n_lval
);
671 printf("%s%s", p
->n_name
, p
->n_lval
? "+" : "");
673 fprintf(io
, "%lld", p
->n_lval
);
679 fprintf(io
, "(%s,%s,%d)",
680 r1
== MAXREGS
? "" : rnames
[r1
],
681 r2
== MAXREGS
? "" : rnames
[r2
], sh
);
683 fprintf(io
, "(%s)", rnames
[p
->n_rval
]);
687 /* Sanitycheck for PIC, to catch adressable constants */
688 if (kflag
&& p
->n_name
[0]) {
692 printf("\nfailing...\n");
693 fwalk(p
, e2print
, 0);
694 comperr("pass2 conput");
698 /* addressable value of the constant */
721 fprintf(io
, "%s", rc
[p
->n_rval
]);
725 comperr("illegal address, op %d, node %p", p
->n_op
, p
);
739 "jbe", /* jumple (jlequ) */
740 "jb", /* jumpl (jlssu) */
741 "jae", /* jumpge (jgequ) */
742 "ja", /* jumpg (jgtru) */
746 /* printf conditional and unconditional branches */
748 cbgen(int o
, int lab
)
750 if (o
< EQ
|| o
> UGT
)
751 comperr("bad conditional branch: %s", opst
[o
]);
752 printf(" %s " LABFMT
"\n", ccbranches
[o
-EQ
], lab
);
756 fixcalls(NODE
*p
, void *arg
)
758 /* Prepare for struct return by allocating bounce space on stack */
762 if (p
->n_stsize
+p2autooff
> stkpos
)
763 stkpos
= p
->n_stsize
+p2autooff
;
769 myreader(struct interpass
*ipole
)
771 struct interpass
*ip
;
774 DLIST_FOREACH(ip
, ipole
, qelem
) {
775 if (ip
->type
!= IP_NODE
)
777 walkf(ip
->ip_node
, fixcalls
, 0);
779 if (stkpos
> p2autooff
)
781 if (stkpos
> p2maxautooff
)
782 p2maxautooff
= stkpos
;
788 * Remove some PCONVs after OREGs are created.
791 pconv2(NODE
*p
, void *arg
)
795 if (p
->n_op
== PLUS
) {
796 if (p
->n_type
== (PTR
|SHORT
) || p
->n_type
== (PTR
|USHORT
)) {
797 if (p
->n_right
->n_op
!= ICON
)
799 if (p
->n_left
->n_op
!= PCONV
)
801 if (p
->n_left
->n_left
->n_op
!= OREG
)
803 q
= p
->n_left
->n_left
;
807 * This will be converted to another OREG later.
820 myoptim(struct interpass
*ip
)
825 rmove(int s
, int d
, TWORD t
)
831 printf(" movl %s,%s\n", rlong
[s
], rlong
[d
]);
835 printf(" movb %s,%s\n", rbyte
[s
], rbyte
[d
]);
839 printf(" movw %s,%s\n", rshort
[s
], rshort
[d
]);
842 printf(" movss %s,%s\n", rnames
[s
], rnames
[d
]);
845 printf(" movsd %s,%s\n", rnames
[s
], rnames
[d
]);
849 /* a=b()*c(); will generate this */
850 /* XXX can it fail anyway? */
851 comperr("bad float rmove: %d %d", s
, d
);
855 printf(" movq %s,%s\n", rnames
[s
], rnames
[d
]);
861 * For class c, find worst-case displacement of the number of
862 * registers in the array r[] indexed by class.
865 COLORMAP(int c
, int *r
)
870 return r
[CLASSA
] < 14;
872 return r
[CLASSB
] < 16;
874 return r
[CLASSC
] < CREGCNT
;
876 return 0; /* XXX gcc */
880 "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
881 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
882 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
883 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14",
887 /* register names for shorter sizes */
889 "%al", "%dl", "%cl", "%bl", "%sil", "%dil", "%bpl", "%spl",
890 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b",
893 "%ax", "%dx", "%cx", "%bx", "%si", "%di", "%bp", "%sp",
894 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w",
897 "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
898 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d",
903 * Return a class suitable for a specific type.
910 if (t
== FLOAT
|| t
== DOUBLE
)
920 if (p
->n_left
->n_op
== REG
)
921 return 0; /* not on stack */
924 if (p
->n_op
== STASG
)
930 * Calculate argument sizes.
939 if (p
->n_op
!= CALL
&& p
->n_op
!= FORTCALL
&& p
->n_op
!= STCALL
)
941 for (p
= p
->n_right
; p
->n_op
== CM
; p
= p
->n_left
)
942 size
+= argsiz(p
->n_right
);
944 size
= (size
+15) & ~15;
946 printf(" subq $%d,%s\n", size
, rnames
[RSP
]);
947 op
->n_qual
= size
; /* XXX */
954 special(NODE
*p
, int shape
)
960 if (o
== STCALL
|| o
== USTCALL
)
964 if (o
!= ICON
|| p
->n_name
[0] ||
965 p
->n_lval
< 0 || p
->n_lval
> 0x7fffffff)
969 return tshape(p
, SZERO
);
971 if (o
!= ICON
|| p
->n_name
[0] ||
972 p
->n_lval
== 0 || p
->n_lval
& 0xffffffff)
976 if (o
!= ICON
|| p
->n_name
[0] ||
977 p
->n_lval
== 0 || (p
->n_lval
>> 32) != 0)
981 if (o
!= ICON
|| p
->n_name
[0])
983 if (p
->n_lval
< MIN_INT
|| p
->n_lval
> MAX_INT
)
987 cerror("special: %x\n", shape
);
993 * Target-dependent command-line options.
1001 * Do something target-dependent for xasm arguments.
1004 myxasm(struct interpass
*ip
, NODE
*p
)
1006 struct interpass
*ip2
;
1007 int Cmax
[] = { 31, 63, 127, 0xffff, 3, 255 };
1008 NODE
*in
= 0, *ut
= 0;
1014 cw
= xasmcode(p
->n_name
);
1015 if (cw
& (XASMASG
|XASMINOUT
))
1017 if ((cw
& XASMASG
) == 0)
1022 case 'D': reg
= RDI
; break;
1023 case 'S': reg
= RSI
; break;
1025 case 'a': reg
= RAX
; break;
1026 case 'b': reg
= RBX
; break;
1027 case 'c': reg
= RCX
; break;
1028 case 'd': reg
= RDX
; break;
1034 p
->n_name
= tmpstrdup(p
->n_name
);
1035 w
= strchr(p
->n_name
, c
);
1036 *w
= 'r'; /* now reg */
1037 return c
== 'q' || c
== 'x' ? 0 : 1;
1045 if (p
->n_left
->n_op
!= ICON
) {
1046 if ((c
= XASMVAL1(cw
)))
1048 uerror("xasm arg not constant");
1050 v
= p
->n_left
->n_lval
;
1051 if ((c
== 'K' && v
< -128) ||
1052 (c
== 'L' && v
!= 0xff && v
!= 0xffff) ||
1053 (c
!= 'K' && v
< 0) ||
1055 uerror("xasm val out of range");
1062 /* If there are requested either memory or register, delete memory */
1063 w
= p
->n_name
= tmpstrdup(p
->n_name
);
1069 t
= p
->n_left
->n_type
;
1071 if (t
== FLOAT
|| t
== DOUBLE
) {
1072 p
->n_label
= CLASSB
;
1074 } else if (t
== LDOUBLE
) {
1075 p
->n_label
= CLASSC
;
1078 p
->n_label
= CLASSA
;
1082 p
->n_left
= mklnode(REG
, 0, reg
, t
);
1084 ip2
= ipnode(mkbinode(ASSIGN
, ut
, tcopy(p
->n_left
), t
));
1085 DLIST_INSERT_AFTER(ip
, ip2
, qelem
);
1088 ip2
= ipnode(mkbinode(ASSIGN
, tcopy(p
->n_left
), in
, t
));
1089 DLIST_INSERT_BEFORE(ip
, ip2
, qelem
);
1096 targarg(char *w
, void *arg
, int n
)
1101 if (w
[1] < '0' || w
[1] > (n
+ '0'))
1102 uerror("bad xasm arg number %c", w
[1]);
1103 if (w
[1] == (n
+ '0'))
1104 p
= ary
[(int)w
[1]-'0' - 1]; /* XXX */
1106 p
= ary
[(int)w
[1]-'0'];
1109 if (optype(p
->n_op
) != LTYPE
)
1110 comperr("bad xarg op %d", p
->n_op
);
1112 if (q
->n_op
== REG
) {
1115 } else if (*w
!= 'w') {
1116 cerror("targarg"); /* XXX ??? */
1117 if (q
->n_type
> UCHAR
) {
1118 regno(q
) = regno(q
)*2+8;
1131 * target-specific conversion of numeric arguments.
1134 numconv(void *ip
, void *p1
, void *q1
)
1136 NODE
*p
= p1
, *q
= q1
;
1137 int cw
= xasmcode(q
->n_name
);
1139 switch (XASMVAL(cw
)) {
1144 p
->n_name
= tmpcalloc(2);
1145 p
->n_name
[0] = XASMVAL(cw
);
1153 char *name
; int num
;
1174 * Check for other names of the xasm constraints registers.
1176 int xasmconstregs(char *s
)
1180 for (i
= 0; xcr
[i
].name
; i
++)
1181 if (strcmp(xcr
[i
].name
, s
) == 0)