1 /* $Id: local2.c,v 1.40 2008/11/22 16:12:24 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.
35 void genargs(NODE
*p
);
37 static int ftlab1
, ftlab2
;
42 printf(LABFMT
":\n", label
);
49 prologue(struct interpass_prolog
*ipp
)
51 ftype
= ipp
->ipp_type
;
54 if (ipp
->ipp_regs
> 0 && ipp
->ipp_regs
!= MINRVAR
)
55 comperr("fix prologue register savings", ipp
->ipp_regs
);
58 printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n");
60 printf(" PUBLIC %s\n", ipp
->ipp_name
);
61 printf("%s:\n", ipp
->ipp_name
);
65 /* Optimizer running, save space on stack */
66 addto
= (p2maxautooff
- AUTOINIT
)/SZCHAR
;
67 printf(" enter #%d\n", addto
);
71 /* non-optimized code, jump to epilogue for code generation */
74 printf(" jmp.w " LABFMT
"\n", ftlab1
);
82 eoftn(struct interpass_prolog
*ipp
)
85 if (ipp
->ipp_regs
!= MINRVAR
)
86 comperr("fix eoftn register savings %x", ipp
->ipp_regs
);
90 addto
= (p2maxautooff
- AUTOINIT
)/SZCHAR
;
92 /* return from function code */
93 //deflab(ipp->ipp_ip.ip_lbl); //XXX - is this necessary?
95 /* If retval is a pointer and not a function pointer, put in A0 */
96 if (ISPTR(DECREF(ipp
->ipp_type
)) &&
97 !ISFTN(DECREF(DECREF(ipp
->ipp_type
))))
98 printf(" mov.w r0,a0\n");
100 /* struct return needs special treatment */
101 if (ftype
== STRTY
|| ftype
== UNIONTY
) {
102 comperr("fix struct return in eoftn");
107 // if (xsaveip == 0) {
109 printf(" enter #%d\n", addto
);
110 printf(" jmp.w " LABFMT
"\n", ftlab2
);
120 hopcode(int f
, int o
)
141 comperr("hopcode2: %d", o
);
142 str
= 0; /* XXX gcc */
144 printf("%s.%c", str
, f
);
148 rnames
[] = { /* keyed to register number tokens */
149 "r0", "r2", "r1", "r3", "a0", "a1", "fb", "sp", "r0h", "r0l",
154 * Return the size (in bytes) of some types.
175 if (!ISPTR(p
->n_type
))
176 comperr("tlen type %d not pointer");
177 return SZPOINT(p
->n_type
)/SZCHAR
;
182 * Emit code to compare two longlong numbers.
215 cb1
= cb2
= 0; /* XXX gcc */
219 expand(p
, 0, " cmp.w UR,UL\n");
220 if (cb1
) cbgen(cb1
, s
);
221 if (cb2
) cbgen(cb2
, e
);
222 expand(p
, 0, " cmp.w AR,AL\n");
229 zzzcode(NODE
*p
, int c
)
234 case 'A': /* print negative shift constant */
237 comperr("ZA bad use");
238 p
->n_lval
= -p
->n_lval
;
240 p
->n_lval
= -p
->n_lval
;
245 printf(" add.b #%d,%s\n",
246 p
->n_rval
, rnames
[STKREG
]);
249 case 'C': /* Print label address */
252 printf(LABFMT
, (int)p
->n_lval
);
254 printf("%s", p
->n_name
);
257 case 'D': /* copy function pointers */
259 printf("\tmov.w #HWRD(%s),%s\n\tmov.w #LWRD(%s),%s\n",
260 p
->n_right
->n_name
, rnames
[l
->n_rval
+1],
261 p
->n_right
->n_name
, rnames
[l
->n_rval
]);
264 case 'E': /* double-reg printout */
265 /* XXX - always r0r2 here */
266 printf("%s%s", rnames
[R0
], rnames
[R2
]);
269 case 'F': /* long comparisions */
277 case 'H': /* push 32-bit address (for functions) */
278 printf("\tpush.w #HWRD(%s)\n\tpush.w #LWRD(%s)\n",
279 p
->n_left
->n_name
, p
->n_left
->n_name
);
282 case 'I': /* push 32-bit address (for functions) */
284 printf("\tpush.w %d[%s]\n\tpush.w %d[%s]\n",
285 (int)l
->n_lval
, rnames
[l
->n_rval
],
286 (int)l
->n_lval
+2, rnames
[l
->n_rval
]);
290 comperr("bad zzzcode %c", c
);
307 if (o
==NAME
|| o
==REG
|| o
==ICON
|| o
==OREG
||
308 (o
==UMUL
&& shumul(p
->n_left
, SOREG
) == SRDIR
))
314 fldexpand(NODE
*p
, int cookie
, char **cp
)
320 * Does the bitfield shape match?
327 if (o
== OREG
|| o
== REG
|| o
== NAME
)
328 return SRDIR
; /* Direct match */
329 if (o
== UMUL
&& shumul(p
->n_left
, SOREG
))
330 return SROREG
; /* Convert into oreg */
331 return SRREG
; /* put it into a register */
334 /* INTEMP shapes must not contain any temporary registers */
335 /* XXX should this go away now? */
345 printf("$" CONFMT
, val
);
349 conput(FILE *fp
, NODE
*p
)
355 if (p
->n_name
[0] != '\0') {
356 fprintf(fp
, "%s", p
->n_name
);
358 fprintf(fp
, "+%d", val
);
360 fprintf(fp
, "%d", val
);
364 comperr("illegal conput");
376 * Write out the upper address, like the upper register of a 2-register
377 * reference, or the next memory location.
380 upput(NODE
*p
, int size
)
386 fputs(rnames
[p
->n_rval
+ 1], stdout
);
396 fprintf(stdout
, "#" CONFMT
, p
->n_lval
>> 16);
399 comperr("upput bad op %d size %d", p
->n_op
, size
);
404 adrput(FILE *io
, NODE
*p
)
406 /* output an address, with offsets, from p */
414 if (p
->n_name
[0] != '\0')
415 fputs(p
->n_name
, io
);
417 fprintf(io
, "+" CONFMT
, p
->n_lval
);
422 fprintf(io
, "%d", (int)p
->n_lval
);
423 fprintf(io
, "[%s]", rnames
[p
->n_rval
]);
426 /* addressable value of the constant */
432 /*if (DEUNSIGN(p->n_type) == CHAR) {
433 fprintf(io, "R%c%c", p->n_rval < 2 ? '0' : '1',
434 (p->n_rval & 1) ? 'H' : 'L');
436 fprintf(io
, "%s", rnames
[p
->n_rval
]);
440 comperr("illegal address, op %d, node %p", p
->n_op
, p
);
454 "jleu", /* jumple (jlequ) */
455 "jltu", /* jumpl (jlssu) */
456 "jgeu", /* jumpge (jgequ) */
457 "jgtu", /* jumpg (jgtru) */
461 /* printf conditional and unconditional branches */
463 cbgen(int o
, int lab
)
465 if (o
< EQ
|| o
> UGT
)
466 comperr("bad conditional branch: %s", opst
[o
]);
467 printf(" %s " LABFMT
"\n", ccbranches
[o
-EQ
], lab
);
476 myoptim(struct interpass
*ip
)
485 if (p
->n_op
== MINUS
&& p
->n_type
== DOUBLE
&&
486 (p
->n_su
& (LMASK
|RMASK
)) == (LREG
|RREG
)) {
489 /* Must walk down correct node first for logops to work */
490 if (p
->n_op
!= CBRANCH
)
493 if ((p
->n_su
& (LMASK
|RMASK
)) != (LREG
|RREG
))
500 struct hardops hardops
[] = {
501 { PLUS
, FLOAT
, "?F_ADD_L04" },
502 { MUL
, LONG
, "?L_MUL_L03" },
503 { MUL
, ULONG
, "?L_MUL_L03" },
504 { DIV
, LONG
, "?SL_DIV_L03" },
505 { DIV
, ULONG
, "?UL_DIV_L03" },
506 { MOD
, LONG
, "?SL_MOD_L03" },
507 { MOD
, ULONG
, "?UL_MOD_L03" },
508 { RS
, LONGLONG
, "__ashrdi3" },
509 { RS
, ULONGLONG
, "__lshrdi3" },
510 { LS
, LONGLONG
, "__ashldi3" },
511 { LS
, ULONGLONG
, "__ashldi3" },
516 special(NODE
*p
, int shape
)
520 if (ISPTR(p
->n_type
) && ISFTN(DECREF(p
->n_type
))) {
521 if (p
->n_op
== NAME
|| p
->n_op
== OREG
)
534 NODE
*q
, *r
, *s
, *right
;
536 if (optype(p
->n_op
) == LTYPE
)
538 if (optype(p
->n_op
) != UTYPE
)
539 myreader(p
->n_right
);
545 if (p
->n_type
!= LONG
&& p
->n_type
!= ULONG
)
547 if (p
->n_right
->n_op
== NAME
|| p
->n_right
->n_op
== OREG
)
549 /* Must convert right into OREG */
551 q
= mklnode(OREG
, BITOOR(freetemp(szty(right
->n_type
))),
552 FPREG
, right
->n_type
);
553 s
= mkbinode(ASSIGN
, q
, right
, right
->n_type
);
557 pass2_compile(ipnode(s
));
564 rmove(int s
, int d
, TWORD t
)
569 printf(" mov.b %s,%s\n", rnames
[s
], rnames
[d
]);
572 printf(" mov.w %s,%s\n", rnames
[s
], rnames
[d
]);
577 * For class c, find worst-case displacement of the number of
578 * registers in the array r[] indexed by class.
581 COLORMAP(int c
, int *r
)
598 return 0; /* XXX gcc */
602 * Return a class suitable for a specific type.
607 if (t
== CHAR
|| t
== UCHAR
)
624 if (t
< LONGLONG
|| t
> MAXTYPES
)
626 if (t
== LONGLONG
|| t
== ULONGLONG
|| t
== DOUBLE
)
637 * Calculate argument sizes.
644 for (p
= p
->n_right
; p
->n_op
== CM
; p
= p
->n_left
)
645 sizen
+= argsiz(p
->n_right
);
650 * Target-dependent command-line options.
657 * Do something target-dependent for xasm arguments.
658 * Supposed to find target-specific constraints and rewrite them.
661 myxasm(struct interpass
*ip
, NODE
*p
)