"vtroff -man -" now works like "vtroff -man"
[unix-history] / usr / src / old / pcc / ccom.vax / local2.c
CommitLineData
439a068b
ML
1static char *sccsid ="@(#)local2.c 1.1 (Berkeley) %G%";
2# include "mfile2"
3# include "ctype.h"
4# ifdef FORT
5int 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
11where(c){
12 fprintf( stderr, "%s, line %d: ", filename, lineno );
13 }
14
15lineid( l, fn ) char *fn; {
16 /* identify line l and file fn */
17 printf( "# line %d, file %s\n", l, fn );
18 }
19
20
21eobl2(){
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
52struct 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
70hopcode( 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
100char *
101rnames[] = { /* 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
110int 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
118tlen(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
137mixtypes(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
148prtype(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
186zzzcode( 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
478rmove( rt, rs, t ){
479 printf( " %s %s,%s\n",
480 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
481 rnames[rs], rnames[rt] );
482 }
483
484struct respref
485respref[] = {
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
493setregs(){ /* set up temporary registers */
494 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
495 ;
496 }
497
498szty(t){ /* size, in registers, needed to hold thing of type t */
499 return( (t==DOUBLE||t==FLOAT) ? 2 : 1 );
500 }
501
502rewfld( p ) NODE *p; {
503 return(1);
504 }
505
506callreg(p) NODE *p; {
507 return( R0 );
508 }
509
510base( 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
527offset( 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
537makeor2( 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
587canaddr( 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
594shltype( o, p ) register NODE *p; {
595 return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
596 }
597
598flshape( 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
603shtemp( 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
608shumul( 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
662adrcon( val ) CONSZ val; {
663 printf( "$" );
664 printf( CONFMT, val );
665 }
666
667conput( 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
683insput( p ) register NODE *p; {
684 cerror( "insput" );
685 }
686
687upput( p ) register NODE *p; {
688 cerror( "upput" );
689 }
690
691adrput( 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
783acon( 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/*
806aacon( 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
835genscall( p, cookie ) register NODE *p; {
836 /* structure valued call */
837 return( gencall( p, cookie ) );
838 }
839
840/* tbl */
841int gc_numbytes;
842/* tbl */
843
844gencall( 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 */
927char *
928ccbranches[] = {
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
942cbgen( 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
953nextcook( 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
961lastchance( p, cook ) NODE *p; {
962 /* forget it! */
963 return(0);
964 }
965
966optim2( 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
1003NODE * 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
1018main( argc, argv ) char *argv[]; {
1019 return( mainp2( argc, argv ) );
1020 }
1021# endif
1022
1023
1024/* added by jwf */
1025struct 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
1036hardops(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
1104zappost(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
1128fixpre(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
1148myreader(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