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