xref: /csrg-svn/old/pcc/ccom.tahoe/code.c (revision 26162)
125826Ssam #ifndef lint
2*26162Ssam static char sccsid[] = "@(#)code.c	1.3 (Berkeley) 02/12/86";
325826Ssam #endif
425826Ssam 
526075Ssam # include "pass1.h"
625826Ssam # include <sys/types.h>
725826Ssam # include <a.out.h>
825826Ssam # include <stab.h>
925826Ssam 
10*26162Ssam # define putstr(s)	fputs((s), stdout)
11*26162Ssam 
1225826Ssam int proflg = 0;	/* are we generating profiling code? */
1325826Ssam int strftn = 0;  /* is the current function one which returns a value */
1425826Ssam int gdebug;
1525826Ssam int fdefflag;  /* are we within a function definition ? */
1625826Ssam #ifndef STABDOT
1725826Ssam char NULLNAME[8];
1825826Ssam #endif
1925826Ssam int labelno;
2025826Ssam 
2125826Ssam branch( n ){
2225826Ssam 	/* output a branch to label n */
2325826Ssam 	/* exception is an ordinary function branching to retlab: then, return */
2425826Ssam 	if( n == retlab && !strftn ){
2525826Ssam 		register TWORD t;
2625826Ssam 		register r;
2725826Ssam 			/* set number of regs in assem comment field */
2825826Ssam 			/* so optimizers can do a better job */
2925826Ssam 		r = 0;
3025826Ssam 		if( retstat & RETVAL ){ /* the function rets a val somewhere */
3125826Ssam 			t = (&stab[curftn])->stype;
3225826Ssam 			t = DECREF(t);
3325826Ssam 			r++;	/* it is at least one */
3425826Ssam 			if(t == DOUBLE)
3525826Ssam 				r++;	/* it takes two */
3625826Ssam 		} else		/* the fn does not ret a val	*/
3725826Ssam 			r = 2;
3825826Ssam 		printf( "	ret#%d\n", r );
3925826Ssam 		}
4025826Ssam 	else printf( "	jbr 	L%d\n", n );
4125826Ssam 	}
4225826Ssam 
4325826Ssam int lastloc = { -1 };
4425826Ssam 
4525826Ssam short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
4625826Ssam #define LOG2SZ 9
4725826Ssam 
4825826Ssam defalign(n) {
4925826Ssam 	/* cause the alignment to become a multiple of n */
5025826Ssam 	n /= SZCHAR;
5125826Ssam 	if( lastloc != PROG && n > 1 ) printf( "	.align	%d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
5225826Ssam 	}
5325826Ssam 
5425826Ssam locctr( l ){
5525826Ssam 	register temp;
5625826Ssam 	/* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
5725826Ssam 
5825826Ssam 	if( l == lastloc ) return(l);
5925826Ssam 	temp = lastloc;
6025826Ssam 	lastloc = l;
6125826Ssam 	switch( l ){
6225826Ssam 
6325826Ssam 	case PROG:
64*26162Ssam 		putstr( "	.text\n" );
6525826Ssam 		psline();
6625826Ssam 		break;
6725826Ssam 
6825826Ssam 	case DATA:
6925826Ssam 	case ADATA:
70*26162Ssam 		putstr( "	.data\n" );
7125826Ssam 		break;
7225826Ssam 
7325826Ssam 	case STRNG:
74*26162Ssam 		putstr( "	.data	1\n" );
7525826Ssam 		break;
7625826Ssam 
7725826Ssam 	case ISTRNG:
78*26162Ssam 		putstr( "	.data	2\n" );
7925826Ssam 		break;
8025826Ssam 
8125826Ssam 	case STAB:
82*26162Ssam 		putstr( "	.stab\n" );
8325826Ssam 		break;
8425826Ssam 
8525826Ssam 	default:
8625826Ssam 		cerror( "illegal location counter" );
8725826Ssam 		}
8825826Ssam 
8925826Ssam 	return( temp );
9025826Ssam 	}
9125826Ssam 
9225826Ssam deflab( n ){
9325826Ssam 	/* output something to define the current position as label n */
9425826Ssam 	printf( "L%d:\n", n );
9525826Ssam 	}
9625826Ssam 
9725826Ssam int crslab = 10;
9825826Ssam 
9925826Ssam getlab(){
10025826Ssam 	/* return a number usable for a label */
10125826Ssam 	return( ++crslab );
10225826Ssam 	}
10325826Ssam 
10425826Ssam 
10525826Ssam efcode(){
10625826Ssam 	/* code for the end of a function */
10725826Ssam 
10825826Ssam 	if( strftn ){  /* copy output (in R2) to caller */
10925826Ssam 		register NODE *l, *r;
11025826Ssam 		register struct symtab *p;
11125826Ssam 		register TWORD t;
11225826Ssam 		register int i;
11325826Ssam 
11425826Ssam 		p = &stab[curftn];
11525826Ssam 		t = p->stype;
11625826Ssam 		t = DECREF(t);
11725826Ssam 
11825826Ssam 		deflab( retlab );
11925826Ssam 
12025826Ssam 		i = getlab();	/* label for return area */
12125826Ssam #ifndef LCOMM
122*26162Ssam 		putstr("	.data\n" );
123*26162Ssam 		putstr("	.align	2\n" );
12425826Ssam 		printf("L%d:	.space	%d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
125*26162Ssam 		putstr("	.text\n" );
12625826Ssam #else
12725826Ssam 		{ int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR;
12825826Ssam 		if (sz % (SZINT/SZCHAR))
12925826Ssam 			sz += (SZINT/SZCHAR) - (sz % (SZINT/SZCHAR));
13025826Ssam 		printf("	.lcomm	L%d,%d\n", i, sz);
13125826Ssam 		}
13225826Ssam #endif
13325826Ssam 		psline();
13425826Ssam 		printf("	movab	L%d,r1\n", i);
13525826Ssam 
13625826Ssam 		reached = 1;
13725826Ssam 		l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
13825826Ssam 		l->tn.rval = 1;  /* R1 */
13925826Ssam 		l->tn.lval = 0;  /* no offset */
14025826Ssam 		r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
14125826Ssam 		r->tn.rval = 0;  /* R0 */
14225826Ssam 		r->tn.lval = 0;
14325826Ssam 		l = buildtree( UNARY MUL, l, NIL );
14425826Ssam 		r = buildtree( UNARY MUL, r, NIL );
14525826Ssam 		l = buildtree( ASSIGN, l, r );
14625826Ssam 		l->in.op = FREE;
14725826Ssam 		ecomp( l->in.left );
14825826Ssam 		printf( "	movab	L%d,r0\n", i );
14925826Ssam 		/* turn off strftn flag, so return sequence will be generated */
15025826Ssam 		strftn = 0;
15125826Ssam 		}
15225826Ssam 	branch( retlab );
15325826Ssam 	p2bend();
15425826Ssam 	fdefflag = 0;
15525826Ssam 	}
15625826Ssam 
15725826Ssam int ftlab1, ftlab2;
15825826Ssam 
15925826Ssam bfcode( a, n ) int a[]; {
16025826Ssam 	/* code for the beginning of a function; a is an array of
16125826Ssam 		indices in stab for the arguments; n is the number */
16225826Ssam 	register i;
16325826Ssam 	register temp;
16425826Ssam 	register struct symtab *p;
16525826Ssam 	int off;
16625826Ssam #ifdef REG_CHAR
16725826Ssam 	char *toreg();
16825826Ssam #endif
16925826Ssam 	char *rname();
17025826Ssam 
17125826Ssam 	locctr( PROG );
17225826Ssam 	p = &stab[curftn];
173*26162Ssam 	putstr( "	.align	1\n");
17425826Ssam 	defnam( p );
17525826Ssam 	temp = p->stype;
17625826Ssam 	temp = DECREF(temp);
17725826Ssam 	strftn = (temp==STRTY) || (temp==UNIONTY);
17825826Ssam 
17925826Ssam 	retlab = getlab();
18025826Ssam 
18125826Ssam 	/* routine prolog */
18225826Ssam 
18325826Ssam 	printf( "	.word	L%d\n", ftnno);
18425826Ssam 	if (gdebug) {
18525826Ssam #ifdef STABDOT
18625826Ssam 		pstabdot(N_SLINE, lineno);
18725826Ssam #else
18825826Ssam 		pstab(NULLNAME, N_SLINE);
18925826Ssam 		printf("0,%d,LL%d\n", lineno, labelno);
19025826Ssam 		printf("LL%d:\n", labelno++);
19125826Ssam #endif
19225826Ssam 	}
19325826Ssam 	ftlab1 = getlab();
19425826Ssam 	ftlab2 = getlab();
19525826Ssam 	printf( "	jbr 	L%d\n", ftlab1);
19625826Ssam 	printf( "L%d:\n", ftlab2);
19725826Ssam 	if( proflg ) {	/* profile code */
19825826Ssam 		i = getlab();
19925826Ssam 		printf("	pushl	$L%d\n", i);
200*26162Ssam 		putstr("	callf	$8,mcount\n");
201*26162Ssam 		putstr("	.data\n");
202*26162Ssam 		putstr("	.align	2\n");
20325826Ssam 		printf("L%d:	.long	0\n", i);
204*26162Ssam 		putstr("	.text\n");
20525826Ssam 		psline();
20625826Ssam 		}
20725826Ssam 
20825826Ssam 	off = ARGINIT;
20925826Ssam 
21025826Ssam 	for( i=0; i<n; ++i ){
21125826Ssam 		p = &stab[a[i]];
21225826Ssam 		if( p->sclass == REGISTER ){
21325826Ssam 			temp = p->offset;  /* save register number */
21425826Ssam 			p->sclass = PARAM;  /* forget that it is a register */
21525826Ssam 			p->offset = NOOFFSET;
21625826Ssam 			oalloc( p, &off );
21725826Ssam #ifdef REG_CHAR
21825826Ssam 			printf( "	%s", toreg(p->stype)) );
21925826Ssam #else
220*26162Ssam 			putstr("	movl");
22125826Ssam #endif
22225826Ssam 			printf( "	%d(fp),%s\n", p->offset/SZCHAR, rname(temp) );
22325826Ssam 			p->offset = temp;  /* remember register number */
22425826Ssam 			p->sclass = REGISTER;   /* remember that it is a register */
22525826Ssam #ifdef REG_CHAR
22625826Ssam 			temp = p->stype;
22725826Ssam 			if( temp==CHAR || temp==SHORT )
22825826Ssam 				p->stype = INT;
22925826Ssam 			else if( temp==UCHAR || temp==USHORT )
23025826Ssam 				p->stype = UNSIGNED;
23125826Ssam #endif
23225826Ssam 			}
23325826Ssam 		else if( p->stype == STRTY || p->stype == UNIONTY ) {
23425826Ssam 			p->offset = NOOFFSET;
23525826Ssam 			if( oalloc( p, &off ) ) cerror( "bad argument" );
23625826Ssam 			SETOFF( off, ALSTACK );
23725826Ssam 			}
23825826Ssam 		else {
23925826Ssam 			if( oalloc( p, &off ) ) cerror( "bad argument" );
24025826Ssam 			}
24125826Ssam 
24225826Ssam 		}
24325826Ssam 	fdefflag = 1;
24425826Ssam 	}
24525826Ssam 
24625826Ssam bccode(){ /* called just before the first executable statment */
24725826Ssam 		/* by now, the automatics and register variables are allocated */
24825826Ssam 	SETOFF( autooff, SZINT );
24925826Ssam 	/* set aside store area offset */
25025826Ssam 	p2bbeg( autooff, regvar );
25125826Ssam 	}
25225826Ssam 
25325826Ssam ejobcode( flag ){
25425826Ssam 	/* called just before final exit */
25525826Ssam 	/* flag is 1 if errors, 0 if none */
25625826Ssam 	}
25725826Ssam 
25825826Ssam aobeg(){
25925826Ssam 	/* called before removing automatics from stab */
26025826Ssam 	}
26125826Ssam 
26225826Ssam aocode(p) struct symtab *p; {
26325826Ssam 	/* called when automatic p removed from stab */
26425826Ssam 	}
26525826Ssam 
26625826Ssam aoend(){
26725826Ssam 	/* called after removing all automatics from stab */
26825826Ssam 	}
26925826Ssam 
27025826Ssam defnam( p ) register struct symtab *p; {
27125826Ssam 	/* define the current location as the name p->sname */
27225826Ssam 
27325826Ssam 	if( p->sclass == EXTDEF ){
27425826Ssam 		printf( "	.globl	%s\n", exname( p->sname ) );
27525826Ssam 		}
27625826Ssam 	if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
27725826Ssam 	else printf( "%s:\n", exname( p->sname ) );
27825826Ssam 
27925826Ssam 	}
28025826Ssam 
28125826Ssam bycode( t, i ){
28225826Ssam #ifdef ASSTRINGS
28325826Ssam static	int	lastoctal = 0;
28425826Ssam #endif
28525826Ssam 
28625826Ssam 	/* put byte i+1 in a string */
28725826Ssam 
28825826Ssam #ifdef ASSTRINGS
28925826Ssam 
29025826Ssam 	i &= 077;
29125826Ssam 	if ( t < 0 ){
292*26162Ssam 		if ( i != 0 )	putstr( "\"\n" );
29325826Ssam 	} else {
294*26162Ssam 		if ( i == 0 ) putstr("\t.ascii\t\"");
29525826Ssam 		if ( t == '\\' || t == '"'){
29625826Ssam 			lastoctal = 0;
29725826Ssam 			printf("\\%c", t);
29825826Ssam 		}
29925826Ssam 		else if ( t < 040 || t >= 0177 ){
30025826Ssam 			lastoctal++;
30125826Ssam 			printf("\\%o",t);
30225826Ssam 		}
30325826Ssam 		else if ( lastoctal && '0' <= t && t <= '9' ){
30425826Ssam 			lastoctal = 0;
30525826Ssam 			printf("\"\n\t.ascii\t\"%c", t );
30625826Ssam 		}
30725826Ssam 		else
30825826Ssam 		{
30925826Ssam 			lastoctal = 0;
31025826Ssam 			putchar(t);
31125826Ssam 		}
312*26162Ssam 		if ( i == 077 ) putstr("\"\n");
31325826Ssam 	}
31425826Ssam #else
31525826Ssam 
31625826Ssam 	i &= 07;
31725826Ssam 	if( t < 0 ){ /* end of the string */
318*26162Ssam 		if( i != 0 ) putchar( '\n' );
31925826Ssam 		}
32025826Ssam 
32125826Ssam 	else { /* stash byte t into string */
322*26162Ssam 		if( i == 0 ) putstr( "	.byte	" );
323*26162Ssam 		else putchar( ',' );
32425826Ssam 		printf( "0x%x", t );
325*26162Ssam 		if( i == 07 ) putchar( '\n' );
32625826Ssam 		}
32725826Ssam #endif
32825826Ssam 	}
32925826Ssam 
33025826Ssam zecode( n ){
33125826Ssam 	/* n integer words of zeros */
33225826Ssam 	OFFSZ temp;
33325826Ssam 	if( n <= 0 ) return;
33425826Ssam 	printf( "	.space	%d\n", (SZINT/SZCHAR)*n );
33525826Ssam 	temp = n;
33625826Ssam 	inoff += temp*SZINT;
33725826Ssam 	}
33825826Ssam 
33925826Ssam fldal( t ) unsigned t; { /* return the alignment of field of type t */
34025826Ssam 	uerror( "illegal field type" );
34125826Ssam 	return( ALINT );
34225826Ssam 	}
34325826Ssam 
34425826Ssam fldty( p ) struct symtab *p; { /* fix up type of field p */
34525826Ssam 	;
34625826Ssam 	}
34725826Ssam 
34825826Ssam where(c){ /* print location of error  */
34925826Ssam 	/* c is either 'u', 'c', or 'w' */
35025826Ssam 	/* GCOS version */
35125826Ssam 	fprintf( stderr, "%s, line %d: ", ftitle, lineno );
35225826Ssam 	}
35325826Ssam 
35425826Ssam 
35525826Ssam #ifdef REG_CHAR
35625826Ssam /* tbl - toreg() returns a pointer to a char string
35725826Ssam 		  which is the correct  "register move" for the passed type
35825826Ssam  */
35925826Ssam struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
36025826Ssam 	{
36125826Ssam 	CHAR, "cvtbl",
36225826Ssam 	SHORT, "cvtwl",
36325826Ssam 	UCHAR,	"movzbl",
36425826Ssam 	USHORT,	"movzwl",
36525826Ssam 	0, "movl"
36625826Ssam 	};
36725826Ssam 
36825826Ssam char
36925826Ssam *toreg(type)
37025826Ssam 	TWORD type;
37125826Ssam {
37225826Ssam 	struct type_move *p;
37325826Ssam 
37425826Ssam 	for ( p=toreg_strs; p->fromtype != 0; p++)
37525826Ssam 		if (p->fromtype == type) return(p->tostrng);
37625826Ssam 
37725826Ssam 	/* type not found, must be a word type */
37825826Ssam 	return(p->tostrng);
37925826Ssam }
38025826Ssam /* tbl */
38125826Ssam #endif
38225826Ssam 
38325826Ssam 
38425826Ssam main( argc, argv ) char *argv[]; {
38525826Ssam #ifdef BUFSTDERR
38625826Ssam 	char errbuf[BUFSIZ];
38725826Ssam 	setbuf(stderr, errbuf);
38825826Ssam #endif
38925826Ssam 	return(mainp1( argc, argv ));
39025826Ssam 	}
39125826Ssam 
39225826Ssam struct sw heapsw[SWITSZ];	/* heap for switches */
39325826Ssam 
39425826Ssam genswitch(p,n) register struct sw *p;{
39525826Ssam 	/*	p points to an array of structures, each consisting
39625826Ssam 		of a constant value and a label.
39725826Ssam 		The first is >=0 if there is a default label;
39825826Ssam 		its value is the label number
39925826Ssam 		The entries p[1] to p[n] are the nontrivial cases
40025826Ssam 		*/
40125826Ssam 	register i;
40225826Ssam 	register CONSZ j;
40325826Ssam 	register CONSZ unsigned range;
40425826Ssam 	register dlab, swlab;
40525826Ssam 
40625826Ssam 	range = p[n].sval-p[1].sval;
40725826Ssam 
40825826Ssam 	if( range <= 3*n && n>=4 ){ /* implement a direct switch */
40925826Ssam 
41025826Ssam 		swlab = getlab();
41125826Ssam 		dlab = p->slab >= 0 ? p->slab : getlab();
41225826Ssam 
41325826Ssam 		/* already in r0 */
414*26162Ssam 		putstr( "	casel	r0,$" );
41525826Ssam 		printf( CONFMT, p[1].sval );
416*26162Ssam 		putstr(",$");
41725826Ssam 		printf( CONFMT, range);
41825826Ssam 		printf("\n	.align 1\nL%d:\n", swlab);
41925826Ssam 		for( i=1,j=p[1].sval; i<=n; j++) {
42025826Ssam 			printf("	.word	L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
42125826Ssam 				swlab);
42225826Ssam 			}
42325826Ssam 
42425826Ssam 		if( p->slab >= 0 ) branch( dlab );
42525826Ssam 		else printf("L%d:\n", dlab);
42625826Ssam 		return;
42725826Ssam 
42825826Ssam 		}
42925826Ssam 
43025826Ssam 	if( n>8 ) {	/* heap switch */
43125826Ssam 
43225826Ssam 		heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
43325826Ssam 		makeheap(p, n, 1);	/* build heap */
43425826Ssam 
43525826Ssam 		walkheap(1, n);	/* produce code */
43625826Ssam 
43725826Ssam 		if( p->slab >= 0 )
43825826Ssam 			branch( dlab );
43925826Ssam 		else
44025826Ssam 			printf("L%d:\n", dlab);
44125826Ssam 		return;
44225826Ssam 	}
44325826Ssam 
44425826Ssam 	/* debugging code */
44525826Ssam 
44625826Ssam 	/* out for the moment
44725826Ssam 	if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
44825826Ssam 	*/
44925826Ssam 
45025826Ssam 	/* simple switch code */
45125826Ssam 
45225826Ssam 	for( i=1; i<=n; ++i ){
45325826Ssam 		/* already in r0 */
45425826Ssam 
455*26162Ssam 		putstr( "	cmpl	r0,$" );
45625826Ssam 		printf( CONFMT, p[i].sval );
45725826Ssam 		printf( "\n	jeql	L%d\n", p[i].slab );
45825826Ssam 		}
45925826Ssam 
46025826Ssam 	if( p->slab>=0 ) branch( p->slab );
46125826Ssam 	}
46225826Ssam 
46325826Ssam makeheap(p, m, n)
46425826Ssam register struct sw *p;
46525826Ssam {
46625826Ssam 	register int q;
46725826Ssam 
46825826Ssam 	q = select(m);
46925826Ssam 	heapsw[n] = p[q];
47025826Ssam 	if( q>1 ) makeheap(p, q-1, 2*n);
47125826Ssam 	if( q<m ) makeheap(p+q, m-q, 2*n+1);
47225826Ssam }
47325826Ssam 
47425826Ssam select(m) {
47525826Ssam 	register int l,i,k;
47625826Ssam 
47725826Ssam 	for(i=1; ; i*=2)
47825826Ssam 		if( (i-1) > m ) break;
47925826Ssam 	l = ((k = i/2 - 1) + 1)/2;
48025826Ssam 	return( l + (m-k < l ? m-k : l));
48125826Ssam }
48225826Ssam 
48325826Ssam walkheap(start, limit)
48425826Ssam {
48525826Ssam 	int label;
48625826Ssam 
48725826Ssam 
48825826Ssam 	if( start > limit ) return;
489*26162Ssam 	putstr( "	cmpl	r0,$" );
49025826Ssam 	printf( CONFMT, heapsw[start].sval);
49125826Ssam 	printf("\n	jeql	L%d\n", heapsw[start].slab);
49225826Ssam 	if( (2*start) > limit ) {
49325826Ssam 		printf("	jbr 	L%d\n", heapsw[0].slab);
49425826Ssam 		return;
49525826Ssam 	}
49625826Ssam 	if( (2*start+1) <= limit ) {
49725826Ssam 		label = getlab();
49825826Ssam 		printf("	jgtr	L%d\n", label);
49925826Ssam 	} else
50025826Ssam 		printf("	jgtr	L%d\n", heapsw[0].slab);
50125826Ssam 	walkheap( 2*start, limit);
50225826Ssam 	if( (2*start+1) <= limit ) {
50325826Ssam 		printf("L%d:\n", label);
50425826Ssam 		walkheap( 2*start+1, limit);
50525826Ssam 	}
50625826Ssam }
507