xref: /original-bsd/old/pcc/ccom.vax/local2.c (revision c5db5770)
1 # ifndef lint
2 static char *sccsid ="@(#)local2.c	1.39 (Berkeley) 05/11/88";
3 # endif
4 
5 # include "pass2.h"
6 # include <ctype.h>
7 
8 # define putstr(s)	fputs((s), stdout)
9 
10 # ifdef FORT
11 int ftlab1, ftlab2;
12 # endif
13 /* a lot of the machine dependent parts of the second pass */
14 
15 # define BITMASK(n) ((1L<<n)-1)
16 
17 /*ARGSUSED*/
where(c)18 where(c){
19 	fprintf( stderr, "%s, line %d: ", filename, lineno );
20 	}
21 
lineid(l,fn)22 lineid( l, fn ) char *fn; {
23 	/* identify line l and file fn */
24 	printf( "#	line %d, file %s\n", l, fn );
25 	}
26 
27 
eobl2()28 eobl2(){
29 	register OFFSZ spoff;	/* offset from stack pointer */
30 #ifndef FORT
31 	extern int ftlab1, ftlab2;
32 #endif
33 
34 	spoff = maxoff;
35 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
36 	spoff /= SZCHAR;
37 	SETOFF(spoff,4);
38 #ifdef FORT
39 #ifndef FLEXNAMES
40 	printf( "	.set	.F%d,%ld\n", ftnno, spoff );
41 #else
42 	/* SHOULD BE L%d ... ftnno but must change pc/f77 */
43 	printf( "	.set	LF%d,%ld\n", ftnno, spoff );
44 #endif
45 #else
46 	printf( "L%d:\n", ftlab1);
47 	if( spoff!=0 )
48 		if( spoff < 64 )
49 			printf( "	subl2	$%ld,sp\n", spoff);
50 		else
51 			printf( "	movab	-%ld(sp),sp\n", spoff);
52 	printf( "	jbr 	L%d\n", ftlab2);
53 #endif
54 	maxargs = -1;
55 	}
56 
57 struct hoptab { int opmask; char * opstring; } ioptab[] = {
58 
59 	PLUS,	"add",
60 	MINUS,	"sub",
61 	MUL,	"mul",
62 	DIV,	"div",
63 	OR,	"bis",
64 	ER,	"xor",
65 	AND,	"bic",
66 	-1, ""    };
67 
hopcode(f,o)68 hopcode( f, o ){
69 	/* output the appropriate string from the above table */
70 
71 	register struct hoptab *q;
72 
73 	if(asgop(o))
74 		o = NOASG o;
75 	for( q = ioptab;  q->opmask>=0; ++q ){
76 		if( q->opmask == o ){
77 			printf( "%s%c", q->opstring, tolower(f));
78 			return;
79 			}
80 		}
81 	cerror( "no hoptab for %s", opst[o] );
82 	}
83 
84 char *
85 rnames[] = {  /* keyed to register number tokens */
86 
87 	"r0", "r1",
88 	"r2", "r3", "r4", "r5",
89 	"r6", "r7", "r8", "r9", "r10", "r11",
90 	"ap", "fp", "sp", "pc",
91 	};
92 
93 int rstatus[] = {
94 	SAREG|STAREG, SAREG|STAREG,
95 	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
96 	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
97 	SAREG, SAREG, SAREG, SAREG,
98 	};
99 
tlen(p)100 tlen(p) NODE *p;
101 {
102 	switch(p->in.type) {
103 		case CHAR:
104 		case UCHAR:
105 			return(1);
106 
107 		case SHORT:
108 		case USHORT:
109 			return(SZSHORT/SZCHAR);
110 
111 		case DOUBLE:
112 			return(SZDOUBLE/SZCHAR);
113 
114 		default:
115 			return(SZINT/SZCHAR);
116 		}
117 }
118 
mixtypes(p,q)119 mixtypes(p, q) NODE *p, *q;
120 {
121 	register TWORD tp, tq;
122 
123 	tp = p->in.type;
124 	tq = q->in.type;
125 
126 	return( (tp==FLOAT || tp==DOUBLE) !=
127 		(tq==FLOAT || tq==DOUBLE) );
128 }
129 
prtype(n)130 prtype(n) NODE *n;
131 {
132 	switch (n->in.type)
133 		{
134 
135 		case DOUBLE:
136 			putchar('d');
137 			return;
138 
139 		case FLOAT:
140 			putchar('f');
141 			return;
142 
143 		case LONG:
144 		case ULONG:
145 		case INT:
146 		case UNSIGNED:
147 			putchar('l');
148 			return;
149 
150 		case SHORT:
151 		case USHORT:
152 			putchar('w');
153 			return;
154 
155 		case CHAR:
156 		case UCHAR:
157 			putchar('b');
158 			return;
159 
160 		default:
161 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
162 			else {
163 				putchar('l');
164 				return;
165 				}
166 		}
167 }
168 
zzzcode(p,c)169 zzzcode( p, c ) register NODE *p; {
170 	register int m;
171 	int val;
172 	switch( c ){
173 
174 	case 'N':  /* logical ops, turned into 0-1 */
175 		/* use register given by register 1 */
176 		cbgen( 0, m=getlab(), 'I' );
177 		deflab( p->bn.label );
178 		printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );
179 		deflab( m );
180 		return;
181 
182 	case 'P':
183 		cbgen( p->in.op, p->bn.label, c );
184 		return;
185 
186 	case 'A':
187 	case 'V':
188 		sconv( p, c == 'V' );
189 		return;
190 
191 	case 'G':	/* i *= f; asgops with int lhs and float rhs */
192 		{
193 		register NODE *l, *r, *s;
194 		int rt;
195 
196 		l = p->in.left;
197 		r = p->in.right;
198 		s = talloc();
199 		rt = r->in.type;
200 
201 		s->in.op = SCONV;
202 		s->in.left = l;
203 		s->in.type = rt;
204 		zzzcode(s, 'A');
205 		putstr("\n\t");
206 
207 		hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
208 		putstr("2\t");
209 		adrput(r);
210 		putchar(',');
211 		adrput(resc);
212 		putstr("\n\t");
213 
214 		s->in.op = ASSIGN;
215 		s->in.left = l;
216 		s->in.right = resc;
217 		s->in.type = l->in.type;
218 		zzzcode(s, 'A');
219 
220 		s->in.op = FREE;
221 		return;
222 		}
223 
224 	case 'J':	/* unsigned DIV/MOD with constant divisors */
225 		{
226 		register int ck = INAREG;
227 		int label1, label2;
228 
229 		/* case constant <= 1 is handled by optim() in pass 1 */
230 		/* case constant < 0x80000000 is handled in table */
231 		switch( p->in.op ) {
232 		/* case DIV: handled in optim2() */
233 		case MOD:
234 			if( p->in.left->in.op == REG &&
235 			    p->in.left->tn.rval == resc->tn.rval )
236 				goto asgmod;
237 			label1 = getlab();
238 			expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n");
239 			printf("\tjlssu\tL%d\n", label1);
240 			expand(p, ck, "\tsubl2\tAR,A1\n");
241 			printf("L%d:", label1);
242 			break;
243 		case ASG DIV:
244 			label1 = getlab();
245 			label2 = getlab();
246 			expand(p, ck, "cmpl\tAL,AR\n");
247 			printf("\tjgequ\tL%d\n", label1);
248 			expand(p, ck, "\tmovl\t$1,AL\n");
249 			printf("\tjbr\tL%d\nL%d:\n", label2, label1);
250 			expand(p, ck, "\tclrl\tAL\n");
251 			printf("L%d:", label2);
252 			break;
253 		case ASG MOD:
254 		asgmod:
255 			label1 = getlab();
256 			expand(p, ck, "cmpl\tAL,AR\n");
257 			printf("\tjlssu\tL%d\n", label1);
258 			expand(p, ck, "\tsubl2\tAR,AL\n");
259 			printf("L%d:", label1);
260 			break;
261 			}
262 		return;
263 		}
264 
265 	case 'B':	/* get oreg value in temp register for left shift */
266 		{
267 		register NODE *r;
268 		if (xdebug) eprint(p, 0, &val, &val);
269 		r = p->in.right;
270 		if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT )
271 			putstr("movl");
272 		else {
273 			putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
274 			prtype(r);
275 			putchar('l');
276 			}
277 		return;
278 		}
279 
280 	case 'C':	/* num words pushed on arg stack */
281 		{
282 		extern int gc_numbytes;
283 		extern int xdebug;
284 
285 		if (xdebug) printf("->%d<-",gc_numbytes);
286 
287 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
288 		return;
289 		}
290 
291 	case 'D':	/* INCR and DECR */
292 		zzzcode(p->in.left, 'A');
293 		putchar('\n');
294 		putchar('\t');
295 
296 	case 'E':	/* INCR and DECR, FOREFF */
297 		if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1)
298 			{
299 			putstr(p->in.op == INCR ? "inc" : "dec");
300 			prtype(p->in.left);
301 			putchar('\t');
302 			adrput(p->in.left);
303 			return;
304 			}
305 		putstr(p->in.op == INCR ? "add" : "sub");
306 		prtype(p->in.left);
307 		putchar('2');
308 		putchar('\t');
309 		adrput(p->in.right);
310 		putchar(',');
311 		adrput(p->in.left);
312 		return;
313 
314 	case 'F':	/* register type of right operand */
315 		{
316 		register NODE *n;
317 		extern int xdebug;
318 		register int ty;
319 
320 		n = getlr( p, 'R' );
321 		ty = n->in.type;
322 
323 		if (xdebug) printf("->%d<-", ty);
324 
325 		if ( ty==DOUBLE) putchar('d');
326 		else if ( ty==FLOAT ) putchar('f');
327 		else putchar('l');
328 		return;
329 		}
330 
331 	case 'L':	/* type of left operand */
332 	case 'R':	/* type of right operand */
333 		{
334 		register NODE *n;
335 		extern int xdebug;
336 
337 		n = getlr( p, c );
338 		if (xdebug) printf("->%d<-", n->in.type);
339 
340 		prtype(n);
341 		return;
342 		}
343 
344 	case 'Z':	/* AND for CC with ICON -- lval is complemented */
345 		{
346 		register NODE *l, *r;
347 
348 		l = getlr( p, 'L' );
349 		r = getlr( p, 'R' );
350 		m = (1 << tlen(l) * SZCHAR) - 1;
351 		r->tn.lval = ~r->tn.lval;
352 		if( (l->in.type == CHAR || l->in.type == SHORT) &&
353 		    (r->tn.lval & ~m) ) {
354 			putstr("cvt");
355 			prtype(l);
356 			putstr("l\t");
357 			adrput(l);
358 			putchar(',');
359 			adrput(resc);
360 			putstr("\n\t");
361 			resc->tn.type = INT;
362 			l = resc;
363 			}
364 		else if( l->in.type == UCHAR || l->in.type == USHORT )
365 			/* remove trash left over from complementing */
366 			r->tn.lval &= m;
367 		putstr("bit");
368 		prtype(l);
369 		printf("\t$%ld", r->tn.lval);
370 		putchar(',');
371 		adrput(l);
372 		return;
373 		}
374 
375 	case 'U':	/* 32 - n, for unsigned right shifts */
376 		printf("$%d", 32 - p->in.right->tn.lval );
377 		return;
378 
379 	case 'T':	/* rounded structure length for arguments */
380 		{
381 		int size;
382 
383 		size = p->stn.stsize;
384 		SETOFF( size, 4);
385 		printf("$%d", size);
386 		return;
387 		}
388 
389 	case 'S':  /* structure assignment */
390 		stasg(p);
391 		break;
392 
393 	default:
394 		cerror( "illegal zzzcode" );
395 		}
396 	}
397 
stasg(p)398 stasg(p)
399 	register NODE *p;
400 {
401 	register NODE *l, *r;
402 	register size;
403 
404 	if( p->in.op == STASG ){
405 		l = p->in.left;
406 		r = p->in.right;
407 
408 		}
409 	else if( p->in.op == STARG ){  /* store an arg into a temporary */
410 		r = p->in.left;
411 		}
412 	else cerror( "STASG bad" );
413 
414 	if( r->in.op == ICON ) r->in.op = NAME;
415 	else if( r->in.op == REG ) r->in.op = OREG;
416 	else if( r->in.op != OREG ) cerror( "STASG-r" );
417 
418 	size = p->stn.stsize;
419 
420 	if( size <= 0 || size > 65535 )
421 		cerror("structure size <0=0 or >65535");
422 
423 	switch(size) {
424 		case 1:
425 			putstr("	movb	");
426 			break;
427 		case 2:
428 			putstr("	movw	");
429 			break;
430 		case 4:
431 			putstr("	movl	");
432 			break;
433 		case 8:
434 			putstr("	movq	");
435 			break;
436 		default:
437 			printf("	movc3	$%d,", size);
438 			break;
439 	}
440 	adrput(r);
441 	if( p->in.op == STASG ){
442 		putchar(',');
443 		adrput(l);
444 		putchar('\n');
445 		}
446 	else
447 		putstr(",(sp)\n");
448 
449 	if( r->in.op == NAME ) r->in.op = ICON;
450 	else if( r->in.op == OREG ) r->in.op = REG;
451 	}
452 
makearg(ty)453 NODE *makearg( ty ) int ty; {
454 	register NODE *p, *q;
455 
456 	/* build a -(sp) operand */
457 	p = talloc();
458 	p->in.op = REG;
459 	/* the type needn't be right, just consistent */
460 	p->in.type = INCREF(ty);
461 	p->tn.rval = SP;
462 	p->tn.lval = 0;
463 	q = talloc();
464 	q->in.op = ASG MINUS;
465 	q->in.type = INCREF(ty);
466 	q->in.left = p;
467 	p = talloc();
468 	p->in.op = ICON;
469 	p->in.type = INT;
470 	p->tn.name = "";
471 	/* size of floating argument is always 2 */
472 	p->tn.lval = (1 + (ty == FLOAT || ty == DOUBLE)) * (SZINT/SZCHAR);
473 	q->in.right = p;
474 	p = talloc();
475 	p->in.op = UNARY MUL;
476 	p->in.left = q;
477 	return( p );
478 	}
479 
sconv(p,forarg)480 sconv( p, forarg ) register NODE *p; {
481 	register NODE *l, *r;
482 	int m, val;
483 
484 	if (xdebug) eprint(p, 0, &val, &val);
485 	r = getlr(p, 'R');
486 	if (p->in.op == ASSIGN)
487 		l = getlr(p, 'L');
488 	else if (p->in.op == SCONV) {
489 		m = r->in.type;
490 		if (forarg)
491 			l = makearg( m );
492 		else
493 			l = resc;
494 		l->in.type = m;
495 		r = getlr(p, 'L');
496 		}
497 	else {		/* OPLTYPE */
498 		m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
499 		if (forarg)
500 			l = makearg( m );
501 		else
502 			l = resc;
503 		l->in.type = m;
504 		}
505 	if (r->in.op == ICON)
506 		if (r->in.name[0] == '\0') {
507 			if (r->tn.lval == 0 &&
508 			    (r->in.type == DOUBLE || r->in.type == FLOAT ||
509 			    !forarg)) {
510 				if (r->in.type == FLOAT)
511 					r->in.type = DOUBLE;
512 				putstr("clr");
513 				prtype(l);
514 				putchar('\t');
515 				adrput(l);
516 				goto cleanup;
517 				}
518 			if (r->tn.lval < 0 && r->tn.lval >= -63) {
519 				putstr("mneg");
520 				prtype(l);
521 				r->tn.lval = -r->tn.lval;
522 				goto ops;
523 				}
524 			if (r->tn.lval < 0)
525 				r->in.type = r->tn.lval >= -128 ? CHAR
526 					: (r->tn.lval >= -32768 ? SHORT
527 					: INT);
528 			else if (l->in.type == FLOAT ||
529 			    l->in.type == DOUBLE)
530 				r->in.type = r->tn.lval <= 63 ? INT
531 					: (r->tn.lval <= 127 ? CHAR
532 					: (r->tn.lval <= 32767 ? SHORT
533 					: INT));
534 			else
535 				r->in.type = r->tn.lval <= 63 ? INT
536 					: (r->tn.lval <= 127 ? CHAR
537 					: (r->tn.lval <= 255 ? UCHAR
538 					: (r->tn.lval <= 32767 ? SHORT
539 					: (r->tn.lval <= 65535 ? USHORT
540 					: INT))));
541 			if (forarg && r->in.type == INT) {
542 				putstr("pushl\t");
543 				adrput(r);
544 				goto cleanup;
545 				}
546 			}
547 		else {
548 			if (forarg && tlen(r) == SZINT/SZCHAR) {
549 				putstr("pushl\t");
550 				adrput(r);
551 				goto cleanup;
552 				}
553 			putstr("moval\t");
554 			acon(r);
555 			putchar(',');
556 			adrput(l);
557 			goto cleanup;
558 			}
559 
560 	if (p->in.op == SCONV &&
561 	    !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
562 	    !mixtypes(l, r)) {
563 		/*
564 		 * Because registers must always contain objects
565 		 * of the same width as INTs, we may have to
566 		 * perform two conversions to get an INT.  Can
567 		 * the conversions be collapsed into one?
568 		 */
569 		if (m = collapsible(l, r))
570 			r->in.type = m;
571 		else {
572 			/* two steps are required */
573 			NODE *x;
574 
575 			if (forarg) {
576 				x = resc;
577 				x->in.type = l->in.type;
578 				}
579 			else {
580 				x = &resc[1];
581 				*x = *l;
582 				}
583 
584 			if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
585 				putstr("movz");
586 			else
587 				putstr("cvt");
588 			prtype(r);
589 			prtype(x);
590 			putchar('\t');
591 			adrput(r);
592 			putchar(',');
593 			adrput(x);
594 			putchar('\n');
595 			putchar('\t');
596 			r = x;
597 			}
598 		l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
599 		}
600 
601 	else if ((forarg || l == resc) &&
602 		 tlen(l) < SZINT/SZCHAR &&
603 		 mixtypes(l, r)) {
604 		/* two steps needed here too */
605 		NODE *x;
606 
607 		if (forarg) {
608 			x = resc;
609 			x->in.type = l->in.type;
610 			}
611 		else {
612 			x = &resc[1];
613 			*x = *l;
614 			}
615 		putstr("cvt");
616 		prtype(r);
617 		prtype(x);
618 		putchar('\t');
619 		adrput(r);
620 		putchar(',');
621 		adrput(x);
622 		putstr("\n\t");
623 		r = x;
624 		l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
625 		}
626 
627 	else if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
628 	    mixtypes(l, r)) {
629 		int label1;
630 		NODE *x = NULL;
631 
632 #if defined(FORT) || defined(SPRECC)
633 		if (forarg)
634 #else
635 		if (forarg || l == resc)
636 #endif
637 			{
638 			/* compute in register, convert to double when done */
639 			x = l;
640 			l = resc;
641 			l->in.type = x->in.type;
642 			}
643 
644 		label1 = getlab();
645 
646 		putstr("cvtl");
647 		prtype(l);
648 		putchar('\t');
649 		adrput(r);
650 		putchar(',');
651 		adrput(l);
652 		printf("\n\tjgeq\tL%d\n\tadd", label1);
653 		prtype(l);
654 		putstr("2\t$0");
655 		prtype(l);
656 		putstr("4.294967296e9,");
657 		adrput(l);
658 		printf("\nL%d:", label1);
659 
660 #if defined(FORT) || defined(SPRECC)
661 		if (!forarg)
662 #else
663 		if (!forarg && (l->in.type == DOUBLE || l != resc))
664 #endif
665 			goto cleanup;
666 		if (x == NULL)
667 			cerror("sconv botch");
668 		if (l == x) {
669 			r = &resc[1];
670 			*r = *l;
671 			}
672 		else {
673 			r = l;
674 			l = x;
675 			}
676 		l->in.type = DOUBLE;
677 		putstr("\n\t");
678 		}
679 
680 	else if( (l->in.type == FLOAT || l->in.type == DOUBLE) &&
681 	    (r->in.type == UCHAR || r->in.type == USHORT) ) {
682 		/* skip unnecessary unsigned to floating conversion */
683 #if defined(FORT) || defined(SPRECC)
684 		if (forarg)
685 #else
686 		if (forarg || l == resc)
687 #endif
688 			l->in.type = DOUBLE;
689 		putstr("movz");
690 		prtype(r);
691 		putstr("l\t");
692 		adrput(r);
693 		putchar(',');
694 		adrput(resc);
695 		putstr("\n\t");
696 		if (l == resc) {
697 			r = &resc[1];
698 			*r = *l;
699 			}
700 		else
701 			r = resc;
702 		r->in.type = INT;
703 		}
704 
705 #if defined(FORT) || defined(SPRECC)
706 	if (forarg && l->in.type == FLOAT)
707 #else
708 	if ((forarg || l == resc) && l->in.type == FLOAT)
709 #endif
710 		{
711 		/* perform an implicit conversion to double */
712 		l->in.type = DOUBLE;
713 		if (r->in.type != FLOAT &&
714 		    r->in.type != CHAR &&
715 		    r->in.type != SHORT) {
716 			/* trim bits from the mantissa */
717 			putstr("cvt");
718 			prtype(r);
719 			putstr("f\t");
720 			adrput(r);
721 			putchar(',');
722 			adrput(resc);
723 			putstr("\n\t");
724 			if (l == resc) {
725 				r = &resc[1];
726 				*r = *l;
727 				}
728 			else
729 				r = resc;
730 			r->in.type = FLOAT;
731 			}
732 		}
733 
734 	if (!mixtypes(l,r)) {
735 		if (tlen(l) == tlen(r)) {
736 			if (forarg && tlen(l) == SZINT/SZCHAR) {
737 				putstr("pushl\t");
738 				adrput(r);
739 				goto cleanup;
740 				}
741 			putstr("mov");
742 #ifdef FORT
743 			if (Oflag)
744 				prtype(l);
745 			else {
746 				if (l->in.type == DOUBLE)
747 					putchar('q');
748 				else if(l->in.type == FLOAT)
749 					putchar('l');
750 				else
751 					prtype(l);
752 				}
753 #else
754 			prtype(l);
755 #endif FORT
756 			goto ops;
757 			}
758 		else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
759 			putstr("movz");
760 		else
761 			putstr("cvt");
762 		}
763 	else
764 		putstr("cvt");
765 	prtype(r);
766 	prtype(l);
767 ops:
768 	putchar('\t');
769 	adrput(r);
770 	putchar(',');
771 	adrput(l);
772 
773 cleanup:
774 	if (forarg)
775 		tfree(l);
776 	}
777 
778 /*
779  * collapsible(dest, src) -- if a conversion with a register destination
780  *	can be accomplished in one instruction, return the type of src
781  *	that will do the job correctly; otherwise return 0.  Note that
782  *	a register must always end up having type INT or UNSIGNED.
783  */
784 int
collapsible(dest,src)785 collapsible(dest, src)
786 NODE *dest, *src;
787 {
788 	int st = src->in.type;
789 	int dt = dest->in.type;
790 	int newt = 0;
791 
792 	/*
793 	 * Are there side effects of evaluating src?
794 	 * If the derived type will not be the same size as src,
795 	 * we may have to use two steps.
796 	 */
797 	if (tlen(src) > tlen(dest)) {
798 		if (tshape(src, STARREG))
799 			return (0);
800 		if (src->in.op == OREG && R2TEST(src->tn.rval))
801 			return (0);
802 		}
803 
804 	/*
805 	 * Can we get an object of dest's type by punning src?
806 	 * Praises be to great Cthulhu for little-endian machines...
807 	 */
808 	if (st == CHAR && dt == USHORT)
809 		/*
810 		 * Special case -- we must sign-extend to 16 bits.
811 		 */
812 		return (0);
813 
814 	if (tlen(src) < tlen(dest))
815 		newt = st;
816 	else
817 		newt = dt;
818 
819 	return (newt);
820 	}
821 
rmove(rt,rs,t)822 rmove( rt, rs, t ) TWORD t; {
823 	printf( "	%s	%s,%s\n",
824 #ifdef FORT
825 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
826 #endif
827 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
828 		rnames[rs], rnames[rt] );
829 	}
830 
831 struct respref
832 respref[] = {
833 	INTAREG|INTBREG,	INTAREG|INTBREG,
834 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
835 	INTEMP,	INTEMP,
836 	FORARG,	FORARG,
837 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
838 	0,	0 };
839 
setregs()840 setregs(){ /* set up temporary registers */
841 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
842 	}
843 
844 /*ARGSUSED*/
rewfld(p)845 rewfld( p ) NODE *p; {
846 	return(1);
847 	}
848 
849 /*ARGSUSED*/
callreg(p)850 callreg(p) NODE *p; {
851 	return( R0 );
852 	}
853 
base(p)854 base( p ) register NODE *p; {
855 	register int o = p->in.op;
856 
857 	if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */
858 	if( o==REG ) return( p->tn.rval );
859     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
860 		return( p->in.left->tn.rval );
861     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
862 		return( p->tn.rval + 0200*1 );
863 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
864 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
865 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
866 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
867 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
868 	if( o==NAME ) return( 100 + 0200*1 );
869 	return( -1 );
870 	}
871 
offset(p,tyl)872 offset( p, tyl ) register NODE *p; int tyl; {
873 
874 	if( tyl==1 &&
875 	    p->in.op==REG &&
876 	    (p->in.type==INT || p->in.type==UNSIGNED) )
877 		return( p->tn.rval );
878 	if( p->in.op==LS &&
879 	    p->in.left->in.op==REG &&
880 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
881 	    p->in.right->in.op==ICON &&
882 	    p->in.right->in.name[0]=='\0' &&
883 	    (1<<p->in.right->tn.lval)==tyl)
884 		return( p->in.left->tn.rval );
885 	if( tyl==2 &&
886 	    p->in.op==PLUS &&
887 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
888 	    p->in.left->in.op==REG &&
889 	    p->in.right->in.op==REG &&
890 	    p->in.left->tn.rval==p->in.right->tn.rval )
891 		return( p->in.left->tn.rval );
892 	return( -1 );
893 	}
894 
makeor2(p,q,b,o)895 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
896 	register NODE *t;
897 	NODE *f;
898 
899 	p->in.op = OREG;
900 	f = p->in.left; 	/* have to free this subtree later */
901 
902 	/* init base */
903 	switch (q->in.op) {
904 		case ICON:
905 		case REG:
906 		case OREG:
907 		case NAME:
908 			t = q;
909 			break;
910 
911 		case MINUS:
912 			q->in.right->tn.lval = -q->in.right->tn.lval;
913 		case PLUS:
914 			t = q->in.right;
915 			break;
916 
917 		case INCR:
918 		case ASG MINUS:
919 			t = q->in.left;
920 			break;
921 
922 		case UNARY MUL:
923 			t = q->in.left->in.left;
924 			break;
925 
926 		default:
927 			cerror("illegal makeor2");
928 	}
929 
930 	p->tn.lval = t->tn.lval;
931 #ifndef FLEXNAMES
932 	{
933 		register int i;
934 		for(i=0; i<NCHNAM; ++i)
935 			p->in.name[i] = t->in.name[i];
936 	}
937 #else
938 	p->in.name = t->in.name;
939 #endif
940 
941 	/* init offset */
942 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
943 
944 	tfree(f);
945 	return;
946 	}
947 
canaddr(p)948 canaddr( p ) NODE *p; {
949 	register int o = p->in.op;
950 
951 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
952 	return(0);
953 	}
954 
flshape(p)955 flshape( p ) NODE *p; {
956 	register int o = p->in.op;
957 
958 	return( o == REG || o == NAME || o == ICON ||
959 		(o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
960 	}
961 
962 /* INTEMP shapes must not contain any temporary registers */
shtemp(p)963 shtemp( p ) register NODE *p; {
964 	int r;
965 
966 	if( p->in.op == STARG ) p = p->in.left;
967 
968 	switch (p->in.op) {
969 	case REG:
970 		return( !istreg(p->tn.rval) );
971 	case OREG:
972 		r = p->tn.rval;
973 		if( R2TEST(r) ) {
974 			if( istreg(R2UPK1(r)) )
975 				return(0);
976 			r = R2UPK2(r);
977 			}
978 		return( !istreg(r) );
979 	case UNARY MUL:
980 		p = p->in.left;
981 		return( p->in.op != UNARY MUL && shtemp(p) );
982 		}
983 
984 	if( optype( p->in.op ) != LTYPE ) return(0);
985 	return(1);
986 	}
987 
shumul(p)988 shumul( p ) register NODE *p; {
989 	register int o;
990 	extern int xdebug;
991 
992 	if (xdebug) {
993 		int val;
994 		printf("shumul:\n");
995 		eprint(p, 0, &val, &val);
996 		}
997 
998 	o = p->in.op;
999 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
1000 
1001 	if( ( o == INCR || o == ASG MINUS ) &&
1002 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
1003 	    p->in.right->in.name[0] == '\0' )
1004 		{
1005 		switch (p->in.type)
1006 			{
1007 			case CHAR|PTR:
1008 			case UCHAR|PTR:
1009 				o = 1;
1010 				break;
1011 
1012 			case SHORT|PTR:
1013 			case USHORT|PTR:
1014 				o = 2;
1015 				break;
1016 
1017 			case INT|PTR:
1018 			case UNSIGNED|PTR:
1019 			case LONG|PTR:
1020 			case ULONG|PTR:
1021 			case FLOAT|PTR:
1022 				o = 4;
1023 				break;
1024 
1025 			case DOUBLE|PTR:
1026 				o = 8;
1027 				break;
1028 
1029 			default:
1030 				if ( ISPTR(p->in.type) &&
1031 				     ISPTR(DECREF(p->in.type)) ) {
1032 					o = 4;
1033 					break;
1034 					}
1035 				else return(0);
1036 			}
1037 		return( p->in.right->tn.lval == o ? STARREG : 0);
1038 		}
1039 
1040 	return( 0 );
1041 	}
1042 
adrcon(val)1043 adrcon( val ) CONSZ val; {
1044 	putchar( '$' );
1045 	printf( CONFMT, val );
1046 	}
1047 
conput(p)1048 conput( p ) register NODE *p; {
1049 	switch( p->in.op ){
1050 
1051 	case ICON:
1052 		acon( p );
1053 		return;
1054 
1055 	case REG:
1056 		putstr( rnames[p->tn.rval] );
1057 		return;
1058 
1059 	default:
1060 		cerror( "illegal conput" );
1061 		}
1062 	}
1063 
1064 /*ARGSUSED*/
insput(p)1065 insput( p ) NODE *p; {
1066 	cerror( "insput" );
1067 	}
1068 
upput(p,size)1069 upput( p, size ) NODE *p; int size; {
1070 	if( size == SZLONG && p->in.op == REG ) {
1071 		putstr( rnames[p->tn.rval + 1] );
1072 		return;
1073 		}
1074 	cerror( "upput" );
1075 	}
1076 
adrput(p)1077 adrput( p ) register NODE *p; {
1078 	register int r;
1079 	/* output an address, with offsets, from p */
1080 
1081 	if( p->in.op == FLD ){
1082 		p = p->in.left;
1083 		}
1084 	switch( p->in.op ){
1085 
1086 	case NAME:
1087 		acon( p );
1088 		return;
1089 
1090 	case ICON:
1091 		/* addressable value of the constant */
1092 		putchar( '$' );
1093 		acon( p );
1094 		return;
1095 
1096 	case REG:
1097 		putstr( rnames[p->tn.rval] );
1098 		return;
1099 
1100 	case OREG:
1101 		r = p->tn.rval;
1102 		if( R2TEST(r) ){ /* double indexing */
1103 			register int flags;
1104 
1105 			flags = R2UPK3(r);
1106 			if( flags & 1 ) putchar('*');
1107 			if( flags & 4 ) putchar('-');
1108 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
1109 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
1110 			if( flags & 2 ) putchar('+');
1111 			printf( "[%s]", rnames[R2UPK2(r)] );
1112 			return;
1113 			}
1114 		if( r == AP ){  /* in the argument region */
1115 			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
1116 			printf( CONFMT, p->tn.lval );
1117 			putstr( "(ap)" );
1118 			return;
1119 			}
1120 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
1121 		printf( "(%s)", rnames[p->tn.rval] );
1122 		return;
1123 
1124 	case UNARY MUL:
1125 		/* STARNM or STARREG found */
1126 		if( tshape(p, STARNM) ) {
1127 			putchar( '*' );
1128 			adrput( p->in.left);
1129 			}
1130 		else {	/* STARREG - really auto inc or dec */
1131 			register NODE *q;
1132 
1133 			q = p->in.left;
1134 			if( q->in.right->tn.lval != tlen(p) )
1135 				cerror("adrput: bad auto-increment/decrement");
1136 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
1137 				rnames[q->in.left->tn.rval],
1138 				(q->in.op==INCR ? "+" : "") );
1139 			p->in.op = OREG;
1140 			p->tn.rval = q->in.left->tn.rval;
1141 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
1142 #ifndef FLEXNAMES
1143 			p->in.name[0] = '\0';
1144 #else
1145 			p->in.name = "";
1146 #endif
1147 			tfree(q);
1148 		}
1149 		return;
1150 
1151 	default:
1152 		cerror( "illegal address" );
1153 		return;
1154 
1155 		}
1156 
1157 	}
1158 
acon(p)1159 acon( p ) register NODE *p; { /* print out a constant */
1160 
1161 	if( p->in.name[0] == '\0' )
1162 		printf( CONFMT, p->tn.lval);
1163 	else {
1164 #ifndef FLEXNAMES
1165 		printf( "%.8s", p->in.name );
1166 #else
1167 		putstr( p->in.name );
1168 #endif
1169 		if( p->tn.lval != 0 ) {
1170 			putchar( '+' );
1171 			printf( CONFMT, p->tn.lval );
1172 			}
1173 		}
1174 	}
1175 
genscall(p,cookie)1176 genscall( p, cookie ) register NODE *p; {
1177 	/* structure valued call */
1178 	return( gencall( p, cookie ) );
1179 	}
1180 
1181 /* tbl */
1182 int gc_numbytes;
1183 /* tbl */
1184 
1185 /*ARGSUSED*/
gencall(p,cookie)1186 gencall( p, cookie ) register NODE *p; {
1187 	/* generate the call given by p */
1188 	register NODE *p1;
1189 	register int temp, temp1;
1190 	register int m;
1191 
1192 	if( p->in.right ) temp = argsize( p->in.right );
1193 	else temp = 0;
1194 
1195 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1196 		/* set aside room for structure return */
1197 
1198 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1199 		else temp1 = temp;
1200 		}
1201 
1202 	if( temp > maxargs ) maxargs = temp;
1203 	SETOFF(temp1,4);
1204 
1205 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
1206 		genargs( p->in.right );
1207 		}
1208 
1209 	p1 = p->in.left;
1210 	if( p1->in.op != ICON ){
1211 		if( p1->in.op != REG ){
1212 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1213 				if( p1->in.op != NAME ){
1214 					order( p1, INAREG );
1215 					}
1216 				}
1217 			}
1218 		}
1219 
1220 /* tbl
1221 	setup gc_numbytes so reference to ZC works */
1222 
1223 	gc_numbytes = temp&(0x3ff);
1224 /* tbl */
1225 
1226 	p->in.op = UNARY CALL;
1227 	m = match( p, INTAREG|INTBREG );
1228 
1229 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
1230 	/* (plus in assignment to gc_numbytes above, for neatness only) */
1231 	if (temp >= 1024)
1232 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
1233 
1234 	return(m != MDONE);
1235 	}
1236 
1237 /* tbl */
1238 char *
1239 ccbranches[] = {
1240 	"eql",
1241 	"neq",
1242 	"leq",
1243 	"lss",
1244 	"geq",
1245 	"gtr",
1246 	"lequ",
1247 	"lssu",
1248 	"gequ",
1249 	"gtru",
1250 	};
1251 /* tbl */
1252 
1253 /*ARGSUSED*/
cbgen(o,lab,mode)1254 cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
1255 
1256 	if( o != 0 && ( o < EQ || o > UGT ) )
1257 		cerror( "bad conditional branch: %s", opst[o] );
1258 	printf( "	j%s	L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab );
1259 	}
1260 
nextcook(p,cookie)1261 nextcook( p, cookie ) NODE *p; {
1262 	/* we have failed to match p with cookie; try another */
1263 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
1264 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1265 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1266 	return( FORREW );
1267 	}
1268 
1269 /*ARGSUSED*/
lastchance(p,cook)1270 lastchance( p, cook ) NODE *p; {
1271 	/* forget it! */
1272 	return(0);
1273 	}
1274 
optim2(p)1275 optim2( p ) register NODE *p; {
1276 	/* do local tree transformations and optimizations */
1277 
1278 	int o;
1279 	int i, mask;
1280 	register NODE *l, *r;
1281 
1282 	switch( o = p->in.op ) {
1283 
1284 	case ASG PLUS:
1285 	case ASG MINUS:
1286 	case ASG MUL:
1287 	case ASG OR:
1288 		/* simple ASG OPSIMP -- reduce range of constant rhs */
1289 		l = p->in.left;
1290 		r = p->in.right;
1291 		if( tlen(l) < SZINT/SZCHAR &&
1292 		    r->in.op==ICON && r->in.name[0]==0 ){
1293 			mask = (1 << tlen(l) * SZCHAR) - 1;
1294 			if( r->tn.lval & (mask & ~(mask >> 1)) )
1295 				r->tn.lval |= ~mask;
1296 			else
1297 				r->tn.lval &= mask;
1298 			}
1299 		break;
1300 
1301 	case AND:
1302 		/* commute L and R to eliminate complements and constants */
1303 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
1304 		    l->in.op == COMPL ) {
1305 			p->in.left = p->in.right;
1306 			p->in.right = l;
1307 			}
1308 		/* fall through */
1309 
1310 	case ASG AND:
1311 		/* change meaning of AND to ~R&L - bic on pdp11/vax */
1312 		r = p->in.right;
1313 		if( r->in.op==ICON && r->in.name[0]==0 ) {
1314 			/* check for degenerate operations */
1315 			l = p->in.left;
1316 			mask = (1 << tlen(l) * SZCHAR) - 1;
1317 			if( o == ASG AND || ISUNSIGNED(r->in.type) ) {
1318 				i = ~r->tn.lval & mask;
1319 				if( i == 0 ) {
1320 					/* redundant mask */
1321 					r->in.op = FREE;
1322 					ncopy(p, l);
1323 					l->in.op = FREE;
1324 					break;
1325 					}
1326 				else if( i == mask )
1327 					/* all bits masked off */
1328 					goto zero;
1329 				r->tn.lval = i;
1330 				if( tlen(l) < SZINT/SZCHAR ){
1331 					/* sign extend */
1332 					if( r->tn.lval & (mask & ~(mask >> 1)) )
1333 						r->tn.lval |= ~mask;
1334 					else
1335 						r->tn.lval &= mask;
1336 					}
1337 				break;
1338 				}
1339 			else if( r->tn.lval == mask &&
1340 				 tlen(l) < SZINT/SZCHAR ) {
1341 				/* use movz instead of bic */
1342 				r->in.op = SCONV;
1343 				r->in.left = l;
1344 				r->in.right = 0;
1345 				r->in.type = ENUNSIGN(l->in.type);
1346 				r->in.su = l->in.su > 1 ? l->in.su : 1;
1347 				ncopy(p, r);
1348 				p->in.left = r;
1349 				p->in.type = INT;
1350 				break;
1351 				}
1352 			/* complement constant */
1353 			r->tn.lval = ~r->tn.lval;
1354 			}
1355 		else if( r->in.op==COMPL ) { /* ~~A => A */
1356 			r->in.op = FREE;
1357 			p->in.right = r->in.left;
1358 			}
1359 		else { /* insert complement node */
1360 			p->in.right = l = talloc();
1361 			l->in.op = COMPL;
1362 			l->in.rall = NOPREF;
1363 			l->in.type = r->in.type;
1364 			l->in.left = r;
1365 			l->in.right = NULL;
1366 			}
1367 		break;
1368 
1369 	case SCONV:
1370 		l = p->in.left;
1371 #if defined(FORT) || defined(SPRECC)
1372 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
1373 		    l->in.type == FLOAT || l->in.type == DOUBLE )
1374 			return;
1375 #else
1376 		if( mixtypes(p, l) ) return;
1377 #endif
1378 		if( l->in.op == PCONV )
1379 			return;
1380 		if( (l->in.op == CALL || l->in.op == UNARY CALL) &&
1381 		    l->in.type != INT && l->in.type != UNSIGNED )
1382 			return;
1383 
1384 		/* Only trust it to get it right if the size is the same */
1385 		if( tlen(p) != tlen(l) )
1386 			return;
1387 
1388 		/* clobber conversion */
1389 		if( l->in.op != FLD )
1390 			l->in.type = p->in.type;
1391 		ncopy( p, l );
1392 		l->in.op = FREE;
1393 
1394 		break;
1395 
1396 	case ASSIGN:
1397 		/*
1398 		 * Conversions are equivalent to assignments;
1399 		 * when the two operations are combined,
1400 		 * we can sometimes zap the conversion.
1401 		 */
1402 		r = p->in.right;
1403 		l = p->in.left;
1404 		if ( r->in.op == SCONV &&
1405 		     !mixtypes(l, r) &&
1406 		     l->in.op != FLD &&
1407 		     tlen(l) == tlen(r) ) {
1408 				p->in.right = r->in.left;
1409 				r->in.op = FREE;
1410 			}
1411 		break;
1412 
1413 	case ULE:
1414 	case ULT:
1415 	case UGE:
1416 	case UGT:
1417 		p->in.op -= (UGE-GE);
1418 		if( degenerate(p) )
1419 			break;
1420 		p->in.op += (UGE-GE);
1421 		break;
1422 
1423 	case EQ:
1424 	case NE:
1425 	case LE:
1426 	case LT:
1427 	case GE:
1428 	case GT:
1429 		if( p->in.left->in.op == SCONV &&
1430 		    p->in.right->in.op == SCONV ) {
1431 			l = p->in.left;
1432 			r = p->in.right;
1433 			if( l->in.type == DOUBLE &&
1434 			    l->in.left->in.type == FLOAT &&
1435 			    r->in.left->in.type == FLOAT ) {
1436 				/* nuke the conversions */
1437 				p->in.left = l->in.left;
1438 				p->in.right = r->in.left;
1439 				l->in.op = FREE;
1440 				r->in.op = FREE;
1441 				}
1442 			/* more? */
1443 			}
1444 		(void) degenerate(p);
1445 		break;
1446 
1447 	case DIV:
1448 		if( p->in.right->in.op == ICON &&
1449 		    p->in.right->tn.name[0] == '\0' &&
1450 		    ISUNSIGNED(p->in.right->in.type) &&
1451 		    (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
1452 			/* easy to do here, harder to do in zzzcode() */
1453 			p->in.op = UGE;
1454 			break;
1455 			}
1456 	case MOD:
1457 	case ASG DIV:
1458 	case ASG MOD:
1459 		/*
1460 		 * optimize DIV and MOD
1461 		 *
1462 		 * basically we spot UCHAR and USHORT and try to do them
1463 		 * as signed ints...  apparently div+mul+sub is always
1464 		 * faster than ediv for finding MOD on the VAX, when
1465 		 * full unsigned MOD isn't needed.
1466 		 *
1467 		 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
1468 		 * are faster for unsigned dividend and a constant divisor
1469 		 * in the right range (.5 to 1 of dividend's range for the
1470 		 * first, .333+ to .5 for the second).  full unsigned is
1471 		 * already done cmp+sub in the appropriate case; the
1472 		 * other cases are less common and require more ambition.
1473 		 */
1474 		if( degenerate(p) )
1475 			break;
1476 		l = p->in.left;
1477 		r = p->in.right;
1478 		if( !ISUNSIGNED(r->in.type) ||
1479 		    tlen(l) >= SZINT/SZCHAR ||
1480 		    !(tlen(r) < SZINT/SZCHAR ||
1481 		      (r->in.op == ICON && r->tn.name[0] == '\0')) )
1482 			break;
1483 		if( r->in.op == ICON )
1484 			r->tn.type = INT;
1485 		else {
1486 			NODE *t = talloc();
1487 			t->in.left = r;
1488 			r = t;
1489 			r->in.op = SCONV;
1490 			r->in.type = INT;
1491 			r->in.right = 0;
1492 			p->in.right = r;
1493 			}
1494 		if( o == DIV || o == MOD ) {
1495 			NODE *t = talloc();
1496 			t->in.left = l;
1497 			l = t;
1498 			l->in.op = SCONV;
1499 			l->in.type = INT;
1500 			l->in.right = 0;
1501 			p->in.left = l;
1502 			}
1503 		/* handle asgops in table */
1504 		break;
1505 
1506 	case RS:
1507 	case ASG RS:
1508 	case LS:
1509 	case ASG LS:
1510 		/* pick up degenerate shifts */
1511 		l = p->in.left;
1512 		r = p->in.right;
1513 		if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
1514 			break;
1515 		i = r->tn.lval;
1516 		if( i < 0 )
1517 			/* front end 'fixes' this? */
1518 			if( o == LS || o == ASG LS )
1519 				o += (RS-LS);
1520 			else
1521 				o += (LS-RS);
1522 		if( (o == RS || o == ASG RS) &&
1523 		    !ISUNSIGNED(l->in.type) )
1524 			/* can't optimize signed right shifts */
1525 			break;
1526 		if( o == LS ) {
1527 			if( i < SZINT )
1528 				break;
1529 			}
1530 		else {
1531 			if( i < tlen(l) * SZCHAR )
1532 				break;
1533 			}
1534 	zero:
1535 		if( !asgop( o ) )
1536 			if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1537 				/* no side effects */
1538 				tfree(l);
1539 				ncopy(p, r);
1540 				r->in.op = FREE;
1541 				p->tn.lval = 0;
1542 				}
1543 			else {
1544 				p->in.op = COMOP;
1545 				r->tn.lval = 0;
1546 				}
1547 		else {
1548 			p->in.op = ASSIGN;
1549 			r->tn.lval = 0;
1550 			}
1551 		break;
1552 		}
1553 	}
1554 
degenerate(p)1555 degenerate(p) register NODE *p; {
1556 	int o;
1557 	int result, i;
1558 	int lower, upper;
1559 	register NODE *l, *r;
1560 
1561 	/*
1562 	 * try to keep degenerate comparisons with constants
1563 	 * out of the table.
1564 	 */
1565 	r = p->in.right;
1566 	l = p->in.left;
1567 	if( r->in.op != ICON ||
1568 	    r->tn.name[0] != '\0' ||
1569 	    tlen(l) >= tlen(r) )
1570 		return (0);
1571 	switch( l->in.type ) {
1572 	case CHAR:
1573 		lower = -(1 << SZCHAR - 1);
1574 		upper = (1 << SZCHAR - 1) - 1;
1575 		break;
1576 	case UCHAR:
1577 		lower = 0;
1578 		upper = (1 << SZCHAR) - 1;
1579 		break;
1580 	case SHORT:
1581 		lower = -(1 << SZSHORT - 1);
1582 		upper = (1 << SZSHORT - 1) - 1;
1583 		break;
1584 	case USHORT:
1585 		lower = 0;
1586 		upper = (1 << SZSHORT) - 1;
1587 		break;
1588 	default:
1589 		cerror("unsupported type in degenerate()");
1590 		}
1591 	i = r->tn.lval;
1592 	switch( o = p->in.op ) {
1593 	case DIV:
1594 	case ASG DIV:
1595 	case MOD:
1596 	case ASG MOD:
1597 		/* DIV and MOD work like EQ */
1598 	case EQ:
1599 	case NE:
1600 		if( lower == 0 && (unsigned) i > upper )
1601 			result = o == NE;
1602 		else if( i < lower || i > upper )
1603 			result = o == NE;
1604 		else
1605 			return (0);
1606 		break;
1607 	case LT:
1608 	case GE:
1609 		if( lower == 0 && (unsigned) i > upper )
1610 			result = o == LT;
1611 		else if( i <= lower )
1612 			result = o != LT;
1613 		else if( i > upper )
1614 			result = o == LT;
1615 		else
1616 			return (0);
1617 		break;
1618 	case LE:
1619 	case GT:
1620 		if( lower == 0 && (unsigned) i >= upper )
1621 			result = o == LE;
1622 		else if( i < lower )
1623 			result = o != LE;
1624 		else if( i >= upper )
1625 			result = o == LE;
1626 		else
1627 			return (0);
1628 		break;
1629 	default:
1630 		cerror("unknown op in degenerate()");
1631 		}
1632 
1633 	if( o == MOD || o == ASG MOD ) {
1634 		r->in.op = FREE;
1635 		ncopy(p, l);
1636 		l->in.op = FREE;
1637 		}
1638 	else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1639 		/* no side effects */
1640 		tfree(l);
1641 		ncopy(p, r);
1642 		r->in.op = FREE;
1643 		p->tn.lval = result;
1644 		}
1645 	else {
1646 		if( o == ASG DIV )
1647 			p->in.op = ASSIGN;
1648 		else {
1649 			p->in.op = COMOP;
1650 			r->tn.type = INT;
1651 			}
1652 		r->tn.lval = result;
1653 		}
1654 	if( logop(o) )
1655 		p->in.type = INT;
1656 
1657 	return (1);
1658 	}
1659 
1660 /* added by jwf */
1661 struct functbl {
1662 	int fop;
1663 	TWORD ftype;
1664 	char *func;
1665 	} opfunc[] = {
1666 	DIV,		TANY,	"udiv",
1667 	MOD,		TANY,	"urem",
1668 	ASG DIV,	TANY,	"audiv",
1669 	ASG MOD,	TANY,	"aurem",
1670 	0,	0,	0 };
1671 
hardops(p)1672 hardops(p)  register NODE *p; {
1673 	/* change hard to do operators into function calls.  */
1674 	register NODE *q;
1675 	register struct functbl *f;
1676 	register o;
1677 	NODE *old,*temp;
1678 
1679 	o = p->in.op;
1680 	if( ! (optype(o)==BITYPE &&
1681 	       (ISUNSIGNED(p->in.left->in.type) ||
1682 		ISUNSIGNED(p->in.right->in.type))) )
1683 		return;
1684 
1685 	for( f=opfunc; f->fop; f++ ) {
1686 		if( o==f->fop ) goto convert;
1687 		}
1688 	return;
1689 
1690 	convert:
1691 	if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' )
1692 		/* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */
1693 		/* save a subroutine call -- use at most 5 instructions */
1694 		return;
1695 	if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR )
1696 		/* optim2() will modify the op into an ordinary int op */
1697 		return;
1698 	if( asgop( o ) ) {
1699 		old = NIL;
1700 		switch( p->in.left->in.op ){
1701 		case FLD:
1702 			q = p->in.left->in.left;
1703 			/*
1704 			 * rewrite (lval.fld /= rval); as
1705 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1706 			 * else the compiler will evaluate lval twice.
1707 			 */
1708 			if( q->in.op == UNARY MUL ){
1709 				/* first allocate a temp storage */
1710 				temp = talloc();
1711 				temp->in.op = OREG;
1712 				temp->tn.rval = TMPREG;
1713 				temp->tn.lval = BITOOR(freetemp(1));
1714 				temp->in.type = INCREF(p->in.type);
1715 #ifdef FLEXNAMES
1716 				temp->in.name = "";
1717 #else
1718 				temp->in.name[0] = '\0';
1719 #endif
1720 				old = q->in.left;
1721 				q->in.left = temp;
1722 			}
1723 			/* fall thru ... */
1724 
1725 		case REG:
1726 		case NAME:
1727 		case OREG:
1728 			/* change ASG OP to a simple OP */
1729 			q = talloc();
1730 			q->in.op = NOASG p->in.op;
1731 			q->in.rall = NOPREF;
1732 			q->in.type = p->in.type;
1733 			q->in.left = tcopy(p->in.left);
1734 			q->in.right = p->in.right;
1735 			p->in.op = ASSIGN;
1736 			p->in.right = q;
1737 			p = q;
1738 			f -= 2; /* Note: this depends on the table order */
1739 			/* on the right side only - replace *temp with
1740 			 *(temp = &lval), build the assignment node */
1741 			if( old ){
1742 				temp = q->in.left->in.left; /* the "*" node */
1743 				q = talloc();
1744 				q->in.op = ASSIGN;
1745 				q->in.left = temp->in.left;
1746 				q->in.right = old;
1747 				q->in.type = old->in.type;
1748 #ifdef FLEXNAMES
1749 				q->in.name = "";
1750 #else
1751 				q->in.name[0] = '\0';
1752 #endif
1753 				temp->in.left = q;
1754 			}
1755 			break;
1756 
1757 		case UNARY MUL:
1758 			/* avoid doing side effects twice */
1759 			q = p->in.left;
1760 			p->in.left = q->in.left;
1761 			q->in.op = FREE;
1762 			break;
1763 
1764 		default:
1765 			cerror( "hardops: can't compute & LHS" );
1766 			}
1767 		}
1768 
1769 	/* build comma op for args to function */
1770 	q = talloc();
1771 	q->in.op = CM;
1772 	q->in.rall = NOPREF;
1773 	q->in.type = INT;
1774 	q->in.left = p->in.left;
1775 	q->in.right = p->in.right;
1776 	p->in.op = CALL;
1777 	p->in.right = q;
1778 
1779 	/* put function name in left node of call */
1780 	p->in.left = q = talloc();
1781 	q->in.op = ICON;
1782 	q->in.rall = NOPREF;
1783 	q->in.type = INCREF( FTN + p->in.type );
1784 #ifndef FLEXNAMES
1785 	strcpy( q->in.name, f->func );
1786 #else
1787 	q->in.name = f->func;
1788 #endif
1789 	q->tn.lval = 0;
1790 	q->tn.rval = 0;
1791 
1792 	}
1793 
zappost(p)1794 zappost(p) NODE *p; {
1795 	/* look for ++ and -- operators and remove them */
1796 
1797 	register int o, ty;
1798 	register NODE *q;
1799 	o = p->in.op;
1800 	ty = optype( o );
1801 
1802 	switch( o ){
1803 
1804 	case INCR:
1805 	case DECR:
1806 			q = p->in.left;
1807 			p->in.right->in.op = FREE;  /* zap constant */
1808 			ncopy( p, q );
1809 			q->in.op = FREE;
1810 			return;
1811 
1812 		}
1813 
1814 	if( ty == BITYPE ) zappost( p->in.right );
1815 	if( ty != LTYPE ) zappost( p->in.left );
1816 }
1817 
fixpre(p)1818 fixpre(p) NODE *p; {
1819 
1820 	register int o, ty;
1821 	o = p->in.op;
1822 	ty = optype( o );
1823 
1824 	switch( o ){
1825 
1826 	case ASG PLUS:
1827 			p->in.op = PLUS;
1828 			break;
1829 	case ASG MINUS:
1830 			p->in.op = MINUS;
1831 			break;
1832 		}
1833 
1834 	if( ty == BITYPE ) fixpre( p->in.right );
1835 	if( ty != LTYPE ) fixpre( p->in.left );
1836 }
1837 
1838 /*ARGSUSED*/
addroreg(l)1839 NODE * addroreg(l) NODE *l;
1840 				/* OREG was built in clocal()
1841 				 * for an auto or formal parameter
1842 				 * now its address is being taken
1843 				 * local code must unwind it
1844 				 * back to PLUS/MINUS REG ICON
1845 				 * according to local conventions
1846 				 */
1847 {
1848 	cerror("address of OREG taken");
1849 	/*NOTREACHED*/
1850 }
1851 
1852 
1853 
1854 # ifndef ONEPASS
main(argc,argv)1855 main( argc, argv ) char *argv[]; {
1856 	return( mainp2( argc, argv ) );
1857 	}
1858 # endif
1859 
strip(p)1860 strip(p) register NODE *p; {
1861 	NODE *q;
1862 
1863 	/* strip nodes off the top when no side effects occur */
1864 	for( ; ; ) {
1865 		switch( p->in.op ) {
1866 		case SCONV:			/* remove lint tidbits */
1867 			q = p->in.left;
1868 			ncopy( p, q );
1869 			q->in.op = FREE;
1870 			break;
1871 		/* could probably add a few more here */
1872 		default:
1873 			return;
1874 			}
1875 		}
1876 	}
1877 
myreader(p)1878 myreader(p) register NODE *p; {
1879 	strip( p );		/* strip off operations with no side effects */
1880 	canon( p );		/* expands r-vals for fields */
1881 	walkf( p, hardops );	/* convert ops to function calls */
1882 	walkf( p, optim2 );
1883 	}
1884