1 # ifndef lint 2 static char *sccsid ="@(#)local2.c 1.20 (Berkeley) 12/11/87"; 3 # endif 4 5 # include "pass2.h" 6 # include "ctype.h" 7 # ifdef FORT 8 int ftlab1, ftlab2; 9 # endif 10 /* a lot of the machine dependent parts of the second pass */ 11 12 # define putstr(s) fputs((s), stdout) 13 14 # define BITMASK(n) ((1L<<n)-1) 15 16 /*ARGSUSED*/ 17 where(c){ 18 fprintf( stderr, "%s, line %d: ", filename, lineno ); 19 } 20 21 lineid( l, fn ) char *fn; { 22 /* identify line l and file fn */ 23 printf( "# line %d, file %s\n", l, fn ); 24 } 25 26 27 eobl2(){ 28 OFFSZ spoff; /* offset from stack pointer */ 29 #ifdef FORT 30 spoff = maxoff; 31 if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 32 spoff /= SZCHAR; 33 SETOFF(spoff,4); 34 #ifndef FLEXNAMES 35 printf( " .set .F%d,%ld\n", ftnno, spoff ); 36 #else 37 /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 38 printf( " .set LF%d,%ld\n", ftnno, spoff ); 39 #endif 40 #else 41 extern int ftlab1, ftlab2; 42 43 spoff = maxoff; 44 if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 45 spoff /= SZCHAR; 46 SETOFF(spoff,4); 47 printf( "L%d:\n", ftlab1); 48 if( spoff!=0 ) 49 if( spoff < 64 ) 50 printf( " subl2 $%ld,sp\n", spoff); 51 else 52 printf( " movab -%ld(sp),sp\n", spoff); 53 printf( " jbr L%d\n", ftlab2); 54 #endif 55 maxargs = -1; 56 } 57 58 struct hoptab { int opmask; char * opstring; } ioptab[] = { 59 60 ASG PLUS, "add", 61 ASG MINUS, "sub", 62 ASG MUL, "mul", 63 ASG DIV, "div", 64 ASG OR, "bis", 65 ASG ER, "xor", 66 ASG AND, "bic", 67 PLUS, "add", 68 MINUS, "sub", 69 MUL, "mul", 70 DIV, "div", 71 OR, "bis", 72 ER, "xor", 73 AND, "bic", 74 -1, "" }; 75 76 hopcode( f, o ){ 77 /* output the appropriate string from the above table */ 78 79 register struct hoptab *q; 80 81 for( q = ioptab; q->opmask>=0; ++q ){ 82 if( q->opmask == o ){ 83 putstr( q->opstring ); 84 /* tbl 85 if( f == 'F' ) putchar( 'e' ); 86 else if( f == 'D' ) putchar( 'd' ); 87 tbl */ 88 /* tbl */ 89 switch( f ) { 90 case 'L': 91 case 'W': 92 case 'B': 93 case 'D': 94 case 'F': 95 putchar(tolower(f)); 96 break; 97 98 } 99 /* tbl */ 100 return; 101 } 102 } 103 cerror( "no hoptab for %s", opst[o] ); 104 } 105 106 char * 107 rnames[] = { /* keyed to register number tokens */ 108 109 "r0", "r1", 110 "r2", "r3", "r4", "r5", 111 "r6", "r7", "r8", "r9", "r10", "r11", 112 "ap", "fp", "sp", "pc", 113 114 }; 115 116 int rstatus[] = { 117 SAREG|STAREG, SAREG|STAREG, 118 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 119 SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 120 SAREG, SAREG, SAREG, SAREG, 121 122 }; 123 124 tlen(p) NODE *p; 125 { 126 switch(p->in.type) { 127 case CHAR: 128 case UCHAR: 129 return(1); 130 131 case SHORT: 132 case USHORT: 133 return(2); 134 135 case DOUBLE: 136 return(8); 137 138 default: 139 return(4); 140 } 141 } 142 143 mixtypes(p, q) NODE *p, *q; 144 { 145 register TWORD tp, tq; 146 147 tp = p->in.type; 148 tq = q->in.type; 149 150 return( (tp==FLOAT || tp==DOUBLE) != 151 (tq==FLOAT || tq==DOUBLE) ); 152 } 153 154 prtype(n) NODE *n; 155 { 156 switch (n->in.type) 157 { 158 case DOUBLE: 159 putchar('d'); 160 return; 161 162 case FLOAT: 163 putchar('f'); 164 return; 165 166 case LONG: 167 case ULONG: 168 case INT: 169 case UNSIGNED: 170 putchar('l'); 171 return; 172 173 case SHORT: 174 case USHORT: 175 putchar('w'); 176 return; 177 178 case CHAR: 179 case UCHAR: 180 putchar('b'); 181 return; 182 183 default: 184 if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 185 else { 186 putchar('l'); 187 return; 188 } 189 } 190 } 191 192 zzzcode( p, c ) register NODE *p; { 193 register m; 194 int val; 195 switch( c ){ 196 197 case 'N': /* logical ops, turned into 0-1 */ 198 /* use register given by register 1 */ 199 cbgen( 0, m=getlab(), 'I' ); 200 deflab( p->bn.label ); 201 printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 202 deflab( m ); 203 return; 204 205 case 'I': 206 case 'P': 207 cbgen( p->in.op, p->bn.label, c ); 208 return; 209 210 case 'A': 211 { 212 register NODE *l, *r; 213 214 if (xdebug) eprint(p, 0, &val, &val); 215 r = getlr(p, 'R'); 216 if (p->in.op == ASSIGN) 217 l = getlr(p, 'L'); 218 else if (p->in.op == SCONV) { 219 l = resc; 220 #if defined(FORT) || defined(SPRECC) 221 l->in.type = r->in.type; 222 #else 223 l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type; 224 #endif 225 r = getlr(p, 'L'); 226 } 227 else { /* OPLTYPE */ 228 l = resc; 229 #if defined(FORT) || defined(SPRECC) 230 l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 231 #else 232 l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); 233 #endif 234 } 235 if (r->in.op == ICON) 236 if (r->in.name[0] == '\0') { 237 if (r->tn.lval == 0) { 238 putstr("clr"); 239 prtype(l); 240 putchar('\t'); 241 adrput(l); 242 return; 243 } 244 if (r->tn.lval < 0 && r->tn.lval >= -63) { 245 putstr("mneg"); 246 prtype(l); 247 r->tn.lval = -r->tn.lval; 248 goto ops; 249 } 250 if (r->tn.lval < 0) 251 r->in.type = r->tn.lval >= -128 ? CHAR 252 : (r->tn.lval >= -32768 ? SHORT 253 : INT); 254 else if (l->in.type == FLOAT || 255 l->in.type == DOUBLE) 256 r->in.type = r->tn.lval <= 63 ? INT 257 : (r->tn.lval <= 127 ? CHAR 258 : (r->tn.lval <= 32767 ? SHORT 259 : INT)); 260 else 261 r->in.type = r->tn.lval <= 63 ? INT 262 : (r->tn.lval <= 127 ? CHAR 263 : (r->tn.lval <= 255 ? UCHAR 264 : (r->tn.lval <= 32767 ? SHORT 265 : (r->tn.lval <= 65535 ? USHORT 266 : INT)))); 267 } 268 else { 269 putstr("moval"); 270 putchar('\t'); 271 acon(r); 272 putchar(','); 273 adrput(l); 274 return; 275 } 276 277 if (p->in.op == SCONV && 278 !(l->in.type == FLOAT || l->in.type == DOUBLE) && 279 !mixtypes(l, r)) { 280 /* 281 * Because registers must always contain objects 282 * of the same width as INTs, we may have to 283 * perform two conversions to get an INT. Can 284 * the conversions be collapsed into one? 285 */ 286 if (m = collapsible(l, r)) 287 r->in.type = m; 288 else { 289 /* 290 * Two steps are required. 291 */ 292 NODE *x = &resc[1]; 293 294 *x = *l; 295 if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 296 putstr("movz"); 297 else 298 putstr("cvt"); 299 prtype(r); 300 prtype(x); 301 putchar('\t'); 302 adrput(r); 303 putchar(','); 304 adrput(x); 305 putchar('\n'); 306 putchar('\t'); 307 r = x; 308 } 309 l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 310 } 311 312 if ((r->in.type == UNSIGNED || r->in.type == ULONG) && 313 mixtypes(l, r)) { 314 int label1, label2; 315 316 label1 = getlab(); 317 label2 = getlab(); 318 319 putstr("movl\t"); 320 adrput(r); 321 putchar(','); 322 adrput(l); 323 putstr("\n\tjbsc\t$31,"); 324 adrput(l); 325 printf(",L%d\n\tcvtl", label1); 326 prtype(l); 327 putchar('\t'); 328 adrput(l); 329 putchar(','); 330 adrput(l); 331 printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 332 prtype(l); 333 putchar('\t'); 334 adrput(l); 335 putchar(','); 336 adrput(l); 337 putstr("\n\tadd"); 338 prtype(l); 339 putstr("2\t$0"); 340 prtype(l); 341 putstr("2.147483648e9,"); 342 adrput(l); 343 printf("\nL%d:", label2); 344 345 return; 346 } 347 348 if (!mixtypes(l,r)) { 349 if (tlen(l) == tlen(r)) { 350 putstr("mov"); 351 #ifdef FORT 352 if (Oflag) 353 prtype(l); 354 else { 355 if (l->in.type == DOUBLE) 356 putchar('q'); 357 else if(l->in.type == FLOAT) 358 putchar('l'); 359 else 360 prtype(l); 361 } 362 #else 363 prtype(l); 364 #endif FORT 365 goto ops; 366 } 367 else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 368 putstr("movz"); 369 else 370 putstr("cvt"); 371 } 372 else 373 putstr("cvt"); 374 prtype(r); 375 prtype(l); 376 ops: 377 putchar('\t'); 378 adrput(r); 379 putchar(','); 380 adrput(l); 381 return; 382 } 383 384 case 'G': /* i *= f; asgops with int lhs and float rhs */ 385 { 386 register NODE *l, *r, *s; 387 int rt; 388 389 l = p->in.left; 390 r = p->in.right; 391 s = talloc(); 392 rt = r->in.type; 393 394 s->in.op = SCONV; 395 s->in.left = l; 396 s->in.type = rt; 397 zzzcode(s, 'A'); 398 putstr("\n\t"); 399 400 hopcode(rt == FLOAT ? 'F' : 'D', p->in.op); 401 putstr("2\t"); 402 adrput(r); 403 putchar(','); 404 adrput(resc); 405 putstr("\n\t"); 406 407 s->in.op = ASSIGN; 408 s->in.left = l; 409 s->in.right = resc; 410 s->in.type = l->in.type; 411 zzzcode(s, 'A'); 412 413 s->in.op = FREE; 414 return; 415 } 416 417 case 'B': /* get oreg value in temp register for left shift */ 418 { 419 register NODE *r; 420 if (xdebug) eprint(p, 0, &val, &val); 421 r = p->in.right; 422 if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) 423 putstr("movl"); 424 else { 425 putstr("cvt"); 426 prtype(r); 427 putchar('l'); 428 } 429 return; 430 } 431 432 case 'C': /* num words pushed on arg stack */ 433 { 434 extern int gc_numbytes; 435 extern int xdebug; 436 437 if (xdebug) printf("->%d<-",gc_numbytes); 438 439 printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 440 return; 441 } 442 443 case 'D': /* INCR and DECR */ 444 zzzcode(p->in.left, 'A'); 445 putchar('\n'); 446 putchar('\t'); 447 448 case 'E': /* INCR and DECR, FOREFF */ 449 if (p->in.right->tn.lval == 1) 450 { 451 putstr( p->in.op == INCR ? "inc" : "dec" ); 452 prtype(p->in.left); 453 putchar('\t'); 454 adrput(p->in.left); 455 return; 456 } 457 putstr( p->in.op == INCR ? "add" : "sub" ); 458 prtype(p->in.left); 459 putchar('2'); 460 putchar('\t'); 461 adrput(p->in.right); 462 putchar(','); 463 adrput(p->in.left); 464 return; 465 466 case 'F': /* register type of right operand */ 467 { 468 register NODE *n; 469 extern int xdebug; 470 register int ty; 471 472 n = getlr( p, 'R' ); 473 ty = n->in.type; 474 475 if (xdebug) printf("->%d<-", ty); 476 477 if ( ty==DOUBLE) putchar('d'); 478 else if ( ty==FLOAT ) putchar('f'); 479 else putchar('l'); 480 return; 481 } 482 483 case 'L': /* type of left operand */ 484 case 'R': /* type of right operand */ 485 { 486 register NODE *n; 487 extern int xdebug; 488 489 n = getlr( p, c ); 490 if (xdebug) printf("->%d<-", n->in.type); 491 492 prtype(n); 493 return; 494 } 495 496 case 'Z': /* complement mask for bit instr */ 497 printf("$%ld", ~p->in.right->tn.lval); 498 return; 499 500 case 'U': /* 32 - n, for unsigned right shifts */ 501 printf("$%d", 32 - p->in.right->tn.lval ); 502 return; 503 504 case 'T': /* rounded structure length for arguments */ 505 { 506 int size; 507 508 size = p->stn.stsize; 509 SETOFF( size, 4); 510 printf("$%d", size); 511 return; 512 } 513 514 case 'S': /* structure assignment */ 515 { 516 register NODE *l, *r; 517 register size; 518 519 if( p->in.op == STASG ){ 520 l = p->in.left; 521 r = p->in.right; 522 523 } 524 else if( p->in.op == STARG ){ /* store an arg into a temporary */ 525 r = p->in.left; 526 } 527 else cerror( "STASG bad" ); 528 529 if( r->in.op == ICON ) r->in.op = NAME; 530 else if( r->in.op == REG ) r->in.op = OREG; 531 else if( r->in.op != OREG ) cerror( "STASG-r" ); 532 533 size = p->stn.stsize; 534 535 if( size <= 0 || size > 65535 ) 536 cerror("structure size <0=0 or >65535"); 537 538 switch(size) { 539 case 1: 540 putstr(" movb "); 541 break; 542 case 2: 543 putstr(" movw "); 544 break; 545 case 4: 546 putstr(" movl "); 547 break; 548 case 8: 549 putstr(" movq "); 550 break; 551 default: 552 printf(" movc3 $%d,", size); 553 break; 554 } 555 adrput(r); 556 if( p->in.op == STASG ){ 557 putchar(','); 558 adrput(l); 559 putchar('\n'); 560 } 561 else 562 putstr(",(sp)\n"); 563 564 if( r->in.op == NAME ) r->in.op = ICON; 565 else if( r->in.op == OREG ) r->in.op = REG; 566 567 } 568 break; 569 570 default: 571 cerror( "illegal zzzcode" ); 572 } 573 } 574 575 /* 576 * collapsible(dest, src) -- if a conversion with a register destination 577 * can be accomplished in one instruction, return the type of src 578 * that will do the job correctly; otherwise return 0. Note that 579 * a register must always end up having type INT or UNSIGNED. 580 */ 581 int 582 collapsible(dest, src) 583 NODE *dest, *src; 584 { 585 int st = src->in.type; 586 int dt = dest->in.type; 587 int newt = 0; 588 589 /* 590 * Are there side effects of evaluating src? 591 * If the derived type will not be the same size as src, 592 * we may have to use two steps. 593 */ 594 if (tlen(src) > tlen(dest)) { 595 if (tshape(src, STARREG)) 596 return (0); 597 if (src->in.op == OREG && R2TEST(src->tn.rval)) 598 return (0); 599 } 600 601 /* 602 * Can we get an object of dest's type by punning src? 603 * Praises be to great Cthulhu for little-endian machines... 604 */ 605 if (st == CHAR && dt == USHORT) 606 /* 607 * Special case -- we must sign-extend to 16 bits. 608 */ 609 return (0); 610 611 if (tlen(src) < tlen(dest)) 612 newt = st; 613 else 614 newt = dt; 615 616 return (newt); 617 } 618 619 rmove( rt, rs, t ) TWORD t; { 620 printf( " %s %s,%s\n", 621 #ifdef FORT 622 !Oflag ? (t==DOUBLE ? "movq" : "movl") : 623 #endif 624 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 625 rnames[rs], rnames[rt] ); 626 } 627 628 struct respref 629 respref[] = { 630 INTAREG|INTBREG, INTAREG|INTBREG, 631 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 632 INTEMP, INTEMP, 633 FORARG, FORARG, 634 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 635 0, 0 }; 636 637 setregs(){ /* set up temporary registers */ 638 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 639 ; 640 } 641 642 /*ARGSUSED*/ 643 rewfld( p ) NODE *p; { 644 return(1); 645 } 646 647 /*ARGSUSED*/ 648 callreg(p) NODE *p; { 649 return( R0 ); 650 } 651 652 base( p ) register NODE *p; { 653 register int o = p->in.op; 654 655 if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ 656 if( o==REG ) return( p->tn.rval ); 657 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 658 return( p->in.left->tn.rval ); 659 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 660 return( p->tn.rval + 0200*1 ); 661 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 662 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 663 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 664 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 665 return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 666 return( -1 ); 667 } 668 669 offset( p, tyl ) register NODE *p; int tyl; { 670 671 if( tyl==1 && 672 p->in.op==REG && 673 (p->in.type==INT || p->in.type==UNSIGNED) ) 674 return( p->tn.rval ); 675 if( p->in.op==LS && 676 p->in.left->in.op==REG && 677 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 678 p->in.right->in.op==ICON && 679 p->in.right->in.name[0]=='\0' && 680 (1<<p->in.right->tn.lval)==tyl) 681 return( p->in.left->tn.rval ); 682 if( tyl==2 && 683 p->in.op==PLUS && 684 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 685 p->in.left->in.op==REG && 686 p->in.right->in.op==REG && 687 p->in.left->tn.rval==p->in.right->tn.rval ) 688 return( p->in.left->tn.rval ); 689 return( -1 ); 690 } 691 692 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 693 register NODE *t; 694 NODE *f; 695 696 p->in.op = OREG; 697 f = p->in.left; /* have to free this subtree later */ 698 699 /* init base */ 700 switch (q->in.op) { 701 case ICON: 702 case REG: 703 case OREG: 704 t = q; 705 break; 706 707 case MINUS: 708 q->in.right->tn.lval = -q->in.right->tn.lval; 709 case PLUS: 710 t = q->in.right; 711 break; 712 713 case INCR: 714 case ASG MINUS: 715 t = q->in.left; 716 break; 717 718 case UNARY MUL: 719 t = q->in.left->in.left; 720 break; 721 722 default: 723 cerror("illegal makeor2"); 724 } 725 726 p->tn.lval = t->tn.lval; 727 #ifndef FLEXNAMES 728 { 729 register int i; 730 for(i=0; i<NCHNAM; ++i) 731 p->in.name[i] = t->in.name[i]; 732 } 733 #else 734 p->in.name = t->in.name; 735 #endif 736 737 /* init offset */ 738 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 739 740 tfree(f); 741 return; 742 } 743 744 canaddr( p ) NODE *p; { 745 register int o = p->in.op; 746 747 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 748 return(0); 749 } 750 751 flshape( p ) register NODE *p; { 752 return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON || 753 (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 754 } 755 756 /* INTEMP shapes must not contain any temporary registers */ 757 shtemp( p ) register NODE *p; { 758 int r; 759 760 if( p->in.op == STARG ) p = p->in.left; 761 762 switch (p->in.op) { 763 case REG: 764 return( !istreg(p->tn.rval) ); 765 case OREG: 766 r = p->tn.rval; 767 if( R2TEST(r) ) { 768 if( istreg(R2UPK1(r)) ) 769 return(0); 770 r = R2UPK2(r); 771 } 772 return( !istreg(r) ); 773 /* 774 case UNARY MUL: 775 p = p->in.left; 776 return( p->in.op != UNARY MUL && shtemp(p) ); 777 */ 778 } 779 780 if( optype( p->in.op ) != LTYPE ) return(0); 781 return(1); 782 } 783 784 shumul( p ) register NODE *p; { 785 register o; 786 extern int xdebug; 787 788 if (xdebug) { 789 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 790 printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 791 } 792 793 794 o = p->in.op; 795 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 796 797 if( ( o == INCR || o == ASG MINUS ) && 798 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 799 p->in.right->in.name[0] == '\0' ) 800 { 801 switch (p->in.type) 802 { 803 case CHAR|PTR: 804 case UCHAR|PTR: 805 o = 1; 806 break; 807 808 case SHORT|PTR: 809 case USHORT|PTR: 810 o = 2; 811 break; 812 813 case INT|PTR: 814 case UNSIGNED|PTR: 815 case LONG|PTR: 816 case ULONG|PTR: 817 case FLOAT|PTR: 818 o = 4; 819 break; 820 821 case DOUBLE|PTR: 822 o = 8; 823 break; 824 825 default: 826 if ( ISPTR(p->in.type) && 827 ISPTR(DECREF(p->in.type)) ) { 828 o = 4; 829 break; 830 } 831 else return(0); 832 } 833 return( p->in.right->tn.lval == o ? STARREG : 0); 834 } 835 836 return( 0 ); 837 } 838 839 adrcon( val ) CONSZ val; { 840 putchar( '$' ); 841 printf( CONFMT, val ); 842 } 843 844 conput( p ) register NODE *p; { 845 switch( p->in.op ){ 846 847 case ICON: 848 acon( p ); 849 return; 850 851 case REG: 852 putstr( rnames[p->tn.rval] ); 853 return; 854 855 default: 856 cerror( "illegal conput" ); 857 } 858 } 859 860 /*ARGSUSED*/ 861 insput( p ) NODE *p; { 862 cerror( "insput" ); 863 } 864 865 /*ARGSUSED*/ 866 upput( p, off ) NODE *p; int off; { 867 cerror( "upput" ); 868 } 869 870 adrput( p ) register NODE *p; { 871 register int r; 872 /* output an address, with offsets, from p */ 873 874 if( p->in.op == FLD ){ 875 p = p->in.left; 876 } 877 switch( p->in.op ){ 878 879 case NAME: 880 acon( p ); 881 return; 882 883 case ICON: 884 /* addressable value of the constant */ 885 putchar( '$' ); 886 acon( p ); 887 return; 888 889 case REG: 890 putstr( rnames[p->tn.rval] ); 891 return; 892 893 case OREG: 894 r = p->tn.rval; 895 if( R2TEST(r) ){ /* double indexing */ 896 register int flags; 897 898 flags = R2UPK3(r); 899 if( flags & 1 ) putchar('*'); 900 if( flags & 4 ) putchar('-'); 901 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 902 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 903 if( flags & 2 ) putchar('+'); 904 printf( "[%s]", rnames[R2UPK2(r)] ); 905 return; 906 } 907 if( r == AP ){ /* in the argument region */ 908 if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 909 printf( CONFMT, p->tn.lval ); 910 putstr( "(ap)" ); 911 return; 912 } 913 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 914 printf( "(%s)", rnames[p->tn.rval] ); 915 return; 916 917 case UNARY MUL: 918 /* STARNM or STARREG found */ 919 if( tshape(p, STARNM) ) { 920 putchar( '*' ); 921 adrput( p->in.left); 922 } 923 else { /* STARREG - really auto inc or dec */ 924 register NODE *q; 925 926 /* tbl 927 p = p->in.left; 928 p->in.left->in.op = OREG; 929 if( p->in.op == INCR ) { 930 adrput( p->in.left ); 931 putchar( '+' ); 932 } 933 else { 934 putchar( '-' ); 935 adrput( p->in.left ); 936 } 937 tbl */ 938 q = p->in.left; 939 if( q->in.right->tn.lval != tlen(p) ) 940 cerror("adrput: bad auto-increment/decrement"); 941 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 942 rnames[q->in.left->tn.rval], 943 (q->in.op==INCR ? "+" : "") ); 944 p->in.op = OREG; 945 p->tn.rval = q->in.left->tn.rval; 946 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 947 #ifndef FLEXNAMES 948 p->in.name[0] = '\0'; 949 #else 950 p->in.name = ""; 951 #endif 952 tfree(q); 953 } 954 return; 955 956 default: 957 cerror( "illegal address" ); 958 return; 959 960 } 961 962 } 963 964 acon( p ) register NODE *p; { /* print out a constant */ 965 966 if( p->in.name[0] == '\0' ){ 967 printf( CONFMT, p->tn.lval); 968 } 969 else if( p->tn.lval == 0 ) { 970 #ifndef FLEXNAMES 971 printf( "%.8s", p->in.name ); 972 #else 973 putstr( p->in.name ); 974 #endif 975 } 976 else { 977 #ifndef FLEXNAMES 978 printf( "%.8s+", p->in.name ); 979 #else 980 printf( "%s+", p->in.name ); 981 #endif 982 printf( CONFMT, p->tn.lval ); 983 } 984 } 985 986 /* 987 aacon( p ) register NODE *p; { /* print out a constant */ 988 /* 989 990 if( p->in.name[0] == '\0' ){ 991 printf( CONFMT, p->tn.lval); 992 return( 0 ); 993 } 994 else if( p->tn.lval == 0 ) { 995 #ifndef FLEXNAMES 996 printf( "$%.8s", p->in.name ); 997 #else 998 printf( "$%s", p->in.name ); 999 #endif 1000 return( 1 ); 1001 } 1002 else { 1003 printf( "$(" ); 1004 printf( CONFMT, p->tn.lval ); 1005 printf( "+" ); 1006 #ifndef FLEXNAMES 1007 printf( "%.8s)", p->in.name ); 1008 #else 1009 printf( "%s)", p->in.name ); 1010 #endif 1011 return(1); 1012 } 1013 } 1014 */ 1015 1016 genscall( p, cookie ) register NODE *p; { 1017 /* structure valued call */ 1018 return( gencall( p, cookie ) ); 1019 } 1020 1021 /* tbl */ 1022 int gc_numbytes; 1023 /* tbl */ 1024 1025 /*ARGSUSED*/ 1026 gencall( p, cookie ) register NODE *p; { 1027 /* generate the call given by p */ 1028 register NODE *p1; 1029 register temp, temp1; 1030 register m; 1031 1032 if( p->in.right ) temp = argsize( p->in.right ); 1033 else temp = 0; 1034 1035 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 1036 /* set aside room for structure return */ 1037 1038 if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 1039 else temp1 = temp; 1040 } 1041 1042 if( temp > maxargs ) maxargs = temp; 1043 SETOFF(temp1,4); 1044 1045 if( p->in.right ){ /* make temp node, put offset in, and generate args */ 1046 genargs( p->in.right ); 1047 } 1048 1049 p1 = p->in.left; 1050 if( p1->in.op != ICON ){ 1051 if( p1->in.op != REG ){ 1052 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 1053 if( p1->in.op != NAME ){ 1054 order( p1, INAREG ); 1055 } 1056 } 1057 } 1058 } 1059 1060 /* 1061 if( p1->in.op == REG && p->tn.rval == R5 ){ 1062 cerror( "call register overwrite" ); 1063 } 1064 */ 1065 /* tbl 1066 setup gc_numbytes so reference to ZC works */ 1067 1068 gc_numbytes = temp&(0x3ff); 1069 /* tbl */ 1070 1071 p->in.op = UNARY CALL; 1072 m = match( p, INTAREG|INTBREG ); 1073 1074 /* compensate for deficiency in 'ret' instruction ... wah,kre */ 1075 /* (plus in assignment to gc_numbytes above, for neatness only) */ 1076 if (temp >= 1024) 1077 printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 1078 1079 /* tbl 1080 switch( temp ) { 1081 case 0: 1082 break; 1083 case 2: 1084 printf( " tst (sp)+\n" ); 1085 break; 1086 case 4: 1087 printf( " cmp (sp)+,(sp)+\n" ); 1088 break; 1089 default: 1090 printf( " add $%d,sp\n", temp); 1091 } 1092 tbl */ 1093 return(m != MDONE); 1094 } 1095 1096 /* tbl */ 1097 char * 1098 ccbranches[] = { 1099 " jeql L%d\n", 1100 " jneq L%d\n", 1101 " jleq L%d\n", 1102 " jlss L%d\n", 1103 " jgeq L%d\n", 1104 " jgtr L%d\n", 1105 " jlequ L%d\n", 1106 " jlssu L%d\n", 1107 " jgequ L%d\n", 1108 " jgtru L%d\n", 1109 }; 1110 /* tbl */ 1111 1112 /*ARGSUSED*/ 1113 cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 1114 1115 /* tbl */ 1116 if( o == 0 ) printf( " jbr L%d\n", lab ); 1117 /* tbl */ 1118 else { 1119 if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 1120 printf( ccbranches[o-EQ], lab ); 1121 } 1122 } 1123 1124 nextcook( p, cookie ) NODE *p; { 1125 /* we have failed to match p with cookie; try another */ 1126 if( cookie == FORREW ) return( 0 ); /* hopeless! */ 1127 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 1128 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 1129 return( FORREW ); 1130 } 1131 1132 /*ARGSUSED*/ 1133 lastchance( p, cook ) NODE *p; { 1134 /* forget it! */ 1135 return(0); 1136 } 1137 1138 optim2( p ) register NODE *p; { 1139 /* do local tree transformations and optimizations */ 1140 1141 register NODE *l, *r; 1142 1143 switch( p->in.op ) { 1144 1145 case AND: 1146 /* commute L and R to eliminate complements and constants */ 1147 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 1148 l->in.op == COMPL ) { 1149 p->in.left = p->in.right; 1150 p->in.right = l; 1151 } 1152 case ASG AND: 1153 /* change meaning of AND to ~R&L - bic on pdp11 */ 1154 r = p->in.right; 1155 if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 1156 r->tn.lval = ~r->tn.lval; 1157 } 1158 else if( r->in.op==COMPL ) { /* ~~A => A */ 1159 r->in.op = FREE; 1160 p->in.right = r->in.left; 1161 } 1162 else { /* insert complement node */ 1163 p->in.right = l = talloc(); 1164 l->in.op = COMPL; 1165 l->in.rall = NOPREF; 1166 l->in.type = r->in.type; 1167 l->in.left = r; 1168 l->in.right = NULL; 1169 } 1170 break; 1171 1172 case SCONV: 1173 l = p->in.left; 1174 #if defined(FORT) || defined(SPRECC) 1175 if( p->in.type == FLOAT || p->in.type == DOUBLE || 1176 l->in.type == FLOAT || l->in.type == DOUBLE ) 1177 return; 1178 #else 1179 if( mixtypes(p, l) ) return; 1180 #endif 1181 if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL ) 1182 return; 1183 1184 /* Only trust it to get it right if the size is the same */ 1185 if( tlen(p) != tlen(l) ) 1186 return; 1187 1188 /* clobber conversion */ 1189 if( l->in.op != FLD ) 1190 l->in.type = p->in.type; 1191 ncopy( p, l ); 1192 l->in.op = FREE; 1193 1194 break; 1195 1196 case ASSIGN: 1197 /* 1198 * Conversions are equivalent to assignments; 1199 * when the two operations are combined, 1200 * we can sometimes zap the conversion. 1201 */ 1202 r = p->in.right; 1203 l = p->in.left; 1204 if ( r->in.op == SCONV && 1205 !mixtypes(l, r) && 1206 l->in.op != FLD && 1207 tlen(l) == tlen(r) ) { 1208 p->in.right = r->in.left; 1209 r->in.op = FREE; 1210 } 1211 break; 1212 1213 } 1214 } 1215 1216 /*ARGSUSED*/ 1217 NODE * addroreg(l) NODE *l; 1218 /* OREG was built in clocal() 1219 * for an auto or formal parameter 1220 * now its address is being taken 1221 * local code must unwind it 1222 * back to PLUS/MINUS REG ICON 1223 * according to local conventions 1224 */ 1225 { 1226 cerror("address of OREG taken"); 1227 /*NOTREACHED*/ 1228 } 1229 1230 1231 1232 # ifndef ONEPASS 1233 main( argc, argv ) char *argv[]; { 1234 return( mainp2( argc, argv ) ); 1235 } 1236 # endif 1237 1238 1239 /* added by jwf */ 1240 struct functbl { 1241 int fop; 1242 TWORD ftype; 1243 char *func; 1244 } opfunc[] = { 1245 DIV, TANY, "udiv", 1246 MOD, TANY, "urem", 1247 ASG DIV, TANY, "audiv", 1248 ASG MOD, TANY, "aurem", 1249 0, 0, 0 }; 1250 1251 hardops(p) register NODE *p; { 1252 /* change hard to do operators into function calls. */ 1253 register NODE *q; 1254 register struct functbl *f; 1255 register o; 1256 NODE *old,*temp; 1257 1258 o = p->in.op; 1259 if( ! (optype(o)==BITYPE && 1260 (ISUNSIGNED(p->in.left->in.type) || 1261 ISUNSIGNED(p->in.right->in.type))) ) 1262 return; 1263 1264 for( f=opfunc; f->fop; f++ ) { 1265 if( o==f->fop ) goto convert; 1266 } 1267 return; 1268 1269 convert: 1270 if( asgop( o ) ) { 1271 old = NIL; 1272 switch( p->in.left->in.op ){ 1273 case FLD: 1274 q = p->in.left->in.left; 1275 /* 1276 * rewrite (lval.fld /= rval); as 1277 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 1278 * else the compiler will evaluate lval twice. 1279 */ 1280 if( q->in.op == UNARY MUL ){ 1281 /* first allocate a temp storage */ 1282 temp = talloc(); 1283 temp->in.op = OREG; 1284 temp->tn.rval = TMPREG; 1285 temp->tn.lval = BITOOR(freetemp(1)); 1286 temp->in.type = INCREF(p->in.type); 1287 #ifdef FLEXNAMES 1288 temp->in.name = ""; 1289 #else 1290 temp->in.name[0] = '\0'; 1291 #endif 1292 old = q->in.left; 1293 q->in.left = temp; 1294 } 1295 /* fall thru ... */ 1296 1297 case REG: 1298 case NAME: 1299 case OREG: 1300 /* change ASG OP to a simple OP */ 1301 q = talloc(); 1302 q->in.op = NOASG p->in.op; 1303 q->in.rall = NOPREF; 1304 q->in.type = p->in.type; 1305 q->in.left = tcopy(p->in.left); 1306 q->in.right = p->in.right; 1307 p->in.op = ASSIGN; 1308 p->in.right = q; 1309 p = q; 1310 f -= 2; /* Note: this depends on the table order */ 1311 /* on the right side only - replace *temp with 1312 *(temp = &lval), build the assignment node */ 1313 if( old ){ 1314 temp = q->in.left->in.left; /* the "*" node */ 1315 q = talloc(); 1316 q->in.op = ASSIGN; 1317 q->in.left = temp->in.left; 1318 q->in.right = old; 1319 q->in.type = old->in.type; 1320 #ifdef FLEXNAMES 1321 q->in.name = ""; 1322 #else 1323 q->in.name[0] = '\0'; 1324 #endif 1325 temp->in.left = q; 1326 } 1327 break; 1328 1329 case UNARY MUL: 1330 /* avoid doing side effects twice */ 1331 q = p->in.left; 1332 p->in.left = q->in.left; 1333 q->in.op = FREE; 1334 break; 1335 1336 default: 1337 cerror( "hardops: can't compute & LHS" ); 1338 } 1339 } 1340 1341 /* build comma op for args to function */ 1342 q = talloc(); 1343 q->in.op = CM; 1344 q->in.rall = NOPREF; 1345 q->in.type = INT; 1346 q->in.left = p->in.left; 1347 q->in.right = p->in.right; 1348 p->in.op = CALL; 1349 p->in.right = q; 1350 1351 /* put function name in left node of call */ 1352 p->in.left = q = talloc(); 1353 q->in.op = ICON; 1354 q->in.rall = NOPREF; 1355 q->in.type = INCREF( FTN + p->in.type ); 1356 #ifndef FLEXNAMES 1357 strcpy( q->in.name, f->func ); 1358 #else 1359 q->in.name = f->func; 1360 #endif 1361 q->tn.lval = 0; 1362 q->tn.rval = 0; 1363 1364 } 1365 1366 zappost(p) NODE *p; { 1367 /* look for ++ and -- operators and remove them */ 1368 1369 register o, ty; 1370 register NODE *q; 1371 o = p->in.op; 1372 ty = optype( o ); 1373 1374 switch( o ){ 1375 1376 case INCR: 1377 case DECR: 1378 q = p->in.left; 1379 p->in.right->in.op = FREE; /* zap constant */ 1380 ncopy( p, q ); 1381 q->in.op = FREE; 1382 return; 1383 1384 } 1385 1386 if( ty == BITYPE ) zappost( p->in.right ); 1387 if( ty != LTYPE ) zappost( p->in.left ); 1388 } 1389 1390 fixpre(p) NODE *p; { 1391 1392 register o, ty; 1393 o = p->in.op; 1394 ty = optype( o ); 1395 1396 switch( o ){ 1397 1398 case ASG PLUS: 1399 p->in.op = PLUS; 1400 break; 1401 case ASG MINUS: 1402 p->in.op = MINUS; 1403 break; 1404 } 1405 1406 if( ty == BITYPE ) fixpre( p->in.right ); 1407 if( ty != LTYPE ) fixpre( p->in.left ); 1408 } 1409 1410 strip(p) register NODE *p; { 1411 NODE *q; 1412 1413 /* strip nodes off the top when no side effects occur */ 1414 for( ; ; ) { 1415 switch( p->in.op ) { 1416 case SCONV: /* remove lint tidbits */ 1417 q = p->in.left; 1418 ncopy( p, q ); 1419 q->in.op = FREE; 1420 break; 1421 /* could probably add a few more here */ 1422 default: 1423 return; 1424 } 1425 } 1426 } 1427 1428 myreader(p) register NODE *p; { 1429 strip( p ); /* strip off operations with no side effects */ 1430 canon( p ); /* expands r-vals for fields */ 1431 walkf( p, hardops ); /* convert ops to function calls */ 1432 walkf( p, optim2 ); 1433 /* jwf toff = 0; /* stack offset swindle */ 1434 } 1435