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