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