xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 32937)
117742Sralph # ifndef lint
2*32937Sdonn static char *sccsid ="@(#)local2.c	1.31 (Berkeley) 12/11/87";
317742Sralph # endif
417742Sralph 
518556Sralph # include "pass2.h"
632935Sdonn # include <ctype.h>
732935Sdonn 
832935Sdonn # define putstr(s)	fputs((s), stdout)
932935Sdonn 
109702Slinton # ifdef FORT
119702Slinton int ftlab1, ftlab2;
129702Slinton # endif
139702Slinton /* a lot of the machine dependent parts of the second pass */
149702Slinton 
159702Slinton # define BITMASK(n) ((1L<<n)-1)
169702Slinton 
1732924Sdonn /*ARGSUSED*/
189702Slinton where(c){
199702Slinton 	fprintf( stderr, "%s, line %d: ", filename, lineno );
209702Slinton 	}
219702Slinton 
229702Slinton lineid( l, fn ) char *fn; {
239702Slinton 	/* identify line l and file fn */
249702Slinton 	printf( "#	line %d, file %s\n", l, fn );
259702Slinton 	}
269702Slinton 
279702Slinton 
289702Slinton eobl2(){
2932935Sdonn 	register OFFSZ spoff;	/* offset from stack pointer */
3032935Sdonn #ifndef FORT
3132935Sdonn 	extern int ftlab1, ftlab2;
3232935Sdonn #endif
3332935Sdonn 
349702Slinton 	spoff = maxoff;
359702Slinton 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
369702Slinton 	spoff /= SZCHAR;
379702Slinton 	SETOFF(spoff,4);
3832935Sdonn #ifdef FORT
399702Slinton #ifndef FLEXNAMES
409702Slinton 	printf( "	.set	.F%d,%ld\n", ftnno, spoff );
419702Slinton #else
429702Slinton 	/* SHOULD BE L%d ... ftnno but must change pc/f77 */
439702Slinton 	printf( "	.set	LF%d,%ld\n", ftnno, spoff );
449702Slinton #endif
459702Slinton #else
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 	PLUS,	"add",
609702Slinton 	MINUS,	"sub",
619702Slinton 	MUL,	"mul",
629702Slinton 	DIV,	"div",
639702Slinton 	OR,	"bis",
649702Slinton 	ER,	"xor",
659702Slinton 	AND,	"bic",
669702Slinton 	-1, ""    };
679702Slinton 
689702Slinton hopcode( f, o ){
699702Slinton 	/* output the appropriate string from the above table */
709702Slinton 
719702Slinton 	register struct hoptab *q;
729702Slinton 
7332935Sdonn 	if(asgop(o))
7432935Sdonn 		o = NOASG o;
759702Slinton 	for( q = ioptab;  q->opmask>=0; ++q ){
769702Slinton 		if( q->opmask == o ){
7732935Sdonn 			printf( "%s%c", q->opstring, tolower(f));
789702Slinton 			return;
799702Slinton 			}
809702Slinton 		}
819702Slinton 	cerror( "no hoptab for %s", opst[o] );
829702Slinton 	}
839702Slinton 
849702Slinton char *
859702Slinton rnames[] = {  /* keyed to register number tokens */
869702Slinton 
879702Slinton 	"r0", "r1",
889702Slinton 	"r2", "r3", "r4", "r5",
899702Slinton 	"r6", "r7", "r8", "r9", "r10", "r11",
909702Slinton 	"ap", "fp", "sp", "pc",
919702Slinton 	};
929702Slinton 
939702Slinton int rstatus[] = {
949702Slinton 	SAREG|STAREG, SAREG|STAREG,
959702Slinton 	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
969702Slinton 	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
979702Slinton 	SAREG, SAREG, SAREG, SAREG,
989702Slinton 	};
999702Slinton 
1009702Slinton tlen(p) NODE *p;
1019702Slinton {
1029702Slinton 	switch(p->in.type) {
1039702Slinton 		case CHAR:
1049702Slinton 		case UCHAR:
1059702Slinton 			return(1);
1069702Slinton 
1079702Slinton 		case SHORT:
1089702Slinton 		case USHORT:
109*32937Sdonn 			return(SZSHORT/SZCHAR);
1109702Slinton 
1119702Slinton 		case DOUBLE:
112*32937Sdonn 			return(SZDOUBLE/SZCHAR);
1139702Slinton 
1149702Slinton 		default:
115*32937Sdonn 			return(SZINT/SZCHAR);
1169702Slinton 		}
1179702Slinton }
1189702Slinton 
1199702Slinton mixtypes(p, q) NODE *p, *q;
1209702Slinton {
12116181Sralph 	register TWORD tp, tq;
1229702Slinton 
1239702Slinton 	tp = p->in.type;
1249702Slinton 	tq = q->in.type;
1259702Slinton 
1269702Slinton 	return( (tp==FLOAT || tp==DOUBLE) !=
1279702Slinton 		(tq==FLOAT || tq==DOUBLE) );
1289702Slinton }
1299702Slinton 
1309702Slinton prtype(n) NODE *n;
1319702Slinton {
1329702Slinton 	switch (n->in.type)
1339702Slinton 		{
13432935Sdonn 
1359702Slinton 		case DOUBLE:
13624418Smckusick 			putchar('d');
1379702Slinton 			return;
1389702Slinton 
1399702Slinton 		case FLOAT:
14024418Smckusick 			putchar('f');
1419702Slinton 			return;
1429702Slinton 
1439702Slinton 		case LONG:
1449702Slinton 		case ULONG:
1459702Slinton 		case INT:
1469702Slinton 		case UNSIGNED:
14724418Smckusick 			putchar('l');
1489702Slinton 			return;
1499702Slinton 
1509702Slinton 		case SHORT:
1519702Slinton 		case USHORT:
15224418Smckusick 			putchar('w');
1539702Slinton 			return;
1549702Slinton 
1559702Slinton 		case CHAR:
1569702Slinton 		case UCHAR:
15724418Smckusick 			putchar('b');
1589702Slinton 			return;
1599702Slinton 
1609702Slinton 		default:
1619702Slinton 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
1629702Slinton 			else {
16324418Smckusick 				putchar('l');
1649702Slinton 				return;
1659702Slinton 				}
1669702Slinton 		}
1679702Slinton }
1689702Slinton 
1699702Slinton zzzcode( p, c ) register NODE *p; {
17032935Sdonn 	register int m;
17132924Sdonn 	int val;
1729702Slinton 	switch( c ){
1739702Slinton 
1749702Slinton 	case 'N':  /* logical ops, turned into 0-1 */
1759702Slinton 		/* use register given by register 1 */
1769702Slinton 		cbgen( 0, m=getlab(), 'I' );
1779702Slinton 		deflab( p->bn.label );
1789702Slinton 		printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );
1799702Slinton 		deflab( m );
1809702Slinton 		return;
1819702Slinton 
1829702Slinton 	case 'P':
1839702Slinton 		cbgen( p->in.op, p->bn.label, c );
1849702Slinton 		return;
1859702Slinton 
1869702Slinton 	case 'A':
18732935Sdonn 	case 'V':
18832935Sdonn 		sconv( p, c == 'V' );
1899702Slinton 		return;
1909702Slinton 
19125751Sdonn 	case 'G':	/* i *= f; asgops with int lhs and float rhs */
19225751Sdonn 		{
19325751Sdonn 		register NODE *l, *r, *s;
19425751Sdonn 		int rt;
19525751Sdonn 
19625751Sdonn 		l = p->in.left;
19725751Sdonn 		r = p->in.right;
19825751Sdonn 		s = talloc();
19925751Sdonn 		rt = r->in.type;
20025751Sdonn 
20125751Sdonn 		s->in.op = SCONV;
20225751Sdonn 		s->in.left = l;
20325751Sdonn 		s->in.type = rt;
20425751Sdonn 		zzzcode(s, 'A');
20525751Sdonn 		putstr("\n\t");
20625751Sdonn 
20725751Sdonn 		hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
20825751Sdonn 		putstr("2\t");
20925751Sdonn 		adrput(r);
21025751Sdonn 		putchar(',');
21125751Sdonn 		adrput(resc);
21225751Sdonn 		putstr("\n\t");
21325751Sdonn 
21425751Sdonn 		s->in.op = ASSIGN;
21525751Sdonn 		s->in.left = l;
21625751Sdonn 		s->in.right = resc;
21725751Sdonn 		s->in.type = l->in.type;
21825751Sdonn 		zzzcode(s, 'A');
21925751Sdonn 
22025751Sdonn 		s->in.op = FREE;
22125751Sdonn 		return;
22225751Sdonn 		}
22325751Sdonn 
22432928Sdonn 	case 'J':	/* unsigned DIV/MOD with constant divisors */
22532928Sdonn 		{
22632928Sdonn 		register int ck = INAREG;
22732928Sdonn 		int label1, label2;
22832928Sdonn 
22932928Sdonn 		/* case constant <= 1 is handled by optim() in pass 1 */
23032928Sdonn 		/* case constant < 0x80000000 is handled in table */
23132928Sdonn 		switch( p->in.op ) {
23232928Sdonn 		/* case DIV: handled in hardops() */
23332928Sdonn 		case MOD:
23432928Sdonn 			if( p->in.left->in.op == REG &&
23532928Sdonn 			    p->in.left->tn.rval == resc->tn.rval )
23632928Sdonn 				goto asgmod;
23732928Sdonn 			label1 = getlab();
23832928Sdonn 			expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n");
23932928Sdonn 			printf("\tjlssu\tL%d\n", label1);
24032928Sdonn 			expand(p, ck, "\tsubl2\tAR,A1\n");
24132928Sdonn 			printf("L%d:", label1);
24232928Sdonn 			break;
24332928Sdonn 		case ASG DIV:
24432928Sdonn 			label1 = getlab();
24532928Sdonn 			label2 = getlab();
24632928Sdonn 			expand(p, ck, "cmpl\tAL,AR\n");
24732928Sdonn 			printf("\tjgequ\tL%d\n", label1);
24832928Sdonn 			expand(p, ck, "\tmovl\t$1,AL\n");
24932928Sdonn 			printf("\tjbr\tL%d\nL%d:\n", label2, label1);
25032928Sdonn 			expand(p, ck, "\tclrl\tAL\n");
25132928Sdonn 			printf("L%d:", label2);
25232928Sdonn 			break;
25332928Sdonn 		case ASG MOD:
25432928Sdonn 		asgmod:
25532928Sdonn 			label1 = getlab();
25632928Sdonn 			expand(p, ck, "cmpl\tAL,AR\n");
25732928Sdonn 			printf("\tjlssu\tL%d\n", label1);
25832928Sdonn 			expand(p, ck, "\tsubl2\tAR,AL\n");
25932928Sdonn 			printf("L%d:", label1);
26032928Sdonn 			break;
26132928Sdonn 			}
26232928Sdonn 		return;
26332928Sdonn 		}
26432928Sdonn 
2659702Slinton 	case 'B':	/* get oreg value in temp register for left shift */
2669702Slinton 		{
2679702Slinton 		register NODE *r;
2689702Slinton 		if (xdebug) eprint(p, 0, &val, &val);
2699702Slinton 		r = p->in.right;
270*32937Sdonn 		if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT )
27124418Smckusick 			putstr("movl");
2729702Slinton 		else {
27332935Sdonn 			putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
2749702Slinton 			prtype(r);
27524418Smckusick 			putchar('l');
2769702Slinton 			}
2779702Slinton 		return;
2789702Slinton 		}
2799702Slinton 
2809702Slinton 	case 'C':	/* num words pushed on arg stack */
2819702Slinton 		{
2829702Slinton 		extern int gc_numbytes;
2839702Slinton 		extern int xdebug;
2849702Slinton 
2859702Slinton 		if (xdebug) printf("->%d<-",gc_numbytes);
2869702Slinton 
2879702Slinton 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
2889702Slinton 		return;
2899702Slinton 		}
2909702Slinton 
2919702Slinton 	case 'D':	/* INCR and DECR */
2929702Slinton 		zzzcode(p->in.left, 'A');
29324418Smckusick 		putchar('\n');
29424418Smckusick 		putchar('\t');
2959702Slinton 
2969702Slinton 	case 'E':	/* INCR and DECR, FOREFF */
29732934Sdonn 		if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1)
2989702Slinton 			{
29932935Sdonn 			putstr(p->in.op == INCR ? "inc" : "dec");
3009702Slinton 			prtype(p->in.left);
30124418Smckusick 			putchar('\t');
3029702Slinton 			adrput(p->in.left);
3039702Slinton 			return;
3049702Slinton 			}
30532935Sdonn 		putstr(p->in.op == INCR ? "add" : "sub");
3069702Slinton 		prtype(p->in.left);
30724418Smckusick 		putchar('2');
30824418Smckusick 		putchar('\t');
3099702Slinton 		adrput(p->in.right);
31024418Smckusick 		putchar(',');
3119702Slinton 		adrput(p->in.left);
3129702Slinton 		return;
3139702Slinton 
3149702Slinton 	case 'F':	/* register type of right operand */
3159702Slinton 		{
3169702Slinton 		register NODE *n;
3179702Slinton 		extern int xdebug;
3189702Slinton 		register int ty;
3199702Slinton 
3209702Slinton 		n = getlr( p, 'R' );
3219702Slinton 		ty = n->in.type;
3229702Slinton 
3239702Slinton 		if (xdebug) printf("->%d<-", ty);
3249702Slinton 
32524418Smckusick 		if ( ty==DOUBLE) putchar('d');
32624418Smckusick 		else if ( ty==FLOAT ) putchar('f');
32724418Smckusick 		else putchar('l');
3289702Slinton 		return;
3299702Slinton 		}
3309702Slinton 
3319702Slinton 	case 'L':	/* type of left operand */
3329702Slinton 	case 'R':	/* type of right operand */
3339702Slinton 		{
3349702Slinton 		register NODE *n;
3359702Slinton 		extern int xdebug;
3369702Slinton 
33716181Sralph 		n = getlr( p, c );
3389702Slinton 		if (xdebug) printf("->%d<-", n->in.type);
3399702Slinton 
3409702Slinton 		prtype(n);
3419702Slinton 		return;
3429702Slinton 		}
3439702Slinton 
3449702Slinton 	case 'Z':	/* complement mask for bit instr */
3459702Slinton 		printf("$%ld", ~p->in.right->tn.lval);
3469702Slinton 		return;
3479702Slinton 
3489702Slinton 	case 'U':	/* 32 - n, for unsigned right shifts */
3499702Slinton 		printf("$%d", 32 - p->in.right->tn.lval );
3509702Slinton 		return;
3519702Slinton 
3529702Slinton 	case 'T':	/* rounded structure length for arguments */
3539702Slinton 		{
3549702Slinton 		int size;
3559702Slinton 
3569702Slinton 		size = p->stn.stsize;
3579702Slinton 		SETOFF( size, 4);
3589702Slinton 		printf("$%d", size);
3599702Slinton 		return;
3609702Slinton 		}
3619702Slinton 
3629702Slinton 	case 'S':  /* structure assignment */
36332935Sdonn 		stasg(p);
36432935Sdonn 		break;
3659702Slinton 
36632935Sdonn 	default:
36732935Sdonn 		cerror( "illegal zzzcode" );
36832935Sdonn 		}
36932935Sdonn 	}
3709702Slinton 
37132935Sdonn stasg(p)
37232935Sdonn 	register NODE *p;
37332935Sdonn {
37432935Sdonn 	register NODE *l, *r;
37532935Sdonn 	register size;
3769702Slinton 
37732935Sdonn 	if( p->in.op == STASG ){
37832935Sdonn 		l = p->in.left;
37932935Sdonn 		r = p->in.right;
3809702Slinton 
38132935Sdonn 		}
38232935Sdonn 	else if( p->in.op == STARG ){  /* store an arg into a temporary */
38332935Sdonn 		r = p->in.left;
38432935Sdonn 		}
38532935Sdonn 	else cerror( "STASG bad" );
3869702Slinton 
38732935Sdonn 	if( r->in.op == ICON ) r->in.op = NAME;
38832935Sdonn 	else if( r->in.op == REG ) r->in.op = OREG;
38932935Sdonn 	else if( r->in.op != OREG ) cerror( "STASG-r" );
3909702Slinton 
39132935Sdonn 	size = p->stn.stsize;
39232935Sdonn 
39332935Sdonn 	if( size <= 0 || size > 65535 )
39432935Sdonn 		cerror("structure size <0=0 or >65535");
39532935Sdonn 
39632935Sdonn 	switch(size) {
39732935Sdonn 		case 1:
39832935Sdonn 			putstr("	movb	");
39932935Sdonn 			break;
40032935Sdonn 		case 2:
40132935Sdonn 			putstr("	movw	");
40232935Sdonn 			break;
40332935Sdonn 		case 4:
40432935Sdonn 			putstr("	movl	");
40532935Sdonn 			break;
40632935Sdonn 		case 8:
40732935Sdonn 			putstr("	movq	");
40832935Sdonn 			break;
40932935Sdonn 		default:
41032935Sdonn 			printf("	movc3	$%d,", size);
41132935Sdonn 			break;
41232935Sdonn 	}
41332935Sdonn 	adrput(r);
41432935Sdonn 	if( p->in.op == STASG ){
41532935Sdonn 		putchar(',');
41632935Sdonn 		adrput(l);
41732935Sdonn 		putchar('\n');
41832935Sdonn 		}
41932935Sdonn 	else
42032935Sdonn 		putstr(",(sp)\n");
42132935Sdonn 
42232935Sdonn 	if( r->in.op == NAME ) r->in.op = ICON;
42332935Sdonn 	else if( r->in.op == OREG ) r->in.op = REG;
42432935Sdonn 	}
42532935Sdonn 
42632935Sdonn NODE *makearg( ty ) int ty; {
42732935Sdonn 	register NODE *p, *q;
42832935Sdonn 
42932935Sdonn 	/* build a -(sp) operand */
43032935Sdonn 	p = talloc();
43132935Sdonn 	p->in.op = REG;
43232935Sdonn 	/* the type needn't be right, just consistent */
43332935Sdonn 	p->in.type = INCREF(ty);
43432935Sdonn 	p->tn.rval = SP;
43532935Sdonn 	p->tn.lval = 0;
43632935Sdonn 	q = talloc();
43732935Sdonn 	q->in.op = ASG MINUS;
43832935Sdonn 	q->in.type = INCREF(ty);
43932935Sdonn 	q->in.left = p;
44032935Sdonn 	p = talloc();
44132935Sdonn 	p->in.op = ICON;
44232935Sdonn 	p->in.type = INT;
44332935Sdonn 	p->tn.name = "";
44432935Sdonn 	p->tn.lval = tlen(ty);
44532935Sdonn 	q->in.right = p;
44632935Sdonn 	p = talloc();
44732935Sdonn 	p->in.op = UNARY MUL;
44832935Sdonn 	p->in.left = q;
44932935Sdonn 	return( p );
45032935Sdonn 	}
45132935Sdonn 
45232935Sdonn sconv( p, forarg ) register NODE *p; {
45332935Sdonn 	register NODE *l, *r;
45432935Sdonn 	int m, val;
45532935Sdonn 
45632935Sdonn 	if (xdebug) eprint(p, 0, &val, &val);
45732935Sdonn 	r = getlr(p, 'R');
45832935Sdonn 	if (p->in.op == ASSIGN)
45932935Sdonn 		l = getlr(p, 'L');
46032935Sdonn 	else if (p->in.op == SCONV) {
46132935Sdonn #if defined(FORT) || defined(SPRECC)
46232935Sdonn 		m = r->in.type;
46332935Sdonn #else
46432935Sdonn 		m = r->in.type==FLOAT ? DOUBLE : r->in.type;
46532935Sdonn #endif
46632935Sdonn 		if (forarg)
46732935Sdonn 			l = makearg( m );
46832935Sdonn 		else
46932935Sdonn 			l = resc;
47032935Sdonn 		l->in.type = m;
47132935Sdonn 		r = getlr(p, 'L');
47232935Sdonn 		}
47332935Sdonn 	else {		/* OPLTYPE */
47432935Sdonn #if defined(FORT) || defined(SPRECC)
47532935Sdonn 		m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
47632935Sdonn #else
47732935Sdonn 		m = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
47832935Sdonn #endif
47932935Sdonn 		if (forarg)
48032935Sdonn 			l = makearg( m );
48132935Sdonn 		else
48232935Sdonn 			l = resc;
48332935Sdonn 		l->in.type = m;
48432935Sdonn 		}
48532935Sdonn 	if (r->in.op == ICON)
48632935Sdonn 		if (r->in.name[0] == '\0') {
48732935Sdonn 			if (r->tn.lval == 0) {
48832935Sdonn 				putstr("clr");
48932935Sdonn 				prtype(l);
49032935Sdonn 				putchar('\t');
49116418Sralph 				adrput(l);
49232935Sdonn 				goto cleanup;
49316418Sralph 				}
49432935Sdonn 			if (r->tn.lval < 0 && r->tn.lval >= -63) {
49532935Sdonn 				putstr("mneg");
49632935Sdonn 				prtype(l);
49732935Sdonn 				r->tn.lval = -r->tn.lval;
49832935Sdonn 				goto ops;
49932935Sdonn 				}
50032935Sdonn 			if (r->tn.lval < 0)
50132935Sdonn 				r->in.type = r->tn.lval >= -128 ? CHAR
50232935Sdonn 					: (r->tn.lval >= -32768 ? SHORT
50332935Sdonn 					: INT);
50432935Sdonn 			else if (l->in.type == FLOAT ||
50532935Sdonn 			    l->in.type == DOUBLE)
50632935Sdonn 				r->in.type = r->tn.lval <= 63 ? INT
50732935Sdonn 					: (r->tn.lval <= 127 ? CHAR
50832935Sdonn 					: (r->tn.lval <= 32767 ? SHORT
50932935Sdonn 					: INT));
51016418Sralph 			else
51132935Sdonn 				r->in.type = r->tn.lval <= 63 ? INT
51232935Sdonn 					: (r->tn.lval <= 127 ? CHAR
51332935Sdonn 					: (r->tn.lval <= 255 ? UCHAR
51432935Sdonn 					: (r->tn.lval <= 32767 ? SHORT
51532935Sdonn 					: (r->tn.lval <= 65535 ? USHORT
51632935Sdonn 					: INT))));
51732935Sdonn 			}
51832935Sdonn 		else {
51932935Sdonn 			putstr("moval");
52032935Sdonn 			putchar('\t');
52132935Sdonn 			acon(r);
52232935Sdonn 			putchar(',');
52332935Sdonn 			adrput(l);
52432935Sdonn 			goto cleanup;
52532935Sdonn 			}
5269702Slinton 
52732935Sdonn 	if (p->in.op == SCONV &&
52832935Sdonn 	    !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
52932935Sdonn 	    !mixtypes(l, r)) {
53032935Sdonn 		/*
53132935Sdonn 		 * Because registers must always contain objects
53232935Sdonn 		 * of the same width as INTs, we may have to
53332935Sdonn 		 * perform two conversions to get an INT.  Can
53432935Sdonn 		 * the conversions be collapsed into one?
53532935Sdonn 		 */
53632935Sdonn 		if (m = collapsible(l, r))
53732935Sdonn 			r->in.type = m;
53832935Sdonn 		else {
53932935Sdonn 			/*
54032935Sdonn 			 * Two steps are required.
54132935Sdonn 			 */
54232935Sdonn 			NODE *x = &resc[1];
5439702Slinton 
54432935Sdonn 			*x = *l;
54532935Sdonn 			if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
54632935Sdonn 				putstr("movz");
54732935Sdonn 			else
54832935Sdonn 				putstr("cvt");
54932935Sdonn 			prtype(r);
55032935Sdonn 			prtype(x);
55132935Sdonn 			putchar('\t');
55232935Sdonn 			adrput(r);
55332935Sdonn 			putchar(',');
55432935Sdonn 			adrput(x);
55532935Sdonn 			putchar('\n');
55632935Sdonn 			putchar('\t');
55732935Sdonn 			r = x;
5589702Slinton 			}
55932935Sdonn 		l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
56032935Sdonn 		}
5619702Slinton 
56232935Sdonn 	if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
56332935Sdonn 	    mixtypes(l, r)) {
56432935Sdonn 		int label1, label2;
56532935Sdonn 
56632935Sdonn 		label1 = getlab();
56732935Sdonn 		label2 = getlab();
56832935Sdonn 
56932935Sdonn 		putstr("movl\t");
57032935Sdonn 		adrput(r);
57132935Sdonn 		putchar(',');
57232935Sdonn 		adrput(l);
57332935Sdonn 		putstr("\n\tjbsc\t$31,");
57432935Sdonn 		adrput(l);
57532935Sdonn 		printf(",L%d\n\tcvtl", label1);
57632935Sdonn 		prtype(l);
57732935Sdonn 		putchar('\t');
57832935Sdonn 		adrput(l);
57932935Sdonn 		putchar(',');
58032935Sdonn 		adrput(l);
58132935Sdonn 		printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1);
58232935Sdonn 		prtype(l);
58332935Sdonn 		putchar('\t');
58432935Sdonn 		adrput(l);
58532935Sdonn 		putchar(',');
58632935Sdonn 		adrput(l);
58732935Sdonn 		putstr("\n\tadd");
58832935Sdonn 		prtype(l);
58932935Sdonn 		putstr("2\t$0");
59032935Sdonn 		prtype(l);
59132935Sdonn 		putstr("2.147483648e9,");
59232935Sdonn 		adrput(l);
59332935Sdonn 		printf("\nL%d:", label2);
59432935Sdonn 
59532935Sdonn 		goto cleanup;
5969702Slinton 		}
59732935Sdonn 
59832935Sdonn 	if (!mixtypes(l,r)) {
59932935Sdonn 		if (tlen(l) == tlen(r)) {
60032935Sdonn 			putstr("mov");
60132935Sdonn #ifdef FORT
60232935Sdonn 			if (Oflag)
60332935Sdonn 				prtype(l);
60432935Sdonn 			else {
60532935Sdonn 				if (l->in.type == DOUBLE)
60632935Sdonn 					putchar('q');
60732935Sdonn 				else if(l->in.type == FLOAT)
60832935Sdonn 					putchar('l');
60932935Sdonn 				else
61032935Sdonn 					prtype(l);
61132935Sdonn 				}
61232935Sdonn #else
61332935Sdonn 			prtype(l);
61432935Sdonn #endif FORT
61532935Sdonn 			goto ops;
61632935Sdonn 			}
61732935Sdonn 		else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
61832935Sdonn 			putstr("movz");
61932935Sdonn 		else
62032935Sdonn 			putstr("cvt");
62132935Sdonn 		}
62232935Sdonn 	else
62332935Sdonn 		putstr("cvt");
62432935Sdonn 	prtype(r);
62532935Sdonn 	prtype(l);
62632935Sdonn ops:
62732935Sdonn 	putchar('\t');
62832935Sdonn 	adrput(r);
62932935Sdonn 	putchar(',');
63032935Sdonn 	adrput(l);
63132935Sdonn 
63232935Sdonn cleanup:
63332935Sdonn 	if (forarg)
63432935Sdonn 		tfree(l);
6359702Slinton 	}
6369702Slinton 
63723536Sbloom /*
63823536Sbloom  * collapsible(dest, src) -- if a conversion with a register destination
63923536Sbloom  *	can be accomplished in one instruction, return the type of src
64023536Sbloom  *	that will do the job correctly; otherwise return 0.  Note that
64123536Sbloom  *	a register must always end up having type INT or UNSIGNED.
64223536Sbloom  */
64323536Sbloom int
64423536Sbloom collapsible(dest, src)
64523536Sbloom NODE *dest, *src;
64623536Sbloom {
64723536Sbloom 	int st = src->in.type;
64823536Sbloom 	int dt = dest->in.type;
64923536Sbloom 	int newt = 0;
65023536Sbloom 
65123536Sbloom 	/*
65223536Sbloom 	 * Are there side effects of evaluating src?
65323536Sbloom 	 * If the derived type will not be the same size as src,
65424418Smckusick 	 * we may have to use two steps.
65523536Sbloom 	 */
65624418Smckusick 	if (tlen(src) > tlen(dest)) {
65724418Smckusick 		if (tshape(src, STARREG))
65824418Smckusick 			return (0);
65924418Smckusick 		if (src->in.op == OREG && R2TEST(src->tn.rval))
66024418Smckusick 			return (0);
66124418Smckusick 		}
66223536Sbloom 
66323536Sbloom 	/*
66423536Sbloom 	 * Can we get an object of dest's type by punning src?
66523536Sbloom 	 * Praises be to great Cthulhu for little-endian machines...
66623536Sbloom 	 */
66723536Sbloom 	if (st == CHAR && dt == USHORT)
66823536Sbloom 		/*
66923536Sbloom 		 * Special case -- we must sign-extend to 16 bits.
67023536Sbloom 		 */
67123536Sbloom 		return (0);
67223536Sbloom 
67323536Sbloom 	if (tlen(src) < tlen(dest))
67423536Sbloom 		newt = st;
67523536Sbloom 	else
67623536Sbloom 		newt = dt;
67723536Sbloom 
67823536Sbloom 	return (newt);
67923536Sbloom 	}
68023536Sbloom 
68117742Sralph rmove( rt, rs, t ) TWORD t; {
6829702Slinton 	printf( "	%s	%s,%s\n",
68317742Sralph #ifdef FORT
68417742Sralph 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
68517742Sralph #endif
6869702Slinton 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
6879702Slinton 		rnames[rs], rnames[rt] );
6889702Slinton 	}
6899702Slinton 
6909702Slinton struct respref
6919702Slinton respref[] = {
6929702Slinton 	INTAREG|INTBREG,	INTAREG|INTBREG,
6939702Slinton 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
6949702Slinton 	INTEMP,	INTEMP,
6959702Slinton 	FORARG,	FORARG,
6969702Slinton 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
6979702Slinton 	0,	0 };
6989702Slinton 
6999702Slinton setregs(){ /* set up temporary registers */
7009702Slinton 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
7019702Slinton 	}
7029702Slinton 
70332924Sdonn /*ARGSUSED*/
7049702Slinton rewfld( p ) NODE *p; {
7059702Slinton 	return(1);
7069702Slinton 	}
7079702Slinton 
70832924Sdonn /*ARGSUSED*/
7099702Slinton callreg(p) NODE *p; {
7109702Slinton 	return( R0 );
7119702Slinton 	}
7129702Slinton 
7139702Slinton base( p ) register NODE *p; {
7149702Slinton 	register int o = p->in.op;
7159702Slinton 
7169702Slinton 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
7179702Slinton 	if( o==REG ) return( p->tn.rval );
7189702Slinton     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
7199702Slinton 		return( p->in.left->tn.rval );
7209702Slinton     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
7219702Slinton 		return( p->tn.rval + 0200*1 );
7229702Slinton 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
7239702Slinton 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
7249702Slinton 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
7259702Slinton 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
7269702Slinton 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
7279702Slinton 	return( -1 );
7289702Slinton 	}
7299702Slinton 
7309702Slinton offset( p, tyl ) register NODE *p; int tyl; {
7319702Slinton 
73224418Smckusick 	if( tyl==1 &&
73324418Smckusick 	    p->in.op==REG &&
73424418Smckusick 	    (p->in.type==INT || p->in.type==UNSIGNED) )
73524418Smckusick 		return( p->tn.rval );
73624418Smckusick 	if( p->in.op==LS &&
73724418Smckusick 	    p->in.left->in.op==REG &&
73824418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
73924418Smckusick 	    p->in.right->in.op==ICON &&
74024418Smckusick 	    p->in.right->in.name[0]=='\0' &&
74124418Smckusick 	    (1<<p->in.right->tn.lval)==tyl)
7429702Slinton 		return( p->in.left->tn.rval );
74324418Smckusick 	if( tyl==2 &&
74424418Smckusick 	    p->in.op==PLUS &&
74524418Smckusick 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
74624418Smckusick 	    p->in.left->in.op==REG &&
74724418Smckusick 	    p->in.right->in.op==REG &&
74824418Smckusick 	    p->in.left->tn.rval==p->in.right->tn.rval )
74924418Smckusick 		return( p->in.left->tn.rval );
7509702Slinton 	return( -1 );
7519702Slinton 	}
7529702Slinton 
7539702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
7549702Slinton 	register NODE *t;
7559702Slinton 	NODE *f;
7569702Slinton 
7579702Slinton 	p->in.op = OREG;
7589702Slinton 	f = p->in.left; 	/* have to free this subtree later */
7599702Slinton 
7609702Slinton 	/* init base */
7619702Slinton 	switch (q->in.op) {
7629702Slinton 		case ICON:
7639702Slinton 		case REG:
7649702Slinton 		case OREG:
7659702Slinton 			t = q;
7669702Slinton 			break;
7679702Slinton 
7689702Slinton 		case MINUS:
7699702Slinton 			q->in.right->tn.lval = -q->in.right->tn.lval;
7709702Slinton 		case PLUS:
7719702Slinton 			t = q->in.right;
7729702Slinton 			break;
7739702Slinton 
7749702Slinton 		case INCR:
7759702Slinton 		case ASG MINUS:
7769702Slinton 			t = q->in.left;
7779702Slinton 			break;
7789702Slinton 
7799702Slinton 		case UNARY MUL:
7809702Slinton 			t = q->in.left->in.left;
7819702Slinton 			break;
7829702Slinton 
7839702Slinton 		default:
7849702Slinton 			cerror("illegal makeor2");
7859702Slinton 	}
7869702Slinton 
7879702Slinton 	p->tn.lval = t->tn.lval;
7889702Slinton #ifndef FLEXNAMES
78932924Sdonn 	{
79032924Sdonn 		register int i;
79132924Sdonn 		for(i=0; i<NCHNAM; ++i)
79232924Sdonn 			p->in.name[i] = t->in.name[i];
79332924Sdonn 	}
7949702Slinton #else
7959702Slinton 	p->in.name = t->in.name;
7969702Slinton #endif
7979702Slinton 
7989702Slinton 	/* init offset */
7999702Slinton 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
8009702Slinton 
8019702Slinton 	tfree(f);
8029702Slinton 	return;
8039702Slinton 	}
8049702Slinton 
8059702Slinton canaddr( p ) NODE *p; {
8069702Slinton 	register int o = p->in.op;
8079702Slinton 
8089702Slinton 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
8099702Slinton 	return(0);
8109702Slinton 	}
8119702Slinton 
81232935Sdonn flshape( p ) NODE *p; {
81332935Sdonn 	register int o = p->in.op;
81432935Sdonn 
81532935Sdonn 	return( o == REG || o == NAME || o == ICON ||
81632935Sdonn 		(o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
8179702Slinton 	}
8189702Slinton 
81932926Sdonn /* INTEMP shapes must not contain any temporary registers */
8209702Slinton shtemp( p ) register NODE *p; {
82132926Sdonn 	int r;
82232926Sdonn 
8239702Slinton 	if( p->in.op == STARG ) p = p->in.left;
82432926Sdonn 
82532926Sdonn 	switch (p->in.op) {
82632926Sdonn 	case REG:
82732926Sdonn 		return( !istreg(p->tn.rval) );
82832926Sdonn 	case OREG:
82932926Sdonn 		r = p->tn.rval;
83032926Sdonn 		if( R2TEST(r) ) {
83132926Sdonn 			if( istreg(R2UPK1(r)) )
83232926Sdonn 				return(0);
83332926Sdonn 			r = R2UPK2(r);
83432926Sdonn 			}
83532926Sdonn 		return( !istreg(r) );
83632926Sdonn 	case UNARY MUL:
83732926Sdonn 		p = p->in.left;
83832926Sdonn 		return( p->in.op != UNARY MUL && shtemp(p) );
83932926Sdonn 		}
84032926Sdonn 
84132926Sdonn 	if( optype( p->in.op ) != LTYPE ) return(0);
84232926Sdonn 	return(1);
8439702Slinton 	}
8449702Slinton 
8459702Slinton shumul( p ) register NODE *p; {
84632935Sdonn 	register int o;
8479702Slinton 	extern int xdebug;
8489702Slinton 
8499702Slinton 	if (xdebug) {
85032933Sdonn 		int val;
85132933Sdonn 		printf("shumul:\n");
85232933Sdonn 		eprint(p, 0, &val, &val);
8539702Slinton 		}
8549702Slinton 
8559702Slinton 	o = p->in.op;
8569702Slinton 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
8579702Slinton 
8589702Slinton 	if( ( o == INCR || o == ASG MINUS ) &&
8599702Slinton 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
8609702Slinton 	    p->in.right->in.name[0] == '\0' )
8619702Slinton 		{
86217659Sralph 		switch (p->in.type)
8639702Slinton 			{
8649702Slinton 			case CHAR|PTR:
8659702Slinton 			case UCHAR|PTR:
8669702Slinton 				o = 1;
8679702Slinton 				break;
8689702Slinton 
8699702Slinton 			case SHORT|PTR:
8709702Slinton 			case USHORT|PTR:
8719702Slinton 				o = 2;
8729702Slinton 				break;
8739702Slinton 
8749702Slinton 			case INT|PTR:
8759702Slinton 			case UNSIGNED|PTR:
8769702Slinton 			case LONG|PTR:
8779702Slinton 			case ULONG|PTR:
8789702Slinton 			case FLOAT|PTR:
8799702Slinton 				o = 4;
8809702Slinton 				break;
8819702Slinton 
8829702Slinton 			case DOUBLE|PTR:
8839702Slinton 				o = 8;
8849702Slinton 				break;
8859702Slinton 
8869702Slinton 			default:
88717742Sralph 				if ( ISPTR(p->in.type) &&
88817742Sralph 				     ISPTR(DECREF(p->in.type)) ) {
8899702Slinton 					o = 4;
8909702Slinton 					break;
8919702Slinton 					}
8929702Slinton 				else return(0);
8939702Slinton 			}
8949702Slinton 		return( p->in.right->tn.lval == o ? STARREG : 0);
8959702Slinton 		}
8969702Slinton 
8979702Slinton 	return( 0 );
8989702Slinton 	}
8999702Slinton 
9009702Slinton adrcon( val ) CONSZ val; {
90124418Smckusick 	putchar( '$' );
9029702Slinton 	printf( CONFMT, val );
9039702Slinton 	}
9049702Slinton 
9059702Slinton conput( p ) register NODE *p; {
9069702Slinton 	switch( p->in.op ){
9079702Slinton 
9089702Slinton 	case ICON:
9099702Slinton 		acon( p );
9109702Slinton 		return;
9119702Slinton 
9129702Slinton 	case REG:
91324418Smckusick 		putstr( rnames[p->tn.rval] );
9149702Slinton 		return;
9159702Slinton 
9169702Slinton 	default:
9179702Slinton 		cerror( "illegal conput" );
9189702Slinton 		}
9199702Slinton 	}
9209702Slinton 
92132923Sdonn /*ARGSUSED*/
92232924Sdonn insput( p ) NODE *p; {
9239702Slinton 	cerror( "insput" );
9249702Slinton 	}
9259702Slinton 
92632928Sdonn upput( p, size ) NODE *p; int size; {
92732928Sdonn 	if( size == SZLONG && p->in.op == REG ) {
92832928Sdonn 		putstr( rnames[p->tn.rval + 1] );
92932928Sdonn 		return;
93032928Sdonn 		}
9319702Slinton 	cerror( "upput" );
9329702Slinton 	}
9339702Slinton 
9349702Slinton adrput( p ) register NODE *p; {
9359702Slinton 	register int r;
9369702Slinton 	/* output an address, with offsets, from p */
9379702Slinton 
9389702Slinton 	if( p->in.op == FLD ){
9399702Slinton 		p = p->in.left;
9409702Slinton 		}
9419702Slinton 	switch( p->in.op ){
9429702Slinton 
9439702Slinton 	case NAME:
9449702Slinton 		acon( p );
9459702Slinton 		return;
9469702Slinton 
9479702Slinton 	case ICON:
9489702Slinton 		/* addressable value of the constant */
94924418Smckusick 		putchar( '$' );
9509702Slinton 		acon( p );
9519702Slinton 		return;
9529702Slinton 
9539702Slinton 	case REG:
95424418Smckusick 		putstr( rnames[p->tn.rval] );
9559702Slinton 		return;
9569702Slinton 
9579702Slinton 	case OREG:
9589702Slinton 		r = p->tn.rval;
9599702Slinton 		if( R2TEST(r) ){ /* double indexing */
9609702Slinton 			register int flags;
9619702Slinton 
9629702Slinton 			flags = R2UPK3(r);
96324418Smckusick 			if( flags & 1 ) putchar('*');
96424418Smckusick 			if( flags & 4 ) putchar('-');
9659702Slinton 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
9669702Slinton 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
96724418Smckusick 			if( flags & 2 ) putchar('+');
9689702Slinton 			printf( "[%s]", rnames[R2UPK2(r)] );
9699702Slinton 			return;
9709702Slinton 			}
9719702Slinton 		if( r == AP ){  /* in the argument region */
97232925Sdonn 			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
9739702Slinton 			printf( CONFMT, p->tn.lval );
97424418Smckusick 			putstr( "(ap)" );
9759702Slinton 			return;
9769702Slinton 			}
9779702Slinton 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
9789702Slinton 		printf( "(%s)", rnames[p->tn.rval] );
9799702Slinton 		return;
9809702Slinton 
9819702Slinton 	case UNARY MUL:
9829702Slinton 		/* STARNM or STARREG found */
9839702Slinton 		if( tshape(p, STARNM) ) {
98424418Smckusick 			putchar( '*' );
9859702Slinton 			adrput( p->in.left);
9869702Slinton 			}
9879702Slinton 		else {	/* STARREG - really auto inc or dec */
9889702Slinton 			register NODE *q;
9899702Slinton 
99017659Sralph 			q = p->in.left;
99117742Sralph 			if( q->in.right->tn.lval != tlen(p) )
99217742Sralph 				cerror("adrput: bad auto-increment/decrement");
99317659Sralph 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
99417659Sralph 				rnames[q->in.left->tn.rval],
99517659Sralph 				(q->in.op==INCR ? "+" : "") );
9969702Slinton 			p->in.op = OREG;
99717659Sralph 			p->tn.rval = q->in.left->tn.rval;
99817659Sralph 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
9999702Slinton #ifndef FLEXNAMES
10009702Slinton 			p->in.name[0] = '\0';
10019702Slinton #else
10029702Slinton 			p->in.name = "";
10039702Slinton #endif
10049702Slinton 			tfree(q);
10059702Slinton 		}
10069702Slinton 		return;
10079702Slinton 
10089702Slinton 	default:
10099702Slinton 		cerror( "illegal address" );
10109702Slinton 		return;
10119702Slinton 
10129702Slinton 		}
10139702Slinton 
10149702Slinton 	}
10159702Slinton 
10169702Slinton acon( p ) register NODE *p; { /* print out a constant */
10179702Slinton 
101832935Sdonn 	if( p->in.name[0] == '\0' )
10199702Slinton 		printf( CONFMT, p->tn.lval);
102032935Sdonn 	else {
10219702Slinton #ifndef FLEXNAMES
10229702Slinton 		printf( "%.8s", p->in.name );
10239702Slinton #else
102424418Smckusick 		putstr( p->in.name );
10259702Slinton #endif
102632935Sdonn 		if( p->tn.lval != 0 ) {
102732935Sdonn 			putchar( '+' );
102832935Sdonn 			printf( CONFMT, p->tn.lval );
102932935Sdonn 			}
10309702Slinton 		}
10319702Slinton 	}
10329702Slinton 
10339702Slinton genscall( p, cookie ) register NODE *p; {
10349702Slinton 	/* structure valued call */
10359702Slinton 	return( gencall( p, cookie ) );
10369702Slinton 	}
10379702Slinton 
10389702Slinton /* tbl */
10399702Slinton int gc_numbytes;
10409702Slinton /* tbl */
10419702Slinton 
104232924Sdonn /*ARGSUSED*/
10439702Slinton gencall( p, cookie ) register NODE *p; {
10449702Slinton 	/* generate the call given by p */
104516418Sralph 	register NODE *p1;
104632935Sdonn 	register int temp, temp1;
104732935Sdonn 	register int m;
10489702Slinton 
10499702Slinton 	if( p->in.right ) temp = argsize( p->in.right );
10509702Slinton 	else temp = 0;
10519702Slinton 
10529702Slinton 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
10539702Slinton 		/* set aside room for structure return */
10549702Slinton 
10559702Slinton 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
10569702Slinton 		else temp1 = temp;
10579702Slinton 		}
10589702Slinton 
10599702Slinton 	if( temp > maxargs ) maxargs = temp;
10609702Slinton 	SETOFF(temp1,4);
10619702Slinton 
10629702Slinton 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
106316418Sralph 		genargs( p->in.right );
10649702Slinton 		}
10659702Slinton 
10669702Slinton 	p1 = p->in.left;
10679702Slinton 	if( p1->in.op != ICON ){
10689702Slinton 		if( p1->in.op != REG ){
10699702Slinton 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
10709702Slinton 				if( p1->in.op != NAME ){
10719702Slinton 					order( p1, INAREG );
10729702Slinton 					}
10739702Slinton 				}
10749702Slinton 			}
10759702Slinton 		}
10769702Slinton 
10779702Slinton /* tbl
10789702Slinton 	setup gc_numbytes so reference to ZC works */
10799702Slinton 
10809702Slinton 	gc_numbytes = temp&(0x3ff);
10819702Slinton /* tbl */
10829702Slinton 
10839702Slinton 	p->in.op = UNARY CALL;
10849702Slinton 	m = match( p, INTAREG|INTBREG );
10859702Slinton 
10869702Slinton 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
10879702Slinton 	/* (plus in assignment to gc_numbytes above, for neatness only) */
10889702Slinton 	if (temp >= 1024)
10899702Slinton 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
10909702Slinton 
10919702Slinton 	return(m != MDONE);
10929702Slinton 	}
10939702Slinton 
10949702Slinton /* tbl */
10959702Slinton char *
10969702Slinton ccbranches[] = {
109732935Sdonn 	"eql",
109832935Sdonn 	"neq",
109932935Sdonn 	"leq",
110032935Sdonn 	"lss",
110132935Sdonn 	"geq",
110232935Sdonn 	"gtr",
110332935Sdonn 	"lequ",
110432935Sdonn 	"lssu",
110532935Sdonn 	"gequ",
110632935Sdonn 	"gtru",
11079702Slinton 	};
11089702Slinton /* tbl */
11099702Slinton 
111032924Sdonn /*ARGSUSED*/
11119702Slinton cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
11129702Slinton 
111332935Sdonn 	if( o != 0 && ( o < EQ || o > UGT ) )
111432935Sdonn 		cerror( "bad conditional branch: %s", opst[o] );
111532935Sdonn 	printf( "	j%s	L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab );
11169702Slinton 	}
11179702Slinton 
11189702Slinton nextcook( p, cookie ) NODE *p; {
11199702Slinton 	/* we have failed to match p with cookie; try another */
11209702Slinton 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
11219702Slinton 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
11229702Slinton 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
11239702Slinton 	return( FORREW );
11249702Slinton 	}
11259702Slinton 
112632924Sdonn /*ARGSUSED*/
11279702Slinton lastchance( p, cook ) NODE *p; {
11289702Slinton 	/* forget it! */
11299702Slinton 	return(0);
11309702Slinton 	}
11319702Slinton 
11329702Slinton optim2( p ) register NODE *p; {
11339702Slinton 	/* do local tree transformations and optimizations */
11349702Slinton 
113532929Sdonn 	int o;
113632932Sdonn 	int i, mask;
113716181Sralph 	register NODE *l, *r;
11389702Slinton 
113932929Sdonn 	switch( o = p->in.op ) {
11409702Slinton 
11419702Slinton 	case AND:
114219933Smckusick 		/* commute L and R to eliminate complements and constants */
114316181Sralph 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
114416181Sralph 		    l->in.op == COMPL ) {
11459702Slinton 			p->in.left = p->in.right;
114616181Sralph 			p->in.right = l;
11479702Slinton 			}
11489702Slinton 	case ASG AND:
11499702Slinton 		/* change meaning of AND to ~R&L - bic on pdp11 */
11509702Slinton 		r = p->in.right;
115132931Sdonn 		if( r->in.op==ICON && r->in.name[0]==0 ) {
115232931Sdonn 			/* check for degenerate operations */
115332931Sdonn 			l = p->in.left;
115432932Sdonn 			mask = (1 << tlen(l) * SZCHAR) - 1;
115532932Sdonn 			if( ISUNSIGNED(r->in.type) ) {
115632932Sdonn 				i = (r->tn.lval & mask);
115732932Sdonn 				if( i == mask ) {
115832932Sdonn 					r->in.op = FREE;
115932932Sdonn 					ncopy(p, l);
116032932Sdonn 					l->in.op = FREE;
116132932Sdonn 					break;
116232932Sdonn 					}
116332932Sdonn 				else if( i == 0 )
116432932Sdonn 					goto zero;
116532932Sdonn 				else
116632932Sdonn 					r->tn.lval = i;
116732932Sdonn 				}
116832932Sdonn 			else if( r->tn.lval == mask &&
116932932Sdonn 				 tlen(l) < SZINT/SZCHAR ) {
117032932Sdonn 				r->in.op = SCONV;
117132932Sdonn 				r->in.left = l;
117232932Sdonn 				r->in.right = 0;
117332932Sdonn 				r->in.type = ENUNSIGN(l->in.type);
117432932Sdonn 				r->in.su = l->in.su > 1 ? l->in.su : 1;
117532932Sdonn 				ncopy(p, r);
117632932Sdonn 				p->in.left = r;
117732932Sdonn 				p->in.type = INT;
117832931Sdonn 				break;
117932931Sdonn 				}
118032931Sdonn 			/* complement constant */
11819702Slinton 			r->tn.lval = ~r->tn.lval;
11829702Slinton 			}
11839702Slinton 		else if( r->in.op==COMPL ) { /* ~~A => A */
11849702Slinton 			r->in.op = FREE;
11859702Slinton 			p->in.right = r->in.left;
11869702Slinton 			}
11879702Slinton 		else { /* insert complement node */
118816181Sralph 			p->in.right = l = talloc();
118916181Sralph 			l->in.op = COMPL;
119016181Sralph 			l->in.rall = NOPREF;
119116181Sralph 			l->in.type = r->in.type;
119216181Sralph 			l->in.left = r;
119316181Sralph 			l->in.right = NULL;
11949702Slinton 			}
11959702Slinton 		break;
11969702Slinton 
119716181Sralph 	case SCONV:
119819933Smckusick 		l = p->in.left;
119917742Sralph #if defined(FORT) || defined(SPRECC)
120016573Sralph 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
120119933Smckusick 		    l->in.type == FLOAT || l->in.type == DOUBLE )
120219933Smckusick 			return;
120316573Sralph #else
120419933Smckusick 		if( mixtypes(p, l) ) return;
120516573Sralph #endif
120632924Sdonn 		if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL )
120725751Sdonn 			return;
120825751Sdonn 
120919933Smckusick 		/* Only trust it to get it right if the size is the same */
121019933Smckusick 		if( tlen(p) != tlen(l) )
121119933Smckusick 			return;
121216181Sralph 
121316181Sralph 		/* clobber conversion */
121419933Smckusick 		if( l->in.op != FLD )
121516181Sralph 			l->in.type = p->in.type;
121616181Sralph 		ncopy( p, l );
121716181Sralph 		l->in.op = FREE;
121819933Smckusick 
121916181Sralph 		break;
122016181Sralph 
122124418Smckusick 	case ASSIGN:
122224418Smckusick 		/*
122324418Smckusick 		 * Conversions are equivalent to assignments;
122424418Smckusick 		 * when the two operations are combined,
122524418Smckusick 		 * we can sometimes zap the conversion.
122624418Smckusick 		 */
122724418Smckusick 		r = p->in.right;
122824418Smckusick 		l = p->in.left;
122924418Smckusick 		if ( r->in.op == SCONV &&
123024418Smckusick 		     !mixtypes(l, r) &&
123132922Sdonn 		     l->in.op != FLD &&
123224418Smckusick 		     tlen(l) == tlen(r) ) {
123324418Smckusick 				p->in.right = r->in.left;
123424418Smckusick 				r->in.op = FREE;
123524418Smckusick 			}
123624418Smckusick 		break;
123724418Smckusick 
123832929Sdonn 	case ULE:
123932929Sdonn 	case ULT:
124032929Sdonn 	case UGE:
124132929Sdonn 	case UGT:
124232931Sdonn 		p->in.op -= (UGE-GE);
124332931Sdonn 		if( degenerate(p) )
124432931Sdonn 			break;
124532931Sdonn 		p->in.op += (UGE-GE);
124632931Sdonn 		break;
124732931Sdonn 
124832929Sdonn 	case EQ:
124932929Sdonn 	case NE:
125032929Sdonn 	case LE:
125132929Sdonn 	case LT:
125232929Sdonn 	case GE:
125332929Sdonn 	case GT:
125432931Sdonn 		(void) degenerate(p);
125532931Sdonn 		break;
125632931Sdonn 
125732931Sdonn 	case DIV:
125832931Sdonn 		if( p->in.right->in.op == ICON &&
125932931Sdonn 		    p->in.right->tn.name[0] == '\0' &&
126032931Sdonn 		    ISUNSIGNED(p->in.right->in.type) &&
126132931Sdonn 		    (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
126232931Sdonn 			/* easy to do here, harder to do in zzzcode() */
126332931Sdonn 			p->in.op = UGE;
126432929Sdonn 			break;
126532931Sdonn 			}
126632931Sdonn 	case MOD:
126732931Sdonn 	case ASG DIV:
126832931Sdonn 	case ASG MOD:
126932931Sdonn 		/*
127032931Sdonn 		 * optimize DIV and MOD
127132931Sdonn 		 *
127232931Sdonn 		 * basically we spot UCHAR and USHORT and try to do them
127332931Sdonn 		 * as signed ints...  apparently div+mul+sub is always
127432931Sdonn 		 * faster than ediv for finding MOD on the VAX, when
127532931Sdonn 		 * full unsigned MOD isn't needed.
127632931Sdonn 		 *
127732931Sdonn 		 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
127832931Sdonn 		 * are faster for unsigned dividend and a constant divisor
127932931Sdonn 		 * in the right range (.5 to 1 of dividend's range for the
128032931Sdonn 		 * first, .333+ to .5 for the second).  full unsigned is
128132931Sdonn 		 * already done cmp+sub in the appropriate case; the
128232931Sdonn 		 * other cases are less common and require more ambition.
128332931Sdonn 		 */
128432931Sdonn 		if( degenerate(p) )
128532929Sdonn 			break;
128632931Sdonn 		l = p->in.left;
128732931Sdonn 		r = p->in.right;
128832931Sdonn 		if( !ISUNSIGNED(r->in.type) ||
128932931Sdonn 		    tlen(l) >= SZINT/SZCHAR ||
129032931Sdonn 		    !(tlen(r) < SZINT/SZCHAR ||
129132931Sdonn 		      (r->in.op == ICON && r->tn.name[0] == '\0')) )
129232929Sdonn 			break;
129332931Sdonn 		if( r->in.op == ICON )
129432931Sdonn 			r->tn.type = INT;
129532931Sdonn 		else {
129632931Sdonn 			NODE *t = talloc();
129732931Sdonn 			t->in.left = r;
129832931Sdonn 			r = t;
129932931Sdonn 			r->in.op = SCONV;
130032931Sdonn 			r->in.type = INT;
130132931Sdonn 			r->in.right = 0;
130232931Sdonn 			p->in.right = r;
130332931Sdonn 			}
130432931Sdonn 		if( o == DIV || o == MOD ) {
130532931Sdonn 			NODE *t = talloc();
130632931Sdonn 			t->in.left = l;
130732931Sdonn 			l = t;
130832931Sdonn 			l->in.op = SCONV;
130932931Sdonn 			l->in.type = INT;
131032931Sdonn 			l->in.right = 0;
131132931Sdonn 			p->in.left = l;
131232931Sdonn 			}
131332931Sdonn 		/* handle asgops in table */
131432931Sdonn 		break;
131532931Sdonn 
131632931Sdonn 	case RS:
131732931Sdonn 	case ASG RS:
131832931Sdonn 	case LS:
131932931Sdonn 	case ASG LS:
132032931Sdonn 		/* pick up degenerate shifts */
132132931Sdonn 		l = p->in.left;
132232931Sdonn 		r = p->in.right;
132332931Sdonn 		if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
132432929Sdonn 			break;
132532929Sdonn 		i = r->tn.lval;
132632931Sdonn 		if( i < 0 )
132732931Sdonn 			/* front end 'fixes' this? */
132832931Sdonn 			if( o == LS || o == ASG LS )
132932931Sdonn 				o += (RS-LS);
133032931Sdonn 			else
133132931Sdonn 				o += (LS-RS);
133232931Sdonn 		if( (o == RS || o == ASG RS) &&
133332931Sdonn 		    !ISUNSIGNED(l->in.type) )
133432931Sdonn 			/* can't optimize signed right shifts */
133532929Sdonn 			break;
133632935Sdonn 		if( o == LS ) {
133732935Sdonn 			if( i < SZINT )
133832935Sdonn 				break;
133932935Sdonn 			}
134032935Sdonn 		else {
134132935Sdonn 			if( i < tlen(l) * SZCHAR )
134232935Sdonn 				break;
134332935Sdonn 			}
134432931Sdonn 	zero:
134532931Sdonn 		if( !asgop( o ) )
134632931Sdonn 			if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
134732931Sdonn 				/* no side effects */
134832932Sdonn 				tfree(l);
134932931Sdonn 				ncopy(p, r);
135032931Sdonn 				r->in.op = FREE;
135132931Sdonn 				p->tn.lval = 0;
135232931Sdonn 				}
135332931Sdonn 			else {
135432931Sdonn 				p->in.op = COMOP;
135532932Sdonn 				r->tn.lval = 0;
135632931Sdonn 				}
135732931Sdonn 		else {
135832931Sdonn 			p->in.op = ASSIGN;
135932931Sdonn 			r->tn.lval = 0;
136032929Sdonn 			}
136132931Sdonn 		break;
136232931Sdonn 		}
136332931Sdonn 	}
136432931Sdonn 
136532931Sdonn degenerate(p) register NODE *p; {
136632931Sdonn 	int o;
136732931Sdonn 	int result, i;
136832931Sdonn 	int lower, upper;
136932931Sdonn 	register NODE *l, *r;
137032931Sdonn 
137132931Sdonn 	/*
137232931Sdonn 	 * try to keep degenerate comparisons with constants
137332931Sdonn 	 * out of the table.
137432931Sdonn 	 */
137532931Sdonn 	r = p->in.right;
137632931Sdonn 	l = p->in.left;
137732931Sdonn 	if( r->in.op != ICON ||
137832931Sdonn 	    r->tn.name[0] != '\0' ||
137932931Sdonn 	    tlen(l) >= tlen(r) )
138032931Sdonn 		return (0);
138132931Sdonn 	switch( l->in.type ) {
138232931Sdonn 	case CHAR:
138332931Sdonn 		lower = -(1 << SZCHAR - 1);
138432931Sdonn 		upper = (1 << SZCHAR - 1) - 1;
138532931Sdonn 		break;
138632931Sdonn 	case UCHAR:
138732931Sdonn 		lower = 0;
138832931Sdonn 		upper = (1 << SZCHAR) - 1;
138932931Sdonn 		break;
139032931Sdonn 	case SHORT:
139132931Sdonn 		lower = -(1 << SZSHORT - 1);
139232931Sdonn 		upper = (1 << SZSHORT - 1) - 1;
139332931Sdonn 		break;
139432931Sdonn 	case USHORT:
139532931Sdonn 		lower = 0;
139632931Sdonn 		upper = (1 << SZSHORT) - 1;
139732931Sdonn 		break;
139832931Sdonn 	default:
139932932Sdonn 		cerror("unsupported type in degenerate()");
140032931Sdonn 		}
140132931Sdonn 	i = r->tn.lval;
140232931Sdonn 	switch( o = p->in.op ) {
140332931Sdonn 	case DIV:
140432931Sdonn 	case ASG DIV:
140532931Sdonn 	case MOD:
140632931Sdonn 	case ASG MOD:
140732931Sdonn 		/* DIV and MOD work like EQ */
140832931Sdonn 	case EQ:
140932931Sdonn 	case NE:
141032931Sdonn 		if( lower == 0 && (unsigned) i > upper )
141132931Sdonn 			result = o == NE;
141232931Sdonn 		else if( i < lower || i > upper )
141332931Sdonn 			result = o == NE;
141432931Sdonn 		else
141532931Sdonn 			return (0);
141632931Sdonn 		break;
141732931Sdonn 	case LT:
141832931Sdonn 	case GE:
141932931Sdonn 		if( lower == 0 && (unsigned) i > upper )
142032931Sdonn 			result = o == LT;
142132931Sdonn 		else if( i <= lower )
142232931Sdonn 			result = o != LT;
142332931Sdonn 		else if( i > upper )
142432931Sdonn 			result = o == LT;
142532931Sdonn 		else
142632931Sdonn 			return (0);
142732931Sdonn 		break;
142832931Sdonn 	case LE:
142932931Sdonn 	case GT:
143032931Sdonn 		if( lower == 0 && (unsigned) i >= upper )
143132931Sdonn 			result = o == LE;
143232931Sdonn 		else if( i < lower )
143332931Sdonn 			result = o != LE;
143432931Sdonn 		else if( i >= upper )
143532931Sdonn 			result = o == LE;
143632931Sdonn 		else
143732931Sdonn 			return (0);
143832931Sdonn 		break;
143932931Sdonn 	default:
144032931Sdonn 		cerror("unknown op in degenerate()");
144132931Sdonn 		}
144232931Sdonn 
144332931Sdonn 	if( o == MOD || o == ASG MOD ) {
144432931Sdonn 		r->in.op = FREE;
144532931Sdonn 		ncopy(p, l);
144632931Sdonn 		l->in.op = FREE;
144732931Sdonn 		}
144832931Sdonn 	else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
144932931Sdonn 		/* no side effects */
145032932Sdonn 		tfree(l);
145132931Sdonn 		ncopy(p, r);
145232931Sdonn 		r->in.op = FREE;
145332931Sdonn 		p->tn.lval = result;
145432931Sdonn 		}
145532931Sdonn 	else {
145632931Sdonn 		if( o == ASG DIV )
145732931Sdonn 			p->in.op = ASSIGN;
145832929Sdonn 		else {
145932929Sdonn 			p->in.op = COMOP;
146032929Sdonn 			r->tn.type = INT;
146132929Sdonn 			}
146232931Sdonn 		r->tn.lval = result;
14639702Slinton 		}
146432931Sdonn 	if( logop(o) )
146532931Sdonn 		p->in.type = INT;
146632931Sdonn 
146732931Sdonn 	return (1);
14689702Slinton 	}
14699702Slinton 
14709702Slinton /* added by jwf */
14719702Slinton struct functbl {
14729702Slinton 	int fop;
14739702Slinton 	TWORD ftype;
14749702Slinton 	char *func;
14759702Slinton 	} opfunc[] = {
14769702Slinton 	DIV,		TANY,	"udiv",
14779702Slinton 	MOD,		TANY,	"urem",
147817715Sralph 	ASG DIV,	TANY,	"audiv",
147917715Sralph 	ASG MOD,	TANY,	"aurem",
14809702Slinton 	0,	0,	0 };
14819702Slinton 
14829702Slinton hardops(p)  register NODE *p; {
14839702Slinton 	/* change hard to do operators into function calls.  */
14849702Slinton 	register NODE *q;
14859702Slinton 	register struct functbl *f;
14869702Slinton 	register o;
148717742Sralph 	NODE *old,*temp;
14889702Slinton 
14899702Slinton 	o = p->in.op;
149017742Sralph 	if( ! (optype(o)==BITYPE &&
149117742Sralph 	       (ISUNSIGNED(p->in.left->in.type) ||
149217742Sralph 		ISUNSIGNED(p->in.right->in.type))) )
149317742Sralph 		return;
14949702Slinton 
14959702Slinton 	for( f=opfunc; f->fop; f++ ) {
14969702Slinton 		if( o==f->fop ) goto convert;
14979702Slinton 		}
14989702Slinton 	return;
14999702Slinton 
15009702Slinton 	convert:
150132931Sdonn 	if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' )
150232928Sdonn 		/* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */
150332928Sdonn 		/* save a subroutine call -- use at most 5 instructions */
150432928Sdonn 		return;
150532931Sdonn 	if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR )
150632931Sdonn 		/* optim2() will modify the op into an ordinary int op */
150732931Sdonn 		return;
15089702Slinton 	if( asgop( o ) ) {
150917742Sralph 		old = NIL;
151017715Sralph 		switch( p->in.left->in.op ){
151117742Sralph 		case FLD:
151217742Sralph 			q = p->in.left->in.left;
151317742Sralph 			/*
151417742Sralph 			 * rewrite (lval.fld /= rval); as
151517742Sralph 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
151617742Sralph 			 * else the compiler will evaluate lval twice.
151717742Sralph 			 */
151817742Sralph 			if( q->in.op == UNARY MUL ){
151917742Sralph 				/* first allocate a temp storage */
152017742Sralph 				temp = talloc();
152117742Sralph 				temp->in.op = OREG;
152217742Sralph 				temp->tn.rval = TMPREG;
152317742Sralph 				temp->tn.lval = BITOOR(freetemp(1));
152417742Sralph 				temp->in.type = INCREF(p->in.type);
152517742Sralph #ifdef FLEXNAMES
152617742Sralph 				temp->in.name = "";
152717742Sralph #else
152817742Sralph 				temp->in.name[0] = '\0';
152917742Sralph #endif
153017742Sralph 				old = q->in.left;
153117742Sralph 				q->in.left = temp;
153217742Sralph 			}
153317742Sralph 			/* fall thru ... */
153417742Sralph 
153517715Sralph 		case REG:
153617715Sralph 		case NAME:
153717715Sralph 		case OREG:
153817715Sralph 			/* change ASG OP to a simple OP */
153917715Sralph 			q = talloc();
154017715Sralph 			q->in.op = NOASG p->in.op;
154117715Sralph 			q->in.rall = NOPREF;
154217715Sralph 			q->in.type = p->in.type;
154317715Sralph 			q->in.left = tcopy(p->in.left);
154417715Sralph 			q->in.right = p->in.right;
154517715Sralph 			p->in.op = ASSIGN;
154617715Sralph 			p->in.right = q;
154717715Sralph 			p = q;
154817715Sralph 			f -= 2; /* Note: this depends on the table order */
154917742Sralph 			/* on the right side only - replace *temp with
155017742Sralph 			 *(temp = &lval), build the assignment node */
155117742Sralph 			if( old ){
155217742Sralph 				temp = q->in.left->in.left; /* the "*" node */
155317742Sralph 				q = talloc();
155417742Sralph 				q->in.op = ASSIGN;
155517742Sralph 				q->in.left = temp->in.left;
155617742Sralph 				q->in.right = old;
155717742Sralph 				q->in.type = old->in.type;
155817742Sralph #ifdef FLEXNAMES
155917742Sralph 				q->in.name = "";
156017742Sralph #else
156117742Sralph 				q->in.name[0] = '\0';
156217742Sralph #endif
156317742Sralph 				temp->in.left = q;
156417742Sralph 			}
156517715Sralph 			break;
15669702Slinton 
156717715Sralph 		case UNARY MUL:
156817715Sralph 			/* avoid doing side effects twice */
156917715Sralph 			q = p->in.left;
157017715Sralph 			p->in.left = q->in.left;
157117715Sralph 			q->in.op = FREE;
157217715Sralph 			break;
157317715Sralph 
157417715Sralph 		default:
157517715Sralph 			cerror( "hardops: can't compute & LHS" );
157617715Sralph 			}
157717742Sralph 		}
157817715Sralph 
15799702Slinton 	/* build comma op for args to function */
15809702Slinton 	q = talloc();
15819702Slinton 	q->in.op = CM;
15829702Slinton 	q->in.rall = NOPREF;
15839702Slinton 	q->in.type = INT;
15849702Slinton 	q->in.left = p->in.left;
15859702Slinton 	q->in.right = p->in.right;
15869702Slinton 	p->in.op = CALL;
15879702Slinton 	p->in.right = q;
15889702Slinton 
15899702Slinton 	/* put function name in left node of call */
15909702Slinton 	p->in.left = q = talloc();
15919702Slinton 	q->in.op = ICON;
15929702Slinton 	q->in.rall = NOPREF;
15939702Slinton 	q->in.type = INCREF( FTN + p->in.type );
15949702Slinton #ifndef FLEXNAMES
15959702Slinton 	strcpy( q->in.name, f->func );
15969702Slinton #else
15979702Slinton 	q->in.name = f->func;
15989702Slinton #endif
15999702Slinton 	q->tn.lval = 0;
16009702Slinton 	q->tn.rval = 0;
16019702Slinton 
16029702Slinton 	}
16039702Slinton 
160417742Sralph zappost(p) NODE *p; {
160517742Sralph 	/* look for ++ and -- operators and remove them */
160617742Sralph 
160732935Sdonn 	register int o, ty;
160817742Sralph 	register NODE *q;
160917742Sralph 	o = p->in.op;
161017742Sralph 	ty = optype( o );
161117742Sralph 
161217742Sralph 	switch( o ){
161317742Sralph 
161417742Sralph 	case INCR:
161517742Sralph 	case DECR:
161617742Sralph 			q = p->in.left;
161717742Sralph 			p->in.right->in.op = FREE;  /* zap constant */
161817742Sralph 			ncopy( p, q );
161917742Sralph 			q->in.op = FREE;
162017742Sralph 			return;
162117742Sralph 
162217742Sralph 		}
162317742Sralph 
162417742Sralph 	if( ty == BITYPE ) zappost( p->in.right );
162517742Sralph 	if( ty != LTYPE ) zappost( p->in.left );
162617742Sralph }
162717742Sralph 
162817742Sralph fixpre(p) NODE *p; {
162917742Sralph 
163032935Sdonn 	register int o, ty;
163117742Sralph 	o = p->in.op;
163217742Sralph 	ty = optype( o );
163317742Sralph 
163417742Sralph 	switch( o ){
163517742Sralph 
163617742Sralph 	case ASG PLUS:
163717742Sralph 			p->in.op = PLUS;
163817742Sralph 			break;
163917742Sralph 	case ASG MINUS:
164017742Sralph 			p->in.op = MINUS;
164117742Sralph 			break;
164217742Sralph 		}
164317742Sralph 
164417742Sralph 	if( ty == BITYPE ) fixpre( p->in.right );
164517742Sralph 	if( ty != LTYPE ) fixpre( p->in.left );
164617742Sralph }
164717742Sralph 
164832935Sdonn /*ARGSUSED*/
164932935Sdonn NODE * addroreg(l) NODE *l;
165032935Sdonn 				/* OREG was built in clocal()
165132935Sdonn 				 * for an auto or formal parameter
165232935Sdonn 				 * now its address is being taken
165332935Sdonn 				 * local code must unwind it
165432935Sdonn 				 * back to PLUS/MINUS REG ICON
165532935Sdonn 				 * according to local conventions
165632935Sdonn 				 */
165732935Sdonn {
165832935Sdonn 	cerror("address of OREG taken");
165932935Sdonn 	/*NOTREACHED*/
166032935Sdonn }
166132935Sdonn 
166232935Sdonn 
166332935Sdonn 
166432935Sdonn # ifndef ONEPASS
166532935Sdonn main( argc, argv ) char *argv[]; {
166632935Sdonn 	return( mainp2( argc, argv ) );
166732935Sdonn 	}
166832935Sdonn # endif
166932935Sdonn 
167024418Smckusick strip(p) register NODE *p; {
167124418Smckusick 	NODE *q;
167224418Smckusick 
167324418Smckusick 	/* strip nodes off the top when no side effects occur */
167424418Smckusick 	for( ; ; ) {
167524418Smckusick 		switch( p->in.op ) {
167624418Smckusick 		case SCONV:			/* remove lint tidbits */
167724418Smckusick 			q = p->in.left;
167824418Smckusick 			ncopy( p, q );
167924418Smckusick 			q->in.op = FREE;
168024418Smckusick 			break;
168124418Smckusick 		/* could probably add a few more here */
168224418Smckusick 		default:
168324418Smckusick 			return;
168424418Smckusick 			}
168524418Smckusick 		}
168624418Smckusick 	}
168724418Smckusick 
16889702Slinton myreader(p) register NODE *p; {
168924418Smckusick 	strip( p );		/* strip off operations with no side effects */
169017742Sralph 	canon( p );		/* expands r-vals for fields */
16919702Slinton 	walkf( p, hardops );	/* convert ops to function calls */
16929702Slinton 	walkf( p, optim2 );
16939702Slinton 	}
1694