xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 19933)
117742Sralph # ifndef lint
2*19933Smckusick static char *sccsid ="@(#)local2.c	1.10 (Berkeley) 05/03/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 
27417208Sralph 		if (l->in.op == REG && l->in.type != FLOAT && l->in.type != DOUBLE) {
27517208Sralph 			if (tlen(l) < tlen(r) && !mixtypes(l,r)) {
27616181Sralph 				if (ISUNSIGNED(l->in.type))
27716181Sralph 					printf("movz");
2789702Slinton 				else
2799702Slinton 					printf("cvt");
28016181Sralph 				prtype(l);
28116181Sralph 				printf("l");
28216181Sralph 				goto ops;
2839702Slinton 				}
2849702Slinton 			else
28516181Sralph 				l->in.type = INT;
2869702Slinton 			}
28717208Sralph 		if (!mixtypes(l,r)) {
28817208Sralph 			if (tlen(l) == tlen(r)) {
2899702Slinton 				printf("mov");
29017742Sralph #ifdef FORT
29117742Sralph 				if (Oflag)
29217742Sralph 					prtype(l);
29317742Sralph 				else {
29417742Sralph 					if (l->in.type == DOUBLE)
29517742Sralph 						printf("q");
29617742Sralph 					else if(l->in.type == FLOAT)
29717742Sralph 						printf("l");
29817742Sralph 					else
29917742Sralph 						prtype(l);
30017742Sralph 					}
30117742Sralph #else
3029702Slinton 				prtype(l);
30317742Sralph #endif FORT
3049702Slinton 				goto ops;
3059702Slinton 				}
3069702Slinton 			else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
3079702Slinton 				printf("movz");
3089702Slinton 			else
3099702Slinton 				printf("cvt");
3109702Slinton 			}
3119702Slinton 		else
3129702Slinton 			printf("cvt");
3139702Slinton 		prtype(r);
3149702Slinton 		prtype(l);
3159702Slinton 	ops:
3169702Slinton 		printf("	");
3179702Slinton 		adrput(r);
3189702Slinton 		printf(",");
3199702Slinton 		adrput(l);
3209702Slinton 		return;
3219702Slinton 		}
3229702Slinton 
3239702Slinton 	case 'B':	/* get oreg value in temp register for left shift */
3249702Slinton 		{
3259702Slinton 		register NODE *r;
3269702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
3279702Slinton 		r = p->in.right;
3289702Slinton 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
3299702Slinton 			printf("movl");
3309702Slinton 		else {
3319702Slinton 			printf("cvt");
3329702Slinton 			prtype(r);
3339702Slinton 			printf("l");
3349702Slinton 			}
3359702Slinton 		return;
3369702Slinton 		}
3379702Slinton 
3389702Slinton 	case 'C':	/* num words pushed on arg stack */
3399702Slinton 		{
3409702Slinton 		extern int gc_numbytes;
3419702Slinton 		extern int xdebug;
3429702Slinton 
3439702Slinton 		if (xdebug) printf("->%d<-",gc_numbytes);
3449702Slinton 
3459702Slinton 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
3469702Slinton 		return;
3479702Slinton 		}
3489702Slinton 
3499702Slinton 	case 'D':	/* INCR and DECR */
3509702Slinton 		zzzcode(p->in.left, 'A');
3519702Slinton 		printf("\n	");
3529702Slinton 
3539702Slinton 	case 'E':	/* INCR and DECR, FOREFF */
3549702Slinton 		if (p->in.right->tn.lval == 1)
3559702Slinton 			{
3569702Slinton 			printf("%s", (p->in.op == INCR ? "inc" : "dec") );
3579702Slinton 			prtype(p->in.left);
3589702Slinton 			printf("	");
3599702Slinton 			adrput(p->in.left);
3609702Slinton 			return;
3619702Slinton 			}
3629702Slinton 		printf("%s", (p->in.op == INCR ? "add" : "sub") );
3639702Slinton 		prtype(p->in.left);
3649702Slinton 		printf("2	");
3659702Slinton 		adrput(p->in.right);
3669702Slinton 		printf(",");
3679702Slinton 		adrput(p->in.left);
3689702Slinton 		return;
3699702Slinton 
3709702Slinton 	case 'F':	/* register type of right operand */
3719702Slinton 		{
3729702Slinton 		register NODE *n;
3739702Slinton 		extern int xdebug;
3749702Slinton 		register int ty;
3759702Slinton 
3769702Slinton 		n = getlr( p, 'R' );
3779702Slinton 		ty = n->in.type;
3789702Slinton 
3799702Slinton 		if (xdebug) printf("->%d<-", ty);
3809702Slinton 
3819702Slinton 		if ( ty==DOUBLE) printf("d");
3829702Slinton 		else if ( ty==FLOAT ) printf("f");
3839702Slinton 		else printf("l");
3849702Slinton 		return;
3859702Slinton 		}
3869702Slinton 
3879702Slinton 	case 'L':	/* type of left operand */
3889702Slinton 	case 'R':	/* type of right operand */
3899702Slinton 		{
3909702Slinton 		register NODE *n;
3919702Slinton 		extern int xdebug;
3929702Slinton 
39316181Sralph 		n = getlr( p, c );
3949702Slinton 		if (xdebug) printf("->%d<-", n->in.type);
3959702Slinton 
3969702Slinton 		prtype(n);
3979702Slinton 		return;
3989702Slinton 		}
3999702Slinton 
4009702Slinton 	case 'Z':	/* complement mask for bit instr */
4019702Slinton 		printf("$%ld", ~p->in.right->tn.lval);
4029702Slinton 		return;
4039702Slinton 
4049702Slinton 	case 'U':	/* 32 - n, for unsigned right shifts */
4059702Slinton 		printf("$%d", 32 - p->in.right->tn.lval );
4069702Slinton 		return;
4079702Slinton 
4089702Slinton 	case 'T':	/* rounded structure length for arguments */
4099702Slinton 		{
4109702Slinton 		int size;
4119702Slinton 
4129702Slinton 		size = p->stn.stsize;
4139702Slinton 		SETOFF( size, 4);
4149702Slinton 		printf("$%d", size);
4159702Slinton 		return;
4169702Slinton 		}
4179702Slinton 
4189702Slinton 	case 'S':  /* structure assignment */
4199702Slinton 		{
4209702Slinton 			register NODE *l, *r;
4219702Slinton 			register size;
4229702Slinton 
4239702Slinton 			if( p->in.op == STASG ){
4249702Slinton 				l = p->in.left;
4259702Slinton 				r = p->in.right;
4269702Slinton 
4279702Slinton 				}
4289702Slinton 			else if( p->in.op == STARG ){  /* store an arg into a temporary */
4299702Slinton 				r = p->in.left;
4309702Slinton 				}
4319702Slinton 			else cerror( "STASG bad" );
4329702Slinton 
4339702Slinton 			if( r->in.op == ICON ) r->in.op = NAME;
4349702Slinton 			else if( r->in.op == REG ) r->in.op = OREG;
4359702Slinton 			else if( r->in.op != OREG ) cerror( "STASG-r" );
4369702Slinton 
4379702Slinton 			size = p->stn.stsize;
4389702Slinton 
4399702Slinton 			if( size <= 0 || size > 65535 )
4409702Slinton 				cerror("structure size <0=0 or >65535");
4419702Slinton 
4429702Slinton 			switch(size) {
4439702Slinton 				case 1:
4449702Slinton 					printf("	movb	");
4459702Slinton 					break;
4469702Slinton 				case 2:
4479702Slinton 					printf("	movw	");
4489702Slinton 					break;
4499702Slinton 				case 4:
4509702Slinton 					printf("	movl	");
4519702Slinton 					break;
4529702Slinton 				case 8:
4539702Slinton 					printf("	movq	");
4549702Slinton 					break;
4559702Slinton 				default:
4569702Slinton 					printf("	movc3	$%d,", size);
4579702Slinton 					break;
4589702Slinton 			}
4599702Slinton 			adrput(r);
46016418Sralph 			if( p->in.op == STASG ){
46116418Sralph 				printf(",");
46216418Sralph 				adrput(l);
46316418Sralph 				printf("\n");
46416418Sralph 				}
46516418Sralph 			else
46616418Sralph 				printf(",(sp)\n");
4679702Slinton 
4689702Slinton 			if( r->in.op == NAME ) r->in.op = ICON;
4699702Slinton 			else if( r->in.op == OREG ) r->in.op = REG;
4709702Slinton 
4719702Slinton 			}
4729702Slinton 		break;
4739702Slinton 
4749702Slinton 	default:
4759702Slinton 		cerror( "illegal zzzcode" );
4769702Slinton 		}
4779702Slinton 	}
4789702Slinton 
47917742Sralph rmove( rt, rs, t ) TWORD t; {
4809702Slinton 	printf( "	%s	%s,%s\n",
48117742Sralph #ifdef FORT
48217742Sralph 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
48317742Sralph #endif
4849702Slinton 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
4859702Slinton 		rnames[rs], rnames[rt] );
4869702Slinton 	}
4879702Slinton 
4889702Slinton struct respref
4899702Slinton respref[] = {
4909702Slinton 	INTAREG|INTBREG,	INTAREG|INTBREG,
4919702Slinton 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
4929702Slinton 	INTEMP,	INTEMP,
4939702Slinton 	FORARG,	FORARG,
4949702Slinton 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
4959702Slinton 	0,	0 };
4969702Slinton 
4979702Slinton setregs(){ /* set up temporary registers */
4989702Slinton 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
4999702Slinton 	;
5009702Slinton 	}
5019702Slinton 
50217742Sralph szty(t) TWORD t; { /* size, in registers, needed to hold thing of type t */
50317742Sralph #if defined(FORT) || defined(SPRECC)
50416181Sralph 	return( (t==DOUBLE) ? 2 : 1 );
50516181Sralph #else
5069702Slinton 	return( (t==DOUBLE||t==FLOAT) ? 2 : 1 );
50716181Sralph #endif
5089702Slinton 	}
5099702Slinton 
5109702Slinton rewfld( p ) NODE *p; {
5119702Slinton 	return(1);
5129702Slinton 	}
5139702Slinton 
5149702Slinton callreg(p) NODE *p; {
5159702Slinton 	return( R0 );
5169702Slinton 	}
5179702Slinton 
5189702Slinton base( p ) register NODE *p; {
5199702Slinton 	register int o = p->in.op;
5209702Slinton 
5219702Slinton 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
5229702Slinton 	if( o==REG ) return( p->tn.rval );
5239702Slinton     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
5249702Slinton 		return( p->in.left->tn.rval );
5259702Slinton     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
5269702Slinton 		return( p->tn.rval + 0200*1 );
5279702Slinton 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
5289702Slinton 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
5299702Slinton 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
5309702Slinton 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
5319702Slinton 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
5329702Slinton 	return( -1 );
5339702Slinton 	}
5349702Slinton 
5359702Slinton offset( p, tyl ) register NODE *p; int tyl; {
5369702Slinton 
5379702Slinton 	if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
5389702Slinton 	if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
5399702Slinton 	      (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
5409702Slinton 	      && (1<<p->in.right->tn.lval)==tyl))
5419702Slinton 		return( p->in.left->tn.rval );
5429702Slinton 	return( -1 );
5439702Slinton 	}
5449702Slinton 
5459702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
5469702Slinton 	register NODE *t;
5479702Slinton 	register int i;
5489702Slinton 	NODE *f;
5499702Slinton 
5509702Slinton 	p->in.op = OREG;
5519702Slinton 	f = p->in.left; 	/* have to free this subtree later */
5529702Slinton 
5539702Slinton 	/* init base */
5549702Slinton 	switch (q->in.op) {
5559702Slinton 		case ICON:
5569702Slinton 		case REG:
5579702Slinton 		case OREG:
5589702Slinton 			t = q;
5599702Slinton 			break;
5609702Slinton 
5619702Slinton 		case MINUS:
5629702Slinton 			q->in.right->tn.lval = -q->in.right->tn.lval;
5639702Slinton 		case PLUS:
5649702Slinton 			t = q->in.right;
5659702Slinton 			break;
5669702Slinton 
5679702Slinton 		case INCR:
5689702Slinton 		case ASG MINUS:
5699702Slinton 			t = q->in.left;
5709702Slinton 			break;
5719702Slinton 
5729702Slinton 		case UNARY MUL:
5739702Slinton 			t = q->in.left->in.left;
5749702Slinton 			break;
5759702Slinton 
5769702Slinton 		default:
5779702Slinton 			cerror("illegal makeor2");
5789702Slinton 	}
5799702Slinton 
5809702Slinton 	p->tn.lval = t->tn.lval;
5819702Slinton #ifndef FLEXNAMES
5829702Slinton 	for(i=0; i<NCHNAM; ++i)
5839702Slinton 		p->in.name[i] = t->in.name[i];
5849702Slinton #else
5859702Slinton 	p->in.name = t->in.name;
5869702Slinton #endif
5879702Slinton 
5889702Slinton 	/* init offset */
5899702Slinton 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
5909702Slinton 
5919702Slinton 	tfree(f);
5929702Slinton 	return;
5939702Slinton 	}
5949702Slinton 
5959702Slinton canaddr( p ) NODE *p; {
5969702Slinton 	register int o = p->in.op;
5979702Slinton 
5989702Slinton 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
5999702Slinton 	return(0);
6009702Slinton 	}
6019702Slinton 
6029702Slinton shltype( o, p ) register NODE *p; {
6039702Slinton 	return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
6049702Slinton 	}
6059702Slinton 
6069702Slinton flshape( p ) register NODE *p; {
6079702Slinton 	return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
6089702Slinton 		(p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
6099702Slinton 	}
6109702Slinton 
6119702Slinton shtemp( p ) register NODE *p; {
6129702Slinton 	if( p->in.op == STARG ) p = p->in.left;
6139702Slinton 	return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
6149702Slinton 	}
6159702Slinton 
6169702Slinton shumul( p ) register NODE *p; {
6179702Slinton 	register o;
6189702Slinton 	extern int xdebug;
6199702Slinton 
6209702Slinton 	if (xdebug) {
6219702Slinton 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
6229702Slinton 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
6239702Slinton 		}
6249702Slinton 
6259702Slinton 
6269702Slinton 	o = p->in.op;
6279702Slinton 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
6289702Slinton 
6299702Slinton 	if( ( o == INCR || o == ASG MINUS ) &&
6309702Slinton 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
6319702Slinton 	    p->in.right->in.name[0] == '\0' )
6329702Slinton 		{
63317659Sralph 		switch (p->in.type)
6349702Slinton 			{
6359702Slinton 			case CHAR|PTR:
6369702Slinton 			case UCHAR|PTR:
6379702Slinton 				o = 1;
6389702Slinton 				break;
6399702Slinton 
6409702Slinton 			case SHORT|PTR:
6419702Slinton 			case USHORT|PTR:
6429702Slinton 				o = 2;
6439702Slinton 				break;
6449702Slinton 
6459702Slinton 			case INT|PTR:
6469702Slinton 			case UNSIGNED|PTR:
6479702Slinton 			case LONG|PTR:
6489702Slinton 			case ULONG|PTR:
6499702Slinton 			case FLOAT|PTR:
6509702Slinton 				o = 4;
6519702Slinton 				break;
6529702Slinton 
6539702Slinton 			case DOUBLE|PTR:
6549702Slinton 				o = 8;
6559702Slinton 				break;
6569702Slinton 
6579702Slinton 			default:
65817742Sralph 				if ( ISPTR(p->in.type) &&
65917742Sralph 				     ISPTR(DECREF(p->in.type)) ) {
6609702Slinton 					o = 4;
6619702Slinton 					break;
6629702Slinton 					}
6639702Slinton 				else return(0);
6649702Slinton 			}
6659702Slinton 		return( p->in.right->tn.lval == o ? STARREG : 0);
6669702Slinton 		}
6679702Slinton 
6689702Slinton 	return( 0 );
6699702Slinton 	}
6709702Slinton 
6719702Slinton adrcon( val ) CONSZ val; {
6729702Slinton 	printf( "$" );
6739702Slinton 	printf( CONFMT, val );
6749702Slinton 	}
6759702Slinton 
6769702Slinton conput( p ) register NODE *p; {
6779702Slinton 	switch( p->in.op ){
6789702Slinton 
6799702Slinton 	case ICON:
6809702Slinton 		acon( p );
6819702Slinton 		return;
6829702Slinton 
6839702Slinton 	case REG:
6849702Slinton 		printf( "%s", rnames[p->tn.rval] );
6859702Slinton 		return;
6869702Slinton 
6879702Slinton 	default:
6889702Slinton 		cerror( "illegal conput" );
6899702Slinton 		}
6909702Slinton 	}
6919702Slinton 
6929702Slinton insput( p ) register NODE *p; {
6939702Slinton 	cerror( "insput" );
6949702Slinton 	}
6959702Slinton 
6969702Slinton upput( p ) register NODE *p; {
6979702Slinton 	cerror( "upput" );
6989702Slinton 	}
6999702Slinton 
7009702Slinton adrput( p ) register NODE *p; {
7019702Slinton 	register int r;
7029702Slinton 	/* output an address, with offsets, from p */
7039702Slinton 
7049702Slinton 	if( p->in.op == FLD ){
7059702Slinton 		p = p->in.left;
7069702Slinton 		}
7079702Slinton 	switch( p->in.op ){
7089702Slinton 
7099702Slinton 	case NAME:
7109702Slinton 		acon( p );
7119702Slinton 		return;
7129702Slinton 
7139702Slinton 	case ICON:
7149702Slinton 		/* addressable value of the constant */
7159702Slinton 		printf( "$" );
7169702Slinton 		acon( p );
7179702Slinton 		return;
7189702Slinton 
7199702Slinton 	case REG:
7209702Slinton 		printf( "%s", rnames[p->tn.rval] );
7219702Slinton 		return;
7229702Slinton 
7239702Slinton 	case OREG:
7249702Slinton 		r = p->tn.rval;
7259702Slinton 		if( R2TEST(r) ){ /* double indexing */
7269702Slinton 			register int flags;
7279702Slinton 
7289702Slinton 			flags = R2UPK3(r);
7299702Slinton 			if( flags & 1 ) printf("*");
7309702Slinton 			if( flags & 4 ) printf("-");
7319702Slinton 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
7329702Slinton 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
7339702Slinton 			if( flags & 2 ) printf("+");
7349702Slinton 			printf( "[%s]", rnames[R2UPK2(r)] );
7359702Slinton 			return;
7369702Slinton 			}
7379702Slinton 		if( r == AP ){  /* in the argument region */
7389702Slinton 			if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" );
7399702Slinton 			printf( CONFMT, p->tn.lval );
7409702Slinton 			printf( "(ap)" );
7419702Slinton 			return;
7429702Slinton 			}
7439702Slinton 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
7449702Slinton 		printf( "(%s)", rnames[p->tn.rval] );
7459702Slinton 		return;
7469702Slinton 
7479702Slinton 	case UNARY MUL:
7489702Slinton 		/* STARNM or STARREG found */
7499702Slinton 		if( tshape(p, STARNM) ) {
7509702Slinton 			printf( "*" );
7519702Slinton 			adrput( p->in.left);
7529702Slinton 			}
7539702Slinton 		else {	/* STARREG - really auto inc or dec */
7549702Slinton 			register NODE *q;
7559702Slinton 
7569702Slinton /* tbl
7579702Slinton 			p = p->in.left;
7589702Slinton 			p->in.left->in.op = OREG;
7599702Slinton 			if( p->in.op == INCR ) {
7609702Slinton 				adrput( p->in.left );
7619702Slinton 				printf( "+" );
7629702Slinton 				}
7639702Slinton 			else {
7649702Slinton 				printf( "-" );
7659702Slinton 				adrput( p->in.left );
7669702Slinton 				}
7679702Slinton    tbl */
76817659Sralph 			q = p->in.left;
76917742Sralph 			if( q->in.right->tn.lval != tlen(p) )
77017742Sralph 				cerror("adrput: bad auto-increment/decrement");
77117659Sralph 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
77217659Sralph 				rnames[q->in.left->tn.rval],
77317659Sralph 				(q->in.op==INCR ? "+" : "") );
7749702Slinton 			p->in.op = OREG;
77517659Sralph 			p->tn.rval = q->in.left->tn.rval;
77617659Sralph 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
7779702Slinton #ifndef FLEXNAMES
7789702Slinton 			p->in.name[0] = '\0';
7799702Slinton #else
7809702Slinton 			p->in.name = "";
7819702Slinton #endif
7829702Slinton 			tfree(q);
7839702Slinton 		}
7849702Slinton 		return;
7859702Slinton 
7869702Slinton 	default:
7879702Slinton 		cerror( "illegal address" );
7889702Slinton 		return;
7899702Slinton 
7909702Slinton 		}
7919702Slinton 
7929702Slinton 	}
7939702Slinton 
7949702Slinton acon( p ) register NODE *p; { /* print out a constant */
7959702Slinton 
7969702Slinton 	if( p->in.name[0] == '\0' ){
7979702Slinton 		printf( CONFMT, p->tn.lval);
7989702Slinton 		}
7999702Slinton 	else if( p->tn.lval == 0 ) {
8009702Slinton #ifndef FLEXNAMES
8019702Slinton 		printf( "%.8s", p->in.name );
8029702Slinton #else
8039702Slinton 		printf( "%s", p->in.name );
8049702Slinton #endif
8059702Slinton 		}
8069702Slinton 	else {
8079702Slinton #ifndef FLEXNAMES
8089702Slinton 		printf( "%.8s+", p->in.name );
8099702Slinton #else
8109702Slinton 		printf( "%s+", p->in.name );
8119702Slinton #endif
8129702Slinton 		printf( CONFMT, p->tn.lval );
8139702Slinton 		}
8149702Slinton 	}
8159702Slinton 
8169702Slinton /*
8179702Slinton aacon( p ) register NODE *p; { /* print out a constant */
8189702Slinton /*
8199702Slinton 
8209702Slinton 	if( p->in.name[0] == '\0' ){
8219702Slinton 		printf( CONFMT, p->tn.lval);
8229702Slinton 		return( 0 );
8239702Slinton 		}
8249702Slinton 	else if( p->tn.lval == 0 ) {
8259702Slinton #ifndef FLEXNAMES
8269702Slinton 		printf( "$%.8s", p->in.name );
8279702Slinton #else
8289702Slinton 		printf( "$%s", p->in.name );
8299702Slinton #endif
8309702Slinton 		return( 1 );
8319702Slinton 		}
8329702Slinton 	else {
8339702Slinton 		printf( "$(" );
8349702Slinton 		printf( CONFMT, p->tn.lval );
8359702Slinton 		printf( "+" );
8369702Slinton #ifndef FLEXNAMES
8379702Slinton 		printf( "%.8s)", p->in.name );
8389702Slinton #else
8399702Slinton 		printf( "%s)", p->in.name );
8409702Slinton #endif
8419702Slinton 		return(1);
8429702Slinton 		}
8439702Slinton 	}
8449702Slinton  */
8459702Slinton 
8469702Slinton genscall( p, cookie ) register NODE *p; {
8479702Slinton 	/* structure valued call */
8489702Slinton 	return( gencall( p, cookie ) );
8499702Slinton 	}
8509702Slinton 
8519702Slinton /* tbl */
8529702Slinton int gc_numbytes;
8539702Slinton /* tbl */
8549702Slinton 
8559702Slinton gencall( p, cookie ) register NODE *p; {
8569702Slinton 	/* generate the call given by p */
85716418Sralph 	register NODE *p1;
8589702Slinton 	register temp, temp1;
8599702Slinton 	register m;
8609702Slinton 
8619702Slinton 	if( p->in.right ) temp = argsize( p->in.right );
8629702Slinton 	else temp = 0;
8639702Slinton 
8649702Slinton 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
8659702Slinton 		/* set aside room for structure return */
8669702Slinton 
8679702Slinton 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
8689702Slinton 		else temp1 = temp;
8699702Slinton 		}
8709702Slinton 
8719702Slinton 	if( temp > maxargs ) maxargs = temp;
8729702Slinton 	SETOFF(temp1,4);
8739702Slinton 
8749702Slinton 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
87516418Sralph 		genargs( p->in.right );
8769702Slinton 		}
8779702Slinton 
8789702Slinton 	p1 = p->in.left;
8799702Slinton 	if( p1->in.op != ICON ){
8809702Slinton 		if( p1->in.op != REG ){
8819702Slinton 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
8829702Slinton 				if( p1->in.op != NAME ){
8839702Slinton 					order( p1, INAREG );
8849702Slinton 					}
8859702Slinton 				}
8869702Slinton 			}
8879702Slinton 		}
8889702Slinton 
8899702Slinton /*
8909702Slinton 	if( p1->in.op == REG && p->tn.rval == R5 ){
8919702Slinton 		cerror( "call register overwrite" );
8929702Slinton 		}
8939702Slinton  */
8949702Slinton /* tbl
8959702Slinton 	setup gc_numbytes so reference to ZC works */
8969702Slinton 
8979702Slinton 	gc_numbytes = temp&(0x3ff);
8989702Slinton /* tbl */
8999702Slinton 
9009702Slinton 	p->in.op = UNARY CALL;
9019702Slinton 	m = match( p, INTAREG|INTBREG );
9029702Slinton 
9039702Slinton 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
9049702Slinton 	/* (plus in assignment to gc_numbytes above, for neatness only) */
9059702Slinton 	if (temp >= 1024)
9069702Slinton 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
9079702Slinton 
9089702Slinton /* tbl
9099702Slinton 	switch( temp ) {
9109702Slinton 	case 0:
9119702Slinton 		break;
9129702Slinton 	case 2:
9139702Slinton 		printf( "	tst	(sp)+\n" );
9149702Slinton 		break;
9159702Slinton 	case 4:
9169702Slinton 		printf( "	cmp	(sp)+,(sp)+\n" );
9179702Slinton 		break;
9189702Slinton 	default:
9199702Slinton 		printf( "	add	$%d,sp\n", temp);
9209702Slinton 		}
9219702Slinton    tbl */
9229702Slinton 	return(m != MDONE);
9239702Slinton 	}
9249702Slinton 
9259702Slinton /* tbl */
9269702Slinton char *
9279702Slinton ccbranches[] = {
9289702Slinton 	"	jeql	L%d\n",
9299702Slinton 	"	jneq	L%d\n",
9309702Slinton 	"	jleq	L%d\n",
9319702Slinton 	"	jlss	L%d\n",
9329702Slinton 	"	jgeq	L%d\n",
9339702Slinton 	"	jgtr	L%d\n",
9349702Slinton 	"	jlequ	L%d\n",
9359702Slinton 	"	jlssu	L%d\n",
9369702Slinton 	"	jgequ	L%d\n",
9379702Slinton 	"	jgtru	L%d\n",
9389702Slinton 	};
9399702Slinton /* tbl */
9409702Slinton 
9419702Slinton cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
9429702Slinton 
9439702Slinton /* tbl */
9449702Slinton 	if( o == 0 ) printf( "	jbr	L%d\n", lab );
9459702Slinton /* tbl */
9469702Slinton 	else {
9479702Slinton 		if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
9489702Slinton 		printf( ccbranches[o-EQ], lab );
9499702Slinton 		}
9509702Slinton 	}
9519702Slinton 
9529702Slinton nextcook( p, cookie ) NODE *p; {
9539702Slinton 	/* we have failed to match p with cookie; try another */
9549702Slinton 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
9559702Slinton 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
9569702Slinton 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
9579702Slinton 	return( FORREW );
9589702Slinton 	}
9599702Slinton 
9609702Slinton lastchance( p, cook ) NODE *p; {
9619702Slinton 	/* forget it! */
9629702Slinton 	return(0);
9639702Slinton 	}
9649702Slinton 
9659702Slinton optim2( p ) register NODE *p; {
9669702Slinton 	/* do local tree transformations and optimizations */
9679702Slinton 
96816181Sralph 	register NODE *l, *r;
96916181Sralph 	int m, ml;
9709702Slinton 
9719702Slinton 	switch( p->in.op ) {
9729702Slinton 
9739702Slinton 	case AND:
974*19933Smckusick 		/* commute L and R to eliminate complements and constants */
97516181Sralph 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
97616181Sralph 		    l->in.op == COMPL ) {
9779702Slinton 			p->in.left = p->in.right;
97816181Sralph 			p->in.right = l;
9799702Slinton 			}
9809702Slinton 	case ASG AND:
9819702Slinton 		/* change meaning of AND to ~R&L - bic on pdp11 */
9829702Slinton 		r = p->in.right;
983*19933Smckusick 		if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */
9849702Slinton 			r->tn.lval = ~r->tn.lval;
9859702Slinton 			}
9869702Slinton 		else if( r->in.op==COMPL ) { /* ~~A => A */
9879702Slinton 			r->in.op = FREE;
9889702Slinton 			p->in.right = r->in.left;
9899702Slinton 			}
9909702Slinton 		else { /* insert complement node */
99116181Sralph 			p->in.right = l = talloc();
99216181Sralph 			l->in.op = COMPL;
99316181Sralph 			l->in.rall = NOPREF;
99416181Sralph 			l->in.type = r->in.type;
99516181Sralph 			l->in.left = r;
99616181Sralph 			l->in.right = NULL;
9979702Slinton 			}
9989702Slinton 		break;
9999702Slinton 
100016181Sralph 	case SCONV:
1001*19933Smckusick 		l = p->in.left;
100217742Sralph #if defined(FORT) || defined(SPRECC)
100316573Sralph 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
1004*19933Smckusick 		    l->in.type == FLOAT || l->in.type == DOUBLE )
1005*19933Smckusick 			return;
100616573Sralph #else
1007*19933Smckusick 		if( mixtypes(p, l) ) return;
100816573Sralph #endif
1009*19933Smckusick 		/* Only trust it to get it right if the size is the same */
1010*19933Smckusick 		if( tlen(p) != tlen(l) )
1011*19933Smckusick 			return;
101216181Sralph 
101316181Sralph 		/* clobber conversion */
1014*19933Smckusick 		if( l->in.op != FLD )
101516181Sralph 			l->in.type = p->in.type;
101616181Sralph 		ncopy( p, l );
101716181Sralph 		l->in.op = FREE;
1018*19933Smckusick 
101916181Sralph 		break;
102016181Sralph 
10219702Slinton 		}
10229702Slinton 	}
10239702Slinton 
102417742Sralph NODE * addroreg(l) NODE *l;
10259702Slinton 				/* OREG was built in clocal()
10269702Slinton 				 * for an auto or formal parameter
10279702Slinton 				 * now its address is being taken
10289702Slinton 				 * local code must unwind it
10299702Slinton 				 * back to PLUS/MINUS REG ICON
10309702Slinton 				 * according to local conventions
10319702Slinton 				 */
10329702Slinton {
10339702Slinton 	cerror("address of OREG taken");
103417742Sralph 	/*NOTREACHED*/
10359702Slinton }
10369702Slinton 
10379702Slinton 
10389702Slinton 
10399702Slinton # ifndef ONEPASS
10409702Slinton main( argc, argv ) char *argv[]; {
10419702Slinton 	return( mainp2( argc, argv ) );
10429702Slinton 	}
10439702Slinton # endif
10449702Slinton 
10459702Slinton 
10469702Slinton /* added by jwf */
10479702Slinton struct functbl {
10489702Slinton 	int fop;
10499702Slinton 	TWORD ftype;
10509702Slinton 	char *func;
10519702Slinton 	} opfunc[] = {
10529702Slinton 	DIV,		TANY,	"udiv",
10539702Slinton 	MOD,		TANY,	"urem",
105417715Sralph 	ASG DIV,	TANY,	"audiv",
105517715Sralph 	ASG MOD,	TANY,	"aurem",
10569702Slinton 	0,	0,	0 };
10579702Slinton 
10589702Slinton hardops(p)  register NODE *p; {
10599702Slinton 	/* change hard to do operators into function calls.  */
10609702Slinton 	register NODE *q;
10619702Slinton 	register struct functbl *f;
10629702Slinton 	register o;
106317742Sralph 	NODE *old,*temp;
10649702Slinton 
10659702Slinton 	o = p->in.op;
106617742Sralph 	if( ! (optype(o)==BITYPE &&
106717742Sralph 	       (ISUNSIGNED(p->in.left->in.type) ||
106817742Sralph 		ISUNSIGNED(p->in.right->in.type))) )
106917742Sralph 		return;
10709702Slinton 
10719702Slinton 	for( f=opfunc; f->fop; f++ ) {
10729702Slinton 		if( o==f->fop ) goto convert;
10739702Slinton 		}
10749702Slinton 	return;
10759702Slinton 
10769702Slinton 	convert:
10779702Slinton 	if( asgop( o ) ) {
107817742Sralph 		old = NIL;
107917715Sralph 		switch( p->in.left->in.op ){
108017742Sralph 		case FLD:
108117742Sralph 			q = p->in.left->in.left;
108217742Sralph 			/*
108317742Sralph 			 * rewrite (lval.fld /= rval); as
108417742Sralph 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
108517742Sralph 			 * else the compiler will evaluate lval twice.
108617742Sralph 			 */
108717742Sralph 			if( q->in.op == UNARY MUL ){
108817742Sralph 				/* first allocate a temp storage */
108917742Sralph 				temp = talloc();
109017742Sralph 				temp->in.op = OREG;
109117742Sralph 				temp->tn.rval = TMPREG;
109217742Sralph 				temp->tn.lval = BITOOR(freetemp(1));
109317742Sralph 				temp->in.type = INCREF(p->in.type);
109417742Sralph #ifdef FLEXNAMES
109517742Sralph 				temp->in.name = "";
109617742Sralph #else
109717742Sralph 				temp->in.name[0] = '\0';
109817742Sralph #endif
109917742Sralph 				old = q->in.left;
110017742Sralph 				q->in.left = temp;
110117742Sralph 			}
110217742Sralph 			/* fall thru ... */
110317742Sralph 
110417715Sralph 		case REG:
110517715Sralph 		case NAME:
110617715Sralph 		case OREG:
110717715Sralph 			/* change ASG OP to a simple OP */
110817715Sralph 			q = talloc();
110917715Sralph 			q->in.op = NOASG p->in.op;
111017715Sralph 			q->in.rall = NOPREF;
111117715Sralph 			q->in.type = p->in.type;
111217715Sralph 			q->in.left = tcopy(p->in.left);
111317715Sralph 			q->in.right = p->in.right;
111417715Sralph 			p->in.op = ASSIGN;
111517715Sralph 			p->in.right = q;
111617715Sralph 			p = q;
111717715Sralph 			f -= 2; /* Note: this depends on the table order */
111817742Sralph 			/* on the right side only - replace *temp with
111917742Sralph 			 *(temp = &lval), build the assignment node */
112017742Sralph 			if( old ){
112117742Sralph 				temp = q->in.left->in.left; /* the "*" node */
112217742Sralph 				q = talloc();
112317742Sralph 				q->in.op = ASSIGN;
112417742Sralph 				q->in.left = temp->in.left;
112517742Sralph 				q->in.right = old;
112617742Sralph 				q->in.type = old->in.type;
112717742Sralph #ifdef FLEXNAMES
112817742Sralph 				q->in.name = "";
112917742Sralph #else
113017742Sralph 				q->in.name[0] = '\0';
113117742Sralph #endif
113217742Sralph 				temp->in.left = q;
113317742Sralph 			}
113417715Sralph 			break;
11359702Slinton 
113617715Sralph 		case UNARY MUL:
113717715Sralph 			/* avoid doing side effects twice */
113817715Sralph 			q = p->in.left;
113917715Sralph 			p->in.left = q->in.left;
114017715Sralph 			q->in.op = FREE;
114117715Sralph 			break;
114217715Sralph 
114317715Sralph 		default:
114417715Sralph 			cerror( "hardops: can't compute & LHS" );
114517715Sralph 			}
114617742Sralph 		}
114717715Sralph 
11489702Slinton 	/* build comma op for args to function */
11499702Slinton 	q = talloc();
11509702Slinton 	q->in.op = CM;
11519702Slinton 	q->in.rall = NOPREF;
11529702Slinton 	q->in.type = INT;
11539702Slinton 	q->in.left = p->in.left;
11549702Slinton 	q->in.right = p->in.right;
11559702Slinton 	p->in.op = CALL;
11569702Slinton 	p->in.right = q;
11579702Slinton 
11589702Slinton 	/* put function name in left node of call */
11599702Slinton 	p->in.left = q = talloc();
11609702Slinton 	q->in.op = ICON;
11619702Slinton 	q->in.rall = NOPREF;
11629702Slinton 	q->in.type = INCREF( FTN + p->in.type );
11639702Slinton #ifndef FLEXNAMES
11649702Slinton 	strcpy( q->in.name, f->func );
11659702Slinton #else
11669702Slinton 	q->in.name = f->func;
11679702Slinton #endif
11689702Slinton 	q->tn.lval = 0;
11699702Slinton 	q->tn.rval = 0;
11709702Slinton 
11719702Slinton 	}
11729702Slinton 
117317742Sralph zappost(p) NODE *p; {
117417742Sralph 	/* look for ++ and -- operators and remove them */
117517742Sralph 
117617742Sralph 	register o, ty;
117717742Sralph 	register NODE *q;
117817742Sralph 	o = p->in.op;
117917742Sralph 	ty = optype( o );
118017742Sralph 
118117742Sralph 	switch( o ){
118217742Sralph 
118317742Sralph 	case INCR:
118417742Sralph 	case DECR:
118517742Sralph 			q = p->in.left;
118617742Sralph 			p->in.right->in.op = FREE;  /* zap constant */
118717742Sralph 			ncopy( p, q );
118817742Sralph 			q->in.op = FREE;
118917742Sralph 			return;
119017742Sralph 
119117742Sralph 		}
119217742Sralph 
119317742Sralph 	if( ty == BITYPE ) zappost( p->in.right );
119417742Sralph 	if( ty != LTYPE ) zappost( p->in.left );
119517742Sralph }
119617742Sralph 
119717742Sralph fixpre(p) NODE *p; {
119817742Sralph 
119917742Sralph 	register o, ty;
120017742Sralph 	o = p->in.op;
120117742Sralph 	ty = optype( o );
120217742Sralph 
120317742Sralph 	switch( o ){
120417742Sralph 
120517742Sralph 	case ASG PLUS:
120617742Sralph 			p->in.op = PLUS;
120717742Sralph 			break;
120817742Sralph 	case ASG MINUS:
120917742Sralph 			p->in.op = MINUS;
121017742Sralph 			break;
121117742Sralph 		}
121217742Sralph 
121317742Sralph 	if( ty == BITYPE ) fixpre( p->in.right );
121417742Sralph 	if( ty != LTYPE ) fixpre( p->in.left );
121517742Sralph }
121617742Sralph 
12179702Slinton myreader(p) register NODE *p; {
121817742Sralph 	canon( p );		/* expands r-vals for fields */
12199702Slinton 	walkf( p, hardops );	/* convert ops to function calls */
12209702Slinton 	walkf( p, optim2 );
12219702Slinton 	/* jwf toff = 0;  /* stack offset swindle */
12229702Slinton 	}
1223