1 /* $Id: code.c,v 1.8 2009/02/08 16:55:08 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 short log2tab
[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
43 /* cause the alignment to become a multiple of n */
45 if( lastloc
!= PROG
&& n
> 1 ) printf( " .align %d\n", n
>= 0 && n
< LOG2SZ
? log2tab
[n
] : 0 );
49 * output something to define the current position as label n
54 printf(LABFMT
":\n", n
);
59 /* code for the end of a function */
60 if (cftnsp
->stype
!= STRTY
+FTN
&& cftnsp
->stype
!= UNIONTY
+FTN
)
65 if( strftn
){ /* copy output (in R2) to caller */
67 register struct symtab
*p
;
78 i
= getlab(); /* label for return area */
80 printf(" .align 2\n" );
82 printf("\t.space %d\n", tsize(t
, p
->dimoff
, p
->sizoff
)/SZCHAR
);
85 printf(" movab " LABFMT
",r1\n", i
);
88 l
= block( REG
, NIL
, NIL
, PTR
|t
, p
->dimoff
, p
->sizoff
);
90 l
->lval
= 0; /* no offset */
91 r
= block( REG
, NIL
, NIL
, PTR
|t
, p
->dimoff
, p
->sizoff
);
94 l
= buildtree( UNARY MUL
, l
, NIL
);
95 r
= buildtree( UNARY MUL
, r
, NIL
);
96 l
= buildtree( ASSIGN
, l
, r
);
99 printf( " movab " LABFMT
",r0\n", i
);
100 /* turn off strftn flag, so return sequence will be generated */
104 printf( " .set .R%d,0x%x\n", ftnno
, ent_mask
[reg_use
] );
112 bfcode(struct symtab
**a
, int n
)
116 if (cftnsp
->stype
!= STRTY
+FTN
&& cftnsp
->stype
!= UNIONTY
+FTN
)
118 /* Function returns struct, adjust arg offset */
119 for (i
= 0; i
< n
; i
++)
120 a
[i
]->soffset
+= SZPOINT(INT
);
124 bccode(){ /* called just before the first executable statment */
125 /* by now, the automatics and register variables are allocated */
126 SETOFF( autooff
, SZINT
);
128 /* set aside store area offset */
129 p2bbeg( autooff
, regvar
);
130 reg_use
= (reg_use
> regvar
? regvar
: reg_use
);
136 /* called just before final exit */
137 /* flag is 1 if errors, 0 if none */
147 /* called before removing automatics from stab */
150 aocode(p
) struct symtab
*p
; {
151 /* called when automatic p removed from stab */
155 /* called after removing all automatics from stab */
160 defnam( p
) register struct symtab
*p
; {
161 /* define the current location as the name p->sname */
164 n
= p
->soname
? p
->soname
: exname(p
->sname
);
165 if( p
->sclass
== EXTDEF
){
166 printf( " .globl %s\n", n
);
168 printf( "%s:\n", n
);
174 /* put byte i+1 in a string */
177 if( t
< 0 ){ /* end of the string */
178 if( i
!= 0 ) printf( "\n" );
181 else { /* stash byte t into string */
182 if( i
== 0 ) printf( " .byte " );
185 if( i
== 07 ) printf( "\n" );
190 fldal( t
) unsigned t
; { /* return the alignment of field of type t */
191 uerror( "illegal field type" );
196 fldty( p
) struct symtab
*p
; { /* fix up type of field p */
201 * XXX - fix genswitch.
204 mygenswitch(int num
, TWORD type
, struct swents
**p
, int n
)
210 struct sw heapsw
[SWITSZ
]; /* heap for switches */
212 genswitch(p
,n
) register struct sw
*p
;{
213 /* p points to an array of structures, each consisting
214 of a constant value and a label.
215 The first is >=0 if there is a default label;
216 its value is the label number
217 The entries p[1] to p[n] are the nontrivial cases
220 register CONSZ j
, range
;
221 register dlab
, swlab
;
223 range
= p
[n
].sval
-p
[1].sval
;
225 if( range
>0 && range
<= 3*n
&& n
>=4 ){ /* implement a direct switch */
228 dlab
= p
->slab
>= 0 ? p
->slab
: getlab();
231 printf(" casel r0,$%ld,$%ld\n", p
[1].sval
, range
);
233 for( i
=1,j
=p
[1].sval
; i
<=n
; j
++) {
234 printf(" .word " LABFMT
"-" LABFMT
"\n",
235 (j
== p
[i
].sval
? ((j
=p
[i
++].sval
), p
[i
-1].slab
) : dlab
),
239 if( p
->slab
>= 0 ) branch( dlab
);
245 if( n
>8 ) { /* heap switch */
247 heapsw
[0].slab
= dlab
= p
->slab
>= 0 ? p
->slab
: getlab();
248 makeheap(p
, n
, 1); /* build heap */
250 walkheap(1, n
); /* produce code */
261 /* out for the moment
262 if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
265 /* simple switch code */
267 for( i
=1; i
<=n
; ++i
){
270 printf( " cmpl r0,$" );
271 printf( CONFMT
, p
[i
].sval
);
272 printf( "\n jeql " LBLFMT
"\n", p
[i
].slab
);
275 if( p
->slab
>=0 ) branch( p
->slab
);
279 register struct sw
*p
;
285 if( q
>1 ) makeheap(p
, q
-1, 2*n
);
286 if( q
<m
) makeheap(p
+q
, m
-q
, 2*n
+1);
293 if( (i
-1) > m
) break;
294 l
= ((k
= i
/2 - 1) + 1)/2;
295 return( l
+ (m
-k
< l
? m
-k
: l
));
298 walkheap(start
, limit
)
303 if( start
> limit
) return;
304 printf(" cmpl r0,$%d\n", heapsw
[start
].sval
);
305 printf(" jeql " LBLFMT
"\n", heapsw
[start
].slab
);
306 if( (2*start
) > limit
) {
307 printf(" jbr " LBLFMT
"\n", heapsw
[0].slab
);
310 if( (2*start
+1) <= limit
) {
312 printf(" jgtr " LBLFMT
"\n", label
);
314 printf(" jgtr " LBLFMT
"\n", heapsw
[0].slab
);
315 walkheap( 2*start
, limit
);
316 if( (2*start
+1) <= limit
) {
318 walkheap( 2*start
+1, limit
);
323 * Called with a function call with arguments as argument.
324 * This is done early in buildtree() and only done once.