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