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