xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 23536)
117742Sralph # ifndef lint
2*23536Sbloom static char *sccsid ="@(#)local2.c	1.11 (Berkeley) 06/18/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 
129702Slinton # define BITMASK(n) ((1L<<n)-1)
139702Slinton 
149702Slinton where(c){
159702Slinton 	fprintf( stderr, "%s, line %d: ", filename, lineno );
169702Slinton 	}
179702Slinton 
189702Slinton lineid( l, fn ) char *fn; {
199702Slinton 	/* identify line l and file fn */
209702Slinton 	printf( "#	line %d, file %s\n", l, fn );
219702Slinton 	}
229702Slinton 
239702Slinton 
249702Slinton eobl2(){
259702Slinton 	OFFSZ spoff;	/* offset from stack pointer */
269702Slinton #ifdef FORT
279702Slinton 	spoff = maxoff;
289702Slinton 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
299702Slinton 	spoff /= SZCHAR;
309702Slinton 	SETOFF(spoff,4);
319702Slinton #ifndef FLEXNAMES
329702Slinton 	printf( "	.set	.F%d,%ld\n", ftnno, spoff );
339702Slinton #else
349702Slinton 	/* SHOULD BE L%d ... ftnno but must change pc/f77 */
359702Slinton 	printf( "	.set	LF%d,%ld\n", ftnno, spoff );
369702Slinton #endif
379702Slinton #else
389702Slinton 	extern int ftlab1, ftlab2;
399702Slinton 
409702Slinton 	spoff = maxoff;
419702Slinton 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
429702Slinton 	spoff /= SZCHAR;
439702Slinton 	SETOFF(spoff,4);
449702Slinton 	printf( "L%d:\n", ftlab1);
459702Slinton 	if( spoff!=0 )
469702Slinton 		if( spoff < 64 )
479702Slinton 			printf( "	subl2	$%ld,sp\n", spoff);
489702Slinton 		else
499702Slinton 			printf( "	movab	-%ld(sp),sp\n", spoff);
509702Slinton 	printf( "	jbr 	L%d\n", ftlab2);
519702Slinton #endif
529702Slinton 	maxargs = -1;
539702Slinton 	}
549702Slinton 
559702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = {
569702Slinton 
579702Slinton 	ASG PLUS, "add",
589702Slinton 	ASG MINUS, "sub",
599702Slinton 	ASG MUL, "mul",
609702Slinton 	ASG DIV, "div",
619702Slinton 	ASG OR, "bis",
629702Slinton 	ASG ER,	"xor",
639702Slinton 	ASG AND, "bic",
649702Slinton 	PLUS,	"add",
659702Slinton 	MINUS,	"sub",
669702Slinton 	MUL,	"mul",
679702Slinton 	DIV,	"div",
689702Slinton 	OR,	"bis",
699702Slinton 	ER,	"xor",
709702Slinton 	AND,	"bic",
719702Slinton 	-1, ""    };
729702Slinton 
739702Slinton hopcode( f, o ){
749702Slinton 	/* output the appropriate string from the above table */
759702Slinton 
769702Slinton 	register struct hoptab *q;
779702Slinton 
789702Slinton 	for( q = ioptab;  q->opmask>=0; ++q ){
799702Slinton 		if( q->opmask == o ){
809702Slinton 			printf( "%s", q->opstring );
819702Slinton /* tbl
829702Slinton 			if( f == 'F' ) printf( "e" );
839702Slinton 			else if( f == 'D' ) printf( "d" );
849702Slinton    tbl */
859702Slinton /* tbl */
869702Slinton 			switch( f ) {
879702Slinton 				case 'L':
889702Slinton 				case 'W':
899702Slinton 				case 'B':
909702Slinton 				case 'D':
919702Slinton 				case 'F':
929702Slinton 					printf("%c", tolower(f));
939702Slinton 					break;
949702Slinton 
959702Slinton 				}
969702Slinton /* tbl */
979702Slinton 			return;
989702Slinton 			}
999702Slinton 		}
1009702Slinton 	cerror( "no hoptab for %s", opst[o] );
1019702Slinton 	}
1029702Slinton 
1039702Slinton char *
1049702Slinton rnames[] = {  /* keyed to register number tokens */
1059702Slinton 
1069702Slinton 	"r0", "r1",
1079702Slinton 	"r2", "r3", "r4", "r5",
1089702Slinton 	"r6", "r7", "r8", "r9", "r10", "r11",
1099702Slinton 	"ap", "fp", "sp", "pc",
1109702Slinton 
1119702Slinton 	};
1129702Slinton 
1139702Slinton int rstatus[] = {
1149702Slinton 	SAREG|STAREG, SAREG|STAREG,
1159702Slinton 	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
1169702Slinton 	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
1179702Slinton 	SAREG, SAREG, SAREG, SAREG,
1189702Slinton 
1199702Slinton 	};
1209702Slinton 
1219702Slinton tlen(p) NODE *p;
1229702Slinton {
1239702Slinton 	switch(p->in.type) {
1249702Slinton 		case CHAR:
1259702Slinton 		case UCHAR:
1269702Slinton 			return(1);
1279702Slinton 
1289702Slinton 		case SHORT:
1299702Slinton 		case USHORT:
1309702Slinton 			return(2);
1319702Slinton 
1329702Slinton 		case DOUBLE:
1339702Slinton 			return(8);
1349702Slinton 
1359702Slinton 		default:
1369702Slinton 			return(4);
1379702Slinton 		}
1389702Slinton }
1399702Slinton 
1409702Slinton mixtypes(p, q) NODE *p, *q;
1419702Slinton {
14216181Sralph 	register TWORD tp, tq;
1439702Slinton 
1449702Slinton 	tp = p->in.type;
1459702Slinton 	tq = q->in.type;
1469702Slinton 
1479702Slinton 	return( (tp==FLOAT || tp==DOUBLE) !=
1489702Slinton 		(tq==FLOAT || tq==DOUBLE) );
1499702Slinton }
1509702Slinton 
1519702Slinton prtype(n) NODE *n;
1529702Slinton {
1539702Slinton 	switch (n->in.type)
1549702Slinton 		{
1559702Slinton 		case DOUBLE:
1569702Slinton 			printf("d");
1579702Slinton 			return;
1589702Slinton 
1599702Slinton 		case FLOAT:
1609702Slinton 			printf("f");
1619702Slinton 			return;
1629702Slinton 
1639702Slinton 		case LONG:
1649702Slinton 		case ULONG:
1659702Slinton 		case INT:
1669702Slinton 		case UNSIGNED:
1679702Slinton 			printf("l");
1689702Slinton 			return;
1699702Slinton 
1709702Slinton 		case SHORT:
1719702Slinton 		case USHORT:
1729702Slinton 			printf("w");
1739702Slinton 			return;
1749702Slinton 
1759702Slinton 		case CHAR:
1769702Slinton 		case UCHAR:
1779702Slinton 			printf("b");
1789702Slinton 			return;
1799702Slinton 
1809702Slinton 		default:
1819702Slinton 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
1829702Slinton 			else {
1839702Slinton 				printf("l");
1849702Slinton 				return;
1859702Slinton 				}
1869702Slinton 		}
1879702Slinton }
1889702Slinton 
1899702Slinton zzzcode( p, c ) register NODE *p; {
1909702Slinton 	register m;
1919702Slinton 	CONSZ val;
1929702Slinton 	switch( c ){
1939702Slinton 
1949702Slinton 	case 'N':  /* logical ops, turned into 0-1 */
1959702Slinton 		/* use register given by register 1 */
1969702Slinton 		cbgen( 0, m=getlab(), 'I' );
1979702Slinton 		deflab( p->bn.label );
1989702Slinton 		printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );
1999702Slinton 		deflab( m );
2009702Slinton 		return;
2019702Slinton 
2029702Slinton 	case 'I':
2039702Slinton 	case 'P':
2049702Slinton 		cbgen( p->in.op, p->bn.label, c );
2059702Slinton 		return;
2069702Slinton 
2079702Slinton 	case 'A':
2089702Slinton 		{
2099702Slinton 		register NODE *l, *r;
2109702Slinton 
2119702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
2129702Slinton 		r = getlr(p, 'R');
21316181Sralph 		if (p->in.op == ASSIGN)
21416181Sralph 			l = getlr(p, 'L');
21517208Sralph 		else if (p->in.op == SCONV) {
2169702Slinton 			l = resc;
21717742Sralph #if defined(FORT) || defined(SPRECC)
21816181Sralph 			l->in.type = r->in.type;
21916181Sralph #else
22016181Sralph 			l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type;
22116181Sralph #endif
22216181Sralph 			r = getlr(p, 'L');
22316181Sralph 			}
22417208Sralph 		else {		/* OPLTYPE */
22516181Sralph 			l = resc;
22617742Sralph #if defined(FORT) || defined(SPRECC)
22716181Sralph 			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
22816181Sralph #else
2299702Slinton 			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
23016181Sralph #endif
2319702Slinton 			}
2329702Slinton 		if (r->in.op == ICON)
23317208Sralph 			if (r->in.name[0] == '\0') {
23417208Sralph 				if (r->tn.lval == 0) {
2359702Slinton 					printf("clr");
2369702Slinton 					prtype(l);
2379702Slinton 					printf("	");
2389702Slinton 					adrput(l);
2399702Slinton 					return;
2409702Slinton 					}
24117208Sralph 				if (r->tn.lval < 0 && r->tn.lval >= -63) {
2429702Slinton 					printf("mneg");
2439702Slinton 					prtype(l);
2449702Slinton 					r->tn.lval = -r->tn.lval;
2459702Slinton 					goto ops;
2469702Slinton 					}
24717208Sralph 				if (r->tn.lval < 0)
24817208Sralph 					r->in.type = r->tn.lval >= -128 ? CHAR
2499702Slinton 						: (r->tn.lval >= -32768 ? SHORT
25017208Sralph 						: INT);
25117208Sralph 				else if (l->in.type == FLOAT ||
25217208Sralph 				    l->in.type == DOUBLE)
25317208Sralph 					r->in.type = r->tn.lval <= 63 ? INT
25417208Sralph 						: (r->tn.lval <= 127 ? CHAR
25517208Sralph 						: (r->tn.lval <= 32767 ? SHORT
25617208Sralph 						: INT));
25717208Sralph 				else
25817208Sralph 					r->in.type = r->tn.lval <= 63 ? INT
25917208Sralph 						: (r->tn.lval <= 127 ? CHAR
2609702Slinton 						: (r->tn.lval <= 255 ? UCHAR
2619702Slinton 						: (r->tn.lval <= 32767 ? SHORT
2629702Slinton 						: (r->tn.lval <= 65535 ? USHORT
26317208Sralph 						: INT))));
2649702Slinton 				}
26517208Sralph 			else {
26616181Sralph 				printf("moval");
26716181Sralph 				printf("	");
26816181Sralph 				acon(r);
26916181Sralph 				printf(",");
27016181Sralph 				adrput(l);
27116181Sralph 				return;
27216181Sralph 				}
2739702Slinton 
274*23536Sbloom 		if (p->in.op == SCONV &&
275*23536Sbloom 		    !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
276*23536Sbloom 		    !mixtypes(l, r)) {
277*23536Sbloom 			/*
278*23536Sbloom 			 * Because registers must always contain objects
279*23536Sbloom 			 * of the same width as INTs, we may have to
280*23536Sbloom 			 * perform two conversions to get an INT.  Can
281*23536Sbloom 			 * the conversions be collapsed into one?
282*23536Sbloom 			 */
283*23536Sbloom 			if (m = collapsible(l, r))
284*23536Sbloom 				r->in.type = m;
285*23536Sbloom 			else {
286*23536Sbloom 				/*
287*23536Sbloom 				 * Two steps are required.
288*23536Sbloom 				 */
289*23536Sbloom 				NODE *x = &resc[1];
290*23536Sbloom 
291*23536Sbloom 				*x = *l;
292*23536Sbloom 				if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
29316181Sralph 					printf("movz");
2949702Slinton 				else
2959702Slinton 					printf("cvt");
296*23536Sbloom 				prtype(r);
297*23536Sbloom 				prtype(x);
298*23536Sbloom 				printf("\t");
299*23536Sbloom 				adrput(r);
300*23536Sbloom 				printf(",");
301*23536Sbloom 				adrput(x);
302*23536Sbloom 				printf("\n\t");
303*23536Sbloom 				r = x;
3049702Slinton 				}
305*23536Sbloom 			l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
3069702Slinton 			}
307*23536Sbloom 
30817208Sralph 		if (!mixtypes(l,r)) {
30917208Sralph 			if (tlen(l) == tlen(r)) {
3109702Slinton 				printf("mov");
31117742Sralph #ifdef FORT
31217742Sralph 				if (Oflag)
31317742Sralph 					prtype(l);
31417742Sralph 				else {
31517742Sralph 					if (l->in.type == DOUBLE)
31617742Sralph 						printf("q");
31717742Sralph 					else if(l->in.type == FLOAT)
31817742Sralph 						printf("l");
31917742Sralph 					else
32017742Sralph 						prtype(l);
32117742Sralph 					}
32217742Sralph #else
3239702Slinton 				prtype(l);
32417742Sralph #endif FORT
3259702Slinton 				goto ops;
3269702Slinton 				}
3279702Slinton 			else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
3289702Slinton 				printf("movz");
3299702Slinton 			else
3309702Slinton 				printf("cvt");
3319702Slinton 			}
3329702Slinton 		else
3339702Slinton 			printf("cvt");
3349702Slinton 		prtype(r);
3359702Slinton 		prtype(l);
3369702Slinton 	ops:
3379702Slinton 		printf("	");
3389702Slinton 		adrput(r);
3399702Slinton 		printf(",");
3409702Slinton 		adrput(l);
3419702Slinton 		return;
3429702Slinton 		}
3439702Slinton 
3449702Slinton 	case 'B':	/* get oreg value in temp register for left shift */
3459702Slinton 		{
3469702Slinton 		register NODE *r;
3479702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
3489702Slinton 		r = p->in.right;
3499702Slinton 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
3509702Slinton 			printf("movl");
3519702Slinton 		else {
3529702Slinton 			printf("cvt");
3539702Slinton 			prtype(r);
3549702Slinton 			printf("l");
3559702Slinton 			}
3569702Slinton 		return;
3579702Slinton 		}
3589702Slinton 
3599702Slinton 	case 'C':	/* num words pushed on arg stack */
3609702Slinton 		{
3619702Slinton 		extern int gc_numbytes;
3629702Slinton 		extern int xdebug;
3639702Slinton 
3649702Slinton 		if (xdebug) printf("->%d<-",gc_numbytes);
3659702Slinton 
3669702Slinton 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
3679702Slinton 		return;
3689702Slinton 		}
3699702Slinton 
3709702Slinton 	case 'D':	/* INCR and DECR */
3719702Slinton 		zzzcode(p->in.left, 'A');
3729702Slinton 		printf("\n	");
3739702Slinton 
3749702Slinton 	case 'E':	/* INCR and DECR, FOREFF */
3759702Slinton 		if (p->in.right->tn.lval == 1)
3769702Slinton 			{
3779702Slinton 			printf("%s", (p->in.op == INCR ? "inc" : "dec") );
3789702Slinton 			prtype(p->in.left);
3799702Slinton 			printf("	");
3809702Slinton 			adrput(p->in.left);
3819702Slinton 			return;
3829702Slinton 			}
3839702Slinton 		printf("%s", (p->in.op == INCR ? "add" : "sub") );
3849702Slinton 		prtype(p->in.left);
3859702Slinton 		printf("2	");
3869702Slinton 		adrput(p->in.right);
3879702Slinton 		printf(",");
3889702Slinton 		adrput(p->in.left);
3899702Slinton 		return;
3909702Slinton 
3919702Slinton 	case 'F':	/* register type of right operand */
3929702Slinton 		{
3939702Slinton 		register NODE *n;
3949702Slinton 		extern int xdebug;
3959702Slinton 		register int ty;
3969702Slinton 
3979702Slinton 		n = getlr( p, 'R' );
3989702Slinton 		ty = n->in.type;
3999702Slinton 
4009702Slinton 		if (xdebug) printf("->%d<-", ty);
4019702Slinton 
4029702Slinton 		if ( ty==DOUBLE) printf("d");
4039702Slinton 		else if ( ty==FLOAT ) printf("f");
4049702Slinton 		else printf("l");
4059702Slinton 		return;
4069702Slinton 		}
4079702Slinton 
4089702Slinton 	case 'L':	/* type of left operand */
4099702Slinton 	case 'R':	/* type of right operand */
4109702Slinton 		{
4119702Slinton 		register NODE *n;
4129702Slinton 		extern int xdebug;
4139702Slinton 
41416181Sralph 		n = getlr( p, c );
4159702Slinton 		if (xdebug) printf("->%d<-", n->in.type);
4169702Slinton 
4179702Slinton 		prtype(n);
4189702Slinton 		return;
4199702Slinton 		}
4209702Slinton 
4219702Slinton 	case 'Z':	/* complement mask for bit instr */
4229702Slinton 		printf("$%ld", ~p->in.right->tn.lval);
4239702Slinton 		return;
4249702Slinton 
4259702Slinton 	case 'U':	/* 32 - n, for unsigned right shifts */
4269702Slinton 		printf("$%d", 32 - p->in.right->tn.lval );
4279702Slinton 		return;
4289702Slinton 
4299702Slinton 	case 'T':	/* rounded structure length for arguments */
4309702Slinton 		{
4319702Slinton 		int size;
4329702Slinton 
4339702Slinton 		size = p->stn.stsize;
4349702Slinton 		SETOFF( size, 4);
4359702Slinton 		printf("$%d", size);
4369702Slinton 		return;
4379702Slinton 		}
4389702Slinton 
4399702Slinton 	case 'S':  /* structure assignment */
4409702Slinton 		{
4419702Slinton 			register NODE *l, *r;
4429702Slinton 			register size;
4439702Slinton 
4449702Slinton 			if( p->in.op == STASG ){
4459702Slinton 				l = p->in.left;
4469702Slinton 				r = p->in.right;
4479702Slinton 
4489702Slinton 				}
4499702Slinton 			else if( p->in.op == STARG ){  /* store an arg into a temporary */
4509702Slinton 				r = p->in.left;
4519702Slinton 				}
4529702Slinton 			else cerror( "STASG bad" );
4539702Slinton 
4549702Slinton 			if( r->in.op == ICON ) r->in.op = NAME;
4559702Slinton 			else if( r->in.op == REG ) r->in.op = OREG;
4569702Slinton 			else if( r->in.op != OREG ) cerror( "STASG-r" );
4579702Slinton 
4589702Slinton 			size = p->stn.stsize;
4599702Slinton 
4609702Slinton 			if( size <= 0 || size > 65535 )
4619702Slinton 				cerror("structure size <0=0 or >65535");
4629702Slinton 
4639702Slinton 			switch(size) {
4649702Slinton 				case 1:
4659702Slinton 					printf("	movb	");
4669702Slinton 					break;
4679702Slinton 				case 2:
4689702Slinton 					printf("	movw	");
4699702Slinton 					break;
4709702Slinton 				case 4:
4719702Slinton 					printf("	movl	");
4729702Slinton 					break;
4739702Slinton 				case 8:
4749702Slinton 					printf("	movq	");
4759702Slinton 					break;
4769702Slinton 				default:
4779702Slinton 					printf("	movc3	$%d,", size);
4789702Slinton 					break;
4799702Slinton 			}
4809702Slinton 			adrput(r);
48116418Sralph 			if( p->in.op == STASG ){
48216418Sralph 				printf(",");
48316418Sralph 				adrput(l);
48416418Sralph 				printf("\n");
48516418Sralph 				}
48616418Sralph 			else
48716418Sralph 				printf(",(sp)\n");
4889702Slinton 
4899702Slinton 			if( r->in.op == NAME ) r->in.op = ICON;
4909702Slinton 			else if( r->in.op == OREG ) r->in.op = REG;
4919702Slinton 
4929702Slinton 			}
4939702Slinton 		break;
4949702Slinton 
4959702Slinton 	default:
4969702Slinton 		cerror( "illegal zzzcode" );
4979702Slinton 		}
4989702Slinton 	}
4999702Slinton 
500*23536Sbloom /*
501*23536Sbloom  * collapsible(dest, src) -- if a conversion with a register destination
502*23536Sbloom  *	can be accomplished in one instruction, return the type of src
503*23536Sbloom  *	that will do the job correctly; otherwise return 0.  Note that
504*23536Sbloom  *	a register must always end up having type INT or UNSIGNED.
505*23536Sbloom  */
506*23536Sbloom int
507*23536Sbloom collapsible(dest, src)
508*23536Sbloom NODE *dest, *src;
509*23536Sbloom {
510*23536Sbloom 	int st = src->in.type;
511*23536Sbloom 	int dt = dest->in.type;
512*23536Sbloom 	int newt = 0;
513*23536Sbloom 
514*23536Sbloom 	/*
515*23536Sbloom 	 * Are there side effects of evaluating src?
516*23536Sbloom 	 * If the derived type will not be the same size as src,
517*23536Sbloom 	 * we have to use two steps.
518*23536Sbloom 	 */
519*23536Sbloom 	if (tlen(src) > tlen(dest) && tshape(src, STARREG))
520*23536Sbloom 		return (0);
521*23536Sbloom 
522*23536Sbloom 	/*
523*23536Sbloom 	 * Can we get an object of dest's type by punning src?
524*23536Sbloom 	 * Praises be to great Cthulhu for little-endian machines...
525*23536Sbloom 	 */
526*23536Sbloom 	if (st == CHAR && dt == USHORT)
527*23536Sbloom 		/*
528*23536Sbloom 		 * Special case -- we must sign-extend to 16 bits.
529*23536Sbloom 		 */
530*23536Sbloom 		return (0);
531*23536Sbloom 
532*23536Sbloom 	if (tlen(src) < tlen(dest))
533*23536Sbloom 		newt = st;
534*23536Sbloom 	else
535*23536Sbloom 		newt = dt;
536*23536Sbloom 
537*23536Sbloom 	return (newt);
538*23536Sbloom 	}
539*23536Sbloom 
54017742Sralph rmove( rt, rs, t ) TWORD t; {
5419702Slinton 	printf( "	%s	%s,%s\n",
54217742Sralph #ifdef FORT
54317742Sralph 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
54417742Sralph #endif
5459702Slinton 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
5469702Slinton 		rnames[rs], rnames[rt] );
5479702Slinton 	}
5489702Slinton 
5499702Slinton struct respref
5509702Slinton respref[] = {
5519702Slinton 	INTAREG|INTBREG,	INTAREG|INTBREG,
5529702Slinton 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
5539702Slinton 	INTEMP,	INTEMP,
5549702Slinton 	FORARG,	FORARG,
5559702Slinton 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
5569702Slinton 	0,	0 };
5579702Slinton 
5589702Slinton setregs(){ /* set up temporary registers */
5599702Slinton 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
5609702Slinton 	;
5619702Slinton 	}
5629702Slinton 
56317742Sralph szty(t) TWORD t; { /* size, in registers, needed to hold thing of type t */
56417742Sralph #if defined(FORT) || defined(SPRECC)
56516181Sralph 	return( (t==DOUBLE) ? 2 : 1 );
56616181Sralph #else
5679702Slinton 	return( (t==DOUBLE||t==FLOAT) ? 2 : 1 );
56816181Sralph #endif
5699702Slinton 	}
5709702Slinton 
5719702Slinton rewfld( p ) NODE *p; {
5729702Slinton 	return(1);
5739702Slinton 	}
5749702Slinton 
5759702Slinton callreg(p) NODE *p; {
5769702Slinton 	return( R0 );
5779702Slinton 	}
5789702Slinton 
5799702Slinton base( p ) register NODE *p; {
5809702Slinton 	register int o = p->in.op;
5819702Slinton 
5829702Slinton 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
5839702Slinton 	if( o==REG ) return( p->tn.rval );
5849702Slinton     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
5859702Slinton 		return( p->in.left->tn.rval );
5869702Slinton     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
5879702Slinton 		return( p->tn.rval + 0200*1 );
5889702Slinton 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
5899702Slinton 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
5909702Slinton 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
5919702Slinton 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
5929702Slinton 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
5939702Slinton 	return( -1 );
5949702Slinton 	}
5959702Slinton 
5969702Slinton offset( p, tyl ) register NODE *p; int tyl; {
5979702Slinton 
5989702Slinton 	if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
5999702Slinton 	if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
6009702Slinton 	      (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
6019702Slinton 	      && (1<<p->in.right->tn.lval)==tyl))
6029702Slinton 		return( p->in.left->tn.rval );
6039702Slinton 	return( -1 );
6049702Slinton 	}
6059702Slinton 
6069702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
6079702Slinton 	register NODE *t;
6089702Slinton 	register int i;
6099702Slinton 	NODE *f;
6109702Slinton 
6119702Slinton 	p->in.op = OREG;
6129702Slinton 	f = p->in.left; 	/* have to free this subtree later */
6139702Slinton 
6149702Slinton 	/* init base */
6159702Slinton 	switch (q->in.op) {
6169702Slinton 		case ICON:
6179702Slinton 		case REG:
6189702Slinton 		case OREG:
6199702Slinton 			t = q;
6209702Slinton 			break;
6219702Slinton 
6229702Slinton 		case MINUS:
6239702Slinton 			q->in.right->tn.lval = -q->in.right->tn.lval;
6249702Slinton 		case PLUS:
6259702Slinton 			t = q->in.right;
6269702Slinton 			break;
6279702Slinton 
6289702Slinton 		case INCR:
6299702Slinton 		case ASG MINUS:
6309702Slinton 			t = q->in.left;
6319702Slinton 			break;
6329702Slinton 
6339702Slinton 		case UNARY MUL:
6349702Slinton 			t = q->in.left->in.left;
6359702Slinton 			break;
6369702Slinton 
6379702Slinton 		default:
6389702Slinton 			cerror("illegal makeor2");
6399702Slinton 	}
6409702Slinton 
6419702Slinton 	p->tn.lval = t->tn.lval;
6429702Slinton #ifndef FLEXNAMES
6439702Slinton 	for(i=0; i<NCHNAM; ++i)
6449702Slinton 		p->in.name[i] = t->in.name[i];
6459702Slinton #else
6469702Slinton 	p->in.name = t->in.name;
6479702Slinton #endif
6489702Slinton 
6499702Slinton 	/* init offset */
6509702Slinton 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
6519702Slinton 
6529702Slinton 	tfree(f);
6539702Slinton 	return;
6549702Slinton 	}
6559702Slinton 
6569702Slinton canaddr( p ) NODE *p; {
6579702Slinton 	register int o = p->in.op;
6589702Slinton 
6599702Slinton 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
6609702Slinton 	return(0);
6619702Slinton 	}
6629702Slinton 
6639702Slinton shltype( o, p ) register NODE *p; {
6649702Slinton 	return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
6659702Slinton 	}
6669702Slinton 
6679702Slinton flshape( p ) register NODE *p; {
6689702Slinton 	return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
6699702Slinton 		(p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
6709702Slinton 	}
6719702Slinton 
6729702Slinton shtemp( p ) register NODE *p; {
6739702Slinton 	if( p->in.op == STARG ) p = p->in.left;
6749702Slinton 	return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
6759702Slinton 	}
6769702Slinton 
6779702Slinton shumul( p ) register NODE *p; {
6789702Slinton 	register o;
6799702Slinton 	extern int xdebug;
6809702Slinton 
6819702Slinton 	if (xdebug) {
6829702Slinton 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
6839702Slinton 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
6849702Slinton 		}
6859702Slinton 
6869702Slinton 
6879702Slinton 	o = p->in.op;
6889702Slinton 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
6899702Slinton 
6909702Slinton 	if( ( o == INCR || o == ASG MINUS ) &&
6919702Slinton 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
6929702Slinton 	    p->in.right->in.name[0] == '\0' )
6939702Slinton 		{
69417659Sralph 		switch (p->in.type)
6959702Slinton 			{
6969702Slinton 			case CHAR|PTR:
6979702Slinton 			case UCHAR|PTR:
6989702Slinton 				o = 1;
6999702Slinton 				break;
7009702Slinton 
7019702Slinton 			case SHORT|PTR:
7029702Slinton 			case USHORT|PTR:
7039702Slinton 				o = 2;
7049702Slinton 				break;
7059702Slinton 
7069702Slinton 			case INT|PTR:
7079702Slinton 			case UNSIGNED|PTR:
7089702Slinton 			case LONG|PTR:
7099702Slinton 			case ULONG|PTR:
7109702Slinton 			case FLOAT|PTR:
7119702Slinton 				o = 4;
7129702Slinton 				break;
7139702Slinton 
7149702Slinton 			case DOUBLE|PTR:
7159702Slinton 				o = 8;
7169702Slinton 				break;
7179702Slinton 
7189702Slinton 			default:
71917742Sralph 				if ( ISPTR(p->in.type) &&
72017742Sralph 				     ISPTR(DECREF(p->in.type)) ) {
7219702Slinton 					o = 4;
7229702Slinton 					break;
7239702Slinton 					}
7249702Slinton 				else return(0);
7259702Slinton 			}
7269702Slinton 		return( p->in.right->tn.lval == o ? STARREG : 0);
7279702Slinton 		}
7289702Slinton 
7299702Slinton 	return( 0 );
7309702Slinton 	}
7319702Slinton 
7329702Slinton adrcon( val ) CONSZ val; {
7339702Slinton 	printf( "$" );
7349702Slinton 	printf( CONFMT, val );
7359702Slinton 	}
7369702Slinton 
7379702Slinton conput( p ) register NODE *p; {
7389702Slinton 	switch( p->in.op ){
7399702Slinton 
7409702Slinton 	case ICON:
7419702Slinton 		acon( p );
7429702Slinton 		return;
7439702Slinton 
7449702Slinton 	case REG:
7459702Slinton 		printf( "%s", rnames[p->tn.rval] );
7469702Slinton 		return;
7479702Slinton 
7489702Slinton 	default:
7499702Slinton 		cerror( "illegal conput" );
7509702Slinton 		}
7519702Slinton 	}
7529702Slinton 
7539702Slinton insput( p ) register NODE *p; {
7549702Slinton 	cerror( "insput" );
7559702Slinton 	}
7569702Slinton 
7579702Slinton upput( p ) register NODE *p; {
7589702Slinton 	cerror( "upput" );
7599702Slinton 	}
7609702Slinton 
7619702Slinton adrput( p ) register NODE *p; {
7629702Slinton 	register int r;
7639702Slinton 	/* output an address, with offsets, from p */
7649702Slinton 
7659702Slinton 	if( p->in.op == FLD ){
7669702Slinton 		p = p->in.left;
7679702Slinton 		}
7689702Slinton 	switch( p->in.op ){
7699702Slinton 
7709702Slinton 	case NAME:
7719702Slinton 		acon( p );
7729702Slinton 		return;
7739702Slinton 
7749702Slinton 	case ICON:
7759702Slinton 		/* addressable value of the constant */
7769702Slinton 		printf( "$" );
7779702Slinton 		acon( p );
7789702Slinton 		return;
7799702Slinton 
7809702Slinton 	case REG:
7819702Slinton 		printf( "%s", rnames[p->tn.rval] );
7829702Slinton 		return;
7839702Slinton 
7849702Slinton 	case OREG:
7859702Slinton 		r = p->tn.rval;
7869702Slinton 		if( R2TEST(r) ){ /* double indexing */
7879702Slinton 			register int flags;
7889702Slinton 
7899702Slinton 			flags = R2UPK3(r);
7909702Slinton 			if( flags & 1 ) printf("*");
7919702Slinton 			if( flags & 4 ) printf("-");
7929702Slinton 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
7939702Slinton 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
7949702Slinton 			if( flags & 2 ) printf("+");
7959702Slinton 			printf( "[%s]", rnames[R2UPK2(r)] );
7969702Slinton 			return;
7979702Slinton 			}
7989702Slinton 		if( r == AP ){  /* in the argument region */
7999702Slinton 			if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" );
8009702Slinton 			printf( CONFMT, p->tn.lval );
8019702Slinton 			printf( "(ap)" );
8029702Slinton 			return;
8039702Slinton 			}
8049702Slinton 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
8059702Slinton 		printf( "(%s)", rnames[p->tn.rval] );
8069702Slinton 		return;
8079702Slinton 
8089702Slinton 	case UNARY MUL:
8099702Slinton 		/* STARNM or STARREG found */
8109702Slinton 		if( tshape(p, STARNM) ) {
8119702Slinton 			printf( "*" );
8129702Slinton 			adrput( p->in.left);
8139702Slinton 			}
8149702Slinton 		else {	/* STARREG - really auto inc or dec */
8159702Slinton 			register NODE *q;
8169702Slinton 
8179702Slinton /* tbl
8189702Slinton 			p = p->in.left;
8199702Slinton 			p->in.left->in.op = OREG;
8209702Slinton 			if( p->in.op == INCR ) {
8219702Slinton 				adrput( p->in.left );
8229702Slinton 				printf( "+" );
8239702Slinton 				}
8249702Slinton 			else {
8259702Slinton 				printf( "-" );
8269702Slinton 				adrput( p->in.left );
8279702Slinton 				}
8289702Slinton    tbl */
82917659Sralph 			q = p->in.left;
83017742Sralph 			if( q->in.right->tn.lval != tlen(p) )
83117742Sralph 				cerror("adrput: bad auto-increment/decrement");
83217659Sralph 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
83317659Sralph 				rnames[q->in.left->tn.rval],
83417659Sralph 				(q->in.op==INCR ? "+" : "") );
8359702Slinton 			p->in.op = OREG;
83617659Sralph 			p->tn.rval = q->in.left->tn.rval;
83717659Sralph 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
8389702Slinton #ifndef FLEXNAMES
8399702Slinton 			p->in.name[0] = '\0';
8409702Slinton #else
8419702Slinton 			p->in.name = "";
8429702Slinton #endif
8439702Slinton 			tfree(q);
8449702Slinton 		}
8459702Slinton 		return;
8469702Slinton 
8479702Slinton 	default:
8489702Slinton 		cerror( "illegal address" );
8499702Slinton 		return;
8509702Slinton 
8519702Slinton 		}
8529702Slinton 
8539702Slinton 	}
8549702Slinton 
8559702Slinton acon( p ) register NODE *p; { /* print out a constant */
8569702Slinton 
8579702Slinton 	if( p->in.name[0] == '\0' ){
8589702Slinton 		printf( CONFMT, p->tn.lval);
8599702Slinton 		}
8609702Slinton 	else if( p->tn.lval == 0 ) {
8619702Slinton #ifndef FLEXNAMES
8629702Slinton 		printf( "%.8s", p->in.name );
8639702Slinton #else
8649702Slinton 		printf( "%s", p->in.name );
8659702Slinton #endif
8669702Slinton 		}
8679702Slinton 	else {
8689702Slinton #ifndef FLEXNAMES
8699702Slinton 		printf( "%.8s+", p->in.name );
8709702Slinton #else
8719702Slinton 		printf( "%s+", p->in.name );
8729702Slinton #endif
8739702Slinton 		printf( CONFMT, p->tn.lval );
8749702Slinton 		}
8759702Slinton 	}
8769702Slinton 
8779702Slinton /*
8789702Slinton aacon( p ) register NODE *p; { /* print out a constant */
8799702Slinton /*
8809702Slinton 
8819702Slinton 	if( p->in.name[0] == '\0' ){
8829702Slinton 		printf( CONFMT, p->tn.lval);
8839702Slinton 		return( 0 );
8849702Slinton 		}
8859702Slinton 	else if( p->tn.lval == 0 ) {
8869702Slinton #ifndef FLEXNAMES
8879702Slinton 		printf( "$%.8s", p->in.name );
8889702Slinton #else
8899702Slinton 		printf( "$%s", p->in.name );
8909702Slinton #endif
8919702Slinton 		return( 1 );
8929702Slinton 		}
8939702Slinton 	else {
8949702Slinton 		printf( "$(" );
8959702Slinton 		printf( CONFMT, p->tn.lval );
8969702Slinton 		printf( "+" );
8979702Slinton #ifndef FLEXNAMES
8989702Slinton 		printf( "%.8s)", p->in.name );
8999702Slinton #else
9009702Slinton 		printf( "%s)", p->in.name );
9019702Slinton #endif
9029702Slinton 		return(1);
9039702Slinton 		}
9049702Slinton 	}
9059702Slinton  */
9069702Slinton 
9079702Slinton genscall( p, cookie ) register NODE *p; {
9089702Slinton 	/* structure valued call */
9099702Slinton 	return( gencall( p, cookie ) );
9109702Slinton 	}
9119702Slinton 
9129702Slinton /* tbl */
9139702Slinton int gc_numbytes;
9149702Slinton /* tbl */
9159702Slinton 
9169702Slinton gencall( p, cookie ) register NODE *p; {
9179702Slinton 	/* generate the call given by p */
91816418Sralph 	register NODE *p1;
9199702Slinton 	register temp, temp1;
9209702Slinton 	register m;
9219702Slinton 
9229702Slinton 	if( p->in.right ) temp = argsize( p->in.right );
9239702Slinton 	else temp = 0;
9249702Slinton 
9259702Slinton 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
9269702Slinton 		/* set aside room for structure return */
9279702Slinton 
9289702Slinton 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
9299702Slinton 		else temp1 = temp;
9309702Slinton 		}
9319702Slinton 
9329702Slinton 	if( temp > maxargs ) maxargs = temp;
9339702Slinton 	SETOFF(temp1,4);
9349702Slinton 
9359702Slinton 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
93616418Sralph 		genargs( p->in.right );
9379702Slinton 		}
9389702Slinton 
9399702Slinton 	p1 = p->in.left;
9409702Slinton 	if( p1->in.op != ICON ){
9419702Slinton 		if( p1->in.op != REG ){
9429702Slinton 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
9439702Slinton 				if( p1->in.op != NAME ){
9449702Slinton 					order( p1, INAREG );
9459702Slinton 					}
9469702Slinton 				}
9479702Slinton 			}
9489702Slinton 		}
9499702Slinton 
9509702Slinton /*
9519702Slinton 	if( p1->in.op == REG && p->tn.rval == R5 ){
9529702Slinton 		cerror( "call register overwrite" );
9539702Slinton 		}
9549702Slinton  */
9559702Slinton /* tbl
9569702Slinton 	setup gc_numbytes so reference to ZC works */
9579702Slinton 
9589702Slinton 	gc_numbytes = temp&(0x3ff);
9599702Slinton /* tbl */
9609702Slinton 
9619702Slinton 	p->in.op = UNARY CALL;
9629702Slinton 	m = match( p, INTAREG|INTBREG );
9639702Slinton 
9649702Slinton 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
9659702Slinton 	/* (plus in assignment to gc_numbytes above, for neatness only) */
9669702Slinton 	if (temp >= 1024)
9679702Slinton 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
9689702Slinton 
9699702Slinton /* tbl
9709702Slinton 	switch( temp ) {
9719702Slinton 	case 0:
9729702Slinton 		break;
9739702Slinton 	case 2:
9749702Slinton 		printf( "	tst	(sp)+\n" );
9759702Slinton 		break;
9769702Slinton 	case 4:
9779702Slinton 		printf( "	cmp	(sp)+,(sp)+\n" );
9789702Slinton 		break;
9799702Slinton 	default:
9809702Slinton 		printf( "	add	$%d,sp\n", temp);
9819702Slinton 		}
9829702Slinton    tbl */
9839702Slinton 	return(m != MDONE);
9849702Slinton 	}
9859702Slinton 
9869702Slinton /* tbl */
9879702Slinton char *
9889702Slinton ccbranches[] = {
9899702Slinton 	"	jeql	L%d\n",
9909702Slinton 	"	jneq	L%d\n",
9919702Slinton 	"	jleq	L%d\n",
9929702Slinton 	"	jlss	L%d\n",
9939702Slinton 	"	jgeq	L%d\n",
9949702Slinton 	"	jgtr	L%d\n",
9959702Slinton 	"	jlequ	L%d\n",
9969702Slinton 	"	jlssu	L%d\n",
9979702Slinton 	"	jgequ	L%d\n",
9989702Slinton 	"	jgtru	L%d\n",
9999702Slinton 	};
10009702Slinton /* tbl */
10019702Slinton 
10029702Slinton cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
10039702Slinton 
10049702Slinton /* tbl */
10059702Slinton 	if( o == 0 ) printf( "	jbr	L%d\n", lab );
10069702Slinton /* tbl */
10079702Slinton 	else {
10089702Slinton 		if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
10099702Slinton 		printf( ccbranches[o-EQ], lab );
10109702Slinton 		}
10119702Slinton 	}
10129702Slinton 
10139702Slinton nextcook( p, cookie ) NODE *p; {
10149702Slinton 	/* we have failed to match p with cookie; try another */
10159702Slinton 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
10169702Slinton 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
10179702Slinton 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
10189702Slinton 	return( FORREW );
10199702Slinton 	}
10209702Slinton 
10219702Slinton lastchance( p, cook ) NODE *p; {
10229702Slinton 	/* forget it! */
10239702Slinton 	return(0);
10249702Slinton 	}
10259702Slinton 
10269702Slinton optim2( p ) register NODE *p; {
10279702Slinton 	/* do local tree transformations and optimizations */
10289702Slinton 
102916181Sralph 	register NODE *l, *r;
103016181Sralph 	int m, ml;
10319702Slinton 
10329702Slinton 	switch( p->in.op ) {
10339702Slinton 
10349702Slinton 	case AND:
103519933Smckusick 		/* commute L and R to eliminate complements and constants */
103616181Sralph 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
103716181Sralph 		    l->in.op == COMPL ) {
10389702Slinton 			p->in.left = p->in.right;
103916181Sralph 			p->in.right = l;
10409702Slinton 			}
10419702Slinton 	case ASG AND:
10429702Slinton 		/* change meaning of AND to ~R&L - bic on pdp11 */
10439702Slinton 		r = p->in.right;
104419933Smckusick 		if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */
10459702Slinton 			r->tn.lval = ~r->tn.lval;
10469702Slinton 			}
10479702Slinton 		else if( r->in.op==COMPL ) { /* ~~A => A */
10489702Slinton 			r->in.op = FREE;
10499702Slinton 			p->in.right = r->in.left;
10509702Slinton 			}
10519702Slinton 		else { /* insert complement node */
105216181Sralph 			p->in.right = l = talloc();
105316181Sralph 			l->in.op = COMPL;
105416181Sralph 			l->in.rall = NOPREF;
105516181Sralph 			l->in.type = r->in.type;
105616181Sralph 			l->in.left = r;
105716181Sralph 			l->in.right = NULL;
10589702Slinton 			}
10599702Slinton 		break;
10609702Slinton 
106116181Sralph 	case SCONV:
106219933Smckusick 		l = p->in.left;
106317742Sralph #if defined(FORT) || defined(SPRECC)
106416573Sralph 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
106519933Smckusick 		    l->in.type == FLOAT || l->in.type == DOUBLE )
106619933Smckusick 			return;
106716573Sralph #else
106819933Smckusick 		if( mixtypes(p, l) ) return;
106916573Sralph #endif
107019933Smckusick 		/* Only trust it to get it right if the size is the same */
107119933Smckusick 		if( tlen(p) != tlen(l) )
107219933Smckusick 			return;
107316181Sralph 
107416181Sralph 		/* clobber conversion */
107519933Smckusick 		if( l->in.op != FLD )
107616181Sralph 			l->in.type = p->in.type;
107716181Sralph 		ncopy( p, l );
107816181Sralph 		l->in.op = FREE;
107919933Smckusick 
108016181Sralph 		break;
108116181Sralph 
10829702Slinton 		}
10839702Slinton 	}
10849702Slinton 
108517742Sralph NODE * addroreg(l) NODE *l;
10869702Slinton 				/* OREG was built in clocal()
10879702Slinton 				 * for an auto or formal parameter
10889702Slinton 				 * now its address is being taken
10899702Slinton 				 * local code must unwind it
10909702Slinton 				 * back to PLUS/MINUS REG ICON
10919702Slinton 				 * according to local conventions
10929702Slinton 				 */
10939702Slinton {
10949702Slinton 	cerror("address of OREG taken");
109517742Sralph 	/*NOTREACHED*/
10969702Slinton }
10979702Slinton 
10989702Slinton 
10999702Slinton 
11009702Slinton # ifndef ONEPASS
11019702Slinton main( argc, argv ) char *argv[]; {
11029702Slinton 	return( mainp2( argc, argv ) );
11039702Slinton 	}
11049702Slinton # endif
11059702Slinton 
11069702Slinton 
11079702Slinton /* added by jwf */
11089702Slinton struct functbl {
11099702Slinton 	int fop;
11109702Slinton 	TWORD ftype;
11119702Slinton 	char *func;
11129702Slinton 	} opfunc[] = {
11139702Slinton 	DIV,		TANY,	"udiv",
11149702Slinton 	MOD,		TANY,	"urem",
111517715Sralph 	ASG DIV,	TANY,	"audiv",
111617715Sralph 	ASG MOD,	TANY,	"aurem",
11179702Slinton 	0,	0,	0 };
11189702Slinton 
11199702Slinton hardops(p)  register NODE *p; {
11209702Slinton 	/* change hard to do operators into function calls.  */
11219702Slinton 	register NODE *q;
11229702Slinton 	register struct functbl *f;
11239702Slinton 	register o;
112417742Sralph 	NODE *old,*temp;
11259702Slinton 
11269702Slinton 	o = p->in.op;
112717742Sralph 	if( ! (optype(o)==BITYPE &&
112817742Sralph 	       (ISUNSIGNED(p->in.left->in.type) ||
112917742Sralph 		ISUNSIGNED(p->in.right->in.type))) )
113017742Sralph 		return;
11319702Slinton 
11329702Slinton 	for( f=opfunc; f->fop; f++ ) {
11339702Slinton 		if( o==f->fop ) goto convert;
11349702Slinton 		}
11359702Slinton 	return;
11369702Slinton 
11379702Slinton 	convert:
11389702Slinton 	if( asgop( o ) ) {
113917742Sralph 		old = NIL;
114017715Sralph 		switch( p->in.left->in.op ){
114117742Sralph 		case FLD:
114217742Sralph 			q = p->in.left->in.left;
114317742Sralph 			/*
114417742Sralph 			 * rewrite (lval.fld /= rval); as
114517742Sralph 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
114617742Sralph 			 * else the compiler will evaluate lval twice.
114717742Sralph 			 */
114817742Sralph 			if( q->in.op == UNARY MUL ){
114917742Sralph 				/* first allocate a temp storage */
115017742Sralph 				temp = talloc();
115117742Sralph 				temp->in.op = OREG;
115217742Sralph 				temp->tn.rval = TMPREG;
115317742Sralph 				temp->tn.lval = BITOOR(freetemp(1));
115417742Sralph 				temp->in.type = INCREF(p->in.type);
115517742Sralph #ifdef FLEXNAMES
115617742Sralph 				temp->in.name = "";
115717742Sralph #else
115817742Sralph 				temp->in.name[0] = '\0';
115917742Sralph #endif
116017742Sralph 				old = q->in.left;
116117742Sralph 				q->in.left = temp;
116217742Sralph 			}
116317742Sralph 			/* fall thru ... */
116417742Sralph 
116517715Sralph 		case REG:
116617715Sralph 		case NAME:
116717715Sralph 		case OREG:
116817715Sralph 			/* change ASG OP to a simple OP */
116917715Sralph 			q = talloc();
117017715Sralph 			q->in.op = NOASG p->in.op;
117117715Sralph 			q->in.rall = NOPREF;
117217715Sralph 			q->in.type = p->in.type;
117317715Sralph 			q->in.left = tcopy(p->in.left);
117417715Sralph 			q->in.right = p->in.right;
117517715Sralph 			p->in.op = ASSIGN;
117617715Sralph 			p->in.right = q;
117717715Sralph 			p = q;
117817715Sralph 			f -= 2; /* Note: this depends on the table order */
117917742Sralph 			/* on the right side only - replace *temp with
118017742Sralph 			 *(temp = &lval), build the assignment node */
118117742Sralph 			if( old ){
118217742Sralph 				temp = q->in.left->in.left; /* the "*" node */
118317742Sralph 				q = talloc();
118417742Sralph 				q->in.op = ASSIGN;
118517742Sralph 				q->in.left = temp->in.left;
118617742Sralph 				q->in.right = old;
118717742Sralph 				q->in.type = old->in.type;
118817742Sralph #ifdef FLEXNAMES
118917742Sralph 				q->in.name = "";
119017742Sralph #else
119117742Sralph 				q->in.name[0] = '\0';
119217742Sralph #endif
119317742Sralph 				temp->in.left = q;
119417742Sralph 			}
119517715Sralph 			break;
11969702Slinton 
119717715Sralph 		case UNARY MUL:
119817715Sralph 			/* avoid doing side effects twice */
119917715Sralph 			q = p->in.left;
120017715Sralph 			p->in.left = q->in.left;
120117715Sralph 			q->in.op = FREE;
120217715Sralph 			break;
120317715Sralph 
120417715Sralph 		default:
120517715Sralph 			cerror( "hardops: can't compute & LHS" );
120617715Sralph 			}
120717742Sralph 		}
120817715Sralph 
12099702Slinton 	/* build comma op for args to function */
12109702Slinton 	q = talloc();
12119702Slinton 	q->in.op = CM;
12129702Slinton 	q->in.rall = NOPREF;
12139702Slinton 	q->in.type = INT;
12149702Slinton 	q->in.left = p->in.left;
12159702Slinton 	q->in.right = p->in.right;
12169702Slinton 	p->in.op = CALL;
12179702Slinton 	p->in.right = q;
12189702Slinton 
12199702Slinton 	/* put function name in left node of call */
12209702Slinton 	p->in.left = q = talloc();
12219702Slinton 	q->in.op = ICON;
12229702Slinton 	q->in.rall = NOPREF;
12239702Slinton 	q->in.type = INCREF( FTN + p->in.type );
12249702Slinton #ifndef FLEXNAMES
12259702Slinton 	strcpy( q->in.name, f->func );
12269702Slinton #else
12279702Slinton 	q->in.name = f->func;
12289702Slinton #endif
12299702Slinton 	q->tn.lval = 0;
12309702Slinton 	q->tn.rval = 0;
12319702Slinton 
12329702Slinton 	}
12339702Slinton 
123417742Sralph zappost(p) NODE *p; {
123517742Sralph 	/* look for ++ and -- operators and remove them */
123617742Sralph 
123717742Sralph 	register o, ty;
123817742Sralph 	register NODE *q;
123917742Sralph 	o = p->in.op;
124017742Sralph 	ty = optype( o );
124117742Sralph 
124217742Sralph 	switch( o ){
124317742Sralph 
124417742Sralph 	case INCR:
124517742Sralph 	case DECR:
124617742Sralph 			q = p->in.left;
124717742Sralph 			p->in.right->in.op = FREE;  /* zap constant */
124817742Sralph 			ncopy( p, q );
124917742Sralph 			q->in.op = FREE;
125017742Sralph 			return;
125117742Sralph 
125217742Sralph 		}
125317742Sralph 
125417742Sralph 	if( ty == BITYPE ) zappost( p->in.right );
125517742Sralph 	if( ty != LTYPE ) zappost( p->in.left );
125617742Sralph }
125717742Sralph 
125817742Sralph fixpre(p) NODE *p; {
125917742Sralph 
126017742Sralph 	register o, ty;
126117742Sralph 	o = p->in.op;
126217742Sralph 	ty = optype( o );
126317742Sralph 
126417742Sralph 	switch( o ){
126517742Sralph 
126617742Sralph 	case ASG PLUS:
126717742Sralph 			p->in.op = PLUS;
126817742Sralph 			break;
126917742Sralph 	case ASG MINUS:
127017742Sralph 			p->in.op = MINUS;
127117742Sralph 			break;
127217742Sralph 		}
127317742Sralph 
127417742Sralph 	if( ty == BITYPE ) fixpre( p->in.right );
127517742Sralph 	if( ty != LTYPE ) fixpre( p->in.left );
127617742Sralph }
127717742Sralph 
12789702Slinton myreader(p) register NODE *p; {
127917742Sralph 	canon( p );		/* expands r-vals for fields */
12809702Slinton 	walkf( p, hardops );	/* convert ops to function calls */
12819702Slinton 	walkf( p, optim2 );
12829702Slinton 	/* jwf toff = 0;  /* stack offset swindle */
12839702Slinton 	}
1284