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