xref: /original-bsd/old/pcc/ccom.vax/code.c (revision 1403a0cd)
1 #ifndef lint
2 static char *sccsid ="@(#)code.c	1.4 (Berkeley) 04/02/85";
3 #endif lint
4 
5 # include "pass1.h"
6 # include <sys/types.h>
7 # include <a.out.h>
8 # include <stab.h>
9 
10 int proflg = 0;	/* are we generating profiling code? */
11 int strftn = 0;  /* is the current function one which returns a value */
12 int gdebug;
13 int fdefflag;  /* are we within a function definition ? */
14 char NULLNAME[8];
15 int labelno;
16 
17 branch( n ){
18 	/* output a branch to label n */
19 	/* exception is an ordinary function branching to retlab: then, return */
20 	if( n == retlab && !strftn ){
21 		printf( "	ret\n" );
22 		}
23 	else printf( "	jbr 	L%d\n", n );
24 	}
25 
26 int lastloc = { -1 };
27 
28 short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
29 #define LOG2SZ 9
30 
31 defalign(n) {
32 	/* cause the alignment to become a multiple of n */
33 	n /= SZCHAR;
34 	if( lastloc != PROG && n > 1 ) printf( "	.align	%d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
35 	}
36 
37 locctr( l ){
38 	register temp;
39 	/* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
40 
41 	if( l == lastloc ) return(l);
42 	temp = lastloc;
43 	lastloc = l;
44 	switch( l ){
45 
46 	case PROG:
47 		printf( "	.text\n" );
48 		psline();
49 		break;
50 
51 	case DATA:
52 	case ADATA:
53 		printf( "	.data\n" );
54 		break;
55 
56 	case STRNG:
57 		printf( "	.data	1\n" );
58 		break;
59 
60 	case ISTRNG:
61 		printf( "	.data	2\n" );
62 		break;
63 
64 	case STAB:
65 		printf( "	.stab\n" );
66 		break;
67 
68 	default:
69 		cerror( "illegal location counter" );
70 		}
71 
72 	return( temp );
73 	}
74 
75 deflab( n ){
76 	/* output something to define the current position as label n */
77 	printf( "L%d:\n", n );
78 	}
79 
80 int crslab = 10;
81 
82 getlab(){
83 	/* return a number usable for a label */
84 	return( ++crslab );
85 	}
86 
87 
88 int ent_mask[] = {
89 	0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0};
90 
91 int reg_use = 11;
92 
93 efcode(){
94 	/* code for the end of a function */
95 
96 	if( strftn ){  /* copy output (in R2) to caller */
97 		register NODE *l, *r;
98 		register struct symtab *p;
99 		register TWORD t;
100 		int i;
101 
102 		p = &stab[curftn];
103 		t = p->stype;
104 		t = DECREF(t);
105 
106 		deflab( retlab );
107 
108 		i = getlab();	/* label for return area */
109 #ifndef LCOMM
110 		printf("	.data\n" );
111 		printf("	.align	2\n" );
112 		printf("L%d:	.space	%d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
113 		printf("	.text\n" );
114 #else
115 		{ int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR;
116 		if (sz % sizeof (int))
117 			sz += sizeof (int) - (sz % sizeof (int));
118 		printf("	.lcomm	L%d,%d\n", i, sz);
119 		}
120 #endif
121 		psline();
122 		printf("	movab	L%d,r1\n", i);
123 
124 		reached = 1;
125 		l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
126 		l->tn.rval = 1;  /* R1 */
127 		l->tn.lval = 0;  /* no offset */
128 		r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
129 		r->tn.rval = 0;  /* R0 */
130 		r->tn.lval = 0;
131 		l = buildtree( UNARY MUL, l, NIL );
132 		r = buildtree( UNARY MUL, r, NIL );
133 		l = buildtree( ASSIGN, l, r );
134 		l->in.op = FREE;
135 		ecomp( l->in.left );
136 		printf( "	movab	L%d,r0\n", i );
137 		/* turn off strftn flag, so return sequence will be generated */
138 		strftn = 0;
139 		}
140 	branch( retlab );
141 #ifndef VMS
142 	printf( "	.set	L%d,0x%x\n", ftnno, ent_mask[reg_use] );
143 #else
144 	printf( "	.set	L%d,%d	# Hex = 0x%x\n", ftnno, 0x3c| ent_mask[reg_use], ent_mask[reg_use]  );
145 	/* KLS kludge, under VMS if you use regs 2-5, you must save them. */
146 #endif
147 	reg_use = 11;
148 	p2bend();
149 	fdefflag = 0;
150 	}
151 
152 int ftlab1, ftlab2;
153 
154 bfcode( a, n ) int a[]; {
155 	/* code for the beginning of a function; a is an array of
156 		indices in stab for the arguments; n is the number */
157 	register i;
158 	register temp;
159 	register struct symtab *p;
160 	int off;
161 	char *toreg();
162 
163 	locctr( PROG );
164 	p = &stab[curftn];
165 	printf( "	.align	1\n");
166 	defnam( p );
167 	temp = p->stype;
168 	temp = DECREF(temp);
169 	strftn = (temp==STRTY) || (temp==UNIONTY);
170 
171 	retlab = getlab();
172 
173 	/* routine prolog */
174 
175 	printf( "	.word	L%d\n", ftnno);
176 	ftlab1 = getlab();
177 	ftlab2 = getlab();
178 	printf( "	jbr 	L%d\n", ftlab1);
179 	printf( "L%d:\n", ftlab2);
180 	if( proflg ) {	/* profile code */
181 		i = getlab();
182 		printf("	movab	L%d,r0\n", i);
183 		printf("	jsb 	mcount\n");
184 		printf("	.data\n");
185 		printf("	.align	2\n");
186 		printf("L%d:	.long	0\n", i);
187 		printf("	.text\n");
188 		psline();
189 		}
190 
191 	off = ARGINIT;
192 
193 	for( i=0; i<n; ++i ){
194 		p = &stab[a[i]];
195 		if( p->sclass == REGISTER ){
196 			temp = p->offset;  /* save register number */
197 			p->sclass = PARAM;  /* forget that it is a register */
198 			p->offset = NOOFFSET;
199 			oalloc( p, &off );
200 /*tbl*/		printf( "	%s	%d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp );
201 			p->offset = temp;  /* remember register number */
202 			p->sclass = REGISTER;   /* remember that it is a register */
203 			}
204 		else if( p->stype == STRTY || p->stype == UNIONTY ) {
205 			p->offset = NOOFFSET;
206 			if( oalloc( p, &off ) ) cerror( "bad argument" );
207 			SETOFF( off, ALSTACK );
208 			}
209 		else {
210 			if( oalloc( p, &off ) ) cerror( "bad argument" );
211 			}
212 
213 		}
214 	if (gdebug) {
215 #ifdef STABDOT
216 		pstabdot(N_SLINE, lineno);
217 #else
218 		pstab(NULLNAME, N_SLINE);
219 		printf("0,%d,LL%d\n", lineno, labelno);
220 		printf("LL%d:\n", labelno++);
221 #endif
222 	}
223 	fdefflag = 1;
224 	}
225 
226 bccode(){ /* called just before the first executable statment */
227 		/* by now, the automatics and register variables are allocated */
228 	SETOFF( autooff, SZINT );
229 	/* set aside store area offset */
230 	p2bbeg( autooff, regvar );
231 	reg_use = (reg_use > regvar ? regvar : reg_use);
232 	}
233 
234 ejobcode( flag ){
235 	/* called just before final exit */
236 	/* flag is 1 if errors, 0 if none */
237 	}
238 
239 aobeg(){
240 	/* called before removing automatics from stab */
241 	}
242 
243 aocode(p) struct symtab *p; {
244 	/* called when automatic p removed from stab */
245 	}
246 
247 aoend(){
248 	/* called after removing all automatics from stab */
249 	}
250 
251 defnam( p ) register struct symtab *p; {
252 	/* define the current location as the name p->sname */
253 
254 	if( p->sclass == EXTDEF ){
255 		printf( "	.globl	%s\n", exname( p->sname ) );
256 		}
257 	if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
258 	else printf( "%s:\n", exname( p->sname ) );
259 
260 	}
261 
262 bycode( t, i ){
263 #ifdef ASSTRINGS
264 static	int	lastoctal = 0;
265 #endif
266 
267 	/* put byte i+1 in a string */
268 
269 #ifdef ASSTRINGS
270 
271 	i &= 077;
272 	if ( t < 0 ){
273 		if ( i != 0 )	printf( "\"\n" );
274 	} else {
275 		if ( i == 0 ) printf("\t.ascii\t\"");
276 		if ( t == '\\' || t == '"'){
277 			lastoctal = 0;
278 			printf("\\%c", t);
279 		}
280 			/*
281 			 *	We escape the colon in strings so that
282 			 *	c2 will, in its infinite wisdom, interpret
283 			 *	the characters preceding the colon as a label.
284 			 *	If we didn't escape the colon, c2 would
285 			 *	throw away any trailing blanks or tabs after
286 			 *	the colon, but reconstruct a assembly
287 			 *	language semantically correct program.
288 			 *	C2 hasn't been taught about strings.
289 			 */
290 		else if ( t == ':' || t < 040 || t >= 0177 ){
291 			lastoctal++;
292 			printf("\\%o",t);
293 		}
294 		else if ( lastoctal && '0' <= t && t <= '9' ){
295 			lastoctal = 0;
296 			printf("\"\n\t.ascii\t\"%c", t );
297 		}
298 		else
299 		{
300 			lastoctal = 0;
301 			putchar(t);
302 		}
303 		if ( i == 077 ) printf("\"\n");
304 	}
305 #else
306 
307 	i &= 07;
308 	if( t < 0 ){ /* end of the string */
309 		if( i != 0 ) printf( "\n" );
310 		}
311 
312 	else { /* stash byte t into string */
313 		if( i == 0 ) printf( "	.byte	" );
314 		else printf( "," );
315 		printf( "0x%x", t );
316 		if( i == 07 ) printf( "\n" );
317 		}
318 #endif
319 	}
320 
321 zecode( n ){
322 	/* n integer words of zeros */
323 	OFFSZ temp;
324 	if( n <= 0 ) return;
325 	printf( "	.space	%d\n", (SZINT/SZCHAR)*n );
326 	temp = n;
327 	inoff += temp*SZINT;
328 	}
329 
330 fldal( t ) unsigned t; { /* return the alignment of field of type t */
331 	uerror( "illegal field type" );
332 	return( ALINT );
333 	}
334 
335 fldty( p ) struct symtab *p; { /* fix up type of field p */
336 	;
337 	}
338 
339 where(c){ /* print location of error  */
340 	/* c is either 'u', 'c', or 'w' */
341 	/* GCOS version */
342 	fprintf( stderr, "%s, line %d: ", ftitle, lineno );
343 	}
344 
345 
346 /* tbl - toreg() returns a pointer to a char string
347 		  which is the correct  "register move" for the passed type
348  */
349 struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
350 	{
351 	CHAR, "cvtbl",
352 	SHORT, "cvtwl",
353 	INT, "movl",
354 	LONG, "movl",
355 	FLOAT, "movf",
356 	DOUBLE, "movd",
357 	UCHAR,	"movzbl",
358 	USHORT,	"movzwl",
359 	UNSIGNED,	"movl",
360 	ULONG,	"movl",
361 	0, ""
362 	};
363 
364 char
365 *toreg(type)
366 	TWORD type;
367 {
368 	struct type_move *p;
369 
370 	for ( p=toreg_strs; p->fromtype != 0; p++)
371 		if (p->fromtype == type) return(p->tostrng);
372 
373 	/* type not found, must be a pointer type */
374 	return("movl");
375 }
376 /* tbl */
377 
378 
379 main( argc, argv ) char *argv[]; {
380 #ifdef BUFSTDERR
381 	char errbuf[BUFSIZ];
382 	setbuf(stderr, errbuf);
383 #endif
384 	return(mainp1( argc, argv ));
385 	}
386 
387 struct sw heapsw[SWITSZ];	/* heap for switches */
388 
389 genswitch(p,n) register struct sw *p;{
390 	/*	p points to an array of structures, each consisting
391 		of a constant value and a label.
392 		The first is >=0 if there is a default label;
393 		its value is the label number
394 		The entries p[1] to p[n] are the nontrivial cases
395 		*/
396 	register i;
397 	register CONSZ j, range;
398 	register dlab, swlab;
399 
400 	range = p[n].sval-p[1].sval;
401 
402 	if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
403 
404 		swlab = getlab();
405 		dlab = p->slab >= 0 ? p->slab : getlab();
406 
407 		/* already in r0 */
408 		printf("	casel	r0,$%ld,$%ld\n", p[1].sval, range);
409 		printf("L%d:\n", swlab);
410 		for( i=1,j=p[1].sval; i<=n; j++) {
411 			printf("	.word	L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
412 				swlab);
413 			}
414 
415 		if( p->slab >= 0 ) branch( dlab );
416 		else printf("L%d:\n", dlab);
417 		return;
418 
419 		}
420 
421 	if( n>8 ) {	/* heap switch */
422 
423 		heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
424 		makeheap(p, n, 1);	/* build heap */
425 
426 		walkheap(1, n);	/* produce code */
427 
428 		if( p->slab >= 0 )
429 			branch( dlab );
430 		else
431 			printf("L%d:\n", dlab);
432 		return;
433 	}
434 
435 	/* debugging code */
436 
437 	/* out for the moment
438 	if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
439 	*/
440 
441 	/* simple switch code */
442 
443 	for( i=1; i<=n; ++i ){
444 		/* already in r0 */
445 
446 		printf( "	cmpl	r0,$" );
447 		printf( CONFMT, p[i].sval );
448 		printf( "\n	jeql	L%d\n", p[i].slab );
449 		}
450 
451 	if( p->slab>=0 ) branch( p->slab );
452 	}
453 
454 makeheap(p, m, n)
455 register struct sw *p;
456 {
457 	register int q;
458 
459 	q = select(m);
460 	heapsw[n] = p[q];
461 	if( q>1 ) makeheap(p, q-1, 2*n);
462 	if( q<m ) makeheap(p+q, m-q, 2*n+1);
463 }
464 
465 select(m) {
466 	register int l,i,k;
467 
468 	for(i=1; ; i*=2)
469 		if( (i-1) > m ) break;
470 	l = ((k = i/2 - 1) + 1)/2;
471 	return( l + (m-k < l ? m-k : l));
472 }
473 
474 walkheap(start, limit)
475 {
476 	int label;
477 
478 
479 	if( start > limit ) return;
480 	printf("	cmpl	r0,$%d\n",  heapsw[start].sval);
481 	printf("	jeql	L%d\n", heapsw[start].slab);
482 	if( (2*start) > limit ) {
483 		printf("	jbr 	L%d\n", heapsw[0].slab);
484 		return;
485 	}
486 	if( (2*start+1) <= limit ) {
487 		label = getlab();
488 		printf("	jgtr	L%d\n", label);
489 	} else
490 		printf("	jgtr	L%d\n", heapsw[0].slab);
491 	walkheap( 2*start, limit);
492 	if( (2*start+1) <= limit ) {
493 		printf("L%d:\n", label);
494 		walkheap( 2*start+1, limit);
495 	}
496 }
497