xref: /csrg-svn/old/pcc/ccom.vax/code.c (revision 15896)
1*15896Ssam static char *sccsid ="@(#)code.c	1.2 (Berkeley) 01/25/84";
29700Slinton # include "mfile1"
39700Slinton # include <sys/types.h>
49700Slinton # include <a.out.h>
59700Slinton # include <stab.h>
69700Slinton 
79700Slinton int proflg = 0;	/* are we generating profiling code? */
89700Slinton int strftn = 0;  /* is the current function one which returns a value */
99700Slinton int gdebug;
109700Slinton int fdefflag;  /* are we within a function definition ? */
119700Slinton char NULLNAME[8];
129700Slinton int labelno;
139700Slinton 
149700Slinton branch( n ){
159700Slinton 	/* output a branch to label n */
169700Slinton 	/* exception is an ordinary function branching to retlab: then, return */
179700Slinton 	if( n == retlab && !strftn ){
189700Slinton 		printf( "	ret\n" );
199700Slinton 		}
209700Slinton 	else printf( "	jbr 	L%d\n", n );
219700Slinton 	}
229700Slinton 
239700Slinton int lastloc = { -1 };
249700Slinton 
259700Slinton short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
269700Slinton #define LOG2SZ 9
279700Slinton 
289700Slinton defalign(n) {
299700Slinton 	/* cause the alignment to become a multiple of n */
309700Slinton 	n /= SZCHAR;
319700Slinton 	if( lastloc != PROG && n > 1 ) printf( "	.align	%d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
329700Slinton 	}
339700Slinton 
349700Slinton locctr( l ){
359700Slinton 	register temp;
369700Slinton 	/* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
379700Slinton 
389700Slinton 	if( l == lastloc ) return(l);
399700Slinton 	temp = lastloc;
409700Slinton 	lastloc = l;
419700Slinton 	switch( l ){
429700Slinton 
439700Slinton 	case PROG:
449700Slinton 		printf( "	.text\n" );
459700Slinton 		psline();
469700Slinton 		break;
479700Slinton 
489700Slinton 	case DATA:
499700Slinton 	case ADATA:
509700Slinton 		printf( "	.data\n" );
519700Slinton 		break;
529700Slinton 
539700Slinton 	case STRNG:
549700Slinton 		printf( "	.data	1\n" );
559700Slinton 		break;
569700Slinton 
579700Slinton 	case ISTRNG:
589700Slinton 		printf( "	.data	2\n" );
599700Slinton 		break;
609700Slinton 
619700Slinton 	case STAB:
629700Slinton 		printf( "	.stab\n" );
639700Slinton 		break;
649700Slinton 
659700Slinton 	default:
669700Slinton 		cerror( "illegal location counter" );
679700Slinton 		}
689700Slinton 
699700Slinton 	return( temp );
709700Slinton 	}
719700Slinton 
729700Slinton deflab( n ){
739700Slinton 	/* output something to define the current position as label n */
749700Slinton 	printf( "L%d:\n", n );
759700Slinton 	}
769700Slinton 
779700Slinton int crslab = 10;
789700Slinton 
799700Slinton getlab(){
809700Slinton 	/* return a number usable for a label */
819700Slinton 	return( ++crslab );
829700Slinton 	}
839700Slinton 
849700Slinton 
859700Slinton int ent_mask[] = {
869700Slinton 	0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0};
879700Slinton 
889700Slinton int reg_use = 11;
899700Slinton 
909700Slinton efcode(){
919700Slinton 	/* code for the end of a function */
929700Slinton 
939700Slinton 	if( strftn ){  /* copy output (in R2) to caller */
949700Slinton 		register NODE *l, *r;
959700Slinton 		register struct symtab *p;
969700Slinton 		register TWORD t;
979700Slinton 		register int j;
989700Slinton 		int i;
999700Slinton 
1009700Slinton 		p = &stab[curftn];
1019700Slinton 		t = p->stype;
1029700Slinton 		t = DECREF(t);
1039700Slinton 
1049700Slinton 		deflab( retlab );
1059700Slinton 
1069700Slinton 		i = getlab();	/* label for return area */
1079700Slinton #ifndef LCOMM
1089700Slinton 		printf("	.data\n" );
1099700Slinton 		printf("	.align	2\n" );
1109700Slinton 		printf("L%d:	.space	%d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
1119700Slinton 		printf("	.text\n" );
1129700Slinton #else
1139700Slinton 		{ int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR;
1149700Slinton 		if (sz % sizeof (int))
1159700Slinton 			sz += sizeof (int) - (sz % sizeof (int));
1169700Slinton 		printf("	.lcomm	L%d,%d\n", i, sz);
1179700Slinton 		}
1189700Slinton #endif
1199700Slinton 		psline();
1209700Slinton 		printf("	movab	L%d,r1\n", i);
1219700Slinton 
1229700Slinton 		reached = 1;
1239700Slinton 		l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
1249700Slinton 		l->tn.rval = 1;  /* R1 */
1259700Slinton 		l->tn.lval = 0;  /* no offset */
1269700Slinton 		r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
1279700Slinton 		r->tn.rval = 0;  /* R0 */
1289700Slinton 		r->tn.lval = 0;
1299700Slinton 		l = buildtree( UNARY MUL, l, NIL );
1309700Slinton 		r = buildtree( UNARY MUL, r, NIL );
1319700Slinton 		l = buildtree( ASSIGN, l, r );
1329700Slinton 		l->in.op = FREE;
1339700Slinton 		ecomp( l->in.left );
1349700Slinton 		printf( "	movab	L%d,r0\n", i );
1359700Slinton 		/* turn off strftn flag, so return sequence will be generated */
1369700Slinton 		strftn = 0;
1379700Slinton 		}
1389700Slinton 	branch( retlab );
1399700Slinton #ifndef VMS
1409700Slinton 	printf( "	.set	L%d,0x%x\n", ftnno, ent_mask[reg_use] );
1419700Slinton #else
1429700Slinton 	printf( "	.set	L%d,%d	# Hex = 0x%x\n", ftnno, 0x3c| ent_mask[reg_use], ent_mask[reg_use]  );
1439700Slinton 	/* KLS kludge, under VMS if you use regs 2-5, you must save them. */
1449700Slinton #endif
1459700Slinton 	reg_use = 11;
1469700Slinton 	p2bend();
1479700Slinton 	fdefflag = 0;
1489700Slinton 	}
1499700Slinton 
1509700Slinton int ftlab1, ftlab2;
1519700Slinton 
1529700Slinton bfcode( a, n ) int a[]; {
1539700Slinton 	/* code for the beginning of a function; a is an array of
1549700Slinton 		indices in stab for the arguments; n is the number */
1559700Slinton 	register i;
1569700Slinton 	register temp;
1579700Slinton 	register struct symtab *p;
1589700Slinton 	int off;
1599700Slinton 	char *toreg();
1609700Slinton 
1619700Slinton 	locctr( PROG );
1629700Slinton 	p = &stab[curftn];
1639700Slinton 	printf( "	.align	1\n");
1649700Slinton 	defnam( p );
1659700Slinton 	temp = p->stype;
1669700Slinton 	temp = DECREF(temp);
1679700Slinton 	strftn = (temp==STRTY) || (temp==UNIONTY);
1689700Slinton 
1699700Slinton 	retlab = getlab();
1709700Slinton 
1719700Slinton 	/* routine prolog */
1729700Slinton 
1739700Slinton 	printf( "	.word	L%d\n", ftnno);
1749700Slinton 	ftlab1 = getlab();
1759700Slinton 	ftlab2 = getlab();
1769700Slinton 	printf( "	jbr 	L%d\n", ftlab1);
1779700Slinton 	printf( "L%d:\n", ftlab2);
1789700Slinton 	if( proflg ) {	/* profile code */
1799700Slinton 		i = getlab();
1809700Slinton 		printf("	movab	L%d,r0\n", i);
1819700Slinton 		printf("	jsb 	mcount\n");
1829700Slinton 		printf("	.data\n");
1839700Slinton 		printf("	.align	2\n");
1849700Slinton 		printf("L%d:	.long	0\n", i);
1859700Slinton 		printf("	.text\n");
1869700Slinton 		psline();
1879700Slinton 		}
1889700Slinton 
1899700Slinton 	off = ARGINIT;
1909700Slinton 
1919700Slinton 	for( i=0; i<n; ++i ){
1929700Slinton 		p = &stab[a[i]];
1939700Slinton 		if( p->sclass == REGISTER ){
1949700Slinton 			temp = p->offset;  /* save register number */
1959700Slinton 			p->sclass = PARAM;  /* forget that it is a register */
1969700Slinton 			p->offset = NOOFFSET;
1979700Slinton 			oalloc( p, &off );
1989700Slinton /*tbl*/		printf( "	%s	%d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp );
1999700Slinton 			p->offset = temp;  /* remember register number */
2009700Slinton 			p->sclass = REGISTER;   /* remember that it is a register */
2019700Slinton 			}
2029700Slinton 		else if( p->stype == STRTY || p->stype == UNIONTY ) {
2039700Slinton 			p->offset = NOOFFSET;
2049700Slinton 			if( oalloc( p, &off ) ) cerror( "bad argument" );
2059700Slinton 			SETOFF( off, ALSTACK );
2069700Slinton 			}
2079700Slinton 		else {
2089700Slinton 			if( oalloc( p, &off ) ) cerror( "bad argument" );
2099700Slinton 			}
2109700Slinton 
2119700Slinton 		}
212*15896Ssam 	if (gdebug) {
213*15896Ssam #ifdef STABDOT
214*15896Ssam 		pstabdot(N_SLINE, lineno);
215*15896Ssam #else
216*15896Ssam 		pstab(NULLNAME, N_SLINE);
217*15896Ssam 		printf("0,%d,LL%d\n", lineno, labelno);
218*15896Ssam 		printf("LL%d:\n", labelno++);
219*15896Ssam #endif
220*15896Ssam 	}
2219700Slinton 	fdefflag = 1;
2229700Slinton 	}
2239700Slinton 
2249700Slinton bccode(){ /* called just before the first executable statment */
2259700Slinton 		/* by now, the automatics and register variables are allocated */
2269700Slinton 	SETOFF( autooff, SZINT );
2279700Slinton 	/* set aside store area offset */
2289700Slinton 	p2bbeg( autooff, regvar );
2299700Slinton 	reg_use = (reg_use > regvar ? regvar : reg_use);
2309700Slinton 	}
2319700Slinton 
2329700Slinton ejobcode( flag ){
2339700Slinton 	/* called just before final exit */
2349700Slinton 	/* flag is 1 if errors, 0 if none */
2359700Slinton 	}
2369700Slinton 
2379700Slinton aobeg(){
2389700Slinton 	/* called before removing automatics from stab */
2399700Slinton 	}
2409700Slinton 
2419700Slinton aocode(p) struct symtab *p; {
2429700Slinton 	/* called when automatic p removed from stab */
2439700Slinton 	}
2449700Slinton 
2459700Slinton aoend(){
2469700Slinton 	/* called after removing all automatics from stab */
2479700Slinton 	}
2489700Slinton 
2499700Slinton defnam( p ) register struct symtab *p; {
2509700Slinton 	/* define the current location as the name p->sname */
2519700Slinton 
2529700Slinton 	if( p->sclass == EXTDEF ){
2539700Slinton 		printf( "	.globl	%s\n", exname( p->sname ) );
2549700Slinton 		}
2559700Slinton 	if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
2569700Slinton 	else printf( "%s:\n", exname( p->sname ) );
2579700Slinton 
2589700Slinton 	}
2599700Slinton 
2609700Slinton bycode( t, i ){
2619700Slinton #ifdef ASSTRINGS
2629700Slinton static	int	lastoctal = 0;
2639700Slinton #endif
2649700Slinton 
2659700Slinton 	/* put byte i+1 in a string */
2669700Slinton 
2679700Slinton #ifdef ASSTRINGS
2689700Slinton 
2699700Slinton 	i &= 077;
2709700Slinton 	if ( t < 0 ){
2719700Slinton 		if ( i != 0 )	printf( "\"\n" );
2729700Slinton 	} else {
2739700Slinton 		if ( i == 0 ) printf("\t.ascii\t\"");
2749700Slinton 		if ( t == '\\' || t == '"'){
2759700Slinton 			lastoctal = 0;
2769700Slinton 			printf("\\%c", t);
2779700Slinton 		}
2789700Slinton 			/*
2799700Slinton 			 *	We escape the colon in strings so that
2809700Slinton 			 *	c2 will, in its infinite wisdom, interpret
2819700Slinton 			 *	the characters preceding the colon as a label.
2829700Slinton 			 *	If we didn't escape the colon, c2 would
2839700Slinton 			 *	throw away any trailing blanks or tabs after
2849700Slinton 			 *	the colon, but reconstruct a assembly
2859700Slinton 			 *	language semantically correct program.
2869700Slinton 			 *	C2 hasn't been taught about strings.
2879700Slinton 			 */
2889700Slinton 		else if ( t == ':' || t < 040 || t >= 0177 ){
2899700Slinton 			lastoctal++;
2909700Slinton 			printf("\\%o",t);
2919700Slinton 		}
2929700Slinton 		else if ( lastoctal && '0' <= t && t <= '9' ){
2939700Slinton 			lastoctal = 0;
2949700Slinton 			printf("\"\n\t.ascii\t\"%c", t );
2959700Slinton 		}
2969700Slinton 		else
2979700Slinton 		{
2989700Slinton 			lastoctal = 0;
2999700Slinton 			putchar(t);
3009700Slinton 		}
3019700Slinton 		if ( i == 077 ) printf("\"\n");
3029700Slinton 	}
3039700Slinton #else
3049700Slinton 
3059700Slinton 	i &= 07;
3069700Slinton 	if( t < 0 ){ /* end of the string */
3079700Slinton 		if( i != 0 ) printf( "\n" );
3089700Slinton 		}
3099700Slinton 
3109700Slinton 	else { /* stash byte t into string */
3119700Slinton 		if( i == 0 ) printf( "	.byte	" );
3129700Slinton 		else printf( "," );
3139700Slinton 		printf( "0x%x", t );
3149700Slinton 		if( i == 07 ) printf( "\n" );
3159700Slinton 		}
3169700Slinton #endif
3179700Slinton 	}
3189700Slinton 
3199700Slinton zecode( n ){
3209700Slinton 	/* n integer words of zeros */
3219700Slinton 	OFFSZ temp;
3229700Slinton 	if( n <= 0 ) return;
3239700Slinton 	printf( "	.space	%d\n", (SZINT/SZCHAR)*n );
3249700Slinton 	temp = n;
3259700Slinton 	inoff += temp*SZINT;
3269700Slinton 	}
3279700Slinton 
3289700Slinton fldal( t ) unsigned t; { /* return the alignment of field of type t */
3299700Slinton 	uerror( "illegal field type" );
3309700Slinton 	return( ALINT );
3319700Slinton 	}
3329700Slinton 
3339700Slinton fldty( p ) struct symtab *p; { /* fix up type of field p */
3349700Slinton 	;
3359700Slinton 	}
3369700Slinton 
3379700Slinton where(c){ /* print location of error  */
3389700Slinton 	/* c is either 'u', 'c', or 'w' */
3399700Slinton 	/* GCOS version */
3409700Slinton 	fprintf( stderr, "%s, line %d: ", ftitle, lineno );
3419700Slinton 	}
3429700Slinton 
3439700Slinton 
3449700Slinton /* tbl - toreg() returns a pointer to a char string
3459700Slinton 		  which is the correct  "register move" for the passed type
3469700Slinton  */
3479700Slinton struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
3489700Slinton 	{
3499700Slinton 	CHAR, "cvtbl",
3509700Slinton 	SHORT, "cvtwl",
3519700Slinton 	INT, "movl",
3529700Slinton 	LONG, "movl",
3539700Slinton 	FLOAT, "movf",
3549700Slinton 	DOUBLE, "movd",
3559700Slinton 	UCHAR,	"movzbl",
3569700Slinton 	USHORT,	"movzwl",
3579700Slinton 	UNSIGNED,	"movl",
3589700Slinton 	ULONG,	"movl",
3599700Slinton 	-1, ""
3609700Slinton 	};
3619700Slinton 
3629700Slinton char
3639700Slinton *toreg(type)
3649700Slinton 	TWORD type;
3659700Slinton {
3669700Slinton 	struct type_move *p;
3679700Slinton 
3689700Slinton 	for ( p=toreg_strs; p->fromtype > 0; p++)
3699700Slinton 		if (p->fromtype == type) return(p->tostrng);
3709700Slinton 
3719700Slinton 	/* type not found, must be a pointer type */
3729700Slinton 	return("movl");
3739700Slinton }
3749700Slinton /* tbl */
3759700Slinton 
3769700Slinton 
3779700Slinton main( argc, argv ) char *argv[]; {
3789700Slinton #ifdef BUFSTDERR
3799700Slinton 	char errbuf[BUFSIZ];
3809700Slinton 	setbuf(stderr, errbuf);
3819700Slinton #endif
3829700Slinton 	return(mainp1( argc, argv ));
3839700Slinton 	}
3849700Slinton 
3859700Slinton struct sw heapsw[SWITSZ];	/* heap for switches */
3869700Slinton 
3879700Slinton genswitch(p,n) register struct sw *p;{
3889700Slinton 	/*	p points to an array of structures, each consisting
3899700Slinton 		of a constant value and a label.
3909700Slinton 		The first is >=0 if there is a default label;
3919700Slinton 		its value is the label number
3929700Slinton 		The entries p[1] to p[n] are the nontrivial cases
3939700Slinton 		*/
3949700Slinton 	register i;
3959700Slinton 	register CONSZ j, range;
3969700Slinton 	register dlab, swlab;
3979700Slinton 
3989700Slinton 	range = p[n].sval-p[1].sval;
3999700Slinton 
4009700Slinton 	if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
4019700Slinton 
4029700Slinton 		swlab = getlab();
4039700Slinton 		dlab = p->slab >= 0 ? p->slab : getlab();
4049700Slinton 
4059700Slinton 		/* already in r0 */
4069700Slinton 		printf("	casel	r0,$%ld,$%ld\n", p[1].sval, range);
4079700Slinton 		printf("L%d:\n", swlab);
4089700Slinton 		for( i=1,j=p[1].sval; i<=n; j++) {
4099700Slinton 			printf("	.word	L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
4109700Slinton 				swlab);
4119700Slinton 			}
4129700Slinton 
4139700Slinton 		if( p->slab >= 0 ) branch( dlab );
4149700Slinton 		else printf("L%d:\n", dlab);
4159700Slinton 		return;
4169700Slinton 
4179700Slinton 		}
4189700Slinton 
4199700Slinton 	if( n>8 ) {	/* heap switch */
4209700Slinton 
4219700Slinton 		heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
4229700Slinton 		makeheap(p, n, 1);	/* build heap */
4239700Slinton 
4249700Slinton 		walkheap(1, n);	/* produce code */
4259700Slinton 
4269700Slinton 		if( p->slab >= 0 )
4279700Slinton 			branch( dlab );
4289700Slinton 		else
4299700Slinton 			printf("L%d:\n", dlab);
4309700Slinton 		return;
4319700Slinton 	}
4329700Slinton 
4339700Slinton 	/* debugging code */
4349700Slinton 
4359700Slinton 	/* out for the moment
4369700Slinton 	if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
4379700Slinton 	*/
4389700Slinton 
4399700Slinton 	/* simple switch code */
4409700Slinton 
4419700Slinton 	for( i=1; i<=n; ++i ){
4429700Slinton 		/* already in r0 */
4439700Slinton 
4449700Slinton 		printf( "	cmpl	r0,$" );
4459700Slinton 		printf( CONFMT, p[i].sval );
4469700Slinton 		printf( "\n	jeql	L%d\n", p[i].slab );
4479700Slinton 		}
4489700Slinton 
4499700Slinton 	if( p->slab>=0 ) branch( p->slab );
4509700Slinton 	}
4519700Slinton 
4529700Slinton makeheap(p, m, n)
4539700Slinton register struct sw *p;
4549700Slinton {
4559700Slinton 	register int q;
4569700Slinton 
4579700Slinton 	q = select(m);
4589700Slinton 	heapsw[n] = p[q];
4599700Slinton 	if( q>1 ) makeheap(p, q-1, 2*n);
4609700Slinton 	if( q<m ) makeheap(p+q, m-q, 2*n+1);
4619700Slinton }
4629700Slinton 
4639700Slinton select(m) {
4649700Slinton 	register int l,i,k;
4659700Slinton 
4669700Slinton 	for(i=1; ; i*=2)
4679700Slinton 		if( (i-1) > m ) break;
4689700Slinton 	l = ((k = i/2 - 1) + 1)/2;
4699700Slinton 	return( l + (m-k < l ? m-k : l));
4709700Slinton }
4719700Slinton 
4729700Slinton walkheap(start, limit)
4739700Slinton {
4749700Slinton 	int label;
4759700Slinton 
4769700Slinton 
4779700Slinton 	if( start > limit ) return;
4789700Slinton 	printf("	cmpl	r0,$%d\n",  heapsw[start].sval);
4799700Slinton 	printf("	jeql	L%d\n", heapsw[start].slab);
4809700Slinton 	if( (2*start) > limit ) {
4819700Slinton 		printf("	jbr 	L%d\n", heapsw[0].slab);
4829700Slinton 		return;
4839700Slinton 	}
4849700Slinton 	if( (2*start+1) <= limit ) {
4859700Slinton 		label = getlab();
4869700Slinton 		printf("	jgtr	L%d\n", label);
4879700Slinton 	} else
4889700Slinton 		printf("	jgtr	L%d\n", heapsw[0].slab);
4899700Slinton 	walkheap( 2*start, limit);
4909700Slinton 	if( (2*start+1) <= limit ) {
4919700Slinton 		printf("L%d:\n", label);
4929700Slinton 		walkheap( 2*start+1, limit);
4939700Slinton 	}
4949700Slinton }
495