xref: /netbsd/external/bsd/pcc/dist/pcc/arch/vax/code.c (revision 6550d01e)
1 /*	Id: code.c,v 1.8 2009/02/08 16:55:08 ragge Exp 	*/
2 /*	$NetBSD: code.c,v 1.1.1.3 2010/06/03 18:57:32 plunky Exp $	*/
3 /*
4  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * Redistributions of source code and documentation must retain the above
11  * copyright notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditionsand the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * All advertising materials mentioning features or use of this software
16  * must display the following acknowledgement:
17  * 	This product includes software developed or owned by Caldera
18  *	International, Inc.
19  * Neither the name of Caldera International, Inc. nor the names of other
20  * contributors may be used to endorse or promote products derived from
21  * this software without specific prior written permission.
22  *
23  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
28  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 # include "pass1.h"
38 
39 short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
40 #define LOG2SZ 9
41 
42 void
43 defalign(n) {
44 	/* cause the alignment to become a multiple of n */
45 	n /= SZCHAR;
46 	if( lastloc != PROG && n > 1 ) printf( "	.align	%d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
47 	}
48 
49 /*
50  * output something to define the current position as label n
51  */
52 void
53 deflab1(int n)
54 {
55 	printf(LABFMT ":\n", n);
56 }
57 
58 void
59 efcode(){
60 	/* code for the end of a function */
61 	if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
62 		return;
63 	cerror("efcode");
64 
65 #ifdef notyet
66 	if( strftn ){  /* copy output (in R2) to caller */
67 		register NODE *l, *r;
68 		register struct symtab *p;
69 		register TWORD t;
70 		register int j;
71 		int i;
72 
73 		p = &stab[curftn];
74 		t = p->stype;
75 		t = DECREF(t);
76 
77 		deflab( retlab );
78 
79 		i = getlab();	/* label for return area */
80 		printf("	.data\n" );
81 		printf("	.align	2\n" );
82 		deflab1(i);
83 		printf("\t.space  %d\n", tsize(t, p->dimoff, p->sizoff)/SZCHAR);
84 		printf("	.text\n" );
85 		psline();
86 		printf("	movab	" LABFMT ",r1\n", i);
87 
88 		reached = 1;
89 		l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
90 		l->rval = 1;  /* R1 */
91 		l->lval = 0;  /* no offset */
92 		r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
93 		r->rval = 0;  /* R0 */
94 		r->lval = 0;
95 		l = buildtree( UNARY MUL, l, NIL );
96 		r = buildtree( UNARY MUL, r, NIL );
97 		l = buildtree( ASSIGN, l, r );
98 		l->op = FREE;
99 		ecomp( l->left );
100 		printf( "	movab	" LABFMT ",r0\n", i );
101 		/* turn off strftn flag, so return sequence will be generated */
102 		strftn = 0;
103 		}
104 	branch( retlab );
105 	printf( "	.set	.R%d,0x%x\n", ftnno, ent_mask[reg_use] );
106 	reg_use = 11;
107 	p2bend();
108 	fdefflag = 0;
109 #endif
110 	}
111 
112 void
113 bfcode(struct symtab **a, int n)
114 {
115 	int i;
116 
117 	if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
118 		return;
119 	/* Function returns struct, adjust arg offset */
120 	for (i = 0; i < n; i++)
121 		a[i]->soffset += SZPOINT(INT);
122 }
123 
124 void
125 bccode(){ /* called just before the first executable statment */
126 		/* by now, the automatics and register variables are allocated */
127 	SETOFF( autooff, SZINT );
128 #if 0
129 	/* set aside store area offset */
130 	p2bbeg( autooff, regvar );
131 	reg_use = (reg_use > regvar ? regvar : reg_use);
132 #endif
133 	}
134 
135 void
136 ejobcode( flag ){
137 	/* called just before final exit */
138 	/* flag is 1 if errors, 0 if none */
139 	}
140 
141 void
142 bjobcode()
143 {
144 }
145 
146 #if 0
147 aobeg(){
148 	/* called before removing automatics from stab */
149 	}
150 
151 aocode(p) struct symtab *p; {
152 	/* called when automatic p removed from stab */
153 	}
154 
155 aoend(){
156 	/* called after removing all automatics from stab */
157 	}
158 #endif
159 
160 void
161 defnam( p ) register struct symtab *p; {
162 	/* define the current location as the name p->sname */
163 	char *n;
164 
165 	n = p->soname ? p->soname : exname(p->sname);
166 	if( p->sclass == EXTDEF ){
167 		printf( "	.globl	%s\n", n );
168 		}
169 	printf( "%s:\n", n );
170 
171 	}
172 
173 void
174 bycode( t, i ){
175 	/* put byte i+1 in a string */
176 
177 	i &= 07;
178 	if( t < 0 ){ /* end of the string */
179 		if( i != 0 ) printf( "\n" );
180 		}
181 
182 	else { /* stash byte t into string */
183 		if( i == 0 ) printf( "	.byte	" );
184 		else printf( "," );
185 		printf( "0x%x", t );
186 		if( i == 07 ) printf( "\n" );
187 		}
188 	}
189 
190 int
191 fldal( t ) unsigned t; { /* return the alignment of field of type t */
192 	uerror( "illegal field type" );
193 	return( ALINT );
194 	}
195 
196 void
197 fldty( p ) struct symtab *p; { /* fix up type of field p */
198 	;
199 	}
200 
201 /*
202  * XXX - fix genswitch.
203  */
204 int
205 mygenswitch(int num, TWORD type, struct swents **p, int n)
206 {
207 	return 0;
208 }
209 
210 #ifdef notyet
211 struct sw heapsw[SWITSZ];	/* heap for switches */
212 
213 genswitch(p,n) register struct sw *p;{
214 	/*	p points to an array of structures, each consisting
215 		of a constant value and a label.
216 		The first is >=0 if there is a default label;
217 		its value is the label number
218 		The entries p[1] to p[n] are the nontrivial cases
219 		*/
220 	register i;
221 	register CONSZ j, range;
222 	register dlab, swlab;
223 
224 	range = p[n].sval-p[1].sval;
225 
226 	if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
227 
228 		swlab = getlab();
229 		dlab = p->slab >= 0 ? p->slab : getlab();
230 
231 		/* already in r0 */
232 		printf("	casel	r0,$%ld,$%ld\n", p[1].sval, range);
233 		deflab1(swlab);
234 		for( i=1,j=p[1].sval; i<=n; j++) {
235 			printf("	.word	" LABFMT "-" LABFMT "\n",
236 			    (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
237 				swlab);
238 			}
239 
240 		if( p->slab >= 0 ) branch( dlab );
241 		else deflab1(dlab);
242 		return;
243 
244 		}
245 
246 	if( n>8 ) {	/* heap switch */
247 
248 		heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
249 		makeheap(p, n, 1);	/* build heap */
250 
251 		walkheap(1, n);	/* produce code */
252 
253 		if( p->slab >= 0 )
254 			branch( dlab );
255 		else
256 			deflab1(dlab);
257 		return;
258 	}
259 
260 	/* debugging code */
261 
262 	/* out for the moment
263 	if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
264 	*/
265 
266 	/* simple switch code */
267 
268 	for( i=1; i<=n; ++i ){
269 		/* already in r0 */
270 
271 		printf( "	cmpl	r0,$" );
272 		printf( CONFMT, p[i].sval );
273 		printf( "\n	jeql	" LBLFMT "\n", p[i].slab );
274 		}
275 
276 	if( p->slab>=0 ) branch( p->slab );
277 	}
278 
279 makeheap(p, m, n)
280 register struct sw *p;
281 {
282 	register int q;
283 
284 	q = select(m);
285 	heapsw[n] = p[q];
286 	if( q>1 ) makeheap(p, q-1, 2*n);
287 	if( q<m ) makeheap(p+q, m-q, 2*n+1);
288 }
289 
290 select(m) {
291 	register int l,i,k;
292 
293 	for(i=1; ; i*=2)
294 		if( (i-1) > m ) break;
295 	l = ((k = i/2 - 1) + 1)/2;
296 	return( l + (m-k < l ? m-k : l));
297 }
298 
299 walkheap(start, limit)
300 {
301 	int label;
302 
303 
304 	if( start > limit ) return;
305 	printf("	cmpl	r0,$%d\n",  heapsw[start].sval);
306 	printf("	jeql	" LBLFMT "\n", heapsw[start].slab);
307 	if( (2*start) > limit ) {
308 		printf("	jbr 	" LBLFMT "\n", heapsw[0].slab);
309 		return;
310 	}
311 	if( (2*start+1) <= limit ) {
312 		label = getlab();
313 		printf("	jgtr	" LBLFMT "\n", label);
314 	} else
315 		printf("	jgtr	" LBLFMT "\n", heapsw[0].slab);
316 	walkheap( 2*start, limit);
317 	if( (2*start+1) <= limit ) {
318 		deflab1(label);
319 		walkheap( 2*start+1, limit);
320 	}
321 }
322 #endif
323 /*
324  * Called with a function call with arguments as argument.
325  * This is done early in buildtree() and only done once.
326  */
327 NODE *
328 funcode(NODE *p)
329 {
330 	return p;
331 }
332