4 * Copyright (c) 2007 Michael Shalayeff
5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 void prtprolog(struct interpass_prolog
*, int);
38 int countargs(NODE
*p
, int *);
39 void fixcalls(NODE
*p
, void *);
44 static const int rl
[] =
45 { R0
, R1
, R1
, R1
, R1
, R1
, R31
, R31
, R31
, R31
,
46 R4
, R5
, R6
, R7
, R8
, R9
, R10
, R11
, R12
, R13
, R14
, R15
, R16
, R17
, R18
,
47 T1
, T4
, T3
, T2
, ARG3
, ARG1
, RET1
};
48 static const int rh
[] =
49 { R0
, R31
, T4
, T3
, T2
, T1
, T4
, T3
, T2
, T1
,
50 R18
, R4
, R5
, R6
, R7
, R8
, R9
, R10
, R11
, R12
, R13
, R14
, R15
, R16
, R17
,
51 T4
, T3
, T2
, T1
, ARG2
, ARG0
, RET0
};
56 printf("\t.label\t" LABFMT
"\n", label
);
59 static int regoff
[MAXREGS
];
63 * Print out the prolog assembler.
64 * addto and regoff are already calculated.
67 prtprolog(struct interpass_prolog
*ipp
, int addto
)
71 /* if this functions calls nothing -- no frame is needed */
72 if (p2calls
|| p2maxautooff
> 4) {
73 printf("\tcopy\t%%r3,%%r1\n\tcopy\t%%sp,%%r3\n");
75 printf("\tstw,ma\t%%r1,%d(%%sp)\n", addto
);
76 else if (addto
< 0x802000)
77 printf("\tstw,ma\t%%r1,8192(%%sp)\n"
78 "\taddil\t%d-8192,%%sp\n"
79 "\tcopy\t%%r1,%%sp\n", addto
);
81 comperr("too much local allocation");
83 printf("\tstw\t%%rp,-20(%%r3)\n");
86 for (i
= 0; i
< MAXREGS
; i
++)
87 if (TESTBIT(ipp
->ipp_regs
, i
)) {
89 printf("\tstw\t%s,%d(%%r3)\n",
90 rnames
[i
], regoff
[i
]);
92 printf("\tstw\t%s,%d(%%r3)\n"
93 "\tstw\t%s,%d(%%r3)\n",
94 rnames
[rl
[i
- RD0
]], regoff
[i
] + 0,
95 rnames
[rh
[i
- RD0
]], regoff
[i
] + 4);
97 printf("\tfstws\t%s,%d(%%r3)\n",
98 rnames
[i
], regoff
[i
]);
100 printf("\tfstds\t%s,%d(%%r3)\n",
101 rnames
[i
], regoff
[i
]);
106 * calculate stack size and offsets
109 offcalc(struct interpass_prolog
*ipp
)
116 /* round up to 4 args */
122 for (off
= 4, i
= 0; i
< MAXREGS
; i
++)
123 if (TESTBIT(ipp
->ipp_regs
, i
)) {
125 off
+= szty(PERMTYPE(i
)) * SZINT
/SZCHAR
;
127 addto
+= off
+ p2maxautooff
;
128 return (addto
+ 63) & ~63;
132 prologue(struct interpass_prolog
*ipp
)
136 ftype
= ipp
->ipp_type
;
139 * We here know what registers to save and how much to
142 addto
= offcalc(ipp
);
143 printf("\t.proc\ncallinfo frame=%d, save_rp, save_sp\n\t.entry\n",
145 prtprolog(ipp
, addto
);
149 eoftn(struct interpass_prolog
*ipp
)
153 if (ipp
->ipp_ip
.ip_lbl
== 0)
154 return; /* no code needs to be generated */
156 /* return from function code */
157 for (i
= 0; i
< MAXREGS
; i
++)
158 if (TESTBIT(ipp
->ipp_regs
, i
)) {
160 printf("\tldw\t%d(%%r3),%s\n",
161 regoff
[i
], rnames
[i
]);
163 printf("\tldw\t%d(%%r3),%s\n"
164 "\tldw\t%d(%%r3),%s\n",
165 regoff
[i
] + 0, rnames
[rl
[i
- RD0
]],
166 regoff
[i
] + 4, rnames
[rh
[i
- RD0
]]);
168 printf("\tfldws\t%d(%%r3),%s\n",
169 regoff
[i
], rnames
[i
]);
171 printf("\tfldds\t%d(%%r3),%s\n",
172 regoff
[i
], rnames
[i
]);
175 if (p2calls
|| p2maxautooff
> 4) {
177 printf("\tldw\t-20(%%r3),%%rp\n");
178 printf("\tcopy\t%%r3,%%r1\n"
179 "\tldw\t0(%%r3),%%r3\n"
181 "\tcopy\t%%r1,%%sp\n");
183 printf("\tbv\t%%r0(%%rp)\n\tnop\n");
185 printf("\t.exit\n\t.procend\n\t.size\t%s, .-%s\n",
186 ipp
->ipp_name
, ipp
->ipp_name
);
195 hopcode(int f
, int o
)
246 comperr("hopcode2: %d", o
);
247 str
= 0; /* XXX gcc */
249 printf("%s%c", str
, f
);
253 * Return type size in bytes. Used by R2REGS, arg 2 to offset().
265 return(SZSHORT
/SZCHAR
);
268 return(SZFLOAT
/SZCHAR
);
271 return(SZDOUBLE
/SZCHAR
);
277 return(SZINT
/SZCHAR
);
281 return SZLONGLONG
/SZCHAR
;
284 if (!ISPTR(p
->n_type
))
285 comperr("tlen type %d not pointer", p
->n_type
);
286 return SZPOINT(p
->n_type
)/SZCHAR
;
296 if (t
< LONGLONG
|| t
== FLOAT
|| t
> BTMASK
)
298 if (t
== LONGLONG
|| t
== ULONGLONG
|| t
== DOUBLE
)
301 return 8; /* LDOUBLE is 16 */
302 if ((t
== STRTY
|| t
== UNIONTY
) && p
->n_right
->n_op
== STARG
)
303 return 4 + p
->n_right
->n_stsize
;
304 /* perhaps it's down there somewhere -- let me take another look! */
305 if ((t
== STRTY
|| t
== UNIONTY
) && p
->n_right
->n_op
== CALL
) {
306 q
= p
->n_right
->n_right
->n_left
->n_left
->n_right
;
307 if (q
->n_op
== STARG
)
308 return 4 + q
->n_stsize
;
310 comperr("argsiz %p", p
);
315 * Emit code to compare two longlong numbers.
348 cb1
= cb2
= 0; /* XXX gcc */
355 expand(p
, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n");
361 expand(p
, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n");
364 expand(p
, 0, "\tcomb,O\tAR,AL,LC\n\tnop\n");
369 zzzcode(NODE
*p
, int c
)
375 case 'C': /* after-call fixup */
376 n
= p
->n_qual
; /* args */
379 case 'P': /* returning struct-call setup */
380 n
= p
->n_qual
; /* args */
383 case 'D': /* Long long comparision */
387 case 'F': /* struct as an arg */
390 comperr("zzzcode %c", c
);
400 if (o
== NAME
|| o
== REG
|| o
== ICON
|| o
== OREG
||
401 (o
== UMUL
&& shumul(p
->n_left
, SOREG
)))
407 fldexpand(NODE
*p
, int cookie
, char **cp
)
413 * Does the bitfield shape match?
419 return SRDIR
; /* Direct match */
421 return SRREG
; /* put it into a register */
424 /* INTEMP shapes must not contain any temporary registers */
425 /* XXX should this go away now? */
433 if (p
->n_op
== STARG
)
438 return (!istreg(p
->n_rval
));
443 if (istreg(R2UPK1(r
)))
451 return (p
->n_op
!= UMUL
&& shtemp(p
));
454 if (optype(p
->n_op
) != LTYPE
)
463 /* fix for L% and R% */
468 conput(FILE *fp
, NODE
*p
)
470 CONSZ val
= p
->n_lval
;
474 if (p
->n_name
[0] != '\0') {
475 fprintf(fp
, "RR'%s-$global$", p
->n_name
);
477 fprintf(fp
, "+" CONFMT
, val
);
479 fprintf(fp
, CONFMT
, val
);
483 comperr("illegal conput, p %p", p
);
495 * Write out the upper address, like the upper register of a 2-register
496 * reference, or the next memory location.
499 upput(NODE
*p
, int size
)
505 printf("%s", rnames
[rh
[p
->n_rval
- RD0
]]);
516 if (p
->n_name
[0] != '\0') {
517 printf("LR'%s-$global$", p
->n_name
);
519 printf("+" CONFMT
, p
->n_lval
);
521 printf("L%%" CONFMT
, p
->n_lval
>> 32);
524 comperr("upput bad op %d size %d", p
->n_op
, size
);
529 adrput(FILE *io
, NODE
*p
)
532 /* output an address, with offsets, from p */
541 if (p
->n_name
[0] != '\0') {
542 fprintf(io
, "RR'%s-$global$", p
->n_name
);
544 fprintf(io
, "+" CONFMT
, p
->n_lval
);
546 fprintf(io
, "R%%" CONFMT
, p
->n_lval
);
551 if (p
->n_name
[0] != '\0') {
552 fprintf(io
, "RR'%s-$global$", p
->n_name
);
554 fprintf(io
, "+" CONFMT
, p
->n_lval
);
556 fprintf(io
, "%d", (int)p
->n_lval
);
558 fprintf(io
, "%s(%s)", rnames
[R2UPK1(r
)],
561 fprintf(io
, "(%s)", rnames
[p
->n_rval
]);
564 if (RD0
<= p
->n_rval
&& p
->n_rval
<= RETD0
)
565 fprintf(io
, "%s", rnames
[rl
[p
->n_rval
- RD0
]]);
567 fprintf(io
, "%s", rnames
[p
->n_rval
]);
571 comperr("illegal address, op %d, node %p", p
->n_op
, p
);
579 cbgen(int o
, int lab
)
584 countargs(NODE
*p
, int *n
)
589 countargs(p
->n_left
, n
);
590 countargs(p
->n_right
, n
);
595 if (*n
% (sz
> 4? 4 : sz
))
602 fixcalls(NODE
*p
, void *arg
)
606 /* Prepare for struct return by allocating bounce space on stack */
607 switch (o
= p
->n_op
) {
610 if (p
->n_stsize
+ p2autooff
> stkpos
)
611 stkpos
= p
->n_stsize
+ p2autooff
;
616 n
= 1 + countargs(p
->n_right
, &n
);
624 myreader(struct interpass
*ipole
)
626 struct interpass
*ip
;
629 DLIST_FOREACH(ip
, ipole
, qelem
) {
636 walkf(ip
->ip_node
, fixcalls
, 0);
640 if (stkpos
> p2autooff
)
642 if (stkpos
> p2maxautooff
)
643 p2maxautooff
= stkpos
;
649 * Remove some PCONVs after OREGs are created.
652 pconv2(NODE
*p
, void *arg
)
656 if (p
->n_op
== PLUS
) {
657 if (p
->n_type
== (PTR
|SHORT
) || p
->n_type
== (PTR
|USHORT
)) {
658 if (p
->n_right
->n_op
!= ICON
)
660 if (p
->n_left
->n_op
!= PCONV
)
662 if (p
->n_left
->n_left
->n_op
!= OREG
)
664 q
= p
->n_left
->n_left
;
668 * This will be converted to another OREG later.
681 myoptim(struct interpass
*ipole
)
686 rmove(int s
, int d
, TWORD t
)
698 #define SW(x,y) { int i = x; x = y; y = i; }
699 if (sl
== dh
|| sh
== dl
) {
700 /* Swap if moving to itself */
705 printf("\tcopy\t%s,%s\n", rnames
[sl
], rnames
[dl
]);
707 printf("\tcopy\t%s,%s\n", rnames
[sh
], rnames
[dh
]);
710 printf("\tfcpy,sgl\t%s,%s\n", rnames
[s
], rnames
[d
]);
714 printf("\tfcpy,dbl\t%s,%s\n", rnames
[s
], rnames
[d
]);
717 printf("\tcopy\t%s,%s\n", rnames
[s
], rnames
[d
]);
722 * For class c, find worst-case displacement of the number of
723 * registers in the array r[] indexed by class.
726 COLORMAP(int c
, int *r
)
737 num
+= r
[CLASSB
] * 2;
740 num
= (r
[CLASSD
] > 8? 8 : r
[CLASSD
]) * 2;
744 num
= (r
[CLASSC
] + 1) / 2;
748 return 0; /* XXX gcc */
751 char * rnames
[MAXREGS
] = {
752 "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", "%r9",
753 "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", "%r17", "%r18",
754 "%t4", "%t3", "%t2", "%t1", "%arg3", "%arg2", "%arg1", "%arg0", "%dp",
755 "%ret0", "%ret1", "%sp", "%r31",
756 "%rd0", "%rd1", "%rd2", "%rd3", "%rd4", "%rd5", "%rd6", "%rd7",
757 "%rd8", "%rd9", "%rd10", "%rd11", "%rd12", "%rd13", "%rd14", "%rd15",
758 "%rd16", "%rd17", "%rd18", "%rd19", "%rd20", "%rd21", "%rd22", "%rd23",
759 "%rd24", "%td4", "%td3", "%td2", "%td1", "%ad1", "%ad0", "%retd0",
760 "%fr0", "%fr4", "%fr5", "%fr6", "%fr7", "%fr8", "%fr9", "%fr10",
761 "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", "%fr16", "%fr17", "%fr18",
762 "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", "%fr24", "%fr25", "%fr26",
763 "%fr27", "%fr28", "%fr29", "%fr30", "%fr31",
764 "%fr0l", "%fr0r", "%fr4l", "%fr4r", "%fr5l", "%fr5r", "%fr6l", "%fr6r",
765 "%fr7l", "%fr7r", "%fr8l", "%fr8r", "%fr9l", "%fr9r",
766 "%fr10l", "%fr10r", "%fr11l", "%fr11r", "%fr12l", "%fr12r",
767 "%fr13l", "%fr13r", "%fr14l", "%fr14r", "%fr15l", "%fr15r",
768 "%fr16l", "%fr16r", "%fr17l", "%fr17r", "%fr18l", "%fr18r",
771 "%fr20l", "%fr20r", "%fr21l", "%fr21r", "%fr22l", "%fr22r",
772 "%fr23l", "%fr23r", "%fr24l", "%fr24r", "%fr25l", "%fr25r",
773 "%fr26l", "%fr26r", "%fr27l", "%fr27r", "%fr28l", "%fr28r",
774 "%fr29l", "%fr29r", "%fr30l", "%fr30r", "%fr31l", "%fr31r",
779 * Return a class suitable for a specific type.
799 * Calculate argument sizes.
808 if (p
->n_op
!= CALL
&& p
->n_op
!= FORTCALL
&& p
->n_op
!= STCALL
)
810 for (p
= p
->n_right
; p
->n_op
== CM
; p
= p
->n_left
)
811 size
+= argsiz(p
->n_right
);
813 op
->n_qual
= size
; /* XXX */
820 special(NODE
*p
, int shape
)
826 if (o
== STCALL
|| o
== USTCALL
)
830 if (o
!= ICON
|| p
->n_name
[0] ||
831 p
->n_lval
< -31 || p
->n_lval
>= 32)
835 if (o
!= ICON
|| p
->n_name
[0] ||
836 p
->n_lval
< -1024 || p
->n_lval
>= 1024)
840 if (o
!= ICON
|| p
->n_name
[0] || (p
->n_lval
& 0xffffffffLL
))
844 if (o
!= ICON
|| p
->n_name
[0] || (p
->n_lval
& ~0xffffffffLL
))
848 if (o
!= ICON
|| p
->n_name
[0] || (p
->n_lval
& ~0xfffff800LL
))
852 if (o
!= ICON
|| p
->n_name
[0] ||
853 p
->n_lval
< -8192 || p
->n_lval
>= 8192)
857 if (o
!= ICON
|| !p
->n_name
[0])
865 * Target-dependent command-line options.
872 * Do something target-dependent for xasm arguments.
873 * Supposed to find target-specific constraints and rewrite them.
876 myxasm(struct interpass
*ip
, NODE
*p
)