xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 24418)
117742Sralph # ifndef lint
2*24418Smckusick static char *sccsid ="@(#)local2.c	1.12 (Berkeley) 08/23/85";
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 
12*24418Smckusick # define putstr(s)	fputs((s), stdout)
13*24418Smckusick 
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 ){
82*24418Smckusick 			putstr( q->opstring );
839702Slinton /* tbl
84*24418Smckusick 			if( f == 'F' ) putchar( 'e' );
85*24418Smckusick 			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':
94*24418Smckusick 					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:
158*24418Smckusick 			putchar('d');
1599702Slinton 			return;
1609702Slinton 
1619702Slinton 		case FLOAT:
162*24418Smckusick 			putchar('f');
1639702Slinton 			return;
1649702Slinton 
1659702Slinton 		case LONG:
1669702Slinton 		case ULONG:
1679702Slinton 		case INT:
1689702Slinton 		case UNSIGNED:
169*24418Smckusick 			putchar('l');
1709702Slinton 			return;
1719702Slinton 
1729702Slinton 		case SHORT:
1739702Slinton 		case USHORT:
174*24418Smckusick 			putchar('w');
1759702Slinton 			return;
1769702Slinton 
1779702Slinton 		case CHAR:
1789702Slinton 		case UCHAR:
179*24418Smckusick 			putchar('b');
1809702Slinton 			return;
1819702Slinton 
1829702Slinton 		default:
1839702Slinton 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
1849702Slinton 			else {
185*24418Smckusick 				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) {
237*24418Smckusick 					putstr("clr");
2389702Slinton 					prtype(l);
239*24418Smckusick 					putchar('\t');
2409702Slinton 					adrput(l);
2419702Slinton 					return;
2429702Slinton 					}
24317208Sralph 				if (r->tn.lval < 0 && r->tn.lval >= -63) {
244*24418Smckusick 					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 {
268*24418Smckusick 				putstr("moval");
269*24418Smckusick 				putchar('\t');
27016181Sralph 				acon(r);
271*24418Smckusick 				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))
295*24418Smckusick 					putstr("movz");
2969702Slinton 				else
297*24418Smckusick 					putstr("cvt");
29823536Sbloom 				prtype(r);
29923536Sbloom 				prtype(x);
300*24418Smckusick 				putchar('\t');
30123536Sbloom 				adrput(r);
302*24418Smckusick 				putchar(',');
30323536Sbloom 				adrput(x);
304*24418Smckusick 				putchar('\n');
305*24418Smckusick 				putchar('\t');
30623536Sbloom 				r = x;
3079702Slinton 				}
30823536Sbloom 			l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
3099702Slinton 			}
31023536Sbloom 
31117208Sralph 		if (!mixtypes(l,r)) {
31217208Sralph 			if (tlen(l) == tlen(r)) {
313*24418Smckusick 				putstr("mov");
31417742Sralph #ifdef FORT
31517742Sralph 				if (Oflag)
31617742Sralph 					prtype(l);
31717742Sralph 				else {
31817742Sralph 					if (l->in.type == DOUBLE)
319*24418Smckusick 						putchar('q');
32017742Sralph 					else if(l->in.type == FLOAT)
321*24418Smckusick 						putchar('l');
32217742Sralph 					else
32317742Sralph 						prtype(l);
32417742Sralph 					}
32517742Sralph #else
3269702Slinton 				prtype(l);
32717742Sralph #endif FORT
3289702Slinton 				goto ops;
3299702Slinton 				}
3309702Slinton 			else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
331*24418Smckusick 				putstr("movz");
3329702Slinton 			else
333*24418Smckusick 				putstr("cvt");
3349702Slinton 			}
3359702Slinton 		else
336*24418Smckusick 			putstr("cvt");
3379702Slinton 		prtype(r);
3389702Slinton 		prtype(l);
3399702Slinton 	ops:
340*24418Smckusick 		putchar('\t');
3419702Slinton 		adrput(r);
342*24418Smckusick 		putchar(',');
3439702Slinton 		adrput(l);
3449702Slinton 		return;
3459702Slinton 		}
3469702Slinton 
3479702Slinton 	case 'B':	/* get oreg value in temp register for left shift */
3489702Slinton 		{
3499702Slinton 		register NODE *r;
3509702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
3519702Slinton 		r = p->in.right;
3529702Slinton 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
353*24418Smckusick 			putstr("movl");
3549702Slinton 		else {
355*24418Smckusick 			putstr("cvt");
3569702Slinton 			prtype(r);
357*24418Smckusick 			putchar('l');
3589702Slinton 			}
3599702Slinton 		return;
3609702Slinton 		}
3619702Slinton 
3629702Slinton 	case 'C':	/* num words pushed on arg stack */
3639702Slinton 		{
3649702Slinton 		extern int gc_numbytes;
3659702Slinton 		extern int xdebug;
3669702Slinton 
3679702Slinton 		if (xdebug) printf("->%d<-",gc_numbytes);
3689702Slinton 
3699702Slinton 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
3709702Slinton 		return;
3719702Slinton 		}
3729702Slinton 
3739702Slinton 	case 'D':	/* INCR and DECR */
3749702Slinton 		zzzcode(p->in.left, 'A');
375*24418Smckusick 		putchar('\n');
376*24418Smckusick 		putchar('\t');
3779702Slinton 
3789702Slinton 	case 'E':	/* INCR and DECR, FOREFF */
3799702Slinton 		if (p->in.right->tn.lval == 1)
3809702Slinton 			{
381*24418Smckusick 			putstr( p->in.op == INCR ? "inc" : "dec" );
3829702Slinton 			prtype(p->in.left);
383*24418Smckusick 			putchar('\t');
3849702Slinton 			adrput(p->in.left);
3859702Slinton 			return;
3869702Slinton 			}
387*24418Smckusick 		putstr( p->in.op == INCR ? "add" : "sub" );
3889702Slinton 		prtype(p->in.left);
389*24418Smckusick 		putchar('2');
390*24418Smckusick 		putchar('\t');
3919702Slinton 		adrput(p->in.right);
392*24418Smckusick 		putchar(',');
3939702Slinton 		adrput(p->in.left);
3949702Slinton 		return;
3959702Slinton 
3969702Slinton 	case 'F':	/* register type of right operand */
3979702Slinton 		{
3989702Slinton 		register NODE *n;
3999702Slinton 		extern int xdebug;
4009702Slinton 		register int ty;
4019702Slinton 
4029702Slinton 		n = getlr( p, 'R' );
4039702Slinton 		ty = n->in.type;
4049702Slinton 
4059702Slinton 		if (xdebug) printf("->%d<-", ty);
4069702Slinton 
407*24418Smckusick 		if ( ty==DOUBLE) putchar('d');
408*24418Smckusick 		else if ( ty==FLOAT ) putchar('f');
409*24418Smckusick 		else putchar('l');
4109702Slinton 		return;
4119702Slinton 		}
4129702Slinton 
4139702Slinton 	case 'L':	/* type of left operand */
4149702Slinton 	case 'R':	/* type of right operand */
4159702Slinton 		{
4169702Slinton 		register NODE *n;
4179702Slinton 		extern int xdebug;
4189702Slinton 
41916181Sralph 		n = getlr( p, c );
4209702Slinton 		if (xdebug) printf("->%d<-", n->in.type);
4219702Slinton 
4229702Slinton 		prtype(n);
4239702Slinton 		return;
4249702Slinton 		}
4259702Slinton 
4269702Slinton 	case 'Z':	/* complement mask for bit instr */
4279702Slinton 		printf("$%ld", ~p->in.right->tn.lval);
4289702Slinton 		return;
4299702Slinton 
4309702Slinton 	case 'U':	/* 32 - n, for unsigned right shifts */
4319702Slinton 		printf("$%d", 32 - p->in.right->tn.lval );
4329702Slinton 		return;
4339702Slinton 
4349702Slinton 	case 'T':	/* rounded structure length for arguments */
4359702Slinton 		{
4369702Slinton 		int size;
4379702Slinton 
4389702Slinton 		size = p->stn.stsize;
4399702Slinton 		SETOFF( size, 4);
4409702Slinton 		printf("$%d", size);
4419702Slinton 		return;
4429702Slinton 		}
4439702Slinton 
4449702Slinton 	case 'S':  /* structure assignment */
4459702Slinton 		{
4469702Slinton 			register NODE *l, *r;
4479702Slinton 			register size;
4489702Slinton 
4499702Slinton 			if( p->in.op == STASG ){
4509702Slinton 				l = p->in.left;
4519702Slinton 				r = p->in.right;
4529702Slinton 
4539702Slinton 				}
4549702Slinton 			else if( p->in.op == STARG ){  /* store an arg into a temporary */
4559702Slinton 				r = p->in.left;
4569702Slinton 				}
4579702Slinton 			else cerror( "STASG bad" );
4589702Slinton 
4599702Slinton 			if( r->in.op == ICON ) r->in.op = NAME;
4609702Slinton 			else if( r->in.op == REG ) r->in.op = OREG;
4619702Slinton 			else if( r->in.op != OREG ) cerror( "STASG-r" );
4629702Slinton 
4639702Slinton 			size = p->stn.stsize;
4649702Slinton 
4659702Slinton 			if( size <= 0 || size > 65535 )
4669702Slinton 				cerror("structure size <0=0 or >65535");
4679702Slinton 
4689702Slinton 			switch(size) {
4699702Slinton 				case 1:
470*24418Smckusick 					putstr("	movb	");
4719702Slinton 					break;
4729702Slinton 				case 2:
473*24418Smckusick 					putstr("	movw	");
4749702Slinton 					break;
4759702Slinton 				case 4:
476*24418Smckusick 					putstr("	movl	");
4779702Slinton 					break;
4789702Slinton 				case 8:
479*24418Smckusick 					putstr("	movq	");
4809702Slinton 					break;
4819702Slinton 				default:
4829702Slinton 					printf("	movc3	$%d,", size);
4839702Slinton 					break;
4849702Slinton 			}
4859702Slinton 			adrput(r);
48616418Sralph 			if( p->in.op == STASG ){
487*24418Smckusick 				putchar(',');
48816418Sralph 				adrput(l);
489*24418Smckusick 				putchar('\n');
49016418Sralph 				}
49116418Sralph 			else
492*24418Smckusick 				putstr(",(sp)\n");
4939702Slinton 
4949702Slinton 			if( r->in.op == NAME ) r->in.op = ICON;
4959702Slinton 			else if( r->in.op == OREG ) r->in.op = REG;
4969702Slinton 
4979702Slinton 			}
4989702Slinton 		break;
4999702Slinton 
5009702Slinton 	default:
5019702Slinton 		cerror( "illegal zzzcode" );
5029702Slinton 		}
5039702Slinton 	}
5049702Slinton 
50523536Sbloom /*
50623536Sbloom  * collapsible(dest, src) -- if a conversion with a register destination
50723536Sbloom  *	can be accomplished in one instruction, return the type of src
50823536Sbloom  *	that will do the job correctly; otherwise return 0.  Note that
50923536Sbloom  *	a register must always end up having type INT or UNSIGNED.
51023536Sbloom  */
51123536Sbloom int
51223536Sbloom collapsible(dest, src)
51323536Sbloom NODE *dest, *src;
51423536Sbloom {
51523536Sbloom 	int st = src->in.type;
51623536Sbloom 	int dt = dest->in.type;
51723536Sbloom 	int newt = 0;
51823536Sbloom 
51923536Sbloom 	/*
52023536Sbloom 	 * Are there side effects of evaluating src?
52123536Sbloom 	 * If the derived type will not be the same size as src,
522*24418Smckusick 	 * we may have to use two steps.
52323536Sbloom 	 */
524*24418Smckusick 	if (tlen(src) > tlen(dest)) {
525*24418Smckusick 		if (tshape(src, STARREG))
526*24418Smckusick 			return (0);
527*24418Smckusick 		if (src->in.op == OREG && R2TEST(src->tn.rval))
528*24418Smckusick 			return (0);
529*24418Smckusick 		}
53023536Sbloom 
53123536Sbloom 	/*
53223536Sbloom 	 * Can we get an object of dest's type by punning src?
53323536Sbloom 	 * Praises be to great Cthulhu for little-endian machines...
53423536Sbloom 	 */
53523536Sbloom 	if (st == CHAR && dt == USHORT)
53623536Sbloom 		/*
53723536Sbloom 		 * Special case -- we must sign-extend to 16 bits.
53823536Sbloom 		 */
53923536Sbloom 		return (0);
54023536Sbloom 
54123536Sbloom 	if (tlen(src) < tlen(dest))
54223536Sbloom 		newt = st;
54323536Sbloom 	else
54423536Sbloom 		newt = dt;
54523536Sbloom 
54623536Sbloom 	return (newt);
54723536Sbloom 	}
54823536Sbloom 
54917742Sralph rmove( rt, rs, t ) TWORD t; {
5509702Slinton 	printf( "	%s	%s,%s\n",
55117742Sralph #ifdef FORT
55217742Sralph 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
55317742Sralph #endif
5549702Slinton 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
5559702Slinton 		rnames[rs], rnames[rt] );
5569702Slinton 	}
5579702Slinton 
5589702Slinton struct respref
5599702Slinton respref[] = {
5609702Slinton 	INTAREG|INTBREG,	INTAREG|INTBREG,
5619702Slinton 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
5629702Slinton 	INTEMP,	INTEMP,
5639702Slinton 	FORARG,	FORARG,
5649702Slinton 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
5659702Slinton 	0,	0 };
5669702Slinton 
5679702Slinton setregs(){ /* set up temporary registers */
5689702Slinton 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
5699702Slinton 	;
5709702Slinton 	}
5719702Slinton 
5729702Slinton rewfld( p ) NODE *p; {
5739702Slinton 	return(1);
5749702Slinton 	}
5759702Slinton 
5769702Slinton callreg(p) NODE *p; {
5779702Slinton 	return( R0 );
5789702Slinton 	}
5799702Slinton 
5809702Slinton base( p ) register NODE *p; {
5819702Slinton 	register int o = p->in.op;
5829702Slinton 
5839702Slinton 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
5849702Slinton 	if( o==REG ) return( p->tn.rval );
5859702Slinton     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
5869702Slinton 		return( p->in.left->tn.rval );
5879702Slinton     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
5889702Slinton 		return( p->tn.rval + 0200*1 );
5899702Slinton 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
5909702Slinton 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
5919702Slinton 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
5929702Slinton 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
5939702Slinton 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
5949702Slinton 	return( -1 );
5959702Slinton 	}
5969702Slinton 
5979702Slinton offset( p, tyl ) register NODE *p; int tyl; {
5989702Slinton 
599*24418Smckusick 	if( tyl==1 &&
600*24418Smckusick 	    p->in.op==REG &&
601*24418Smckusick 	    (p->in.type==INT || p->in.type==UNSIGNED) )
602*24418Smckusick 		return( p->tn.rval );
603*24418Smckusick 	if( p->in.op==LS &&
604*24418Smckusick 	    p->in.left->in.op==REG &&
605*24418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
606*24418Smckusick 	    p->in.right->in.op==ICON &&
607*24418Smckusick 	    p->in.right->in.name[0]=='\0' &&
608*24418Smckusick 	    (1<<p->in.right->tn.lval)==tyl)
6099702Slinton 		return( p->in.left->tn.rval );
610*24418Smckusick 	if( tyl==2 &&
611*24418Smckusick 	    p->in.op==PLUS &&
612*24418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
613*24418Smckusick 	    p->in.left->in.op==REG &&
614*24418Smckusick 	    p->in.right->in.op==REG &&
615*24418Smckusick 	    p->in.left->tn.rval==p->in.right->tn.rval )
616*24418Smckusick 		return( p->in.left->tn.rval );
6179702Slinton 	return( -1 );
6189702Slinton 	}
6199702Slinton 
6209702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
6219702Slinton 	register NODE *t;
6229702Slinton 	register int i;
6239702Slinton 	NODE *f;
6249702Slinton 
6259702Slinton 	p->in.op = OREG;
6269702Slinton 	f = p->in.left; 	/* have to free this subtree later */
6279702Slinton 
6289702Slinton 	/* init base */
6299702Slinton 	switch (q->in.op) {
6309702Slinton 		case ICON:
6319702Slinton 		case REG:
6329702Slinton 		case OREG:
6339702Slinton 			t = q;
6349702Slinton 			break;
6359702Slinton 
6369702Slinton 		case MINUS:
6379702Slinton 			q->in.right->tn.lval = -q->in.right->tn.lval;
6389702Slinton 		case PLUS:
6399702Slinton 			t = q->in.right;
6409702Slinton 			break;
6419702Slinton 
6429702Slinton 		case INCR:
6439702Slinton 		case ASG MINUS:
6449702Slinton 			t = q->in.left;
6459702Slinton 			break;
6469702Slinton 
6479702Slinton 		case UNARY MUL:
6489702Slinton 			t = q->in.left->in.left;
6499702Slinton 			break;
6509702Slinton 
6519702Slinton 		default:
6529702Slinton 			cerror("illegal makeor2");
6539702Slinton 	}
6549702Slinton 
6559702Slinton 	p->tn.lval = t->tn.lval;
6569702Slinton #ifndef FLEXNAMES
6579702Slinton 	for(i=0; i<NCHNAM; ++i)
6589702Slinton 		p->in.name[i] = t->in.name[i];
6599702Slinton #else
6609702Slinton 	p->in.name = t->in.name;
6619702Slinton #endif
6629702Slinton 
6639702Slinton 	/* init offset */
6649702Slinton 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
6659702Slinton 
6669702Slinton 	tfree(f);
6679702Slinton 	return;
6689702Slinton 	}
6699702Slinton 
6709702Slinton canaddr( p ) NODE *p; {
6719702Slinton 	register int o = p->in.op;
6729702Slinton 
6739702Slinton 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
6749702Slinton 	return(0);
6759702Slinton 	}
6769702Slinton 
6779702Slinton flshape( p ) register NODE *p; {
6789702Slinton 	return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
6799702Slinton 		(p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
6809702Slinton 	}
6819702Slinton 
6829702Slinton shtemp( p ) register NODE *p; {
6839702Slinton 	if( p->in.op == STARG ) p = p->in.left;
6849702Slinton 	return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
6859702Slinton 	}
6869702Slinton 
6879702Slinton shumul( p ) register NODE *p; {
6889702Slinton 	register o;
6899702Slinton 	extern int xdebug;
6909702Slinton 
6919702Slinton 	if (xdebug) {
6929702Slinton 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
6939702Slinton 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
6949702Slinton 		}
6959702Slinton 
6969702Slinton 
6979702Slinton 	o = p->in.op;
6989702Slinton 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
6999702Slinton 
7009702Slinton 	if( ( o == INCR || o == ASG MINUS ) &&
7019702Slinton 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
7029702Slinton 	    p->in.right->in.name[0] == '\0' )
7039702Slinton 		{
70417659Sralph 		switch (p->in.type)
7059702Slinton 			{
7069702Slinton 			case CHAR|PTR:
7079702Slinton 			case UCHAR|PTR:
7089702Slinton 				o = 1;
7099702Slinton 				break;
7109702Slinton 
7119702Slinton 			case SHORT|PTR:
7129702Slinton 			case USHORT|PTR:
7139702Slinton 				o = 2;
7149702Slinton 				break;
7159702Slinton 
7169702Slinton 			case INT|PTR:
7179702Slinton 			case UNSIGNED|PTR:
7189702Slinton 			case LONG|PTR:
7199702Slinton 			case ULONG|PTR:
7209702Slinton 			case FLOAT|PTR:
7219702Slinton 				o = 4;
7229702Slinton 				break;
7239702Slinton 
7249702Slinton 			case DOUBLE|PTR:
7259702Slinton 				o = 8;
7269702Slinton 				break;
7279702Slinton 
7289702Slinton 			default:
72917742Sralph 				if ( ISPTR(p->in.type) &&
73017742Sralph 				     ISPTR(DECREF(p->in.type)) ) {
7319702Slinton 					o = 4;
7329702Slinton 					break;
7339702Slinton 					}
7349702Slinton 				else return(0);
7359702Slinton 			}
7369702Slinton 		return( p->in.right->tn.lval == o ? STARREG : 0);
7379702Slinton 		}
7389702Slinton 
7399702Slinton 	return( 0 );
7409702Slinton 	}
7419702Slinton 
7429702Slinton adrcon( val ) CONSZ val; {
743*24418Smckusick 	putchar( '$' );
7449702Slinton 	printf( CONFMT, val );
7459702Slinton 	}
7469702Slinton 
7479702Slinton conput( p ) register NODE *p; {
7489702Slinton 	switch( p->in.op ){
7499702Slinton 
7509702Slinton 	case ICON:
7519702Slinton 		acon( p );
7529702Slinton 		return;
7539702Slinton 
7549702Slinton 	case REG:
755*24418Smckusick 		putstr( rnames[p->tn.rval] );
7569702Slinton 		return;
7579702Slinton 
7589702Slinton 	default:
7599702Slinton 		cerror( "illegal conput" );
7609702Slinton 		}
7619702Slinton 	}
7629702Slinton 
7639702Slinton insput( p ) register NODE *p; {
7649702Slinton 	cerror( "insput" );
7659702Slinton 	}
7669702Slinton 
7679702Slinton upput( p ) register NODE *p; {
7689702Slinton 	cerror( "upput" );
7699702Slinton 	}
7709702Slinton 
7719702Slinton adrput( p ) register NODE *p; {
7729702Slinton 	register int r;
7739702Slinton 	/* output an address, with offsets, from p */
7749702Slinton 
7759702Slinton 	if( p->in.op == FLD ){
7769702Slinton 		p = p->in.left;
7779702Slinton 		}
7789702Slinton 	switch( p->in.op ){
7799702Slinton 
7809702Slinton 	case NAME:
7819702Slinton 		acon( p );
7829702Slinton 		return;
7839702Slinton 
7849702Slinton 	case ICON:
7859702Slinton 		/* addressable value of the constant */
786*24418Smckusick 		putchar( '$' );
7879702Slinton 		acon( p );
7889702Slinton 		return;
7899702Slinton 
7909702Slinton 	case REG:
791*24418Smckusick 		putstr( rnames[p->tn.rval] );
7929702Slinton 		return;
7939702Slinton 
7949702Slinton 	case OREG:
7959702Slinton 		r = p->tn.rval;
7969702Slinton 		if( R2TEST(r) ){ /* double indexing */
7979702Slinton 			register int flags;
7989702Slinton 
7999702Slinton 			flags = R2UPK3(r);
800*24418Smckusick 			if( flags & 1 ) putchar('*');
801*24418Smckusick 			if( flags & 4 ) putchar('-');
8029702Slinton 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
8039702Slinton 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
804*24418Smckusick 			if( flags & 2 ) putchar('+');
8059702Slinton 			printf( "[%s]", rnames[R2UPK2(r)] );
8069702Slinton 			return;
8079702Slinton 			}
8089702Slinton 		if( r == AP ){  /* in the argument region */
8099702Slinton 			if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" );
8109702Slinton 			printf( CONFMT, p->tn.lval );
811*24418Smckusick 			putstr( "(ap)" );
8129702Slinton 			return;
8139702Slinton 			}
8149702Slinton 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
8159702Slinton 		printf( "(%s)", rnames[p->tn.rval] );
8169702Slinton 		return;
8179702Slinton 
8189702Slinton 	case UNARY MUL:
8199702Slinton 		/* STARNM or STARREG found */
8209702Slinton 		if( tshape(p, STARNM) ) {
821*24418Smckusick 			putchar( '*' );
8229702Slinton 			adrput( p->in.left);
8239702Slinton 			}
8249702Slinton 		else {	/* STARREG - really auto inc or dec */
8259702Slinton 			register NODE *q;
8269702Slinton 
8279702Slinton /* tbl
8289702Slinton 			p = p->in.left;
8299702Slinton 			p->in.left->in.op = OREG;
8309702Slinton 			if( p->in.op == INCR ) {
8319702Slinton 				adrput( p->in.left );
832*24418Smckusick 				putchar( '+' );
8339702Slinton 				}
8349702Slinton 			else {
835*24418Smckusick 				putchar( '-' );
8369702Slinton 				adrput( p->in.left );
8379702Slinton 				}
8389702Slinton    tbl */
83917659Sralph 			q = p->in.left;
84017742Sralph 			if( q->in.right->tn.lval != tlen(p) )
84117742Sralph 				cerror("adrput: bad auto-increment/decrement");
84217659Sralph 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
84317659Sralph 				rnames[q->in.left->tn.rval],
84417659Sralph 				(q->in.op==INCR ? "+" : "") );
8459702Slinton 			p->in.op = OREG;
84617659Sralph 			p->tn.rval = q->in.left->tn.rval;
84717659Sralph 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
8489702Slinton #ifndef FLEXNAMES
8499702Slinton 			p->in.name[0] = '\0';
8509702Slinton #else
8519702Slinton 			p->in.name = "";
8529702Slinton #endif
8539702Slinton 			tfree(q);
8549702Slinton 		}
8559702Slinton 		return;
8569702Slinton 
8579702Slinton 	default:
8589702Slinton 		cerror( "illegal address" );
8599702Slinton 		return;
8609702Slinton 
8619702Slinton 		}
8629702Slinton 
8639702Slinton 	}
8649702Slinton 
8659702Slinton acon( p ) register NODE *p; { /* print out a constant */
8669702Slinton 
8679702Slinton 	if( p->in.name[0] == '\0' ){
8689702Slinton 		printf( CONFMT, p->tn.lval);
8699702Slinton 		}
8709702Slinton 	else if( p->tn.lval == 0 ) {
8719702Slinton #ifndef FLEXNAMES
8729702Slinton 		printf( "%.8s", p->in.name );
8739702Slinton #else
874*24418Smckusick 		putstr( p->in.name );
8759702Slinton #endif
8769702Slinton 		}
8779702Slinton 	else {
8789702Slinton #ifndef FLEXNAMES
8799702Slinton 		printf( "%.8s+", p->in.name );
8809702Slinton #else
8819702Slinton 		printf( "%s+", p->in.name );
8829702Slinton #endif
8839702Slinton 		printf( CONFMT, p->tn.lval );
8849702Slinton 		}
8859702Slinton 	}
8869702Slinton 
8879702Slinton /*
8889702Slinton aacon( p ) register NODE *p; { /* print out a constant */
8899702Slinton /*
8909702Slinton 
8919702Slinton 	if( p->in.name[0] == '\0' ){
8929702Slinton 		printf( CONFMT, p->tn.lval);
8939702Slinton 		return( 0 );
8949702Slinton 		}
8959702Slinton 	else if( p->tn.lval == 0 ) {
8969702Slinton #ifndef FLEXNAMES
8979702Slinton 		printf( "$%.8s", p->in.name );
8989702Slinton #else
8999702Slinton 		printf( "$%s", p->in.name );
9009702Slinton #endif
9019702Slinton 		return( 1 );
9029702Slinton 		}
9039702Slinton 	else {
9049702Slinton 		printf( "$(" );
9059702Slinton 		printf( CONFMT, p->tn.lval );
9069702Slinton 		printf( "+" );
9079702Slinton #ifndef FLEXNAMES
9089702Slinton 		printf( "%.8s)", p->in.name );
9099702Slinton #else
9109702Slinton 		printf( "%s)", p->in.name );
9119702Slinton #endif
9129702Slinton 		return(1);
9139702Slinton 		}
9149702Slinton 	}
9159702Slinton  */
9169702Slinton 
9179702Slinton genscall( p, cookie ) register NODE *p; {
9189702Slinton 	/* structure valued call */
9199702Slinton 	return( gencall( p, cookie ) );
9209702Slinton 	}
9219702Slinton 
9229702Slinton /* tbl */
9239702Slinton int gc_numbytes;
9249702Slinton /* tbl */
9259702Slinton 
9269702Slinton gencall( p, cookie ) register NODE *p; {
9279702Slinton 	/* generate the call given by p */
92816418Sralph 	register NODE *p1;
9299702Slinton 	register temp, temp1;
9309702Slinton 	register m;
9319702Slinton 
9329702Slinton 	if( p->in.right ) temp = argsize( p->in.right );
9339702Slinton 	else temp = 0;
9349702Slinton 
9359702Slinton 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
9369702Slinton 		/* set aside room for structure return */
9379702Slinton 
9389702Slinton 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
9399702Slinton 		else temp1 = temp;
9409702Slinton 		}
9419702Slinton 
9429702Slinton 	if( temp > maxargs ) maxargs = temp;
9439702Slinton 	SETOFF(temp1,4);
9449702Slinton 
9459702Slinton 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
94616418Sralph 		genargs( p->in.right );
9479702Slinton 		}
9489702Slinton 
9499702Slinton 	p1 = p->in.left;
9509702Slinton 	if( p1->in.op != ICON ){
9519702Slinton 		if( p1->in.op != REG ){
9529702Slinton 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
9539702Slinton 				if( p1->in.op != NAME ){
9549702Slinton 					order( p1, INAREG );
9559702Slinton 					}
9569702Slinton 				}
9579702Slinton 			}
9589702Slinton 		}
9599702Slinton 
9609702Slinton /*
9619702Slinton 	if( p1->in.op == REG && p->tn.rval == R5 ){
9629702Slinton 		cerror( "call register overwrite" );
9639702Slinton 		}
9649702Slinton  */
9659702Slinton /* tbl
9669702Slinton 	setup gc_numbytes so reference to ZC works */
9679702Slinton 
9689702Slinton 	gc_numbytes = temp&(0x3ff);
9699702Slinton /* tbl */
9709702Slinton 
9719702Slinton 	p->in.op = UNARY CALL;
9729702Slinton 	m = match( p, INTAREG|INTBREG );
9739702Slinton 
9749702Slinton 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
9759702Slinton 	/* (plus in assignment to gc_numbytes above, for neatness only) */
9769702Slinton 	if (temp >= 1024)
9779702Slinton 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
9789702Slinton 
9799702Slinton /* tbl
9809702Slinton 	switch( temp ) {
9819702Slinton 	case 0:
9829702Slinton 		break;
9839702Slinton 	case 2:
9849702Slinton 		printf( "	tst	(sp)+\n" );
9859702Slinton 		break;
9869702Slinton 	case 4:
9879702Slinton 		printf( "	cmp	(sp)+,(sp)+\n" );
9889702Slinton 		break;
9899702Slinton 	default:
9909702Slinton 		printf( "	add	$%d,sp\n", temp);
9919702Slinton 		}
9929702Slinton    tbl */
9939702Slinton 	return(m != MDONE);
9949702Slinton 	}
9959702Slinton 
9969702Slinton /* tbl */
9979702Slinton char *
9989702Slinton ccbranches[] = {
9999702Slinton 	"	jeql	L%d\n",
10009702Slinton 	"	jneq	L%d\n",
10019702Slinton 	"	jleq	L%d\n",
10029702Slinton 	"	jlss	L%d\n",
10039702Slinton 	"	jgeq	L%d\n",
10049702Slinton 	"	jgtr	L%d\n",
10059702Slinton 	"	jlequ	L%d\n",
10069702Slinton 	"	jlssu	L%d\n",
10079702Slinton 	"	jgequ	L%d\n",
10089702Slinton 	"	jgtru	L%d\n",
10099702Slinton 	};
10109702Slinton /* tbl */
10119702Slinton 
10129702Slinton cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
10139702Slinton 
10149702Slinton /* tbl */
10159702Slinton 	if( o == 0 ) printf( "	jbr	L%d\n", lab );
10169702Slinton /* tbl */
10179702Slinton 	else {
10189702Slinton 		if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
10199702Slinton 		printf( ccbranches[o-EQ], lab );
10209702Slinton 		}
10219702Slinton 	}
10229702Slinton 
10239702Slinton nextcook( p, cookie ) NODE *p; {
10249702Slinton 	/* we have failed to match p with cookie; try another */
10259702Slinton 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
10269702Slinton 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
10279702Slinton 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
10289702Slinton 	return( FORREW );
10299702Slinton 	}
10309702Slinton 
10319702Slinton lastchance( p, cook ) NODE *p; {
10329702Slinton 	/* forget it! */
10339702Slinton 	return(0);
10349702Slinton 	}
10359702Slinton 
10369702Slinton optim2( p ) register NODE *p; {
10379702Slinton 	/* do local tree transformations and optimizations */
10389702Slinton 
103916181Sralph 	register NODE *l, *r;
104016181Sralph 	int m, ml;
10419702Slinton 
10429702Slinton 	switch( p->in.op ) {
10439702Slinton 
10449702Slinton 	case AND:
104519933Smckusick 		/* commute L and R to eliminate complements and constants */
104616181Sralph 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
104716181Sralph 		    l->in.op == COMPL ) {
10489702Slinton 			p->in.left = p->in.right;
104916181Sralph 			p->in.right = l;
10509702Slinton 			}
10519702Slinton 	case ASG AND:
10529702Slinton 		/* change meaning of AND to ~R&L - bic on pdp11 */
10539702Slinton 		r = p->in.right;
105419933Smckusick 		if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */
10559702Slinton 			r->tn.lval = ~r->tn.lval;
10569702Slinton 			}
10579702Slinton 		else if( r->in.op==COMPL ) { /* ~~A => A */
10589702Slinton 			r->in.op = FREE;
10599702Slinton 			p->in.right = r->in.left;
10609702Slinton 			}
10619702Slinton 		else { /* insert complement node */
106216181Sralph 			p->in.right = l = talloc();
106316181Sralph 			l->in.op = COMPL;
106416181Sralph 			l->in.rall = NOPREF;
106516181Sralph 			l->in.type = r->in.type;
106616181Sralph 			l->in.left = r;
106716181Sralph 			l->in.right = NULL;
10689702Slinton 			}
10699702Slinton 		break;
10709702Slinton 
107116181Sralph 	case SCONV:
107219933Smckusick 		l = p->in.left;
107317742Sralph #if defined(FORT) || defined(SPRECC)
107416573Sralph 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
107519933Smckusick 		    l->in.type == FLOAT || l->in.type == DOUBLE )
107619933Smckusick 			return;
107716573Sralph #else
107819933Smckusick 		if( mixtypes(p, l) ) return;
107916573Sralph #endif
108019933Smckusick 		/* Only trust it to get it right if the size is the same */
108119933Smckusick 		if( tlen(p) != tlen(l) )
108219933Smckusick 			return;
108316181Sralph 
108416181Sralph 		/* clobber conversion */
108519933Smckusick 		if( l->in.op != FLD )
108616181Sralph 			l->in.type = p->in.type;
108716181Sralph 		ncopy( p, l );
108816181Sralph 		l->in.op = FREE;
108919933Smckusick 
109016181Sralph 		break;
109116181Sralph 
1092*24418Smckusick 	case ASSIGN:
1093*24418Smckusick 		/*
1094*24418Smckusick 		 * Conversions are equivalent to assignments;
1095*24418Smckusick 		 * when the two operations are combined,
1096*24418Smckusick 		 * we can sometimes zap the conversion.
1097*24418Smckusick 		 */
1098*24418Smckusick 		r = p->in.right;
1099*24418Smckusick 		l = p->in.left;
1100*24418Smckusick 		if ( r->in.op == SCONV &&
1101*24418Smckusick 		     !mixtypes(l, r) &&
1102*24418Smckusick 		     tlen(l) == tlen(r) ) {
1103*24418Smckusick 				p->in.right = r->in.left;
1104*24418Smckusick 				r->in.op = FREE;
1105*24418Smckusick 			}
1106*24418Smckusick 		break;
1107*24418Smckusick 
11089702Slinton 		}
11099702Slinton 	}
11109702Slinton 
111117742Sralph NODE * addroreg(l) NODE *l;
11129702Slinton 				/* OREG was built in clocal()
11139702Slinton 				 * for an auto or formal parameter
11149702Slinton 				 * now its address is being taken
11159702Slinton 				 * local code must unwind it
11169702Slinton 				 * back to PLUS/MINUS REG ICON
11179702Slinton 				 * according to local conventions
11189702Slinton 				 */
11199702Slinton {
11209702Slinton 	cerror("address of OREG taken");
112117742Sralph 	/*NOTREACHED*/
11229702Slinton }
11239702Slinton 
11249702Slinton 
11259702Slinton 
11269702Slinton # ifndef ONEPASS
11279702Slinton main( argc, argv ) char *argv[]; {
11289702Slinton 	return( mainp2( argc, argv ) );
11299702Slinton 	}
11309702Slinton # endif
11319702Slinton 
11329702Slinton 
11339702Slinton /* added by jwf */
11349702Slinton struct functbl {
11359702Slinton 	int fop;
11369702Slinton 	TWORD ftype;
11379702Slinton 	char *func;
11389702Slinton 	} opfunc[] = {
11399702Slinton 	DIV,		TANY,	"udiv",
11409702Slinton 	MOD,		TANY,	"urem",
114117715Sralph 	ASG DIV,	TANY,	"audiv",
114217715Sralph 	ASG MOD,	TANY,	"aurem",
11439702Slinton 	0,	0,	0 };
11449702Slinton 
11459702Slinton hardops(p)  register NODE *p; {
11469702Slinton 	/* change hard to do operators into function calls.  */
11479702Slinton 	register NODE *q;
11489702Slinton 	register struct functbl *f;
11499702Slinton 	register o;
115017742Sralph 	NODE *old,*temp;
11519702Slinton 
11529702Slinton 	o = p->in.op;
115317742Sralph 	if( ! (optype(o)==BITYPE &&
115417742Sralph 	       (ISUNSIGNED(p->in.left->in.type) ||
115517742Sralph 		ISUNSIGNED(p->in.right->in.type))) )
115617742Sralph 		return;
11579702Slinton 
11589702Slinton 	for( f=opfunc; f->fop; f++ ) {
11599702Slinton 		if( o==f->fop ) goto convert;
11609702Slinton 		}
11619702Slinton 	return;
11629702Slinton 
11639702Slinton 	convert:
11649702Slinton 	if( asgop( o ) ) {
116517742Sralph 		old = NIL;
116617715Sralph 		switch( p->in.left->in.op ){
116717742Sralph 		case FLD:
116817742Sralph 			q = p->in.left->in.left;
116917742Sralph 			/*
117017742Sralph 			 * rewrite (lval.fld /= rval); as
117117742Sralph 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
117217742Sralph 			 * else the compiler will evaluate lval twice.
117317742Sralph 			 */
117417742Sralph 			if( q->in.op == UNARY MUL ){
117517742Sralph 				/* first allocate a temp storage */
117617742Sralph 				temp = talloc();
117717742Sralph 				temp->in.op = OREG;
117817742Sralph 				temp->tn.rval = TMPREG;
117917742Sralph 				temp->tn.lval = BITOOR(freetemp(1));
118017742Sralph 				temp->in.type = INCREF(p->in.type);
118117742Sralph #ifdef FLEXNAMES
118217742Sralph 				temp->in.name = "";
118317742Sralph #else
118417742Sralph 				temp->in.name[0] = '\0';
118517742Sralph #endif
118617742Sralph 				old = q->in.left;
118717742Sralph 				q->in.left = temp;
118817742Sralph 			}
118917742Sralph 			/* fall thru ... */
119017742Sralph 
119117715Sralph 		case REG:
119217715Sralph 		case NAME:
119317715Sralph 		case OREG:
119417715Sralph 			/* change ASG OP to a simple OP */
119517715Sralph 			q = talloc();
119617715Sralph 			q->in.op = NOASG p->in.op;
119717715Sralph 			q->in.rall = NOPREF;
119817715Sralph 			q->in.type = p->in.type;
119917715Sralph 			q->in.left = tcopy(p->in.left);
120017715Sralph 			q->in.right = p->in.right;
120117715Sralph 			p->in.op = ASSIGN;
120217715Sralph 			p->in.right = q;
120317715Sralph 			p = q;
120417715Sralph 			f -= 2; /* Note: this depends on the table order */
120517742Sralph 			/* on the right side only - replace *temp with
120617742Sralph 			 *(temp = &lval), build the assignment node */
120717742Sralph 			if( old ){
120817742Sralph 				temp = q->in.left->in.left; /* the "*" node */
120917742Sralph 				q = talloc();
121017742Sralph 				q->in.op = ASSIGN;
121117742Sralph 				q->in.left = temp->in.left;
121217742Sralph 				q->in.right = old;
121317742Sralph 				q->in.type = old->in.type;
121417742Sralph #ifdef FLEXNAMES
121517742Sralph 				q->in.name = "";
121617742Sralph #else
121717742Sralph 				q->in.name[0] = '\0';
121817742Sralph #endif
121917742Sralph 				temp->in.left = q;
122017742Sralph 			}
122117715Sralph 			break;
12229702Slinton 
122317715Sralph 		case UNARY MUL:
122417715Sralph 			/* avoid doing side effects twice */
122517715Sralph 			q = p->in.left;
122617715Sralph 			p->in.left = q->in.left;
122717715Sralph 			q->in.op = FREE;
122817715Sralph 			break;
122917715Sralph 
123017715Sralph 		default:
123117715Sralph 			cerror( "hardops: can't compute & LHS" );
123217715Sralph 			}
123317742Sralph 		}
123417715Sralph 
12359702Slinton 	/* build comma op for args to function */
12369702Slinton 	q = talloc();
12379702Slinton 	q->in.op = CM;
12389702Slinton 	q->in.rall = NOPREF;
12399702Slinton 	q->in.type = INT;
12409702Slinton 	q->in.left = p->in.left;
12419702Slinton 	q->in.right = p->in.right;
12429702Slinton 	p->in.op = CALL;
12439702Slinton 	p->in.right = q;
12449702Slinton 
12459702Slinton 	/* put function name in left node of call */
12469702Slinton 	p->in.left = q = talloc();
12479702Slinton 	q->in.op = ICON;
12489702Slinton 	q->in.rall = NOPREF;
12499702Slinton 	q->in.type = INCREF( FTN + p->in.type );
12509702Slinton #ifndef FLEXNAMES
12519702Slinton 	strcpy( q->in.name, f->func );
12529702Slinton #else
12539702Slinton 	q->in.name = f->func;
12549702Slinton #endif
12559702Slinton 	q->tn.lval = 0;
12569702Slinton 	q->tn.rval = 0;
12579702Slinton 
12589702Slinton 	}
12599702Slinton 
126017742Sralph zappost(p) NODE *p; {
126117742Sralph 	/* look for ++ and -- operators and remove them */
126217742Sralph 
126317742Sralph 	register o, ty;
126417742Sralph 	register NODE *q;
126517742Sralph 	o = p->in.op;
126617742Sralph 	ty = optype( o );
126717742Sralph 
126817742Sralph 	switch( o ){
126917742Sralph 
127017742Sralph 	case INCR:
127117742Sralph 	case DECR:
127217742Sralph 			q = p->in.left;
127317742Sralph 			p->in.right->in.op = FREE;  /* zap constant */
127417742Sralph 			ncopy( p, q );
127517742Sralph 			q->in.op = FREE;
127617742Sralph 			return;
127717742Sralph 
127817742Sralph 		}
127917742Sralph 
128017742Sralph 	if( ty == BITYPE ) zappost( p->in.right );
128117742Sralph 	if( ty != LTYPE ) zappost( p->in.left );
128217742Sralph }
128317742Sralph 
128417742Sralph fixpre(p) NODE *p; {
128517742Sralph 
128617742Sralph 	register o, ty;
128717742Sralph 	o = p->in.op;
128817742Sralph 	ty = optype( o );
128917742Sralph 
129017742Sralph 	switch( o ){
129117742Sralph 
129217742Sralph 	case ASG PLUS:
129317742Sralph 			p->in.op = PLUS;
129417742Sralph 			break;
129517742Sralph 	case ASG MINUS:
129617742Sralph 			p->in.op = MINUS;
129717742Sralph 			break;
129817742Sralph 		}
129917742Sralph 
130017742Sralph 	if( ty == BITYPE ) fixpre( p->in.right );
130117742Sralph 	if( ty != LTYPE ) fixpre( p->in.left );
130217742Sralph }
130317742Sralph 
1304*24418Smckusick strip(p) register NODE *p; {
1305*24418Smckusick 	NODE *q;
1306*24418Smckusick 
1307*24418Smckusick 	/* strip nodes off the top when no side effects occur */
1308*24418Smckusick 	for( ; ; ) {
1309*24418Smckusick 		switch( p->in.op ) {
1310*24418Smckusick 		case SCONV:			/* remove lint tidbits */
1311*24418Smckusick 			q = p->in.left;
1312*24418Smckusick 			ncopy( p, q );
1313*24418Smckusick 			q->in.op = FREE;
1314*24418Smckusick 			break;
1315*24418Smckusick 		/* could probably add a few more here */
1316*24418Smckusick 		default:
1317*24418Smckusick 			return;
1318*24418Smckusick 			}
1319*24418Smckusick 		}
1320*24418Smckusick 	}
1321*24418Smckusick 
13229702Slinton myreader(p) register NODE *p; {
1323*24418Smckusick 	strip( p );		/* strip off operations with no side effects */
132417742Sralph 	canon( p );		/* expands r-vals for fields */
13259702Slinton 	walkf( p, hardops );	/* convert ops to function calls */
13269702Slinton 	walkf( p, optim2 );
13279702Slinton 	/* jwf toff = 0;  /* stack offset swindle */
13289702Slinton 	}
1329