xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 32925)
117742Sralph # ifndef lint
2*32925Sdonn static char *sccsid ="@(#)local2.c	1.19 (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 
7569702Slinton shtemp( p ) register NODE *p; {
7579702Slinton 	if( p->in.op == STARG ) p = p->in.left;
7589702Slinton 	return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
7599702Slinton 	}
7609702Slinton 
7619702Slinton shumul( p ) register NODE *p; {
7629702Slinton 	register o;
7639702Slinton 	extern int xdebug;
7649702Slinton 
7659702Slinton 	if (xdebug) {
7669702Slinton 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
7679702Slinton 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
7689702Slinton 		}
7699702Slinton 
7709702Slinton 
7719702Slinton 	o = p->in.op;
7729702Slinton 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
7739702Slinton 
7749702Slinton 	if( ( o == INCR || o == ASG MINUS ) &&
7759702Slinton 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
7769702Slinton 	    p->in.right->in.name[0] == '\0' )
7779702Slinton 		{
77817659Sralph 		switch (p->in.type)
7799702Slinton 			{
7809702Slinton 			case CHAR|PTR:
7819702Slinton 			case UCHAR|PTR:
7829702Slinton 				o = 1;
7839702Slinton 				break;
7849702Slinton 
7859702Slinton 			case SHORT|PTR:
7869702Slinton 			case USHORT|PTR:
7879702Slinton 				o = 2;
7889702Slinton 				break;
7899702Slinton 
7909702Slinton 			case INT|PTR:
7919702Slinton 			case UNSIGNED|PTR:
7929702Slinton 			case LONG|PTR:
7939702Slinton 			case ULONG|PTR:
7949702Slinton 			case FLOAT|PTR:
7959702Slinton 				o = 4;
7969702Slinton 				break;
7979702Slinton 
7989702Slinton 			case DOUBLE|PTR:
7999702Slinton 				o = 8;
8009702Slinton 				break;
8019702Slinton 
8029702Slinton 			default:
80317742Sralph 				if ( ISPTR(p->in.type) &&
80417742Sralph 				     ISPTR(DECREF(p->in.type)) ) {
8059702Slinton 					o = 4;
8069702Slinton 					break;
8079702Slinton 					}
8089702Slinton 				else return(0);
8099702Slinton 			}
8109702Slinton 		return( p->in.right->tn.lval == o ? STARREG : 0);
8119702Slinton 		}
8129702Slinton 
8139702Slinton 	return( 0 );
8149702Slinton 	}
8159702Slinton 
8169702Slinton adrcon( val ) CONSZ val; {
81724418Smckusick 	putchar( '$' );
8189702Slinton 	printf( CONFMT, val );
8199702Slinton 	}
8209702Slinton 
8219702Slinton conput( p ) register NODE *p; {
8229702Slinton 	switch( p->in.op ){
8239702Slinton 
8249702Slinton 	case ICON:
8259702Slinton 		acon( p );
8269702Slinton 		return;
8279702Slinton 
8289702Slinton 	case REG:
82924418Smckusick 		putstr( rnames[p->tn.rval] );
8309702Slinton 		return;
8319702Slinton 
8329702Slinton 	default:
8339702Slinton 		cerror( "illegal conput" );
8349702Slinton 		}
8359702Slinton 	}
8369702Slinton 
83732923Sdonn /*ARGSUSED*/
83832924Sdonn insput( p ) NODE *p; {
8399702Slinton 	cerror( "insput" );
8409702Slinton 	}
8419702Slinton 
84232923Sdonn /*ARGSUSED*/
84332924Sdonn upput( p, off ) NODE *p; int off; {
8449702Slinton 	cerror( "upput" );
8459702Slinton 	}
8469702Slinton 
8479702Slinton adrput( p ) register NODE *p; {
8489702Slinton 	register int r;
8499702Slinton 	/* output an address, with offsets, from p */
8509702Slinton 
8519702Slinton 	if( p->in.op == FLD ){
8529702Slinton 		p = p->in.left;
8539702Slinton 		}
8549702Slinton 	switch( p->in.op ){
8559702Slinton 
8569702Slinton 	case NAME:
8579702Slinton 		acon( p );
8589702Slinton 		return;
8599702Slinton 
8609702Slinton 	case ICON:
8619702Slinton 		/* addressable value of the constant */
86224418Smckusick 		putchar( '$' );
8639702Slinton 		acon( p );
8649702Slinton 		return;
8659702Slinton 
8669702Slinton 	case REG:
86724418Smckusick 		putstr( rnames[p->tn.rval] );
8689702Slinton 		return;
8699702Slinton 
8709702Slinton 	case OREG:
8719702Slinton 		r = p->tn.rval;
8729702Slinton 		if( R2TEST(r) ){ /* double indexing */
8739702Slinton 			register int flags;
8749702Slinton 
8759702Slinton 			flags = R2UPK3(r);
87624418Smckusick 			if( flags & 1 ) putchar('*');
87724418Smckusick 			if( flags & 4 ) putchar('-');
8789702Slinton 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
8799702Slinton 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
88024418Smckusick 			if( flags & 2 ) putchar('+');
8819702Slinton 			printf( "[%s]", rnames[R2UPK2(r)] );
8829702Slinton 			return;
8839702Slinton 			}
8849702Slinton 		if( r == AP ){  /* in the argument region */
885*32925Sdonn 			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
8869702Slinton 			printf( CONFMT, p->tn.lval );
88724418Smckusick 			putstr( "(ap)" );
8889702Slinton 			return;
8899702Slinton 			}
8909702Slinton 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
8919702Slinton 		printf( "(%s)", rnames[p->tn.rval] );
8929702Slinton 		return;
8939702Slinton 
8949702Slinton 	case UNARY MUL:
8959702Slinton 		/* STARNM or STARREG found */
8969702Slinton 		if( tshape(p, STARNM) ) {
89724418Smckusick 			putchar( '*' );
8989702Slinton 			adrput( p->in.left);
8999702Slinton 			}
9009702Slinton 		else {	/* STARREG - really auto inc or dec */
9019702Slinton 			register NODE *q;
9029702Slinton 
9039702Slinton /* tbl
9049702Slinton 			p = p->in.left;
9059702Slinton 			p->in.left->in.op = OREG;
9069702Slinton 			if( p->in.op == INCR ) {
9079702Slinton 				adrput( p->in.left );
90824418Smckusick 				putchar( '+' );
9099702Slinton 				}
9109702Slinton 			else {
91124418Smckusick 				putchar( '-' );
9129702Slinton 				adrput( p->in.left );
9139702Slinton 				}
9149702Slinton    tbl */
91517659Sralph 			q = p->in.left;
91617742Sralph 			if( q->in.right->tn.lval != tlen(p) )
91717742Sralph 				cerror("adrput: bad auto-increment/decrement");
91817659Sralph 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
91917659Sralph 				rnames[q->in.left->tn.rval],
92017659Sralph 				(q->in.op==INCR ? "+" : "") );
9219702Slinton 			p->in.op = OREG;
92217659Sralph 			p->tn.rval = q->in.left->tn.rval;
92317659Sralph 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
9249702Slinton #ifndef FLEXNAMES
9259702Slinton 			p->in.name[0] = '\0';
9269702Slinton #else
9279702Slinton 			p->in.name = "";
9289702Slinton #endif
9299702Slinton 			tfree(q);
9309702Slinton 		}
9319702Slinton 		return;
9329702Slinton 
9339702Slinton 	default:
9349702Slinton 		cerror( "illegal address" );
9359702Slinton 		return;
9369702Slinton 
9379702Slinton 		}
9389702Slinton 
9399702Slinton 	}
9409702Slinton 
9419702Slinton acon( p ) register NODE *p; { /* print out a constant */
9429702Slinton 
9439702Slinton 	if( p->in.name[0] == '\0' ){
9449702Slinton 		printf( CONFMT, p->tn.lval);
9459702Slinton 		}
9469702Slinton 	else if( p->tn.lval == 0 ) {
9479702Slinton #ifndef FLEXNAMES
9489702Slinton 		printf( "%.8s", p->in.name );
9499702Slinton #else
95024418Smckusick 		putstr( p->in.name );
9519702Slinton #endif
9529702Slinton 		}
9539702Slinton 	else {
9549702Slinton #ifndef FLEXNAMES
9559702Slinton 		printf( "%.8s+", p->in.name );
9569702Slinton #else
9579702Slinton 		printf( "%s+", p->in.name );
9589702Slinton #endif
9599702Slinton 		printf( CONFMT, p->tn.lval );
9609702Slinton 		}
9619702Slinton 	}
9629702Slinton 
9639702Slinton /*
9649702Slinton aacon( p ) register NODE *p; { /* print out a constant */
9659702Slinton /*
9669702Slinton 
9679702Slinton 	if( p->in.name[0] == '\0' ){
9689702Slinton 		printf( CONFMT, p->tn.lval);
9699702Slinton 		return( 0 );
9709702Slinton 		}
9719702Slinton 	else if( p->tn.lval == 0 ) {
9729702Slinton #ifndef FLEXNAMES
9739702Slinton 		printf( "$%.8s", p->in.name );
9749702Slinton #else
9759702Slinton 		printf( "$%s", p->in.name );
9769702Slinton #endif
9779702Slinton 		return( 1 );
9789702Slinton 		}
9799702Slinton 	else {
9809702Slinton 		printf( "$(" );
9819702Slinton 		printf( CONFMT, p->tn.lval );
9829702Slinton 		printf( "+" );
9839702Slinton #ifndef FLEXNAMES
9849702Slinton 		printf( "%.8s)", p->in.name );
9859702Slinton #else
9869702Slinton 		printf( "%s)", p->in.name );
9879702Slinton #endif
9889702Slinton 		return(1);
9899702Slinton 		}
9909702Slinton 	}
9919702Slinton  */
9929702Slinton 
9939702Slinton genscall( p, cookie ) register NODE *p; {
9949702Slinton 	/* structure valued call */
9959702Slinton 	return( gencall( p, cookie ) );
9969702Slinton 	}
9979702Slinton 
9989702Slinton /* tbl */
9999702Slinton int gc_numbytes;
10009702Slinton /* tbl */
10019702Slinton 
100232924Sdonn /*ARGSUSED*/
10039702Slinton gencall( p, cookie ) register NODE *p; {
10049702Slinton 	/* generate the call given by p */
100516418Sralph 	register NODE *p1;
10069702Slinton 	register temp, temp1;
10079702Slinton 	register m;
10089702Slinton 
10099702Slinton 	if( p->in.right ) temp = argsize( p->in.right );
10109702Slinton 	else temp = 0;
10119702Slinton 
10129702Slinton 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
10139702Slinton 		/* set aside room for structure return */
10149702Slinton 
10159702Slinton 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
10169702Slinton 		else temp1 = temp;
10179702Slinton 		}
10189702Slinton 
10199702Slinton 	if( temp > maxargs ) maxargs = temp;
10209702Slinton 	SETOFF(temp1,4);
10219702Slinton 
10229702Slinton 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
102316418Sralph 		genargs( p->in.right );
10249702Slinton 		}
10259702Slinton 
10269702Slinton 	p1 = p->in.left;
10279702Slinton 	if( p1->in.op != ICON ){
10289702Slinton 		if( p1->in.op != REG ){
10299702Slinton 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
10309702Slinton 				if( p1->in.op != NAME ){
10319702Slinton 					order( p1, INAREG );
10329702Slinton 					}
10339702Slinton 				}
10349702Slinton 			}
10359702Slinton 		}
10369702Slinton 
10379702Slinton /*
10389702Slinton 	if( p1->in.op == REG && p->tn.rval == R5 ){
10399702Slinton 		cerror( "call register overwrite" );
10409702Slinton 		}
10419702Slinton  */
10429702Slinton /* tbl
10439702Slinton 	setup gc_numbytes so reference to ZC works */
10449702Slinton 
10459702Slinton 	gc_numbytes = temp&(0x3ff);
10469702Slinton /* tbl */
10479702Slinton 
10489702Slinton 	p->in.op = UNARY CALL;
10499702Slinton 	m = match( p, INTAREG|INTBREG );
10509702Slinton 
10519702Slinton 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
10529702Slinton 	/* (plus in assignment to gc_numbytes above, for neatness only) */
10539702Slinton 	if (temp >= 1024)
10549702Slinton 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
10559702Slinton 
10569702Slinton /* tbl
10579702Slinton 	switch( temp ) {
10589702Slinton 	case 0:
10599702Slinton 		break;
10609702Slinton 	case 2:
10619702Slinton 		printf( "	tst	(sp)+\n" );
10629702Slinton 		break;
10639702Slinton 	case 4:
10649702Slinton 		printf( "	cmp	(sp)+,(sp)+\n" );
10659702Slinton 		break;
10669702Slinton 	default:
10679702Slinton 		printf( "	add	$%d,sp\n", temp);
10689702Slinton 		}
10699702Slinton    tbl */
10709702Slinton 	return(m != MDONE);
10719702Slinton 	}
10729702Slinton 
10739702Slinton /* tbl */
10749702Slinton char *
10759702Slinton ccbranches[] = {
10769702Slinton 	"	jeql	L%d\n",
10779702Slinton 	"	jneq	L%d\n",
10789702Slinton 	"	jleq	L%d\n",
10799702Slinton 	"	jlss	L%d\n",
10809702Slinton 	"	jgeq	L%d\n",
10819702Slinton 	"	jgtr	L%d\n",
10829702Slinton 	"	jlequ	L%d\n",
10839702Slinton 	"	jlssu	L%d\n",
10849702Slinton 	"	jgequ	L%d\n",
10859702Slinton 	"	jgtru	L%d\n",
10869702Slinton 	};
10879702Slinton /* tbl */
10889702Slinton 
108932924Sdonn /*ARGSUSED*/
10909702Slinton cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
10919702Slinton 
10929702Slinton /* tbl */
10939702Slinton 	if( o == 0 ) printf( "	jbr	L%d\n", lab );
10949702Slinton /* tbl */
10959702Slinton 	else {
10969702Slinton 		if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
10979702Slinton 		printf( ccbranches[o-EQ], lab );
10989702Slinton 		}
10999702Slinton 	}
11009702Slinton 
11019702Slinton nextcook( p, cookie ) NODE *p; {
11029702Slinton 	/* we have failed to match p with cookie; try another */
11039702Slinton 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
11049702Slinton 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
11059702Slinton 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
11069702Slinton 	return( FORREW );
11079702Slinton 	}
11089702Slinton 
110932924Sdonn /*ARGSUSED*/
11109702Slinton lastchance( p, cook ) NODE *p; {
11119702Slinton 	/* forget it! */
11129702Slinton 	return(0);
11139702Slinton 	}
11149702Slinton 
11159702Slinton optim2( p ) register NODE *p; {
11169702Slinton 	/* do local tree transformations and optimizations */
11179702Slinton 
111816181Sralph 	register NODE *l, *r;
11199702Slinton 
11209702Slinton 	switch( p->in.op ) {
11219702Slinton 
11229702Slinton 	case AND:
112319933Smckusick 		/* commute L and R to eliminate complements and constants */
112416181Sralph 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
112516181Sralph 		    l->in.op == COMPL ) {
11269702Slinton 			p->in.left = p->in.right;
112716181Sralph 			p->in.right = l;
11289702Slinton 			}
11299702Slinton 	case ASG AND:
11309702Slinton 		/* change meaning of AND to ~R&L - bic on pdp11 */
11319702Slinton 		r = p->in.right;
113219933Smckusick 		if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */
11339702Slinton 			r->tn.lval = ~r->tn.lval;
11349702Slinton 			}
11359702Slinton 		else if( r->in.op==COMPL ) { /* ~~A => A */
11369702Slinton 			r->in.op = FREE;
11379702Slinton 			p->in.right = r->in.left;
11389702Slinton 			}
11399702Slinton 		else { /* insert complement node */
114016181Sralph 			p->in.right = l = talloc();
114116181Sralph 			l->in.op = COMPL;
114216181Sralph 			l->in.rall = NOPREF;
114316181Sralph 			l->in.type = r->in.type;
114416181Sralph 			l->in.left = r;
114516181Sralph 			l->in.right = NULL;
11469702Slinton 			}
11479702Slinton 		break;
11489702Slinton 
114916181Sralph 	case SCONV:
115019933Smckusick 		l = p->in.left;
115117742Sralph #if defined(FORT) || defined(SPRECC)
115216573Sralph 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
115319933Smckusick 		    l->in.type == FLOAT || l->in.type == DOUBLE )
115419933Smckusick 			return;
115516573Sralph #else
115619933Smckusick 		if( mixtypes(p, l) ) return;
115716573Sralph #endif
115832924Sdonn 		if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL )
115925751Sdonn 			return;
116025751Sdonn 
116119933Smckusick 		/* Only trust it to get it right if the size is the same */
116219933Smckusick 		if( tlen(p) != tlen(l) )
116319933Smckusick 			return;
116416181Sralph 
116516181Sralph 		/* clobber conversion */
116619933Smckusick 		if( l->in.op != FLD )
116716181Sralph 			l->in.type = p->in.type;
116816181Sralph 		ncopy( p, l );
116916181Sralph 		l->in.op = FREE;
117019933Smckusick 
117116181Sralph 		break;
117216181Sralph 
117324418Smckusick 	case ASSIGN:
117424418Smckusick 		/*
117524418Smckusick 		 * Conversions are equivalent to assignments;
117624418Smckusick 		 * when the two operations are combined,
117724418Smckusick 		 * we can sometimes zap the conversion.
117824418Smckusick 		 */
117924418Smckusick 		r = p->in.right;
118024418Smckusick 		l = p->in.left;
118124418Smckusick 		if ( r->in.op == SCONV &&
118224418Smckusick 		     !mixtypes(l, r) &&
118332922Sdonn 		     l->in.op != FLD &&
118424418Smckusick 		     tlen(l) == tlen(r) ) {
118524418Smckusick 				p->in.right = r->in.left;
118624418Smckusick 				r->in.op = FREE;
118724418Smckusick 			}
118824418Smckusick 		break;
118924418Smckusick 
11909702Slinton 		}
11919702Slinton 	}
11929702Slinton 
119332924Sdonn /*ARGSUSED*/
119417742Sralph NODE * addroreg(l) NODE *l;
11959702Slinton 				/* OREG was built in clocal()
11969702Slinton 				 * for an auto or formal parameter
11979702Slinton 				 * now its address is being taken
11989702Slinton 				 * local code must unwind it
11999702Slinton 				 * back to PLUS/MINUS REG ICON
12009702Slinton 				 * according to local conventions
12019702Slinton 				 */
12029702Slinton {
12039702Slinton 	cerror("address of OREG taken");
120417742Sralph 	/*NOTREACHED*/
12059702Slinton }
12069702Slinton 
12079702Slinton 
12089702Slinton 
12099702Slinton # ifndef ONEPASS
12109702Slinton main( argc, argv ) char *argv[]; {
12119702Slinton 	return( mainp2( argc, argv ) );
12129702Slinton 	}
12139702Slinton # endif
12149702Slinton 
12159702Slinton 
12169702Slinton /* added by jwf */
12179702Slinton struct functbl {
12189702Slinton 	int fop;
12199702Slinton 	TWORD ftype;
12209702Slinton 	char *func;
12219702Slinton 	} opfunc[] = {
12229702Slinton 	DIV,		TANY,	"udiv",
12239702Slinton 	MOD,		TANY,	"urem",
122417715Sralph 	ASG DIV,	TANY,	"audiv",
122517715Sralph 	ASG MOD,	TANY,	"aurem",
12269702Slinton 	0,	0,	0 };
12279702Slinton 
12289702Slinton hardops(p)  register NODE *p; {
12299702Slinton 	/* change hard to do operators into function calls.  */
12309702Slinton 	register NODE *q;
12319702Slinton 	register struct functbl *f;
12329702Slinton 	register o;
123317742Sralph 	NODE *old,*temp;
12349702Slinton 
12359702Slinton 	o = p->in.op;
123617742Sralph 	if( ! (optype(o)==BITYPE &&
123717742Sralph 	       (ISUNSIGNED(p->in.left->in.type) ||
123817742Sralph 		ISUNSIGNED(p->in.right->in.type))) )
123917742Sralph 		return;
12409702Slinton 
12419702Slinton 	for( f=opfunc; f->fop; f++ ) {
12429702Slinton 		if( o==f->fop ) goto convert;
12439702Slinton 		}
12449702Slinton 	return;
12459702Slinton 
12469702Slinton 	convert:
12479702Slinton 	if( asgop( o ) ) {
124817742Sralph 		old = NIL;
124917715Sralph 		switch( p->in.left->in.op ){
125017742Sralph 		case FLD:
125117742Sralph 			q = p->in.left->in.left;
125217742Sralph 			/*
125317742Sralph 			 * rewrite (lval.fld /= rval); as
125417742Sralph 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
125517742Sralph 			 * else the compiler will evaluate lval twice.
125617742Sralph 			 */
125717742Sralph 			if( q->in.op == UNARY MUL ){
125817742Sralph 				/* first allocate a temp storage */
125917742Sralph 				temp = talloc();
126017742Sralph 				temp->in.op = OREG;
126117742Sralph 				temp->tn.rval = TMPREG;
126217742Sralph 				temp->tn.lval = BITOOR(freetemp(1));
126317742Sralph 				temp->in.type = INCREF(p->in.type);
126417742Sralph #ifdef FLEXNAMES
126517742Sralph 				temp->in.name = "";
126617742Sralph #else
126717742Sralph 				temp->in.name[0] = '\0';
126817742Sralph #endif
126917742Sralph 				old = q->in.left;
127017742Sralph 				q->in.left = temp;
127117742Sralph 			}
127217742Sralph 			/* fall thru ... */
127317742Sralph 
127417715Sralph 		case REG:
127517715Sralph 		case NAME:
127617715Sralph 		case OREG:
127717715Sralph 			/* change ASG OP to a simple OP */
127817715Sralph 			q = talloc();
127917715Sralph 			q->in.op = NOASG p->in.op;
128017715Sralph 			q->in.rall = NOPREF;
128117715Sralph 			q->in.type = p->in.type;
128217715Sralph 			q->in.left = tcopy(p->in.left);
128317715Sralph 			q->in.right = p->in.right;
128417715Sralph 			p->in.op = ASSIGN;
128517715Sralph 			p->in.right = q;
128617715Sralph 			p = q;
128717715Sralph 			f -= 2; /* Note: this depends on the table order */
128817742Sralph 			/* on the right side only - replace *temp with
128917742Sralph 			 *(temp = &lval), build the assignment node */
129017742Sralph 			if( old ){
129117742Sralph 				temp = q->in.left->in.left; /* the "*" node */
129217742Sralph 				q = talloc();
129317742Sralph 				q->in.op = ASSIGN;
129417742Sralph 				q->in.left = temp->in.left;
129517742Sralph 				q->in.right = old;
129617742Sralph 				q->in.type = old->in.type;
129717742Sralph #ifdef FLEXNAMES
129817742Sralph 				q->in.name = "";
129917742Sralph #else
130017742Sralph 				q->in.name[0] = '\0';
130117742Sralph #endif
130217742Sralph 				temp->in.left = q;
130317742Sralph 			}
130417715Sralph 			break;
13059702Slinton 
130617715Sralph 		case UNARY MUL:
130717715Sralph 			/* avoid doing side effects twice */
130817715Sralph 			q = p->in.left;
130917715Sralph 			p->in.left = q->in.left;
131017715Sralph 			q->in.op = FREE;
131117715Sralph 			break;
131217715Sralph 
131317715Sralph 		default:
131417715Sralph 			cerror( "hardops: can't compute & LHS" );
131517715Sralph 			}
131617742Sralph 		}
131717715Sralph 
13189702Slinton 	/* build comma op for args to function */
13199702Slinton 	q = talloc();
13209702Slinton 	q->in.op = CM;
13219702Slinton 	q->in.rall = NOPREF;
13229702Slinton 	q->in.type = INT;
13239702Slinton 	q->in.left = p->in.left;
13249702Slinton 	q->in.right = p->in.right;
13259702Slinton 	p->in.op = CALL;
13269702Slinton 	p->in.right = q;
13279702Slinton 
13289702Slinton 	/* put function name in left node of call */
13299702Slinton 	p->in.left = q = talloc();
13309702Slinton 	q->in.op = ICON;
13319702Slinton 	q->in.rall = NOPREF;
13329702Slinton 	q->in.type = INCREF( FTN + p->in.type );
13339702Slinton #ifndef FLEXNAMES
13349702Slinton 	strcpy( q->in.name, f->func );
13359702Slinton #else
13369702Slinton 	q->in.name = f->func;
13379702Slinton #endif
13389702Slinton 	q->tn.lval = 0;
13399702Slinton 	q->tn.rval = 0;
13409702Slinton 
13419702Slinton 	}
13429702Slinton 
134317742Sralph zappost(p) NODE *p; {
134417742Sralph 	/* look for ++ and -- operators and remove them */
134517742Sralph 
134617742Sralph 	register o, ty;
134717742Sralph 	register NODE *q;
134817742Sralph 	o = p->in.op;
134917742Sralph 	ty = optype( o );
135017742Sralph 
135117742Sralph 	switch( o ){
135217742Sralph 
135317742Sralph 	case INCR:
135417742Sralph 	case DECR:
135517742Sralph 			q = p->in.left;
135617742Sralph 			p->in.right->in.op = FREE;  /* zap constant */
135717742Sralph 			ncopy( p, q );
135817742Sralph 			q->in.op = FREE;
135917742Sralph 			return;
136017742Sralph 
136117742Sralph 		}
136217742Sralph 
136317742Sralph 	if( ty == BITYPE ) zappost( p->in.right );
136417742Sralph 	if( ty != LTYPE ) zappost( p->in.left );
136517742Sralph }
136617742Sralph 
136717742Sralph fixpre(p) NODE *p; {
136817742Sralph 
136917742Sralph 	register o, ty;
137017742Sralph 	o = p->in.op;
137117742Sralph 	ty = optype( o );
137217742Sralph 
137317742Sralph 	switch( o ){
137417742Sralph 
137517742Sralph 	case ASG PLUS:
137617742Sralph 			p->in.op = PLUS;
137717742Sralph 			break;
137817742Sralph 	case ASG MINUS:
137917742Sralph 			p->in.op = MINUS;
138017742Sralph 			break;
138117742Sralph 		}
138217742Sralph 
138317742Sralph 	if( ty == BITYPE ) fixpre( p->in.right );
138417742Sralph 	if( ty != LTYPE ) fixpre( p->in.left );
138517742Sralph }
138617742Sralph 
138724418Smckusick strip(p) register NODE *p; {
138824418Smckusick 	NODE *q;
138924418Smckusick 
139024418Smckusick 	/* strip nodes off the top when no side effects occur */
139124418Smckusick 	for( ; ; ) {
139224418Smckusick 		switch( p->in.op ) {
139324418Smckusick 		case SCONV:			/* remove lint tidbits */
139424418Smckusick 			q = p->in.left;
139524418Smckusick 			ncopy( p, q );
139624418Smckusick 			q->in.op = FREE;
139724418Smckusick 			break;
139824418Smckusick 		/* could probably add a few more here */
139924418Smckusick 		default:
140024418Smckusick 			return;
140124418Smckusick 			}
140224418Smckusick 		}
140324418Smckusick 	}
140424418Smckusick 
14059702Slinton myreader(p) register NODE *p; {
140624418Smckusick 	strip( p );		/* strip off operations with no side effects */
140717742Sralph 	canon( p );		/* expands r-vals for fields */
14089702Slinton 	walkf( p, hardops );	/* convert ops to function calls */
14099702Slinton 	walkf( p, optim2 );
14109702Slinton 	/* jwf toff = 0;  /* stack offset swindle */
14119702Slinton 	}
1412