1 # ifndef lint 2 static char *sccsid ="@(#)local2.c 1.38 (Berkeley) 12/11/87"; 3 # endif 4 5 # include "pass2.h" 6 # include <ctype.h> 7 8 # define putstr(s) fputs((s), stdout) 9 10 # ifdef FORT 11 int ftlab1, ftlab2; 12 # endif 13 /* a lot of the machine dependent parts of the second pass */ 14 15 # define BITMASK(n) ((1L<<n)-1) 16 17 /*ARGSUSED*/ 18 where(c){ 19 fprintf( stderr, "%s, line %d: ", filename, lineno ); 20 } 21 22 lineid( l, fn ) char *fn; { 23 /* identify line l and file fn */ 24 printf( "# line %d, file %s\n", l, fn ); 25 } 26 27 28 eobl2(){ 29 register OFFSZ spoff; /* offset from stack pointer */ 30 #ifndef FORT 31 extern int ftlab1, ftlab2; 32 #endif 33 34 spoff = maxoff; 35 if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 36 spoff /= SZCHAR; 37 SETOFF(spoff,4); 38 #ifdef FORT 39 #ifndef FLEXNAMES 40 printf( " .set .F%d,%ld\n", ftnno, spoff ); 41 #else 42 /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 43 printf( " .set LF%d,%ld\n", ftnno, spoff ); 44 #endif 45 #else 46 printf( "L%d:\n", ftlab1); 47 if( spoff!=0 ) 48 if( spoff < 64 ) 49 printf( " subl2 $%ld,sp\n", spoff); 50 else 51 printf( " movab -%ld(sp),sp\n", spoff); 52 printf( " jbr L%d\n", ftlab2); 53 #endif 54 maxargs = -1; 55 } 56 57 struct hoptab { int opmask; char * opstring; } ioptab[] = { 58 59 PLUS, "add", 60 MINUS, "sub", 61 MUL, "mul", 62 DIV, "div", 63 OR, "bis", 64 ER, "xor", 65 AND, "bic", 66 -1, "" }; 67 68 hopcode( f, o ){ 69 /* output the appropriate string from the above table */ 70 71 register struct hoptab *q; 72 73 if(asgop(o)) 74 o = NOASG o; 75 for( q = ioptab; q->opmask>=0; ++q ){ 76 if( q->opmask == o ){ 77 printf( "%s%c", q->opstring, tolower(f)); 78 return; 79 } 80 } 81 cerror( "no hoptab for %s", opst[o] ); 82 } 83 84 char * 85 rnames[] = { /* keyed to register number tokens */ 86 87 "r0", "r1", 88 "r2", "r3", "r4", "r5", 89 "r6", "r7", "r8", "r9", "r10", "r11", 90 "ap", "fp", "sp", "pc", 91 }; 92 93 int rstatus[] = { 94 SAREG|STAREG, SAREG|STAREG, 95 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 96 SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 97 SAREG, SAREG, SAREG, SAREG, 98 }; 99 100 tlen(p) NODE *p; 101 { 102 switch(p->in.type) { 103 case CHAR: 104 case UCHAR: 105 return(1); 106 107 case SHORT: 108 case USHORT: 109 return(SZSHORT/SZCHAR); 110 111 case DOUBLE: 112 return(SZDOUBLE/SZCHAR); 113 114 default: 115 return(SZINT/SZCHAR); 116 } 117 } 118 119 mixtypes(p, q) NODE *p, *q; 120 { 121 register TWORD tp, tq; 122 123 tp = p->in.type; 124 tq = q->in.type; 125 126 return( (tp==FLOAT || tp==DOUBLE) != 127 (tq==FLOAT || tq==DOUBLE) ); 128 } 129 130 prtype(n) NODE *n; 131 { 132 switch (n->in.type) 133 { 134 135 case DOUBLE: 136 putchar('d'); 137 return; 138 139 case FLOAT: 140 putchar('f'); 141 return; 142 143 case LONG: 144 case ULONG: 145 case INT: 146 case UNSIGNED: 147 putchar('l'); 148 return; 149 150 case SHORT: 151 case USHORT: 152 putchar('w'); 153 return; 154 155 case CHAR: 156 case UCHAR: 157 putchar('b'); 158 return; 159 160 default: 161 if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 162 else { 163 putchar('l'); 164 return; 165 } 166 } 167 } 168 169 zzzcode( p, c ) register NODE *p; { 170 register int m; 171 int val; 172 switch( c ){ 173 174 case 'N': /* logical ops, turned into 0-1 */ 175 /* use register given by register 1 */ 176 cbgen( 0, m=getlab(), 'I' ); 177 deflab( p->bn.label ); 178 printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 179 deflab( m ); 180 return; 181 182 case 'P': 183 cbgen( p->in.op, p->bn.label, c ); 184 return; 185 186 case 'A': 187 case 'V': 188 sconv( p, c == 'V' ); 189 return; 190 191 case 'G': /* i *= f; asgops with int lhs and float rhs */ 192 { 193 register NODE *l, *r, *s; 194 int rt; 195 196 l = p->in.left; 197 r = p->in.right; 198 s = talloc(); 199 rt = r->in.type; 200 201 s->in.op = SCONV; 202 s->in.left = l; 203 s->in.type = rt; 204 zzzcode(s, 'A'); 205 putstr("\n\t"); 206 207 hopcode(rt == FLOAT ? 'F' : 'D', p->in.op); 208 putstr("2\t"); 209 adrput(r); 210 putchar(','); 211 adrput(resc); 212 putstr("\n\t"); 213 214 s->in.op = ASSIGN; 215 s->in.left = l; 216 s->in.right = resc; 217 s->in.type = l->in.type; 218 zzzcode(s, 'A'); 219 220 s->in.op = FREE; 221 return; 222 } 223 224 case 'J': /* unsigned DIV/MOD with constant divisors */ 225 { 226 register int ck = INAREG; 227 int label1, label2; 228 229 /* case constant <= 1 is handled by optim() in pass 1 */ 230 /* case constant < 0x80000000 is handled in table */ 231 switch( p->in.op ) { 232 /* case DIV: handled in optim2() */ 233 case MOD: 234 if( p->in.left->in.op == REG && 235 p->in.left->tn.rval == resc->tn.rval ) 236 goto asgmod; 237 label1 = getlab(); 238 expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n"); 239 printf("\tjlssu\tL%d\n", label1); 240 expand(p, ck, "\tsubl2\tAR,A1\n"); 241 printf("L%d:", label1); 242 break; 243 case ASG DIV: 244 label1 = getlab(); 245 label2 = getlab(); 246 expand(p, ck, "cmpl\tAL,AR\n"); 247 printf("\tjgequ\tL%d\n", label1); 248 expand(p, ck, "\tmovl\t$1,AL\n"); 249 printf("\tjbr\tL%d\nL%d:\n", label2, label1); 250 expand(p, ck, "\tclrl\tAL\n"); 251 printf("L%d:", label2); 252 break; 253 case ASG MOD: 254 asgmod: 255 label1 = getlab(); 256 expand(p, ck, "cmpl\tAL,AR\n"); 257 printf("\tjlssu\tL%d\n", label1); 258 expand(p, ck, "\tsubl2\tAR,AL\n"); 259 printf("L%d:", label1); 260 break; 261 } 262 return; 263 } 264 265 case 'B': /* get oreg value in temp register for left shift */ 266 { 267 register NODE *r; 268 if (xdebug) eprint(p, 0, &val, &val); 269 r = p->in.right; 270 if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT ) 271 putstr("movl"); 272 else { 273 putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt"); 274 prtype(r); 275 putchar('l'); 276 } 277 return; 278 } 279 280 case 'C': /* num words pushed on arg stack */ 281 { 282 extern int gc_numbytes; 283 extern int xdebug; 284 285 if (xdebug) printf("->%d<-",gc_numbytes); 286 287 printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 288 return; 289 } 290 291 case 'D': /* INCR and DECR */ 292 zzzcode(p->in.left, 'A'); 293 putchar('\n'); 294 putchar('\t'); 295 296 case 'E': /* INCR and DECR, FOREFF */ 297 if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1) 298 { 299 putstr(p->in.op == INCR ? "inc" : "dec"); 300 prtype(p->in.left); 301 putchar('\t'); 302 adrput(p->in.left); 303 return; 304 } 305 putstr(p->in.op == INCR ? "add" : "sub"); 306 prtype(p->in.left); 307 putchar('2'); 308 putchar('\t'); 309 adrput(p->in.right); 310 putchar(','); 311 adrput(p->in.left); 312 return; 313 314 case 'F': /* register type of right operand */ 315 { 316 register NODE *n; 317 extern int xdebug; 318 register int ty; 319 320 n = getlr( p, 'R' ); 321 ty = n->in.type; 322 323 if (xdebug) printf("->%d<-", ty); 324 325 if ( ty==DOUBLE) putchar('d'); 326 else if ( ty==FLOAT ) putchar('f'); 327 else putchar('l'); 328 return; 329 } 330 331 case 'L': /* type of left operand */ 332 case 'R': /* type of right operand */ 333 { 334 register NODE *n; 335 extern int xdebug; 336 337 n = getlr( p, c ); 338 if (xdebug) printf("->%d<-", n->in.type); 339 340 prtype(n); 341 return; 342 } 343 344 case 'Z': /* AND for CC with ICON -- lval is complemented */ 345 { 346 register NODE *l, *r; 347 348 l = getlr( p, 'L' ); 349 r = getlr( p, 'R' ); 350 m = (1 << tlen(l) * SZCHAR) - 1; 351 r->tn.lval = ~r->tn.lval; 352 if( (l->in.type == CHAR || l->in.type == SHORT) && 353 (r->tn.lval & ~m) ) { 354 putstr("cvt"); 355 prtype(l); 356 putstr("l\t"); 357 adrput(l); 358 putchar(','); 359 adrput(resc); 360 putstr("\n\t"); 361 resc->tn.type = INT; 362 l = resc; 363 } 364 else if( l->in.type == UCHAR || l->in.type == USHORT ) 365 /* remove trash left over from complementing */ 366 r->tn.lval &= m; 367 putstr("bit"); 368 prtype(l); 369 printf("\t$%ld", r->tn.lval); 370 putchar(','); 371 adrput(l); 372 return; 373 } 374 375 case 'U': /* 32 - n, for unsigned right shifts */ 376 printf("$%d", 32 - p->in.right->tn.lval ); 377 return; 378 379 case 'T': /* rounded structure length for arguments */ 380 { 381 int size; 382 383 size = p->stn.stsize; 384 SETOFF( size, 4); 385 printf("$%d", size); 386 return; 387 } 388 389 case 'S': /* structure assignment */ 390 stasg(p); 391 break; 392 393 default: 394 cerror( "illegal zzzcode" ); 395 } 396 } 397 398 stasg(p) 399 register NODE *p; 400 { 401 register NODE *l, *r; 402 register size; 403 404 if( p->in.op == STASG ){ 405 l = p->in.left; 406 r = p->in.right; 407 408 } 409 else if( p->in.op == STARG ){ /* store an arg into a temporary */ 410 r = p->in.left; 411 } 412 else cerror( "STASG bad" ); 413 414 if( r->in.op == ICON ) r->in.op = NAME; 415 else if( r->in.op == REG ) r->in.op = OREG; 416 else if( r->in.op != OREG ) cerror( "STASG-r" ); 417 418 size = p->stn.stsize; 419 420 if( size <= 0 || size > 65535 ) 421 cerror("structure size <0=0 or >65535"); 422 423 switch(size) { 424 case 1: 425 putstr(" movb "); 426 break; 427 case 2: 428 putstr(" movw "); 429 break; 430 case 4: 431 putstr(" movl "); 432 break; 433 case 8: 434 putstr(" movq "); 435 break; 436 default: 437 printf(" movc3 $%d,", size); 438 break; 439 } 440 adrput(r); 441 if( p->in.op == STASG ){ 442 putchar(','); 443 adrput(l); 444 putchar('\n'); 445 } 446 else 447 putstr(",(sp)\n"); 448 449 if( r->in.op == NAME ) r->in.op = ICON; 450 else if( r->in.op == OREG ) r->in.op = REG; 451 } 452 453 NODE *makearg( ty ) int ty; { 454 register NODE *p, *q; 455 456 /* build a -(sp) operand */ 457 p = talloc(); 458 p->in.op = REG; 459 /* the type needn't be right, just consistent */ 460 p->in.type = INCREF(ty); 461 p->tn.rval = SP; 462 p->tn.lval = 0; 463 q = talloc(); 464 q->in.op = ASG MINUS; 465 q->in.type = INCREF(ty); 466 q->in.left = p; 467 p = talloc(); 468 p->in.op = ICON; 469 p->in.type = INT; 470 p->tn.name = ""; 471 /* size of floating argument is always 2 */ 472 p->tn.lval = (1 + (ty == FLOAT || ty == DOUBLE)) * (SZINT/SZCHAR); 473 q->in.right = p; 474 p = talloc(); 475 p->in.op = UNARY MUL; 476 p->in.left = q; 477 return( p ); 478 } 479 480 sconv( p, forarg ) register NODE *p; { 481 register NODE *l, *r; 482 int m, val; 483 484 if (xdebug) eprint(p, 0, &val, &val); 485 r = getlr(p, 'R'); 486 if (p->in.op == ASSIGN) 487 l = getlr(p, 'L'); 488 else if (p->in.op == SCONV) { 489 m = r->in.type; 490 if (forarg) 491 l = makearg( m ); 492 else 493 l = resc; 494 l->in.type = m; 495 r = getlr(p, 'L'); 496 } 497 else { /* OPLTYPE */ 498 m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 499 if (forarg) 500 l = makearg( m ); 501 else 502 l = resc; 503 l->in.type = m; 504 } 505 if (r->in.op == ICON) 506 if (r->in.name[0] == '\0') { 507 if (r->tn.lval == 0 && 508 (r->in.type == DOUBLE || r->in.type == FLOAT || 509 !forarg)) { 510 if (r->in.type == FLOAT) 511 r->in.type = DOUBLE; 512 putstr("clr"); 513 prtype(l); 514 putchar('\t'); 515 adrput(l); 516 goto cleanup; 517 } 518 if (r->tn.lval < 0 && r->tn.lval >= -63) { 519 putstr("mneg"); 520 prtype(l); 521 r->tn.lval = -r->tn.lval; 522 goto ops; 523 } 524 if (r->tn.lval < 0) 525 r->in.type = r->tn.lval >= -128 ? CHAR 526 : (r->tn.lval >= -32768 ? SHORT 527 : INT); 528 else if (l->in.type == FLOAT || 529 l->in.type == DOUBLE) 530 r->in.type = r->tn.lval <= 63 ? INT 531 : (r->tn.lval <= 127 ? CHAR 532 : (r->tn.lval <= 32767 ? SHORT 533 : INT)); 534 else 535 r->in.type = r->tn.lval <= 63 ? INT 536 : (r->tn.lval <= 127 ? CHAR 537 : (r->tn.lval <= 255 ? UCHAR 538 : (r->tn.lval <= 32767 ? SHORT 539 : (r->tn.lval <= 65535 ? USHORT 540 : INT)))); 541 if (forarg && r->in.type == INT) { 542 putstr("pushl\t"); 543 adrput(r); 544 goto cleanup; 545 } 546 } 547 else { 548 if (forarg && tlen(r) == SZINT/SZCHAR) { 549 putstr("pushl\t"); 550 adrput(r); 551 goto cleanup; 552 } 553 putstr("moval\t"); 554 acon(r); 555 putchar(','); 556 adrput(l); 557 goto cleanup; 558 } 559 560 if (p->in.op == SCONV && 561 !(l->in.type == FLOAT || l->in.type == DOUBLE) && 562 !mixtypes(l, r)) { 563 /* 564 * Because registers must always contain objects 565 * of the same width as INTs, we may have to 566 * perform two conversions to get an INT. Can 567 * the conversions be collapsed into one? 568 */ 569 if (m = collapsible(l, r)) 570 r->in.type = m; 571 else { 572 /* two steps are required */ 573 NODE *x; 574 575 if (forarg) { 576 x = resc; 577 x->in.type = l->in.type; 578 } 579 else { 580 x = &resc[1]; 581 *x = *l; 582 } 583 584 if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 585 putstr("movz"); 586 else 587 putstr("cvt"); 588 prtype(r); 589 prtype(x); 590 putchar('\t'); 591 adrput(r); 592 putchar(','); 593 adrput(x); 594 putchar('\n'); 595 putchar('\t'); 596 r = x; 597 } 598 l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 599 } 600 601 else if ((forarg || l == resc) && 602 tlen(l) < SZINT/SZCHAR && 603 mixtypes(l, r)) { 604 /* two steps needed here too */ 605 NODE *x; 606 607 if (forarg) { 608 x = resc; 609 x->in.type = l->in.type; 610 } 611 else { 612 x = &resc[1]; 613 *x = *l; 614 } 615 putstr("cvt"); 616 prtype(r); 617 prtype(x); 618 putchar('\t'); 619 adrput(r); 620 putchar(','); 621 adrput(x); 622 putstr("\n\t"); 623 r = x; 624 l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 625 } 626 627 else if ((r->in.type == UNSIGNED || r->in.type == ULONG) && 628 mixtypes(l, r)) { 629 int label1, label2; 630 NODE *x = NULL; 631 632 #if defined(FORT) || defined(SPRECC) 633 if (forarg) 634 #else 635 if (forarg || l == resc) 636 #endif 637 { 638 /* compute in register, convert to double when done */ 639 x = l; 640 l = resc; 641 l->in.type = x->in.type; 642 } 643 644 label1 = getlab(); 645 label2 = getlab(); 646 647 putstr("movl\t"); 648 adrput(r); 649 putchar(','); 650 adrput(l); 651 putstr("\n\tjbsc\t$31,"); 652 adrput(l); 653 printf(",L%d\n\tcvtl", label1); 654 prtype(l); 655 putchar('\t'); 656 adrput(l); 657 putchar(','); 658 adrput(l); 659 printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 660 prtype(l); 661 putchar('\t'); 662 adrput(l); 663 putchar(','); 664 adrput(l); 665 putstr("\n\tadd"); 666 prtype(l); 667 putstr("2\t$0"); 668 prtype(l); 669 putstr("2.147483648e9,"); 670 adrput(l); 671 printf("\nL%d:", label2); 672 673 #if defined(FORT) || defined(SPRECC) 674 if (!forarg) 675 #else 676 if (!forarg && (l->in.type == DOUBLE || l != resc)) 677 #endif 678 goto cleanup; 679 if (x == NULL) 680 cerror("sconv botch"); 681 if (l == x) { 682 r = &resc[1]; 683 *r = *l; 684 } 685 else { 686 r = l; 687 l = x; 688 } 689 l->in.type = DOUBLE; 690 putstr("\n\t"); 691 } 692 693 else if( (l->in.type == FLOAT || l->in.type == DOUBLE) && 694 (r->in.type == UCHAR || r->in.type == USHORT) ) { 695 /* skip unnecessary unsigned to floating conversion */ 696 #if defined(FORT) || defined(SPRECC) 697 if (forarg) 698 #else 699 if (forarg || l == resc) 700 #endif 701 l->in.type = DOUBLE; 702 putstr("movz"); 703 prtype(r); 704 putstr("l\t"); 705 adrput(r); 706 putchar(','); 707 adrput(resc); 708 putstr("\n\t"); 709 if (l == resc) { 710 r = &resc[1]; 711 *r = *l; 712 } 713 else 714 r = resc; 715 r->in.type = INT; 716 } 717 718 #if defined(FORT) || defined(SPRECC) 719 if (forarg && l->in.type == FLOAT) 720 #else 721 if ((forarg || l == resc) && l->in.type == FLOAT) 722 #endif 723 { 724 /* perform an implicit conversion to double */ 725 l->in.type = DOUBLE; 726 if (r->in.type != FLOAT && 727 r->in.type != CHAR && 728 r->in.type != SHORT) { 729 /* trim bits from the mantissa */ 730 putstr("cvt"); 731 prtype(r); 732 putstr("f\t"); 733 adrput(r); 734 putchar(','); 735 adrput(resc); 736 putstr("\n\t"); 737 if (l == resc) { 738 r = &resc[1]; 739 *r = *l; 740 } 741 else 742 r = resc; 743 r->in.type = FLOAT; 744 } 745 } 746 747 if (!mixtypes(l,r)) { 748 if (tlen(l) == tlen(r)) { 749 if (forarg && tlen(l) == SZINT/SZCHAR) { 750 putstr("pushl\t"); 751 adrput(r); 752 goto cleanup; 753 } 754 putstr("mov"); 755 #ifdef FORT 756 if (Oflag) 757 prtype(l); 758 else { 759 if (l->in.type == DOUBLE) 760 putchar('q'); 761 else if(l->in.type == FLOAT) 762 putchar('l'); 763 else 764 prtype(l); 765 } 766 #else 767 prtype(l); 768 #endif FORT 769 goto ops; 770 } 771 else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 772 putstr("movz"); 773 else 774 putstr("cvt"); 775 } 776 else 777 putstr("cvt"); 778 prtype(r); 779 prtype(l); 780 ops: 781 putchar('\t'); 782 adrput(r); 783 putchar(','); 784 adrput(l); 785 786 cleanup: 787 if (forarg) 788 tfree(l); 789 } 790 791 /* 792 * collapsible(dest, src) -- if a conversion with a register destination 793 * can be accomplished in one instruction, return the type of src 794 * that will do the job correctly; otherwise return 0. Note that 795 * a register must always end up having type INT or UNSIGNED. 796 */ 797 int 798 collapsible(dest, src) 799 NODE *dest, *src; 800 { 801 int st = src->in.type; 802 int dt = dest->in.type; 803 int newt = 0; 804 805 /* 806 * Are there side effects of evaluating src? 807 * If the derived type will not be the same size as src, 808 * we may have to use two steps. 809 */ 810 if (tlen(src) > tlen(dest)) { 811 if (tshape(src, STARREG)) 812 return (0); 813 if (src->in.op == OREG && R2TEST(src->tn.rval)) 814 return (0); 815 } 816 817 /* 818 * Can we get an object of dest's type by punning src? 819 * Praises be to great Cthulhu for little-endian machines... 820 */ 821 if (st == CHAR && dt == USHORT) 822 /* 823 * Special case -- we must sign-extend to 16 bits. 824 */ 825 return (0); 826 827 if (tlen(src) < tlen(dest)) 828 newt = st; 829 else 830 newt = dt; 831 832 return (newt); 833 } 834 835 rmove( rt, rs, t ) TWORD t; { 836 printf( " %s %s,%s\n", 837 #ifdef FORT 838 !Oflag ? (t==DOUBLE ? "movq" : "movl") : 839 #endif 840 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 841 rnames[rs], rnames[rt] ); 842 } 843 844 struct respref 845 respref[] = { 846 INTAREG|INTBREG, INTAREG|INTBREG, 847 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 848 INTEMP, INTEMP, 849 FORARG, FORARG, 850 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 851 0, 0 }; 852 853 setregs(){ /* set up temporary registers */ 854 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 855 } 856 857 /*ARGSUSED*/ 858 rewfld( p ) NODE *p; { 859 return(1); 860 } 861 862 /*ARGSUSED*/ 863 callreg(p) NODE *p; { 864 return( R0 ); 865 } 866 867 base( p ) register NODE *p; { 868 register int o = p->in.op; 869 870 if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */ 871 if( o==REG ) return( p->tn.rval ); 872 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 873 return( p->in.left->tn.rval ); 874 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 875 return( p->tn.rval + 0200*1 ); 876 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 877 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 878 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 879 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 880 return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 881 if( o==NAME ) return( 100 + 0200*1 ); 882 return( -1 ); 883 } 884 885 offset( p, tyl ) register NODE *p; int tyl; { 886 887 if( tyl==1 && 888 p->in.op==REG && 889 (p->in.type==INT || p->in.type==UNSIGNED) ) 890 return( p->tn.rval ); 891 if( p->in.op==LS && 892 p->in.left->in.op==REG && 893 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 894 p->in.right->in.op==ICON && 895 p->in.right->in.name[0]=='\0' && 896 (1<<p->in.right->tn.lval)==tyl) 897 return( p->in.left->tn.rval ); 898 if( tyl==2 && 899 p->in.op==PLUS && 900 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 901 p->in.left->in.op==REG && 902 p->in.right->in.op==REG && 903 p->in.left->tn.rval==p->in.right->tn.rval ) 904 return( p->in.left->tn.rval ); 905 return( -1 ); 906 } 907 908 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 909 register NODE *t; 910 NODE *f; 911 912 p->in.op = OREG; 913 f = p->in.left; /* have to free this subtree later */ 914 915 /* init base */ 916 switch (q->in.op) { 917 case ICON: 918 case REG: 919 case OREG: 920 case NAME: 921 t = q; 922 break; 923 924 case MINUS: 925 q->in.right->tn.lval = -q->in.right->tn.lval; 926 case PLUS: 927 t = q->in.right; 928 break; 929 930 case INCR: 931 case ASG MINUS: 932 t = q->in.left; 933 break; 934 935 case UNARY MUL: 936 t = q->in.left->in.left; 937 break; 938 939 default: 940 cerror("illegal makeor2"); 941 } 942 943 p->tn.lval = t->tn.lval; 944 #ifndef FLEXNAMES 945 { 946 register int i; 947 for(i=0; i<NCHNAM; ++i) 948 p->in.name[i] = t->in.name[i]; 949 } 950 #else 951 p->in.name = t->in.name; 952 #endif 953 954 /* init offset */ 955 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 956 957 tfree(f); 958 return; 959 } 960 961 canaddr( p ) NODE *p; { 962 register int o = p->in.op; 963 964 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 965 return(0); 966 } 967 968 flshape( p ) NODE *p; { 969 register int o = p->in.op; 970 971 return( o == REG || o == NAME || o == ICON || 972 (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 973 } 974 975 /* INTEMP shapes must not contain any temporary registers */ 976 shtemp( p ) register NODE *p; { 977 int r; 978 979 if( p->in.op == STARG ) p = p->in.left; 980 981 switch (p->in.op) { 982 case REG: 983 return( !istreg(p->tn.rval) ); 984 case OREG: 985 r = p->tn.rval; 986 if( R2TEST(r) ) { 987 if( istreg(R2UPK1(r)) ) 988 return(0); 989 r = R2UPK2(r); 990 } 991 return( !istreg(r) ); 992 case UNARY MUL: 993 p = p->in.left; 994 return( p->in.op != UNARY MUL && shtemp(p) ); 995 } 996 997 if( optype( p->in.op ) != LTYPE ) return(0); 998 return(1); 999 } 1000 1001 shumul( p ) register NODE *p; { 1002 register int o; 1003 extern int xdebug; 1004 1005 if (xdebug) { 1006 int val; 1007 printf("shumul:\n"); 1008 eprint(p, 0, &val, &val); 1009 } 1010 1011 o = p->in.op; 1012 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 1013 1014 if( ( o == INCR || o == ASG MINUS ) && 1015 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 1016 p->in.right->in.name[0] == '\0' ) 1017 { 1018 switch (p->in.type) 1019 { 1020 case CHAR|PTR: 1021 case UCHAR|PTR: 1022 o = 1; 1023 break; 1024 1025 case SHORT|PTR: 1026 case USHORT|PTR: 1027 o = 2; 1028 break; 1029 1030 case INT|PTR: 1031 case UNSIGNED|PTR: 1032 case LONG|PTR: 1033 case ULONG|PTR: 1034 case FLOAT|PTR: 1035 o = 4; 1036 break; 1037 1038 case DOUBLE|PTR: 1039 o = 8; 1040 break; 1041 1042 default: 1043 if ( ISPTR(p->in.type) && 1044 ISPTR(DECREF(p->in.type)) ) { 1045 o = 4; 1046 break; 1047 } 1048 else return(0); 1049 } 1050 return( p->in.right->tn.lval == o ? STARREG : 0); 1051 } 1052 1053 return( 0 ); 1054 } 1055 1056 adrcon( val ) CONSZ val; { 1057 putchar( '$' ); 1058 printf( CONFMT, val ); 1059 } 1060 1061 conput( p ) register NODE *p; { 1062 switch( p->in.op ){ 1063 1064 case ICON: 1065 acon( p ); 1066 return; 1067 1068 case REG: 1069 putstr( rnames[p->tn.rval] ); 1070 return; 1071 1072 default: 1073 cerror( "illegal conput" ); 1074 } 1075 } 1076 1077 /*ARGSUSED*/ 1078 insput( p ) NODE *p; { 1079 cerror( "insput" ); 1080 } 1081 1082 upput( p, size ) NODE *p; int size; { 1083 if( size == SZLONG && p->in.op == REG ) { 1084 putstr( rnames[p->tn.rval + 1] ); 1085 return; 1086 } 1087 cerror( "upput" ); 1088 } 1089 1090 adrput( p ) register NODE *p; { 1091 register int r; 1092 /* output an address, with offsets, from p */ 1093 1094 if( p->in.op == FLD ){ 1095 p = p->in.left; 1096 } 1097 switch( p->in.op ){ 1098 1099 case NAME: 1100 acon( p ); 1101 return; 1102 1103 case ICON: 1104 /* addressable value of the constant */ 1105 putchar( '$' ); 1106 acon( p ); 1107 return; 1108 1109 case REG: 1110 putstr( rnames[p->tn.rval] ); 1111 return; 1112 1113 case OREG: 1114 r = p->tn.rval; 1115 if( R2TEST(r) ){ /* double indexing */ 1116 register int flags; 1117 1118 flags = R2UPK3(r); 1119 if( flags & 1 ) putchar('*'); 1120 if( flags & 4 ) putchar('-'); 1121 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 1122 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 1123 if( flags & 2 ) putchar('+'); 1124 printf( "[%s]", rnames[R2UPK2(r)] ); 1125 return; 1126 } 1127 if( r == AP ){ /* in the argument region */ 1128 if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 1129 printf( CONFMT, p->tn.lval ); 1130 putstr( "(ap)" ); 1131 return; 1132 } 1133 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 1134 printf( "(%s)", rnames[p->tn.rval] ); 1135 return; 1136 1137 case UNARY MUL: 1138 /* STARNM or STARREG found */ 1139 if( tshape(p, STARNM) ) { 1140 putchar( '*' ); 1141 adrput( p->in.left); 1142 } 1143 else { /* STARREG - really auto inc or dec */ 1144 register NODE *q; 1145 1146 q = p->in.left; 1147 if( q->in.right->tn.lval != tlen(p) ) 1148 cerror("adrput: bad auto-increment/decrement"); 1149 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 1150 rnames[q->in.left->tn.rval], 1151 (q->in.op==INCR ? "+" : "") ); 1152 p->in.op = OREG; 1153 p->tn.rval = q->in.left->tn.rval; 1154 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 1155 #ifndef FLEXNAMES 1156 p->in.name[0] = '\0'; 1157 #else 1158 p->in.name = ""; 1159 #endif 1160 tfree(q); 1161 } 1162 return; 1163 1164 default: 1165 cerror( "illegal address" ); 1166 return; 1167 1168 } 1169 1170 } 1171 1172 acon( p ) register NODE *p; { /* print out a constant */ 1173 1174 if( p->in.name[0] == '\0' ) 1175 printf( CONFMT, p->tn.lval); 1176 else { 1177 #ifndef FLEXNAMES 1178 printf( "%.8s", p->in.name ); 1179 #else 1180 putstr( p->in.name ); 1181 #endif 1182 if( p->tn.lval != 0 ) { 1183 putchar( '+' ); 1184 printf( CONFMT, p->tn.lval ); 1185 } 1186 } 1187 } 1188 1189 genscall( p, cookie ) register NODE *p; { 1190 /* structure valued call */ 1191 return( gencall( p, cookie ) ); 1192 } 1193 1194 /* tbl */ 1195 int gc_numbytes; 1196 /* tbl */ 1197 1198 /*ARGSUSED*/ 1199 gencall( p, cookie ) register NODE *p; { 1200 /* generate the call given by p */ 1201 register NODE *p1; 1202 register int temp, temp1; 1203 register int m; 1204 1205 if( p->in.right ) temp = argsize( p->in.right ); 1206 else temp = 0; 1207 1208 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 1209 /* set aside room for structure return */ 1210 1211 if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 1212 else temp1 = temp; 1213 } 1214 1215 if( temp > maxargs ) maxargs = temp; 1216 SETOFF(temp1,4); 1217 1218 if( p->in.right ){ /* make temp node, put offset in, and generate args */ 1219 genargs( p->in.right ); 1220 } 1221 1222 p1 = p->in.left; 1223 if( p1->in.op != ICON ){ 1224 if( p1->in.op != REG ){ 1225 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 1226 if( p1->in.op != NAME ){ 1227 order( p1, INAREG ); 1228 } 1229 } 1230 } 1231 } 1232 1233 /* tbl 1234 setup gc_numbytes so reference to ZC works */ 1235 1236 gc_numbytes = temp&(0x3ff); 1237 /* tbl */ 1238 1239 p->in.op = UNARY CALL; 1240 m = match( p, INTAREG|INTBREG ); 1241 1242 /* compensate for deficiency in 'ret' instruction ... wah,kre */ 1243 /* (plus in assignment to gc_numbytes above, for neatness only) */ 1244 if (temp >= 1024) 1245 printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 1246 1247 return(m != MDONE); 1248 } 1249 1250 /* tbl */ 1251 char * 1252 ccbranches[] = { 1253 "eql", 1254 "neq", 1255 "leq", 1256 "lss", 1257 "geq", 1258 "gtr", 1259 "lequ", 1260 "lssu", 1261 "gequ", 1262 "gtru", 1263 }; 1264 /* tbl */ 1265 1266 /*ARGSUSED*/ 1267 cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 1268 1269 if( o != 0 && ( o < EQ || o > UGT ) ) 1270 cerror( "bad conditional branch: %s", opst[o] ); 1271 printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab ); 1272 } 1273 1274 nextcook( p, cookie ) NODE *p; { 1275 /* we have failed to match p with cookie; try another */ 1276 if( cookie == FORREW ) return( 0 ); /* hopeless! */ 1277 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 1278 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 1279 return( FORREW ); 1280 } 1281 1282 /*ARGSUSED*/ 1283 lastchance( p, cook ) NODE *p; { 1284 /* forget it! */ 1285 return(0); 1286 } 1287 1288 optim2( p ) register NODE *p; { 1289 /* do local tree transformations and optimizations */ 1290 1291 int o; 1292 int i, mask; 1293 register NODE *l, *r; 1294 1295 switch( o = p->in.op ) { 1296 1297 case ASG PLUS: 1298 case ASG MINUS: 1299 case ASG MUL: 1300 case ASG OR: 1301 /* simple ASG OPSIMP -- reduce range of constant rhs */ 1302 l = p->in.left; 1303 r = p->in.right; 1304 if( tlen(l) < SZINT/SZCHAR && 1305 r->in.op==ICON && r->in.name[0]==0 ){ 1306 mask = (1 << tlen(l) * SZCHAR) - 1; 1307 if( r->tn.lval & (mask & ~(mask >> 1)) ) 1308 r->tn.lval |= ~mask; 1309 else 1310 r->tn.lval &= mask; 1311 } 1312 break; 1313 1314 case AND: 1315 /* commute L and R to eliminate complements and constants */ 1316 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 1317 l->in.op == COMPL ) { 1318 p->in.left = p->in.right; 1319 p->in.right = l; 1320 } 1321 /* fall through */ 1322 1323 case ASG AND: 1324 /* change meaning of AND to ~R&L - bic on pdp11/vax */ 1325 r = p->in.right; 1326 if( r->in.op==ICON && r->in.name[0]==0 ) { 1327 /* check for degenerate operations */ 1328 l = p->in.left; 1329 mask = (1 << tlen(l) * SZCHAR) - 1; 1330 if( o == ASG AND || ISUNSIGNED(r->in.type) ) { 1331 i = ~r->tn.lval & mask; 1332 if( i == 0 ) { 1333 /* redundant mask */ 1334 r->in.op = FREE; 1335 ncopy(p, l); 1336 l->in.op = FREE; 1337 break; 1338 } 1339 else if( i == mask ) 1340 /* all bits masked off */ 1341 goto zero; 1342 r->tn.lval = i; 1343 if( tlen(l) < SZINT/SZCHAR ){ 1344 /* sign extend */ 1345 if( r->tn.lval & (mask & ~(mask >> 1)) ) 1346 r->tn.lval |= ~mask; 1347 else 1348 r->tn.lval &= mask; 1349 } 1350 break; 1351 } 1352 else if( r->tn.lval == mask && 1353 tlen(l) < SZINT/SZCHAR ) { 1354 /* use movz instead of bic */ 1355 r->in.op = SCONV; 1356 r->in.left = l; 1357 r->in.right = 0; 1358 r->in.type = ENUNSIGN(l->in.type); 1359 r->in.su = l->in.su > 1 ? l->in.su : 1; 1360 ncopy(p, r); 1361 p->in.left = r; 1362 p->in.type = INT; 1363 break; 1364 } 1365 /* complement constant */ 1366 r->tn.lval = ~r->tn.lval; 1367 } 1368 else if( r->in.op==COMPL ) { /* ~~A => A */ 1369 r->in.op = FREE; 1370 p->in.right = r->in.left; 1371 } 1372 else { /* insert complement node */ 1373 p->in.right = l = talloc(); 1374 l->in.op = COMPL; 1375 l->in.rall = NOPREF; 1376 l->in.type = r->in.type; 1377 l->in.left = r; 1378 l->in.right = NULL; 1379 } 1380 break; 1381 1382 case SCONV: 1383 l = p->in.left; 1384 #if defined(FORT) || defined(SPRECC) 1385 if( p->in.type == FLOAT || p->in.type == DOUBLE || 1386 l->in.type == FLOAT || l->in.type == DOUBLE ) 1387 return; 1388 #else 1389 if( mixtypes(p, l) ) return; 1390 #endif 1391 if( l->in.op == PCONV ) 1392 return; 1393 if( (l->in.op == CALL || l->in.op == UNARY CALL) && 1394 l->in.type != INT && l->in.type != UNSIGNED ) 1395 return; 1396 1397 /* Only trust it to get it right if the size is the same */ 1398 if( tlen(p) != tlen(l) ) 1399 return; 1400 1401 /* clobber conversion */ 1402 if( l->in.op != FLD ) 1403 l->in.type = p->in.type; 1404 ncopy( p, l ); 1405 l->in.op = FREE; 1406 1407 break; 1408 1409 case ASSIGN: 1410 /* 1411 * Conversions are equivalent to assignments; 1412 * when the two operations are combined, 1413 * we can sometimes zap the conversion. 1414 */ 1415 r = p->in.right; 1416 l = p->in.left; 1417 if ( r->in.op == SCONV && 1418 !mixtypes(l, r) && 1419 l->in.op != FLD && 1420 tlen(l) == tlen(r) ) { 1421 p->in.right = r->in.left; 1422 r->in.op = FREE; 1423 } 1424 break; 1425 1426 case ULE: 1427 case ULT: 1428 case UGE: 1429 case UGT: 1430 p->in.op -= (UGE-GE); 1431 if( degenerate(p) ) 1432 break; 1433 p->in.op += (UGE-GE); 1434 break; 1435 1436 case EQ: 1437 case NE: 1438 case LE: 1439 case LT: 1440 case GE: 1441 case GT: 1442 if( p->in.left->in.op == SCONV && 1443 p->in.right->in.op == SCONV ) { 1444 l = p->in.left; 1445 r = p->in.right; 1446 if( l->in.type == DOUBLE && 1447 l->in.left->in.type == FLOAT && 1448 r->in.left->in.type == FLOAT ) { 1449 /* nuke the conversions */ 1450 p->in.left = l->in.left; 1451 p->in.right = r->in.left; 1452 l->in.op = FREE; 1453 r->in.op = FREE; 1454 } 1455 /* more? */ 1456 } 1457 (void) degenerate(p); 1458 break; 1459 1460 case DIV: 1461 if( p->in.right->in.op == ICON && 1462 p->in.right->tn.name[0] == '\0' && 1463 ISUNSIGNED(p->in.right->in.type) && 1464 (unsigned) p->in.right->tn.lval >= 0x80000000 ) { 1465 /* easy to do here, harder to do in zzzcode() */ 1466 p->in.op = UGE; 1467 break; 1468 } 1469 case MOD: 1470 case ASG DIV: 1471 case ASG MOD: 1472 /* 1473 * optimize DIV and MOD 1474 * 1475 * basically we spot UCHAR and USHORT and try to do them 1476 * as signed ints... apparently div+mul+sub is always 1477 * faster than ediv for finding MOD on the VAX, when 1478 * full unsigned MOD isn't needed. 1479 * 1480 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub 1481 * are faster for unsigned dividend and a constant divisor 1482 * in the right range (.5 to 1 of dividend's range for the 1483 * first, .333+ to .5 for the second). full unsigned is 1484 * already done cmp+sub in the appropriate case; the 1485 * other cases are less common and require more ambition. 1486 */ 1487 if( degenerate(p) ) 1488 break; 1489 l = p->in.left; 1490 r = p->in.right; 1491 if( !ISUNSIGNED(r->in.type) || 1492 tlen(l) >= SZINT/SZCHAR || 1493 !(tlen(r) < SZINT/SZCHAR || 1494 (r->in.op == ICON && r->tn.name[0] == '\0')) ) 1495 break; 1496 if( r->in.op == ICON ) 1497 r->tn.type = INT; 1498 else { 1499 NODE *t = talloc(); 1500 t->in.left = r; 1501 r = t; 1502 r->in.op = SCONV; 1503 r->in.type = INT; 1504 r->in.right = 0; 1505 p->in.right = r; 1506 } 1507 if( o == DIV || o == MOD ) { 1508 NODE *t = talloc(); 1509 t->in.left = l; 1510 l = t; 1511 l->in.op = SCONV; 1512 l->in.type = INT; 1513 l->in.right = 0; 1514 p->in.left = l; 1515 } 1516 /* handle asgops in table */ 1517 break; 1518 1519 case RS: 1520 case ASG RS: 1521 case LS: 1522 case ASG LS: 1523 /* pick up degenerate shifts */ 1524 l = p->in.left; 1525 r = p->in.right; 1526 if( !(r->in.op == ICON && r->tn.name[0] == '\0') ) 1527 break; 1528 i = r->tn.lval; 1529 if( i < 0 ) 1530 /* front end 'fixes' this? */ 1531 if( o == LS || o == ASG LS ) 1532 o += (RS-LS); 1533 else 1534 o += (LS-RS); 1535 if( (o == RS || o == ASG RS) && 1536 !ISUNSIGNED(l->in.type) ) 1537 /* can't optimize signed right shifts */ 1538 break; 1539 if( o == LS ) { 1540 if( i < SZINT ) 1541 break; 1542 } 1543 else { 1544 if( i < tlen(l) * SZCHAR ) 1545 break; 1546 } 1547 zero: 1548 if( !asgop( o ) ) 1549 if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1550 /* no side effects */ 1551 tfree(l); 1552 ncopy(p, r); 1553 r->in.op = FREE; 1554 p->tn.lval = 0; 1555 } 1556 else { 1557 p->in.op = COMOP; 1558 r->tn.lval = 0; 1559 } 1560 else { 1561 p->in.op = ASSIGN; 1562 r->tn.lval = 0; 1563 } 1564 break; 1565 } 1566 } 1567 1568 degenerate(p) register NODE *p; { 1569 int o; 1570 int result, i; 1571 int lower, upper; 1572 register NODE *l, *r; 1573 1574 /* 1575 * try to keep degenerate comparisons with constants 1576 * out of the table. 1577 */ 1578 r = p->in.right; 1579 l = p->in.left; 1580 if( r->in.op != ICON || 1581 r->tn.name[0] != '\0' || 1582 tlen(l) >= tlen(r) ) 1583 return (0); 1584 switch( l->in.type ) { 1585 case CHAR: 1586 lower = -(1 << SZCHAR - 1); 1587 upper = (1 << SZCHAR - 1) - 1; 1588 break; 1589 case UCHAR: 1590 lower = 0; 1591 upper = (1 << SZCHAR) - 1; 1592 break; 1593 case SHORT: 1594 lower = -(1 << SZSHORT - 1); 1595 upper = (1 << SZSHORT - 1) - 1; 1596 break; 1597 case USHORT: 1598 lower = 0; 1599 upper = (1 << SZSHORT) - 1; 1600 break; 1601 default: 1602 cerror("unsupported type in degenerate()"); 1603 } 1604 i = r->tn.lval; 1605 switch( o = p->in.op ) { 1606 case DIV: 1607 case ASG DIV: 1608 case MOD: 1609 case ASG MOD: 1610 /* DIV and MOD work like EQ */ 1611 case EQ: 1612 case NE: 1613 if( lower == 0 && (unsigned) i > upper ) 1614 result = o == NE; 1615 else if( i < lower || i > upper ) 1616 result = o == NE; 1617 else 1618 return (0); 1619 break; 1620 case LT: 1621 case GE: 1622 if( lower == 0 && (unsigned) i > upper ) 1623 result = o == LT; 1624 else if( i <= lower ) 1625 result = o != LT; 1626 else if( i > upper ) 1627 result = o == LT; 1628 else 1629 return (0); 1630 break; 1631 case LE: 1632 case GT: 1633 if( lower == 0 && (unsigned) i >= upper ) 1634 result = o == LE; 1635 else if( i < lower ) 1636 result = o != LE; 1637 else if( i >= upper ) 1638 result = o == LE; 1639 else 1640 return (0); 1641 break; 1642 default: 1643 cerror("unknown op in degenerate()"); 1644 } 1645 1646 if( o == MOD || o == ASG MOD ) { 1647 r->in.op = FREE; 1648 ncopy(p, l); 1649 l->in.op = FREE; 1650 } 1651 else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1652 /* no side effects */ 1653 tfree(l); 1654 ncopy(p, r); 1655 r->in.op = FREE; 1656 p->tn.lval = result; 1657 } 1658 else { 1659 if( o == ASG DIV ) 1660 p->in.op = ASSIGN; 1661 else { 1662 p->in.op = COMOP; 1663 r->tn.type = INT; 1664 } 1665 r->tn.lval = result; 1666 } 1667 if( logop(o) ) 1668 p->in.type = INT; 1669 1670 return (1); 1671 } 1672 1673 /* added by jwf */ 1674 struct functbl { 1675 int fop; 1676 TWORD ftype; 1677 char *func; 1678 } opfunc[] = { 1679 DIV, TANY, "udiv", 1680 MOD, TANY, "urem", 1681 ASG DIV, TANY, "audiv", 1682 ASG MOD, TANY, "aurem", 1683 0, 0, 0 }; 1684 1685 hardops(p) register NODE *p; { 1686 /* change hard to do operators into function calls. */ 1687 register NODE *q; 1688 register struct functbl *f; 1689 register o; 1690 NODE *old,*temp; 1691 1692 o = p->in.op; 1693 if( ! (optype(o)==BITYPE && 1694 (ISUNSIGNED(p->in.left->in.type) || 1695 ISUNSIGNED(p->in.right->in.type))) ) 1696 return; 1697 1698 for( f=opfunc; f->fop; f++ ) { 1699 if( o==f->fop ) goto convert; 1700 } 1701 return; 1702 1703 convert: 1704 if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' ) 1705 /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */ 1706 /* save a subroutine call -- use at most 5 instructions */ 1707 return; 1708 if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR ) 1709 /* optim2() will modify the op into an ordinary int op */ 1710 return; 1711 if( asgop( o ) ) { 1712 old = NIL; 1713 switch( p->in.left->in.op ){ 1714 case FLD: 1715 q = p->in.left->in.left; 1716 /* 1717 * rewrite (lval.fld /= rval); as 1718 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 1719 * else the compiler will evaluate lval twice. 1720 */ 1721 if( q->in.op == UNARY MUL ){ 1722 /* first allocate a temp storage */ 1723 temp = talloc(); 1724 temp->in.op = OREG; 1725 temp->tn.rval = TMPREG; 1726 temp->tn.lval = BITOOR(freetemp(1)); 1727 temp->in.type = INCREF(p->in.type); 1728 #ifdef FLEXNAMES 1729 temp->in.name = ""; 1730 #else 1731 temp->in.name[0] = '\0'; 1732 #endif 1733 old = q->in.left; 1734 q->in.left = temp; 1735 } 1736 /* fall thru ... */ 1737 1738 case REG: 1739 case NAME: 1740 case OREG: 1741 /* change ASG OP to a simple OP */ 1742 q = talloc(); 1743 q->in.op = NOASG p->in.op; 1744 q->in.rall = NOPREF; 1745 q->in.type = p->in.type; 1746 q->in.left = tcopy(p->in.left); 1747 q->in.right = p->in.right; 1748 p->in.op = ASSIGN; 1749 p->in.right = q; 1750 p = q; 1751 f -= 2; /* Note: this depends on the table order */ 1752 /* on the right side only - replace *temp with 1753 *(temp = &lval), build the assignment node */ 1754 if( old ){ 1755 temp = q->in.left->in.left; /* the "*" node */ 1756 q = talloc(); 1757 q->in.op = ASSIGN; 1758 q->in.left = temp->in.left; 1759 q->in.right = old; 1760 q->in.type = old->in.type; 1761 #ifdef FLEXNAMES 1762 q->in.name = ""; 1763 #else 1764 q->in.name[0] = '\0'; 1765 #endif 1766 temp->in.left = q; 1767 } 1768 break; 1769 1770 case UNARY MUL: 1771 /* avoid doing side effects twice */ 1772 q = p->in.left; 1773 p->in.left = q->in.left; 1774 q->in.op = FREE; 1775 break; 1776 1777 default: 1778 cerror( "hardops: can't compute & LHS" ); 1779 } 1780 } 1781 1782 /* build comma op for args to function */ 1783 q = talloc(); 1784 q->in.op = CM; 1785 q->in.rall = NOPREF; 1786 q->in.type = INT; 1787 q->in.left = p->in.left; 1788 q->in.right = p->in.right; 1789 p->in.op = CALL; 1790 p->in.right = q; 1791 1792 /* put function name in left node of call */ 1793 p->in.left = q = talloc(); 1794 q->in.op = ICON; 1795 q->in.rall = NOPREF; 1796 q->in.type = INCREF( FTN + p->in.type ); 1797 #ifndef FLEXNAMES 1798 strcpy( q->in.name, f->func ); 1799 #else 1800 q->in.name = f->func; 1801 #endif 1802 q->tn.lval = 0; 1803 q->tn.rval = 0; 1804 1805 } 1806 1807 zappost(p) NODE *p; { 1808 /* look for ++ and -- operators and remove them */ 1809 1810 register int o, ty; 1811 register NODE *q; 1812 o = p->in.op; 1813 ty = optype( o ); 1814 1815 switch( o ){ 1816 1817 case INCR: 1818 case DECR: 1819 q = p->in.left; 1820 p->in.right->in.op = FREE; /* zap constant */ 1821 ncopy( p, q ); 1822 q->in.op = FREE; 1823 return; 1824 1825 } 1826 1827 if( ty == BITYPE ) zappost( p->in.right ); 1828 if( ty != LTYPE ) zappost( p->in.left ); 1829 } 1830 1831 fixpre(p) NODE *p; { 1832 1833 register int o, ty; 1834 o = p->in.op; 1835 ty = optype( o ); 1836 1837 switch( o ){ 1838 1839 case ASG PLUS: 1840 p->in.op = PLUS; 1841 break; 1842 case ASG MINUS: 1843 p->in.op = MINUS; 1844 break; 1845 } 1846 1847 if( ty == BITYPE ) fixpre( p->in.right ); 1848 if( ty != LTYPE ) fixpre( p->in.left ); 1849 } 1850 1851 /*ARGSUSED*/ 1852 NODE * addroreg(l) NODE *l; 1853 /* OREG was built in clocal() 1854 * for an auto or formal parameter 1855 * now its address is being taken 1856 * local code must unwind it 1857 * back to PLUS/MINUS REG ICON 1858 * according to local conventions 1859 */ 1860 { 1861 cerror("address of OREG taken"); 1862 /*NOTREACHED*/ 1863 } 1864 1865 1866 1867 # ifndef ONEPASS 1868 main( argc, argv ) char *argv[]; { 1869 return( mainp2( argc, argv ) ); 1870 } 1871 # endif 1872 1873 strip(p) register NODE *p; { 1874 NODE *q; 1875 1876 /* strip nodes off the top when no side effects occur */ 1877 for( ; ; ) { 1878 switch( p->in.op ) { 1879 case SCONV: /* remove lint tidbits */ 1880 q = p->in.left; 1881 ncopy( p, q ); 1882 q->in.op = FREE; 1883 break; 1884 /* could probably add a few more here */ 1885 default: 1886 return; 1887 } 1888 } 1889 } 1890 1891 myreader(p) register NODE *p; { 1892 strip( p ); /* strip off operations with no side effects */ 1893 canon( p ); /* expands r-vals for fields */ 1894 walkf( p, hardops ); /* convert ops to function calls */ 1895 walkf( p, optim2 ); 1896 } 1897