xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 25751)
117742Sralph # ifndef lint
2*25751Sdonn static char *sccsid ="@(#)local2.c	1.13 (Berkeley) 01/08/86";
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 
169702Slinton where(c){
179702Slinton 	fprintf( stderr, "%s, line %d: ", filename, lineno );
189702Slinton 	}
199702Slinton 
209702Slinton lineid( l, fn ) char *fn; {
219702Slinton 	/* identify line l and file fn */
229702Slinton 	printf( "#	line %d, file %s\n", l, fn );
239702Slinton 	}
249702Slinton 
259702Slinton 
269702Slinton eobl2(){
279702Slinton 	OFFSZ spoff;	/* offset from stack pointer */
289702Slinton #ifdef FORT
299702Slinton 	spoff = maxoff;
309702Slinton 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
319702Slinton 	spoff /= SZCHAR;
329702Slinton 	SETOFF(spoff,4);
339702Slinton #ifndef FLEXNAMES
349702Slinton 	printf( "	.set	.F%d,%ld\n", ftnno, spoff );
359702Slinton #else
369702Slinton 	/* SHOULD BE L%d ... ftnno but must change pc/f77 */
379702Slinton 	printf( "	.set	LF%d,%ld\n", ftnno, spoff );
389702Slinton #endif
399702Slinton #else
409702Slinton 	extern int ftlab1, ftlab2;
419702Slinton 
429702Slinton 	spoff = maxoff;
439702Slinton 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
449702Slinton 	spoff /= SZCHAR;
459702Slinton 	SETOFF(spoff,4);
469702Slinton 	printf( "L%d:\n", ftlab1);
479702Slinton 	if( spoff!=0 )
489702Slinton 		if( spoff < 64 )
499702Slinton 			printf( "	subl2	$%ld,sp\n", spoff);
509702Slinton 		else
519702Slinton 			printf( "	movab	-%ld(sp),sp\n", spoff);
529702Slinton 	printf( "	jbr 	L%d\n", ftlab2);
539702Slinton #endif
549702Slinton 	maxargs = -1;
559702Slinton 	}
569702Slinton 
579702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = {
589702Slinton 
599702Slinton 	ASG PLUS, "add",
609702Slinton 	ASG MINUS, "sub",
619702Slinton 	ASG MUL, "mul",
629702Slinton 	ASG DIV, "div",
639702Slinton 	ASG OR, "bis",
649702Slinton 	ASG ER,	"xor",
659702Slinton 	ASG AND, "bic",
669702Slinton 	PLUS,	"add",
679702Slinton 	MINUS,	"sub",
689702Slinton 	MUL,	"mul",
699702Slinton 	DIV,	"div",
709702Slinton 	OR,	"bis",
719702Slinton 	ER,	"xor",
729702Slinton 	AND,	"bic",
739702Slinton 	-1, ""    };
749702Slinton 
759702Slinton hopcode( f, o ){
769702Slinton 	/* output the appropriate string from the above table */
779702Slinton 
789702Slinton 	register struct hoptab *q;
799702Slinton 
809702Slinton 	for( q = ioptab;  q->opmask>=0; ++q ){
819702Slinton 		if( q->opmask == o ){
8224418Smckusick 			putstr( q->opstring );
839702Slinton /* tbl
8424418Smckusick 			if( f == 'F' ) putchar( 'e' );
8524418Smckusick 			else if( f == 'D' ) putchar( 'd' );
869702Slinton    tbl */
879702Slinton /* tbl */
889702Slinton 			switch( f ) {
899702Slinton 				case 'L':
909702Slinton 				case 'W':
919702Slinton 				case 'B':
929702Slinton 				case 'D':
939702Slinton 				case 'F':
9424418Smckusick 					putchar(tolower(f));
959702Slinton 					break;
969702Slinton 
979702Slinton 				}
989702Slinton /* tbl */
999702Slinton 			return;
1009702Slinton 			}
1019702Slinton 		}
1029702Slinton 	cerror( "no hoptab for %s", opst[o] );
1039702Slinton 	}
1049702Slinton 
1059702Slinton char *
1069702Slinton rnames[] = {  /* keyed to register number tokens */
1079702Slinton 
1089702Slinton 	"r0", "r1",
1099702Slinton 	"r2", "r3", "r4", "r5",
1109702Slinton 	"r6", "r7", "r8", "r9", "r10", "r11",
1119702Slinton 	"ap", "fp", "sp", "pc",
1129702Slinton 
1139702Slinton 	};
1149702Slinton 
1159702Slinton int rstatus[] = {
1169702Slinton 	SAREG|STAREG, SAREG|STAREG,
1179702Slinton 	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
1189702Slinton 	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
1199702Slinton 	SAREG, SAREG, SAREG, SAREG,
1209702Slinton 
1219702Slinton 	};
1229702Slinton 
1239702Slinton tlen(p) NODE *p;
1249702Slinton {
1259702Slinton 	switch(p->in.type) {
1269702Slinton 		case CHAR:
1279702Slinton 		case UCHAR:
1289702Slinton 			return(1);
1299702Slinton 
1309702Slinton 		case SHORT:
1319702Slinton 		case USHORT:
1329702Slinton 			return(2);
1339702Slinton 
1349702Slinton 		case DOUBLE:
1359702Slinton 			return(8);
1369702Slinton 
1379702Slinton 		default:
1389702Slinton 			return(4);
1399702Slinton 		}
1409702Slinton }
1419702Slinton 
1429702Slinton mixtypes(p, q) NODE *p, *q;
1439702Slinton {
14416181Sralph 	register TWORD tp, tq;
1459702Slinton 
1469702Slinton 	tp = p->in.type;
1479702Slinton 	tq = q->in.type;
1489702Slinton 
1499702Slinton 	return( (tp==FLOAT || tp==DOUBLE) !=
1509702Slinton 		(tq==FLOAT || tq==DOUBLE) );
1519702Slinton }
1529702Slinton 
1539702Slinton prtype(n) NODE *n;
1549702Slinton {
1559702Slinton 	switch (n->in.type)
1569702Slinton 		{
1579702Slinton 		case DOUBLE:
15824418Smckusick 			putchar('d');
1599702Slinton 			return;
1609702Slinton 
1619702Slinton 		case FLOAT:
16224418Smckusick 			putchar('f');
1639702Slinton 			return;
1649702Slinton 
1659702Slinton 		case LONG:
1669702Slinton 		case ULONG:
1679702Slinton 		case INT:
1689702Slinton 		case UNSIGNED:
16924418Smckusick 			putchar('l');
1709702Slinton 			return;
1719702Slinton 
1729702Slinton 		case SHORT:
1739702Slinton 		case USHORT:
17424418Smckusick 			putchar('w');
1759702Slinton 			return;
1769702Slinton 
1779702Slinton 		case CHAR:
1789702Slinton 		case UCHAR:
17924418Smckusick 			putchar('b');
1809702Slinton 			return;
1819702Slinton 
1829702Slinton 		default:
1839702Slinton 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
1849702Slinton 			else {
18524418Smckusick 				putchar('l');
1869702Slinton 				return;
1879702Slinton 				}
1889702Slinton 		}
1899702Slinton }
1909702Slinton 
1919702Slinton zzzcode( p, c ) register NODE *p; {
1929702Slinton 	register m;
1939702Slinton 	CONSZ val;
1949702Slinton 	switch( c ){
1959702Slinton 
1969702Slinton 	case 'N':  /* logical ops, turned into 0-1 */
1979702Slinton 		/* use register given by register 1 */
1989702Slinton 		cbgen( 0, m=getlab(), 'I' );
1999702Slinton 		deflab( p->bn.label );
2009702Slinton 		printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );
2019702Slinton 		deflab( m );
2029702Slinton 		return;
2039702Slinton 
2049702Slinton 	case 'I':
2059702Slinton 	case 'P':
2069702Slinton 		cbgen( p->in.op, p->bn.label, c );
2079702Slinton 		return;
2089702Slinton 
2099702Slinton 	case 'A':
2109702Slinton 		{
2119702Slinton 		register NODE *l, *r;
2129702Slinton 
2139702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
2149702Slinton 		r = getlr(p, 'R');
21516181Sralph 		if (p->in.op == ASSIGN)
21616181Sralph 			l = getlr(p, 'L');
21717208Sralph 		else if (p->in.op == SCONV) {
2189702Slinton 			l = resc;
21917742Sralph #if defined(FORT) || defined(SPRECC)
22016181Sralph 			l->in.type = r->in.type;
22116181Sralph #else
22216181Sralph 			l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type;
22316181Sralph #endif
22416181Sralph 			r = getlr(p, 'L');
22516181Sralph 			}
22617208Sralph 		else {		/* OPLTYPE */
22716181Sralph 			l = resc;
22817742Sralph #if defined(FORT) || defined(SPRECC)
22916181Sralph 			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
23016181Sralph #else
2319702Slinton 			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
23216181Sralph #endif
2339702Slinton 			}
2349702Slinton 		if (r->in.op == ICON)
23517208Sralph 			if (r->in.name[0] == '\0') {
23617208Sralph 				if (r->tn.lval == 0) {
23724418Smckusick 					putstr("clr");
2389702Slinton 					prtype(l);
23924418Smckusick 					putchar('\t');
2409702Slinton 					adrput(l);
2419702Slinton 					return;
2429702Slinton 					}
24317208Sralph 				if (r->tn.lval < 0 && r->tn.lval >= -63) {
24424418Smckusick 					putstr("mneg");
2459702Slinton 					prtype(l);
2469702Slinton 					r->tn.lval = -r->tn.lval;
2479702Slinton 					goto ops;
2489702Slinton 					}
24917208Sralph 				if (r->tn.lval < 0)
25017208Sralph 					r->in.type = r->tn.lval >= -128 ? CHAR
2519702Slinton 						: (r->tn.lval >= -32768 ? SHORT
25217208Sralph 						: INT);
25317208Sralph 				else if (l->in.type == FLOAT ||
25417208Sralph 				    l->in.type == DOUBLE)
25517208Sralph 					r->in.type = r->tn.lval <= 63 ? INT
25617208Sralph 						: (r->tn.lval <= 127 ? CHAR
25717208Sralph 						: (r->tn.lval <= 32767 ? SHORT
25817208Sralph 						: INT));
25917208Sralph 				else
26017208Sralph 					r->in.type = r->tn.lval <= 63 ? INT
26117208Sralph 						: (r->tn.lval <= 127 ? CHAR
2629702Slinton 						: (r->tn.lval <= 255 ? UCHAR
2639702Slinton 						: (r->tn.lval <= 32767 ? SHORT
2649702Slinton 						: (r->tn.lval <= 65535 ? USHORT
26517208Sralph 						: INT))));
2669702Slinton 				}
26717208Sralph 			else {
26824418Smckusick 				putstr("moval");
26924418Smckusick 				putchar('\t');
27016181Sralph 				acon(r);
27124418Smckusick 				putchar(',');
27216181Sralph 				adrput(l);
27316181Sralph 				return;
27416181Sralph 				}
2759702Slinton 
27623536Sbloom 		if (p->in.op == SCONV &&
27723536Sbloom 		    !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
27823536Sbloom 		    !mixtypes(l, r)) {
27923536Sbloom 			/*
28023536Sbloom 			 * Because registers must always contain objects
28123536Sbloom 			 * of the same width as INTs, we may have to
28223536Sbloom 			 * perform two conversions to get an INT.  Can
28323536Sbloom 			 * the conversions be collapsed into one?
28423536Sbloom 			 */
28523536Sbloom 			if (m = collapsible(l, r))
28623536Sbloom 				r->in.type = m;
28723536Sbloom 			else {
28823536Sbloom 				/*
28923536Sbloom 				 * Two steps are required.
29023536Sbloom 				 */
29123536Sbloom 				NODE *x = &resc[1];
29223536Sbloom 
29323536Sbloom 				*x = *l;
29423536Sbloom 				if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
29524418Smckusick 					putstr("movz");
2969702Slinton 				else
29724418Smckusick 					putstr("cvt");
29823536Sbloom 				prtype(r);
29923536Sbloom 				prtype(x);
30024418Smckusick 				putchar('\t');
30123536Sbloom 				adrput(r);
30224418Smckusick 				putchar(',');
30323536Sbloom 				adrput(x);
30424418Smckusick 				putchar('\n');
30524418Smckusick 				putchar('\t');
30623536Sbloom 				r = x;
3079702Slinton 				}
30823536Sbloom 			l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
3099702Slinton 			}
31023536Sbloom 
311*25751Sdonn 		if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
312*25751Sdonn 		    mixtypes(l, r)) {
313*25751Sdonn 			int label1, label2;
314*25751Sdonn 
315*25751Sdonn 			label1 = getlab();
316*25751Sdonn 			label2 = getlab();
317*25751Sdonn 
318*25751Sdonn 			putstr("movl\t");
319*25751Sdonn 			adrput(r);
320*25751Sdonn 			putchar(',');
321*25751Sdonn 			adrput(l);
322*25751Sdonn 			putstr("\n\tbbsc\t$31,");
323*25751Sdonn 			adrput(l);
324*25751Sdonn 			printf(",L%d\n\tcvtl", label1);
325*25751Sdonn 			prtype(l);
326*25751Sdonn 			putchar('\t');
327*25751Sdonn 			adrput(l);
328*25751Sdonn 			putchar(',');
329*25751Sdonn 			adrput(l);
330*25751Sdonn 			printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1);
331*25751Sdonn 			prtype(l);
332*25751Sdonn 			putchar('\t');
333*25751Sdonn 			adrput(l);
334*25751Sdonn 			putchar(',');
335*25751Sdonn 			adrput(l);
336*25751Sdonn 			putstr("\n\tadd");
337*25751Sdonn 			prtype(l);
338*25751Sdonn 			putstr("2\t$0");
339*25751Sdonn 			prtype(l);
340*25751Sdonn 			putstr("2.147483648e9,");
341*25751Sdonn 			adrput(l);
342*25751Sdonn 			printf("\nL%d:", label2);
343*25751Sdonn 
344*25751Sdonn 			return;
345*25751Sdonn 			}
346*25751Sdonn 
34717208Sralph 		if (!mixtypes(l,r)) {
34817208Sralph 			if (tlen(l) == tlen(r)) {
34924418Smckusick 				putstr("mov");
35017742Sralph #ifdef FORT
35117742Sralph 				if (Oflag)
35217742Sralph 					prtype(l);
35317742Sralph 				else {
35417742Sralph 					if (l->in.type == DOUBLE)
35524418Smckusick 						putchar('q');
35617742Sralph 					else if(l->in.type == FLOAT)
35724418Smckusick 						putchar('l');
35817742Sralph 					else
35917742Sralph 						prtype(l);
36017742Sralph 					}
36117742Sralph #else
3629702Slinton 				prtype(l);
36317742Sralph #endif FORT
3649702Slinton 				goto ops;
3659702Slinton 				}
3669702Slinton 			else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
36724418Smckusick 				putstr("movz");
3689702Slinton 			else
36924418Smckusick 				putstr("cvt");
3709702Slinton 			}
3719702Slinton 		else
37224418Smckusick 			putstr("cvt");
3739702Slinton 		prtype(r);
3749702Slinton 		prtype(l);
3759702Slinton 	ops:
37624418Smckusick 		putchar('\t');
3779702Slinton 		adrput(r);
37824418Smckusick 		putchar(',');
3799702Slinton 		adrput(l);
3809702Slinton 		return;
3819702Slinton 		}
3829702Slinton 
383*25751Sdonn 	case 'G':	/* i *= f; asgops with int lhs and float rhs */
384*25751Sdonn 		{
385*25751Sdonn 		register NODE *l, *r, *s;
386*25751Sdonn 		int rt;
387*25751Sdonn 
388*25751Sdonn 		l = p->in.left;
389*25751Sdonn 		r = p->in.right;
390*25751Sdonn 		s = talloc();
391*25751Sdonn 		rt = r->in.type;
392*25751Sdonn 
393*25751Sdonn 		s->in.op = SCONV;
394*25751Sdonn 		s->in.left = l;
395*25751Sdonn 		s->in.type = rt;
396*25751Sdonn 		zzzcode(s, 'A');
397*25751Sdonn 		putstr("\n\t");
398*25751Sdonn 
399*25751Sdonn 		hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
400*25751Sdonn 		putstr("2\t");
401*25751Sdonn 		adrput(r);
402*25751Sdonn 		putchar(',');
403*25751Sdonn 		adrput(resc);
404*25751Sdonn 		putstr("\n\t");
405*25751Sdonn 
406*25751Sdonn 		s->in.op = ASSIGN;
407*25751Sdonn 		s->in.left = l;
408*25751Sdonn 		s->in.right = resc;
409*25751Sdonn 		s->in.type = l->in.type;
410*25751Sdonn 		zzzcode(s, 'A');
411*25751Sdonn 
412*25751Sdonn 		s->in.op = FREE;
413*25751Sdonn 		return;
414*25751Sdonn 		}
415*25751Sdonn 
4169702Slinton 	case 'B':	/* get oreg value in temp register for left shift */
4179702Slinton 		{
4189702Slinton 		register NODE *r;
4199702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
4209702Slinton 		r = p->in.right;
4219702Slinton 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
42224418Smckusick 			putstr("movl");
4239702Slinton 		else {
42424418Smckusick 			putstr("cvt");
4259702Slinton 			prtype(r);
42624418Smckusick 			putchar('l');
4279702Slinton 			}
4289702Slinton 		return;
4299702Slinton 		}
4309702Slinton 
4319702Slinton 	case 'C':	/* num words pushed on arg stack */
4329702Slinton 		{
4339702Slinton 		extern int gc_numbytes;
4349702Slinton 		extern int xdebug;
4359702Slinton 
4369702Slinton 		if (xdebug) printf("->%d<-",gc_numbytes);
4379702Slinton 
4389702Slinton 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
4399702Slinton 		return;
4409702Slinton 		}
4419702Slinton 
4429702Slinton 	case 'D':	/* INCR and DECR */
4439702Slinton 		zzzcode(p->in.left, 'A');
44424418Smckusick 		putchar('\n');
44524418Smckusick 		putchar('\t');
4469702Slinton 
4479702Slinton 	case 'E':	/* INCR and DECR, FOREFF */
4489702Slinton 		if (p->in.right->tn.lval == 1)
4499702Slinton 			{
45024418Smckusick 			putstr( p->in.op == INCR ? "inc" : "dec" );
4519702Slinton 			prtype(p->in.left);
45224418Smckusick 			putchar('\t');
4539702Slinton 			adrput(p->in.left);
4549702Slinton 			return;
4559702Slinton 			}
45624418Smckusick 		putstr( p->in.op == INCR ? "add" : "sub" );
4579702Slinton 		prtype(p->in.left);
45824418Smckusick 		putchar('2');
45924418Smckusick 		putchar('\t');
4609702Slinton 		adrput(p->in.right);
46124418Smckusick 		putchar(',');
4629702Slinton 		adrput(p->in.left);
4639702Slinton 		return;
4649702Slinton 
4659702Slinton 	case 'F':	/* register type of right operand */
4669702Slinton 		{
4679702Slinton 		register NODE *n;
4689702Slinton 		extern int xdebug;
4699702Slinton 		register int ty;
4709702Slinton 
4719702Slinton 		n = getlr( p, 'R' );
4729702Slinton 		ty = n->in.type;
4739702Slinton 
4749702Slinton 		if (xdebug) printf("->%d<-", ty);
4759702Slinton 
47624418Smckusick 		if ( ty==DOUBLE) putchar('d');
47724418Smckusick 		else if ( ty==FLOAT ) putchar('f');
47824418Smckusick 		else putchar('l');
4799702Slinton 		return;
4809702Slinton 		}
4819702Slinton 
4829702Slinton 	case 'L':	/* type of left operand */
4839702Slinton 	case 'R':	/* type of right operand */
4849702Slinton 		{
4859702Slinton 		register NODE *n;
4869702Slinton 		extern int xdebug;
4879702Slinton 
48816181Sralph 		n = getlr( p, c );
4899702Slinton 		if (xdebug) printf("->%d<-", n->in.type);
4909702Slinton 
4919702Slinton 		prtype(n);
4929702Slinton 		return;
4939702Slinton 		}
4949702Slinton 
4959702Slinton 	case 'Z':	/* complement mask for bit instr */
4969702Slinton 		printf("$%ld", ~p->in.right->tn.lval);
4979702Slinton 		return;
4989702Slinton 
4999702Slinton 	case 'U':	/* 32 - n, for unsigned right shifts */
5009702Slinton 		printf("$%d", 32 - p->in.right->tn.lval );
5019702Slinton 		return;
5029702Slinton 
5039702Slinton 	case 'T':	/* rounded structure length for arguments */
5049702Slinton 		{
5059702Slinton 		int size;
5069702Slinton 
5079702Slinton 		size = p->stn.stsize;
5089702Slinton 		SETOFF( size, 4);
5099702Slinton 		printf("$%d", size);
5109702Slinton 		return;
5119702Slinton 		}
5129702Slinton 
5139702Slinton 	case 'S':  /* structure assignment */
5149702Slinton 		{
5159702Slinton 			register NODE *l, *r;
5169702Slinton 			register size;
5179702Slinton 
5189702Slinton 			if( p->in.op == STASG ){
5199702Slinton 				l = p->in.left;
5209702Slinton 				r = p->in.right;
5219702Slinton 
5229702Slinton 				}
5239702Slinton 			else if( p->in.op == STARG ){  /* store an arg into a temporary */
5249702Slinton 				r = p->in.left;
5259702Slinton 				}
5269702Slinton 			else cerror( "STASG bad" );
5279702Slinton 
5289702Slinton 			if( r->in.op == ICON ) r->in.op = NAME;
5299702Slinton 			else if( r->in.op == REG ) r->in.op = OREG;
5309702Slinton 			else if( r->in.op != OREG ) cerror( "STASG-r" );
5319702Slinton 
5329702Slinton 			size = p->stn.stsize;
5339702Slinton 
5349702Slinton 			if( size <= 0 || size > 65535 )
5359702Slinton 				cerror("structure size <0=0 or >65535");
5369702Slinton 
5379702Slinton 			switch(size) {
5389702Slinton 				case 1:
53924418Smckusick 					putstr("	movb	");
5409702Slinton 					break;
5419702Slinton 				case 2:
54224418Smckusick 					putstr("	movw	");
5439702Slinton 					break;
5449702Slinton 				case 4:
54524418Smckusick 					putstr("	movl	");
5469702Slinton 					break;
5479702Slinton 				case 8:
54824418Smckusick 					putstr("	movq	");
5499702Slinton 					break;
5509702Slinton 				default:
5519702Slinton 					printf("	movc3	$%d,", size);
5529702Slinton 					break;
5539702Slinton 			}
5549702Slinton 			adrput(r);
55516418Sralph 			if( p->in.op == STASG ){
55624418Smckusick 				putchar(',');
55716418Sralph 				adrput(l);
55824418Smckusick 				putchar('\n');
55916418Sralph 				}
56016418Sralph 			else
56124418Smckusick 				putstr(",(sp)\n");
5629702Slinton 
5639702Slinton 			if( r->in.op == NAME ) r->in.op = ICON;
5649702Slinton 			else if( r->in.op == OREG ) r->in.op = REG;
5659702Slinton 
5669702Slinton 			}
5679702Slinton 		break;
5689702Slinton 
5699702Slinton 	default:
5709702Slinton 		cerror( "illegal zzzcode" );
5719702Slinton 		}
5729702Slinton 	}
5739702Slinton 
57423536Sbloom /*
57523536Sbloom  * collapsible(dest, src) -- if a conversion with a register destination
57623536Sbloom  *	can be accomplished in one instruction, return the type of src
57723536Sbloom  *	that will do the job correctly; otherwise return 0.  Note that
57823536Sbloom  *	a register must always end up having type INT or UNSIGNED.
57923536Sbloom  */
58023536Sbloom int
58123536Sbloom collapsible(dest, src)
58223536Sbloom NODE *dest, *src;
58323536Sbloom {
58423536Sbloom 	int st = src->in.type;
58523536Sbloom 	int dt = dest->in.type;
58623536Sbloom 	int newt = 0;
58723536Sbloom 
58823536Sbloom 	/*
58923536Sbloom 	 * Are there side effects of evaluating src?
59023536Sbloom 	 * If the derived type will not be the same size as src,
59124418Smckusick 	 * we may have to use two steps.
59223536Sbloom 	 */
59324418Smckusick 	if (tlen(src) > tlen(dest)) {
59424418Smckusick 		if (tshape(src, STARREG))
59524418Smckusick 			return (0);
59624418Smckusick 		if (src->in.op == OREG && R2TEST(src->tn.rval))
59724418Smckusick 			return (0);
59824418Smckusick 		}
59923536Sbloom 
60023536Sbloom 	/*
60123536Sbloom 	 * Can we get an object of dest's type by punning src?
60223536Sbloom 	 * Praises be to great Cthulhu for little-endian machines...
60323536Sbloom 	 */
60423536Sbloom 	if (st == CHAR && dt == USHORT)
60523536Sbloom 		/*
60623536Sbloom 		 * Special case -- we must sign-extend to 16 bits.
60723536Sbloom 		 */
60823536Sbloom 		return (0);
60923536Sbloom 
61023536Sbloom 	if (tlen(src) < tlen(dest))
61123536Sbloom 		newt = st;
61223536Sbloom 	else
61323536Sbloom 		newt = dt;
61423536Sbloom 
61523536Sbloom 	return (newt);
61623536Sbloom 	}
61723536Sbloom 
61817742Sralph rmove( rt, rs, t ) TWORD t; {
6199702Slinton 	printf( "	%s	%s,%s\n",
62017742Sralph #ifdef FORT
62117742Sralph 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
62217742Sralph #endif
6239702Slinton 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
6249702Slinton 		rnames[rs], rnames[rt] );
6259702Slinton 	}
6269702Slinton 
6279702Slinton struct respref
6289702Slinton respref[] = {
6299702Slinton 	INTAREG|INTBREG,	INTAREG|INTBREG,
6309702Slinton 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
6319702Slinton 	INTEMP,	INTEMP,
6329702Slinton 	FORARG,	FORARG,
6339702Slinton 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
6349702Slinton 	0,	0 };
6359702Slinton 
6369702Slinton setregs(){ /* set up temporary registers */
6379702Slinton 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
6389702Slinton 	;
6399702Slinton 	}
6409702Slinton 
6419702Slinton rewfld( p ) NODE *p; {
6429702Slinton 	return(1);
6439702Slinton 	}
6449702Slinton 
6459702Slinton callreg(p) NODE *p; {
6469702Slinton 	return( R0 );
6479702Slinton 	}
6489702Slinton 
6499702Slinton base( p ) register NODE *p; {
6509702Slinton 	register int o = p->in.op;
6519702Slinton 
6529702Slinton 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
6539702Slinton 	if( o==REG ) return( p->tn.rval );
6549702Slinton     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
6559702Slinton 		return( p->in.left->tn.rval );
6569702Slinton     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
6579702Slinton 		return( p->tn.rval + 0200*1 );
6589702Slinton 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
6599702Slinton 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
6609702Slinton 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
6619702Slinton 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
6629702Slinton 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
6639702Slinton 	return( -1 );
6649702Slinton 	}
6659702Slinton 
6669702Slinton offset( p, tyl ) register NODE *p; int tyl; {
6679702Slinton 
66824418Smckusick 	if( tyl==1 &&
66924418Smckusick 	    p->in.op==REG &&
67024418Smckusick 	    (p->in.type==INT || p->in.type==UNSIGNED) )
67124418Smckusick 		return( p->tn.rval );
67224418Smckusick 	if( p->in.op==LS &&
67324418Smckusick 	    p->in.left->in.op==REG &&
67424418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
67524418Smckusick 	    p->in.right->in.op==ICON &&
67624418Smckusick 	    p->in.right->in.name[0]=='\0' &&
67724418Smckusick 	    (1<<p->in.right->tn.lval)==tyl)
6789702Slinton 		return( p->in.left->tn.rval );
67924418Smckusick 	if( tyl==2 &&
68024418Smckusick 	    p->in.op==PLUS &&
68124418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
68224418Smckusick 	    p->in.left->in.op==REG &&
68324418Smckusick 	    p->in.right->in.op==REG &&
68424418Smckusick 	    p->in.left->tn.rval==p->in.right->tn.rval )
68524418Smckusick 		return( p->in.left->tn.rval );
6869702Slinton 	return( -1 );
6879702Slinton 	}
6889702Slinton 
6899702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
6909702Slinton 	register NODE *t;
6919702Slinton 	register int i;
6929702Slinton 	NODE *f;
6939702Slinton 
6949702Slinton 	p->in.op = OREG;
6959702Slinton 	f = p->in.left; 	/* have to free this subtree later */
6969702Slinton 
6979702Slinton 	/* init base */
6989702Slinton 	switch (q->in.op) {
6999702Slinton 		case ICON:
7009702Slinton 		case REG:
7019702Slinton 		case OREG:
7029702Slinton 			t = q;
7039702Slinton 			break;
7049702Slinton 
7059702Slinton 		case MINUS:
7069702Slinton 			q->in.right->tn.lval = -q->in.right->tn.lval;
7079702Slinton 		case PLUS:
7089702Slinton 			t = q->in.right;
7099702Slinton 			break;
7109702Slinton 
7119702Slinton 		case INCR:
7129702Slinton 		case ASG MINUS:
7139702Slinton 			t = q->in.left;
7149702Slinton 			break;
7159702Slinton 
7169702Slinton 		case UNARY MUL:
7179702Slinton 			t = q->in.left->in.left;
7189702Slinton 			break;
7199702Slinton 
7209702Slinton 		default:
7219702Slinton 			cerror("illegal makeor2");
7229702Slinton 	}
7239702Slinton 
7249702Slinton 	p->tn.lval = t->tn.lval;
7259702Slinton #ifndef FLEXNAMES
7269702Slinton 	for(i=0; i<NCHNAM; ++i)
7279702Slinton 		p->in.name[i] = t->in.name[i];
7289702Slinton #else
7299702Slinton 	p->in.name = t->in.name;
7309702Slinton #endif
7319702Slinton 
7329702Slinton 	/* init offset */
7339702Slinton 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
7349702Slinton 
7359702Slinton 	tfree(f);
7369702Slinton 	return;
7379702Slinton 	}
7389702Slinton 
7399702Slinton canaddr( p ) NODE *p; {
7409702Slinton 	register int o = p->in.op;
7419702Slinton 
7429702Slinton 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
7439702Slinton 	return(0);
7449702Slinton 	}
7459702Slinton 
7469702Slinton flshape( p ) register NODE *p; {
7479702Slinton 	return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
7489702Slinton 		(p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
7499702Slinton 	}
7509702Slinton 
7519702Slinton shtemp( p ) register NODE *p; {
7529702Slinton 	if( p->in.op == STARG ) p = p->in.left;
7539702Slinton 	return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
7549702Slinton 	}
7559702Slinton 
7569702Slinton shumul( p ) register NODE *p; {
7579702Slinton 	register o;
7589702Slinton 	extern int xdebug;
7599702Slinton 
7609702Slinton 	if (xdebug) {
7619702Slinton 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
7629702Slinton 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
7639702Slinton 		}
7649702Slinton 
7659702Slinton 
7669702Slinton 	o = p->in.op;
7679702Slinton 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
7689702Slinton 
7699702Slinton 	if( ( o == INCR || o == ASG MINUS ) &&
7709702Slinton 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
7719702Slinton 	    p->in.right->in.name[0] == '\0' )
7729702Slinton 		{
77317659Sralph 		switch (p->in.type)
7749702Slinton 			{
7759702Slinton 			case CHAR|PTR:
7769702Slinton 			case UCHAR|PTR:
7779702Slinton 				o = 1;
7789702Slinton 				break;
7799702Slinton 
7809702Slinton 			case SHORT|PTR:
7819702Slinton 			case USHORT|PTR:
7829702Slinton 				o = 2;
7839702Slinton 				break;
7849702Slinton 
7859702Slinton 			case INT|PTR:
7869702Slinton 			case UNSIGNED|PTR:
7879702Slinton 			case LONG|PTR:
7889702Slinton 			case ULONG|PTR:
7899702Slinton 			case FLOAT|PTR:
7909702Slinton 				o = 4;
7919702Slinton 				break;
7929702Slinton 
7939702Slinton 			case DOUBLE|PTR:
7949702Slinton 				o = 8;
7959702Slinton 				break;
7969702Slinton 
7979702Slinton 			default:
79817742Sralph 				if ( ISPTR(p->in.type) &&
79917742Sralph 				     ISPTR(DECREF(p->in.type)) ) {
8009702Slinton 					o = 4;
8019702Slinton 					break;
8029702Slinton 					}
8039702Slinton 				else return(0);
8049702Slinton 			}
8059702Slinton 		return( p->in.right->tn.lval == o ? STARREG : 0);
8069702Slinton 		}
8079702Slinton 
8089702Slinton 	return( 0 );
8099702Slinton 	}
8109702Slinton 
8119702Slinton adrcon( val ) CONSZ val; {
81224418Smckusick 	putchar( '$' );
8139702Slinton 	printf( CONFMT, val );
8149702Slinton 	}
8159702Slinton 
8169702Slinton conput( p ) register NODE *p; {
8179702Slinton 	switch( p->in.op ){
8189702Slinton 
8199702Slinton 	case ICON:
8209702Slinton 		acon( p );
8219702Slinton 		return;
8229702Slinton 
8239702Slinton 	case REG:
82424418Smckusick 		putstr( rnames[p->tn.rval] );
8259702Slinton 		return;
8269702Slinton 
8279702Slinton 	default:
8289702Slinton 		cerror( "illegal conput" );
8299702Slinton 		}
8309702Slinton 	}
8319702Slinton 
8329702Slinton insput( p ) register NODE *p; {
8339702Slinton 	cerror( "insput" );
8349702Slinton 	}
8359702Slinton 
8369702Slinton upput( p ) register NODE *p; {
8379702Slinton 	cerror( "upput" );
8389702Slinton 	}
8399702Slinton 
8409702Slinton adrput( p ) register NODE *p; {
8419702Slinton 	register int r;
8429702Slinton 	/* output an address, with offsets, from p */
8439702Slinton 
8449702Slinton 	if( p->in.op == FLD ){
8459702Slinton 		p = p->in.left;
8469702Slinton 		}
8479702Slinton 	switch( p->in.op ){
8489702Slinton 
8499702Slinton 	case NAME:
8509702Slinton 		acon( p );
8519702Slinton 		return;
8529702Slinton 
8539702Slinton 	case ICON:
8549702Slinton 		/* addressable value of the constant */
85524418Smckusick 		putchar( '$' );
8569702Slinton 		acon( p );
8579702Slinton 		return;
8589702Slinton 
8599702Slinton 	case REG:
86024418Smckusick 		putstr( rnames[p->tn.rval] );
8619702Slinton 		return;
8629702Slinton 
8639702Slinton 	case OREG:
8649702Slinton 		r = p->tn.rval;
8659702Slinton 		if( R2TEST(r) ){ /* double indexing */
8669702Slinton 			register int flags;
8679702Slinton 
8689702Slinton 			flags = R2UPK3(r);
86924418Smckusick 			if( flags & 1 ) putchar('*');
87024418Smckusick 			if( flags & 4 ) putchar('-');
8719702Slinton 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
8729702Slinton 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
87324418Smckusick 			if( flags & 2 ) putchar('+');
8749702Slinton 			printf( "[%s]", rnames[R2UPK2(r)] );
8759702Slinton 			return;
8769702Slinton 			}
8779702Slinton 		if( r == AP ){  /* in the argument region */
8789702Slinton 			if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" );
8799702Slinton 			printf( CONFMT, p->tn.lval );
88024418Smckusick 			putstr( "(ap)" );
8819702Slinton 			return;
8829702Slinton 			}
8839702Slinton 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
8849702Slinton 		printf( "(%s)", rnames[p->tn.rval] );
8859702Slinton 		return;
8869702Slinton 
8879702Slinton 	case UNARY MUL:
8889702Slinton 		/* STARNM or STARREG found */
8899702Slinton 		if( tshape(p, STARNM) ) {
89024418Smckusick 			putchar( '*' );
8919702Slinton 			adrput( p->in.left);
8929702Slinton 			}
8939702Slinton 		else {	/* STARREG - really auto inc or dec */
8949702Slinton 			register NODE *q;
8959702Slinton 
8969702Slinton /* tbl
8979702Slinton 			p = p->in.left;
8989702Slinton 			p->in.left->in.op = OREG;
8999702Slinton 			if( p->in.op == INCR ) {
9009702Slinton 				adrput( p->in.left );
90124418Smckusick 				putchar( '+' );
9029702Slinton 				}
9039702Slinton 			else {
90424418Smckusick 				putchar( '-' );
9059702Slinton 				adrput( p->in.left );
9069702Slinton 				}
9079702Slinton    tbl */
90817659Sralph 			q = p->in.left;
90917742Sralph 			if( q->in.right->tn.lval != tlen(p) )
91017742Sralph 				cerror("adrput: bad auto-increment/decrement");
91117659Sralph 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
91217659Sralph 				rnames[q->in.left->tn.rval],
91317659Sralph 				(q->in.op==INCR ? "+" : "") );
9149702Slinton 			p->in.op = OREG;
91517659Sralph 			p->tn.rval = q->in.left->tn.rval;
91617659Sralph 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
9179702Slinton #ifndef FLEXNAMES
9189702Slinton 			p->in.name[0] = '\0';
9199702Slinton #else
9209702Slinton 			p->in.name = "";
9219702Slinton #endif
9229702Slinton 			tfree(q);
9239702Slinton 		}
9249702Slinton 		return;
9259702Slinton 
9269702Slinton 	default:
9279702Slinton 		cerror( "illegal address" );
9289702Slinton 		return;
9299702Slinton 
9309702Slinton 		}
9319702Slinton 
9329702Slinton 	}
9339702Slinton 
9349702Slinton acon( p ) register NODE *p; { /* print out a constant */
9359702Slinton 
9369702Slinton 	if( p->in.name[0] == '\0' ){
9379702Slinton 		printf( CONFMT, p->tn.lval);
9389702Slinton 		}
9399702Slinton 	else if( p->tn.lval == 0 ) {
9409702Slinton #ifndef FLEXNAMES
9419702Slinton 		printf( "%.8s", p->in.name );
9429702Slinton #else
94324418Smckusick 		putstr( p->in.name );
9449702Slinton #endif
9459702Slinton 		}
9469702Slinton 	else {
9479702Slinton #ifndef FLEXNAMES
9489702Slinton 		printf( "%.8s+", p->in.name );
9499702Slinton #else
9509702Slinton 		printf( "%s+", p->in.name );
9519702Slinton #endif
9529702Slinton 		printf( CONFMT, p->tn.lval );
9539702Slinton 		}
9549702Slinton 	}
9559702Slinton 
9569702Slinton /*
9579702Slinton aacon( p ) register NODE *p; { /* print out a constant */
9589702Slinton /*
9599702Slinton 
9609702Slinton 	if( p->in.name[0] == '\0' ){
9619702Slinton 		printf( CONFMT, p->tn.lval);
9629702Slinton 		return( 0 );
9639702Slinton 		}
9649702Slinton 	else if( p->tn.lval == 0 ) {
9659702Slinton #ifndef FLEXNAMES
9669702Slinton 		printf( "$%.8s", p->in.name );
9679702Slinton #else
9689702Slinton 		printf( "$%s", p->in.name );
9699702Slinton #endif
9709702Slinton 		return( 1 );
9719702Slinton 		}
9729702Slinton 	else {
9739702Slinton 		printf( "$(" );
9749702Slinton 		printf( CONFMT, p->tn.lval );
9759702Slinton 		printf( "+" );
9769702Slinton #ifndef FLEXNAMES
9779702Slinton 		printf( "%.8s)", p->in.name );
9789702Slinton #else
9799702Slinton 		printf( "%s)", p->in.name );
9809702Slinton #endif
9819702Slinton 		return(1);
9829702Slinton 		}
9839702Slinton 	}
9849702Slinton  */
9859702Slinton 
9869702Slinton genscall( p, cookie ) register NODE *p; {
9879702Slinton 	/* structure valued call */
9889702Slinton 	return( gencall( p, cookie ) );
9899702Slinton 	}
9909702Slinton 
9919702Slinton /* tbl */
9929702Slinton int gc_numbytes;
9939702Slinton /* tbl */
9949702Slinton 
9959702Slinton gencall( p, cookie ) register NODE *p; {
9969702Slinton 	/* generate the call given by p */
99716418Sralph 	register NODE *p1;
9989702Slinton 	register temp, temp1;
9999702Slinton 	register m;
10009702Slinton 
10019702Slinton 	if( p->in.right ) temp = argsize( p->in.right );
10029702Slinton 	else temp = 0;
10039702Slinton 
10049702Slinton 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
10059702Slinton 		/* set aside room for structure return */
10069702Slinton 
10079702Slinton 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
10089702Slinton 		else temp1 = temp;
10099702Slinton 		}
10109702Slinton 
10119702Slinton 	if( temp > maxargs ) maxargs = temp;
10129702Slinton 	SETOFF(temp1,4);
10139702Slinton 
10149702Slinton 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
101516418Sralph 		genargs( p->in.right );
10169702Slinton 		}
10179702Slinton 
10189702Slinton 	p1 = p->in.left;
10199702Slinton 	if( p1->in.op != ICON ){
10209702Slinton 		if( p1->in.op != REG ){
10219702Slinton 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
10229702Slinton 				if( p1->in.op != NAME ){
10239702Slinton 					order( p1, INAREG );
10249702Slinton 					}
10259702Slinton 				}
10269702Slinton 			}
10279702Slinton 		}
10289702Slinton 
10299702Slinton /*
10309702Slinton 	if( p1->in.op == REG && p->tn.rval == R5 ){
10319702Slinton 		cerror( "call register overwrite" );
10329702Slinton 		}
10339702Slinton  */
10349702Slinton /* tbl
10359702Slinton 	setup gc_numbytes so reference to ZC works */
10369702Slinton 
10379702Slinton 	gc_numbytes = temp&(0x3ff);
10389702Slinton /* tbl */
10399702Slinton 
10409702Slinton 	p->in.op = UNARY CALL;
10419702Slinton 	m = match( p, INTAREG|INTBREG );
10429702Slinton 
10439702Slinton 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
10449702Slinton 	/* (plus in assignment to gc_numbytes above, for neatness only) */
10459702Slinton 	if (temp >= 1024)
10469702Slinton 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
10479702Slinton 
10489702Slinton /* tbl
10499702Slinton 	switch( temp ) {
10509702Slinton 	case 0:
10519702Slinton 		break;
10529702Slinton 	case 2:
10539702Slinton 		printf( "	tst	(sp)+\n" );
10549702Slinton 		break;
10559702Slinton 	case 4:
10569702Slinton 		printf( "	cmp	(sp)+,(sp)+\n" );
10579702Slinton 		break;
10589702Slinton 	default:
10599702Slinton 		printf( "	add	$%d,sp\n", temp);
10609702Slinton 		}
10619702Slinton    tbl */
10629702Slinton 	return(m != MDONE);
10639702Slinton 	}
10649702Slinton 
10659702Slinton /* tbl */
10669702Slinton char *
10679702Slinton ccbranches[] = {
10689702Slinton 	"	jeql	L%d\n",
10699702Slinton 	"	jneq	L%d\n",
10709702Slinton 	"	jleq	L%d\n",
10719702Slinton 	"	jlss	L%d\n",
10729702Slinton 	"	jgeq	L%d\n",
10739702Slinton 	"	jgtr	L%d\n",
10749702Slinton 	"	jlequ	L%d\n",
10759702Slinton 	"	jlssu	L%d\n",
10769702Slinton 	"	jgequ	L%d\n",
10779702Slinton 	"	jgtru	L%d\n",
10789702Slinton 	};
10799702Slinton /* tbl */
10809702Slinton 
10819702Slinton cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
10829702Slinton 
10839702Slinton /* tbl */
10849702Slinton 	if( o == 0 ) printf( "	jbr	L%d\n", lab );
10859702Slinton /* tbl */
10869702Slinton 	else {
10879702Slinton 		if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
10889702Slinton 		printf( ccbranches[o-EQ], lab );
10899702Slinton 		}
10909702Slinton 	}
10919702Slinton 
10929702Slinton nextcook( p, cookie ) NODE *p; {
10939702Slinton 	/* we have failed to match p with cookie; try another */
10949702Slinton 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
10959702Slinton 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
10969702Slinton 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
10979702Slinton 	return( FORREW );
10989702Slinton 	}
10999702Slinton 
11009702Slinton lastchance( p, cook ) NODE *p; {
11019702Slinton 	/* forget it! */
11029702Slinton 	return(0);
11039702Slinton 	}
11049702Slinton 
11059702Slinton optim2( p ) register NODE *p; {
11069702Slinton 	/* do local tree transformations and optimizations */
11079702Slinton 
110816181Sralph 	register NODE *l, *r;
110916181Sralph 	int m, ml;
11109702Slinton 
11119702Slinton 	switch( p->in.op ) {
11129702Slinton 
11139702Slinton 	case AND:
111419933Smckusick 		/* commute L and R to eliminate complements and constants */
111516181Sralph 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
111616181Sralph 		    l->in.op == COMPL ) {
11179702Slinton 			p->in.left = p->in.right;
111816181Sralph 			p->in.right = l;
11199702Slinton 			}
11209702Slinton 	case ASG AND:
11219702Slinton 		/* change meaning of AND to ~R&L - bic on pdp11 */
11229702Slinton 		r = p->in.right;
112319933Smckusick 		if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */
11249702Slinton 			r->tn.lval = ~r->tn.lval;
11259702Slinton 			}
11269702Slinton 		else if( r->in.op==COMPL ) { /* ~~A => A */
11279702Slinton 			r->in.op = FREE;
11289702Slinton 			p->in.right = r->in.left;
11299702Slinton 			}
11309702Slinton 		else { /* insert complement node */
113116181Sralph 			p->in.right = l = talloc();
113216181Sralph 			l->in.op = COMPL;
113316181Sralph 			l->in.rall = NOPREF;
113416181Sralph 			l->in.type = r->in.type;
113516181Sralph 			l->in.left = r;
113616181Sralph 			l->in.right = NULL;
11379702Slinton 			}
11389702Slinton 		break;
11399702Slinton 
114016181Sralph 	case SCONV:
114119933Smckusick 		l = p->in.left;
114217742Sralph #if defined(FORT) || defined(SPRECC)
114316573Sralph 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
114419933Smckusick 		    l->in.type == FLOAT || l->in.type == DOUBLE )
114519933Smckusick 			return;
114616573Sralph #else
114719933Smckusick 		if( mixtypes(p, l) ) return;
114816573Sralph #endif
1149*25751Sdonn 		if( l->in.op == PCONV )
1150*25751Sdonn 			return;
1151*25751Sdonn 
115219933Smckusick 		/* Only trust it to get it right if the size is the same */
115319933Smckusick 		if( tlen(p) != tlen(l) )
115419933Smckusick 			return;
115516181Sralph 
115616181Sralph 		/* clobber conversion */
115719933Smckusick 		if( l->in.op != FLD )
115816181Sralph 			l->in.type = p->in.type;
115916181Sralph 		ncopy( p, l );
116016181Sralph 		l->in.op = FREE;
116119933Smckusick 
116216181Sralph 		break;
116316181Sralph 
116424418Smckusick 	case ASSIGN:
116524418Smckusick 		/*
116624418Smckusick 		 * Conversions are equivalent to assignments;
116724418Smckusick 		 * when the two operations are combined,
116824418Smckusick 		 * we can sometimes zap the conversion.
116924418Smckusick 		 */
117024418Smckusick 		r = p->in.right;
117124418Smckusick 		l = p->in.left;
117224418Smckusick 		if ( r->in.op == SCONV &&
117324418Smckusick 		     !mixtypes(l, r) &&
117424418Smckusick 		     tlen(l) == tlen(r) ) {
117524418Smckusick 				p->in.right = r->in.left;
117624418Smckusick 				r->in.op = FREE;
117724418Smckusick 			}
117824418Smckusick 		break;
117924418Smckusick 
11809702Slinton 		}
11819702Slinton 	}
11829702Slinton 
118317742Sralph NODE * addroreg(l) NODE *l;
11849702Slinton 				/* OREG was built in clocal()
11859702Slinton 				 * for an auto or formal parameter
11869702Slinton 				 * now its address is being taken
11879702Slinton 				 * local code must unwind it
11889702Slinton 				 * back to PLUS/MINUS REG ICON
11899702Slinton 				 * according to local conventions
11909702Slinton 				 */
11919702Slinton {
11929702Slinton 	cerror("address of OREG taken");
119317742Sralph 	/*NOTREACHED*/
11949702Slinton }
11959702Slinton 
11969702Slinton 
11979702Slinton 
11989702Slinton # ifndef ONEPASS
11999702Slinton main( argc, argv ) char *argv[]; {
12009702Slinton 	return( mainp2( argc, argv ) );
12019702Slinton 	}
12029702Slinton # endif
12039702Slinton 
12049702Slinton 
12059702Slinton /* added by jwf */
12069702Slinton struct functbl {
12079702Slinton 	int fop;
12089702Slinton 	TWORD ftype;
12099702Slinton 	char *func;
12109702Slinton 	} opfunc[] = {
12119702Slinton 	DIV,		TANY,	"udiv",
12129702Slinton 	MOD,		TANY,	"urem",
121317715Sralph 	ASG DIV,	TANY,	"audiv",
121417715Sralph 	ASG MOD,	TANY,	"aurem",
12159702Slinton 	0,	0,	0 };
12169702Slinton 
12179702Slinton hardops(p)  register NODE *p; {
12189702Slinton 	/* change hard to do operators into function calls.  */
12199702Slinton 	register NODE *q;
12209702Slinton 	register struct functbl *f;
12219702Slinton 	register o;
122217742Sralph 	NODE *old,*temp;
12239702Slinton 
12249702Slinton 	o = p->in.op;
122517742Sralph 	if( ! (optype(o)==BITYPE &&
122617742Sralph 	       (ISUNSIGNED(p->in.left->in.type) ||
122717742Sralph 		ISUNSIGNED(p->in.right->in.type))) )
122817742Sralph 		return;
12299702Slinton 
12309702Slinton 	for( f=opfunc; f->fop; f++ ) {
12319702Slinton 		if( o==f->fop ) goto convert;
12329702Slinton 		}
12339702Slinton 	return;
12349702Slinton 
12359702Slinton 	convert:
12369702Slinton 	if( asgop( o ) ) {
123717742Sralph 		old = NIL;
123817715Sralph 		switch( p->in.left->in.op ){
123917742Sralph 		case FLD:
124017742Sralph 			q = p->in.left->in.left;
124117742Sralph 			/*
124217742Sralph 			 * rewrite (lval.fld /= rval); as
124317742Sralph 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
124417742Sralph 			 * else the compiler will evaluate lval twice.
124517742Sralph 			 */
124617742Sralph 			if( q->in.op == UNARY MUL ){
124717742Sralph 				/* first allocate a temp storage */
124817742Sralph 				temp = talloc();
124917742Sralph 				temp->in.op = OREG;
125017742Sralph 				temp->tn.rval = TMPREG;
125117742Sralph 				temp->tn.lval = BITOOR(freetemp(1));
125217742Sralph 				temp->in.type = INCREF(p->in.type);
125317742Sralph #ifdef FLEXNAMES
125417742Sralph 				temp->in.name = "";
125517742Sralph #else
125617742Sralph 				temp->in.name[0] = '\0';
125717742Sralph #endif
125817742Sralph 				old = q->in.left;
125917742Sralph 				q->in.left = temp;
126017742Sralph 			}
126117742Sralph 			/* fall thru ... */
126217742Sralph 
126317715Sralph 		case REG:
126417715Sralph 		case NAME:
126517715Sralph 		case OREG:
126617715Sralph 			/* change ASG OP to a simple OP */
126717715Sralph 			q = talloc();
126817715Sralph 			q->in.op = NOASG p->in.op;
126917715Sralph 			q->in.rall = NOPREF;
127017715Sralph 			q->in.type = p->in.type;
127117715Sralph 			q->in.left = tcopy(p->in.left);
127217715Sralph 			q->in.right = p->in.right;
127317715Sralph 			p->in.op = ASSIGN;
127417715Sralph 			p->in.right = q;
127517715Sralph 			p = q;
127617715Sralph 			f -= 2; /* Note: this depends on the table order */
127717742Sralph 			/* on the right side only - replace *temp with
127817742Sralph 			 *(temp = &lval), build the assignment node */
127917742Sralph 			if( old ){
128017742Sralph 				temp = q->in.left->in.left; /* the "*" node */
128117742Sralph 				q = talloc();
128217742Sralph 				q->in.op = ASSIGN;
128317742Sralph 				q->in.left = temp->in.left;
128417742Sralph 				q->in.right = old;
128517742Sralph 				q->in.type = old->in.type;
128617742Sralph #ifdef FLEXNAMES
128717742Sralph 				q->in.name = "";
128817742Sralph #else
128917742Sralph 				q->in.name[0] = '\0';
129017742Sralph #endif
129117742Sralph 				temp->in.left = q;
129217742Sralph 			}
129317715Sralph 			break;
12949702Slinton 
129517715Sralph 		case UNARY MUL:
129617715Sralph 			/* avoid doing side effects twice */
129717715Sralph 			q = p->in.left;
129817715Sralph 			p->in.left = q->in.left;
129917715Sralph 			q->in.op = FREE;
130017715Sralph 			break;
130117715Sralph 
130217715Sralph 		default:
130317715Sralph 			cerror( "hardops: can't compute & LHS" );
130417715Sralph 			}
130517742Sralph 		}
130617715Sralph 
13079702Slinton 	/* build comma op for args to function */
13089702Slinton 	q = talloc();
13099702Slinton 	q->in.op = CM;
13109702Slinton 	q->in.rall = NOPREF;
13119702Slinton 	q->in.type = INT;
13129702Slinton 	q->in.left = p->in.left;
13139702Slinton 	q->in.right = p->in.right;
13149702Slinton 	p->in.op = CALL;
13159702Slinton 	p->in.right = q;
13169702Slinton 
13179702Slinton 	/* put function name in left node of call */
13189702Slinton 	p->in.left = q = talloc();
13199702Slinton 	q->in.op = ICON;
13209702Slinton 	q->in.rall = NOPREF;
13219702Slinton 	q->in.type = INCREF( FTN + p->in.type );
13229702Slinton #ifndef FLEXNAMES
13239702Slinton 	strcpy( q->in.name, f->func );
13249702Slinton #else
13259702Slinton 	q->in.name = f->func;
13269702Slinton #endif
13279702Slinton 	q->tn.lval = 0;
13289702Slinton 	q->tn.rval = 0;
13299702Slinton 
13309702Slinton 	}
13319702Slinton 
133217742Sralph zappost(p) NODE *p; {
133317742Sralph 	/* look for ++ and -- operators and remove them */
133417742Sralph 
133517742Sralph 	register o, ty;
133617742Sralph 	register NODE *q;
133717742Sralph 	o = p->in.op;
133817742Sralph 	ty = optype( o );
133917742Sralph 
134017742Sralph 	switch( o ){
134117742Sralph 
134217742Sralph 	case INCR:
134317742Sralph 	case DECR:
134417742Sralph 			q = p->in.left;
134517742Sralph 			p->in.right->in.op = FREE;  /* zap constant */
134617742Sralph 			ncopy( p, q );
134717742Sralph 			q->in.op = FREE;
134817742Sralph 			return;
134917742Sralph 
135017742Sralph 		}
135117742Sralph 
135217742Sralph 	if( ty == BITYPE ) zappost( p->in.right );
135317742Sralph 	if( ty != LTYPE ) zappost( p->in.left );
135417742Sralph }
135517742Sralph 
135617742Sralph fixpre(p) NODE *p; {
135717742Sralph 
135817742Sralph 	register o, ty;
135917742Sralph 	o = p->in.op;
136017742Sralph 	ty = optype( o );
136117742Sralph 
136217742Sralph 	switch( o ){
136317742Sralph 
136417742Sralph 	case ASG PLUS:
136517742Sralph 			p->in.op = PLUS;
136617742Sralph 			break;
136717742Sralph 	case ASG MINUS:
136817742Sralph 			p->in.op = MINUS;
136917742Sralph 			break;
137017742Sralph 		}
137117742Sralph 
137217742Sralph 	if( ty == BITYPE ) fixpre( p->in.right );
137317742Sralph 	if( ty != LTYPE ) fixpre( p->in.left );
137417742Sralph }
137517742Sralph 
137624418Smckusick strip(p) register NODE *p; {
137724418Smckusick 	NODE *q;
137824418Smckusick 
137924418Smckusick 	/* strip nodes off the top when no side effects occur */
138024418Smckusick 	for( ; ; ) {
138124418Smckusick 		switch( p->in.op ) {
138224418Smckusick 		case SCONV:			/* remove lint tidbits */
138324418Smckusick 			q = p->in.left;
138424418Smckusick 			ncopy( p, q );
138524418Smckusick 			q->in.op = FREE;
138624418Smckusick 			break;
138724418Smckusick 		/* could probably add a few more here */
138824418Smckusick 		default:
138924418Smckusick 			return;
139024418Smckusick 			}
139124418Smckusick 		}
139224418Smckusick 	}
139324418Smckusick 
13949702Slinton myreader(p) register NODE *p; {
139524418Smckusick 	strip( p );		/* strip off operations with no side effects */
139617742Sralph 	canon( p );		/* expands r-vals for fields */
13979702Slinton 	walkf( p, hardops );	/* convert ops to function calls */
13989702Slinton 	walkf( p, optim2 );
13999702Slinton 	/* jwf toff = 0;  /* stack offset swindle */
14009702Slinton 	}
1401