xref: /csrg-svn/old/pcc/ccom.tahoe/local2.c (revision 32884)
125828Ssam #ifndef lint
2*32884Sdonn static char sccsid[] = "@(#)local2.c	1.22 (Berkeley) 12/10/87";
325828Ssam #endif
425828Ssam 
526076Ssam # include "pass2.h"
626076Ssam # include <ctype.h>
726162Ssam 
826162Ssam # define putstr(s)	fputs((s), stdout)
929672Ssam # define ISCHAR(p)	(p->in.type == UCHAR || p->in.type == CHAR)
1026162Ssam 
1125828Ssam # ifdef FORT
1225828Ssam int ftlab1, ftlab2;
1325828Ssam # endif
1425828Ssam /* a lot of the machine dependent parts of the second pass */
1525828Ssam 
1625828Ssam # define BITMASK(n) ((1L<<n)-1)
1725828Ssam 
1825828Ssam # ifndef ONEPASS
1925828Ssam where(c){
2025828Ssam 	fprintf( stderr, "%s, line %d: ", filename, lineno );
2125828Ssam 	}
2225828Ssam # endif
2325828Ssam 
2425828Ssam lineid( l, fn ) char *fn; {
2525828Ssam 	/* identify line l and file fn */
2625828Ssam 	printf( "#	line %d, file %s\n", l, fn );
2725828Ssam 	}
2825828Ssam 
2925828Ssam int ent_mask;
3025828Ssam 
3125828Ssam eobl2(){
3225828Ssam 	register OFFSZ spoff;	/* offset from stack pointer */
3325828Ssam #ifndef FORT
3425828Ssam 	extern int ftlab1, ftlab2;
3525828Ssam #endif
3625828Ssam 
3725828Ssam 	spoff = maxoff;
3825828Ssam 	spoff /= SZCHAR;
3925828Ssam 	SETOFF(spoff,4);
4025828Ssam #ifdef FORT
4125828Ssam #ifndef FLEXNAMES
4225828Ssam 	printf( "	.set	.F%d,%d\n", ftnno, spoff );
4325828Ssam #else
4425828Ssam 	/* SHOULD BE L%d ... ftnno but must change pc/f77 */
4525828Ssam 	printf( "	.set	LF%d,%d\n", ftnno, spoff );
4625828Ssam #endif
4725828Ssam 	printf( "	.set	LWM%d,0x%x\n", ftnno, ent_mask&0x1ffc|0x1000);
4825828Ssam #else
4925828Ssam 	printf( "	.set	L%d,0x%x\n", ftnno, ent_mask&0x1ffc);
5025828Ssam 	printf( "L%d:\n", ftlab1);
5125828Ssam 	if( maxoff > AUTOINIT )
5225828Ssam 		printf( "	subl3	$%d,fp,sp\n", spoff);
5325828Ssam 	printf( "	jbr 	L%d\n", ftlab2);
5425828Ssam #endif
5525828Ssam 	ent_mask = 0;
5625828Ssam 	maxargs = -1;
5725828Ssam 	}
5825828Ssam 
5925828Ssam struct hoptab { int opmask; char * opstring; } ioptab[] = {
6025828Ssam 
6125828Ssam 	PLUS,	"add",
6225828Ssam 	MINUS,	"sub",
6325828Ssam 	MUL,	"mul",
6425828Ssam 	DIV,	"div",
6525828Ssam 	MOD,	"div",
6625828Ssam 	OR,	"or",
6725828Ssam 	ER,	"xor",
6825828Ssam 	AND,	"and",
6925828Ssam 	-1,	""    };
7025828Ssam 
7125828Ssam hopcode( f, o ){
7225828Ssam 	/* output the appropriate string from the above table */
7325828Ssam 
7425828Ssam 	register struct hoptab *q;
7525828Ssam 
7625828Ssam 	if(asgop(o))
7725828Ssam 		o = NOASG o;
7825828Ssam 	for( q = ioptab;  q->opmask>=0; ++q ){
7925828Ssam 		if( q->opmask == o ){
8025828Ssam 			if(f == 'E')
8125828Ssam 				printf( "e%s", q->opstring);
8225828Ssam 			else
8325828Ssam 				printf( "%s%c", q->opstring, tolower(f));
8425828Ssam 			return;
8525828Ssam 			}
8625828Ssam 		}
8725828Ssam 	cerror( "no hoptab for %s", opst[o] );
8825828Ssam 	}
8925828Ssam 
9025828Ssam char *
9125828Ssam rnames[] = {  /* keyed to register number tokens */
9225828Ssam 
9325828Ssam 	"r0", "r1",
9425828Ssam 	"r2", "r3", "r4", "r5",
9525828Ssam 	"r6", "r7", "r8", "r9", "r10", "r11",
9625828Ssam 	"r12", "fp", "sp", "pc",
9725828Ssam 	};
9825828Ssam 
9925828Ssam /* output register name and update entry mask */
10025828Ssam char *
10125828Ssam rname(r)
10225828Ssam 	register int r;
10325828Ssam {
10425828Ssam 
10525828Ssam 	ent_mask |= 1<<r;
10625828Ssam 	return(rnames[r]);
10725828Ssam }
10825828Ssam 
10925828Ssam int rstatus[] = {
11025828Ssam 	SAREG|STAREG, SAREG|STAREG,
11125828Ssam 	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
11225828Ssam 	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
11325828Ssam 	SAREG, SAREG, SAREG, SAREG,
11425828Ssam 	};
11525828Ssam 
11625828Ssam tlen(p) NODE *p;
11725828Ssam {
11825828Ssam 	switch(p->in.type) {
11925828Ssam 		case CHAR:
12025828Ssam 		case UCHAR:
12125828Ssam 			return(1);
12225828Ssam 
12325828Ssam 		case SHORT:
12425828Ssam 		case USHORT:
12525828Ssam 			return(2);
12625828Ssam 
12725828Ssam 		case DOUBLE:
12825828Ssam 			return(8);
12925828Ssam 
13025828Ssam 		default:
13125828Ssam 			return(4);
13225828Ssam 		}
13325828Ssam }
13425828Ssam 
13530360Ssam anyfloat(p, q)
13630360Ssam 	NODE *p, *q;
13730360Ssam {
13830360Ssam 	register TWORD tp, tq;
13930360Ssam 
14030360Ssam 	tp = p->in.type;
14130360Ssam 	tq = q->in.type;
14230360Ssam 	return (tp == FLOAT || tp == DOUBLE || tq == FLOAT || tq == DOUBLE);
14330360Ssam }
14430360Ssam 
14525828Ssam prtype(n) NODE *n;
14625828Ssam {
14725828Ssam 	switch (n->in.type)
14825828Ssam 		{
14925828Ssam 
15025828Ssam 		case DOUBLE:
15126162Ssam 			putchar('d');
15225828Ssam 			return;
15325828Ssam 
15425828Ssam 		case FLOAT:
15526162Ssam 			putchar('f');
15625828Ssam 			return;
15725828Ssam 
15825828Ssam 		case INT:
15925828Ssam 		case UNSIGNED:
16026162Ssam 			putchar('l');
16125828Ssam 			return;
16225828Ssam 
16325828Ssam 		case SHORT:
16425828Ssam 		case USHORT:
16526162Ssam 			putchar('w');
16625828Ssam 			return;
16725828Ssam 
16825828Ssam 		case CHAR:
16925828Ssam 		case UCHAR:
17026162Ssam 			putchar('b');
17125828Ssam 			return;
17225828Ssam 
17325828Ssam 		default:
17425828Ssam 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
17525828Ssam 			else {
17626162Ssam 				putchar('l');
17725828Ssam 				return;
17825828Ssam 				}
17925828Ssam 		}
18025828Ssam }
18125828Ssam 
18225828Ssam zzzcode( p, c ) register NODE *p; {
18325828Ssam 	register int m;
18425828Ssam 	int val;
18525828Ssam 	switch( c ){
18625828Ssam 
18725828Ssam 	case 'N':  /* logical ops, turned into 0-1 */
18825828Ssam 		/* use register given by register 1 */
18925828Ssam 		cbgen( 0, m=getlab(), 'I' );
19025828Ssam 		deflab( p->bn.label );
19125828Ssam 		printf( "	clrl	%s\n", rname(getlr( p, '1' )->tn.rval) );
19225828Ssam 		deflab( m );
19325828Ssam 		return;
19425828Ssam 
19525828Ssam 	case 'P':
19625828Ssam 		cbgen( p->in.op, p->bn.label, c );
19725828Ssam 		return;
19825828Ssam 
19932876Sdonn 	case 'G':	/* i *= f; asgops with int lhs and float rhs */
20025828Ssam 		{
20132876Sdonn 		register NODE *l, *r, *s;
20232876Sdonn 		int lt, rt;
20325828Ssam 
20432876Sdonn 		l = p->in.left;
20532876Sdonn 		r = p->in.right;
20632876Sdonn 		s = talloc();
20732876Sdonn 		rt = r->in.type;
20832876Sdonn 		lt = l->in.type;
20925828Ssam 
21032876Sdonn 		if (lt != INT && lt != UNSIGNED) {
21132876Sdonn 			s->in.op = SCONV;
21232876Sdonn 			s->in.left = l;
21332876Sdonn 			s->in.type = ISUNSIGNED(lt) ? UNSIGNED : INT;
21432876Sdonn 			zzzcode(s, 'U');
21532876Sdonn 			putstr("\n\t");
21625828Ssam 		}
21732876Sdonn 
21832876Sdonn 		if (ISUNSIGNED(lt)) {
21932876Sdonn 			s->in.op = SCONV;
22032876Sdonn 			s->in.left = lt == UNSIGNED ? l : resc;
22132876Sdonn 			s->in.type = rt;
22232876Sdonn 			unsigned_to_float(s);
22332876Sdonn 		} else {
22432876Sdonn 			putstr("cvl");
22532876Sdonn 			prtype(r);
22632876Sdonn 			putchar('\t');
22732876Sdonn 			adrput(lt == INT ? l : resc);
22832876Sdonn 		}
22932876Sdonn 		putstr("\n\t");
23032876Sdonn 
23132876Sdonn 		hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
23226162Ssam 		putchar('\t');
23325828Ssam 		adrput(r);
23432876Sdonn 
23532876Sdonn 		if (ISUNSIGNED(lt)) {
23632876Sdonn 			putstr("\n\t");
23732876Sdonn 			s->in.op = SCONV;
23832876Sdonn 			s->in.left = r;		/* we need only the type */
23932876Sdonn 			s->in.type = UNSIGNED;
24032876Sdonn 			float_to_unsigned(s);
24132876Sdonn 		} else {
24232876Sdonn 			putstr("\n\tcv");
24332876Sdonn 			prtype(r);
24432876Sdonn 			putstr("l\t");
24532876Sdonn 			if (lt == INT)
24632876Sdonn 				adrput(l);
24732876Sdonn 			else
24832876Sdonn 				adrput(resc);
24932876Sdonn 		}
25032876Sdonn 		if (lt != INT) {
25132876Sdonn 			putstr("\n\t");
25232876Sdonn 			s->in.op = ASSIGN;
25332876Sdonn 			s->in.left = l;
25432876Sdonn 			s->in.right = resc;
25532876Sdonn 			s->in.type = lt;
25632876Sdonn 			zzzcode(s, 'U');
25732876Sdonn 		}
25832876Sdonn 
25932876Sdonn 		s->in.op = FREE;
26025828Ssam 		return;
26125828Ssam 		}
26225828Ssam 
26325828Ssam 	case 'B':	/* get oreg value in temp register for shift */
26425828Ssam 		{
26525828Ssam 		register NODE *r;
26625828Ssam 		if (xdebug) eprint(p, 0, &val, &val);
26725828Ssam 		r = p->in.right;
26825828Ssam 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
26926162Ssam 			putstr("movl");
27025828Ssam 		else {
27126162Ssam 			putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
27225828Ssam 			prtype(r);
27326162Ssam 			putchar('l');
27425828Ssam 			}
27525828Ssam 		return;
27625828Ssam 		}
27725828Ssam 
27825828Ssam 	case 'C':	/* num bytes pushed on arg stack */
27925828Ssam 		{
28025828Ssam 		extern int gc_numbytes;
28125828Ssam 		extern int xdebug;
28225828Ssam 
28325828Ssam 		if (xdebug) printf("->%d<-",gc_numbytes);
28425828Ssam 
28525828Ssam 		printf("call%c	$%d",
28625828Ssam 		 (p->in.left->in.op==ICON && gc_numbytes<60)?'f':'s',
28725828Ssam 		 gc_numbytes+4);
28825828Ssam 		/* dont change to double (here's the only place to catch it) */
28925828Ssam 		if(p->in.type == FLOAT)
29025828Ssam 			rtyflg = 1;
29125828Ssam 		return;
29225828Ssam 		}
29325828Ssam 
29425828Ssam 	case 'D':	/* INCR and DECR */
29532876Sdonn 		zzzcode(p->in.left, 'U');
29626162Ssam 		putstr("\n	");
29725828Ssam 
29825828Ssam 	case 'E':	/* INCR and DECR, FOREFF */
29925828Ssam  		if (p->in.right->tn.lval == 1)
30025828Ssam 			{
30126162Ssam 			putstr(p->in.op == INCR ? "inc" : "dec");
30225828Ssam 			prtype(p->in.left);
30326162Ssam 			putchar('\t');
30425828Ssam 			adrput(p->in.left);
30525828Ssam 			return;
30625828Ssam 			}
30726162Ssam 		putstr(p->in.op == INCR ? "add" : "sub");
30825828Ssam 		prtype(p->in.left);
30926162Ssam 		putstr("2	");
31025828Ssam 		adrput(p->in.right);
31126162Ssam 		putchar(',');
31225828Ssam 		adrput(p->in.left);
31325828Ssam 		return;
31425828Ssam 
31525828Ssam 	case 'F':	/* masked constant for fields */
31625947Ssam 		printf(ACONFMT, (p->in.right->tn.lval&((1<<fldsz)-1))<<fldshf);
31725828Ssam 		return;
31825828Ssam 
319*32884Sdonn 	case 'I':	/* produce value of bitfield assignment */
320*32884Sdonn 			/* avoid shifts -- shifts are SLOW on this machine */
321*32884Sdonn 		{
322*32884Sdonn 			register NODE *r = p->in.right;
323*32884Sdonn 			if(r->in.op == ICON && r->tn.name[0] == '\0') {
324*32884Sdonn 				putstr("movl\t");
325*32884Sdonn 				printf(ACONFMT, r->tn.lval & ((1<<fldsz)-1));
326*32884Sdonn 				}
327*32884Sdonn 			else {
328*32884Sdonn 				putstr("andl3\t");
329*32884Sdonn 				printf(ACONFMT, (1 << fldsz) - 1);
330*32884Sdonn 				putchar(',');
331*32884Sdonn 				adrput(r);
332*32884Sdonn 				}
333*32884Sdonn 			putchar(',');
334*32884Sdonn 			adrput(resc);
335*32884Sdonn 			break;
336*32884Sdonn 			}
337*32884Sdonn 
33825828Ssam 	case 'H':	/* opcode for shift */
33925828Ssam 		if(p->in.op == LS || p->in.op == ASG LS)
34026162Ssam 			putstr("shll");
34125828Ssam 		else if(ISUNSIGNED(p->in.left->in.type))
34226162Ssam 			putstr("shrl");
34325828Ssam 		else
34426162Ssam 			putstr("shar");
34525828Ssam 		return;
34625828Ssam 
34725828Ssam 	case 'L':	/* type of left operand */
34825828Ssam 	case 'R':	/* type of right operand */
34925828Ssam 		{
35025828Ssam 		register NODE *n;
35125828Ssam 		extern int xdebug;
35225828Ssam 
35325828Ssam 		n = getlr ( p, c);
35425828Ssam 		if (xdebug) printf("->%d<-", n->in.type);
35525828Ssam 
35625828Ssam 		prtype(n);
35725828Ssam 		return;
35825828Ssam 		}
35925828Ssam 
36030360Ssam 	case 'M': {  /* initiate ediv for mod and unsigned div */
36125828Ssam 		register char *r;
36225828Ssam 		m = getlr(p, '1')->tn.rval;
36325828Ssam 		r = rname(m);
36425828Ssam 		printf("\tclrl\t%s\n\tmovl\t", r);
36525828Ssam 		adrput(p->in.left);
36625828Ssam 		printf(",%s\n", rname(m+1));
36725828Ssam 		if(!ISUNSIGNED(p->in.type)) { 	/* should be MOD */
36825828Ssam 			m = getlab();
36925828Ssam 			printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r);
37025828Ssam 			deflab(m);
37125828Ssam 		}
37225828Ssam 		return;
37330360Ssam 	}
37425828Ssam 
37530360Ssam 	case 'T': {	/* rounded structure length for arguments */
37630360Ssam 		int size = p->stn.stsize;
37725828Ssam 		SETOFF( size, 4);
37825828Ssam 		printf("movab	-%d(sp),sp", size);
37925828Ssam 		return;
38030360Ssam 	}
38125828Ssam 
38225828Ssam 	case 'S':  /* structure assignment */
38325977Ssam 		stasg(p);
38425977Ssam 		break;
38525828Ssam 
38629672Ssam 	case 'X':	/* multiplication for short and char */
38729672Ssam 		if (ISUNSIGNED(p->in.left->in.type))
38829672Ssam 			printf("\tmovz");
38929672Ssam 		else
39029672Ssam 			printf("\tcvt");
39129672Ssam 		zzzcode(p, 'L');
39229672Ssam 		printf("l\t");
39329672Ssam 		adrput(p->in.left);
39429672Ssam 		printf(",");
39529672Ssam 		adrput(&resc[0]);
39629672Ssam 		printf("\n");
39729672Ssam 		if (ISUNSIGNED(p->in.right->in.type))
39829672Ssam 			printf("\tmovz");
39929672Ssam 		else
40029672Ssam 			printf("\tcvt");
40129672Ssam 		zzzcode(p, 'R');
40229672Ssam 		printf("l\t");
40329672Ssam 		adrput(p->in.right);
40429672Ssam 		printf(",");
40529672Ssam 		adrput(&resc[1]);
40629672Ssam 		printf("\n");
40729672Ssam 		return;
40829672Ssam 
40930360Ssam 	case 'U':		/* SCONV */
41030360Ssam 	case 'V':		/* SCONV with FORCC */
41130360Ssam 		sconv(p, c == 'V');
41230360Ssam 		break;
41330360Ssam 
41432879Sdonn 	case 'W': {		/* SCONV or ASSIGN float/double => unsigned */
41532879Sdonn 		NODE *src = p->in.op == SCONV ? p->in.left : p->in.right;
41632879Sdonn 
41732876Sdonn 		putstr("ld");
41832879Sdonn 		prtype(src);
41932876Sdonn 		putchar('\t');
42032879Sdonn 		adrput(src);
42132876Sdonn 		putstr("\n\t");
42232876Sdonn 		float_to_unsigned(p);
42332876Sdonn 		break;
42432879Sdonn 	}
42532876Sdonn 
42632879Sdonn 	case 'Y':		/* SCONV or ASSIGN unsigned => float/double */
42732876Sdonn 		unsigned_to_float(p);	/* stores into accumulator */
42832876Sdonn 		putstr("\n\tst");
42932876Sdonn 		prtype(p);
43032876Sdonn 		putchar('\t');
43132879Sdonn 		if (p->in.op == SCONV)
43232879Sdonn 			adrput(resc);
43332879Sdonn 		else
43432879Sdonn 			adrput(p->in.left);
43532879Sdonn 		rtyflg = 1;
43632876Sdonn 		break;
43732876Sdonn 
43830360Ssam 	case 'Z':
43930360Ssam 		p = p->in.right;
44030360Ssam 		switch (p->in.type) {
44130360Ssam 		case SHORT: {
44230360Ssam 			short w = p->tn.lval;
44330360Ssam 			p->tn.lval = w;
44430360Ssam 			break;
44530360Ssam 		}
44630360Ssam 		case CHAR: {
44730360Ssam 			char c = p->tn.lval;
44830360Ssam 			p->tn.lval = c;
44930360Ssam 			break;
45030360Ssam 		}
45130360Ssam 		}
45230360Ssam 		printf("$%d", p->tn.lval);
45330360Ssam 		break;
45430360Ssam 
45525977Ssam 	default:
45625977Ssam 		cerror( "illegal zzzcode" );
45725977Ssam 	}
45830360Ssam }
45925828Ssam 
46025977Ssam #define	MOVB(dst, src, off) { \
46126162Ssam 	putstr("\tmovb\t"); upput(src, off); putchar(','); \
46225977Ssam 	upput(dst, off); putchar('\n'); \
46325977Ssam }
46425977Ssam #define	MOVW(dst, src, off) { \
46526162Ssam 	putstr("\tmovw\t"); upput(src, off); putchar(','); \
46625977Ssam 	upput(dst, off); putchar('\n'); \
46725977Ssam }
46825977Ssam #define	MOVL(dst, src, off) { \
46926162Ssam 	putstr("\tmovl\t"); upput(src, off); putchar(','); \
47025977Ssam 	upput(dst, off); putchar('\n'); \
47125977Ssam }
47225977Ssam /*
47325977Ssam  * Generate code for a structure assignment.
47425977Ssam  */
47525977Ssam stasg(p)
47625977Ssam 	register NODE *p;
47725977Ssam {
47825977Ssam 	register NODE *l, *r;
47925977Ssam 	register int size;
48025828Ssam 
48125977Ssam 	switch (p->in.op) {
48225977Ssam 	case STASG:			/* regular assignment */
48325977Ssam 		l = p->in.left;
48425977Ssam 		r = p->in.right;
48525977Ssam 		break;
48625977Ssam 	case STARG:			/* place arg on the stack */
48725977Ssam 		l = getlr(p, '3');
48825977Ssam 		r = p->in.left;
48925977Ssam 		break;
49025977Ssam 	default:
49125977Ssam 		cerror("STASG bad");
49225977Ssam 		/*NOTREACHED*/
49325977Ssam 	}
49425977Ssam 	/*
49525977Ssam 	 * Pun source for use in code generation.
49625977Ssam 	 */
49725977Ssam 	switch (r->in.op) {
49825977Ssam 	case ICON:
49925977Ssam 		r->in.op = NAME;
50025977Ssam 		break;
50125977Ssam 	case REG:
50225977Ssam 		r->in.op = OREG;
50325977Ssam 		break;
50425977Ssam 	default:
50525977Ssam 		cerror( "STASG-r" );
50625977Ssam 		/*NOTREACHED*/
50725977Ssam 	}
50825977Ssam 	size = p->stn.stsize;
50925977Ssam 	if (size <= 0 || size > 65535)
51025977Ssam 		cerror("structure size out of range");
51125977Ssam 	/*
51225977Ssam 	 * Generate optimized code based on structure size
51325977Ssam 	 * and alignment properties....
51425977Ssam 	 */
51525977Ssam 	switch (size) {
51625828Ssam 
51725977Ssam 	case 1:
51826162Ssam 		putstr("\tmovb\t");
51925977Ssam 	optimized:
52025977Ssam 		adrput(r);
52126162Ssam 		putchar(',');
52225977Ssam 		adrput(l);
52326162Ssam 		putchar('\n');
52425977Ssam 		break;
52525828Ssam 
52625977Ssam 	case 2:
52725977Ssam 		if (p->stn.stalign != 2) {
52825977Ssam 			MOVB(l, r, SZCHAR);
52926162Ssam 			putstr("\tmovb\t");
53025977Ssam 		} else
53126162Ssam 			putstr("\tmovw\t");
53225977Ssam 		goto optimized;
53325977Ssam 
53425977Ssam 	case 4:
53525977Ssam 		if (p->stn.stalign != 4) {
53625977Ssam 			if (p->stn.stalign != 2) {
53725977Ssam 				MOVB(l, r, 3*SZCHAR);
53825977Ssam 				MOVB(l, r, 2*SZCHAR);
53925977Ssam 				MOVB(l, r, 1*SZCHAR);
54026162Ssam 				putstr("\tmovb\t");
54125947Ssam 			} else {
54225977Ssam 				MOVW(l, r, SZSHORT);
54326162Ssam 				putstr("\tmovw\t");
54425828Ssam 			}
54525977Ssam 		} else
54626162Ssam 			putstr("\tmovl\t");
54725977Ssam 		goto optimized;
54825828Ssam 
54925977Ssam 	case 6:
55025977Ssam 		if (p->stn.stalign != 2)
55125977Ssam 			goto movblk;
55225977Ssam 		MOVW(l, r, 2*SZSHORT);
55325977Ssam 		MOVW(l, r, 1*SZSHORT);
55426162Ssam 		putstr("\tmovw\t");
55525977Ssam 		goto optimized;
55625977Ssam 
55725977Ssam 	case 8:
55825977Ssam 		if (p->stn.stalign == 4) {
55925977Ssam 			MOVL(l, r, SZLONG);
56026162Ssam 			putstr("\tmovl\t");
56125977Ssam 			goto optimized;
56225977Ssam 		}
56325977Ssam 		/* fall thru...*/
56425977Ssam 
56525977Ssam 	default:
56625977Ssam 	movblk:
56725977Ssam 		/*
56825977Ssam 		 * Can we ever get a register conflict with R1 here?
56925977Ssam 		 */
57026162Ssam 		putstr("\tmovab\t");
57125977Ssam 		adrput(l);
57226162Ssam 		putstr(",r1\n\tmovab\t");
57325977Ssam 		adrput(r);
57425977Ssam 		printf(",r0\n\tmovl\t$%d,r2\n\tmovblk\n", size);
57525977Ssam 		rname(R2);
57625828Ssam 		break;
57725977Ssam 	}
57825977Ssam 	/*
57925977Ssam 	 * Reverse above pun for reclaim.
58025977Ssam 	 */
58125977Ssam 	if (r->in.op == NAME)
58225977Ssam 		r->in.op = ICON;
58325977Ssam 	else if (r->in.op == OREG)
58425977Ssam 		r->in.op = REG;
58525977Ssam }
58625828Ssam 
58725977Ssam /*
58825977Ssam  * Output the address of the second item in the
58925977Ssam  * pair pointed to by p.
59025977Ssam  */
59125977Ssam upput(p, size)
59225977Ssam 	register NODE *p;
59325977Ssam {
59425977Ssam 	CONSZ save;
59525977Ssam 
59625977Ssam 	if (p->in.op == FLD)
59725977Ssam 		p = p->in.left;
59825977Ssam 	switch (p->in.op) {
59925977Ssam 
60025977Ssam 	case NAME:
60125977Ssam 	case OREG:
60225977Ssam 		save = p->tn.lval;
60325977Ssam 		p->tn.lval += size/SZCHAR;
60425977Ssam 		adrput(p);
60525977Ssam 		p->tn.lval = save;
60625977Ssam 		break;
60725977Ssam 
60825977Ssam 	case REG:
60925977Ssam 		if (size == SZLONG) {
61026162Ssam 			putstr(rname(p->tn.rval+1));
61125977Ssam 			break;
61225977Ssam 		}
61325977Ssam 		/* fall thru... */
61425977Ssam 
61525828Ssam 	default:
61625977Ssam 		cerror("illegal upper address op %s size %d",
61725977Ssam 		    opst[p->tn.op], size);
61825977Ssam 		/*NOTREACHED*/
61925828Ssam 	}
62025977Ssam }
62125828Ssam 
62230360Ssam /*
62332876Sdonn  * Convert a float or double in the accumulator into an unsigned int.
62432876Sdonn  * Unlike the vax, the tahoe stores 0 into the destination
62532876Sdonn  *	on a conversion of > 2 ** 31, so we compensate.
62632876Sdonn  */
62732876Sdonn float_to_unsigned(p)
62832876Sdonn 	NODE *p;
62932876Sdonn {
63032876Sdonn 	register NODE *l = p->in.left;
63132876Sdonn 	int label1 = getlab();
63232876Sdonn 	int label2 = getlab();
63332876Sdonn 	int label3 = getlab();
63432879Sdonn 	NODE *src, *dst;
63532876Sdonn 
63632879Sdonn 	if (p->in.op == SCONV) {
63732879Sdonn 		src = p->in.left;
63832879Sdonn 		dst = resc;
63932879Sdonn 	} else {
64032879Sdonn 		src = p->in.right;
64132879Sdonn 		dst = p->in.left;
64232879Sdonn 	}
64332879Sdonn 
64432876Sdonn 	printf(".data\n\t.align\t2\nL%d:\n\t.long\t0x50000000", label1);
64532879Sdonn 	if (src->in.type == DOUBLE)
64632879Sdonn 		putstr(", 0x00000000 # .double");
64732879Sdonn 	else
64832879Sdonn 		putstr(" # .float");
64932879Sdonn 	putstr(" 2147483648\n\t.text\n\tcmp");
65032879Sdonn 	prtype(src);
65132876Sdonn 	printf("\tL%d\n\tjlss\tL%d\n\tsub", label1, label2);
65232879Sdonn 	prtype(src);
65332876Sdonn 	printf("\tL%d\n\tcv", label1);
65432879Sdonn 	prtype(src);
65532876Sdonn 	putstr("l\t");
65632879Sdonn 	adrput(dst);
65732876Sdonn 	putstr("\n\taddl2\t$-2147483648,");
65832879Sdonn 	adrput(dst);
65932876Sdonn 	printf("\n\tjbr\tL%d\nL%d:\n\tcv", label3, label2);
66032879Sdonn 	prtype(src);
66132876Sdonn 	putstr("l\t");
66232879Sdonn 	adrput(dst);
66332876Sdonn 	printf("\nL%d:", label3);
66432876Sdonn }
66532876Sdonn 
66632876Sdonn /*
66732876Sdonn  * Convert an unsigned int into a float or double, leaving the result
66832876Sdonn  *	in the accumulator.
66932876Sdonn  */
67032876Sdonn unsigned_to_float(p)
67132876Sdonn 	register NODE *p;
67232876Sdonn {
67332876Sdonn 	int label1 = getlab();
67432876Sdonn 	int label2 = getlab();
67532879Sdonn 	NODE *src, *dst;
67632876Sdonn 
67732879Sdonn 	if (p->in.op == SCONV) {
67832879Sdonn 		src = p->in.left;
67932879Sdonn 		dst = resc;
68032879Sdonn 	} else {
68132879Sdonn 		src = p->in.right;
68232879Sdonn 		dst = p->in.left;
68332879Sdonn 	}
68432879Sdonn 
68532876Sdonn 	printf(".data\n\t.align\t2\nL%d:\n\t.long\t0x50800000", label2);
68632876Sdonn 	if (p->in.type == DOUBLE)
68732879Sdonn 		putstr(", 0x00000000 # .double");
68832879Sdonn 	else
68932879Sdonn 		putstr(" # .float");
69032879Sdonn 	putstr(" 4294967296\n\t.text\n\tmovl\t");
69132879Sdonn 	adrput(src);
69232876Sdonn 	putchar(',');
69332879Sdonn 	adrput(dst);
69432876Sdonn 	putstr("\n\tcvl");
69532876Sdonn 	prtype(p);
69632876Sdonn 	putchar('\t');
69732879Sdonn 	adrput(dst);
69832879Sdonn 	printf("\n\tjgeq\tL%d\n\tadd", label1);
69932879Sdonn 	prtype(p);
70032879Sdonn 	printf("\tL%d\nL%d:", label2, label1);
70132876Sdonn }
70232876Sdonn 
70332876Sdonn /*
70432875Sdonn  * Prlen() is a cheap prtype()...
70532875Sdonn  */
70632875Sdonn static char convtab[SZINT/SZCHAR + 1] = {
70732875Sdonn 	'?', 'b', 'w', '?', 'l'
70832875Sdonn };
70932875Sdonn #define	prlen(len)	putchar(convtab[len])
71032875Sdonn 
71132875Sdonn 
71232875Sdonn /*
71332873Sdonn  * Generate code for integral scalar conversions.
71432875Sdonn  * Some of this code is designed to work around a tahoe misfeature
71532875Sdonn  *	that causes sign- and zero- extension to be defeated in
71632875Sdonn  *	certain circumstances.
71732875Sdonn  * Basically if the source operand of a CVT or MOVZ instruction is
71832875Sdonn  *	shorter than the destination, and the source is a register
71932875Sdonn  *	or an immediate constant, sign- and zero- extension are
72032875Sdonn  *	ignored and the high bits of the source are copied.  (Note
72132875Sdonn  *	that zero-extension is not a problem for immediate
72232875Sdonn  *	constants.)
72332873Sdonn  */
72432873Sdonn sconv(p, forcc)
72532873Sdonn 	NODE *p;
72632873Sdonn 	int forcc;
72732873Sdonn {
72832873Sdonn 	register NODE *src, *dst;
72932873Sdonn 	register NODE *tmp;
73032873Sdonn 	register int srclen, dstlen;
73132873Sdonn 	int srctype, dsttype;
73232873Sdonn 	int val;
73332882Sdonn 	int neg = 0;
73430360Ssam 
73532873Sdonn 	if (p->in.op == ASSIGN) {
73632879Sdonn 		src = p->in.right;
73732879Sdonn 		dst = p->in.left;
73832873Sdonn 		dstlen = tlen(dst);
73932873Sdonn 		dsttype = dst->in.type;
74032879Sdonn 	} else if (p->in.op == SCONV) {
74132879Sdonn 		src = p->in.left;
74232879Sdonn 		dst = resc;
74332873Sdonn 		dstlen = tlen(p);
74432873Sdonn 		dsttype = p->in.type;
74532879Sdonn 	} else /* if (p->in.op == OPLEAF) */ {
74632879Sdonn 		src = p;
74732879Sdonn 		dst = resc;
74832879Sdonn 		dstlen = SZINT/SZCHAR;
74932879Sdonn 		dsttype = ISUNSIGNED(src->in.type) ? UNSIGNED : INT;
75032873Sdonn 	}
75132873Sdonn 
75232875Sdonn 	if (src->in.op == REG) {
75332875Sdonn 		srclen = SZINT/SZCHAR;
75432875Sdonn 		srctype = ISUNSIGNED(src->in.type) ? UNSIGNED : INT;
75532875Sdonn 	} else {
75632875Sdonn 		srclen = tlen(src);
75732875Sdonn 		srctype = src->in.type;
75832875Sdonn 	}
75932873Sdonn 
76032882Sdonn 	if (src->in.op == ICON && src->tn.name[0] == '\0') {
76132875Sdonn 		if (src->tn.lval == 0) {
76232875Sdonn 			putstr("clr");
76332875Sdonn 			prtype(dst);
76432875Sdonn 			putchar('\t');
76532875Sdonn 			adrput(dst);
76632875Sdonn 			return;
76732875Sdonn 		}
76832875Sdonn 		if (dstlen < srclen) {
76932875Sdonn 			switch (dsttype) {
77032875Sdonn 			case CHAR:
77132875Sdonn 				src->tn.lval = (char) src->tn.lval;
77232875Sdonn 				break;
77332875Sdonn 			case UCHAR:
77432875Sdonn 				src->tn.lval = (unsigned char) src->tn.lval;
77532875Sdonn 				break;
77632875Sdonn 			case SHORT:
77732875Sdonn 				src->tn.lval = (short) src->tn.lval;
77832875Sdonn 				break;
77932875Sdonn 			case USHORT:
78032875Sdonn 				src->tn.lval = (unsigned short) src->tn.lval;
78132875Sdonn 				break;
78232875Sdonn 			}
78332875Sdonn 		}
78432875Sdonn 		if (dst->in.op == REG) {
78532875Sdonn 			dsttype = INT;
78632875Sdonn 			dstlen = SZINT/SZCHAR;
78732875Sdonn 		}
78832875Sdonn 		srctype = dsttype;
78932875Sdonn 		srclen = dstlen;
79032882Sdonn 		if ((val = src->tn.lval) & 1 << dstlen * SZCHAR - 1) {
79132882Sdonn 			src->tn.lval = -(val | ~((1 << dstlen * SZCHAR) - 1));
79232882Sdonn 			++neg;		/* MNEGx may be shorter */
79332882Sdonn 		}
79432875Sdonn 	}
79532875Sdonn 
79632873Sdonn 	if (srclen < dstlen) {
79732873Sdonn 		if (srctype == CHAR && dsttype == USHORT && dst->in.op == REG) {
79832873Sdonn 			/* (unsigned short) c; => sign extend to 16 bits */
79932874Sdonn 			putstr("cvtbl\t");
80032873Sdonn 			adrput(src);
80132873Sdonn 			putstr(",-(sp)\n\tmovzwl\t2(sp),");
80232873Sdonn 			adrput(dst);
80332873Sdonn 			putstr("\n\tmovab\t4(sp),sp");
80432873Sdonn 			if (forcc) {
80532873Sdonn 				/* inverted test */
80632873Sdonn 				putstr("\n\tcmpl\t$0,");
80732873Sdonn 				adrput(dst);
80832873Sdonn 			}
80932873Sdonn 			return;
81032873Sdonn 		}
81132873Sdonn 		genconv(ISUNSIGNED(srctype),
81232873Sdonn 			srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
81332873Sdonn 			src, dst);
81432873Sdonn 		return;
81532873Sdonn 	}
81632873Sdonn 
81732873Sdonn 	if (srclen > dstlen && dst->in.op == REG) {
81832875Sdonn 		/* if dst is a register, the result must look like an int */
81932873Sdonn 		if (src->in.op == REG) {
82032873Sdonn 			if (ISUNSIGNED(dsttype)) {
82132873Sdonn 				val = (1 << dstlen * SZCHAR) - 1;
82232873Sdonn 				if (src->tn.rval == dst->tn.rval)
82332873Sdonn 					/* conversion in place */
82432874Sdonn 					printf("andl2\t$%#x,", val);
82532873Sdonn 				else {
82632874Sdonn 					printf("andl3\t$%#x,", val);
82732873Sdonn 					adrput(src);
82832873Sdonn 					putchar(',');
82932873Sdonn 				}
83032873Sdonn 				adrput(dst);
83132873Sdonn 				return;
83232873Sdonn 			}
83332875Sdonn 			/*
83432875Sdonn 			 * Sign extension in register can also be
83532875Sdonn 			 * accomplished by shifts, but unfortunately
83632875Sdonn 			 * shifts are extremely slow, due to the lack
83732875Sdonn 			 * of a barrel shifter.
83832875Sdonn 			 */
83932875Sdonn 			putstr("pushl\t");
84032873Sdonn 			adrput(src);
84132875Sdonn 			putstr("\n\tcvt");
84232875Sdonn 			prlen(dstlen);
84332875Sdonn 			printf("l\t%d(sp),", SZINT/SZCHAR - dstlen);
84432873Sdonn 			adrput(dst);
84532875Sdonn 			putstr("\n\tmovab\t4(sp),sp");
84632875Sdonn 			if (forcc) {
84732875Sdonn 				/* inverted test */
84832875Sdonn 				putstr("\n\tcmpl\t$0,");
84932875Sdonn 				adrput(dst);
85032875Sdonn 			}
85132873Sdonn 			return;
85232873Sdonn 		}
85332873Sdonn 		tmp = talloc();
85432873Sdonn 		if ((src->in.op == UNARY MUL &&
85532873Sdonn 		    ((src->in.left->in.op == NAME ||
85632873Sdonn 		     (src->in.left->in.op == ICON)))) ||
85732873Sdonn 		    (src->in.op == OREG && !R2TEST(src->tn.rval))) {
85832873Sdonn 			/* we can increment src's address & pun it */
85932873Sdonn 			*tmp = *src;
86032873Sdonn 			tmp->tn.lval += srclen - dstlen;
86132873Sdonn 		} else {
86232873Sdonn 			/* we must store src's address */
86332873Sdonn 			*tmp = *dst;
86432875Sdonn 			putstr("mova");
86532875Sdonn 			prlen(srclen);
86632875Sdonn 			putchar('\t');
86732873Sdonn 			adrput(src);
86832873Sdonn 			putchar(',');
86932873Sdonn 			adrput(tmp);
87032874Sdonn 			putstr("\n\t");
87132873Sdonn 			tmp->tn.op = OREG;
87232873Sdonn 			tmp->tn.lval = srclen - dstlen;
87332873Sdonn 		}
87432873Sdonn 		genconv(ISUNSIGNED(dsttype), dstlen, SZINT/SZCHAR, tmp, dst);
87532873Sdonn 		tmp->in.op = FREE;
87632873Sdonn 		return;
87732873Sdonn 	}
87832873Sdonn 
87932882Sdonn 	genconv(neg ? -1 : ISUNSIGNED(dsttype),
88032873Sdonn 		srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
88132873Sdonn 		src, dst);
88232873Sdonn }
88332873Sdonn 
88432882Sdonn genconv(srcflag, srclen, dstlen, src, dst)
88532882Sdonn 	int srcflag;
88632875Sdonn 	register int srclen, dstlen;
88732873Sdonn 	NODE *src, *dst;
88832873Sdonn {
88932873Sdonn 	if (srclen != dstlen) {
89032882Sdonn 		if (srcflag > 0 && srclen < dstlen)
89132874Sdonn 			putstr("movz");
89232873Sdonn 		else
89332874Sdonn 			putstr("cvt");
89432875Sdonn 		prlen(srclen);
89532882Sdonn 	} else if (srcflag < 0)
89632882Sdonn 		putstr("mneg");
89732882Sdonn 	else
89832874Sdonn 		putstr("mov");
89932875Sdonn 	prlen(dstlen);
90032873Sdonn 	putchar('\t');
90132873Sdonn 	adrput(src);
90232873Sdonn 	putchar(',');
90332873Sdonn 	adrput(dst);
90432873Sdonn }
90532873Sdonn 
90625828Ssam rmove( rt, rs, t ) TWORD t;{
90725828Ssam 	printf( "	movl	%s,%s\n", rname(rs), rname(rt) );
90825828Ssam 	if(t==DOUBLE)
90925828Ssam 		printf( "	movl	%s,%s\n", rname(rs+1), rname(rt+1) );
91025828Ssam 	}
91125828Ssam 
91225828Ssam struct respref
91325828Ssam respref[] = {
91425828Ssam 	INTAREG|INTBREG,	INTAREG|INTBREG,
91525828Ssam 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
91625828Ssam 	INTEMP,	INTEMP,
91725828Ssam 	FORARG,	FORARG,
91825828Ssam 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
91925828Ssam 	0,	0 };
92025828Ssam 
92125828Ssam setregs(){ /* set up temporary registers */
92225828Ssam 	fregs = 6;	/* tbl- 6 free regs on Tahoe (0-5) */
92325828Ssam 	}
92425828Ssam 
92526076Ssam #ifndef szty
92625828Ssam szty(t) TWORD t;{ /* size, in registers, needed to hold thing of type t */
92725828Ssam 	return(t==DOUBLE ? 2 : 1 );
92825828Ssam 	}
92926076Ssam #endif
93025828Ssam 
93125828Ssam rewfld( p ) NODE *p; {
93225828Ssam 	return(1);
93325828Ssam 	}
93425828Ssam 
93525828Ssam callreg(p) NODE *p; {
93625828Ssam 	return( R0 );
93725828Ssam 	}
93825828Ssam 
93925828Ssam base( p ) register NODE *p; {
94025828Ssam 	register int o = p->in.op;
94125828Ssam 
94225828Ssam 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
94325828Ssam 	if( o==REG ) return( p->tn.rval );
94425828Ssam     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
94525828Ssam 		return( p->in.left->tn.rval );
94625828Ssam     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
94725828Ssam 		return( p->tn.rval + 0200*1 );
94825828Ssam 	return( -1 );
94925828Ssam 	}
95025828Ssam 
95125828Ssam offset( p, tyl ) register NODE *p; int tyl; {
95225828Ssam 
95325828Ssam 	if(tyl > 8) return( -1 );
95425828Ssam 	if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
95525828Ssam 	if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
95625828Ssam 	      (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
95725828Ssam 	      && (1<<p->in.right->tn.lval)==tyl))
95825828Ssam 		return( p->in.left->tn.rval );
95925828Ssam 	return( -1 );
96025828Ssam 	}
96125828Ssam 
96225828Ssam makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
96325828Ssam 	register NODE *t;
96425828Ssam 	register int i;
96525828Ssam 	NODE *f;
96625828Ssam 
96725828Ssam 	p->in.op = OREG;
96825828Ssam 	f = p->in.left; 	/* have to free this subtree later */
96925828Ssam 
97025828Ssam 	/* init base */
97125828Ssam 	switch (q->in.op) {
97225828Ssam 		case ICON:
97325828Ssam 		case REG:
97425828Ssam 		case OREG:
97525828Ssam 			t = q;
97625828Ssam 			break;
97725828Ssam 
97825828Ssam 		case MINUS:
97925828Ssam 			q->in.right->tn.lval = -q->in.right->tn.lval;
98025828Ssam 		case PLUS:
98125828Ssam 			t = q->in.right;
98225828Ssam 			break;
98325828Ssam 
98425828Ssam 		case UNARY MUL:
98525828Ssam 			t = q->in.left->in.left;
98625828Ssam 			break;
98725828Ssam 
98825828Ssam 		default:
98925828Ssam 			cerror("illegal makeor2");
99025828Ssam 	}
99125828Ssam 
99225828Ssam 	p->tn.lval = t->tn.lval;
99325828Ssam #ifndef FLEXNAMES
99425828Ssam 	for(i=0; i<NCHNAM; ++i)
99525828Ssam 		p->in.name[i] = t->in.name[i];
99625828Ssam #else
99725828Ssam 	p->in.name = t->in.name;
99825828Ssam #endif
99925828Ssam 
100025828Ssam 	/* init offset */
100125828Ssam 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
100225828Ssam 
100325828Ssam 	tfree(f);
100425828Ssam 	return;
100525828Ssam 	}
100625828Ssam 
100725828Ssam canaddr( p ) NODE *p; {
100825828Ssam 	register int o = p->in.op;
100925828Ssam 
101025828Ssam 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
101125828Ssam 	return(0);
101225828Ssam 	}
101325828Ssam 
101426076Ssam #ifndef shltype
101525828Ssam shltype( o, p ) register NODE *p; {
101625828Ssam 	return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
101725828Ssam 	}
101826076Ssam #endif
101925828Ssam 
102025828Ssam flshape( p ) NODE *p; {
102125828Ssam 	register int o = p->in.op;
102225828Ssam 
102325828Ssam 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
102425828Ssam 	return(0);
102525828Ssam 	}
102625828Ssam 
102725828Ssam shtemp( p ) register NODE *p; {
102825828Ssam 	if( p->in.op == STARG ) p = p->in.left;
102925828Ssam 	return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
103025828Ssam 	}
103125828Ssam 
103225828Ssam shumul( p ) register NODE *p; {
103325828Ssam 	register int o;
103425828Ssam 	extern int xdebug;
103525828Ssam 
103625828Ssam 	if (xdebug) {
103725828Ssam 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
103825828Ssam 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
103925828Ssam 		}
104025828Ssam 
104125828Ssam 	o = p->in.op;
104225828Ssam 	if(( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON )
104325828Ssam 	 && p->in.type != PTR+DOUBLE)
104425828Ssam 		return( STARNM );
104525828Ssam 
104625828Ssam 	return( 0 );
104725828Ssam 	}
104825828Ssam 
104925828Ssam special( p, shape ) register NODE *p; {
105025828Ssam 	if( shape==SIREG && p->in.op == OREG && R2TEST(p->tn.rval) ) return(1);
105125828Ssam 	else return(0);
105225828Ssam }
105325828Ssam 
105425828Ssam adrcon( val ) CONSZ val; {
105525947Ssam 	printf(ACONFMT, val);
105625828Ssam 	}
105725828Ssam 
105825828Ssam conput( p ) register NODE *p; {
105925828Ssam 	switch( p->in.op ){
106025828Ssam 
106125828Ssam 	case ICON:
106225828Ssam 		acon( p );
106325828Ssam 		return;
106425828Ssam 
106525828Ssam 	case REG:
106626162Ssam 		putstr(rname(p->tn.rval));
106725828Ssam 		return;
106825828Ssam 
106925828Ssam 	default:
107025828Ssam 		cerror( "illegal conput" );
107125828Ssam 		}
107225828Ssam 	}
107325828Ssam 
107425828Ssam insput( p ) NODE *p; {
107525828Ssam 	cerror( "insput" );
107625828Ssam 	}
107725828Ssam 
107825828Ssam adrput( p ) register NODE *p; {
107925828Ssam 	register int r;
108025828Ssam 	/* output an address, with offsets, from p */
108125828Ssam 
108225828Ssam 	if( p->in.op == FLD ){
108325828Ssam 		p = p->in.left;
108425828Ssam 		}
108525828Ssam 	switch( p->in.op ){
108625828Ssam 
108725828Ssam 	case NAME:
108825828Ssam 		acon( p );
108925828Ssam 		return;
109025828Ssam 
109125828Ssam 	case ICON:
109225828Ssam 		/* addressable value of the constant */
109326162Ssam 		putchar('$');
109425828Ssam 		acon( p );
109525828Ssam 		return;
109625828Ssam 
109725828Ssam 	case REG:
109826162Ssam 		putstr(rname(p->tn.rval));
109925828Ssam 		if(p->in.type == DOUBLE)	/* for entry mask */
110025828Ssam 			(void) rname(p->tn.rval+1);
110125828Ssam 		return;
110225828Ssam 
110325828Ssam 	case OREG:
110425828Ssam 		r = p->tn.rval;
110525828Ssam 		if( R2TEST(r) ){ /* double indexing */
110625828Ssam 			register int flags;
110725828Ssam 
110825828Ssam 			flags = R2UPK3(r);
110926162Ssam 			if( flags & 1 ) putchar('*');
111025828Ssam 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
111125828Ssam 			if( R2UPK1(r) != 100) printf( "(%s)", rname(R2UPK1(r)) );
111225828Ssam 			printf( "[%s]", rname(R2UPK2(r)) );
111325828Ssam 			return;
111425828Ssam 			}
111525828Ssam 		if( r == FP && p->tn.lval > 0 ){  /* in the argument region */
111625828Ssam 			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
111725828Ssam 			printf( CONFMT, p->tn.lval );
111826162Ssam 			putstr( "(fp)" );
111925828Ssam 			return;
112025828Ssam 			}
112125828Ssam 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
112225828Ssam 		printf( "(%s)", rname(p->tn.rval) );
112325828Ssam 		return;
112425828Ssam 
112525828Ssam 	case UNARY MUL:
112625828Ssam 		/* STARNM or STARREG found */
112725828Ssam 		if( tshape(p, STARNM) ) {
112826162Ssam 			putchar( '*' );
112925828Ssam 			adrput( p->in.left);
113025828Ssam 			}
113125828Ssam 		return;
113225828Ssam 
113325828Ssam 	default:
113425828Ssam 		cerror( "illegal address" );
113525828Ssam 		return;
113625828Ssam 
113725828Ssam 		}
113825828Ssam 
113925828Ssam 	}
114025828Ssam 
114125828Ssam acon( p ) register NODE *p; { /* print out a constant */
114225828Ssam 
114325828Ssam 	if( p->in.name[0] == '\0' ){
114425828Ssam 		printf( CONFMT, p->tn.lval);
114526162Ssam 		return;
114626162Ssam 	} else {
114725828Ssam #ifndef FLEXNAMES
114825828Ssam 		printf( "%.8s", p->in.name );
114925828Ssam #else
115026162Ssam 		putstr(p->in.name);
115125828Ssam #endif
115226162Ssam 		if (p->tn.lval != 0) {
115326162Ssam 			putchar('+');
115426162Ssam 			printf(CONFMT, p->tn.lval);
115525828Ssam 		}
115625828Ssam 	}
115726162Ssam 	}
115825828Ssam 
115925828Ssam genscall( p, cookie ) register NODE *p; {
116025828Ssam 	/* structure valued call */
116125828Ssam 	return( gencall( p, cookie ) );
116225828Ssam 	}
116325828Ssam 
116425828Ssam genfcall( p, cookie ) register NODE *p; {
116525828Ssam 	register NODE *p1;
116625828Ssam 	register int m;
116725828Ssam 	static char *funcops[6] = {
116825828Ssam 		"sin", "cos", "sqrt", "exp", "log", "atan"
116925828Ssam 	};
117025828Ssam 
117125828Ssam 	/* generate function opcodes */
117225828Ssam 	if(p->in.op==UNARY FORTCALL && p->in.type==FLOAT &&
117325828Ssam 	 (p1 = p->in.left)->in.op==ICON &&
117425828Ssam 	 p1->tn.lval==0 && p1->in.type==INCREF(FTN|FLOAT)) {
117525828Ssam #ifdef FLEXNAMES
117625828Ssam 		p1->in.name++;
117725828Ssam #else
117825828Ssam 		strcpy(p1->in.name, p1->in.name[1]);
117925828Ssam #endif
118025828Ssam 		for(m=0; m<6; m++)
118125828Ssam 			if(!strcmp(p1->in.name, funcops[m]))
118225828Ssam 				break;
118325828Ssam 		if(m >= 6)
118425828Ssam 			uerror("no opcode for fortarn function %s", p1->in.name);
118525828Ssam 	} else
118625828Ssam 		uerror("illegal type of fortarn function");
118725828Ssam 	p1 = p->in.right;
118825828Ssam 	p->in.op = FORTCALL;
118925828Ssam 	if(!canaddr(p1))
119025828Ssam 		order( p1, INAREG|INBREG|SOREG|STARREG|STARNM );
119125828Ssam 	m = match( p, INTAREG|INTBREG );
119225828Ssam 	return(m != MDONE);
119325828Ssam }
119425828Ssam 
119525828Ssam /* tbl */
119625828Ssam int gc_numbytes;
119725828Ssam /* tbl */
119825828Ssam 
119925828Ssam gencall( p, cookie ) register NODE *p; {
120025828Ssam 	/* generate the call given by p */
120125828Ssam 	register NODE *p1, *ptemp;
120225828Ssam 	register int temp, temp1;
120325828Ssam 	register int m;
120425828Ssam 
120525828Ssam 	if( p->in.right ) temp = argsize( p->in.right );
120625828Ssam 	else temp = 0;
120725828Ssam 
120825828Ssam 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
120925828Ssam 		/* set aside room for structure return */
121025828Ssam 
121125828Ssam 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
121225828Ssam 		else temp1 = temp;
121325828Ssam 		}
121425828Ssam 
121525828Ssam 	if( temp > maxargs ) maxargs = temp;
121625828Ssam 	SETOFF(temp1,4);
121725828Ssam 
121825828Ssam 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
121925828Ssam 		ptemp = talloc();
122025828Ssam 		ptemp->in.op = OREG;
122125828Ssam 		ptemp->tn.lval = -1;
122225828Ssam 		ptemp->tn.rval = SP;
122325828Ssam #ifndef FLEXNAMES
122425828Ssam 		ptemp->in.name[0] = '\0';
122525828Ssam #else
122625828Ssam 		ptemp->in.name = "";
122725828Ssam #endif
122825828Ssam 		ptemp->in.rall = NOPREF;
122925828Ssam 		ptemp->in.su = 0;
123025828Ssam 		genargs( p->in.right, ptemp );
123125828Ssam 		ptemp->in.op = FREE;
123225828Ssam 		}
123325828Ssam 
123425828Ssam 	p1 = p->in.left;
123525828Ssam 	if( p1->in.op != ICON ){
123625828Ssam 		if( p1->in.op != REG ){
123725828Ssam 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
123825828Ssam 				if( p1->in.op != NAME ){
123925828Ssam 					order( p1, INAREG );
124025828Ssam 					}
124125828Ssam 				}
124225828Ssam 			}
124325828Ssam 		}
124425828Ssam 
124525828Ssam /* tbl
124625828Ssam 	setup gc_numbytes so reference to ZC works */
124725828Ssam 
124825828Ssam 	gc_numbytes = temp&(0x3ff);
124925828Ssam 
125025828Ssam 	p->in.op = UNARY CALL;
125125828Ssam 	m = match( p, INTAREG|INTBREG );
125225828Ssam 
125325828Ssam 	return(m != MDONE);
125425828Ssam 	}
125525828Ssam 
125625828Ssam /* tbl */
125725828Ssam char *
125825828Ssam ccbranches[] = {
125925828Ssam 	"eql",
126025828Ssam 	"neq",
126125828Ssam 	"leq",
126225828Ssam 	"lss",
126325828Ssam 	"geq",
126425828Ssam 	"gtr",
126525828Ssam 	"lequ",
126625828Ssam 	"lssu",
126725828Ssam 	"gequ",
126825828Ssam 	"gtru",
126925828Ssam 	};
127025828Ssam /* tbl */
127125828Ssam 
127225828Ssam cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
127325828Ssam 
127425828Ssam 		if(o != 0 && (o < EQ || o > UGT ))
127525828Ssam 			cerror( "bad conditional branch: %s", opst[o] );
127625828Ssam 		printf( "	j%s	L%d\n",
127725828Ssam 		 o == 0 ? "br" : ccbranches[o-EQ], lab );
127825828Ssam 	}
127925828Ssam 
128025828Ssam nextcook( p, cookie ) NODE *p; {
128125828Ssam 	/* we have failed to match p with cookie; try another */
128225828Ssam 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
128325828Ssam 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
128425828Ssam 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
128525828Ssam 	return( FORREW );
128625828Ssam 	}
128725828Ssam 
128825828Ssam lastchance( p, cook ) NODE *p; {
128925828Ssam 	/* forget it! */
129025828Ssam 	return(0);
129125828Ssam 	}
129225828Ssam 
129325828Ssam optim2( p ) register NODE *p; {
129425828Ssam # ifdef ONEPASS
129525828Ssam 	/* do local tree transformations and optimizations */
129625828Ssam # define RV(p) p->in.right->tn.lval
129726076Ssam # define nncon(p)	((p)->in.op == ICON && (p)->in.name[0] == 0)
129830360Ssam 	register int o, i;
129930360Ssam 	register NODE *l, *r;
130025828Ssam 
130130360Ssam 	switch (o = p->in.op) {
130230360Ssam 
130330360Ssam 	case DIV: case ASG DIV:
130430360Ssam 	case MOD: case ASG MOD:
130530360Ssam 		/*
130630360Ssam 		 * Change unsigned mods and divs to
130730360Ssam 		 * logicals (mul is done in mip & c2)
130830360Ssam 		 */
130930360Ssam 		if (ISUNSIGNED(p->in.left->in.type) && nncon(p->in.right) &&
131030360Ssam 		    (i = ispow2(RV(p))) >= 0) {
131130360Ssam 			if (o == DIV || o == ASG DIV) {
131230360Ssam 				p->in.op = RS;
131330360Ssam 				RV(p) = i;
131430360Ssam 			} else {
131530360Ssam 				p->in.op = AND;
131630360Ssam 				RV(p)--;
131730360Ssam 			}
131830360Ssam 			if (asgop(o))
131930360Ssam 				p->in.op = ASG p->in.op;
132025828Ssam 		}
132130360Ssam 		return;
132230360Ssam 
132330360Ssam 	case SCONV:
132430360Ssam 		l = p->in.left;
132532879Sdonn 		if (anyfloat(p, l)) {
132632879Sdonn 			/* save some labor later */
132732879Sdonn 			NODE *t = talloc();
132832879Sdonn 
132932879Sdonn 			if (p->in.type == UCHAR || p->in.type == USHORT) {
133032879Sdonn 				*t = *p;
133132879Sdonn 				t->in.type = UNSIGNED;
133232879Sdonn 				p->in.left = t;
133332879Sdonn 			} else if (l->in.type == UCHAR || l->in.type == USHORT) {
133432879Sdonn 				*t = *p;
133532879Sdonn 				t->in.type = INT;
133632879Sdonn 				p->in.left = t;
133732879Sdonn 			}
133832879Sdonn 		} else if (l->in.op != PCONV &&
133932878Sdonn 		    l->in.op != CALL && l->in.op != UNARY CALL &&
134030360Ssam 		    tlen(p) == tlen(l)) {
134132879Sdonn 			/* clobber conversions w/o side effects */
134230360Ssam 			if (l->in.op != FLD)
134330360Ssam 				l->in.type = p->in.type;
134430360Ssam 			ncopy(p, l);
134530360Ssam 			l->in.op = FREE;
134630360Ssam 		}
134730360Ssam 		return;
134830360Ssam 
134930360Ssam 	case ASSIGN:
135030360Ssam 		/*
135130360Ssam 		 * Try to zap storage conversions of non-float items.
135230360Ssam 		 */
135330360Ssam 		r = p->in.right;
135432880Sdonn 		if (r->in.op == SCONV) {
135530360Ssam 			int wdest, wconv, wsrc;
135632880Sdonn 
135732883Sdonn 			if (p->in.left->in.op == FLD)
135832883Sdonn 				return;
135932880Sdonn 			if (anyfloat(r, r->in.left)) {
136032880Sdonn 				/* let the code table handle two cases */
136132880Sdonn 				if (p->in.left->in.type == UNSIGNED &&
136232880Sdonn 					   r->in.type == UNSIGNED) {
136332880Sdonn 					p->in.right = r->in.left;
136432880Sdonn 					r->in.op = FREE;
136532880Sdonn 				} else if ((p->in.left->in.type == FLOAT ||
136632880Sdonn 					    p->in.left->in.type == DOUBLE) &&
136732880Sdonn 					   p->in.left->in.type == r->in.type &&
136832880Sdonn 					   r->in.left->in.type == UNSIGNED) {
136932880Sdonn 					p->in.right = r->in.left;
137032880Sdonn 					r->in.op = FREE;
137132880Sdonn 				}
137232880Sdonn 				return;
137332880Sdonn 			}
137430360Ssam 			wdest = tlen(p->in.left);
137530360Ssam 			wconv = tlen(r);
137630360Ssam 			/*
137730360Ssam 			 * If size doesn't change across assignment or
137830360Ssam 			 * conversion expands src before shrinking again
137930360Ssam 			 * due to the assignment, delete conversion so
138030360Ssam 			 * code generator can create optimal code.
138130360Ssam 			 */
138230360Ssam 			if (wdest == wconv ||
138330360Ssam 			 (wdest == (wsrc = tlen(r->in.left)) && wconv > wsrc)) {
138430360Ssam 				p->in.right = r->in.left;
138530360Ssam 				r->in.op = FREE;
138630360Ssam 			}
138730360Ssam 		}
138830360Ssam 		return;
138925828Ssam 	}
139025828Ssam # endif
139125828Ssam }
139225828Ssam 
139325828Ssam struct functbl {
139425828Ssam 	int fop;
139532877Sdonn 	TWORD ftype;
139625828Ssam 	char *func;
139732877Sdonn 	} opfunc[] = {
139832877Sdonn 	DIV,		TANY,	"udiv",
139932877Sdonn 	MOD,		TANY,	"urem",
140032877Sdonn 	ASG DIV,	TANY,	"audiv",
140132877Sdonn 	ASG MOD,	TANY,	"aurem",
140232877Sdonn 	0,	0,	0 };
140325828Ssam 
140425828Ssam hardops(p)  register NODE *p; {
140525828Ssam 	/* change hard to do operators into function calls.  */
140625828Ssam 	register NODE *q;
140725828Ssam 	register struct functbl *f;
140832877Sdonn 	register o;
140932877Sdonn 	NODE *old,*temp;
141025828Ssam 
141125828Ssam 	o = p->in.op;
141232877Sdonn 	if( ! (optype(o)==BITYPE &&
141332877Sdonn 	       (ISUNSIGNED(p->in.left->in.type) ||
141432877Sdonn 		ISUNSIGNED(p->in.right->in.type))) )
141532877Sdonn 		return;
141625828Ssam 
141725828Ssam 	for( f=opfunc; f->fop; f++ ) {
141825828Ssam 		if( o==f->fop ) goto convert;
141932877Sdonn 		}
142025828Ssam 	return;
142125828Ssam 
142225828Ssam 	convert:
142325828Ssam 	if( asgop( o ) ) {
142432877Sdonn 		old = NIL;
142532877Sdonn 		switch( p->in.left->in.op ){
142632877Sdonn 		case FLD:
142732877Sdonn 			q = p->in.left->in.left;
142832877Sdonn 			/*
142932877Sdonn 			 * rewrite (lval.fld /= rval); as
143032877Sdonn 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
143132877Sdonn 			 * else the compiler will evaluate lval twice.
143232877Sdonn 			 */
143332877Sdonn 			if( q->in.op == UNARY MUL ){
143432877Sdonn 				/* first allocate a temp storage */
143532877Sdonn 				temp = talloc();
143632877Sdonn 				temp->in.op = OREG;
143732877Sdonn 				temp->tn.rval = TMPREG;
143832877Sdonn 				temp->tn.lval = BITOOR(freetemp(1));
143932877Sdonn 				temp->in.type = INCREF(p->in.type);
144032877Sdonn #ifdef FLEXNAMES
144132877Sdonn 				temp->in.name = "";
144232877Sdonn #else
144332877Sdonn 				temp->in.name[0] = '\0';
144432877Sdonn #endif
144532877Sdonn 				old = q->in.left;
144632877Sdonn 				q->in.left = temp;
144732877Sdonn 			}
144832877Sdonn 			/* fall thru ... */
144925828Ssam 
145032877Sdonn 		case REG:
145132877Sdonn 		case NAME:
145232877Sdonn 		case OREG:
145332877Sdonn 			/* change ASG OP to a simple OP */
145432877Sdonn 			q = talloc();
145532877Sdonn 			q->in.op = NOASG p->in.op;
145632877Sdonn 			q->in.rall = NOPREF;
145732877Sdonn 			q->in.type = p->in.type;
145832877Sdonn 			q->in.left = tcopy(p->in.left);
145932877Sdonn 			q->in.right = p->in.right;
146032877Sdonn 			p->in.op = ASSIGN;
146132877Sdonn 			p->in.right = q;
146232877Sdonn 			p = q;
146332877Sdonn 			f -= 2; /* Note: this depends on the table order */
146432877Sdonn 			/* on the right side only - replace *temp with
146532877Sdonn 			 *(temp = &lval), build the assignment node */
146632877Sdonn 			if( old ){
146732877Sdonn 				temp = q->in.left->in.left; /* the "*" node */
146832877Sdonn 				q = talloc();
146932877Sdonn 				q->in.op = ASSIGN;
147032877Sdonn 				q->in.left = temp->in.left;
147132877Sdonn 				q->in.right = old;
147232877Sdonn 				q->in.type = old->in.type;
147332877Sdonn #ifdef FLEXNAMES
147432877Sdonn 				q->in.name = "";
147525828Ssam #else
147632877Sdonn 				q->in.name[0] = '\0';
147725828Ssam #endif
147832877Sdonn 				temp->in.left = q;
147932877Sdonn 			}
148032877Sdonn 			break;
148125828Ssam 
148232877Sdonn 		case UNARY MUL:
148332877Sdonn 			/* avoid doing side effects twice */
148432877Sdonn 			q = p->in.left;
148532877Sdonn 			p->in.left = q->in.left;
148632877Sdonn 			q->in.op = FREE;
148732877Sdonn 			break;
148832877Sdonn 
148932877Sdonn 		default:
149032877Sdonn 			cerror( "hardops: can't compute & LHS" );
149132877Sdonn 			}
149232877Sdonn 		}
149332877Sdonn 
149425828Ssam 	/* build comma op for args to function */
149532877Sdonn 	q = talloc();
149632877Sdonn 	q->in.op = CM;
149732877Sdonn 	q->in.rall = NOPREF;
149832877Sdonn 	q->in.type = INT;
149932877Sdonn 	q->in.left = p->in.left;
150032877Sdonn 	q->in.right = p->in.right;
150125828Ssam 	p->in.op = CALL;
150225828Ssam 	p->in.right = q;
150325828Ssam 
150425828Ssam 	/* put function name in left node of call */
150525828Ssam 	p->in.left = q = talloc();
150625828Ssam 	q->in.op = ICON;
150725828Ssam 	q->in.rall = NOPREF;
150825828Ssam 	q->in.type = INCREF( FTN + p->in.type );
150925828Ssam #ifndef FLEXNAMES
151032877Sdonn 	strcpy( q->in.name, f->func );
151125828Ssam #else
151232877Sdonn 	q->in.name = f->func;
151325828Ssam #endif
151425828Ssam 	q->tn.lval = 0;
151525828Ssam 	q->tn.rval = 0;
151625828Ssam 
151725828Ssam 	}
151825828Ssam 
151925828Ssam zappost(p) NODE *p; {
152025828Ssam 	/* look for ++ and -- operators and remove them */
152125828Ssam 
152225828Ssam 	register int o, ty;
152325828Ssam 	register NODE *q;
152425828Ssam 	o = p->in.op;
152525828Ssam 	ty = optype( o );
152625828Ssam 
152725828Ssam 	switch( o ){
152825828Ssam 
152925828Ssam 	case INCR:
153025828Ssam 	case DECR:
153125828Ssam 			q = p->in.left;
153225828Ssam 			p->in.right->in.op = FREE;  /* zap constant */
153325828Ssam 			ncopy( p, q );
153425828Ssam 			q->in.op = FREE;
153525828Ssam 			return;
153625828Ssam 
153725828Ssam 		}
153825828Ssam 
153925828Ssam 	if( ty == BITYPE ) zappost( p->in.right );
154025828Ssam 	if( ty != LTYPE ) zappost( p->in.left );
154125828Ssam }
154225828Ssam 
154325828Ssam fixpre(p) NODE *p; {
154425828Ssam 
154525828Ssam 	register int o, ty;
154625828Ssam 	o = p->in.op;
154725828Ssam 	ty = optype( o );
154825828Ssam 
154925828Ssam 	switch( o ){
155025828Ssam 
155125828Ssam 	case ASG PLUS:
155225828Ssam 			p->in.op = PLUS;
155325828Ssam 			break;
155425828Ssam 	case ASG MINUS:
155525828Ssam 			p->in.op = MINUS;
155625828Ssam 			break;
155725828Ssam 		}
155825828Ssam 
155925828Ssam 	if( ty == BITYPE ) fixpre( p->in.right );
156025828Ssam 	if( ty != LTYPE ) fixpre( p->in.left );
156125828Ssam }
156225828Ssam 
156325828Ssam NODE * addroreg(l) NODE *l;
156425828Ssam 				/* OREG was built in clocal()
156525828Ssam 				 * for an auto or formal parameter
156625828Ssam 				 * now its address is being taken
156725828Ssam 				 * local code must unwind it
156825828Ssam 				 * back to PLUS/MINUS REG ICON
156925828Ssam 				 * according to local conventions
157025828Ssam 				 */
157125828Ssam {
157225828Ssam 	cerror("address of OREG taken");
157325828Ssam }
157425828Ssam 
157525828Ssam # ifndef ONEPASS
157625828Ssam main( argc, argv ) char *argv[]; {
157725828Ssam 	return( mainp2( argc, argv ) );
157825828Ssam 	}
157925828Ssam # endif
158025828Ssam 
158130360Ssam strip(p) register NODE *p; {
158230360Ssam 	NODE *q;
158330360Ssam 
158430360Ssam 	/* strip nodes off the top when no side effects occur */
158530360Ssam 	for( ; ; ) {
158630360Ssam 		switch( p->in.op ) {
158730360Ssam 		case SCONV:			/* remove lint tidbits */
158830360Ssam 			q = p->in.left;
158930360Ssam 			ncopy( p, q );
159030360Ssam 			q->in.op = FREE;
159130360Ssam 			break;
159230360Ssam 		/* could probably add a few more here */
159330360Ssam 		default:
159430360Ssam 			return;
159530360Ssam 			}
159630360Ssam 		}
159730360Ssam 	}
159830360Ssam 
159925828Ssam myreader(p) register NODE *p; {
160030360Ssam 	strip( p );		/* strip off operations with no side effects */
160125828Ssam 	walkf( p, hardops );	/* convert ops to function calls */
160225828Ssam 	canon( p );		/* expands r-vals for fileds */
160325828Ssam 	walkf( p, optim2 );
160425828Ssam 	}
1605