xref: /csrg-svn/old/pcc/ccom.vax/code.c (revision 9700)
1*9700Slinton static char *sccsid ="@(#)code.c	1.1 (Berkeley) 12/15/82";
2*9700Slinton # include "mfile1"
3*9700Slinton # include <sys/types.h>
4*9700Slinton # include <a.out.h>
5*9700Slinton # include <stab.h>
6*9700Slinton 
7*9700Slinton int proflg = 0;	/* are we generating profiling code? */
8*9700Slinton int strftn = 0;  /* is the current function one which returns a value */
9*9700Slinton int gdebug;
10*9700Slinton int fdefflag;  /* are we within a function definition ? */
11*9700Slinton char NULLNAME[8];
12*9700Slinton int labelno;
13*9700Slinton 
14*9700Slinton branch( n ){
15*9700Slinton 	/* output a branch to label n */
16*9700Slinton 	/* exception is an ordinary function branching to retlab: then, return */
17*9700Slinton 	if( n == retlab && !strftn ){
18*9700Slinton 		printf( "	ret\n" );
19*9700Slinton 		}
20*9700Slinton 	else printf( "	jbr 	L%d\n", n );
21*9700Slinton 	}
22*9700Slinton 
23*9700Slinton int lastloc = { -1 };
24*9700Slinton 
25*9700Slinton short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
26*9700Slinton #define LOG2SZ 9
27*9700Slinton 
28*9700Slinton defalign(n) {
29*9700Slinton 	/* cause the alignment to become a multiple of n */
30*9700Slinton 	n /= SZCHAR;
31*9700Slinton 	if( lastloc != PROG && n > 1 ) printf( "	.align	%d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
32*9700Slinton 	}
33*9700Slinton 
34*9700Slinton locctr( l ){
35*9700Slinton 	register temp;
36*9700Slinton 	/* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
37*9700Slinton 
38*9700Slinton 	if( l == lastloc ) return(l);
39*9700Slinton 	temp = lastloc;
40*9700Slinton 	lastloc = l;
41*9700Slinton 	switch( l ){
42*9700Slinton 
43*9700Slinton 	case PROG:
44*9700Slinton 		printf( "	.text\n" );
45*9700Slinton 		psline();
46*9700Slinton 		break;
47*9700Slinton 
48*9700Slinton 	case DATA:
49*9700Slinton 	case ADATA:
50*9700Slinton 		printf( "	.data\n" );
51*9700Slinton 		break;
52*9700Slinton 
53*9700Slinton 	case STRNG:
54*9700Slinton 		printf( "	.data	1\n" );
55*9700Slinton 		break;
56*9700Slinton 
57*9700Slinton 	case ISTRNG:
58*9700Slinton 		printf( "	.data	2\n" );
59*9700Slinton 		break;
60*9700Slinton 
61*9700Slinton 	case STAB:
62*9700Slinton 		printf( "	.stab\n" );
63*9700Slinton 		break;
64*9700Slinton 
65*9700Slinton 	default:
66*9700Slinton 		cerror( "illegal location counter" );
67*9700Slinton 		}
68*9700Slinton 
69*9700Slinton 	return( temp );
70*9700Slinton 	}
71*9700Slinton 
72*9700Slinton deflab( n ){
73*9700Slinton 	/* output something to define the current position as label n */
74*9700Slinton 	printf( "L%d:\n", n );
75*9700Slinton 	}
76*9700Slinton 
77*9700Slinton int crslab = 10;
78*9700Slinton 
79*9700Slinton getlab(){
80*9700Slinton 	/* return a number usable for a label */
81*9700Slinton 	return( ++crslab );
82*9700Slinton 	}
83*9700Slinton 
84*9700Slinton 
85*9700Slinton int ent_mask[] = {
86*9700Slinton 	0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0};
87*9700Slinton 
88*9700Slinton int reg_use = 11;
89*9700Slinton 
90*9700Slinton efcode(){
91*9700Slinton 	/* code for the end of a function */
92*9700Slinton 
93*9700Slinton 	if( strftn ){  /* copy output (in R2) to caller */
94*9700Slinton 		register NODE *l, *r;
95*9700Slinton 		register struct symtab *p;
96*9700Slinton 		register TWORD t;
97*9700Slinton 		register int j;
98*9700Slinton 		int i;
99*9700Slinton 
100*9700Slinton 		p = &stab[curftn];
101*9700Slinton 		t = p->stype;
102*9700Slinton 		t = DECREF(t);
103*9700Slinton 
104*9700Slinton 		deflab( retlab );
105*9700Slinton 
106*9700Slinton 		i = getlab();	/* label for return area */
107*9700Slinton #ifndef LCOMM
108*9700Slinton 		printf("	.data\n" );
109*9700Slinton 		printf("	.align	2\n" );
110*9700Slinton 		printf("L%d:	.space	%d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
111*9700Slinton 		printf("	.text\n" );
112*9700Slinton #else
113*9700Slinton 		{ int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR;
114*9700Slinton 		if (sz % sizeof (int))
115*9700Slinton 			sz += sizeof (int) - (sz % sizeof (int));
116*9700Slinton 		printf("	.lcomm	L%d,%d\n", i, sz);
117*9700Slinton 		}
118*9700Slinton #endif
119*9700Slinton 		psline();
120*9700Slinton 		printf("	movab	L%d,r1\n", i);
121*9700Slinton 
122*9700Slinton 		reached = 1;
123*9700Slinton 		l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
124*9700Slinton 		l->tn.rval = 1;  /* R1 */
125*9700Slinton 		l->tn.lval = 0;  /* no offset */
126*9700Slinton 		r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
127*9700Slinton 		r->tn.rval = 0;  /* R0 */
128*9700Slinton 		r->tn.lval = 0;
129*9700Slinton 		l = buildtree( UNARY MUL, l, NIL );
130*9700Slinton 		r = buildtree( UNARY MUL, r, NIL );
131*9700Slinton 		l = buildtree( ASSIGN, l, r );
132*9700Slinton 		l->in.op = FREE;
133*9700Slinton 		ecomp( l->in.left );
134*9700Slinton 		printf( "	movab	L%d,r0\n", i );
135*9700Slinton 		/* turn off strftn flag, so return sequence will be generated */
136*9700Slinton 		strftn = 0;
137*9700Slinton 		}
138*9700Slinton 	branch( retlab );
139*9700Slinton #ifndef VMS
140*9700Slinton 	printf( "	.set	L%d,0x%x\n", ftnno, ent_mask[reg_use] );
141*9700Slinton #else
142*9700Slinton 	printf( "	.set	L%d,%d	# Hex = 0x%x\n", ftnno, 0x3c| ent_mask[reg_use], ent_mask[reg_use]  );
143*9700Slinton 	/* KLS kludge, under VMS if you use regs 2-5, you must save them. */
144*9700Slinton #endif
145*9700Slinton 	reg_use = 11;
146*9700Slinton 	p2bend();
147*9700Slinton 	fdefflag = 0;
148*9700Slinton 	}
149*9700Slinton 
150*9700Slinton int ftlab1, ftlab2;
151*9700Slinton 
152*9700Slinton bfcode( a, n ) int a[]; {
153*9700Slinton 	/* code for the beginning of a function; a is an array of
154*9700Slinton 		indices in stab for the arguments; n is the number */
155*9700Slinton 	register i;
156*9700Slinton 	register temp;
157*9700Slinton 	register struct symtab *p;
158*9700Slinton 	int off;
159*9700Slinton 	char *toreg();
160*9700Slinton 
161*9700Slinton 	locctr( PROG );
162*9700Slinton 	p = &stab[curftn];
163*9700Slinton 	printf( "	.align	1\n");
164*9700Slinton 	defnam( p );
165*9700Slinton 	temp = p->stype;
166*9700Slinton 	temp = DECREF(temp);
167*9700Slinton 	strftn = (temp==STRTY) || (temp==UNIONTY);
168*9700Slinton 
169*9700Slinton 	retlab = getlab();
170*9700Slinton 
171*9700Slinton 	/* routine prolog */
172*9700Slinton 
173*9700Slinton 	printf( "	.word	L%d\n", ftnno);
174*9700Slinton 	if (gdebug) {
175*9700Slinton #ifdef STABDOT
176*9700Slinton 		pstabdot(N_SLINE, lineno);
177*9700Slinton #else
178*9700Slinton 		pstab(NULLNAME, N_SLINE);
179*9700Slinton 		printf("0,%d,LL%d\n", lineno, labelno);
180*9700Slinton 		printf("LL%d:\n", labelno++);
181*9700Slinton #endif
182*9700Slinton 	}
183*9700Slinton 	ftlab1 = getlab();
184*9700Slinton 	ftlab2 = getlab();
185*9700Slinton 	printf( "	jbr 	L%d\n", ftlab1);
186*9700Slinton 	printf( "L%d:\n", ftlab2);
187*9700Slinton 	if( proflg ) {	/* profile code */
188*9700Slinton 		i = getlab();
189*9700Slinton 		printf("	movab	L%d,r0\n", i);
190*9700Slinton 		printf("	jsb 	mcount\n");
191*9700Slinton 		printf("	.data\n");
192*9700Slinton 		printf("	.align	2\n");
193*9700Slinton 		printf("L%d:	.long	0\n", i);
194*9700Slinton 		printf("	.text\n");
195*9700Slinton 		psline();
196*9700Slinton 		}
197*9700Slinton 
198*9700Slinton 	off = ARGINIT;
199*9700Slinton 
200*9700Slinton 	for( i=0; i<n; ++i ){
201*9700Slinton 		p = &stab[a[i]];
202*9700Slinton 		if( p->sclass == REGISTER ){
203*9700Slinton 			temp = p->offset;  /* save register number */
204*9700Slinton 			p->sclass = PARAM;  /* forget that it is a register */
205*9700Slinton 			p->offset = NOOFFSET;
206*9700Slinton 			oalloc( p, &off );
207*9700Slinton /*tbl*/		printf( "	%s	%d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp );
208*9700Slinton 			p->offset = temp;  /* remember register number */
209*9700Slinton 			p->sclass = REGISTER;   /* remember that it is a register */
210*9700Slinton 			}
211*9700Slinton 		else if( p->stype == STRTY || p->stype == UNIONTY ) {
212*9700Slinton 			p->offset = NOOFFSET;
213*9700Slinton 			if( oalloc( p, &off ) ) cerror( "bad argument" );
214*9700Slinton 			SETOFF( off, ALSTACK );
215*9700Slinton 			}
216*9700Slinton 		else {
217*9700Slinton 			if( oalloc( p, &off ) ) cerror( "bad argument" );
218*9700Slinton 			}
219*9700Slinton 
220*9700Slinton 		}
221*9700Slinton 	fdefflag = 1;
222*9700Slinton 	}
223*9700Slinton 
224*9700Slinton bccode(){ /* called just before the first executable statment */
225*9700Slinton 		/* by now, the automatics and register variables are allocated */
226*9700Slinton 	SETOFF( autooff, SZINT );
227*9700Slinton 	/* set aside store area offset */
228*9700Slinton 	p2bbeg( autooff, regvar );
229*9700Slinton 	reg_use = (reg_use > regvar ? regvar : reg_use);
230*9700Slinton 	}
231*9700Slinton 
232*9700Slinton ejobcode( flag ){
233*9700Slinton 	/* called just before final exit */
234*9700Slinton 	/* flag is 1 if errors, 0 if none */
235*9700Slinton 	}
236*9700Slinton 
237*9700Slinton aobeg(){
238*9700Slinton 	/* called before removing automatics from stab */
239*9700Slinton 	}
240*9700Slinton 
241*9700Slinton aocode(p) struct symtab *p; {
242*9700Slinton 	/* called when automatic p removed from stab */
243*9700Slinton 	}
244*9700Slinton 
245*9700Slinton aoend(){
246*9700Slinton 	/* called after removing all automatics from stab */
247*9700Slinton 	}
248*9700Slinton 
249*9700Slinton defnam( p ) register struct symtab *p; {
250*9700Slinton 	/* define the current location as the name p->sname */
251*9700Slinton 
252*9700Slinton 	if( p->sclass == EXTDEF ){
253*9700Slinton 		printf( "	.globl	%s\n", exname( p->sname ) );
254*9700Slinton 		}
255*9700Slinton 	if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
256*9700Slinton 	else printf( "%s:\n", exname( p->sname ) );
257*9700Slinton 
258*9700Slinton 	}
259*9700Slinton 
260*9700Slinton bycode( t, i ){
261*9700Slinton #ifdef ASSTRINGS
262*9700Slinton static	int	lastoctal = 0;
263*9700Slinton #endif
264*9700Slinton 
265*9700Slinton 	/* put byte i+1 in a string */
266*9700Slinton 
267*9700Slinton #ifdef ASSTRINGS
268*9700Slinton 
269*9700Slinton 	i &= 077;
270*9700Slinton 	if ( t < 0 ){
271*9700Slinton 		if ( i != 0 )	printf( "\"\n" );
272*9700Slinton 	} else {
273*9700Slinton 		if ( i == 0 ) printf("\t.ascii\t\"");
274*9700Slinton 		if ( t == '\\' || t == '"'){
275*9700Slinton 			lastoctal = 0;
276*9700Slinton 			printf("\\%c", t);
277*9700Slinton 		}
278*9700Slinton 			/*
279*9700Slinton 			 *	We escape the colon in strings so that
280*9700Slinton 			 *	c2 will, in its infinite wisdom, interpret
281*9700Slinton 			 *	the characters preceding the colon as a label.
282*9700Slinton 			 *	If we didn't escape the colon, c2 would
283*9700Slinton 			 *	throw away any trailing blanks or tabs after
284*9700Slinton 			 *	the colon, but reconstruct a assembly
285*9700Slinton 			 *	language semantically correct program.
286*9700Slinton 			 *	C2 hasn't been taught about strings.
287*9700Slinton 			 */
288*9700Slinton 		else if ( t == ':' || t < 040 || t >= 0177 ){
289*9700Slinton 			lastoctal++;
290*9700Slinton 			printf("\\%o",t);
291*9700Slinton 		}
292*9700Slinton 		else if ( lastoctal && '0' <= t && t <= '9' ){
293*9700Slinton 			lastoctal = 0;
294*9700Slinton 			printf("\"\n\t.ascii\t\"%c", t );
295*9700Slinton 		}
296*9700Slinton 		else
297*9700Slinton 		{
298*9700Slinton 			lastoctal = 0;
299*9700Slinton 			putchar(t);
300*9700Slinton 		}
301*9700Slinton 		if ( i == 077 ) printf("\"\n");
302*9700Slinton 	}
303*9700Slinton #else
304*9700Slinton 
305*9700Slinton 	i &= 07;
306*9700Slinton 	if( t < 0 ){ /* end of the string */
307*9700Slinton 		if( i != 0 ) printf( "\n" );
308*9700Slinton 		}
309*9700Slinton 
310*9700Slinton 	else { /* stash byte t into string */
311*9700Slinton 		if( i == 0 ) printf( "	.byte	" );
312*9700Slinton 		else printf( "," );
313*9700Slinton 		printf( "0x%x", t );
314*9700Slinton 		if( i == 07 ) printf( "\n" );
315*9700Slinton 		}
316*9700Slinton #endif
317*9700Slinton 	}
318*9700Slinton 
319*9700Slinton zecode( n ){
320*9700Slinton 	/* n integer words of zeros */
321*9700Slinton 	OFFSZ temp;
322*9700Slinton 	if( n <= 0 ) return;
323*9700Slinton 	printf( "	.space	%d\n", (SZINT/SZCHAR)*n );
324*9700Slinton 	temp = n;
325*9700Slinton 	inoff += temp*SZINT;
326*9700Slinton 	}
327*9700Slinton 
328*9700Slinton fldal( t ) unsigned t; { /* return the alignment of field of type t */
329*9700Slinton 	uerror( "illegal field type" );
330*9700Slinton 	return( ALINT );
331*9700Slinton 	}
332*9700Slinton 
333*9700Slinton fldty( p ) struct symtab *p; { /* fix up type of field p */
334*9700Slinton 	;
335*9700Slinton 	}
336*9700Slinton 
337*9700Slinton where(c){ /* print location of error  */
338*9700Slinton 	/* c is either 'u', 'c', or 'w' */
339*9700Slinton 	/* GCOS version */
340*9700Slinton 	fprintf( stderr, "%s, line %d: ", ftitle, lineno );
341*9700Slinton 	}
342*9700Slinton 
343*9700Slinton 
344*9700Slinton /* tbl - toreg() returns a pointer to a char string
345*9700Slinton 		  which is the correct  "register move" for the passed type
346*9700Slinton  */
347*9700Slinton struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
348*9700Slinton 	{
349*9700Slinton 	CHAR, "cvtbl",
350*9700Slinton 	SHORT, "cvtwl",
351*9700Slinton 	INT, "movl",
352*9700Slinton 	LONG, "movl",
353*9700Slinton 	FLOAT, "movf",
354*9700Slinton 	DOUBLE, "movd",
355*9700Slinton 	UCHAR,	"movzbl",
356*9700Slinton 	USHORT,	"movzwl",
357*9700Slinton 	UNSIGNED,	"movl",
358*9700Slinton 	ULONG,	"movl",
359*9700Slinton 	-1, ""
360*9700Slinton 	};
361*9700Slinton 
362*9700Slinton char
363*9700Slinton *toreg(type)
364*9700Slinton 	TWORD type;
365*9700Slinton {
366*9700Slinton 	struct type_move *p;
367*9700Slinton 
368*9700Slinton 	for ( p=toreg_strs; p->fromtype > 0; p++)
369*9700Slinton 		if (p->fromtype == type) return(p->tostrng);
370*9700Slinton 
371*9700Slinton 	/* type not found, must be a pointer type */
372*9700Slinton 	return("movl");
373*9700Slinton }
374*9700Slinton /* tbl */
375*9700Slinton 
376*9700Slinton 
377*9700Slinton main( argc, argv ) char *argv[]; {
378*9700Slinton #ifdef BUFSTDERR
379*9700Slinton 	char errbuf[BUFSIZ];
380*9700Slinton 	setbuf(stderr, errbuf);
381*9700Slinton #endif
382*9700Slinton 	return(mainp1( argc, argv ));
383*9700Slinton 	}
384*9700Slinton 
385*9700Slinton struct sw heapsw[SWITSZ];	/* heap for switches */
386*9700Slinton 
387*9700Slinton genswitch(p,n) register struct sw *p;{
388*9700Slinton 	/*	p points to an array of structures, each consisting
389*9700Slinton 		of a constant value and a label.
390*9700Slinton 		The first is >=0 if there is a default label;
391*9700Slinton 		its value is the label number
392*9700Slinton 		The entries p[1] to p[n] are the nontrivial cases
393*9700Slinton 		*/
394*9700Slinton 	register i;
395*9700Slinton 	register CONSZ j, range;
396*9700Slinton 	register dlab, swlab;
397*9700Slinton 
398*9700Slinton 	range = p[n].sval-p[1].sval;
399*9700Slinton 
400*9700Slinton 	if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
401*9700Slinton 
402*9700Slinton 		swlab = getlab();
403*9700Slinton 		dlab = p->slab >= 0 ? p->slab : getlab();
404*9700Slinton 
405*9700Slinton 		/* already in r0 */
406*9700Slinton 		printf("	casel	r0,$%ld,$%ld\n", p[1].sval, range);
407*9700Slinton 		printf("L%d:\n", swlab);
408*9700Slinton 		for( i=1,j=p[1].sval; i<=n; j++) {
409*9700Slinton 			printf("	.word	L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
410*9700Slinton 				swlab);
411*9700Slinton 			}
412*9700Slinton 
413*9700Slinton 		if( p->slab >= 0 ) branch( dlab );
414*9700Slinton 		else printf("L%d:\n", dlab);
415*9700Slinton 		return;
416*9700Slinton 
417*9700Slinton 		}
418*9700Slinton 
419*9700Slinton 	if( n>8 ) {	/* heap switch */
420*9700Slinton 
421*9700Slinton 		heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
422*9700Slinton 		makeheap(p, n, 1);	/* build heap */
423*9700Slinton 
424*9700Slinton 		walkheap(1, n);	/* produce code */
425*9700Slinton 
426*9700Slinton 		if( p->slab >= 0 )
427*9700Slinton 			branch( dlab );
428*9700Slinton 		else
429*9700Slinton 			printf("L%d:\n", dlab);
430*9700Slinton 		return;
431*9700Slinton 	}
432*9700Slinton 
433*9700Slinton 	/* debugging code */
434*9700Slinton 
435*9700Slinton 	/* out for the moment
436*9700Slinton 	if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
437*9700Slinton 	*/
438*9700Slinton 
439*9700Slinton 	/* simple switch code */
440*9700Slinton 
441*9700Slinton 	for( i=1; i<=n; ++i ){
442*9700Slinton 		/* already in r0 */
443*9700Slinton 
444*9700Slinton 		printf( "	cmpl	r0,$" );
445*9700Slinton 		printf( CONFMT, p[i].sval );
446*9700Slinton 		printf( "\n	jeql	L%d\n", p[i].slab );
447*9700Slinton 		}
448*9700Slinton 
449*9700Slinton 	if( p->slab>=0 ) branch( p->slab );
450*9700Slinton 	}
451*9700Slinton 
452*9700Slinton makeheap(p, m, n)
453*9700Slinton register struct sw *p;
454*9700Slinton {
455*9700Slinton 	register int q;
456*9700Slinton 
457*9700Slinton 	q = select(m);
458*9700Slinton 	heapsw[n] = p[q];
459*9700Slinton 	if( q>1 ) makeheap(p, q-1, 2*n);
460*9700Slinton 	if( q<m ) makeheap(p+q, m-q, 2*n+1);
461*9700Slinton }
462*9700Slinton 
463*9700Slinton select(m) {
464*9700Slinton 	register int l,i,k;
465*9700Slinton 
466*9700Slinton 	for(i=1; ; i*=2)
467*9700Slinton 		if( (i-1) > m ) break;
468*9700Slinton 	l = ((k = i/2 - 1) + 1)/2;
469*9700Slinton 	return( l + (m-k < l ? m-k : l));
470*9700Slinton }
471*9700Slinton 
472*9700Slinton walkheap(start, limit)
473*9700Slinton {
474*9700Slinton 	int label;
475*9700Slinton 
476*9700Slinton 
477*9700Slinton 	if( start > limit ) return;
478*9700Slinton 	printf("	cmpl	r0,$%d\n",  heapsw[start].sval);
479*9700Slinton 	printf("	jeql	L%d\n", heapsw[start].slab);
480*9700Slinton 	if( (2*start) > limit ) {
481*9700Slinton 		printf("	jbr 	L%d\n", heapsw[0].slab);
482*9700Slinton 		return;
483*9700Slinton 	}
484*9700Slinton 	if( (2*start+1) <= limit ) {
485*9700Slinton 		label = getlab();
486*9700Slinton 		printf("	jgtr	L%d\n", label);
487*9700Slinton 	} else
488*9700Slinton 		printf("	jgtr	L%d\n", heapsw[0].slab);
489*9700Slinton 	walkheap( 2*start, limit);
490*9700Slinton 	if( (2*start+1) <= limit ) {
491*9700Slinton 		printf("L%d:\n", label);
492*9700Slinton 		walkheap( 2*start+1, limit);
493*9700Slinton 	}
494*9700Slinton }
495