xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 32932)
117742Sralph # ifndef lint
2*32932Sdonn static char *sccsid ="@(#)local2.c	1.26 (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 
41732928Sdonn 	case 'J':	/* unsigned DIV/MOD with constant divisors */
41832928Sdonn 		{
41932928Sdonn 		register int ck = INAREG;
42032928Sdonn 		int label1, label2;
42132928Sdonn 
42232928Sdonn 		/* case constant <= 1 is handled by optim() in pass 1 */
42332928Sdonn 		/* case constant < 0x80000000 is handled in table */
42432928Sdonn 		switch( p->in.op ) {
42532928Sdonn 		/* case DIV: handled in hardops() */
42632928Sdonn 		case MOD:
42732928Sdonn 			if( p->in.left->in.op == REG &&
42832928Sdonn 			    p->in.left->tn.rval == resc->tn.rval )
42932928Sdonn 				goto asgmod;
43032928Sdonn 			label1 = getlab();
43132928Sdonn 			expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n");
43232928Sdonn 			printf("\tjlssu\tL%d\n", label1);
43332928Sdonn 			expand(p, ck, "\tsubl2\tAR,A1\n");
43432928Sdonn 			printf("L%d:", label1);
43532928Sdonn 			break;
43632928Sdonn 		case ASG DIV:
43732928Sdonn 			label1 = getlab();
43832928Sdonn 			label2 = getlab();
43932928Sdonn 			expand(p, ck, "cmpl\tAL,AR\n");
44032928Sdonn 			printf("\tjgequ\tL%d\n", label1);
44132928Sdonn 			expand(p, ck, "\tmovl\t$1,AL\n");
44232928Sdonn 			printf("\tjbr\tL%d\nL%d:\n", label2, label1);
44332928Sdonn 			expand(p, ck, "\tclrl\tAL\n");
44432928Sdonn 			printf("L%d:", label2);
44532928Sdonn 			break;
44632928Sdonn 		case ASG MOD:
44732928Sdonn 		asgmod:
44832928Sdonn 			label1 = getlab();
44932928Sdonn 			expand(p, ck, "cmpl\tAL,AR\n");
45032928Sdonn 			printf("\tjlssu\tL%d\n", label1);
45132928Sdonn 			expand(p, ck, "\tsubl2\tAR,AL\n");
45232928Sdonn 			printf("L%d:", label1);
45332928Sdonn 			break;
45432928Sdonn 			}
45532928Sdonn 		return;
45632928Sdonn 		}
45732928Sdonn 
4589702Slinton 	case 'B':	/* get oreg value in temp register for left shift */
4599702Slinton 		{
4609702Slinton 		register NODE *r;
4619702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
4629702Slinton 		r = p->in.right;
4639702Slinton 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
46424418Smckusick 			putstr("movl");
4659702Slinton 		else {
46624418Smckusick 			putstr("cvt");
4679702Slinton 			prtype(r);
46824418Smckusick 			putchar('l');
4699702Slinton 			}
4709702Slinton 		return;
4719702Slinton 		}
4729702Slinton 
4739702Slinton 	case 'C':	/* num words pushed on arg stack */
4749702Slinton 		{
4759702Slinton 		extern int gc_numbytes;
4769702Slinton 		extern int xdebug;
4779702Slinton 
4789702Slinton 		if (xdebug) printf("->%d<-",gc_numbytes);
4799702Slinton 
4809702Slinton 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
4819702Slinton 		return;
4829702Slinton 		}
4839702Slinton 
4849702Slinton 	case 'D':	/* INCR and DECR */
4859702Slinton 		zzzcode(p->in.left, 'A');
48624418Smckusick 		putchar('\n');
48724418Smckusick 		putchar('\t');
4889702Slinton 
4899702Slinton 	case 'E':	/* INCR and DECR, FOREFF */
4909702Slinton 		if (p->in.right->tn.lval == 1)
4919702Slinton 			{
49224418Smckusick 			putstr( p->in.op == INCR ? "inc" : "dec" );
4939702Slinton 			prtype(p->in.left);
49424418Smckusick 			putchar('\t');
4959702Slinton 			adrput(p->in.left);
4969702Slinton 			return;
4979702Slinton 			}
49824418Smckusick 		putstr( p->in.op == INCR ? "add" : "sub" );
4999702Slinton 		prtype(p->in.left);
50024418Smckusick 		putchar('2');
50124418Smckusick 		putchar('\t');
5029702Slinton 		adrput(p->in.right);
50324418Smckusick 		putchar(',');
5049702Slinton 		adrput(p->in.left);
5059702Slinton 		return;
5069702Slinton 
5079702Slinton 	case 'F':	/* register type of right operand */
5089702Slinton 		{
5099702Slinton 		register NODE *n;
5109702Slinton 		extern int xdebug;
5119702Slinton 		register int ty;
5129702Slinton 
5139702Slinton 		n = getlr( p, 'R' );
5149702Slinton 		ty = n->in.type;
5159702Slinton 
5169702Slinton 		if (xdebug) printf("->%d<-", ty);
5179702Slinton 
51824418Smckusick 		if ( ty==DOUBLE) putchar('d');
51924418Smckusick 		else if ( ty==FLOAT ) putchar('f');
52024418Smckusick 		else putchar('l');
5219702Slinton 		return;
5229702Slinton 		}
5239702Slinton 
5249702Slinton 	case 'L':	/* type of left operand */
5259702Slinton 	case 'R':	/* type of right operand */
5269702Slinton 		{
5279702Slinton 		register NODE *n;
5289702Slinton 		extern int xdebug;
5299702Slinton 
53016181Sralph 		n = getlr( p, c );
5319702Slinton 		if (xdebug) printf("->%d<-", n->in.type);
5329702Slinton 
5339702Slinton 		prtype(n);
5349702Slinton 		return;
5359702Slinton 		}
5369702Slinton 
5379702Slinton 	case 'Z':	/* complement mask for bit instr */
5389702Slinton 		printf("$%ld", ~p->in.right->tn.lval);
5399702Slinton 		return;
5409702Slinton 
5419702Slinton 	case 'U':	/* 32 - n, for unsigned right shifts */
5429702Slinton 		printf("$%d", 32 - p->in.right->tn.lval );
5439702Slinton 		return;
5449702Slinton 
5459702Slinton 	case 'T':	/* rounded structure length for arguments */
5469702Slinton 		{
5479702Slinton 		int size;
5489702Slinton 
5499702Slinton 		size = p->stn.stsize;
5509702Slinton 		SETOFF( size, 4);
5519702Slinton 		printf("$%d", size);
5529702Slinton 		return;
5539702Slinton 		}
5549702Slinton 
5559702Slinton 	case 'S':  /* structure assignment */
5569702Slinton 		{
5579702Slinton 			register NODE *l, *r;
5589702Slinton 			register size;
5599702Slinton 
5609702Slinton 			if( p->in.op == STASG ){
5619702Slinton 				l = p->in.left;
5629702Slinton 				r = p->in.right;
5639702Slinton 
5649702Slinton 				}
5659702Slinton 			else if( p->in.op == STARG ){  /* store an arg into a temporary */
5669702Slinton 				r = p->in.left;
5679702Slinton 				}
5689702Slinton 			else cerror( "STASG bad" );
5699702Slinton 
5709702Slinton 			if( r->in.op == ICON ) r->in.op = NAME;
5719702Slinton 			else if( r->in.op == REG ) r->in.op = OREG;
5729702Slinton 			else if( r->in.op != OREG ) cerror( "STASG-r" );
5739702Slinton 
5749702Slinton 			size = p->stn.stsize;
5759702Slinton 
5769702Slinton 			if( size <= 0 || size > 65535 )
5779702Slinton 				cerror("structure size <0=0 or >65535");
5789702Slinton 
5799702Slinton 			switch(size) {
5809702Slinton 				case 1:
58124418Smckusick 					putstr("	movb	");
5829702Slinton 					break;
5839702Slinton 				case 2:
58424418Smckusick 					putstr("	movw	");
5859702Slinton 					break;
5869702Slinton 				case 4:
58724418Smckusick 					putstr("	movl	");
5889702Slinton 					break;
5899702Slinton 				case 8:
59024418Smckusick 					putstr("	movq	");
5919702Slinton 					break;
5929702Slinton 				default:
5939702Slinton 					printf("	movc3	$%d,", size);
5949702Slinton 					break;
5959702Slinton 			}
5969702Slinton 			adrput(r);
59716418Sralph 			if( p->in.op == STASG ){
59824418Smckusick 				putchar(',');
59916418Sralph 				adrput(l);
60024418Smckusick 				putchar('\n');
60116418Sralph 				}
60216418Sralph 			else
60324418Smckusick 				putstr(",(sp)\n");
6049702Slinton 
6059702Slinton 			if( r->in.op == NAME ) r->in.op = ICON;
6069702Slinton 			else if( r->in.op == OREG ) r->in.op = REG;
6079702Slinton 
6089702Slinton 			}
6099702Slinton 		break;
6109702Slinton 
6119702Slinton 	default:
6129702Slinton 		cerror( "illegal zzzcode" );
6139702Slinton 		}
6149702Slinton 	}
6159702Slinton 
61623536Sbloom /*
61723536Sbloom  * collapsible(dest, src) -- if a conversion with a register destination
61823536Sbloom  *	can be accomplished in one instruction, return the type of src
61923536Sbloom  *	that will do the job correctly; otherwise return 0.  Note that
62023536Sbloom  *	a register must always end up having type INT or UNSIGNED.
62123536Sbloom  */
62223536Sbloom int
62323536Sbloom collapsible(dest, src)
62423536Sbloom NODE *dest, *src;
62523536Sbloom {
62623536Sbloom 	int st = src->in.type;
62723536Sbloom 	int dt = dest->in.type;
62823536Sbloom 	int newt = 0;
62923536Sbloom 
63023536Sbloom 	/*
63123536Sbloom 	 * Are there side effects of evaluating src?
63223536Sbloom 	 * If the derived type will not be the same size as src,
63324418Smckusick 	 * we may have to use two steps.
63423536Sbloom 	 */
63524418Smckusick 	if (tlen(src) > tlen(dest)) {
63624418Smckusick 		if (tshape(src, STARREG))
63724418Smckusick 			return (0);
63824418Smckusick 		if (src->in.op == OREG && R2TEST(src->tn.rval))
63924418Smckusick 			return (0);
64024418Smckusick 		}
64123536Sbloom 
64223536Sbloom 	/*
64323536Sbloom 	 * Can we get an object of dest's type by punning src?
64423536Sbloom 	 * Praises be to great Cthulhu for little-endian machines...
64523536Sbloom 	 */
64623536Sbloom 	if (st == CHAR && dt == USHORT)
64723536Sbloom 		/*
64823536Sbloom 		 * Special case -- we must sign-extend to 16 bits.
64923536Sbloom 		 */
65023536Sbloom 		return (0);
65123536Sbloom 
65223536Sbloom 	if (tlen(src) < tlen(dest))
65323536Sbloom 		newt = st;
65423536Sbloom 	else
65523536Sbloom 		newt = dt;
65623536Sbloom 
65723536Sbloom 	return (newt);
65823536Sbloom 	}
65923536Sbloom 
66017742Sralph rmove( rt, rs, t ) TWORD t; {
6619702Slinton 	printf( "	%s	%s,%s\n",
66217742Sralph #ifdef FORT
66317742Sralph 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
66417742Sralph #endif
6659702Slinton 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
6669702Slinton 		rnames[rs], rnames[rt] );
6679702Slinton 	}
6689702Slinton 
6699702Slinton struct respref
6709702Slinton respref[] = {
6719702Slinton 	INTAREG|INTBREG,	INTAREG|INTBREG,
6729702Slinton 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
6739702Slinton 	INTEMP,	INTEMP,
6749702Slinton 	FORARG,	FORARG,
6759702Slinton 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
6769702Slinton 	0,	0 };
6779702Slinton 
6789702Slinton setregs(){ /* set up temporary registers */
6799702Slinton 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
6809702Slinton 	;
6819702Slinton 	}
6829702Slinton 
68332924Sdonn /*ARGSUSED*/
6849702Slinton rewfld( p ) NODE *p; {
6859702Slinton 	return(1);
6869702Slinton 	}
6879702Slinton 
68832924Sdonn /*ARGSUSED*/
6899702Slinton callreg(p) NODE *p; {
6909702Slinton 	return( R0 );
6919702Slinton 	}
6929702Slinton 
6939702Slinton base( p ) register NODE *p; {
6949702Slinton 	register int o = p->in.op;
6959702Slinton 
6969702Slinton 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
6979702Slinton 	if( o==REG ) return( p->tn.rval );
6989702Slinton     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
6999702Slinton 		return( p->in.left->tn.rval );
7009702Slinton     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
7019702Slinton 		return( p->tn.rval + 0200*1 );
7029702Slinton 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
7039702Slinton 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
7049702Slinton 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
7059702Slinton 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
7069702Slinton 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
7079702Slinton 	return( -1 );
7089702Slinton 	}
7099702Slinton 
7109702Slinton offset( p, tyl ) register NODE *p; int tyl; {
7119702Slinton 
71224418Smckusick 	if( tyl==1 &&
71324418Smckusick 	    p->in.op==REG &&
71424418Smckusick 	    (p->in.type==INT || p->in.type==UNSIGNED) )
71524418Smckusick 		return( p->tn.rval );
71624418Smckusick 	if( p->in.op==LS &&
71724418Smckusick 	    p->in.left->in.op==REG &&
71824418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
71924418Smckusick 	    p->in.right->in.op==ICON &&
72024418Smckusick 	    p->in.right->in.name[0]=='\0' &&
72124418Smckusick 	    (1<<p->in.right->tn.lval)==tyl)
7229702Slinton 		return( p->in.left->tn.rval );
72324418Smckusick 	if( tyl==2 &&
72424418Smckusick 	    p->in.op==PLUS &&
72524418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
72624418Smckusick 	    p->in.left->in.op==REG &&
72724418Smckusick 	    p->in.right->in.op==REG &&
72824418Smckusick 	    p->in.left->tn.rval==p->in.right->tn.rval )
72924418Smckusick 		return( p->in.left->tn.rval );
7309702Slinton 	return( -1 );
7319702Slinton 	}
7329702Slinton 
7339702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
7349702Slinton 	register NODE *t;
7359702Slinton 	NODE *f;
7369702Slinton 
7379702Slinton 	p->in.op = OREG;
7389702Slinton 	f = p->in.left; 	/* have to free this subtree later */
7399702Slinton 
7409702Slinton 	/* init base */
7419702Slinton 	switch (q->in.op) {
7429702Slinton 		case ICON:
7439702Slinton 		case REG:
7449702Slinton 		case OREG:
7459702Slinton 			t = q;
7469702Slinton 			break;
7479702Slinton 
7489702Slinton 		case MINUS:
7499702Slinton 			q->in.right->tn.lval = -q->in.right->tn.lval;
7509702Slinton 		case PLUS:
7519702Slinton 			t = q->in.right;
7529702Slinton 			break;
7539702Slinton 
7549702Slinton 		case INCR:
7559702Slinton 		case ASG MINUS:
7569702Slinton 			t = q->in.left;
7579702Slinton 			break;
7589702Slinton 
7599702Slinton 		case UNARY MUL:
7609702Slinton 			t = q->in.left->in.left;
7619702Slinton 			break;
7629702Slinton 
7639702Slinton 		default:
7649702Slinton 			cerror("illegal makeor2");
7659702Slinton 	}
7669702Slinton 
7679702Slinton 	p->tn.lval = t->tn.lval;
7689702Slinton #ifndef FLEXNAMES
76932924Sdonn 	{
77032924Sdonn 		register int i;
77132924Sdonn 		for(i=0; i<NCHNAM; ++i)
77232924Sdonn 			p->in.name[i] = t->in.name[i];
77332924Sdonn 	}
7749702Slinton #else
7759702Slinton 	p->in.name = t->in.name;
7769702Slinton #endif
7779702Slinton 
7789702Slinton 	/* init offset */
7799702Slinton 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
7809702Slinton 
7819702Slinton 	tfree(f);
7829702Slinton 	return;
7839702Slinton 	}
7849702Slinton 
7859702Slinton canaddr( p ) NODE *p; {
7869702Slinton 	register int o = p->in.op;
7879702Slinton 
7889702Slinton 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
7899702Slinton 	return(0);
7909702Slinton 	}
7919702Slinton 
7929702Slinton flshape( p ) register NODE *p; {
7939702Slinton 	return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
7949702Slinton 		(p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
7959702Slinton 	}
7969702Slinton 
79732926Sdonn /* INTEMP shapes must not contain any temporary registers */
7989702Slinton shtemp( p ) register NODE *p; {
79932926Sdonn 	int r;
80032926Sdonn 
8019702Slinton 	if( p->in.op == STARG ) p = p->in.left;
80232926Sdonn 
80332926Sdonn 	switch (p->in.op) {
80432926Sdonn 	case REG:
80532926Sdonn 		return( !istreg(p->tn.rval) );
80632926Sdonn 	case OREG:
80732926Sdonn 		r = p->tn.rval;
80832926Sdonn 		if( R2TEST(r) ) {
80932926Sdonn 			if( istreg(R2UPK1(r)) )
81032926Sdonn 				return(0);
81132926Sdonn 			r = R2UPK2(r);
81232926Sdonn 			}
81332926Sdonn 		return( !istreg(r) );
81432926Sdonn 	case UNARY MUL:
81532926Sdonn 		p = p->in.left;
81632926Sdonn 		return( p->in.op != UNARY MUL && shtemp(p) );
81732926Sdonn 		}
81832926Sdonn 
81932926Sdonn 	if( optype( p->in.op ) != LTYPE ) return(0);
82032926Sdonn 	return(1);
8219702Slinton 	}
8229702Slinton 
8239702Slinton shumul( p ) register NODE *p; {
8249702Slinton 	register o;
8259702Slinton 	extern int xdebug;
8269702Slinton 
8279702Slinton 	if (xdebug) {
8289702Slinton 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
8299702Slinton 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
8309702Slinton 		}
8319702Slinton 
8329702Slinton 
8339702Slinton 	o = p->in.op;
8349702Slinton 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
8359702Slinton 
8369702Slinton 	if( ( o == INCR || o == ASG MINUS ) &&
8379702Slinton 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
8389702Slinton 	    p->in.right->in.name[0] == '\0' )
8399702Slinton 		{
84017659Sralph 		switch (p->in.type)
8419702Slinton 			{
8429702Slinton 			case CHAR|PTR:
8439702Slinton 			case UCHAR|PTR:
8449702Slinton 				o = 1;
8459702Slinton 				break;
8469702Slinton 
8479702Slinton 			case SHORT|PTR:
8489702Slinton 			case USHORT|PTR:
8499702Slinton 				o = 2;
8509702Slinton 				break;
8519702Slinton 
8529702Slinton 			case INT|PTR:
8539702Slinton 			case UNSIGNED|PTR:
8549702Slinton 			case LONG|PTR:
8559702Slinton 			case ULONG|PTR:
8569702Slinton 			case FLOAT|PTR:
8579702Slinton 				o = 4;
8589702Slinton 				break;
8599702Slinton 
8609702Slinton 			case DOUBLE|PTR:
8619702Slinton 				o = 8;
8629702Slinton 				break;
8639702Slinton 
8649702Slinton 			default:
86517742Sralph 				if ( ISPTR(p->in.type) &&
86617742Sralph 				     ISPTR(DECREF(p->in.type)) ) {
8679702Slinton 					o = 4;
8689702Slinton 					break;
8699702Slinton 					}
8709702Slinton 				else return(0);
8719702Slinton 			}
8729702Slinton 		return( p->in.right->tn.lval == o ? STARREG : 0);
8739702Slinton 		}
8749702Slinton 
8759702Slinton 	return( 0 );
8769702Slinton 	}
8779702Slinton 
8789702Slinton adrcon( val ) CONSZ val; {
87924418Smckusick 	putchar( '$' );
8809702Slinton 	printf( CONFMT, val );
8819702Slinton 	}
8829702Slinton 
8839702Slinton conput( p ) register NODE *p; {
8849702Slinton 	switch( p->in.op ){
8859702Slinton 
8869702Slinton 	case ICON:
8879702Slinton 		acon( p );
8889702Slinton 		return;
8899702Slinton 
8909702Slinton 	case REG:
89124418Smckusick 		putstr( rnames[p->tn.rval] );
8929702Slinton 		return;
8939702Slinton 
8949702Slinton 	default:
8959702Slinton 		cerror( "illegal conput" );
8969702Slinton 		}
8979702Slinton 	}
8989702Slinton 
89932923Sdonn /*ARGSUSED*/
90032924Sdonn insput( p ) NODE *p; {
9019702Slinton 	cerror( "insput" );
9029702Slinton 	}
9039702Slinton 
90432928Sdonn upput( p, size ) NODE *p; int size; {
90532928Sdonn 	if( size == SZLONG && p->in.op == REG ) {
90632928Sdonn 		putstr( rnames[p->tn.rval + 1] );
90732928Sdonn 		return;
90832928Sdonn 		}
9099702Slinton 	cerror( "upput" );
9109702Slinton 	}
9119702Slinton 
9129702Slinton adrput( p ) register NODE *p; {
9139702Slinton 	register int r;
9149702Slinton 	/* output an address, with offsets, from p */
9159702Slinton 
9169702Slinton 	if( p->in.op == FLD ){
9179702Slinton 		p = p->in.left;
9189702Slinton 		}
9199702Slinton 	switch( p->in.op ){
9209702Slinton 
9219702Slinton 	case NAME:
9229702Slinton 		acon( p );
9239702Slinton 		return;
9249702Slinton 
9259702Slinton 	case ICON:
9269702Slinton 		/* addressable value of the constant */
92724418Smckusick 		putchar( '$' );
9289702Slinton 		acon( p );
9299702Slinton 		return;
9309702Slinton 
9319702Slinton 	case REG:
93224418Smckusick 		putstr( rnames[p->tn.rval] );
9339702Slinton 		return;
9349702Slinton 
9359702Slinton 	case OREG:
9369702Slinton 		r = p->tn.rval;
9379702Slinton 		if( R2TEST(r) ){ /* double indexing */
9389702Slinton 			register int flags;
9399702Slinton 
9409702Slinton 			flags = R2UPK3(r);
94124418Smckusick 			if( flags & 1 ) putchar('*');
94224418Smckusick 			if( flags & 4 ) putchar('-');
9439702Slinton 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
9449702Slinton 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
94524418Smckusick 			if( flags & 2 ) putchar('+');
9469702Slinton 			printf( "[%s]", rnames[R2UPK2(r)] );
9479702Slinton 			return;
9489702Slinton 			}
9499702Slinton 		if( r == AP ){  /* in the argument region */
95032925Sdonn 			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
9519702Slinton 			printf( CONFMT, p->tn.lval );
95224418Smckusick 			putstr( "(ap)" );
9539702Slinton 			return;
9549702Slinton 			}
9559702Slinton 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
9569702Slinton 		printf( "(%s)", rnames[p->tn.rval] );
9579702Slinton 		return;
9589702Slinton 
9599702Slinton 	case UNARY MUL:
9609702Slinton 		/* STARNM or STARREG found */
9619702Slinton 		if( tshape(p, STARNM) ) {
96224418Smckusick 			putchar( '*' );
9639702Slinton 			adrput( p->in.left);
9649702Slinton 			}
9659702Slinton 		else {	/* STARREG - really auto inc or dec */
9669702Slinton 			register NODE *q;
9679702Slinton 
9689702Slinton /* tbl
9699702Slinton 			p = p->in.left;
9709702Slinton 			p->in.left->in.op = OREG;
9719702Slinton 			if( p->in.op == INCR ) {
9729702Slinton 				adrput( p->in.left );
97324418Smckusick 				putchar( '+' );
9749702Slinton 				}
9759702Slinton 			else {
97624418Smckusick 				putchar( '-' );
9779702Slinton 				adrput( p->in.left );
9789702Slinton 				}
9799702Slinton    tbl */
98017659Sralph 			q = p->in.left;
98117742Sralph 			if( q->in.right->tn.lval != tlen(p) )
98217742Sralph 				cerror("adrput: bad auto-increment/decrement");
98317659Sralph 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
98417659Sralph 				rnames[q->in.left->tn.rval],
98517659Sralph 				(q->in.op==INCR ? "+" : "") );
9869702Slinton 			p->in.op = OREG;
98717659Sralph 			p->tn.rval = q->in.left->tn.rval;
98817659Sralph 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
9899702Slinton #ifndef FLEXNAMES
9909702Slinton 			p->in.name[0] = '\0';
9919702Slinton #else
9929702Slinton 			p->in.name = "";
9939702Slinton #endif
9949702Slinton 			tfree(q);
9959702Slinton 		}
9969702Slinton 		return;
9979702Slinton 
9989702Slinton 	default:
9999702Slinton 		cerror( "illegal address" );
10009702Slinton 		return;
10019702Slinton 
10029702Slinton 		}
10039702Slinton 
10049702Slinton 	}
10059702Slinton 
10069702Slinton acon( p ) register NODE *p; { /* print out a constant */
10079702Slinton 
10089702Slinton 	if( p->in.name[0] == '\0' ){
10099702Slinton 		printf( CONFMT, p->tn.lval);
10109702Slinton 		}
10119702Slinton 	else if( p->tn.lval == 0 ) {
10129702Slinton #ifndef FLEXNAMES
10139702Slinton 		printf( "%.8s", p->in.name );
10149702Slinton #else
101524418Smckusick 		putstr( p->in.name );
10169702Slinton #endif
10179702Slinton 		}
10189702Slinton 	else {
10199702Slinton #ifndef FLEXNAMES
10209702Slinton 		printf( "%.8s+", p->in.name );
10219702Slinton #else
10229702Slinton 		printf( "%s+", p->in.name );
10239702Slinton #endif
10249702Slinton 		printf( CONFMT, p->tn.lval );
10259702Slinton 		}
10269702Slinton 	}
10279702Slinton 
10289702Slinton /*
10299702Slinton aacon( p ) register NODE *p; { /* print out a constant */
10309702Slinton /*
10319702Slinton 
10329702Slinton 	if( p->in.name[0] == '\0' ){
10339702Slinton 		printf( CONFMT, p->tn.lval);
10349702Slinton 		return( 0 );
10359702Slinton 		}
10369702Slinton 	else if( p->tn.lval == 0 ) {
10379702Slinton #ifndef FLEXNAMES
10389702Slinton 		printf( "$%.8s", p->in.name );
10399702Slinton #else
10409702Slinton 		printf( "$%s", p->in.name );
10419702Slinton #endif
10429702Slinton 		return( 1 );
10439702Slinton 		}
10449702Slinton 	else {
10459702Slinton 		printf( "$(" );
10469702Slinton 		printf( CONFMT, p->tn.lval );
10479702Slinton 		printf( "+" );
10489702Slinton #ifndef FLEXNAMES
10499702Slinton 		printf( "%.8s)", p->in.name );
10509702Slinton #else
10519702Slinton 		printf( "%s)", p->in.name );
10529702Slinton #endif
10539702Slinton 		return(1);
10549702Slinton 		}
10559702Slinton 	}
10569702Slinton  */
10579702Slinton 
10589702Slinton genscall( p, cookie ) register NODE *p; {
10599702Slinton 	/* structure valued call */
10609702Slinton 	return( gencall( p, cookie ) );
10619702Slinton 	}
10629702Slinton 
10639702Slinton /* tbl */
10649702Slinton int gc_numbytes;
10659702Slinton /* tbl */
10669702Slinton 
106732924Sdonn /*ARGSUSED*/
10689702Slinton gencall( p, cookie ) register NODE *p; {
10699702Slinton 	/* generate the call given by p */
107016418Sralph 	register NODE *p1;
10719702Slinton 	register temp, temp1;
10729702Slinton 	register m;
10739702Slinton 
10749702Slinton 	if( p->in.right ) temp = argsize( p->in.right );
10759702Slinton 	else temp = 0;
10769702Slinton 
10779702Slinton 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
10789702Slinton 		/* set aside room for structure return */
10799702Slinton 
10809702Slinton 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
10819702Slinton 		else temp1 = temp;
10829702Slinton 		}
10839702Slinton 
10849702Slinton 	if( temp > maxargs ) maxargs = temp;
10859702Slinton 	SETOFF(temp1,4);
10869702Slinton 
10879702Slinton 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
108816418Sralph 		genargs( p->in.right );
10899702Slinton 		}
10909702Slinton 
10919702Slinton 	p1 = p->in.left;
10929702Slinton 	if( p1->in.op != ICON ){
10939702Slinton 		if( p1->in.op != REG ){
10949702Slinton 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
10959702Slinton 				if( p1->in.op != NAME ){
10969702Slinton 					order( p1, INAREG );
10979702Slinton 					}
10989702Slinton 				}
10999702Slinton 			}
11009702Slinton 		}
11019702Slinton 
11029702Slinton /*
11039702Slinton 	if( p1->in.op == REG && p->tn.rval == R5 ){
11049702Slinton 		cerror( "call register overwrite" );
11059702Slinton 		}
11069702Slinton  */
11079702Slinton /* tbl
11089702Slinton 	setup gc_numbytes so reference to ZC works */
11099702Slinton 
11109702Slinton 	gc_numbytes = temp&(0x3ff);
11119702Slinton /* tbl */
11129702Slinton 
11139702Slinton 	p->in.op = UNARY CALL;
11149702Slinton 	m = match( p, INTAREG|INTBREG );
11159702Slinton 
11169702Slinton 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
11179702Slinton 	/* (plus in assignment to gc_numbytes above, for neatness only) */
11189702Slinton 	if (temp >= 1024)
11199702Slinton 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
11209702Slinton 
11219702Slinton /* tbl
11229702Slinton 	switch( temp ) {
11239702Slinton 	case 0:
11249702Slinton 		break;
11259702Slinton 	case 2:
11269702Slinton 		printf( "	tst	(sp)+\n" );
11279702Slinton 		break;
11289702Slinton 	case 4:
11299702Slinton 		printf( "	cmp	(sp)+,(sp)+\n" );
11309702Slinton 		break;
11319702Slinton 	default:
11329702Slinton 		printf( "	add	$%d,sp\n", temp);
11339702Slinton 		}
11349702Slinton    tbl */
11359702Slinton 	return(m != MDONE);
11369702Slinton 	}
11379702Slinton 
11389702Slinton /* tbl */
11399702Slinton char *
11409702Slinton ccbranches[] = {
11419702Slinton 	"	jeql	L%d\n",
11429702Slinton 	"	jneq	L%d\n",
11439702Slinton 	"	jleq	L%d\n",
11449702Slinton 	"	jlss	L%d\n",
11459702Slinton 	"	jgeq	L%d\n",
11469702Slinton 	"	jgtr	L%d\n",
11479702Slinton 	"	jlequ	L%d\n",
11489702Slinton 	"	jlssu	L%d\n",
11499702Slinton 	"	jgequ	L%d\n",
11509702Slinton 	"	jgtru	L%d\n",
11519702Slinton 	};
11529702Slinton /* tbl */
11539702Slinton 
115432924Sdonn /*ARGSUSED*/
11559702Slinton cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
11569702Slinton 
11579702Slinton /* tbl */
11589702Slinton 	if( o == 0 ) printf( "	jbr	L%d\n", lab );
11599702Slinton /* tbl */
11609702Slinton 	else {
11619702Slinton 		if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
11629702Slinton 		printf( ccbranches[o-EQ], lab );
11639702Slinton 		}
11649702Slinton 	}
11659702Slinton 
11669702Slinton nextcook( p, cookie ) NODE *p; {
11679702Slinton 	/* we have failed to match p with cookie; try another */
11689702Slinton 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
11699702Slinton 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
11709702Slinton 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
11719702Slinton 	return( FORREW );
11729702Slinton 	}
11739702Slinton 
117432924Sdonn /*ARGSUSED*/
11759702Slinton lastchance( p, cook ) NODE *p; {
11769702Slinton 	/* forget it! */
11779702Slinton 	return(0);
11789702Slinton 	}
11799702Slinton 
11809702Slinton optim2( p ) register NODE *p; {
11819702Slinton 	/* do local tree transformations and optimizations */
11829702Slinton 
118332929Sdonn 	int o;
1184*32932Sdonn 	int i, mask;
118516181Sralph 	register NODE *l, *r;
11869702Slinton 
118732929Sdonn 	switch( o = p->in.op ) {
11889702Slinton 
11899702Slinton 	case AND:
119019933Smckusick 		/* commute L and R to eliminate complements and constants */
119116181Sralph 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
119216181Sralph 		    l->in.op == COMPL ) {
11939702Slinton 			p->in.left = p->in.right;
119416181Sralph 			p->in.right = l;
11959702Slinton 			}
11969702Slinton 	case ASG AND:
11979702Slinton 		/* change meaning of AND to ~R&L - bic on pdp11 */
11989702Slinton 		r = p->in.right;
119932931Sdonn 		if( r->in.op==ICON && r->in.name[0]==0 ) {
120032931Sdonn 			/* check for degenerate operations */
120132931Sdonn 			l = p->in.left;
1202*32932Sdonn 			mask = (1 << tlen(l) * SZCHAR) - 1;
1203*32932Sdonn 			if( ISUNSIGNED(r->in.type) ) {
1204*32932Sdonn 				i = (r->tn.lval & mask);
1205*32932Sdonn 				if( i == mask ) {
1206*32932Sdonn 					r->in.op = FREE;
1207*32932Sdonn 					ncopy(p, l);
1208*32932Sdonn 					l->in.op = FREE;
1209*32932Sdonn 					break;
1210*32932Sdonn 					}
1211*32932Sdonn 				else if( i == 0 )
1212*32932Sdonn 					goto zero;
1213*32932Sdonn 				else
1214*32932Sdonn 					r->tn.lval = i;
1215*32932Sdonn 				}
1216*32932Sdonn 			else if( r->tn.lval == mask &&
1217*32932Sdonn 				 tlen(l) < SZINT/SZCHAR ) {
1218*32932Sdonn 				r->in.op = SCONV;
1219*32932Sdonn 				r->in.left = l;
1220*32932Sdonn 				r->in.right = 0;
1221*32932Sdonn 				r->in.type = ENUNSIGN(l->in.type);
1222*32932Sdonn 				r->in.su = l->in.su > 1 ? l->in.su : 1;
1223*32932Sdonn 				ncopy(p, r);
1224*32932Sdonn 				p->in.left = r;
1225*32932Sdonn 				p->in.type = INT;
122632931Sdonn 				break;
122732931Sdonn 				}
122832931Sdonn 			/* complement constant */
12299702Slinton 			r->tn.lval = ~r->tn.lval;
12309702Slinton 			}
12319702Slinton 		else if( r->in.op==COMPL ) { /* ~~A => A */
12329702Slinton 			r->in.op = FREE;
12339702Slinton 			p->in.right = r->in.left;
12349702Slinton 			}
12359702Slinton 		else { /* insert complement node */
123616181Sralph 			p->in.right = l = talloc();
123716181Sralph 			l->in.op = COMPL;
123816181Sralph 			l->in.rall = NOPREF;
123916181Sralph 			l->in.type = r->in.type;
124016181Sralph 			l->in.left = r;
124116181Sralph 			l->in.right = NULL;
12429702Slinton 			}
12439702Slinton 		break;
12449702Slinton 
124516181Sralph 	case SCONV:
124619933Smckusick 		l = p->in.left;
124717742Sralph #if defined(FORT) || defined(SPRECC)
124816573Sralph 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
124919933Smckusick 		    l->in.type == FLOAT || l->in.type == DOUBLE )
125019933Smckusick 			return;
125116573Sralph #else
125219933Smckusick 		if( mixtypes(p, l) ) return;
125316573Sralph #endif
125432924Sdonn 		if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL )
125525751Sdonn 			return;
125625751Sdonn 
125719933Smckusick 		/* Only trust it to get it right if the size is the same */
125819933Smckusick 		if( tlen(p) != tlen(l) )
125919933Smckusick 			return;
126016181Sralph 
126116181Sralph 		/* clobber conversion */
126219933Smckusick 		if( l->in.op != FLD )
126316181Sralph 			l->in.type = p->in.type;
126416181Sralph 		ncopy( p, l );
126516181Sralph 		l->in.op = FREE;
126619933Smckusick 
126716181Sralph 		break;
126816181Sralph 
126924418Smckusick 	case ASSIGN:
127024418Smckusick 		/*
127124418Smckusick 		 * Conversions are equivalent to assignments;
127224418Smckusick 		 * when the two operations are combined,
127324418Smckusick 		 * we can sometimes zap the conversion.
127424418Smckusick 		 */
127524418Smckusick 		r = p->in.right;
127624418Smckusick 		l = p->in.left;
127724418Smckusick 		if ( r->in.op == SCONV &&
127824418Smckusick 		     !mixtypes(l, r) &&
127932922Sdonn 		     l->in.op != FLD &&
128024418Smckusick 		     tlen(l) == tlen(r) ) {
128124418Smckusick 				p->in.right = r->in.left;
128224418Smckusick 				r->in.op = FREE;
128324418Smckusick 			}
128424418Smckusick 		break;
128524418Smckusick 
128632929Sdonn 	case ULE:
128732929Sdonn 	case ULT:
128832929Sdonn 	case UGE:
128932929Sdonn 	case UGT:
129032931Sdonn 		p->in.op -= (UGE-GE);
129132931Sdonn 		if( degenerate(p) )
129232931Sdonn 			break;
129332931Sdonn 		p->in.op += (UGE-GE);
129432931Sdonn 		break;
129532931Sdonn 
129632929Sdonn 	case EQ:
129732929Sdonn 	case NE:
129832929Sdonn 	case LE:
129932929Sdonn 	case LT:
130032929Sdonn 	case GE:
130132929Sdonn 	case GT:
130232931Sdonn 		(void) degenerate(p);
130332931Sdonn 		break;
130432931Sdonn 
130532931Sdonn 	case DIV:
130632931Sdonn 		if( p->in.right->in.op == ICON &&
130732931Sdonn 		    p->in.right->tn.name[0] == '\0' &&
130832931Sdonn 		    ISUNSIGNED(p->in.right->in.type) &&
130932931Sdonn 		    (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
131032931Sdonn 			/* easy to do here, harder to do in zzzcode() */
131132931Sdonn 			p->in.op = UGE;
131232929Sdonn 			break;
131332931Sdonn 			}
131432931Sdonn 	case MOD:
131532931Sdonn 	case ASG DIV:
131632931Sdonn 	case ASG MOD:
131732931Sdonn 		/*
131832931Sdonn 		 * optimize DIV and MOD
131932931Sdonn 		 *
132032931Sdonn 		 * basically we spot UCHAR and USHORT and try to do them
132132931Sdonn 		 * as signed ints...  apparently div+mul+sub is always
132232931Sdonn 		 * faster than ediv for finding MOD on the VAX, when
132332931Sdonn 		 * full unsigned MOD isn't needed.
132432931Sdonn 		 *
132532931Sdonn 		 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
132632931Sdonn 		 * are faster for unsigned dividend and a constant divisor
132732931Sdonn 		 * in the right range (.5 to 1 of dividend's range for the
132832931Sdonn 		 * first, .333+ to .5 for the second).  full unsigned is
132932931Sdonn 		 * already done cmp+sub in the appropriate case; the
133032931Sdonn 		 * other cases are less common and require more ambition.
133132931Sdonn 		 */
133232931Sdonn 		if( degenerate(p) )
133332929Sdonn 			break;
133432931Sdonn 		l = p->in.left;
133532931Sdonn 		r = p->in.right;
133632931Sdonn 		if( !ISUNSIGNED(r->in.type) ||
133732931Sdonn 		    tlen(l) >= SZINT/SZCHAR ||
133832931Sdonn 		    !(tlen(r) < SZINT/SZCHAR ||
133932931Sdonn 		      (r->in.op == ICON && r->tn.name[0] == '\0')) )
134032929Sdonn 			break;
134132931Sdonn 		if( r->in.op == ICON )
134232931Sdonn 			r->tn.type = INT;
134332931Sdonn 		else {
134432931Sdonn 			NODE *t = talloc();
134532931Sdonn 			t->in.left = r;
134632931Sdonn 			r = t;
134732931Sdonn 			r->in.op = SCONV;
134832931Sdonn 			r->in.type = INT;
134932931Sdonn 			r->in.right = 0;
135032931Sdonn 			p->in.right = r;
135132931Sdonn 			}
135232931Sdonn 		if( o == DIV || o == MOD ) {
135332931Sdonn 			NODE *t = talloc();
135432931Sdonn 			t->in.left = l;
135532931Sdonn 			l = t;
135632931Sdonn 			l->in.op = SCONV;
135732931Sdonn 			l->in.type = INT;
135832931Sdonn 			l->in.right = 0;
135932931Sdonn 			p->in.left = l;
136032931Sdonn 			}
136132931Sdonn 		/* handle asgops in table */
136232931Sdonn 		break;
136332931Sdonn 
136432931Sdonn 	case RS:
136532931Sdonn 	case ASG RS:
136632931Sdonn 	case LS:
136732931Sdonn 	case ASG LS:
136832931Sdonn 		/* pick up degenerate shifts */
136932931Sdonn 		l = p->in.left;
137032931Sdonn 		r = p->in.right;
137132931Sdonn 		if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
137232929Sdonn 			break;
137332929Sdonn 		i = r->tn.lval;
137432931Sdonn 		if( i < 0 )
137532931Sdonn 			/* front end 'fixes' this? */
137632931Sdonn 			if( o == LS || o == ASG LS )
137732931Sdonn 				o += (RS-LS);
137832931Sdonn 			else
137932931Sdonn 				o += (LS-RS);
138032931Sdonn 		if( (o == RS || o == ASG RS) &&
138132931Sdonn 		    !ISUNSIGNED(l->in.type) )
138232931Sdonn 			/* can't optimize signed right shifts */
138332929Sdonn 			break;
138432931Sdonn 		if( i < tlen(l) * SZCHAR )
138532929Sdonn 			break;
138632931Sdonn 	zero:
138732931Sdonn 		if( !asgop( o ) )
138832931Sdonn 			if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
138932931Sdonn 				/* no side effects */
1390*32932Sdonn 				tfree(l);
139132931Sdonn 				ncopy(p, r);
139232931Sdonn 				r->in.op = FREE;
139332931Sdonn 				p->tn.lval = 0;
139432931Sdonn 				}
139532931Sdonn 			else {
139632931Sdonn 				p->in.op = COMOP;
1397*32932Sdonn 				r->tn.lval = 0;
139832931Sdonn 				}
139932931Sdonn 		else {
140032931Sdonn 			p->in.op = ASSIGN;
140132931Sdonn 			r->tn.lval = 0;
140232929Sdonn 			}
140332931Sdonn 		break;
140432931Sdonn 		}
140532931Sdonn 	}
140632931Sdonn 
140732931Sdonn degenerate(p) register NODE *p; {
140832931Sdonn 	int o;
140932931Sdonn 	int result, i;
141032931Sdonn 	int lower, upper;
141132931Sdonn 	register NODE *l, *r;
141232931Sdonn 
141332931Sdonn 	/*
141432931Sdonn 	 * try to keep degenerate comparisons with constants
141532931Sdonn 	 * out of the table.
141632931Sdonn 	 */
141732931Sdonn 	r = p->in.right;
141832931Sdonn 	l = p->in.left;
141932931Sdonn 	if( r->in.op != ICON ||
142032931Sdonn 	    r->tn.name[0] != '\0' ||
142132931Sdonn 	    tlen(l) >= tlen(r) )
142232931Sdonn 		return (0);
142332931Sdonn 	switch( l->in.type ) {
142432931Sdonn 	case CHAR:
142532931Sdonn 		lower = -(1 << SZCHAR - 1);
142632931Sdonn 		upper = (1 << SZCHAR - 1) - 1;
142732931Sdonn 		break;
142832931Sdonn 	case UCHAR:
142932931Sdonn 		lower = 0;
143032931Sdonn 		upper = (1 << SZCHAR) - 1;
143132931Sdonn 		break;
143232931Sdonn 	case SHORT:
143332931Sdonn 		lower = -(1 << SZSHORT - 1);
143432931Sdonn 		upper = (1 << SZSHORT - 1) - 1;
143532931Sdonn 		break;
143632931Sdonn 	case USHORT:
143732931Sdonn 		lower = 0;
143832931Sdonn 		upper = (1 << SZSHORT) - 1;
143932931Sdonn 		break;
144032931Sdonn 	default:
1441*32932Sdonn 		cerror("unsupported type in degenerate()");
144232931Sdonn 		}
144332931Sdonn 	i = r->tn.lval;
144432931Sdonn 	switch( o = p->in.op ) {
144532931Sdonn 	case DIV:
144632931Sdonn 	case ASG DIV:
144732931Sdonn 	case MOD:
144832931Sdonn 	case ASG MOD:
144932931Sdonn 		/* DIV and MOD work like EQ */
145032931Sdonn 	case EQ:
145132931Sdonn 	case NE:
145232931Sdonn 		if( lower == 0 && (unsigned) i > upper )
145332931Sdonn 			result = o == NE;
145432931Sdonn 		else if( i < lower || i > upper )
145532931Sdonn 			result = o == NE;
145632931Sdonn 		else
145732931Sdonn 			return (0);
145832931Sdonn 		break;
145932931Sdonn 	case LT:
146032931Sdonn 	case GE:
146132931Sdonn 		if( lower == 0 && (unsigned) i > upper )
146232931Sdonn 			result = o == LT;
146332931Sdonn 		else if( i <= lower )
146432931Sdonn 			result = o != LT;
146532931Sdonn 		else if( i > upper )
146632931Sdonn 			result = o == LT;
146732931Sdonn 		else
146832931Sdonn 			return (0);
146932931Sdonn 		break;
147032931Sdonn 	case LE:
147132931Sdonn 	case GT:
147232931Sdonn 		if( lower == 0 && (unsigned) i >= upper )
147332931Sdonn 			result = o == LE;
147432931Sdonn 		else if( i < lower )
147532931Sdonn 			result = o != LE;
147632931Sdonn 		else if( i >= upper )
147732931Sdonn 			result = o == LE;
147832931Sdonn 		else
147932931Sdonn 			return (0);
148032931Sdonn 		break;
148132931Sdonn 	default:
148232931Sdonn 		cerror("unknown op in degenerate()");
148332931Sdonn 		}
148432931Sdonn 
148532931Sdonn 	if( o == MOD || o == ASG MOD ) {
148632931Sdonn 		r->in.op = FREE;
148732931Sdonn 		ncopy(p, l);
148832931Sdonn 		l->in.op = FREE;
148932931Sdonn 		}
149032931Sdonn 	else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
149132931Sdonn 		/* no side effects */
1492*32932Sdonn 		tfree(l);
149332931Sdonn 		ncopy(p, r);
149432931Sdonn 		r->in.op = FREE;
149532931Sdonn 		p->tn.lval = result;
149632931Sdonn 		}
149732931Sdonn 	else {
149832931Sdonn 		if( o == ASG DIV )
149932931Sdonn 			p->in.op = ASSIGN;
150032929Sdonn 		else {
150132929Sdonn 			p->in.op = COMOP;
150232929Sdonn 			r->tn.type = INT;
150332929Sdonn 			}
150432931Sdonn 		r->tn.lval = result;
15059702Slinton 		}
150632931Sdonn 	if( logop(o) )
150732931Sdonn 		p->in.type = INT;
150832931Sdonn 
150932931Sdonn 	return (1);
15109702Slinton 	}
15119702Slinton 
151232924Sdonn /*ARGSUSED*/
151317742Sralph NODE * addroreg(l) NODE *l;
15149702Slinton 				/* OREG was built in clocal()
15159702Slinton 				 * for an auto or formal parameter
15169702Slinton 				 * now its address is being taken
15179702Slinton 				 * local code must unwind it
15189702Slinton 				 * back to PLUS/MINUS REG ICON
15199702Slinton 				 * according to local conventions
15209702Slinton 				 */
15219702Slinton {
15229702Slinton 	cerror("address of OREG taken");
152317742Sralph 	/*NOTREACHED*/
15249702Slinton }
15259702Slinton 
15269702Slinton 
15279702Slinton 
15289702Slinton # ifndef ONEPASS
15299702Slinton main( argc, argv ) char *argv[]; {
15309702Slinton 	return( mainp2( argc, argv ) );
15319702Slinton 	}
15329702Slinton # endif
15339702Slinton 
15349702Slinton 
15359702Slinton /* added by jwf */
15369702Slinton struct functbl {
15379702Slinton 	int fop;
15389702Slinton 	TWORD ftype;
15399702Slinton 	char *func;
15409702Slinton 	} opfunc[] = {
15419702Slinton 	DIV,		TANY,	"udiv",
15429702Slinton 	MOD,		TANY,	"urem",
154317715Sralph 	ASG DIV,	TANY,	"audiv",
154417715Sralph 	ASG MOD,	TANY,	"aurem",
15459702Slinton 	0,	0,	0 };
15469702Slinton 
15479702Slinton hardops(p)  register NODE *p; {
15489702Slinton 	/* change hard to do operators into function calls.  */
15499702Slinton 	register NODE *q;
15509702Slinton 	register struct functbl *f;
15519702Slinton 	register o;
155217742Sralph 	NODE *old,*temp;
15539702Slinton 
15549702Slinton 	o = p->in.op;
155517742Sralph 	if( ! (optype(o)==BITYPE &&
155617742Sralph 	       (ISUNSIGNED(p->in.left->in.type) ||
155717742Sralph 		ISUNSIGNED(p->in.right->in.type))) )
155817742Sralph 		return;
15599702Slinton 
15609702Slinton 	for( f=opfunc; f->fop; f++ ) {
15619702Slinton 		if( o==f->fop ) goto convert;
15629702Slinton 		}
15639702Slinton 	return;
15649702Slinton 
15659702Slinton 	convert:
156632931Sdonn 	if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' )
156732928Sdonn 		/* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */
156832928Sdonn 		/* save a subroutine call -- use at most 5 instructions */
156932928Sdonn 		return;
157032931Sdonn 	if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR )
157132931Sdonn 		/* optim2() will modify the op into an ordinary int op */
157232931Sdonn 		return;
15739702Slinton 	if( asgop( o ) ) {
157417742Sralph 		old = NIL;
157517715Sralph 		switch( p->in.left->in.op ){
157617742Sralph 		case FLD:
157717742Sralph 			q = p->in.left->in.left;
157817742Sralph 			/*
157917742Sralph 			 * rewrite (lval.fld /= rval); as
158017742Sralph 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
158117742Sralph 			 * else the compiler will evaluate lval twice.
158217742Sralph 			 */
158317742Sralph 			if( q->in.op == UNARY MUL ){
158417742Sralph 				/* first allocate a temp storage */
158517742Sralph 				temp = talloc();
158617742Sralph 				temp->in.op = OREG;
158717742Sralph 				temp->tn.rval = TMPREG;
158817742Sralph 				temp->tn.lval = BITOOR(freetemp(1));
158917742Sralph 				temp->in.type = INCREF(p->in.type);
159017742Sralph #ifdef FLEXNAMES
159117742Sralph 				temp->in.name = "";
159217742Sralph #else
159317742Sralph 				temp->in.name[0] = '\0';
159417742Sralph #endif
159517742Sralph 				old = q->in.left;
159617742Sralph 				q->in.left = temp;
159717742Sralph 			}
159817742Sralph 			/* fall thru ... */
159917742Sralph 
160017715Sralph 		case REG:
160117715Sralph 		case NAME:
160217715Sralph 		case OREG:
160317715Sralph 			/* change ASG OP to a simple OP */
160417715Sralph 			q = talloc();
160517715Sralph 			q->in.op = NOASG p->in.op;
160617715Sralph 			q->in.rall = NOPREF;
160717715Sralph 			q->in.type = p->in.type;
160817715Sralph 			q->in.left = tcopy(p->in.left);
160917715Sralph 			q->in.right = p->in.right;
161017715Sralph 			p->in.op = ASSIGN;
161117715Sralph 			p->in.right = q;
161217715Sralph 			p = q;
161317715Sralph 			f -= 2; /* Note: this depends on the table order */
161417742Sralph 			/* on the right side only - replace *temp with
161517742Sralph 			 *(temp = &lval), build the assignment node */
161617742Sralph 			if( old ){
161717742Sralph 				temp = q->in.left->in.left; /* the "*" node */
161817742Sralph 				q = talloc();
161917742Sralph 				q->in.op = ASSIGN;
162017742Sralph 				q->in.left = temp->in.left;
162117742Sralph 				q->in.right = old;
162217742Sralph 				q->in.type = old->in.type;
162317742Sralph #ifdef FLEXNAMES
162417742Sralph 				q->in.name = "";
162517742Sralph #else
162617742Sralph 				q->in.name[0] = '\0';
162717742Sralph #endif
162817742Sralph 				temp->in.left = q;
162917742Sralph 			}
163017715Sralph 			break;
16319702Slinton 
163217715Sralph 		case UNARY MUL:
163317715Sralph 			/* avoid doing side effects twice */
163417715Sralph 			q = p->in.left;
163517715Sralph 			p->in.left = q->in.left;
163617715Sralph 			q->in.op = FREE;
163717715Sralph 			break;
163817715Sralph 
163917715Sralph 		default:
164017715Sralph 			cerror( "hardops: can't compute & LHS" );
164117715Sralph 			}
164217742Sralph 		}
164317715Sralph 
16449702Slinton 	/* build comma op for args to function */
16459702Slinton 	q = talloc();
16469702Slinton 	q->in.op = CM;
16479702Slinton 	q->in.rall = NOPREF;
16489702Slinton 	q->in.type = INT;
16499702Slinton 	q->in.left = p->in.left;
16509702Slinton 	q->in.right = p->in.right;
16519702Slinton 	p->in.op = CALL;
16529702Slinton 	p->in.right = q;
16539702Slinton 
16549702Slinton 	/* put function name in left node of call */
16559702Slinton 	p->in.left = q = talloc();
16569702Slinton 	q->in.op = ICON;
16579702Slinton 	q->in.rall = NOPREF;
16589702Slinton 	q->in.type = INCREF( FTN + p->in.type );
16599702Slinton #ifndef FLEXNAMES
16609702Slinton 	strcpy( q->in.name, f->func );
16619702Slinton #else
16629702Slinton 	q->in.name = f->func;
16639702Slinton #endif
16649702Slinton 	q->tn.lval = 0;
16659702Slinton 	q->tn.rval = 0;
16669702Slinton 
16679702Slinton 	}
16689702Slinton 
166917742Sralph zappost(p) NODE *p; {
167017742Sralph 	/* look for ++ and -- operators and remove them */
167117742Sralph 
167217742Sralph 	register o, ty;
167317742Sralph 	register NODE *q;
167417742Sralph 	o = p->in.op;
167517742Sralph 	ty = optype( o );
167617742Sralph 
167717742Sralph 	switch( o ){
167817742Sralph 
167917742Sralph 	case INCR:
168017742Sralph 	case DECR:
168117742Sralph 			q = p->in.left;
168217742Sralph 			p->in.right->in.op = FREE;  /* zap constant */
168317742Sralph 			ncopy( p, q );
168417742Sralph 			q->in.op = FREE;
168517742Sralph 			return;
168617742Sralph 
168717742Sralph 		}
168817742Sralph 
168917742Sralph 	if( ty == BITYPE ) zappost( p->in.right );
169017742Sralph 	if( ty != LTYPE ) zappost( p->in.left );
169117742Sralph }
169217742Sralph 
169317742Sralph fixpre(p) NODE *p; {
169417742Sralph 
169517742Sralph 	register o, ty;
169617742Sralph 	o = p->in.op;
169717742Sralph 	ty = optype( o );
169817742Sralph 
169917742Sralph 	switch( o ){
170017742Sralph 
170117742Sralph 	case ASG PLUS:
170217742Sralph 			p->in.op = PLUS;
170317742Sralph 			break;
170417742Sralph 	case ASG MINUS:
170517742Sralph 			p->in.op = MINUS;
170617742Sralph 			break;
170717742Sralph 		}
170817742Sralph 
170917742Sralph 	if( ty == BITYPE ) fixpre( p->in.right );
171017742Sralph 	if( ty != LTYPE ) fixpre( p->in.left );
171117742Sralph }
171217742Sralph 
171324418Smckusick strip(p) register NODE *p; {
171424418Smckusick 	NODE *q;
171524418Smckusick 
171624418Smckusick 	/* strip nodes off the top when no side effects occur */
171724418Smckusick 	for( ; ; ) {
171824418Smckusick 		switch( p->in.op ) {
171924418Smckusick 		case SCONV:			/* remove lint tidbits */
172024418Smckusick 			q = p->in.left;
172124418Smckusick 			ncopy( p, q );
172224418Smckusick 			q->in.op = FREE;
172324418Smckusick 			break;
172424418Smckusick 		/* could probably add a few more here */
172524418Smckusick 		default:
172624418Smckusick 			return;
172724418Smckusick 			}
172824418Smckusick 		}
172924418Smckusick 	}
173024418Smckusick 
17319702Slinton myreader(p) register NODE *p; {
173224418Smckusick 	strip( p );		/* strip off operations with no side effects */
173317742Sralph 	canon( p );		/* expands r-vals for fields */
17349702Slinton 	walkf( p, hardops );	/* convert ops to function calls */
17359702Slinton 	walkf( p, optim2 );
17369702Slinton 	/* jwf toff = 0;  /* stack offset swindle */
17379702Slinton 	}
1738