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