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