1 /* $Id: local2.c,v 1.154.2.2 2011/02/26 07:17:34 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 #if defined(PECOFFABI) || defined(MACHOABI)
45 printf(LABFMT
":\n", label
);
52 * Print out the prolog assembler.
53 * addto and regoff are already calculated.
56 prtprolog(struct interpass_prolog
*ipp
, int addto
)
60 printf(" pushl %%ebp\n");
61 printf(" movl %%esp,%%ebp\n");
63 printf(" subl $8,%%esp\n"); /* 16-byte stack alignment */
66 printf(" subl $%d,%%esp\n", addto
);
67 for (i
= 0; i
< MAXREGS
; i
++)
68 if (TESTBIT(ipp
->ipp_regs
, i
))
69 fprintf(stdout
, " movl %s,-%d(%s)\n",
70 rnames
[i
], regoff
[i
], rnames
[FPREG
]);
74 * calculate stack size and offsets
77 offcalc(struct interpass_prolog
*ipp
)
82 if (addto
>= AUTOINIT
/SZCHAR
)
83 addto
-= AUTOINIT
/SZCHAR
;
84 for (i
= 0; i
< MAXREGS
; i
++)
85 if (TESTBIT(ipp
->ipp_regs
, i
)) {
86 addto
+= SZINT
/SZCHAR
;
93 prologue(struct interpass_prolog
*ipp
)
97 ftype
= ipp
->ipp_type
;
101 printf(" .globl %s\n", ipp
->ipp_name
);
102 printf(" .align 4\n");
103 printf("%s:\n", ipp
->ipp_name
);
106 * We here know what register to save and how much to
109 addto
= offcalc(ipp
);
110 #if defined(MACHOABI)
111 addto
= (addto
+ 15) & ~15; /* stack alignment */
113 prtprolog(ipp
, addto
);
117 eoftn(struct interpass_prolog
*ipp
)
121 if (ipp
->ipp_ip
.ip_lbl
== 0)
122 return; /* no code needs to be generated */
124 /* return from function code */
125 for (i
= 0; i
< MAXREGS
; i
++)
126 if (TESTBIT(ipp
->ipp_regs
, i
))
127 fprintf(stdout
, " movl -%d(%s),%s\n",
128 regoff
[i
], rnames
[FPREG
], rnames
[i
]);
130 /* struct return needs special treatment */
131 if (ftype
== STRTY
|| ftype
== UNIONTY
) {
132 printf(" movl 8(%%ebp),%%eax\n");
134 printf(" ret $%d\n", 4 + ipp
->ipp_argstacksize
);
137 if (ipp
->ipp_argstacksize
)
138 printf(" ret $%d\n", ipp
->ipp_argstacksize
);
144 printf("\t.size " EXPREFIX
"%s,.-" EXPREFIX
"%s\n", ipp
->ipp_name
,
155 hopcode(int f
, int o
)
176 comperr("hopcode2: %d", o
);
177 str
= 0; /* XXX gcc */
179 printf("%s%c", str
, f
);
183 * Return type size in bytes. Used by R2REGS, arg 2 to offset().
195 return(SZSHORT
/SZCHAR
);
198 return(SZDOUBLE
/SZCHAR
);
204 return(SZINT
/SZCHAR
);
208 return SZLONGLONG
/SZCHAR
;
211 if (!ISPTR(p
->n_type
))
212 comperr("tlen type %d not pointer");
213 return SZPOINT(p
->n_type
)/SZCHAR
;
218 * Emit code to compare two longlong numbers.
258 cb1
= cb2
= 0; /* XXX gcc */
262 expand(p
, 0, " cmpl UR,UL\n");
263 if (cb1
) cbgen(cb1
, s
);
264 if (cb2
) cbgen(cb2
, e
);
265 expand(p
, 0, " cmpl AR,AL\n");
271 fldexpand(NODE
*p
, int cookie
, char **cp
)
275 if (p
->n_op
== ASSIGN
)
279 printf("%d", UPKFSZ(p
->n_rval
));
282 printf("%d", UPKFOFF(p
->n_rval
));
286 val
= (CONSZ
)1 << UPKFSZ(p
->n_rval
);
288 val
<<= UPKFOFF(p
->n_rval
);
289 printf("0x%llx", (**cp
== 'M' ? val
: ~val
) & 0xffffffff);
292 comperr("fldexpand");
302 if (ISUNSIGNED(p
->n_right
->n_type
))
304 switch (p
->n_right
->n_type
) {
322 sz
-= UPKFSZ(p
->n_left
->n_rval
);
323 printf("\tshl%c $%d,", ch
, sz
);
324 adrput(stdout
, getlr(p
, 'D'));
325 printf("\n\tsar%c $%d,", ch
, sz
);
326 adrput(stdout
, getlr(p
, 'D'));
330 /* long long bitfield assign */
341 o
= UPKFOFF(q
->n_rval
);
342 s
= UPKFSZ(q
->n_rval
);
343 m
= (CONSZ
)1 << (s
-1);
351 mh
= (m
>> 32) & 0xffffffff;
352 nh
= (n
>> 32) & 0xffffffff;
354 #define S(...) snprintf(buf, sizeof buf, __VA_ARGS__); expand(p, 0, buf)
356 if (o
< 32) { /* lower 32 buts */
357 S(" andl $0x%x,AL\n", nl
);
359 S(" sall $%d,A1\n", o
);
360 S(" andl $0x%x,A1\n", ml
);
363 if ((o
+s
) >= 32) { /* upper 32 bits */
364 S(" andl $0x%x,UL\n", nh
);
366 S(" sall $%d,A1\n", o
);
368 S(" shrl $%d,U1\n", 32-o
);
370 S(" andl $0x%x,A1\n", mh
);
374 // fwalk(p, e2print, 0);
380 * Push a structure on stack as argument.
381 * the scratch registers are already free here
388 #if defined(MACHOABI)
389 fprintf(fp
, " subl $%d,%%esp\n", p
->n_stsize
);
390 fprintf(fp
, " subl $4,%%esp\n");
391 fprintf(fp
, " pushl $%d\n", p
->n_stsize
);
392 expand(p
, 0, " pushl AL\n");
393 expand(p
, 0, " leal 12(%esp),A1\n");
394 expand(p
, 0, " pushl A1\n");
396 fprintf(fp
, " call L%s$stub\n", EXPREFIX
"memcpy");
397 addstub(&stublist
, EXPREFIX
"memcpy");
399 fprintf(fp
, " call %s\n", EXPREFIX
"memcpy");
401 fprintf(fp
, " addl $16,%%esp\n");
403 fprintf(fp
, " subl $%d,%%esp\n", (p
->n_stsize
+3) & ~3);
404 fprintf(fp
, " pushl $%d\n", p
->n_stsize
);
405 expand(p
, 0, " pushl AL\n");
406 expand(p
, 0, " leal 8(%esp),A1\n");
407 expand(p
, 0, " pushl A1\n");
408 fprintf(fp
, " call %s%s\n", EXPREFIX
"memcpy", kflag
? "@PLT" : "");
409 fprintf(fp
, " addl $12,%%esp\n");
414 * Compare two floating point numbers.
419 static char *fpcb
[] = { "jz", "jnz", "jbe", "jc", "jnc", "ja" };
421 if ((p
->n_su
& DORIGHT
) == 0)
422 expand(p
, 0, " fxch\n");
423 expand(p
, 0, " fucomip %st(1),%st\n"); /* emit compare insn */
424 expand(p
, 0, " fstp %st(0)\n"); /* pop fromstack */
426 if (p
->n_op
== NE
|| p
->n_op
== GT
|| p
->n_op
== GE
)
427 expand(p
, 0, " jp LC\n");
428 else if (p
->n_op
== EQ
)
430 printf(" %s ", fpcb
[p
->n_op
- EQ
]);
431 expand(p
, 0, "LC\n");
437 * Convert an unsigned long long to floating point number.
447 expand(p
, 0, " .data\n");
448 printf(LABFMT
": .long 0,0x80000000,0x403f\n", loadlab
);
449 expand(p
, 0, " .text\n");
452 expand(p
, 0, " pushl UL\n pushl AL\n");
453 expand(p
, 0, " fildq (%esp)\n");
454 expand(p
, 0, " addl $8,%esp\n");
455 expand(p
, 0, " cmpl $0,UL\n");
456 printf(" jge " LABFMT
"\n", jmplab
);
457 printf(" fldt " LABFMT
"\n", loadlab
);
458 printf(" faddp %%st,%%st(1)\n");
459 printf(LABFMT
":\n", jmplab
);
467 if (t
< LONGLONG
|| t
== FLOAT
|| t
> BTMASK
)
469 if (t
== LONGLONG
|| t
== ULONGLONG
|| t
== DOUBLE
)
473 if (t
== STRTY
|| t
== UNIONTY
)
474 return (p
->n_stsize
+3) & ~3;
485 if (t
>= p
->n_left
->n_type
)
486 return; /* cast to more precision */
492 printf(" sub $%d,%%esp\n", sz
);
493 printf(" fstp%c (%%esp)\n", c
);
494 printf(" fld%c (%%esp)\n", c
);
495 printf(" add $%d,%%esp\n", sz
);
504 d
[0] = "l", d
[1] = "%eax", d
[2] = "%edx";
506 d
[0] = "r", d
[1] = "%edx", d
[2] = "%eax";
508 printf("\tsh%sdl %s,%s\n",d
[0], d
[1], d
[2]);
509 printf("\ts%s%sl %%cl,%s\n", p
->n_op
== RS
&&
510 p
->n_left
->n_type
== ULONGLONG
? "h" : "a", d
[0], d
[1]);
511 printf("\ttestb $32,%%cl\n");
513 printf("\tmovl %s,%s\n", d
[1], d
[2]);
514 if (p
->n_op
== RS
&& p
->n_left
->n_type
== LONGLONG
)
515 printf("\tsarl $31,%%edx\n");
517 printf("\txorl %s,%s\n",d
[1],d
[1]);
522 zzzcode(NODE
*p
, int c
)
529 case 'A': /* swap st0 and st1 if right is evaluated second */
530 if ((p
->n_su
& DORIGHT
) == 0) {
538 case 'B': { /* packed bitfield ops */
542 sz
= UPKFSZ(l
->n_rval
);
543 off
= UPKFOFF(l
->n_rval
);
544 if (sz
+ off
<= SZINT
)
546 /* lower already printed */
547 expand(p
, INAREG
, " movl AR,A1\n");
548 expand(p
, INAREG
, " andl $M,UL\n");
549 printf(" sarl $%d,", SZINT
-off
);
550 expand(p
, INAREG
, "A1\n");
551 expand(p
, INAREG
, " andl $N,A1\n");
552 expand(p
, INAREG
, " orl A1,UL\n");
556 case 'C': /* remove from stack after subroutine call */
558 if (p
->n_left
->n_flags
& FSTDCALL
)
562 if (p
->n_op
== STCALL
|| p
->n_op
== USTCALL
)
564 if (p
->n_flags
& FFPPOP
)
565 printf(" fstp %%st(0)\n");
566 if (p
->n_op
== UCALL
)
567 return; /* XXX remove ZC from UCALL */
569 printf(" addl $%d, %s\n", pr
, rnames
[ESP
]);
572 case 'D': /* Long long comparision */
576 case 'E': /* Perform bitfield sign-extension */
580 case 'F': /* Structure argument */
581 if (p
->n_stalign
!= 0) /* already on stack */
585 case 'G': /* Floating point compare */
589 case 'H': /* assign of longlong between regs */
590 rmove(DECRA(p
->n_right
->n_reg
, 0),
591 DECRA(p
->n_left
->n_reg
, 0), LONGLONG
);
594 case 'I': /* float casts */
598 case 'J': /* convert unsigned long long to floating point */
602 case 'K': /* Load longlong reg into another reg */
603 rmove(regno(p
), DECRA(p
->n_reg
, 0), LONGLONG
);
606 case 'L': /* long long bitfield assign */
610 case 'M': /* Output sconv move, if needed */
612 /* XXX fixneed: regnum */
613 pr
= DECRA(p
->n_reg
, 0);
614 lr
= DECRA(l
->n_reg
, 0);
615 if ((pr
== AL
&& lr
== EAX
) || (pr
== BL
&& lr
== EBX
) ||
616 (pr
== CL
&& lr
== ECX
) || (pr
== DL
&& lr
== EDX
))
619 printf(" movb %%%cl,%s\n",
620 rnames
[lr
][2], rnames
[pr
]);
621 l
->n_rval
= l
->n_reg
= p
->n_reg
; /* XXX - not pretty */
624 case 'N': /* output extended reg name */
625 printf("%s", rnames
[getlr(p
, '1')->n_rval
]);
628 case 'O': /* print out emulated ops */
630 if (p
->n_op
== RS
|| p
->n_op
== LS
) {
633 } else if (p
->n_op
== MUL
) {
634 printf("\timull %%ecx, %%edx\n");
635 printf("\timull %%eax, %%esi\n");
636 printf("\taddl %%edx, %%esi\n");
637 printf("\tmull %%ecx\n");
638 printf("\taddl %%esi, %%edx\n");
641 expand(p
, INCREG
, "\tpushl UR\n\tpushl AR\n");
642 expand(p
, INCREG
, "\tpushl UL\n\tpushl AL\n");
643 if (p
->n_op
== DIV
&& p
->n_type
== ULONGLONG
) ch
= "udiv";
644 else if (p
->n_op
== DIV
) ch
= "div";
645 else if (p
->n_op
== MOD
&& p
->n_type
== ULONGLONG
) ch
= "umod";
646 else if (p
->n_op
== MOD
) ch
= "mod";
647 else ch
= 0, comperr("ZO");
649 printf("\tcall " EXPREFIX
"__%sdi3%s\n\taddl $%d,%s\n",
650 ch
, (kflag
? "@PLT" : ""), pr
, rnames
[ESP
]);
652 printf("\tcall " EXPREFIX
"__%sdi3\n\taddl $%d,%s\n",
653 ch
, pr
, rnames
[ESP
]);
657 case 'P': /* push hidden argument on stack */
658 printf("\tleal -%d(%%ebp),", stkpos
);
659 adrput(stdout
, getlr(p
, '1'));
660 printf("\n\tpushl ");
661 adrput(stdout
, getlr(p
, '1'));
665 case 'Q': /* emit struct assign */
667 * With <= 16 bytes, put out mov's, otherwise use movsb/w/l.
668 * esi/edi/ecx are available.
669 * XXX should not need esi/edi if not rep movsX.
670 * XXX can save one insn if src ptr in reg.
672 switch (p
->n_stsize
) {
674 expand(p
, INAREG
, " movb (%esi),%cl\n");
675 expand(p
, INAREG
, " movb %cl,AL\n");
678 expand(p
, INAREG
, " movw (%esi),%cx\n");
679 expand(p
, INAREG
, " movw %cx,AL\n");
682 expand(p
, INAREG
, " movl (%esi),%ecx\n");
683 expand(p
, INAREG
, " movl %ecx,AL\n");
686 expand(p
, INAREG
, " leal AL,%edi\n");
687 if (p
->n_stsize
<= 16 && (p
->n_stsize
& 3) == 0) {
688 printf(" movl (%%esi),%%ecx\n");
689 printf(" movl %%ecx,(%%edi)\n");
690 printf(" movl 4(%%esi),%%ecx\n");
691 printf(" movl %%ecx,4(%%edi)\n");
692 if (p
->n_stsize
> 8) {
693 printf(" movl 8(%%esi),%%ecx\n");
694 printf(" movl %%ecx,8(%%edi)\n");
696 if (p
->n_stsize
== 16) {
697 printf("\tmovl 12(%%esi),%%ecx\n");
698 printf("\tmovl %%ecx,12(%%edi)\n");
701 if (p
->n_stsize
> 4) {
702 printf("\tmovl $%d,%%ecx\n",
704 printf(" rep movsl\n");
715 case 'S': /* emit eventual move after cast from longlong */
716 pr
= DECRA(p
->n_reg
, 0);
717 lr
= p
->n_left
->n_rval
;
721 if (rnames
[pr
][2] == 'l' && rnames
[lr
][2] == 'x' &&
722 rnames
[pr
][1] == rnames
[lr
][1])
724 if (rnames
[lr
][2] == 'x') {
725 printf("\tmovb %%%cl,%s\n",
726 rnames
[lr
][1], rnames
[pr
]);
729 /* Must go via stack */
730 s
= BITOOR(freetemp(1));
731 printf("\tmovl %%e%ci,%d(%%ebp)\n", rnames
[lr
][1], s
);
732 printf("\tmovb %d(%%ebp),%s\n", s
, rnames
[pr
]);
733 // comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]);
738 if (rnames
[lr
][1] == rnames
[pr
][2] &&
739 rnames
[lr
][2] == rnames
[pr
][3])
741 printf("\tmovw %%%c%c,%%%s\n",
742 rnames
[lr
][1], rnames
[lr
][2], rnames
[pr
]+2);
746 if (rnames
[lr
][1] == rnames
[pr
][2] &&
747 rnames
[lr
][2] == rnames
[pr
][3])
749 printf("\tmovl %%e%c%c,%s\n",
750 rnames
[lr
][1], rnames
[lr
][2], rnames
[pr
]);
754 if (rnames
[lr
][1] == rnames
[pr
][2] &&
755 rnames
[lr
][2] == rnames
[pr
][3])
757 comperr("SCONV2 %s->%s", rnames
[lr
], rnames
[pr
]);
763 comperr("zzzcode %c", c
);
780 if (o
==NAME
|| o
==REG
|| o
==ICON
|| o
==OREG
||
781 (o
==UMUL
&& shumul(p
->n_left
, SOREG
)))
787 * Does the bitfield shape match?
794 if (o
== OREG
|| o
== REG
|| o
== NAME
)
795 return SRDIR
; /* Direct match */
796 if (o
== UMUL
&& shumul(p
->n_left
, SOREG
))
797 return SROREG
; /* Convert into oreg */
798 return SRREG
; /* put it into a register */
801 /* INTEMP shapes must not contain any temporary registers */
802 /* XXX should this go away now? */
810 if (p
->n_op
== STARG
)
815 return (!istreg(p
->n_rval
));
820 if (istreg(R2UPK1(r
)))
828 return (p
->n_op
!= UMUL
&& shtemp(p
));
831 if (optype(p
->n_op
) != LTYPE
)
840 printf("$" CONFMT
, val
);
844 conput(FILE *fp
, NODE
*p
)
846 int val
= (int)p
->n_lval
;
850 if (p
->n_name
[0] != '\0') {
851 fprintf(fp
, "%s", p
->n_name
);
853 fprintf(fp
, "+%d", val
);
855 fprintf(fp
, "%d", val
);
859 comperr("illegal conput, p %p", p
);
871 * Write out the upper address, like the upper register of a 2-register
872 * reference, or the next memory location.
875 upput(NODE
*p
, int size
)
884 fprintf(stdout
, "%%%s", &rnames
[p
->n_rval
][3]);
894 fprintf(stdout
, "$" CONFMT
, p
->n_lval
>> 32);
897 comperr("upput bad op %d size %d", p
->n_op
, size
);
902 adrput(FILE *io
, NODE
*p
)
905 /* output an address, with offsets, from p */
913 if (p
->n_name
[0] != '\0') {
914 fputs(p
->n_name
, io
);
916 fprintf(io
, "+" CONFMT
, p
->n_lval
);
918 fprintf(io
, CONFMT
, p
->n_lval
);
924 printf("%s%s", p
->n_name
, p
->n_lval
? "+" : "");
926 fprintf(io
, "%d", (int)p
->n_lval
);
928 fprintf(io
, "(%s,%s,4)", rnames
[R2UPK1(r
)],
931 fprintf(io
, "(%s)", rnames
[p
->n_rval
]);
935 /* Sanitycheck for PIC, to catch adressable constants */
936 if (kflag
&& p
->n_name
[0] && 0) {
940 printf("\nfailing...\n");
941 fwalk(p
, e2print
, 0);
942 comperr("pass2 conput");
946 /* addressable value of the constant */
955 fprintf(io
, "%%%c%c%c", rnames
[p
->n_rval
][0],
956 rnames
[p
->n_rval
][1], rnames
[p
->n_rval
][2]);
960 fprintf(io
, "%%%s", &rnames
[p
->n_rval
][2]);
963 fprintf(io
, "%s", rnames
[p
->n_rval
]);
968 comperr("illegal address, op %d, node %p", p
->n_op
, p
);
982 "jbe", /* jumple (jlequ) */
983 "jb", /* jumpl (jlssu) */
984 "jae", /* jumpge (jgequ) */
985 "ja", /* jumpg (jgtru) */
989 /* printf conditional and unconditional branches */
991 cbgen(int o
, int lab
)
993 if (o
< EQ
|| o
> UGT
)
994 comperr("bad conditional branch: %s", opst
[o
]);
995 printf(" %s " LABFMT
"\n", ccbranches
[o
-EQ
], lab
);
999 fixcalls(NODE
*p
, void *arg
)
1001 /* Prepare for struct return by allocating bounce space on stack */
1005 if (p
->n_stsize
+p2autooff
> stkpos
)
1006 stkpos
= p
->n_stsize
+p2autooff
;
1010 if (p
->n_type
!= LONGLONG
&& p
->n_type
!= ULONGLONG
)
1012 if (p
->n_right
->n_op
== ICON
) /* constants must be char */
1013 p
->n_right
->n_type
= CHAR
;
1019 * Must store floats in memory if there are two function calls involved.
1022 storefloat(struct interpass
*ip
, NODE
*p
)
1026 switch (optype(p
->n_op
)) {
1028 l
= storefloat(ip
, p
->n_left
);
1029 r
= storefloat(ip
, p
->n_right
);
1031 return 0; /* arguments, don't care */
1032 if (callop(p
->n_op
))
1033 return 1; /* found one */
1034 #define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
1035 (p)->n_type == LDOUBLE)
1036 if (ISF(p
->n_left
) && ISF(p
->n_right
) && l
&& r
) {
1037 /* must store one. store left */
1038 struct interpass
*nip
;
1039 TWORD t
= p
->n_left
->n_type
;
1043 off
= BITOOR(freetemp(szty(t
)));
1044 ll
= mklnode(OREG
, off
, FPREG
, t
);
1045 nip
= ipnode(mkbinode(ASSIGN
, ll
, p
->n_left
, t
));
1046 p
->n_left
= mklnode(OREG
, off
, FPREG
, t
);
1047 DLIST_INSERT_BEFORE(ip
, nip
, qelem
);
1052 l
= storefloat(ip
, p
->n_left
);
1053 if (callop(p
->n_op
))
1062 outfargs(struct interpass
*ip
, NODE
**ary
, int num
, int *cwp
, int c
)
1064 struct interpass
*ip2
;
1068 for (i
= 0; i
< num
; i
++)
1069 if (XASMVAL(cwp
[i
]) == c
&& (cwp
[i
] & (XASMASG
|XASMINOUT
)))
1074 r
= mklnode(REG
, 0, c
== 'u' ? 040 : 037, q
->n_type
);
1075 ary
[i
]->n_left
= tcopy(r
);
1076 ip2
= ipnode(mkbinode(ASSIGN
, q
, r
, q
->n_type
));
1077 DLIST_INSERT_AFTER(ip
, ip2
, qelem
);
1081 infargs(struct interpass
*ip
, NODE
**ary
, int num
, int *cwp
, int c
)
1083 struct interpass
*ip2
;
1087 for (i
= 0; i
< num
; i
++)
1088 if (XASMVAL(cwp
[i
]) == c
&& (cwp
[i
] & XASMASG
) == 0)
1093 q
= (cwp
[i
] & XASMINOUT
) ? tcopy(q
) : q
;
1094 r
= mklnode(REG
, 0, c
== 'u' ? 040 : 037, q
->n_type
);
1095 if ((cwp
[i
] & XASMINOUT
) == 0)
1096 ary
[i
]->n_left
= tcopy(r
);
1097 ip2
= ipnode(mkbinode(ASSIGN
, r
, q
, q
->n_type
));
1098 DLIST_INSERT_BEFORE(ip
, ip2
, qelem
);
1102 * Extract float args to XASM and ensure that they are put on the stack
1104 * This should be done sow other way.
1107 fixxfloat(struct interpass
*ip
, NODE
*p
)
1114 if (w
->n_op
== ICON
&& w
->n_type
== STRTY
)
1116 /* index all xasm args first */
1117 for (; w
->n_op
== CM
; w
= w
->n_left
)
1119 ary
= tmpcalloc(nn
* sizeof(NODE
*));
1120 cwp
= tmpcalloc(nn
* sizeof(int));
1121 for (i
= 0, w
= p
->n_left
; w
->n_op
== CM
; w
= w
->n_left
) {
1122 ary
[i
] = w
->n_right
;
1123 cwp
[i
] = xasmcode(ary
[i
]->n_name
);
1127 cwp
[i
] = xasmcode(ary
[i
]->n_name
);
1128 for (i
= 0; i
< nn
; i
++)
1129 if (XASMVAL(cwp
[i
]) == 't' || XASMVAL(cwp
[i
]) == 'u')
1134 for (i
= 0; i
< nn
; i
++) {
1135 c
= XASMVAL(cwp
[i
]);
1136 if (c
>= '0' && c
<= '9')
1137 cwp
[i
] = (cwp
[i
] & ~0377) | XASMVAL(cwp
[c
-'0']);
1139 infargs(ip
, ary
, nn
, cwp
, 'u');
1140 infargs(ip
, ary
, nn
, cwp
, 't');
1141 outfargs(ip
, ary
, nn
, cwp
, 't');
1142 outfargs(ip
, ary
, nn
, cwp
, 'u');
1146 myreader(struct interpass
*ipole
)
1148 struct interpass
*ip
;
1151 DLIST_FOREACH(ip
, ipole
, qelem
) {
1152 if (ip
->type
!= IP_NODE
)
1154 walkf(ip
->ip_node
, fixcalls
, 0);
1155 storefloat(ip
, ip
->ip_node
);
1156 if (ip
->ip_node
->n_op
== XASM
)
1157 fixxfloat(ip
, ip
->ip_node
);
1159 if (stkpos
> p2autooff
)
1161 if (stkpos
> p2maxautooff
)
1162 p2maxautooff
= stkpos
;
1168 * Remove some PCONVs after OREGs are created.
1171 pconv2(NODE
*p
, void *arg
)
1175 if (p
->n_op
== PLUS
) {
1176 if (p
->n_type
== (PTR
|SHORT
) || p
->n_type
== (PTR
|USHORT
)) {
1177 if (p
->n_right
->n_op
!= ICON
)
1179 if (p
->n_left
->n_op
!= PCONV
)
1181 if (p
->n_left
->n_left
->n_op
!= OREG
)
1183 q
= p
->n_left
->n_left
;
1187 * This will be converted to another OREG later.
1196 walkf(p
, pconv2
, 0);
1200 myoptim(struct interpass
*ip
)
1205 { EAX
, EAX
, EAX
, EAX
, EAX
, EDX
, EDX
, EDX
, EDX
, ECX
, ECX
, ECX
, EBX
, EBX
, ESI
};
1207 { EDX
, ECX
, EBX
, ESI
, EDI
, ECX
, EBX
, ESI
, EDI
, EBX
, ESI
, EDI
, ESI
, EDI
, EDI
};
1210 rmove(int s
, int d
, TWORD t
)
1223 /* sanity checks, remove when satisfied */
1224 if (memcmp(rnames
[s
], rnames
[sl
]+1, 3) != 0 ||
1225 memcmp(rnames
[s
]+3, rnames
[sh
]+1, 3) != 0)
1226 comperr("rmove source error");
1227 if (memcmp(rnames
[d
], rnames
[dl
]+1, 3) != 0 ||
1228 memcmp(rnames
[d
]+3, rnames
[dh
]+1, 3) != 0)
1229 comperr("rmove dest error");
1230 #define SW(x,y) { int i = x; x = y; y = i; }
1232 /* Swap if overwriting */
1237 printf(" movl %s,%s\n", rnames
[sl
], rnames
[dl
]);
1239 printf(" movl %s,%s\n", rnames
[sh
], rnames
[dh
]);
1241 if (memcmp(rnames
[s
], rnames
[d
], 3) != 0)
1242 printf(" movl %%%c%c%c,%%%c%c%c\n",
1243 rnames
[s
][0],rnames
[s
][1],rnames
[s
][2],
1244 rnames
[d
][0],rnames
[d
][1],rnames
[d
][2]);
1245 if (memcmp(&rnames
[s
][3], &rnames
[d
][3], 3) != 0)
1246 printf(" movl %%%c%c%c,%%%c%c%c\n",
1247 rnames
[s
][3],rnames
[s
][4],rnames
[s
][5],
1248 rnames
[d
][3],rnames
[d
][4],rnames
[d
][5]);
1253 printf(" movb %s,%s\n", rnames
[s
], rnames
[d
]);
1259 /* a=b()*c(); will generate this */
1260 comperr("bad float rmove: %d %d", s
, d
);
1264 printf(" movl %s,%s\n", rnames
[s
], rnames
[d
]);
1269 * For class c, find worst-case displacement of the number of
1270 * registers in the array r[] indexed by class.
1273 COLORMAP(int c
, int *r
)
1279 num
= r
[CLASSB
] > 4 ? 4 : r
[CLASSB
];
1290 num
+= r
[CLASSB
] > 4 ? 4 : r
[CLASSB
];
1294 return r
[CLASSD
] < DREGCNT
;
1296 return 0; /* XXX gcc */
1300 "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
1301 "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh",
1302 "eaxedx", "eaxecx", "eaxebx", "eaxesi", "eaxedi", "edxecx",
1303 "edxebx", "edxesi", "edxedi", "ecxebx", "ecxesi", "ecxedi",
1304 "ebxesi", "ebxedi", "esiedi",
1305 "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7",
1309 * Return a class suitable for a specific type.
1314 if (t
== CHAR
|| t
== UCHAR
)
1316 if (t
== LONGLONG
|| t
== ULONGLONG
)
1318 if (t
== FLOAT
|| t
== DOUBLE
|| t
== LDOUBLE
)
1324 * Calculate argument sizes.
1333 if (p
->n_op
!= CALL
&& p
->n_op
!= FORTCALL
&& p
->n_op
!= STCALL
)
1335 for (p
= p
->n_right
; p
->n_op
== CM
; p
= p
->n_left
)
1336 size
+= argsiz(p
->n_right
);
1344 #if defined(MACHOABI)
1345 int newsize
= (size
+ 15) & ~15; /* stack alignment */
1346 int align
= newsize
-size
;
1349 printf(" subl $%d,%%esp\n", align
);
1354 op
->n_qual
= size
; /* XXX */
1361 special(NODE
*p
, int shape
)
1367 if (o
== STCALL
|| o
== USTCALL
)
1371 if (o
!= ICON
|| p
->n_name
[0] ||
1372 p
->n_lval
< 0 || p
->n_lval
> 0x7fffffff)
1376 return tshape(p
, SZERO
);
1378 if (o
!= ICON
|| p
->n_name
[0] ||
1379 p
->n_lval
== 0 || p
->n_lval
& 0xffffffff)
1383 if (o
!= ICON
|| p
->n_name
[0] ||
1384 p
->n_lval
== 0 || (p
->n_lval
>> 32) != 0)
1392 * Target-dependent command-line options.
1400 * Do something target-dependent for xasm arguments.
1403 myxasm(struct interpass
*ip
, NODE
*p
)
1405 struct interpass
*ip2
;
1406 int Cmax
[] = { 31, 63, 127, 0xffff, 3, 255 };
1407 NODE
*in
= 0, *ut
= 0;
1413 cw
= xasmcode(p
->n_name
);
1414 if (cw
& (XASMASG
|XASMINOUT
))
1416 if ((cw
& XASMASG
) == 0)
1421 case 'D': reg
= EDI
; break;
1422 case 'S': reg
= ESI
; break;
1423 case 'a': reg
= EAX
; break;
1424 case 'b': reg
= EBX
; break;
1425 case 'c': reg
= ECX
; break;
1426 case 'd': reg
= EDX
; break;
1430 p
->n_name
= tmpstrdup(p
->n_name
);
1431 w
= strchr(p
->n_name
, XASMVAL(cw
));
1432 *w
= 'r'; /* now reg */
1435 case 'A': reg
= EAXEDX
; break;
1437 /* Set edges in MYSETXARG */
1438 if (p
->n_left
->n_op
== REG
|| p
->n_left
->n_op
== TEMP
)
1440 t
= p
->n_left
->n_type
;
1443 p
->n_left
= mklnode(TEMP
, 0, p2env
.epp
->ip_tmpnum
++, t
);
1445 ip2
= ipnode(mkbinode(ASSIGN
, ut
, tcopy(p
->n_left
), t
));
1446 DLIST_INSERT_AFTER(ip
, ip2
, qelem
);
1449 ip2
= ipnode(mkbinode(ASSIGN
, tcopy(p
->n_left
), in
, t
));
1450 DLIST_INSERT_BEFORE(ip
, ip2
, qelem
);
1461 if (p
->n_left
->n_op
!= ICON
)
1462 uerror("xasm arg not constant");
1463 v
= p
->n_left
->n_lval
;
1464 if ((c
== 'K' && v
< -128) ||
1465 (c
== 'L' && v
!= 0xff && v
!= 0xffff) ||
1466 (c
!= 'K' && v
< 0) ||
1468 uerror("xasm val out of range");
1475 /* If there are requested either memory or register, delete memory */
1476 w
= p
->n_name
= tmpstrdup(p
->n_name
);
1482 t
= p
->n_left
->n_type
;
1483 if (reg
== EAXEDX
) {
1484 p
->n_label
= CLASSC
;
1486 p
->n_label
= CLASSA
;
1487 if (t
== CHAR
|| t
== UCHAR
) {
1488 p
->n_label
= CLASSB
;
1492 if (t
== FLOAT
|| t
== DOUBLE
|| t
== LDOUBLE
) {
1493 p
->n_label
= CLASSD
;
1499 p
->n_left
= mklnode(REG
, 0, reg
, t
);
1501 ip2
= ipnode(mkbinode(ASSIGN
, ut
, tcopy(p
->n_left
), t
));
1502 DLIST_INSERT_AFTER(ip
, ip2
, qelem
);
1505 ip2
= ipnode(mkbinode(ASSIGN
, tcopy(p
->n_left
), in
, t
));
1506 DLIST_INSERT_BEFORE(ip
, ip2
, qelem
);
1512 targarg(char *w
, void *arg
)
1517 if (ary
[(int)w
[1]-'0'] == 0)
1518 p
= ary
[(int)w
[1]-'0'-1]->n_left
; /* XXX */
1520 p
= ary
[(int)w
[1]-'0']->n_left
;
1521 if (optype(p
->n_op
) != LTYPE
)
1522 comperr("bad xarg op %d", p
->n_op
);
1524 if (q
->n_op
== REG
) {
1527 } else if (*w
!= 'w') {
1528 if (q
->n_type
> UCHAR
) {
1529 regno(q
) = regno(q
)*2+8;
1542 * target-specific conversion of numeric arguments.
1545 numconv(void *ip
, void *p1
, void *q1
)
1547 NODE
*p
= p1
, *q
= q1
;
1548 int cw
= xasmcode(q
->n_name
);
1550 switch (XASMVAL(cw
)) {
1555 p
->n_name
= tmpcalloc(2);
1556 p
->n_name
[0] = (char)XASMVAL(cw
);
1564 char *name
; int num
;
1580 * Check for other names of the xasm constraints registers.
1584 * Check for other names of the xasm constraints registers.
1586 int xasmconstregs(char *s
)
1590 if (strncmp(s
, "st", 2) == 0) {
1592 if (s
[2] == '(' && s
[4] == ')')
1594 return ESIEDI
+ 1 + off
;
1597 for (i
= 0; xcr
[i
].name
; i
++)
1598 if (strcmp(xcr
[i
].name
, s
) == 0)