1 /* $Id: local2.c,v 1.72 2006/03/18 08:18:33 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.
40 lineid(int l
, char *fn
)
42 /* identify line l and file fn */
43 printf("# line %d, file %s\n", l
, fn
);
49 printf(LABFMT
":\n", label
);
56 * Print out the prolog assembler.
57 * addto and regoff are already calculated.
60 prtprolog(struct interpass_prolog
*ipp
, int addto
)
64 printf(" pushl %%ebp\n");
65 printf(" movl %%esp,%%ebp\n");
67 printf(" subl $%d,%%esp\n", addto
);
68 for (i
= ipp
->ipp_regs
, j
= 0; i
; i
>>= 1, j
++)
70 fprintf(stdout
, " movl %s,-%d(%s)\n",
71 rnames
[j
], regoff
[j
], rnames
[FPREG
]);
75 * calculate stack size and offsets
78 offcalc(struct interpass_prolog
*ipp
)
83 if (addto
>= AUTOINIT
/SZCHAR
)
84 addto
-= AUTOINIT
/SZCHAR
;
85 for (i
= ipp
->ipp_regs
, j
= 0; i
; i
>>= 1, j
++) {
87 addto
+= SZINT
/SZCHAR
;
95 prologue(struct interpass_prolog
*ipp
)
99 ftype
= ipp
->ipp_type
;
101 printf(" .globl %s\n", ipp
->ipp_name
);
102 printf(" .align 4\n");
103 printf("%s:\n", ipp
->ipp_name
);
105 * We here know what register to save and how much to
108 addto
= offcalc(ipp
);
109 prtprolog(ipp
, addto
);
113 eoftn(struct interpass_prolog
*ipp
)
117 if (ipp
->ipp_ip
.ip_lbl
== 0)
118 return; /* no code needs to be generated */
120 /* return from function code */
121 for (i
= ipp
->ipp_regs
, j
= 0; i
; i
>>= 1, j
++) {
123 fprintf(stdout
, " movl -%d(%s),%s\n",
124 regoff
[j
], rnames
[FPREG
], rnames
[j
]);
128 /* struct return needs special treatment */
129 if (ftype
== STRTY
|| ftype
== UNIONTY
) {
130 printf(" movl 8(%%ebp),%%eax\n");
145 hopcode(int f
, int o
)
166 comperr("hopcode2: %d", o
);
167 str
= 0; /* XXX gcc */
169 printf("%s%c", str
, f
);
173 * Return type size in bytes. Used by R2REGS, arg 2 to offset().
185 return(SZSHORT
/SZCHAR
);
188 return(SZDOUBLE
/SZCHAR
);
194 return(SZINT
/SZCHAR
);
198 return SZLONGLONG
/SZCHAR
;
201 if (!ISPTR(p
->n_type
))
202 comperr("tlen type %d not pointer");
203 return SZPOINT(p
->n_type
)/SZCHAR
;
208 * Emit code to compare two longlong numbers.
241 cb1
= cb2
= 0; /* XXX gcc */
245 expand(p
, 0, " cmpl UR,UL\n");
246 if (cb1
) cbgen(cb1
, s
);
247 if (cb2
) cbgen(cb2
, e
);
248 expand(p
, 0, " cmpl AR,AL\n");
254 * Assign to a bitfield.
255 * Clumsy at least, but what to do?
260 NODE
*fn
= p
->n_left
;
261 int shift
= UPKFOFF(fn
->n_rval
);
262 int fsz
= UPKFSZ(fn
->n_rval
);
265 /* get instruction size */
267 case CHAR
: case UCHAR
: tch
= 'b'; break;
268 case SHORT
: case USHORT
: tch
= 'w'; break;
269 case INT
: case UNSIGNED
: tch
= 'l'; break;
270 default: comperr("bfasg");
273 /* put src into a temporary reg */
274 fprintf(stdout
, " mov%c ", tch
);
275 adrput(stdout
, getlr(p
, 'R'));
276 fprintf(stdout
, ",");
277 adrput(stdout
, getlr(p
, '1'));
278 fprintf(stdout
, "\n");
280 /* AND away the bits from dest */
281 andval
= ~(((1 << fsz
) - 1) << shift
);
282 fprintf(stdout
, " and%c $%d,", tch
, andval
);
283 adrput(stdout
, fn
->n_left
);
284 fprintf(stdout
, "\n");
286 /* AND away unwanted bits from src */
287 andval
= ((1 << fsz
) - 1);
288 fprintf(stdout
, " and%c $%d,", tch
, andval
);
289 adrput(stdout
, getlr(p
, '1'));
290 fprintf(stdout
, "\n");
292 /* SHIFT left src number of bits */
294 fprintf(stdout
, " sal%c $%d,", tch
, shift
);
295 adrput(stdout
, getlr(p
, '1'));
296 fprintf(stdout
, "\n");
299 /* OR in src to dest */
300 fprintf(stdout
, " or%c ", tch
);
301 adrput(stdout
, getlr(p
, '1'));
302 fprintf(stdout
, ",");
303 adrput(stdout
, fn
->n_left
);
304 fprintf(stdout
, "\n");
308 * Push a structure on stack as argument.
309 * the scratch registers are already free here
316 fprintf(fp
, " subl $%d,%%esp\n", p
->n_stsize
);
317 fprintf(fp
, " pushl $%d\n", p
->n_stsize
);
318 expand(p
, 0, " pushl AL\n");
319 expand(p
, 0, " leal 8(%esp),A1\n");
320 expand(p
, 0, " pushl A1\n");
321 fprintf(fp
, " call memcpy\n");
322 fprintf(fp
, " addl $12,%%esp\n");
326 * Compare two floating point numbers.
332 if (p
->n_left
->n_op
== REG
)
333 expand(p
, 0, " fucompp\n"); /* emit compare insn */
334 else if (p
->n_left
->n_type
== DOUBLE
)
335 expand(p
, 0, " fcompl AL\n"); /* emit compare insn */
336 else if (p
->n_left
->n_type
== FLOAT
)
337 expand(p
, 0, " fcomp AL\n"); /* emit compare insn */
339 comperr("bad compare %p\n", p
);
340 expand(p
, 0, " fnstsw %ax\n"); /* move status reg to ax */
344 expand(p
, 0, " andb $64,%ah\n jne LC\n");
347 expand(p
, 0, " andb $64,%ah\n je LC\n");
350 expand(p
, 0, " andb $65,%ah\n cmpb $1,%ah\n jne LC\n");
353 expand(p
, 0, " andb $65,%ah\n je LC\n");
356 expand(p
, 0, " andb $1,%ah\n jne LC\n");
359 expand(p
, 0, " andb $65,%ah\n jne LC\n");
362 comperr("fcomp op %d\n", p
->n_op
);
367 * Convert an unsigned long long to floating point number.
377 expand(p
, 0, " .data\n");
378 printf(LABFMT
": .long 0,0x80000000,0x403f\n", loadlab
);
379 expand(p
, 0, " .text\n");
382 expand(p
, 0, " pushl UL\n pushl AL\n");
383 expand(p
, 0, " fildq (%esp)\n");
384 expand(p
, 0, " addl $8,%esp\n");
385 expand(p
, 0, " cmpl $0,UL\n");
386 printf(" jge " LABFMT
"\n", jmplab
);
387 printf(" fldt " LABFMT
"\n", loadlab
);
388 printf(" faddp %%st,%%st(1)\n");
389 printf(LABFMT
":\n", jmplab
);
397 if (t
< LONGLONG
|| t
== FLOAT
|| t
> MAXTYPES
)
399 if (t
== LONGLONG
|| t
== ULONGLONG
|| t
== DOUBLE
)
410 zzzcode(NODE
*p
, int c
)
420 * Shift operations. Either the right node is a constant
421 * or a register, in the latter case it must be %cl.
425 printf("$" CONFMT
, p
->n_lval
);
426 else if (p
->n_op
!= REG
|| p
->n_rval
!= 2) /* CX */
427 comperr("bad shift reg");
434 * Print conversion chars for loading into register.
438 case SHORT
: printf("swl"); break;
439 case USHORT
: printf("zwl"); break;
440 case CHAR
: printf("sbl"); break;
441 case UCHAR
: printf("zbl"); break;
442 default: comperr("ZB: %d", p
->n_type
);
446 case 'C': /* remove from stack after subroutine call */
448 if (p
->n_op
== STCALL
|| p
->n_op
== USTCALL
) {
450 q
= &table
[TBLIDX(p
->n_su
)];
451 if (q
->visit
== FOREFF
)
454 if (p
->n_op
== UCALL
)
455 return; /* XXX remove ZC from UCALL */
457 printf(" addl $%d, %s\n", pr
, rnames
[ESP
]);
460 case 'D': /* Long long comparision */
464 case 'E': /* Assign to bitfield */
468 case 'F': /* Structure argument */
469 if (p
->n_stalign
!= 0) /* already on stack */
473 case 'G': /* Floating point compare */
477 case 'H': /* Fix correct order of sub from stack */
478 /* Check which leg was evaluated first */
479 if ((p
->n_su
& DORIGHT
) == 0)
483 case 'I': /* high part of init constant */
484 if (p
->n_name
[0] != '\0')
485 comperr("named highword");
486 fprintf(stdout
, CONFMT
, (p
->n_lval
>> 32) & 0xffffffff);
489 case 'J': /* convert unsigned long long to floating point */
497 * Prints out a register of small type, like %al.
498 * Type is determined by op.
501 if (r
->n_op
!= REG
&& r
->n_op
!= MOVE
)
503 comperr("zzz LR1 %p", p
);
506 case 'M': /* Output sconv move, if needed */
508 /* XXX fixneed: regnum */
509 pr
= DECRA(p
->n_reg
, 0);
510 lr
= DECRA(l
->n_reg
, 0);
511 if ((pr
== AL
&& lr
== EAX
) || (pr
== BL
&& lr
== EBX
) ||
512 (pr
== CL
&& lr
== ECX
) || (pr
== DL
&& lr
== EDX
))
515 printf(" movb %%%cl,%s\n",
516 rnames
[lr
][2], rnames
[pr
]);
517 l
->n_rval
= l
->n_reg
= p
->n_reg
; /* XXX - not pretty */
520 case 'N': /* output extended reg name */
521 printf("%s", rnames
[getlr(p
, '1')->n_rval
]);
524 case 'O': /* print out emulated ops */
525 if (p
->n_op
== RS
|| p
->n_op
== LS
)
526 expand(p
, INAREG
, "\tpushl AR\n");
528 expand(p
, INCREG
, "\tpushl UR\n\tpushl AR\n");
529 expand(p
, INCREG
, "\tpushl UL\n\tpushl AL\n");
530 if (p
->n_op
== DIV
&& p
->n_type
== ULONGLONG
) ch
= "udiv";
531 else if (p
->n_op
== DIV
) ch
= "div";
532 else if (p
->n_op
== MUL
) ch
= "mul";
533 else if (p
->n_op
== MOD
&& p
->n_type
== ULONGLONG
) ch
= "umod";
534 else if (p
->n_op
== MOD
) ch
= "mod";
535 else if (p
->n_op
== RS
&& p
->n_type
== ULONGLONG
) ch
= "lshr";
536 else if (p
->n_op
== RS
) ch
= "ashr";
537 else if (p
->n_op
== LS
) ch
= "ashl";
538 else ch
= 0, comperr("ZO");
539 printf("\tcall __%sdi3\n\taddl $16,%s\n", ch
, rnames
[ESP
]);
542 case 'P': /* push hidden argument on stack */
543 r
= (NODE
*)p
->n_sue
;
544 printf("\tleal -%d(%%esp),", stkpos
);
545 adrput(stdout
, getlr(p
, '1'));
546 printf("\n\tpushl ");
547 adrput(stdout
, getlr(p
, '1'));
551 case 'Q': /* emit struct assign */
552 /* XXX - optimize for small structs */
553 printf("\tpushl $%d\n", p
->n_stsize
);
554 expand(p
, INAREG
, "\tpushl AR\n");
555 expand(p
, INAREG
, "\tleal AL,%eax\n\tpushl %eax\n");
556 printf("\tcall memcpy\n");
560 comperr("zzzcode %c", c
);
577 if (o
==NAME
|| o
==REG
|| o
==ICON
|| o
==OREG
||
578 (o
==UMUL
&& shumul(p
->n_left
)))
584 * Does the bitfield shape match?
591 if (o
== OREG
|| o
== REG
|| o
== NAME
)
592 return SRDIR
; /* Direct match */
593 if (o
== UMUL
&& shumul(p
->n_left
))
594 return SROREG
; /* Convert into oreg */
595 return SRREG
; /* put it into a register */
598 /* INTEMP shapes must not contain any temporary registers */
599 /* XXX should this go away now? */
607 if (p
->n_op
== STARG
)
612 return (!istreg(p
->n_rval
));
617 if (istreg(R2UPK1(r
)))
625 return (p
->n_op
!= UMUL
&& shtemp(p
));
628 if (optype(p
->n_op
) != LTYPE
)
637 printf("$" CONFMT
, val
);
641 conput(FILE *fp
, NODE
*p
)
647 if (p
->n_name
[0] != '\0') {
648 fprintf(fp
, "%s", p
->n_name
);
650 fprintf(fp
, "+%d", val
);
652 fprintf(fp
, "%d", val
);
656 comperr("illegal conput");
668 * Write out the upper address, like the upper register of a 2-register
669 * reference, or the next memory location.
672 upput(NODE
*p
, int size
)
678 fprintf(stdout
, "%%%s", &rnames
[p
->n_rval
][3]);
688 fprintf(stdout
, "$" CONFMT
, p
->n_lval
>> 32);
691 comperr("upput bad op %d size %d", p
->n_op
, size
);
696 adrput(FILE *io
, NODE
*p
)
699 /* output an address, with offsets, from p */
707 if (p
->n_name
[0] != '\0')
708 fputs(p
->n_name
, io
);
710 fprintf(io
, "+" CONFMT
, p
->n_lval
);
716 fprintf(io
, "%d", (int)p
->n_lval
);
717 fprintf(io
, "(%s)", rnames
[p
->n_rval
]);
720 /* addressable value of the constant */
730 fprintf(io
, "%%%c%c%c", rnames
[p
->n_rval
][0],
731 rnames
[p
->n_rval
][1], rnames
[p
->n_rval
][2]);
735 fprintf(io
, "%%%s", &rnames
[p
->n_rval
][2]);
738 fprintf(io
, "%s", rnames
[p
->n_rval
]);
743 comperr("illegal address, op %d, node %p", p
->n_op
, p
);
757 "jbe", /* jumple (jlequ) */
758 "jb", /* jumpl (jlssu) */
759 "jae", /* jumpge (jgequ) */
760 "ja", /* jumpg (jgtru) */
764 /* printf conditional and unconditional branches */
766 cbgen(int o
, int lab
)
768 if (o
< EQ
|| o
> UGT
)
769 comperr("bad conditional branch: %s", opst
[o
]);
770 printf(" %s " LABFMT
"\n", ccbranches
[o
-EQ
], lab
);
774 * Prepare for struct return by allocate bounce space on stack.
783 if (p
->n_stsize
+p2autooff
> p2maxautooff
)
784 stkpos
= p2maxautooff
= p
->n_stsize
+p2autooff
;
791 myreader(struct interpass
*ipole
)
793 struct interpass
*ip
;
796 DLIST_FOREACH(ip
, ipole
, qelem
) {
797 if (ip
->type
!= IP_NODE
)
799 walkf(ip
->ip_node
, fixcalls
);
806 * Remove some PCONVs after OREGs are created.
813 if (p
->n_op
== PLUS
) {
814 if (p
->n_type
== (PTR
|SHORT
) || p
->n_type
== (PTR
|USHORT
)) {
815 if (p
->n_right
->n_op
!= ICON
)
817 if (p
->n_left
->n_op
!= PCONV
)
819 if (p
->n_left
->n_left
->n_op
!= OREG
)
821 q
= p
->n_left
->n_left
;
825 * This will be converted to another OREG later.
838 myoptim(struct interpass
*ip
)
843 rmove(int s
, int d
, TWORD t
)
848 if (memcmp(rnames
[s
], rnames
[d
], 3) != 0)
849 printf(" movl %%%c%c%c,%%%c%c%c\n",
850 rnames
[s
][0],rnames
[s
][1],rnames
[s
][2],
851 rnames
[d
][0],rnames
[d
][1],rnames
[d
][2]);
852 if (memcmp(&rnames
[s
][3], &rnames
[d
][3], 3) != 0)
853 printf(" movl %%%c%c%c,%%%c%c%c\n",
854 rnames
[s
][3],rnames
[s
][4],rnames
[s
][5],
855 rnames
[d
][3],rnames
[d
][4],rnames
[d
][5]);
859 printf(" movb %s,%s\n", rnames
[s
], rnames
[d
]);
865 /* a=b()*c(); will generate this */
866 comperr("bad float rmove: %d %d", s
, d
);
870 printf(" movl %s,%s\n", rnames
[s
], rnames
[d
]);
875 * For class c, find worst-case displacement of the number of
876 * registers in the array r[] indexed by class.
879 COLORMAP(int c
, int *r
)
885 num
= r
[CLASSB
] > 4 ? 4 : r
[CLASSB
];
896 num
+= r
[CLASSB
] > 4 ? 4 : r
[CLASSB
];
900 return r
[CLASSD
] < DREGCNT
;
902 return 0; /* XXX gcc */
906 "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
907 "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh",
908 "eaxedx", "eaxecx", "eaxebx", "eaxesi", "eaxedi", "edxecx",
909 "edxebx", "edxesi", "edxedi", "ecxebx", "ecxesi", "ecxedi",
910 "ebxesi", "ebxedi", "esiedi",
911 "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7",
915 * Return a class suitable for a specific type.
920 if (t
== CHAR
|| t
== UCHAR
)
922 if (t
== LONGLONG
|| t
== ULONGLONG
)
924 if (t
== FLOAT
|| t
== DOUBLE
|| t
== LDOUBLE
)
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 op
->n_qual
= size
; /* XXX */
951 special(NODE
*p
, int shape
)
957 if (o
== STCALL
|| o
== USTCALL
)
961 if (o
!= ICON
|| p
->n_name
[0] || p
->n_lval
< 0)