1 /* $Id: local2.c,v 1.11 2008/11/22 16:12:25 ragge Exp $ */
3 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * Redistributions of source code and documentation must retain the above
10 * copyright notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditionsand the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed or owned by Caldera
18 * Neither the name of Caldera International, Inc. nor the names of other
19 * contributors may be used to endorse or promote products derived from
20 * this software without specific prior written permission.
22 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
23 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
27 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
38 /* a lot of the machine dependent parts of the second pass */
40 static void prtype(NODE
*n
);
41 static void acon(NODE
*p
);
44 * Print out the prolog assembler.
45 * addto and regoff are already calculated.
48 prologue(struct interpass_prolog
*ipp
)
51 printf(" .globl %s\n", ipp
->ipp_name
);
52 printf(" .align 4\n");
53 printf("%s:\n", ipp
->ipp_name
);
54 printf(" .word 0x%x\n", ipp
->ipp_regs
[0]);
56 printf(" subl2 $%d,%%sp\n", p2maxautooff
);
60 * Called after all instructions in a function are emitted.
61 * Generates code for epilog here.
64 eoftn(struct interpass_prolog
*ipp
)
66 if (ipp
->ipp_ip
.ip_lbl
== 0)
67 return; /* no code needs to be generated */
71 struct hoptab
{ int opmask
; char * opstring
; } ioptab
[] = {
85 /* output the appropriate string from the above table */
87 register struct hoptab
*q
;
89 for( q
= ioptab
; q
->opmask
>=0; ++q
){
91 printf( "%s", q
->opstring
);
93 if( f == 'F' ) printf( "e" );
94 else if( f == 'D' ) printf( "d" );
103 printf("%c", tolower(f
));
111 cerror( "no hoptab for %s", opst
[o
] );
115 rnames
[] = { /* keyed to register number tokens */
117 "r0", "r1", "r2", "r3", "r4", "r5",
118 "r6", "r7", "r8", "r9", "r10", "r11",
119 "ap", "fp", "sp", "pc",
120 /* The concatenated regs has the name of the lowest */
121 "r0", "r1", "r2", "r3", "r4", "r5",
122 "r6", "r7", "r8", "r9", "r10"
149 mixtypes(NODE
*p
, NODE
*q
)
156 return( (tp
==FLOAT
|| tp
==DOUBLE
) !=
157 (tq
==FLOAT
|| tq
==DOUBLE
) );
191 if ( !ISPTR( n
->n_type
) ) cerror("zzzcode- bad type");
200 zzzcode( p
, c
) register NODE
*p
; {
205 case 'N': /* logical ops, turned into 0-1 */
206 /* use register given by register 1 */
207 cbgen( 0, m
=getlab2());
208 deflab( p
->n_label
);
209 printf( " clrl %s\n", rnames
[getlr( p
, '1' )->n_rval
] );
215 register NODE
*l
, *r
;
217 if (xdebug
) e2print(p
, 0, &val
, &val
);
219 if (optype(p
->n_op
) == LTYPE
|| p
->n_op
== UMUL
) {
221 l
->n_type
= (r
->n_type
==FLOAT
|| r
->n_type
==DOUBLE
? DOUBLE
: INT
);
224 if (r
->n_op
== ICON
&& r
->n_name
[0] == '\0') {
225 if (r
->n_lval
== 0) {
232 if (r
->n_lval
< 0 && r
->n_lval
>= -63) {
235 r
->n_lval
= -r
->n_lval
;
238 r
->n_type
= (r
->n_lval
< 0 ?
239 (r
->n_lval
>= -128 ? CHAR
240 : (r
->n_lval
>= -32768 ? SHORT
241 : INT
)) : r
->n_type
);
242 r
->n_type
= (r
->n_lval
>= 0 ?
243 (r
->n_lval
<= 63 ? INT
244 : ( r
->n_lval
<= 127 ? CHAR
245 : (r
->n_lval
<= 255 ? UCHAR
246 : (r
->n_lval
<= 32767 ? SHORT
247 : (r
->n_lval
<= 65535 ? USHORT
248 : INT
))))) : r
->n_type
);
250 if (l
->n_op
== REG
&& l
->n_type
!= FLOAT
&& l
->n_type
!= DOUBLE
)
254 if (tlen(l
) == tlen(r
))
260 else if (tlen(l
) > tlen(r
) && ISUNSIGNED(r
->n_type
))
283 case 'C': /* num words pushed on arg stack */
284 if (p
->n_op
== STCALL
|| p
->n_op
== USTCALL
)
286 printf("$%d", p
->n_qual
);
289 case 'D': /* INCR and DECR */
290 zzzcode(p
->n_left
, 'A');
294 case 'E': /* INCR and DECR, FOREFF */
295 if (p
->n_right
->n_lval
== 1)
297 printf("%s", (p
->n_op
== INCR
? "inc" : "dec") );
300 adrput(stdout
, p
->n_left
);
303 printf("%s", (p
->n_op
== INCR
? "add" : "sub") );
306 adrput(stdout
, p
->n_right
);
312 case 'F': /* register type of right operand */
321 if (xdebug
) printf("->%d<-", ty
);
323 if ( ty
==DOUBLE
) printf("d");
324 else if ( ty
==FLOAT
) printf("f");
329 case 'J': /* jump or ret? */
331 extern struct interpass_prolog
*epp
;
332 struct interpass
*ip
=
333 DLIST_PREV((struct interpass
*)epp
, qelem
);
334 if (ip
->type
!= IP_DEFLAB
||
335 ip
->ip_lbl
!= getlr(p
, 'L')->n_lval
)
336 expand(p
, FOREFF
, "jbr LL");
342 case 'L': /* type of left operand */
343 case 'R': /* type of right operand */
349 if (xdebug
) printf("->%d<-", n
->n_type
);
355 case 'Z': /* complement mask for bit instr */
356 printf("$%Ld", ~p
->n_right
->n_lval
);
359 case 'U': /* 32 - n, for unsigned right shifts */
360 printf("$" CONFMT
, 32 - p
->n_right
->n_lval
);
363 case 'T': /* rounded structure length for arguments */
373 case 'S': /* structure assignment */
375 register NODE
*l
, *r
;
378 l
= r
= NULL
; /* XXX gcc */
379 if( p
->n_op
== STASG
){
384 else if( p
->n_op
== STARG
){ /* store an arg into a temporary */
388 else cerror( "STASG bad" );
390 if( r
->n_op
== ICON
) r
->n_op
= NAME
;
391 else if( r
->n_op
== REG
) r
->n_op
= OREG
;
392 else if( r
->n_op
!= OREG
) cerror( "STASG-r" );
396 if( size
<= 0 || size
> 65535 )
397 cerror("structure size <0=0 or >65535");
413 printf(" movc3 $%d,", size
);
421 if( r
->n_op
== NAME
) r
->n_op
= ICON
;
422 else if( r
->n_op
== OREG
) r
->n_op
= REG
;
428 comperr("illegal zzzcode '%c'", c
);
433 rmove( int rt
,int rs
, TWORD t
){
434 printf( " %s %s,%s\n",
435 (t
==FLOAT
? "movf" : (t
==DOUBLE
? "movd" : "movl")),
436 rnames
[rs
], rnames
[rt
] );
440 setregs(){ /* set up temporary registers */
441 fregs
= 6; /* tbl- 6 free regs on VAX (0-5) */
445 szty(t
){ /* size, in registers, needed to hold thing of type t */
446 return( (t
==DOUBLE
||t
==FLOAT
) ? 2 : 1 );
451 rewfld( p
) NODE
*p
; {
456 callreg(p
) NODE
*p
; {
460 base( p
) register NODE
*p
; {
461 register int o
= p
->op
;
463 if( (o
==ICON
&& p
->name
[0] != '\0')) return( 100 ); /* ie no base reg */
464 if( o
==REG
) return( p
->rval
);
465 if( (o
==PLUS
|| o
==MINUS
) && p
->left
->op
== REG
&& p
->right
->op
==ICON
)
466 return( p
->left
->rval
);
467 if( o
==OREG
&& !R2TEST(p
->rval
) && (p
->type
==INT
|| p
->type
==UNSIGNED
|| ISPTR(p
->type
)) )
468 return( p
->rval
+ 0200*1 );
469 if( o
==INCR
&& p
->left
->op
==REG
) return( p
->left
->rval
+ 0200*2 );
470 if( o
==ASG MINUS
&& p
->left
->op
==REG
) return( p
->left
->rval
+ 0200*4 );
471 if( o
==UNARY MUL
&& p
->left
->op
==INCR
&& p
->left
->left
->op
==REG
472 && (p
->type
==INT
|| p
->type
==UNSIGNED
|| ISPTR(p
->type
)) )
473 return( p
->left
->left
->rval
+ 0200*(1+2) );
477 offset( p
, tyl
) register NODE
*p
; int tyl
; {
479 if( tyl
==1 && p
->op
==REG
&& (p
->type
==INT
|| p
->type
==UNSIGNED
) ) return( p
->rval
);
480 if( (p
->op
==LS
&& p
->left
->op
==REG
&& (p
->left
->type
==INT
|| p
->left
->type
==UNSIGNED
) &&
481 (p
->right
->op
==ICON
&& p
->right
->name
[0]=='\0')
482 && (1<<p
->right
->lval
)==tyl
))
483 return( p
->left
->rval
);
490 makeor2( p
, q
, b
, o
) register NODE
*p
, *q
; register int b
, o
; {
495 f
= p
->n_left
; /* have to free this subtree later */
506 q
->n_right
->n_lval
= -q
->n_right
->n_lval
;
512 t
= q
->n_left
->n_left
;
516 cerror("illegal makeor2");
517 t
= NULL
; /* XXX gcc */
520 p
->n_lval
= t
->n_lval
;
521 p
->n_name
= t
->n_name
;
524 p
->n_rval
= R2PACK( (b
& 0177), o
, (b
>>7) );
531 canaddr( p
) NODE
*p
; {
532 register int o
= p
->n_op
;
534 if( o
==NAME
|| o
==REG
|| o
==ICON
|| o
==OREG
|| (o
==UMUL
&& shumul(p
->n_left
, STARNM
|SOREG
)) ) return(1);
538 shltype( o
, p
) register NODE
*p
; {
539 return( o
== REG
|| o
== NAME
|| o
== ICON
|| o
== OREG
|| ( o
==UMUL
&& shumul(p
->n_left
, STARNM
|SOREG
)) );
544 fldexpand(NODE
*p
, int cookie
, char **cp
)
550 flshape( p
) register NODE
*p
; {
551 return( p
->n_op
== REG
|| p
->n_op
== NAME
|| p
->n_op
== ICON
||
552 (p
->n_op
== OREG
&& (!R2TEST(p
->n_rval
) || tlen(p
) == 1)) );
556 shtemp( p
) register NODE
*p
; {
557 if( p
->n_op
== STARG
) p
= p
->n_left
;
558 return( p
->n_op
==NAME
|| p
->n_op
==ICON
|| p
->n_op
== OREG
|| (p
->n_op
==UMUL
&& shumul(p
->n_left
, STARNM
|SOREG
)) );
562 shumul( p
, shape
) register NODE
*p
; int shape
; {
567 printf("\nshumul:op=%d,lop=%d,rop=%d", p
->n_op
, p
->n_left
->n_op
, p
->n_right
->n_op
);
568 printf(" prname=%s,plty=%d, prlval=%lld\n", p
->n_right
->n_name
, p
->n_left
->n_type
, p
->n_right
->n_lval
);
573 if( o
== NAME
|| (o
== OREG
&& !R2TEST(p
->n_rval
)) || o
== ICON
)
578 if( ( o
== INCR
|| o
== ASG MINUS
) &&
579 ( p
->n_left
->n_op
== REG
&& p
->n_right
->n_op
== ICON
) &&
580 p
->n_right
->n_name
[0] == '\0' )
582 switch (p
->n_left
->n_type
)
607 if ( ISPTR(p
->n_left
->n_type
) ) {
613 return( p
->n_right
->n_lval
== o
? STARREG
: 0);
621 adrcon( val
) CONSZ val
; {
623 printf( CONFMT
, val
);
627 conput(FILE *fp
, NODE
*p
)
636 printf( "%s", rnames
[p
->n_rval
] );
640 cerror( "illegal conput" );
645 insput( p
) register NODE
*p
; {
650 upput( p
, size
) register NODE
*p
; {
655 adrput(FILE *fp
, NODE
*p
)
658 /* output an address, with offsets, from p */
660 if( p
->n_op
== FLD
){
670 /* addressable value of the constant */
671 if (p
->n_name
[0] == '\0') /* uses xxxab */
677 printf( "%s", rnames
[p
->n_rval
] );
682 if( R2TEST(r
) ){ /* double indexing */
686 if( flags
& 1 ) printf("*");
687 if( flags
& 4 ) printf("-");
688 if( p
->n_lval
!= 0 || p
->n_name
[0] != '\0' ) acon(p
);
689 if( R2UPK1(r
) != 100) printf( "(%s)", rnames
[R2UPK1(r
)] );
690 if( flags
& 2 ) printf("+");
691 printf( "[%s]", rnames
[R2UPK2(r
)] );
694 if( r
== AP
){ /* in the argument region */
695 if( p
->n_lval
<= 0 || p
->n_name
[0] != '\0' ) werror( "bad arg temp" );
696 printf( CONFMT
, p
->n_lval
);
700 if( p
->n_lval
!= 0 || p
->n_name
[0] != '\0') acon( p
);
701 printf( "(%s)", rnames
[p
->n_rval
] );
705 /* STARNM or STARREG found */
706 if( tshape(p
, STARNM
) ) {
708 adrput(0, p
->n_left
);
710 else { /* STARREG - really auto inc or dec */
715 p->n_left->n_op = OREG;
716 if( p->n_op == INCR ) {
726 printf("%c(%s)%c", (p
->n_left
->n_op
==INCR
? '\0' : '-'),
727 rnames
[p
->n_left
->n_left
->n_rval
],
728 (p
->n_left
->n_op
==INCR
? '+' : '\0') );
730 printf("%c(%s)%c", '-',
731 rnames
[p
->n_left
->n_left
->n_rval
],
735 p
->n_rval
= p
->n_left
->n_left
->n_rval
;
739 p
->n_lval
= (p
->n_left
->n_op
== INCR
? -p
->n_left
->n_right
->n_lval
: 0);
749 cerror( "illegal address" );
756 * print out a constant
762 if (p
->n_name
[0] == '\0') {
763 printf(CONFMT
, p
->n_lval
);
764 } else if( p
->n_lval
== 0 ) {
765 printf("%s", p
->n_name
);
767 printf("%s+", p
->n_name
);
768 printf(CONFMT
, p
->n_lval
);
773 genscall( p
, cookie
) register NODE
*p
; {
774 /* structure valued call */
775 return( gencall( p
, cookie
) );
782 gencall( p
, cookie
) register NODE
*p
; {
783 /* generate the call given by p */
784 register NODE
*p1
, *ptemp
;
785 register temp
, temp1
;
788 if( p
->right
) temp
= argsize( p
->right
);
791 if( p
->op
== STCALL
|| p
->op
== UNARY STCALL
){
792 /* set aside room for structure return */
794 if( p
->stsize
> temp
) temp1
= p
->stsize
;
798 if( temp
> maxargs
) maxargs
= temp
;
801 if( p
->right
){ /* make temp node, put offset in, and generate args */
806 ptemp
->name
[0] = '\0';
807 ptemp
->rall
= NOPREF
;
809 genargs( p
->right
, ptemp
);
814 if( p1
->op
!= ICON
){
816 if( p1
->op
!= OREG
|| R2TEST(p1
->rval
) ){
817 if( p1
->op
!= NAME
){
825 if( p1->op == REG && p->rval == R5 ){
826 cerror( "call register overwrite" );
830 setup gc_numbytes so reference to ZC works */
836 m
= match( p
, INTAREG
|INTBREG
);
842 printf( " tst (sp)+\n" );
845 printf( " cmp (sp)+,(sp)+\n" );
848 printf( " add $%d,sp\n", temp);
870 * printf conditional and unconditional branches
873 cbgen(int o
, int lab
)
877 printf(" jbr " LABFMT
"\n", lab
);
880 comperr("bad conditional branch: %s", opst
[o
]);
881 printf("\t%s\t" LABFMT
"\n", ccbranches
[o
-EQ
], lab
);
886 optim2(NODE
*p
, void *arg
)
888 /* do local tree transformations and optimizations */
895 /* commute L and R to eliminate compliments and constants */
896 if( (p
->n_left
->n_op
==ICON
&&p
->n_left
->n_name
[0]==0) || p
->n_left
->n_op
==COMPL
) {
898 p
->n_left
= p
->n_right
;
903 /* change meaning of AND to ~R&L - bic on pdp11 */
905 if( r
->op
==ICON
&& r
->name
[0]==0 ) { /* compliment constant */
908 else if( r
->op
==COMPL
) { /* ~~A => A */
912 else { /* insert complement node */
914 p
->right
->op
= COMPL
;
915 p
->right
->rall
= NOPREF
;
916 p
->right
->type
= r
->type
;
918 p
->right
->right
= NULL
;
926 myreader(struct interpass
*ipole
)
928 struct interpass
*ip
;
930 DLIST_FOREACH(ip
, ipole
, qelem
) {
931 if (ip
->type
!= IP_NODE
)
933 walkf(ip
->ip_node
, optim2
, 0);
943 myoptim(struct interpass
*ip
)
948 * Return argument size in regs.
955 if (t
== STRTY
|| t
== UNIONTY
)
956 return p
->n_stsize
/(SZINT
/SZCHAR
);
961 * Last chance to do something before calling a function.
969 /* Calculate argument sizes */
971 if (p
->n_op
!= CALL
&& p
->n_op
!= FORTCALL
&& p
->n_op
!= STCALL
)
973 for (p
= p
->n_right
; p
->n_op
== CM
; p
= p
->n_left
)
974 size
+= argsiz(p
->n_right
);
976 op
->n_qual
= size
; /* XXX */
980 * Return a class suitable for a specific type.
985 return (szty(t
) == 2 ? CLASSB
: CLASSA
);
989 * For class c, find worst-case displacement of the number of
990 * registers in the array r[] indexed by class.
993 COLORMAP(int c
, int *r
)
999 /* there are 12 classa, so min 6 classb are needed to block */
1000 num
= r
[CLASSB
] * 2;
1004 /* 6 classa may block all classb */
1005 num
= r
[CLASSB
] + r
[CLASSA
];
1008 comperr("COLORMAP");
1009 return 0; /* XXX gcc */
1016 special(NODE
*p
, int shape
)
1022 * Target-dependent command-line options.
1029 * Do something target-dependent for xasm arguments.
1030 * Supposed to find target-specific constraints and rewrite them.
1033 myxasm(struct interpass
*ip
, NODE
*p
)