xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 32926)
117742Sralph # ifndef lint
2*32926Sdonn static char *sccsid ="@(#)local2.c	1.20 (Berkeley) 12/11/87";
317742Sralph # endif
417742Sralph 
518556Sralph # include "pass2.h"
69702Slinton # include "ctype.h"
79702Slinton # ifdef FORT
89702Slinton int ftlab1, ftlab2;
99702Slinton # endif
109702Slinton /* a lot of the machine dependent parts of the second pass */
119702Slinton 
1224418Smckusick # define putstr(s)	fputs((s), stdout)
1324418Smckusick 
149702Slinton # define BITMASK(n) ((1L<<n)-1)
159702Slinton 
1632924Sdonn /*ARGSUSED*/
179702Slinton where(c){
189702Slinton 	fprintf( stderr, "%s, line %d: ", filename, lineno );
199702Slinton 	}
209702Slinton 
219702Slinton lineid( l, fn ) char *fn; {
229702Slinton 	/* identify line l and file fn */
239702Slinton 	printf( "#	line %d, file %s\n", l, fn );
249702Slinton 	}
259702Slinton 
269702Slinton 
279702Slinton eobl2(){
289702Slinton 	OFFSZ spoff;	/* offset from stack pointer */
299702Slinton #ifdef FORT
309702Slinton 	spoff = maxoff;
319702Slinton 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
329702Slinton 	spoff /= SZCHAR;
339702Slinton 	SETOFF(spoff,4);
349702Slinton #ifndef FLEXNAMES
359702Slinton 	printf( "	.set	.F%d,%ld\n", ftnno, spoff );
369702Slinton #else
379702Slinton 	/* SHOULD BE L%d ... ftnno but must change pc/f77 */
389702Slinton 	printf( "	.set	LF%d,%ld\n", ftnno, spoff );
399702Slinton #endif
409702Slinton #else
419702Slinton 	extern int ftlab1, ftlab2;
429702Slinton 
439702Slinton 	spoff = maxoff;
449702Slinton 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
459702Slinton 	spoff /= SZCHAR;
469702Slinton 	SETOFF(spoff,4);
479702Slinton 	printf( "L%d:\n", ftlab1);
489702Slinton 	if( spoff!=0 )
499702Slinton 		if( spoff < 64 )
509702Slinton 			printf( "	subl2	$%ld,sp\n", spoff);
519702Slinton 		else
529702Slinton 			printf( "	movab	-%ld(sp),sp\n", spoff);
539702Slinton 	printf( "	jbr 	L%d\n", ftlab2);
549702Slinton #endif
559702Slinton 	maxargs = -1;
569702Slinton 	}
579702Slinton 
589702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = {
599702Slinton 
609702Slinton 	ASG PLUS, "add",
619702Slinton 	ASG MINUS, "sub",
629702Slinton 	ASG MUL, "mul",
639702Slinton 	ASG DIV, "div",
649702Slinton 	ASG OR, "bis",
659702Slinton 	ASG ER,	"xor",
669702Slinton 	ASG AND, "bic",
679702Slinton 	PLUS,	"add",
689702Slinton 	MINUS,	"sub",
699702Slinton 	MUL,	"mul",
709702Slinton 	DIV,	"div",
719702Slinton 	OR,	"bis",
729702Slinton 	ER,	"xor",
739702Slinton 	AND,	"bic",
749702Slinton 	-1, ""    };
759702Slinton 
769702Slinton hopcode( f, o ){
779702Slinton 	/* output the appropriate string from the above table */
789702Slinton 
799702Slinton 	register struct hoptab *q;
809702Slinton 
819702Slinton 	for( q = ioptab;  q->opmask>=0; ++q ){
829702Slinton 		if( q->opmask == o ){
8324418Smckusick 			putstr( q->opstring );
849702Slinton /* tbl
8524418Smckusick 			if( f == 'F' ) putchar( 'e' );
8624418Smckusick 			else if( f == 'D' ) putchar( 'd' );
879702Slinton    tbl */
889702Slinton /* tbl */
899702Slinton 			switch( f ) {
909702Slinton 				case 'L':
919702Slinton 				case 'W':
929702Slinton 				case 'B':
939702Slinton 				case 'D':
949702Slinton 				case 'F':
9524418Smckusick 					putchar(tolower(f));
969702Slinton 					break;
979702Slinton 
989702Slinton 				}
999702Slinton /* tbl */
1009702Slinton 			return;
1019702Slinton 			}
1029702Slinton 		}
1039702Slinton 	cerror( "no hoptab for %s", opst[o] );
1049702Slinton 	}
1059702Slinton 
1069702Slinton char *
1079702Slinton rnames[] = {  /* keyed to register number tokens */
1089702Slinton 
1099702Slinton 	"r0", "r1",
1109702Slinton 	"r2", "r3", "r4", "r5",
1119702Slinton 	"r6", "r7", "r8", "r9", "r10", "r11",
1129702Slinton 	"ap", "fp", "sp", "pc",
1139702Slinton 
1149702Slinton 	};
1159702Slinton 
1169702Slinton int rstatus[] = {
1179702Slinton 	SAREG|STAREG, SAREG|STAREG,
1189702Slinton 	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
1199702Slinton 	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
1209702Slinton 	SAREG, SAREG, SAREG, SAREG,
1219702Slinton 
1229702Slinton 	};
1239702Slinton 
1249702Slinton tlen(p) NODE *p;
1259702Slinton {
1269702Slinton 	switch(p->in.type) {
1279702Slinton 		case CHAR:
1289702Slinton 		case UCHAR:
1299702Slinton 			return(1);
1309702Slinton 
1319702Slinton 		case SHORT:
1329702Slinton 		case USHORT:
1339702Slinton 			return(2);
1349702Slinton 
1359702Slinton 		case DOUBLE:
1369702Slinton 			return(8);
1379702Slinton 
1389702Slinton 		default:
1399702Slinton 			return(4);
1409702Slinton 		}
1419702Slinton }
1429702Slinton 
1439702Slinton mixtypes(p, q) NODE *p, *q;
1449702Slinton {
14516181Sralph 	register TWORD tp, tq;
1469702Slinton 
1479702Slinton 	tp = p->in.type;
1489702Slinton 	tq = q->in.type;
1499702Slinton 
1509702Slinton 	return( (tp==FLOAT || tp==DOUBLE) !=
1519702Slinton 		(tq==FLOAT || tq==DOUBLE) );
1529702Slinton }
1539702Slinton 
1549702Slinton prtype(n) NODE *n;
1559702Slinton {
1569702Slinton 	switch (n->in.type)
1579702Slinton 		{
1589702Slinton 		case DOUBLE:
15924418Smckusick 			putchar('d');
1609702Slinton 			return;
1619702Slinton 
1629702Slinton 		case FLOAT:
16324418Smckusick 			putchar('f');
1649702Slinton 			return;
1659702Slinton 
1669702Slinton 		case LONG:
1679702Slinton 		case ULONG:
1689702Slinton 		case INT:
1699702Slinton 		case UNSIGNED:
17024418Smckusick 			putchar('l');
1719702Slinton 			return;
1729702Slinton 
1739702Slinton 		case SHORT:
1749702Slinton 		case USHORT:
17524418Smckusick 			putchar('w');
1769702Slinton 			return;
1779702Slinton 
1789702Slinton 		case CHAR:
1799702Slinton 		case UCHAR:
18024418Smckusick 			putchar('b');
1819702Slinton 			return;
1829702Slinton 
1839702Slinton 		default:
1849702Slinton 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
1859702Slinton 			else {
18624418Smckusick 				putchar('l');
1879702Slinton 				return;
1889702Slinton 				}
1899702Slinton 		}
1909702Slinton }
1919702Slinton 
1929702Slinton zzzcode( p, c ) register NODE *p; {
1939702Slinton 	register m;
19432924Sdonn 	int val;
1959702Slinton 	switch( c ){
1969702Slinton 
1979702Slinton 	case 'N':  /* logical ops, turned into 0-1 */
1989702Slinton 		/* use register given by register 1 */
1999702Slinton 		cbgen( 0, m=getlab(), 'I' );
2009702Slinton 		deflab( p->bn.label );
2019702Slinton 		printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );
2029702Slinton 		deflab( m );
2039702Slinton 		return;
2049702Slinton 
2059702Slinton 	case 'I':
2069702Slinton 	case 'P':
2079702Slinton 		cbgen( p->in.op, p->bn.label, c );
2089702Slinton 		return;
2099702Slinton 
2109702Slinton 	case 'A':
2119702Slinton 		{
2129702Slinton 		register NODE *l, *r;
2139702Slinton 
2149702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
2159702Slinton 		r = getlr(p, 'R');
21616181Sralph 		if (p->in.op == ASSIGN)
21716181Sralph 			l = getlr(p, 'L');
21817208Sralph 		else if (p->in.op == SCONV) {
2199702Slinton 			l = resc;
22017742Sralph #if defined(FORT) || defined(SPRECC)
22116181Sralph 			l->in.type = r->in.type;
22216181Sralph #else
22316181Sralph 			l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type;
22416181Sralph #endif
22516181Sralph 			r = getlr(p, 'L');
22616181Sralph 			}
22717208Sralph 		else {		/* OPLTYPE */
22816181Sralph 			l = resc;
22917742Sralph #if defined(FORT) || defined(SPRECC)
23016181Sralph 			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
23116181Sralph #else
2329702Slinton 			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
23316181Sralph #endif
2349702Slinton 			}
2359702Slinton 		if (r->in.op == ICON)
23617208Sralph 			if (r->in.name[0] == '\0') {
23717208Sralph 				if (r->tn.lval == 0) {
23824418Smckusick 					putstr("clr");
2399702Slinton 					prtype(l);
24024418Smckusick 					putchar('\t');
2419702Slinton 					adrput(l);
2429702Slinton 					return;
2439702Slinton 					}
24417208Sralph 				if (r->tn.lval < 0 && r->tn.lval >= -63) {
24524418Smckusick 					putstr("mneg");
2469702Slinton 					prtype(l);
2479702Slinton 					r->tn.lval = -r->tn.lval;
2489702Slinton 					goto ops;
2499702Slinton 					}
25017208Sralph 				if (r->tn.lval < 0)
25117208Sralph 					r->in.type = r->tn.lval >= -128 ? CHAR
2529702Slinton 						: (r->tn.lval >= -32768 ? SHORT
25317208Sralph 						: INT);
25417208Sralph 				else if (l->in.type == FLOAT ||
25517208Sralph 				    l->in.type == DOUBLE)
25617208Sralph 					r->in.type = r->tn.lval <= 63 ? INT
25717208Sralph 						: (r->tn.lval <= 127 ? CHAR
25817208Sralph 						: (r->tn.lval <= 32767 ? SHORT
25917208Sralph 						: INT));
26017208Sralph 				else
26117208Sralph 					r->in.type = r->tn.lval <= 63 ? INT
26217208Sralph 						: (r->tn.lval <= 127 ? CHAR
2639702Slinton 						: (r->tn.lval <= 255 ? UCHAR
2649702Slinton 						: (r->tn.lval <= 32767 ? SHORT
2659702Slinton 						: (r->tn.lval <= 65535 ? USHORT
26617208Sralph 						: INT))));
2679702Slinton 				}
26817208Sralph 			else {
26924418Smckusick 				putstr("moval");
27024418Smckusick 				putchar('\t');
27116181Sralph 				acon(r);
27224418Smckusick 				putchar(',');
27316181Sralph 				adrput(l);
27416181Sralph 				return;
27516181Sralph 				}
2769702Slinton 
27723536Sbloom 		if (p->in.op == SCONV &&
27823536Sbloom 		    !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
27923536Sbloom 		    !mixtypes(l, r)) {
28023536Sbloom 			/*
28123536Sbloom 			 * Because registers must always contain objects
28223536Sbloom 			 * of the same width as INTs, we may have to
28323536Sbloom 			 * perform two conversions to get an INT.  Can
28423536Sbloom 			 * the conversions be collapsed into one?
28523536Sbloom 			 */
28623536Sbloom 			if (m = collapsible(l, r))
28723536Sbloom 				r->in.type = m;
28823536Sbloom 			else {
28923536Sbloom 				/*
29023536Sbloom 				 * Two steps are required.
29123536Sbloom 				 */
29223536Sbloom 				NODE *x = &resc[1];
29323536Sbloom 
29423536Sbloom 				*x = *l;
29523536Sbloom 				if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
29624418Smckusick 					putstr("movz");
2979702Slinton 				else
29824418Smckusick 					putstr("cvt");
29923536Sbloom 				prtype(r);
30023536Sbloom 				prtype(x);
30124418Smckusick 				putchar('\t');
30223536Sbloom 				adrput(r);
30324418Smckusick 				putchar(',');
30423536Sbloom 				adrput(x);
30524418Smckusick 				putchar('\n');
30624418Smckusick 				putchar('\t');
30723536Sbloom 				r = x;
3089702Slinton 				}
30923536Sbloom 			l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
3109702Slinton 			}
31123536Sbloom 
31225751Sdonn 		if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
31325751Sdonn 		    mixtypes(l, r)) {
31425751Sdonn 			int label1, label2;
31525751Sdonn 
31625751Sdonn 			label1 = getlab();
31725751Sdonn 			label2 = getlab();
31825751Sdonn 
31925751Sdonn 			putstr("movl\t");
32025751Sdonn 			adrput(r);
32125751Sdonn 			putchar(',');
32225751Sdonn 			adrput(l);
32327269Sdonn 			putstr("\n\tjbsc\t$31,");
32425751Sdonn 			adrput(l);
32525751Sdonn 			printf(",L%d\n\tcvtl", label1);
32625751Sdonn 			prtype(l);
32725751Sdonn 			putchar('\t');
32825751Sdonn 			adrput(l);
32925751Sdonn 			putchar(',');
33025751Sdonn 			adrput(l);
33125751Sdonn 			printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1);
33225751Sdonn 			prtype(l);
33325751Sdonn 			putchar('\t');
33425751Sdonn 			adrput(l);
33525751Sdonn 			putchar(',');
33625751Sdonn 			adrput(l);
33725751Sdonn 			putstr("\n\tadd");
33825751Sdonn 			prtype(l);
33925751Sdonn 			putstr("2\t$0");
34025751Sdonn 			prtype(l);
34125751Sdonn 			putstr("2.147483648e9,");
34225751Sdonn 			adrput(l);
34325751Sdonn 			printf("\nL%d:", label2);
34425751Sdonn 
34525751Sdonn 			return;
34625751Sdonn 			}
34725751Sdonn 
34817208Sralph 		if (!mixtypes(l,r)) {
34917208Sralph 			if (tlen(l) == tlen(r)) {
35024418Smckusick 				putstr("mov");
35117742Sralph #ifdef FORT
35217742Sralph 				if (Oflag)
35317742Sralph 					prtype(l);
35417742Sralph 				else {
35517742Sralph 					if (l->in.type == DOUBLE)
35624418Smckusick 						putchar('q');
35717742Sralph 					else if(l->in.type == FLOAT)
35824418Smckusick 						putchar('l');
35917742Sralph 					else
36017742Sralph 						prtype(l);
36117742Sralph 					}
36217742Sralph #else
3639702Slinton 				prtype(l);
36417742Sralph #endif FORT
3659702Slinton 				goto ops;
3669702Slinton 				}
3679702Slinton 			else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
36824418Smckusick 				putstr("movz");
3699702Slinton 			else
37024418Smckusick 				putstr("cvt");
3719702Slinton 			}
3729702Slinton 		else
37324418Smckusick 			putstr("cvt");
3749702Slinton 		prtype(r);
3759702Slinton 		prtype(l);
3769702Slinton 	ops:
37724418Smckusick 		putchar('\t');
3789702Slinton 		adrput(r);
37924418Smckusick 		putchar(',');
3809702Slinton 		adrput(l);
3819702Slinton 		return;
3829702Slinton 		}
3839702Slinton 
38425751Sdonn 	case 'G':	/* i *= f; asgops with int lhs and float rhs */
38525751Sdonn 		{
38625751Sdonn 		register NODE *l, *r, *s;
38725751Sdonn 		int rt;
38825751Sdonn 
38925751Sdonn 		l = p->in.left;
39025751Sdonn 		r = p->in.right;
39125751Sdonn 		s = talloc();
39225751Sdonn 		rt = r->in.type;
39325751Sdonn 
39425751Sdonn 		s->in.op = SCONV;
39525751Sdonn 		s->in.left = l;
39625751Sdonn 		s->in.type = rt;
39725751Sdonn 		zzzcode(s, 'A');
39825751Sdonn 		putstr("\n\t");
39925751Sdonn 
40025751Sdonn 		hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
40125751Sdonn 		putstr("2\t");
40225751Sdonn 		adrput(r);
40325751Sdonn 		putchar(',');
40425751Sdonn 		adrput(resc);
40525751Sdonn 		putstr("\n\t");
40625751Sdonn 
40725751Sdonn 		s->in.op = ASSIGN;
40825751Sdonn 		s->in.left = l;
40925751Sdonn 		s->in.right = resc;
41025751Sdonn 		s->in.type = l->in.type;
41125751Sdonn 		zzzcode(s, 'A');
41225751Sdonn 
41325751Sdonn 		s->in.op = FREE;
41425751Sdonn 		return;
41525751Sdonn 		}
41625751Sdonn 
4179702Slinton 	case 'B':	/* get oreg value in temp register for left shift */
4189702Slinton 		{
4199702Slinton 		register NODE *r;
4209702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
4219702Slinton 		r = p->in.right;
4229702Slinton 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
42324418Smckusick 			putstr("movl");
4249702Slinton 		else {
42524418Smckusick 			putstr("cvt");
4269702Slinton 			prtype(r);
42724418Smckusick 			putchar('l');
4289702Slinton 			}
4299702Slinton 		return;
4309702Slinton 		}
4319702Slinton 
4329702Slinton 	case 'C':	/* num words pushed on arg stack */
4339702Slinton 		{
4349702Slinton 		extern int gc_numbytes;
4359702Slinton 		extern int xdebug;
4369702Slinton 
4379702Slinton 		if (xdebug) printf("->%d<-",gc_numbytes);
4389702Slinton 
4399702Slinton 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
4409702Slinton 		return;
4419702Slinton 		}
4429702Slinton 
4439702Slinton 	case 'D':	/* INCR and DECR */
4449702Slinton 		zzzcode(p->in.left, 'A');
44524418Smckusick 		putchar('\n');
44624418Smckusick 		putchar('\t');
4479702Slinton 
4489702Slinton 	case 'E':	/* INCR and DECR, FOREFF */
4499702Slinton 		if (p->in.right->tn.lval == 1)
4509702Slinton 			{
45124418Smckusick 			putstr( p->in.op == INCR ? "inc" : "dec" );
4529702Slinton 			prtype(p->in.left);
45324418Smckusick 			putchar('\t');
4549702Slinton 			adrput(p->in.left);
4559702Slinton 			return;
4569702Slinton 			}
45724418Smckusick 		putstr( p->in.op == INCR ? "add" : "sub" );
4589702Slinton 		prtype(p->in.left);
45924418Smckusick 		putchar('2');
46024418Smckusick 		putchar('\t');
4619702Slinton 		adrput(p->in.right);
46224418Smckusick 		putchar(',');
4639702Slinton 		adrput(p->in.left);
4649702Slinton 		return;
4659702Slinton 
4669702Slinton 	case 'F':	/* register type of right operand */
4679702Slinton 		{
4689702Slinton 		register NODE *n;
4699702Slinton 		extern int xdebug;
4709702Slinton 		register int ty;
4719702Slinton 
4729702Slinton 		n = getlr( p, 'R' );
4739702Slinton 		ty = n->in.type;
4749702Slinton 
4759702Slinton 		if (xdebug) printf("->%d<-", ty);
4769702Slinton 
47724418Smckusick 		if ( ty==DOUBLE) putchar('d');
47824418Smckusick 		else if ( ty==FLOAT ) putchar('f');
47924418Smckusick 		else putchar('l');
4809702Slinton 		return;
4819702Slinton 		}
4829702Slinton 
4839702Slinton 	case 'L':	/* type of left operand */
4849702Slinton 	case 'R':	/* type of right operand */
4859702Slinton 		{
4869702Slinton 		register NODE *n;
4879702Slinton 		extern int xdebug;
4889702Slinton 
48916181Sralph 		n = getlr( p, c );
4909702Slinton 		if (xdebug) printf("->%d<-", n->in.type);
4919702Slinton 
4929702Slinton 		prtype(n);
4939702Slinton 		return;
4949702Slinton 		}
4959702Slinton 
4969702Slinton 	case 'Z':	/* complement mask for bit instr */
4979702Slinton 		printf("$%ld", ~p->in.right->tn.lval);
4989702Slinton 		return;
4999702Slinton 
5009702Slinton 	case 'U':	/* 32 - n, for unsigned right shifts */
5019702Slinton 		printf("$%d", 32 - p->in.right->tn.lval );
5029702Slinton 		return;
5039702Slinton 
5049702Slinton 	case 'T':	/* rounded structure length for arguments */
5059702Slinton 		{
5069702Slinton 		int size;
5079702Slinton 
5089702Slinton 		size = p->stn.stsize;
5099702Slinton 		SETOFF( size, 4);
5109702Slinton 		printf("$%d", size);
5119702Slinton 		return;
5129702Slinton 		}
5139702Slinton 
5149702Slinton 	case 'S':  /* structure assignment */
5159702Slinton 		{
5169702Slinton 			register NODE *l, *r;
5179702Slinton 			register size;
5189702Slinton 
5199702Slinton 			if( p->in.op == STASG ){
5209702Slinton 				l = p->in.left;
5219702Slinton 				r = p->in.right;
5229702Slinton 
5239702Slinton 				}
5249702Slinton 			else if( p->in.op == STARG ){  /* store an arg into a temporary */
5259702Slinton 				r = p->in.left;
5269702Slinton 				}
5279702Slinton 			else cerror( "STASG bad" );
5289702Slinton 
5299702Slinton 			if( r->in.op == ICON ) r->in.op = NAME;
5309702Slinton 			else if( r->in.op == REG ) r->in.op = OREG;
5319702Slinton 			else if( r->in.op != OREG ) cerror( "STASG-r" );
5329702Slinton 
5339702Slinton 			size = p->stn.stsize;
5349702Slinton 
5359702Slinton 			if( size <= 0 || size > 65535 )
5369702Slinton 				cerror("structure size <0=0 or >65535");
5379702Slinton 
5389702Slinton 			switch(size) {
5399702Slinton 				case 1:
54024418Smckusick 					putstr("	movb	");
5419702Slinton 					break;
5429702Slinton 				case 2:
54324418Smckusick 					putstr("	movw	");
5449702Slinton 					break;
5459702Slinton 				case 4:
54624418Smckusick 					putstr("	movl	");
5479702Slinton 					break;
5489702Slinton 				case 8:
54924418Smckusick 					putstr("	movq	");
5509702Slinton 					break;
5519702Slinton 				default:
5529702Slinton 					printf("	movc3	$%d,", size);
5539702Slinton 					break;
5549702Slinton 			}
5559702Slinton 			adrput(r);
55616418Sralph 			if( p->in.op == STASG ){
55724418Smckusick 				putchar(',');
55816418Sralph 				adrput(l);
55924418Smckusick 				putchar('\n');
56016418Sralph 				}
56116418Sralph 			else
56224418Smckusick 				putstr(",(sp)\n");
5639702Slinton 
5649702Slinton 			if( r->in.op == NAME ) r->in.op = ICON;
5659702Slinton 			else if( r->in.op == OREG ) r->in.op = REG;
5669702Slinton 
5679702Slinton 			}
5689702Slinton 		break;
5699702Slinton 
5709702Slinton 	default:
5719702Slinton 		cerror( "illegal zzzcode" );
5729702Slinton 		}
5739702Slinton 	}
5749702Slinton 
57523536Sbloom /*
57623536Sbloom  * collapsible(dest, src) -- if a conversion with a register destination
57723536Sbloom  *	can be accomplished in one instruction, return the type of src
57823536Sbloom  *	that will do the job correctly; otherwise return 0.  Note that
57923536Sbloom  *	a register must always end up having type INT or UNSIGNED.
58023536Sbloom  */
58123536Sbloom int
58223536Sbloom collapsible(dest, src)
58323536Sbloom NODE *dest, *src;
58423536Sbloom {
58523536Sbloom 	int st = src->in.type;
58623536Sbloom 	int dt = dest->in.type;
58723536Sbloom 	int newt = 0;
58823536Sbloom 
58923536Sbloom 	/*
59023536Sbloom 	 * Are there side effects of evaluating src?
59123536Sbloom 	 * If the derived type will not be the same size as src,
59224418Smckusick 	 * we may have to use two steps.
59323536Sbloom 	 */
59424418Smckusick 	if (tlen(src) > tlen(dest)) {
59524418Smckusick 		if (tshape(src, STARREG))
59624418Smckusick 			return (0);
59724418Smckusick 		if (src->in.op == OREG && R2TEST(src->tn.rval))
59824418Smckusick 			return (0);
59924418Smckusick 		}
60023536Sbloom 
60123536Sbloom 	/*
60223536Sbloom 	 * Can we get an object of dest's type by punning src?
60323536Sbloom 	 * Praises be to great Cthulhu for little-endian machines...
60423536Sbloom 	 */
60523536Sbloom 	if (st == CHAR && dt == USHORT)
60623536Sbloom 		/*
60723536Sbloom 		 * Special case -- we must sign-extend to 16 bits.
60823536Sbloom 		 */
60923536Sbloom 		return (0);
61023536Sbloom 
61123536Sbloom 	if (tlen(src) < tlen(dest))
61223536Sbloom 		newt = st;
61323536Sbloom 	else
61423536Sbloom 		newt = dt;
61523536Sbloom 
61623536Sbloom 	return (newt);
61723536Sbloom 	}
61823536Sbloom 
61917742Sralph rmove( rt, rs, t ) TWORD t; {
6209702Slinton 	printf( "	%s	%s,%s\n",
62117742Sralph #ifdef FORT
62217742Sralph 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
62317742Sralph #endif
6249702Slinton 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
6259702Slinton 		rnames[rs], rnames[rt] );
6269702Slinton 	}
6279702Slinton 
6289702Slinton struct respref
6299702Slinton respref[] = {
6309702Slinton 	INTAREG|INTBREG,	INTAREG|INTBREG,
6319702Slinton 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
6329702Slinton 	INTEMP,	INTEMP,
6339702Slinton 	FORARG,	FORARG,
6349702Slinton 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
6359702Slinton 	0,	0 };
6369702Slinton 
6379702Slinton setregs(){ /* set up temporary registers */
6389702Slinton 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
6399702Slinton 	;
6409702Slinton 	}
6419702Slinton 
64232924Sdonn /*ARGSUSED*/
6439702Slinton rewfld( p ) NODE *p; {
6449702Slinton 	return(1);
6459702Slinton 	}
6469702Slinton 
64732924Sdonn /*ARGSUSED*/
6489702Slinton callreg(p) NODE *p; {
6499702Slinton 	return( R0 );
6509702Slinton 	}
6519702Slinton 
6529702Slinton base( p ) register NODE *p; {
6539702Slinton 	register int o = p->in.op;
6549702Slinton 
6559702Slinton 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
6569702Slinton 	if( o==REG ) return( p->tn.rval );
6579702Slinton     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
6589702Slinton 		return( p->in.left->tn.rval );
6599702Slinton     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
6609702Slinton 		return( p->tn.rval + 0200*1 );
6619702Slinton 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
6629702Slinton 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
6639702Slinton 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
6649702Slinton 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
6659702Slinton 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
6669702Slinton 	return( -1 );
6679702Slinton 	}
6689702Slinton 
6699702Slinton offset( p, tyl ) register NODE *p; int tyl; {
6709702Slinton 
67124418Smckusick 	if( tyl==1 &&
67224418Smckusick 	    p->in.op==REG &&
67324418Smckusick 	    (p->in.type==INT || p->in.type==UNSIGNED) )
67424418Smckusick 		return( p->tn.rval );
67524418Smckusick 	if( p->in.op==LS &&
67624418Smckusick 	    p->in.left->in.op==REG &&
67724418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
67824418Smckusick 	    p->in.right->in.op==ICON &&
67924418Smckusick 	    p->in.right->in.name[0]=='\0' &&
68024418Smckusick 	    (1<<p->in.right->tn.lval)==tyl)
6819702Slinton 		return( p->in.left->tn.rval );
68224418Smckusick 	if( tyl==2 &&
68324418Smckusick 	    p->in.op==PLUS &&
68424418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
68524418Smckusick 	    p->in.left->in.op==REG &&
68624418Smckusick 	    p->in.right->in.op==REG &&
68724418Smckusick 	    p->in.left->tn.rval==p->in.right->tn.rval )
68824418Smckusick 		return( p->in.left->tn.rval );
6899702Slinton 	return( -1 );
6909702Slinton 	}
6919702Slinton 
6929702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
6939702Slinton 	register NODE *t;
6949702Slinton 	NODE *f;
6959702Slinton 
6969702Slinton 	p->in.op = OREG;
6979702Slinton 	f = p->in.left; 	/* have to free this subtree later */
6989702Slinton 
6999702Slinton 	/* init base */
7009702Slinton 	switch (q->in.op) {
7019702Slinton 		case ICON:
7029702Slinton 		case REG:
7039702Slinton 		case OREG:
7049702Slinton 			t = q;
7059702Slinton 			break;
7069702Slinton 
7079702Slinton 		case MINUS:
7089702Slinton 			q->in.right->tn.lval = -q->in.right->tn.lval;
7099702Slinton 		case PLUS:
7109702Slinton 			t = q->in.right;
7119702Slinton 			break;
7129702Slinton 
7139702Slinton 		case INCR:
7149702Slinton 		case ASG MINUS:
7159702Slinton 			t = q->in.left;
7169702Slinton 			break;
7179702Slinton 
7189702Slinton 		case UNARY MUL:
7199702Slinton 			t = q->in.left->in.left;
7209702Slinton 			break;
7219702Slinton 
7229702Slinton 		default:
7239702Slinton 			cerror("illegal makeor2");
7249702Slinton 	}
7259702Slinton 
7269702Slinton 	p->tn.lval = t->tn.lval;
7279702Slinton #ifndef FLEXNAMES
72832924Sdonn 	{
72932924Sdonn 		register int i;
73032924Sdonn 		for(i=0; i<NCHNAM; ++i)
73132924Sdonn 			p->in.name[i] = t->in.name[i];
73232924Sdonn 	}
7339702Slinton #else
7349702Slinton 	p->in.name = t->in.name;
7359702Slinton #endif
7369702Slinton 
7379702Slinton 	/* init offset */
7389702Slinton 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
7399702Slinton 
7409702Slinton 	tfree(f);
7419702Slinton 	return;
7429702Slinton 	}
7439702Slinton 
7449702Slinton canaddr( p ) NODE *p; {
7459702Slinton 	register int o = p->in.op;
7469702Slinton 
7479702Slinton 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
7489702Slinton 	return(0);
7499702Slinton 	}
7509702Slinton 
7519702Slinton flshape( p ) register NODE *p; {
7529702Slinton 	return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
7539702Slinton 		(p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
7549702Slinton 	}
7559702Slinton 
756*32926Sdonn /* INTEMP shapes must not contain any temporary registers */
7579702Slinton shtemp( p ) register NODE *p; {
758*32926Sdonn 	int r;
759*32926Sdonn 
7609702Slinton 	if( p->in.op == STARG ) p = p->in.left;
761*32926Sdonn 
762*32926Sdonn 	switch (p->in.op) {
763*32926Sdonn 	case REG:
764*32926Sdonn 		return( !istreg(p->tn.rval) );
765*32926Sdonn 	case OREG:
766*32926Sdonn 		r = p->tn.rval;
767*32926Sdonn 		if( R2TEST(r) ) {
768*32926Sdonn 			if( istreg(R2UPK1(r)) )
769*32926Sdonn 				return(0);
770*32926Sdonn 			r = R2UPK2(r);
771*32926Sdonn 			}
772*32926Sdonn 		return( !istreg(r) );
773*32926Sdonn /*
774*32926Sdonn 	case UNARY MUL:
775*32926Sdonn 		p = p->in.left;
776*32926Sdonn 		return( p->in.op != UNARY MUL && shtemp(p) );
777*32926Sdonn */
778*32926Sdonn 		}
779*32926Sdonn 
780*32926Sdonn 	if( optype( p->in.op ) != LTYPE ) return(0);
781*32926Sdonn 	return(1);
7829702Slinton 	}
7839702Slinton 
7849702Slinton shumul( p ) register NODE *p; {
7859702Slinton 	register o;
7869702Slinton 	extern int xdebug;
7879702Slinton 
7889702Slinton 	if (xdebug) {
7899702Slinton 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
7909702Slinton 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
7919702Slinton 		}
7929702Slinton 
7939702Slinton 
7949702Slinton 	o = p->in.op;
7959702Slinton 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
7969702Slinton 
7979702Slinton 	if( ( o == INCR || o == ASG MINUS ) &&
7989702Slinton 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
7999702Slinton 	    p->in.right->in.name[0] == '\0' )
8009702Slinton 		{
80117659Sralph 		switch (p->in.type)
8029702Slinton 			{
8039702Slinton 			case CHAR|PTR:
8049702Slinton 			case UCHAR|PTR:
8059702Slinton 				o = 1;
8069702Slinton 				break;
8079702Slinton 
8089702Slinton 			case SHORT|PTR:
8099702Slinton 			case USHORT|PTR:
8109702Slinton 				o = 2;
8119702Slinton 				break;
8129702Slinton 
8139702Slinton 			case INT|PTR:
8149702Slinton 			case UNSIGNED|PTR:
8159702Slinton 			case LONG|PTR:
8169702Slinton 			case ULONG|PTR:
8179702Slinton 			case FLOAT|PTR:
8189702Slinton 				o = 4;
8199702Slinton 				break;
8209702Slinton 
8219702Slinton 			case DOUBLE|PTR:
8229702Slinton 				o = 8;
8239702Slinton 				break;
8249702Slinton 
8259702Slinton 			default:
82617742Sralph 				if ( ISPTR(p->in.type) &&
82717742Sralph 				     ISPTR(DECREF(p->in.type)) ) {
8289702Slinton 					o = 4;
8299702Slinton 					break;
8309702Slinton 					}
8319702Slinton 				else return(0);
8329702Slinton 			}
8339702Slinton 		return( p->in.right->tn.lval == o ? STARREG : 0);
8349702Slinton 		}
8359702Slinton 
8369702Slinton 	return( 0 );
8379702Slinton 	}
8389702Slinton 
8399702Slinton adrcon( val ) CONSZ val; {
84024418Smckusick 	putchar( '$' );
8419702Slinton 	printf( CONFMT, val );
8429702Slinton 	}
8439702Slinton 
8449702Slinton conput( p ) register NODE *p; {
8459702Slinton 	switch( p->in.op ){
8469702Slinton 
8479702Slinton 	case ICON:
8489702Slinton 		acon( p );
8499702Slinton 		return;
8509702Slinton 
8519702Slinton 	case REG:
85224418Smckusick 		putstr( rnames[p->tn.rval] );
8539702Slinton 		return;
8549702Slinton 
8559702Slinton 	default:
8569702Slinton 		cerror( "illegal conput" );
8579702Slinton 		}
8589702Slinton 	}
8599702Slinton 
86032923Sdonn /*ARGSUSED*/
86132924Sdonn insput( p ) NODE *p; {
8629702Slinton 	cerror( "insput" );
8639702Slinton 	}
8649702Slinton 
86532923Sdonn /*ARGSUSED*/
86632924Sdonn upput( p, off ) NODE *p; int off; {
8679702Slinton 	cerror( "upput" );
8689702Slinton 	}
8699702Slinton 
8709702Slinton adrput( p ) register NODE *p; {
8719702Slinton 	register int r;
8729702Slinton 	/* output an address, with offsets, from p */
8739702Slinton 
8749702Slinton 	if( p->in.op == FLD ){
8759702Slinton 		p = p->in.left;
8769702Slinton 		}
8779702Slinton 	switch( p->in.op ){
8789702Slinton 
8799702Slinton 	case NAME:
8809702Slinton 		acon( p );
8819702Slinton 		return;
8829702Slinton 
8839702Slinton 	case ICON:
8849702Slinton 		/* addressable value of the constant */
88524418Smckusick 		putchar( '$' );
8869702Slinton 		acon( p );
8879702Slinton 		return;
8889702Slinton 
8899702Slinton 	case REG:
89024418Smckusick 		putstr( rnames[p->tn.rval] );
8919702Slinton 		return;
8929702Slinton 
8939702Slinton 	case OREG:
8949702Slinton 		r = p->tn.rval;
8959702Slinton 		if( R2TEST(r) ){ /* double indexing */
8969702Slinton 			register int flags;
8979702Slinton 
8989702Slinton 			flags = R2UPK3(r);
89924418Smckusick 			if( flags & 1 ) putchar('*');
90024418Smckusick 			if( flags & 4 ) putchar('-');
9019702Slinton 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
9029702Slinton 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
90324418Smckusick 			if( flags & 2 ) putchar('+');
9049702Slinton 			printf( "[%s]", rnames[R2UPK2(r)] );
9059702Slinton 			return;
9069702Slinton 			}
9079702Slinton 		if( r == AP ){  /* in the argument region */
90832925Sdonn 			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
9099702Slinton 			printf( CONFMT, p->tn.lval );
91024418Smckusick 			putstr( "(ap)" );
9119702Slinton 			return;
9129702Slinton 			}
9139702Slinton 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
9149702Slinton 		printf( "(%s)", rnames[p->tn.rval] );
9159702Slinton 		return;
9169702Slinton 
9179702Slinton 	case UNARY MUL:
9189702Slinton 		/* STARNM or STARREG found */
9199702Slinton 		if( tshape(p, STARNM) ) {
92024418Smckusick 			putchar( '*' );
9219702Slinton 			adrput( p->in.left);
9229702Slinton 			}
9239702Slinton 		else {	/* STARREG - really auto inc or dec */
9249702Slinton 			register NODE *q;
9259702Slinton 
9269702Slinton /* tbl
9279702Slinton 			p = p->in.left;
9289702Slinton 			p->in.left->in.op = OREG;
9299702Slinton 			if( p->in.op == INCR ) {
9309702Slinton 				adrput( p->in.left );
93124418Smckusick 				putchar( '+' );
9329702Slinton 				}
9339702Slinton 			else {
93424418Smckusick 				putchar( '-' );
9359702Slinton 				adrput( p->in.left );
9369702Slinton 				}
9379702Slinton    tbl */
93817659Sralph 			q = p->in.left;
93917742Sralph 			if( q->in.right->tn.lval != tlen(p) )
94017742Sralph 				cerror("adrput: bad auto-increment/decrement");
94117659Sralph 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
94217659Sralph 				rnames[q->in.left->tn.rval],
94317659Sralph 				(q->in.op==INCR ? "+" : "") );
9449702Slinton 			p->in.op = OREG;
94517659Sralph 			p->tn.rval = q->in.left->tn.rval;
94617659Sralph 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
9479702Slinton #ifndef FLEXNAMES
9489702Slinton 			p->in.name[0] = '\0';
9499702Slinton #else
9509702Slinton 			p->in.name = "";
9519702Slinton #endif
9529702Slinton 			tfree(q);
9539702Slinton 		}
9549702Slinton 		return;
9559702Slinton 
9569702Slinton 	default:
9579702Slinton 		cerror( "illegal address" );
9589702Slinton 		return;
9599702Slinton 
9609702Slinton 		}
9619702Slinton 
9629702Slinton 	}
9639702Slinton 
9649702Slinton acon( p ) register NODE *p; { /* print out a constant */
9659702Slinton 
9669702Slinton 	if( p->in.name[0] == '\0' ){
9679702Slinton 		printf( CONFMT, p->tn.lval);
9689702Slinton 		}
9699702Slinton 	else if( p->tn.lval == 0 ) {
9709702Slinton #ifndef FLEXNAMES
9719702Slinton 		printf( "%.8s", p->in.name );
9729702Slinton #else
97324418Smckusick 		putstr( p->in.name );
9749702Slinton #endif
9759702Slinton 		}
9769702Slinton 	else {
9779702Slinton #ifndef FLEXNAMES
9789702Slinton 		printf( "%.8s+", p->in.name );
9799702Slinton #else
9809702Slinton 		printf( "%s+", p->in.name );
9819702Slinton #endif
9829702Slinton 		printf( CONFMT, p->tn.lval );
9839702Slinton 		}
9849702Slinton 	}
9859702Slinton 
9869702Slinton /*
9879702Slinton aacon( p ) register NODE *p; { /* print out a constant */
9889702Slinton /*
9899702Slinton 
9909702Slinton 	if( p->in.name[0] == '\0' ){
9919702Slinton 		printf( CONFMT, p->tn.lval);
9929702Slinton 		return( 0 );
9939702Slinton 		}
9949702Slinton 	else if( p->tn.lval == 0 ) {
9959702Slinton #ifndef FLEXNAMES
9969702Slinton 		printf( "$%.8s", p->in.name );
9979702Slinton #else
9989702Slinton 		printf( "$%s", p->in.name );
9999702Slinton #endif
10009702Slinton 		return( 1 );
10019702Slinton 		}
10029702Slinton 	else {
10039702Slinton 		printf( "$(" );
10049702Slinton 		printf( CONFMT, p->tn.lval );
10059702Slinton 		printf( "+" );
10069702Slinton #ifndef FLEXNAMES
10079702Slinton 		printf( "%.8s)", p->in.name );
10089702Slinton #else
10099702Slinton 		printf( "%s)", p->in.name );
10109702Slinton #endif
10119702Slinton 		return(1);
10129702Slinton 		}
10139702Slinton 	}
10149702Slinton  */
10159702Slinton 
10169702Slinton genscall( p, cookie ) register NODE *p; {
10179702Slinton 	/* structure valued call */
10189702Slinton 	return( gencall( p, cookie ) );
10199702Slinton 	}
10209702Slinton 
10219702Slinton /* tbl */
10229702Slinton int gc_numbytes;
10239702Slinton /* tbl */
10249702Slinton 
102532924Sdonn /*ARGSUSED*/
10269702Slinton gencall( p, cookie ) register NODE *p; {
10279702Slinton 	/* generate the call given by p */
102816418Sralph 	register NODE *p1;
10299702Slinton 	register temp, temp1;
10309702Slinton 	register m;
10319702Slinton 
10329702Slinton 	if( p->in.right ) temp = argsize( p->in.right );
10339702Slinton 	else temp = 0;
10349702Slinton 
10359702Slinton 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
10369702Slinton 		/* set aside room for structure return */
10379702Slinton 
10389702Slinton 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
10399702Slinton 		else temp1 = temp;
10409702Slinton 		}
10419702Slinton 
10429702Slinton 	if( temp > maxargs ) maxargs = temp;
10439702Slinton 	SETOFF(temp1,4);
10449702Slinton 
10459702Slinton 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
104616418Sralph 		genargs( p->in.right );
10479702Slinton 		}
10489702Slinton 
10499702Slinton 	p1 = p->in.left;
10509702Slinton 	if( p1->in.op != ICON ){
10519702Slinton 		if( p1->in.op != REG ){
10529702Slinton 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
10539702Slinton 				if( p1->in.op != NAME ){
10549702Slinton 					order( p1, INAREG );
10559702Slinton 					}
10569702Slinton 				}
10579702Slinton 			}
10589702Slinton 		}
10599702Slinton 
10609702Slinton /*
10619702Slinton 	if( p1->in.op == REG && p->tn.rval == R5 ){
10629702Slinton 		cerror( "call register overwrite" );
10639702Slinton 		}
10649702Slinton  */
10659702Slinton /* tbl
10669702Slinton 	setup gc_numbytes so reference to ZC works */
10679702Slinton 
10689702Slinton 	gc_numbytes = temp&(0x3ff);
10699702Slinton /* tbl */
10709702Slinton 
10719702Slinton 	p->in.op = UNARY CALL;
10729702Slinton 	m = match( p, INTAREG|INTBREG );
10739702Slinton 
10749702Slinton 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
10759702Slinton 	/* (plus in assignment to gc_numbytes above, for neatness only) */
10769702Slinton 	if (temp >= 1024)
10779702Slinton 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
10789702Slinton 
10799702Slinton /* tbl
10809702Slinton 	switch( temp ) {
10819702Slinton 	case 0:
10829702Slinton 		break;
10839702Slinton 	case 2:
10849702Slinton 		printf( "	tst	(sp)+\n" );
10859702Slinton 		break;
10869702Slinton 	case 4:
10879702Slinton 		printf( "	cmp	(sp)+,(sp)+\n" );
10889702Slinton 		break;
10899702Slinton 	default:
10909702Slinton 		printf( "	add	$%d,sp\n", temp);
10919702Slinton 		}
10929702Slinton    tbl */
10939702Slinton 	return(m != MDONE);
10949702Slinton 	}
10959702Slinton 
10969702Slinton /* tbl */
10979702Slinton char *
10989702Slinton ccbranches[] = {
10999702Slinton 	"	jeql	L%d\n",
11009702Slinton 	"	jneq	L%d\n",
11019702Slinton 	"	jleq	L%d\n",
11029702Slinton 	"	jlss	L%d\n",
11039702Slinton 	"	jgeq	L%d\n",
11049702Slinton 	"	jgtr	L%d\n",
11059702Slinton 	"	jlequ	L%d\n",
11069702Slinton 	"	jlssu	L%d\n",
11079702Slinton 	"	jgequ	L%d\n",
11089702Slinton 	"	jgtru	L%d\n",
11099702Slinton 	};
11109702Slinton /* tbl */
11119702Slinton 
111232924Sdonn /*ARGSUSED*/
11139702Slinton cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
11149702Slinton 
11159702Slinton /* tbl */
11169702Slinton 	if( o == 0 ) printf( "	jbr	L%d\n", lab );
11179702Slinton /* tbl */
11189702Slinton 	else {
11199702Slinton 		if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
11209702Slinton 		printf( ccbranches[o-EQ], lab );
11219702Slinton 		}
11229702Slinton 	}
11239702Slinton 
11249702Slinton nextcook( p, cookie ) NODE *p; {
11259702Slinton 	/* we have failed to match p with cookie; try another */
11269702Slinton 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
11279702Slinton 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
11289702Slinton 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
11299702Slinton 	return( FORREW );
11309702Slinton 	}
11319702Slinton 
113232924Sdonn /*ARGSUSED*/
11339702Slinton lastchance( p, cook ) NODE *p; {
11349702Slinton 	/* forget it! */
11359702Slinton 	return(0);
11369702Slinton 	}
11379702Slinton 
11389702Slinton optim2( p ) register NODE *p; {
11399702Slinton 	/* do local tree transformations and optimizations */
11409702Slinton 
114116181Sralph 	register NODE *l, *r;
11429702Slinton 
11439702Slinton 	switch( p->in.op ) {
11449702Slinton 
11459702Slinton 	case AND:
114619933Smckusick 		/* commute L and R to eliminate complements and constants */
114716181Sralph 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
114816181Sralph 		    l->in.op == COMPL ) {
11499702Slinton 			p->in.left = p->in.right;
115016181Sralph 			p->in.right = l;
11519702Slinton 			}
11529702Slinton 	case ASG AND:
11539702Slinton 		/* change meaning of AND to ~R&L - bic on pdp11 */
11549702Slinton 		r = p->in.right;
115519933Smckusick 		if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */
11569702Slinton 			r->tn.lval = ~r->tn.lval;
11579702Slinton 			}
11589702Slinton 		else if( r->in.op==COMPL ) { /* ~~A => A */
11599702Slinton 			r->in.op = FREE;
11609702Slinton 			p->in.right = r->in.left;
11619702Slinton 			}
11629702Slinton 		else { /* insert complement node */
116316181Sralph 			p->in.right = l = talloc();
116416181Sralph 			l->in.op = COMPL;
116516181Sralph 			l->in.rall = NOPREF;
116616181Sralph 			l->in.type = r->in.type;
116716181Sralph 			l->in.left = r;
116816181Sralph 			l->in.right = NULL;
11699702Slinton 			}
11709702Slinton 		break;
11719702Slinton 
117216181Sralph 	case SCONV:
117319933Smckusick 		l = p->in.left;
117417742Sralph #if defined(FORT) || defined(SPRECC)
117516573Sralph 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
117619933Smckusick 		    l->in.type == FLOAT || l->in.type == DOUBLE )
117719933Smckusick 			return;
117816573Sralph #else
117919933Smckusick 		if( mixtypes(p, l) ) return;
118016573Sralph #endif
118132924Sdonn 		if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL )
118225751Sdonn 			return;
118325751Sdonn 
118419933Smckusick 		/* Only trust it to get it right if the size is the same */
118519933Smckusick 		if( tlen(p) != tlen(l) )
118619933Smckusick 			return;
118716181Sralph 
118816181Sralph 		/* clobber conversion */
118919933Smckusick 		if( l->in.op != FLD )
119016181Sralph 			l->in.type = p->in.type;
119116181Sralph 		ncopy( p, l );
119216181Sralph 		l->in.op = FREE;
119319933Smckusick 
119416181Sralph 		break;
119516181Sralph 
119624418Smckusick 	case ASSIGN:
119724418Smckusick 		/*
119824418Smckusick 		 * Conversions are equivalent to assignments;
119924418Smckusick 		 * when the two operations are combined,
120024418Smckusick 		 * we can sometimes zap the conversion.
120124418Smckusick 		 */
120224418Smckusick 		r = p->in.right;
120324418Smckusick 		l = p->in.left;
120424418Smckusick 		if ( r->in.op == SCONV &&
120524418Smckusick 		     !mixtypes(l, r) &&
120632922Sdonn 		     l->in.op != FLD &&
120724418Smckusick 		     tlen(l) == tlen(r) ) {
120824418Smckusick 				p->in.right = r->in.left;
120924418Smckusick 				r->in.op = FREE;
121024418Smckusick 			}
121124418Smckusick 		break;
121224418Smckusick 
12139702Slinton 		}
12149702Slinton 	}
12159702Slinton 
121632924Sdonn /*ARGSUSED*/
121717742Sralph NODE * addroreg(l) NODE *l;
12189702Slinton 				/* OREG was built in clocal()
12199702Slinton 				 * for an auto or formal parameter
12209702Slinton 				 * now its address is being taken
12219702Slinton 				 * local code must unwind it
12229702Slinton 				 * back to PLUS/MINUS REG ICON
12239702Slinton 				 * according to local conventions
12249702Slinton 				 */
12259702Slinton {
12269702Slinton 	cerror("address of OREG taken");
122717742Sralph 	/*NOTREACHED*/
12289702Slinton }
12299702Slinton 
12309702Slinton 
12319702Slinton 
12329702Slinton # ifndef ONEPASS
12339702Slinton main( argc, argv ) char *argv[]; {
12349702Slinton 	return( mainp2( argc, argv ) );
12359702Slinton 	}
12369702Slinton # endif
12379702Slinton 
12389702Slinton 
12399702Slinton /* added by jwf */
12409702Slinton struct functbl {
12419702Slinton 	int fop;
12429702Slinton 	TWORD ftype;
12439702Slinton 	char *func;
12449702Slinton 	} opfunc[] = {
12459702Slinton 	DIV,		TANY,	"udiv",
12469702Slinton 	MOD,		TANY,	"urem",
124717715Sralph 	ASG DIV,	TANY,	"audiv",
124817715Sralph 	ASG MOD,	TANY,	"aurem",
12499702Slinton 	0,	0,	0 };
12509702Slinton 
12519702Slinton hardops(p)  register NODE *p; {
12529702Slinton 	/* change hard to do operators into function calls.  */
12539702Slinton 	register NODE *q;
12549702Slinton 	register struct functbl *f;
12559702Slinton 	register o;
125617742Sralph 	NODE *old,*temp;
12579702Slinton 
12589702Slinton 	o = p->in.op;
125917742Sralph 	if( ! (optype(o)==BITYPE &&
126017742Sralph 	       (ISUNSIGNED(p->in.left->in.type) ||
126117742Sralph 		ISUNSIGNED(p->in.right->in.type))) )
126217742Sralph 		return;
12639702Slinton 
12649702Slinton 	for( f=opfunc; f->fop; f++ ) {
12659702Slinton 		if( o==f->fop ) goto convert;
12669702Slinton 		}
12679702Slinton 	return;
12689702Slinton 
12699702Slinton 	convert:
12709702Slinton 	if( asgop( o ) ) {
127117742Sralph 		old = NIL;
127217715Sralph 		switch( p->in.left->in.op ){
127317742Sralph 		case FLD:
127417742Sralph 			q = p->in.left->in.left;
127517742Sralph 			/*
127617742Sralph 			 * rewrite (lval.fld /= rval); as
127717742Sralph 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
127817742Sralph 			 * else the compiler will evaluate lval twice.
127917742Sralph 			 */
128017742Sralph 			if( q->in.op == UNARY MUL ){
128117742Sralph 				/* first allocate a temp storage */
128217742Sralph 				temp = talloc();
128317742Sralph 				temp->in.op = OREG;
128417742Sralph 				temp->tn.rval = TMPREG;
128517742Sralph 				temp->tn.lval = BITOOR(freetemp(1));
128617742Sralph 				temp->in.type = INCREF(p->in.type);
128717742Sralph #ifdef FLEXNAMES
128817742Sralph 				temp->in.name = "";
128917742Sralph #else
129017742Sralph 				temp->in.name[0] = '\0';
129117742Sralph #endif
129217742Sralph 				old = q->in.left;
129317742Sralph 				q->in.left = temp;
129417742Sralph 			}
129517742Sralph 			/* fall thru ... */
129617742Sralph 
129717715Sralph 		case REG:
129817715Sralph 		case NAME:
129917715Sralph 		case OREG:
130017715Sralph 			/* change ASG OP to a simple OP */
130117715Sralph 			q = talloc();
130217715Sralph 			q->in.op = NOASG p->in.op;
130317715Sralph 			q->in.rall = NOPREF;
130417715Sralph 			q->in.type = p->in.type;
130517715Sralph 			q->in.left = tcopy(p->in.left);
130617715Sralph 			q->in.right = p->in.right;
130717715Sralph 			p->in.op = ASSIGN;
130817715Sralph 			p->in.right = q;
130917715Sralph 			p = q;
131017715Sralph 			f -= 2; /* Note: this depends on the table order */
131117742Sralph 			/* on the right side only - replace *temp with
131217742Sralph 			 *(temp = &lval), build the assignment node */
131317742Sralph 			if( old ){
131417742Sralph 				temp = q->in.left->in.left; /* the "*" node */
131517742Sralph 				q = talloc();
131617742Sralph 				q->in.op = ASSIGN;
131717742Sralph 				q->in.left = temp->in.left;
131817742Sralph 				q->in.right = old;
131917742Sralph 				q->in.type = old->in.type;
132017742Sralph #ifdef FLEXNAMES
132117742Sralph 				q->in.name = "";
132217742Sralph #else
132317742Sralph 				q->in.name[0] = '\0';
132417742Sralph #endif
132517742Sralph 				temp->in.left = q;
132617742Sralph 			}
132717715Sralph 			break;
13289702Slinton 
132917715Sralph 		case UNARY MUL:
133017715Sralph 			/* avoid doing side effects twice */
133117715Sralph 			q = p->in.left;
133217715Sralph 			p->in.left = q->in.left;
133317715Sralph 			q->in.op = FREE;
133417715Sralph 			break;
133517715Sralph 
133617715Sralph 		default:
133717715Sralph 			cerror( "hardops: can't compute & LHS" );
133817715Sralph 			}
133917742Sralph 		}
134017715Sralph 
13419702Slinton 	/* build comma op for args to function */
13429702Slinton 	q = talloc();
13439702Slinton 	q->in.op = CM;
13449702Slinton 	q->in.rall = NOPREF;
13459702Slinton 	q->in.type = INT;
13469702Slinton 	q->in.left = p->in.left;
13479702Slinton 	q->in.right = p->in.right;
13489702Slinton 	p->in.op = CALL;
13499702Slinton 	p->in.right = q;
13509702Slinton 
13519702Slinton 	/* put function name in left node of call */
13529702Slinton 	p->in.left = q = talloc();
13539702Slinton 	q->in.op = ICON;
13549702Slinton 	q->in.rall = NOPREF;
13559702Slinton 	q->in.type = INCREF( FTN + p->in.type );
13569702Slinton #ifndef FLEXNAMES
13579702Slinton 	strcpy( q->in.name, f->func );
13589702Slinton #else
13599702Slinton 	q->in.name = f->func;
13609702Slinton #endif
13619702Slinton 	q->tn.lval = 0;
13629702Slinton 	q->tn.rval = 0;
13639702Slinton 
13649702Slinton 	}
13659702Slinton 
136617742Sralph zappost(p) NODE *p; {
136717742Sralph 	/* look for ++ and -- operators and remove them */
136817742Sralph 
136917742Sralph 	register o, ty;
137017742Sralph 	register NODE *q;
137117742Sralph 	o = p->in.op;
137217742Sralph 	ty = optype( o );
137317742Sralph 
137417742Sralph 	switch( o ){
137517742Sralph 
137617742Sralph 	case INCR:
137717742Sralph 	case DECR:
137817742Sralph 			q = p->in.left;
137917742Sralph 			p->in.right->in.op = FREE;  /* zap constant */
138017742Sralph 			ncopy( p, q );
138117742Sralph 			q->in.op = FREE;
138217742Sralph 			return;
138317742Sralph 
138417742Sralph 		}
138517742Sralph 
138617742Sralph 	if( ty == BITYPE ) zappost( p->in.right );
138717742Sralph 	if( ty != LTYPE ) zappost( p->in.left );
138817742Sralph }
138917742Sralph 
139017742Sralph fixpre(p) NODE *p; {
139117742Sralph 
139217742Sralph 	register o, ty;
139317742Sralph 	o = p->in.op;
139417742Sralph 	ty = optype( o );
139517742Sralph 
139617742Sralph 	switch( o ){
139717742Sralph 
139817742Sralph 	case ASG PLUS:
139917742Sralph 			p->in.op = PLUS;
140017742Sralph 			break;
140117742Sralph 	case ASG MINUS:
140217742Sralph 			p->in.op = MINUS;
140317742Sralph 			break;
140417742Sralph 		}
140517742Sralph 
140617742Sralph 	if( ty == BITYPE ) fixpre( p->in.right );
140717742Sralph 	if( ty != LTYPE ) fixpre( p->in.left );
140817742Sralph }
140917742Sralph 
141024418Smckusick strip(p) register NODE *p; {
141124418Smckusick 	NODE *q;
141224418Smckusick 
141324418Smckusick 	/* strip nodes off the top when no side effects occur */
141424418Smckusick 	for( ; ; ) {
141524418Smckusick 		switch( p->in.op ) {
141624418Smckusick 		case SCONV:			/* remove lint tidbits */
141724418Smckusick 			q = p->in.left;
141824418Smckusick 			ncopy( p, q );
141924418Smckusick 			q->in.op = FREE;
142024418Smckusick 			break;
142124418Smckusick 		/* could probably add a few more here */
142224418Smckusick 		default:
142324418Smckusick 			return;
142424418Smckusick 			}
142524418Smckusick 		}
142624418Smckusick 	}
142724418Smckusick 
14289702Slinton myreader(p) register NODE *p; {
142924418Smckusick 	strip( p );		/* strip off operations with no side effects */
143017742Sralph 	canon( p );		/* expands r-vals for fields */
14319702Slinton 	walkf( p, hardops );	/* convert ops to function calls */
14329702Slinton 	walkf( p, optim2 );
14339702Slinton 	/* jwf toff = 0;  /* stack offset swindle */
14349702Slinton 	}
1435