xref: /original-bsd/old/pcc/ccom.vax/local2.c (revision f0fd5f8a)
1 static char *sccsid ="@(#)local2.c	1.1 (Berkeley) 12/15/82";
2 # include "mfile2"
3 # include "ctype.h"
4 # ifdef FORT
5 int ftlab1, ftlab2;
6 # endif
7 /* a lot of the machine dependent parts of the second pass */
8 
9 # define BITMASK(n) ((1L<<n)-1)
10 
11 where(c){
12 	fprintf( stderr, "%s, line %d: ", filename, lineno );
13 	}
14 
15 lineid( l, fn ) char *fn; {
16 	/* identify line l and file fn */
17 	printf( "#	line %d, file %s\n", l, fn );
18 	}
19 
20 
21 eobl2(){
22 	OFFSZ spoff;	/* offset from stack pointer */
23 #ifdef FORT
24 	spoff = maxoff;
25 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
26 	spoff /= SZCHAR;
27 	SETOFF(spoff,4);
28 #ifndef FLEXNAMES
29 	printf( "	.set	.F%d,%ld\n", ftnno, spoff );
30 #else
31 	/* SHOULD BE L%d ... ftnno but must change pc/f77 */
32 	printf( "	.set	LF%d,%ld\n", ftnno, spoff );
33 #endif
34 #else
35 	extern int ftlab1, ftlab2;
36 
37 	spoff = maxoff;
38 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
39 	spoff /= SZCHAR;
40 	SETOFF(spoff,4);
41 	printf( "L%d:\n", ftlab1);
42 	if( spoff!=0 )
43 		if( spoff < 64 )
44 			printf( "	subl2	$%ld,sp\n", spoff);
45 		else
46 			printf( "	movab	-%ld(sp),sp\n", spoff);
47 	printf( "	jbr 	L%d\n", ftlab2);
48 #endif
49 	maxargs = -1;
50 	}
51 
52 struct hoptab { int opmask; char * opstring; } ioptab[] = {
53 
54 	ASG PLUS, "add",
55 	ASG MINUS, "sub",
56 	ASG MUL, "mul",
57 	ASG DIV, "div",
58 	ASG OR, "bis",
59 	ASG ER,	"xor",
60 	ASG AND, "bic",
61 	PLUS,	"add",
62 	MINUS,	"sub",
63 	MUL,	"mul",
64 	DIV,	"div",
65 	OR,	"bis",
66 	ER,	"xor",
67 	AND,	"bic",
68 	-1, ""    };
69 
70 hopcode( f, o ){
71 	/* output the appropriate string from the above table */
72 
73 	register struct hoptab *q;
74 
75 	for( q = ioptab;  q->opmask>=0; ++q ){
76 		if( q->opmask == o ){
77 			printf( "%s", q->opstring );
78 /* tbl
79 			if( f == 'F' ) printf( "e" );
80 			else if( f == 'D' ) printf( "d" );
81    tbl */
82 /* tbl */
83 			switch( f ) {
84 				case 'L':
85 				case 'W':
86 				case 'B':
87 				case 'D':
88 				case 'F':
89 					printf("%c", tolower(f));
90 					break;
91 
92 				}
93 /* tbl */
94 			return;
95 			}
96 		}
97 	cerror( "no hoptab for %s", opst[o] );
98 	}
99 
100 char *
101 rnames[] = {  /* keyed to register number tokens */
102 
103 	"r0", "r1",
104 	"r2", "r3", "r4", "r5",
105 	"r6", "r7", "r8", "r9", "r10", "r11",
106 	"ap", "fp", "sp", "pc",
107 
108 	};
109 
110 int rstatus[] = {
111 	SAREG|STAREG, SAREG|STAREG,
112 	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
113 	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
114 	SAREG, SAREG, SAREG, SAREG,
115 
116 	};
117 
118 tlen(p) NODE *p;
119 {
120 	switch(p->in.type) {
121 		case CHAR:
122 		case UCHAR:
123 			return(1);
124 
125 		case SHORT:
126 		case USHORT:
127 			return(2);
128 
129 		case DOUBLE:
130 			return(8);
131 
132 		default:
133 			return(4);
134 		}
135 }
136 
137 mixtypes(p, q) NODE *p, *q;
138 {
139 	register tp, tq;
140 
141 	tp = p->in.type;
142 	tq = q->in.type;
143 
144 	return( (tp==FLOAT || tp==DOUBLE) !=
145 		(tq==FLOAT || tq==DOUBLE) );
146 }
147 
148 prtype(n) NODE *n;
149 {
150 	switch (n->in.type)
151 		{
152 		case DOUBLE:
153 			printf("d");
154 			return;
155 
156 		case FLOAT:
157 			printf("f");
158 			return;
159 
160 		case LONG:
161 		case ULONG:
162 		case INT:
163 		case UNSIGNED:
164 			printf("l");
165 			return;
166 
167 		case SHORT:
168 		case USHORT:
169 			printf("w");
170 			return;
171 
172 		case CHAR:
173 		case UCHAR:
174 			printf("b");
175 			return;
176 
177 		default:
178 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
179 			else {
180 				printf("l");
181 				return;
182 				}
183 		}
184 }
185 
186 zzzcode( p, c ) register NODE *p; {
187 	register m;
188 	CONSZ val;
189 	switch( c ){
190 
191 	case 'N':  /* logical ops, turned into 0-1 */
192 		/* use register given by register 1 */
193 		cbgen( 0, m=getlab(), 'I' );
194 		deflab( p->bn.label );
195 		printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );
196 		deflab( m );
197 		return;
198 
199 	case 'I':
200 	case 'P':
201 		cbgen( p->in.op, p->bn.label, c );
202 		return;
203 
204 	case 'A':
205 		{
206 		register NODE *l, *r;
207 
208 		if (xdebug) eprint(p, 0, &val, &val);
209 		r = getlr(p, 'R');
210 		if (optype(p->in.op) == LTYPE || p->in.op == UNARY MUL)
211 			{
212 			l = resc;
213 			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
214 			}
215 		else
216 			l = getlr(p, 'L');
217 		if (r->in.op == ICON)
218 			if(r->in.name[0] == '\0')
219 				{
220 				if (r->tn.lval == 0)
221 					{
222 					printf("clr");
223 					prtype(l);
224 					printf("	");
225 					adrput(l);
226 					return;
227 					}
228 				if (r->tn.lval < 0 && r->tn.lval >= -63)
229 					{
230 					printf("mneg");
231 					prtype(l);
232 					r->tn.lval = -r->tn.lval;
233 					goto ops;
234 					}
235 				r->in.type = (r->tn.lval < 0 ?
236 						(r->tn.lval >= -128 ? CHAR
237 						: (r->tn.lval >= -32768 ? SHORT
238 						: INT )) : r->in.type);
239 				r->in.type = (r->tn.lval >= 0 ?
240 						(r->tn.lval <= 63 ? INT
241 						: ( r->tn.lval <= 127 ? CHAR
242 						: (r->tn.lval <= 255 ? UCHAR
243 						: (r->tn.lval <= 32767 ? SHORT
244 						: (r->tn.lval <= 65535 ? USHORT
245 						: INT ))))) : r->in.type );
246 				}
247 				else
248 					{
249 					printf("moval");
250 					printf("	");
251 					acon(r);
252 					printf(",");
253 					adrput(l);
254 					return;
255 					}
256 
257 		if (l->in.op == REG && l->in.type != FLOAT && l->in.type != DOUBLE)
258 			{
259 			if( tlen(l) < tlen(r) )
260 				{
261 				if (!mixtypes(l,r))
262 					{
263 					!ISUNSIGNED(l->in.type)?
264 						printf("cvt"):
265 						printf("movz");
266 					prtype(l);
267 					printf("l");
268 					goto ops;
269 					}
270 				else
271 					{
272 					printf("cvt");
273 					prtype(r);
274 					prtype(l);
275 					printf("	");
276 					adrput(r);
277 					printf(",");
278 					adrput(l);
279 					printf("cvt");
280 					prtype(l);
281 					printf("l");
282 					printf("	");
283 					adrput(l);
284 					printf(",");
285 					adrput(l);
286 					return;
287 					}
288 				}
289 			else
290 				{
291 			l->in.type = INT;
292 				}
293 			}
294 		if (!mixtypes(l,r))
295 			{
296 			if (tlen(l) == tlen(r))
297 				{
298 				printf("mov");
299 				prtype(l);
300 				goto ops;
301 				}
302 			else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
303 				{
304 				printf("movz");
305 				}
306 			else
307 				{
308 				printf("cvt");
309 				}
310 			}
311 		else
312 			{
313 			printf("cvt");
314 			}
315 		prtype(r);
316 		prtype(l);
317 	ops:
318 		printf("	");
319 		adrput(r);
320 		printf(",");
321 		adrput(l);
322 		return;
323 		}
324 
325 	case 'B':	/* get oreg value in temp register for left shift */
326 		{
327 		register NODE *r;
328 		if (xdebug) eprint(p, 0, &val, &val);
329 		r = p->in.right;
330 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
331 			printf("movl");
332 		else {
333 			printf("cvt");
334 			prtype(r);
335 			printf("l");
336 			}
337 		return;
338 		}
339 
340 	case 'C':	/* num words pushed on arg stack */
341 		{
342 		extern int gc_numbytes;
343 		extern int xdebug;
344 
345 		if (xdebug) printf("->%d<-",gc_numbytes);
346 
347 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
348 		return;
349 		}
350 
351 	case 'D':	/* INCR and DECR */
352 		zzzcode(p->in.left, 'A');
353 		printf("\n	");
354 
355 	case 'E':	/* INCR and DECR, FOREFF */
356 		if (p->in.right->tn.lval == 1)
357 			{
358 			printf("%s", (p->in.op == INCR ? "inc" : "dec") );
359 			prtype(p->in.left);
360 			printf("	");
361 			adrput(p->in.left);
362 			return;
363 			}
364 		printf("%s", (p->in.op == INCR ? "add" : "sub") );
365 		prtype(p->in.left);
366 		printf("2	");
367 		adrput(p->in.right);
368 		printf(",");
369 		adrput(p->in.left);
370 		return;
371 
372 	case 'F':	/* register type of right operand */
373 		{
374 		register NODE *n;
375 		extern int xdebug;
376 		register int ty;
377 
378 		n = getlr( p, 'R' );
379 		ty = n->in.type;
380 
381 		if (xdebug) printf("->%d<-", ty);
382 
383 		if ( ty==DOUBLE) printf("d");
384 		else if ( ty==FLOAT ) printf("f");
385 		else printf("l");
386 		return;
387 		}
388 
389 	case 'L':	/* type of left operand */
390 	case 'R':	/* type of right operand */
391 		{
392 		register NODE *n;
393 		extern int xdebug;
394 
395 		n = getlr ( p, c);
396 		if (xdebug) printf("->%d<-", n->in.type);
397 
398 		prtype(n);
399 		return;
400 		}
401 
402 	case 'Z':	/* complement mask for bit instr */
403 		printf("$%ld", ~p->in.right->tn.lval);
404 		return;
405 
406 	case 'U':	/* 32 - n, for unsigned right shifts */
407 		printf("$%d", 32 - p->in.right->tn.lval );
408 		return;
409 
410 	case 'T':	/* rounded structure length for arguments */
411 		{
412 		int size;
413 
414 		size = p->stn.stsize;
415 		SETOFF( size, 4);
416 		printf("$%d", size);
417 		return;
418 		}
419 
420 	case 'S':  /* structure assignment */
421 		{
422 			register NODE *l, *r;
423 			register size;
424 
425 			if( p->in.op == STASG ){
426 				l = p->in.left;
427 				r = p->in.right;
428 
429 				}
430 			else if( p->in.op == STARG ){  /* store an arg into a temporary */
431 				l = getlr( p, '3' );
432 				r = p->in.left;
433 				}
434 			else cerror( "STASG bad" );
435 
436 			if( r->in.op == ICON ) r->in.op = NAME;
437 			else if( r->in.op == REG ) r->in.op = OREG;
438 			else if( r->in.op != OREG ) cerror( "STASG-r" );
439 
440 			size = p->stn.stsize;
441 
442 			if( size <= 0 || size > 65535 )
443 				cerror("structure size <0=0 or >65535");
444 
445 			switch(size) {
446 				case 1:
447 					printf("	movb	");
448 					break;
449 				case 2:
450 					printf("	movw	");
451 					break;
452 				case 4:
453 					printf("	movl	");
454 					break;
455 				case 8:
456 					printf("	movq	");
457 					break;
458 				default:
459 					printf("	movc3	$%d,", size);
460 					break;
461 			}
462 			adrput(r);
463 			printf(",");
464 			adrput(l);
465 			printf("\n");
466 
467 			if( r->in.op == NAME ) r->in.op = ICON;
468 			else if( r->in.op == OREG ) r->in.op = REG;
469 
470 			}
471 		break;
472 
473 	default:
474 		cerror( "illegal zzzcode" );
475 		}
476 	}
477 
478 rmove( rt, rs, t ){
479 	printf( "	%s	%s,%s\n",
480 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
481 		rnames[rs], rnames[rt] );
482 	}
483 
484 struct respref
485 respref[] = {
486 	INTAREG|INTBREG,	INTAREG|INTBREG,
487 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
488 	INTEMP,	INTEMP,
489 	FORARG,	FORARG,
490 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
491 	0,	0 };
492 
493 setregs(){ /* set up temporary registers */
494 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
495 	;
496 	}
497 
498 szty(t){ /* size, in registers, needed to hold thing of type t */
499 	return( (t==DOUBLE||t==FLOAT) ? 2 : 1 );
500 	}
501 
502 rewfld( p ) NODE *p; {
503 	return(1);
504 	}
505 
506 callreg(p) NODE *p; {
507 	return( R0 );
508 	}
509 
510 base( p ) register NODE *p; {
511 	register int o = p->in.op;
512 
513 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
514 	if( o==REG ) return( p->tn.rval );
515     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
516 		return( p->in.left->tn.rval );
517     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
518 		return( p->tn.rval + 0200*1 );
519 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
520 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
521 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
522 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
523 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
524 	return( -1 );
525 	}
526 
527 offset( p, tyl ) register NODE *p; int tyl; {
528 
529 	if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
530 	if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
531 	      (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
532 	      && (1<<p->in.right->tn.lval)==tyl))
533 		return( p->in.left->tn.rval );
534 	return( -1 );
535 	}
536 
537 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
538 	register NODE *t;
539 	register int i;
540 	NODE *f;
541 
542 	p->in.op = OREG;
543 	f = p->in.left; 	/* have to free this subtree later */
544 
545 	/* init base */
546 	switch (q->in.op) {
547 		case ICON:
548 		case REG:
549 		case OREG:
550 			t = q;
551 			break;
552 
553 		case MINUS:
554 			q->in.right->tn.lval = -q->in.right->tn.lval;
555 		case PLUS:
556 			t = q->in.right;
557 			break;
558 
559 		case INCR:
560 		case ASG MINUS:
561 			t = q->in.left;
562 			break;
563 
564 		case UNARY MUL:
565 			t = q->in.left->in.left;
566 			break;
567 
568 		default:
569 			cerror("illegal makeor2");
570 	}
571 
572 	p->tn.lval = t->tn.lval;
573 #ifndef FLEXNAMES
574 	for(i=0; i<NCHNAM; ++i)
575 		p->in.name[i] = t->in.name[i];
576 #else
577 	p->in.name = t->in.name;
578 #endif
579 
580 	/* init offset */
581 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
582 
583 	tfree(f);
584 	return;
585 	}
586 
587 canaddr( p ) NODE *p; {
588 	register int o = p->in.op;
589 
590 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
591 	return(0);
592 	}
593 
594 shltype( o, p ) register NODE *p; {
595 	return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
596 	}
597 
598 flshape( p ) register NODE *p; {
599 	return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
600 		(p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
601 	}
602 
603 shtemp( p ) register NODE *p; {
604 	if( p->in.op == STARG ) p = p->in.left;
605 	return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
606 	}
607 
608 shumul( p ) register NODE *p; {
609 	register o;
610 	extern int xdebug;
611 
612 	if (xdebug) {
613 		 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
614 		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
615 		}
616 
617 
618 	o = p->in.op;
619 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
620 
621 	if( ( o == INCR || o == ASG MINUS ) &&
622 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
623 	    p->in.right->in.name[0] == '\0' )
624 		{
625 		switch (p->in.left->in.type)
626 			{
627 			case CHAR|PTR:
628 			case UCHAR|PTR:
629 				o = 1;
630 				break;
631 
632 			case SHORT|PTR:
633 			case USHORT|PTR:
634 				o = 2;
635 				break;
636 
637 			case INT|PTR:
638 			case UNSIGNED|PTR:
639 			case LONG|PTR:
640 			case ULONG|PTR:
641 			case FLOAT|PTR:
642 				o = 4;
643 				break;
644 
645 			case DOUBLE|PTR:
646 				o = 8;
647 				break;
648 
649 			default:
650 				if ( ISPTR(p->in.left->in.type) ) {
651 					o = 4;
652 					break;
653 					}
654 				else return(0);
655 			}
656 		return( p->in.right->tn.lval == o ? STARREG : 0);
657 		}
658 
659 	return( 0 );
660 	}
661 
662 adrcon( val ) CONSZ val; {
663 	printf( "$" );
664 	printf( CONFMT, val );
665 	}
666 
667 conput( p ) register NODE *p; {
668 	switch( p->in.op ){
669 
670 	case ICON:
671 		acon( p );
672 		return;
673 
674 	case REG:
675 		printf( "%s", rnames[p->tn.rval] );
676 		return;
677 
678 	default:
679 		cerror( "illegal conput" );
680 		}
681 	}
682 
683 insput( p ) register NODE *p; {
684 	cerror( "insput" );
685 	}
686 
687 upput( p ) register NODE *p; {
688 	cerror( "upput" );
689 	}
690 
691 adrput( p ) register NODE *p; {
692 	register int r;
693 	/* output an address, with offsets, from p */
694 
695 	if( p->in.op == FLD ){
696 		p = p->in.left;
697 		}
698 	switch( p->in.op ){
699 
700 	case NAME:
701 		acon( p );
702 		return;
703 
704 	case ICON:
705 		/* addressable value of the constant */
706 		printf( "$" );
707 		acon( p );
708 		return;
709 
710 	case REG:
711 		printf( "%s", rnames[p->tn.rval] );
712 		return;
713 
714 	case OREG:
715 		r = p->tn.rval;
716 		if( R2TEST(r) ){ /* double indexing */
717 			register int flags;
718 
719 			flags = R2UPK3(r);
720 			if( flags & 1 ) printf("*");
721 			if( flags & 4 ) printf("-");
722 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
723 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
724 			if( flags & 2 ) printf("+");
725 			printf( "[%s]", rnames[R2UPK2(r)] );
726 			return;
727 			}
728 		if( r == AP ){  /* in the argument region */
729 			if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" );
730 			printf( CONFMT, p->tn.lval );
731 			printf( "(ap)" );
732 			return;
733 			}
734 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
735 		printf( "(%s)", rnames[p->tn.rval] );
736 		return;
737 
738 	case UNARY MUL:
739 		/* STARNM or STARREG found */
740 		if( tshape(p, STARNM) ) {
741 			printf( "*" );
742 			adrput( p->in.left);
743 			}
744 		else {	/* STARREG - really auto inc or dec */
745 			register NODE *q;
746 
747 /* tbl
748 			p = p->in.left;
749 			p->in.left->in.op = OREG;
750 			if( p->in.op == INCR ) {
751 				adrput( p->in.left );
752 				printf( "+" );
753 				}
754 			else {
755 				printf( "-" );
756 				adrput( p->in.left );
757 				}
758    tbl */
759 			printf("%s(%s)%s", (p->in.left->in.op==INCR ? "" : "-"),
760 				rnames[p->in.left->in.left->tn.rval],
761 				(p->in.left->in.op==INCR ? "+" : "") );
762 			p->in.op = OREG;
763 			p->tn.rval = p->in.left->in.left->tn.rval;
764 			q = p->in.left;
765 			p->tn.lval = (p->in.left->in.op == INCR ? -p->in.left->in.right->tn.lval : 0);
766 #ifndef FLEXNAMES
767 			p->in.name[0] = '\0';
768 #else
769 			p->in.name = "";
770 #endif
771 			tfree(q);
772 		}
773 		return;
774 
775 	default:
776 		cerror( "illegal address" );
777 		return;
778 
779 		}
780 
781 	}
782 
783 acon( p ) register NODE *p; { /* print out a constant */
784 
785 	if( p->in.name[0] == '\0' ){
786 		printf( CONFMT, p->tn.lval);
787 		}
788 	else if( p->tn.lval == 0 ) {
789 #ifndef FLEXNAMES
790 		printf( "%.8s", p->in.name );
791 #else
792 		printf( "%s", p->in.name );
793 #endif
794 		}
795 	else {
796 #ifndef FLEXNAMES
797 		printf( "%.8s+", p->in.name );
798 #else
799 		printf( "%s+", p->in.name );
800 #endif
801 		printf( CONFMT, p->tn.lval );
802 		}
803 	}
804 
805 /*
806 aacon( p ) register NODE *p; { /* print out a constant */
807 /*
808 
809 	if( p->in.name[0] == '\0' ){
810 		printf( CONFMT, p->tn.lval);
811 		return( 0 );
812 		}
813 	else if( p->tn.lval == 0 ) {
814 #ifndef FLEXNAMES
815 		printf( "$%.8s", p->in.name );
816 #else
817 		printf( "$%s", p->in.name );
818 #endif
819 		return( 1 );
820 		}
821 	else {
822 		printf( "$(" );
823 		printf( CONFMT, p->tn.lval );
824 		printf( "+" );
825 #ifndef FLEXNAMES
826 		printf( "%.8s)", p->in.name );
827 #else
828 		printf( "%s)", p->in.name );
829 #endif
830 		return(1);
831 		}
832 	}
833  */
834 
835 genscall( p, cookie ) register NODE *p; {
836 	/* structure valued call */
837 	return( gencall( p, cookie ) );
838 	}
839 
840 /* tbl */
841 int gc_numbytes;
842 /* tbl */
843 
844 gencall( p, cookie ) register NODE *p; {
845 	/* generate the call given by p */
846 	register NODE *p1, *ptemp;
847 	register temp, temp1;
848 	register m;
849 
850 	if( p->in.right ) temp = argsize( p->in.right );
851 	else temp = 0;
852 
853 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
854 		/* set aside room for structure return */
855 
856 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
857 		else temp1 = temp;
858 		}
859 
860 	if( temp > maxargs ) maxargs = temp;
861 	SETOFF(temp1,4);
862 
863 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
864 		ptemp = talloc();
865 		ptemp->in.op = OREG;
866 		ptemp->tn.lval = -1;
867 		ptemp->tn.rval = SP;
868 #ifndef FLEXNAMES
869 		ptemp->in.name[0] = '\0';
870 #else
871 		ptemp->in.name = "";
872 #endif
873 		ptemp->in.rall = NOPREF;
874 		ptemp->in.su = 0;
875 		genargs( p->in.right, ptemp );
876 		ptemp->in.op = FREE;
877 		}
878 
879 	p1 = p->in.left;
880 	if( p1->in.op != ICON ){
881 		if( p1->in.op != REG ){
882 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
883 				if( p1->in.op != NAME ){
884 					order( p1, INAREG );
885 					}
886 				}
887 			}
888 		}
889 
890 /*
891 	if( p1->in.op == REG && p->tn.rval == R5 ){
892 		cerror( "call register overwrite" );
893 		}
894  */
895 /* tbl
896 	setup gc_numbytes so reference to ZC works */
897 
898 	gc_numbytes = temp&(0x3ff);
899 /* tbl */
900 
901 	p->in.op = UNARY CALL;
902 	m = match( p, INTAREG|INTBREG );
903 
904 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
905 	/* (plus in assignment to gc_numbytes above, for neatness only) */
906 	if (temp >= 1024)
907 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
908 
909 /* tbl
910 	switch( temp ) {
911 	case 0:
912 		break;
913 	case 2:
914 		printf( "	tst	(sp)+\n" );
915 		break;
916 	case 4:
917 		printf( "	cmp	(sp)+,(sp)+\n" );
918 		break;
919 	default:
920 		printf( "	add	$%d,sp\n", temp);
921 		}
922    tbl */
923 	return(m != MDONE);
924 	}
925 
926 /* tbl */
927 char *
928 ccbranches[] = {
929 	"	jeql	L%d\n",
930 	"	jneq	L%d\n",
931 	"	jleq	L%d\n",
932 	"	jlss	L%d\n",
933 	"	jgeq	L%d\n",
934 	"	jgtr	L%d\n",
935 	"	jlequ	L%d\n",
936 	"	jlssu	L%d\n",
937 	"	jgequ	L%d\n",
938 	"	jgtru	L%d\n",
939 	};
940 /* tbl */
941 
942 cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
943 
944 /* tbl */
945 	if( o == 0 ) printf( "	jbr	L%d\n", lab );
946 /* tbl */
947 	else {
948 		if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
949 		printf( ccbranches[o-EQ], lab );
950 		}
951 	}
952 
953 nextcook( p, cookie ) NODE *p; {
954 	/* we have failed to match p with cookie; try another */
955 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
956 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
957 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
958 	return( FORREW );
959 	}
960 
961 lastchance( p, cook ) NODE *p; {
962 	/* forget it! */
963 	return(0);
964 	}
965 
966 optim2( p ) register NODE *p; {
967 	/* do local tree transformations and optimizations */
968 
969 	register NODE *r;
970 
971 	switch( p->in.op ) {
972 
973 	case AND:
974 		/* commute L and R to eliminate compliments and constants */
975 		if( (p->in.left->in.op==ICON&&p->in.left->in.name[0]==0) || p->in.left->in.op==COMPL ) {
976 			r = p->in.left;
977 			p->in.left = p->in.right;
978 			p->in.right = r;
979 			}
980 	case ASG AND:
981 		/* change meaning of AND to ~R&L - bic on pdp11 */
982 		r = p->in.right;
983 		if( r->in.op==ICON && r->in.name[0]==0 ) { /* compliment constant */
984 			r->tn.lval = ~r->tn.lval;
985 			}
986 		else if( r->in.op==COMPL ) { /* ~~A => A */
987 			r->in.op = FREE;
988 			p->in.right = r->in.left;
989 			}
990 		else { /* insert complement node */
991 			p->in.right = talloc();
992 			p->in.right->in.op = COMPL;
993 			p->in.right->in.rall = NOPREF;
994 			p->in.right->in.type = r->in.type;
995 			p->in.right->in.left = r;
996 			p->in.right->in.right = NULL;
997 			}
998 		break;
999 
1000 		}
1001 	}
1002 
1003 NODE * addroreg(l)
1004 				/* OREG was built in clocal()
1005 				 * for an auto or formal parameter
1006 				 * now its address is being taken
1007 				 * local code must unwind it
1008 				 * back to PLUS/MINUS REG ICON
1009 				 * according to local conventions
1010 				 */
1011 {
1012 	cerror("address of OREG taken");
1013 }
1014 
1015 
1016 
1017 # ifndef ONEPASS
1018 main( argc, argv ) char *argv[]; {
1019 	return( mainp2( argc, argv ) );
1020 	}
1021 # endif
1022 
1023 
1024 /* added by jwf */
1025 struct functbl {
1026 	int fop;
1027 	TWORD ftype;
1028 	char *func;
1029 	} opfunc[] = {
1030 	DIV,		TANY,	"udiv",
1031 	MOD,		TANY,	"urem",
1032 	ASG DIV,	TANY,	"udiv",
1033 	ASG MOD,	TANY,	"urem",
1034 	0,	0,	0 };
1035 
1036 hardops(p)  register NODE *p; {
1037 	/* change hard to do operators into function calls.  */
1038 	register NODE *q;
1039 	register struct functbl *f;
1040 	register o;
1041 	register TWORD t;
1042 
1043 	o = p->in.op;
1044 	t = p->in.type;
1045 	if( t!=UNSIGNED && t!=ULONG ) return;
1046 
1047 	for( f=opfunc; f->fop; f++ ) {
1048 		if( o==f->fop ) goto convert;
1049 		}
1050 	return;
1051 
1052 	/* need to rewrite tree for ASG OP */
1053 	/* must change ASG OP to a simple OP */
1054 	convert:
1055 	if( asgop( o ) ) {
1056 		q = talloc();
1057 		switch( p->in.op ) {
1058 			case ASG DIV:
1059 				q->in.op = DIV;
1060 				break;
1061 			case ASG MOD:
1062 				q->in.op = MOD;
1063 				break;
1064 		}
1065 		q->in.rall = NOPREF;
1066 		q->in.type = p->in.type;
1067 		q->in.left = tcopy(p->in.left);
1068 		q->in.right = p->in.right;
1069 		p->in.op = ASSIGN;
1070 		p->in.right = q;
1071 		zappost(q->in.left); /* remove post-INCR(DECR) from new node */
1072 		fixpre(q->in.left);	/* change pre-INCR(DECR) to +/-	*/
1073 		p = q;
1074 
1075 	}
1076 
1077 	/* build comma op for args to function */
1078 	q = talloc();
1079 	q->in.op = CM;
1080 	q->in.rall = NOPREF;
1081 	q->in.type = INT;
1082 	q->in.left = p->in.left;
1083 	q->in.right = p->in.right;
1084 	p->in.op = CALL;
1085 	p->in.right = q;
1086 
1087 	/* put function name in left node of call */
1088 	p->in.left = q = talloc();
1089 	q->in.op = ICON;
1090 	q->in.rall = NOPREF;
1091 	q->in.type = INCREF( FTN + p->in.type );
1092 #ifndef FLEXNAMES
1093 	strcpy( q->in.name, f->func );
1094 #else
1095 	q->in.name = f->func;
1096 #endif
1097 	q->tn.lval = 0;
1098 	q->tn.rval = 0;
1099 
1100 	return;
1101 
1102 	}
1103 
1104 zappost(p) NODE *p; {
1105 	/* look for ++ and -- operators and remove them */
1106 
1107 	register o, ty;
1108 	register NODE *q;
1109 	o = p->in.op;
1110 	ty = optype( o );
1111 
1112 	switch( o ){
1113 
1114 	case INCR:
1115 	case DECR:
1116 			q = p->in.left;
1117 			p->in.right->in.op = FREE;  /* zap constant */
1118 			ncopy( p, q );
1119 			q->in.op = FREE;
1120 			return;
1121 
1122 		}
1123 
1124 	if( ty == BITYPE ) zappost( p->in.right );
1125 	if( ty != LTYPE ) zappost( p->in.left );
1126 }
1127 
1128 fixpre(p) NODE *p; {
1129 
1130 	register o, ty;
1131 	o = p->in.op;
1132 	ty = optype( o );
1133 
1134 	switch( o ){
1135 
1136 	case ASG PLUS:
1137 			p->in.op = PLUS;
1138 			break;
1139 	case ASG MINUS:
1140 			p->in.op = MINUS;
1141 			break;
1142 		}
1143 
1144 	if( ty == BITYPE ) fixpre( p->in.right );
1145 	if( ty != LTYPE ) fixpre( p->in.left );
1146 }
1147 
1148 myreader(p) register NODE *p; {
1149 	walkf( p, hardops );	/* convert ops to function calls */
1150 	canon( p );		/* expands r-vals for fileds */
1151 	walkf( p, optim2 );
1152 	/* jwf toff = 0;  /* stack offset swindle */
1153 	}
1154 
1155 
1156