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