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