1 # ifndef lint 2 static char *sccsid ="@(#)local2.c 1.24 (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 'J': /* unsigned DIV/MOD with constant divisors */ 418 { 419 register int ck = INAREG; 420 int label1, label2; 421 422 /* case constant <= 1 is handled by optim() in pass 1 */ 423 /* case constant < 0x80000000 is handled in table */ 424 switch( p->in.op ) { 425 /* case DIV: handled in hardops() */ 426 case MOD: 427 if( p->in.left->in.op == REG && 428 p->in.left->tn.rval == resc->tn.rval ) 429 goto asgmod; 430 label1 = getlab(); 431 expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n"); 432 printf("\tjlssu\tL%d\n", label1); 433 expand(p, ck, "\tsubl2\tAR,A1\n"); 434 printf("L%d:", label1); 435 break; 436 case ASG DIV: 437 label1 = getlab(); 438 label2 = getlab(); 439 expand(p, ck, "cmpl\tAL,AR\n"); 440 printf("\tjgequ\tL%d\n", label1); 441 expand(p, ck, "\tmovl\t$1,AL\n"); 442 printf("\tjbr\tL%d\nL%d:\n", label2, label1); 443 expand(p, ck, "\tclrl\tAL\n"); 444 printf("L%d:", label2); 445 break; 446 case ASG MOD: 447 asgmod: 448 label1 = getlab(); 449 expand(p, ck, "cmpl\tAL,AR\n"); 450 printf("\tjlssu\tL%d\n", label1); 451 expand(p, ck, "\tsubl2\tAR,AL\n"); 452 printf("L%d:", label1); 453 break; 454 } 455 return; 456 } 457 458 case 'B': /* get oreg value in temp register for left shift */ 459 { 460 register NODE *r; 461 if (xdebug) eprint(p, 0, &val, &val); 462 r = p->in.right; 463 if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) 464 putstr("movl"); 465 else { 466 putstr("cvt"); 467 prtype(r); 468 putchar('l'); 469 } 470 return; 471 } 472 473 case 'C': /* num words pushed on arg stack */ 474 { 475 extern int gc_numbytes; 476 extern int xdebug; 477 478 if (xdebug) printf("->%d<-",gc_numbytes); 479 480 printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 481 return; 482 } 483 484 case 'D': /* INCR and DECR */ 485 zzzcode(p->in.left, 'A'); 486 putchar('\n'); 487 putchar('\t'); 488 489 case 'E': /* INCR and DECR, FOREFF */ 490 if (p->in.right->tn.lval == 1) 491 { 492 putstr( p->in.op == INCR ? "inc" : "dec" ); 493 prtype(p->in.left); 494 putchar('\t'); 495 adrput(p->in.left); 496 return; 497 } 498 putstr( p->in.op == INCR ? "add" : "sub" ); 499 prtype(p->in.left); 500 putchar('2'); 501 putchar('\t'); 502 adrput(p->in.right); 503 putchar(','); 504 adrput(p->in.left); 505 return; 506 507 case 'F': /* register type of right operand */ 508 { 509 register NODE *n; 510 extern int xdebug; 511 register int ty; 512 513 n = getlr( p, 'R' ); 514 ty = n->in.type; 515 516 if (xdebug) printf("->%d<-", ty); 517 518 if ( ty==DOUBLE) putchar('d'); 519 else if ( ty==FLOAT ) putchar('f'); 520 else putchar('l'); 521 return; 522 } 523 524 case 'L': /* type of left operand */ 525 case 'R': /* type of right operand */ 526 { 527 register NODE *n; 528 extern int xdebug; 529 530 n = getlr( p, c ); 531 if (xdebug) printf("->%d<-", n->in.type); 532 533 prtype(n); 534 return; 535 } 536 537 case 'Z': /* complement mask for bit instr */ 538 printf("$%ld", ~p->in.right->tn.lval); 539 return; 540 541 case 'U': /* 32 - n, for unsigned right shifts */ 542 printf("$%d", 32 - p->in.right->tn.lval ); 543 return; 544 545 case 'T': /* rounded structure length for arguments */ 546 { 547 int size; 548 549 size = p->stn.stsize; 550 SETOFF( size, 4); 551 printf("$%d", size); 552 return; 553 } 554 555 case 'S': /* structure assignment */ 556 { 557 register NODE *l, *r; 558 register size; 559 560 if( p->in.op == STASG ){ 561 l = p->in.left; 562 r = p->in.right; 563 564 } 565 else if( p->in.op == STARG ){ /* store an arg into a temporary */ 566 r = p->in.left; 567 } 568 else cerror( "STASG bad" ); 569 570 if( r->in.op == ICON ) r->in.op = NAME; 571 else if( r->in.op == REG ) r->in.op = OREG; 572 else if( r->in.op != OREG ) cerror( "STASG-r" ); 573 574 size = p->stn.stsize; 575 576 if( size <= 0 || size > 65535 ) 577 cerror("structure size <0=0 or >65535"); 578 579 switch(size) { 580 case 1: 581 putstr(" movb "); 582 break; 583 case 2: 584 putstr(" movw "); 585 break; 586 case 4: 587 putstr(" movl "); 588 break; 589 case 8: 590 putstr(" movq "); 591 break; 592 default: 593 printf(" movc3 $%d,", size); 594 break; 595 } 596 adrput(r); 597 if( p->in.op == STASG ){ 598 putchar(','); 599 adrput(l); 600 putchar('\n'); 601 } 602 else 603 putstr(",(sp)\n"); 604 605 if( r->in.op == NAME ) r->in.op = ICON; 606 else if( r->in.op == OREG ) r->in.op = REG; 607 608 } 609 break; 610 611 default: 612 cerror( "illegal zzzcode" ); 613 } 614 } 615 616 /* 617 * collapsible(dest, src) -- if a conversion with a register destination 618 * can be accomplished in one instruction, return the type of src 619 * that will do the job correctly; otherwise return 0. Note that 620 * a register must always end up having type INT or UNSIGNED. 621 */ 622 int 623 collapsible(dest, src) 624 NODE *dest, *src; 625 { 626 int st = src->in.type; 627 int dt = dest->in.type; 628 int newt = 0; 629 630 /* 631 * Are there side effects of evaluating src? 632 * If the derived type will not be the same size as src, 633 * we may have to use two steps. 634 */ 635 if (tlen(src) > tlen(dest)) { 636 if (tshape(src, STARREG)) 637 return (0); 638 if (src->in.op == OREG && R2TEST(src->tn.rval)) 639 return (0); 640 } 641 642 /* 643 * Can we get an object of dest's type by punning src? 644 * Praises be to great Cthulhu for little-endian machines... 645 */ 646 if (st == CHAR && dt == USHORT) 647 /* 648 * Special case -- we must sign-extend to 16 bits. 649 */ 650 return (0); 651 652 if (tlen(src) < tlen(dest)) 653 newt = st; 654 else 655 newt = dt; 656 657 return (newt); 658 } 659 660 rmove( rt, rs, t ) TWORD t; { 661 printf( " %s %s,%s\n", 662 #ifdef FORT 663 !Oflag ? (t==DOUBLE ? "movq" : "movl") : 664 #endif 665 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 666 rnames[rs], rnames[rt] ); 667 } 668 669 struct respref 670 respref[] = { 671 INTAREG|INTBREG, INTAREG|INTBREG, 672 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 673 INTEMP, INTEMP, 674 FORARG, FORARG, 675 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 676 0, 0 }; 677 678 setregs(){ /* set up temporary registers */ 679 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 680 ; 681 } 682 683 /*ARGSUSED*/ 684 rewfld( p ) NODE *p; { 685 return(1); 686 } 687 688 /*ARGSUSED*/ 689 callreg(p) NODE *p; { 690 return( R0 ); 691 } 692 693 base( p ) register NODE *p; { 694 register int o = p->in.op; 695 696 if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ 697 if( o==REG ) return( p->tn.rval ); 698 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 699 return( p->in.left->tn.rval ); 700 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 701 return( p->tn.rval + 0200*1 ); 702 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 703 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 704 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 705 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 706 return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 707 return( -1 ); 708 } 709 710 offset( p, tyl ) register NODE *p; int tyl; { 711 712 if( tyl==1 && 713 p->in.op==REG && 714 (p->in.type==INT || p->in.type==UNSIGNED) ) 715 return( p->tn.rval ); 716 if( p->in.op==LS && 717 p->in.left->in.op==REG && 718 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 719 p->in.right->in.op==ICON && 720 p->in.right->in.name[0]=='\0' && 721 (1<<p->in.right->tn.lval)==tyl) 722 return( p->in.left->tn.rval ); 723 if( tyl==2 && 724 p->in.op==PLUS && 725 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 726 p->in.left->in.op==REG && 727 p->in.right->in.op==REG && 728 p->in.left->tn.rval==p->in.right->tn.rval ) 729 return( p->in.left->tn.rval ); 730 return( -1 ); 731 } 732 733 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 734 register NODE *t; 735 NODE *f; 736 737 p->in.op = OREG; 738 f = p->in.left; /* have to free this subtree later */ 739 740 /* init base */ 741 switch (q->in.op) { 742 case ICON: 743 case REG: 744 case OREG: 745 t = q; 746 break; 747 748 case MINUS: 749 q->in.right->tn.lval = -q->in.right->tn.lval; 750 case PLUS: 751 t = q->in.right; 752 break; 753 754 case INCR: 755 case ASG MINUS: 756 t = q->in.left; 757 break; 758 759 case UNARY MUL: 760 t = q->in.left->in.left; 761 break; 762 763 default: 764 cerror("illegal makeor2"); 765 } 766 767 p->tn.lval = t->tn.lval; 768 #ifndef FLEXNAMES 769 { 770 register int i; 771 for(i=0; i<NCHNAM; ++i) 772 p->in.name[i] = t->in.name[i]; 773 } 774 #else 775 p->in.name = t->in.name; 776 #endif 777 778 /* init offset */ 779 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 780 781 tfree(f); 782 return; 783 } 784 785 canaddr( p ) NODE *p; { 786 register int o = p->in.op; 787 788 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 789 return(0); 790 } 791 792 flshape( p ) register NODE *p; { 793 return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON || 794 (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 795 } 796 797 /* INTEMP shapes must not contain any temporary registers */ 798 shtemp( p ) register NODE *p; { 799 int r; 800 801 if( p->in.op == STARG ) p = p->in.left; 802 803 switch (p->in.op) { 804 case REG: 805 return( !istreg(p->tn.rval) ); 806 case OREG: 807 r = p->tn.rval; 808 if( R2TEST(r) ) { 809 if( istreg(R2UPK1(r)) ) 810 return(0); 811 r = R2UPK2(r); 812 } 813 return( !istreg(r) ); 814 case UNARY MUL: 815 p = p->in.left; 816 return( p->in.op != UNARY MUL && shtemp(p) ); 817 } 818 819 if( optype( p->in.op ) != LTYPE ) return(0); 820 return(1); 821 } 822 823 shumul( p ) register NODE *p; { 824 register o; 825 extern int xdebug; 826 827 if (xdebug) { 828 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 829 printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 830 } 831 832 833 o = p->in.op; 834 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 835 836 if( ( o == INCR || o == ASG MINUS ) && 837 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 838 p->in.right->in.name[0] == '\0' ) 839 { 840 switch (p->in.type) 841 { 842 case CHAR|PTR: 843 case UCHAR|PTR: 844 o = 1; 845 break; 846 847 case SHORT|PTR: 848 case USHORT|PTR: 849 o = 2; 850 break; 851 852 case INT|PTR: 853 case UNSIGNED|PTR: 854 case LONG|PTR: 855 case ULONG|PTR: 856 case FLOAT|PTR: 857 o = 4; 858 break; 859 860 case DOUBLE|PTR: 861 o = 8; 862 break; 863 864 default: 865 if ( ISPTR(p->in.type) && 866 ISPTR(DECREF(p->in.type)) ) { 867 o = 4; 868 break; 869 } 870 else return(0); 871 } 872 return( p->in.right->tn.lval == o ? STARREG : 0); 873 } 874 875 return( 0 ); 876 } 877 878 adrcon( val ) CONSZ val; { 879 putchar( '$' ); 880 printf( CONFMT, val ); 881 } 882 883 conput( p ) register NODE *p; { 884 switch( p->in.op ){ 885 886 case ICON: 887 acon( p ); 888 return; 889 890 case REG: 891 putstr( rnames[p->tn.rval] ); 892 return; 893 894 default: 895 cerror( "illegal conput" ); 896 } 897 } 898 899 /*ARGSUSED*/ 900 insput( p ) NODE *p; { 901 cerror( "insput" ); 902 } 903 904 upput( p, size ) NODE *p; int size; { 905 if( size == SZLONG && p->in.op == REG ) { 906 putstr( rnames[p->tn.rval + 1] ); 907 return; 908 } 909 cerror( "upput" ); 910 } 911 912 adrput( p ) register NODE *p; { 913 register int r; 914 /* output an address, with offsets, from p */ 915 916 if( p->in.op == FLD ){ 917 p = p->in.left; 918 } 919 switch( p->in.op ){ 920 921 case NAME: 922 acon( p ); 923 return; 924 925 case ICON: 926 /* addressable value of the constant */ 927 putchar( '$' ); 928 acon( p ); 929 return; 930 931 case REG: 932 putstr( rnames[p->tn.rval] ); 933 return; 934 935 case OREG: 936 r = p->tn.rval; 937 if( R2TEST(r) ){ /* double indexing */ 938 register int flags; 939 940 flags = R2UPK3(r); 941 if( flags & 1 ) putchar('*'); 942 if( flags & 4 ) putchar('-'); 943 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 944 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 945 if( flags & 2 ) putchar('+'); 946 printf( "[%s]", rnames[R2UPK2(r)] ); 947 return; 948 } 949 if( r == AP ){ /* in the argument region */ 950 if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 951 printf( CONFMT, p->tn.lval ); 952 putstr( "(ap)" ); 953 return; 954 } 955 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 956 printf( "(%s)", rnames[p->tn.rval] ); 957 return; 958 959 case UNARY MUL: 960 /* STARNM or STARREG found */ 961 if( tshape(p, STARNM) ) { 962 putchar( '*' ); 963 adrput( p->in.left); 964 } 965 else { /* STARREG - really auto inc or dec */ 966 register NODE *q; 967 968 /* tbl 969 p = p->in.left; 970 p->in.left->in.op = OREG; 971 if( p->in.op == INCR ) { 972 adrput( p->in.left ); 973 putchar( '+' ); 974 } 975 else { 976 putchar( '-' ); 977 adrput( p->in.left ); 978 } 979 tbl */ 980 q = p->in.left; 981 if( q->in.right->tn.lval != tlen(p) ) 982 cerror("adrput: bad auto-increment/decrement"); 983 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 984 rnames[q->in.left->tn.rval], 985 (q->in.op==INCR ? "+" : "") ); 986 p->in.op = OREG; 987 p->tn.rval = q->in.left->tn.rval; 988 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 989 #ifndef FLEXNAMES 990 p->in.name[0] = '\0'; 991 #else 992 p->in.name = ""; 993 #endif 994 tfree(q); 995 } 996 return; 997 998 default: 999 cerror( "illegal address" ); 1000 return; 1001 1002 } 1003 1004 } 1005 1006 acon( p ) register NODE *p; { /* print out a constant */ 1007 1008 if( p->in.name[0] == '\0' ){ 1009 printf( CONFMT, p->tn.lval); 1010 } 1011 else if( p->tn.lval == 0 ) { 1012 #ifndef FLEXNAMES 1013 printf( "%.8s", p->in.name ); 1014 #else 1015 putstr( p->in.name ); 1016 #endif 1017 } 1018 else { 1019 #ifndef FLEXNAMES 1020 printf( "%.8s+", p->in.name ); 1021 #else 1022 printf( "%s+", p->in.name ); 1023 #endif 1024 printf( CONFMT, p->tn.lval ); 1025 } 1026 } 1027 1028 /* 1029 aacon( p ) register NODE *p; { /* print out a constant */ 1030 /* 1031 1032 if( p->in.name[0] == '\0' ){ 1033 printf( CONFMT, p->tn.lval); 1034 return( 0 ); 1035 } 1036 else if( p->tn.lval == 0 ) { 1037 #ifndef FLEXNAMES 1038 printf( "$%.8s", p->in.name ); 1039 #else 1040 printf( "$%s", p->in.name ); 1041 #endif 1042 return( 1 ); 1043 } 1044 else { 1045 printf( "$(" ); 1046 printf( CONFMT, p->tn.lval ); 1047 printf( "+" ); 1048 #ifndef FLEXNAMES 1049 printf( "%.8s)", p->in.name ); 1050 #else 1051 printf( "%s)", p->in.name ); 1052 #endif 1053 return(1); 1054 } 1055 } 1056 */ 1057 1058 genscall( p, cookie ) register NODE *p; { 1059 /* structure valued call */ 1060 return( gencall( p, cookie ) ); 1061 } 1062 1063 /* tbl */ 1064 int gc_numbytes; 1065 /* tbl */ 1066 1067 /*ARGSUSED*/ 1068 gencall( p, cookie ) register NODE *p; { 1069 /* generate the call given by p */ 1070 register NODE *p1; 1071 register temp, temp1; 1072 register m; 1073 1074 if( p->in.right ) temp = argsize( p->in.right ); 1075 else temp = 0; 1076 1077 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 1078 /* set aside room for structure return */ 1079 1080 if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 1081 else temp1 = temp; 1082 } 1083 1084 if( temp > maxargs ) maxargs = temp; 1085 SETOFF(temp1,4); 1086 1087 if( p->in.right ){ /* make temp node, put offset in, and generate args */ 1088 genargs( p->in.right ); 1089 } 1090 1091 p1 = p->in.left; 1092 if( p1->in.op != ICON ){ 1093 if( p1->in.op != REG ){ 1094 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 1095 if( p1->in.op != NAME ){ 1096 order( p1, INAREG ); 1097 } 1098 } 1099 } 1100 } 1101 1102 /* 1103 if( p1->in.op == REG && p->tn.rval == R5 ){ 1104 cerror( "call register overwrite" ); 1105 } 1106 */ 1107 /* tbl 1108 setup gc_numbytes so reference to ZC works */ 1109 1110 gc_numbytes = temp&(0x3ff); 1111 /* tbl */ 1112 1113 p->in.op = UNARY CALL; 1114 m = match( p, INTAREG|INTBREG ); 1115 1116 /* compensate for deficiency in 'ret' instruction ... wah,kre */ 1117 /* (plus in assignment to gc_numbytes above, for neatness only) */ 1118 if (temp >= 1024) 1119 printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 1120 1121 /* tbl 1122 switch( temp ) { 1123 case 0: 1124 break; 1125 case 2: 1126 printf( " tst (sp)+\n" ); 1127 break; 1128 case 4: 1129 printf( " cmp (sp)+,(sp)+\n" ); 1130 break; 1131 default: 1132 printf( " add $%d,sp\n", temp); 1133 } 1134 tbl */ 1135 return(m != MDONE); 1136 } 1137 1138 /* tbl */ 1139 char * 1140 ccbranches[] = { 1141 " jeql L%d\n", 1142 " jneq L%d\n", 1143 " jleq L%d\n", 1144 " jlss L%d\n", 1145 " jgeq L%d\n", 1146 " jgtr L%d\n", 1147 " jlequ L%d\n", 1148 " jlssu L%d\n", 1149 " jgequ L%d\n", 1150 " jgtru L%d\n", 1151 }; 1152 /* tbl */ 1153 1154 /*ARGSUSED*/ 1155 cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 1156 1157 /* tbl */ 1158 if( o == 0 ) printf( " jbr L%d\n", lab ); 1159 /* tbl */ 1160 else { 1161 if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 1162 printf( ccbranches[o-EQ], lab ); 1163 } 1164 } 1165 1166 nextcook( p, cookie ) NODE *p; { 1167 /* we have failed to match p with cookie; try another */ 1168 if( cookie == FORREW ) return( 0 ); /* hopeless! */ 1169 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 1170 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 1171 return( FORREW ); 1172 } 1173 1174 /*ARGSUSED*/ 1175 lastchance( p, cook ) NODE *p; { 1176 /* forget it! */ 1177 return(0); 1178 } 1179 1180 optim2( p ) register NODE *p; { 1181 /* do local tree transformations and optimizations */ 1182 1183 int o; 1184 int result, i; 1185 int lower, upper; 1186 register NODE *l, *r; 1187 1188 switch( o = p->in.op ) { 1189 1190 case AND: 1191 /* commute L and R to eliminate complements and constants */ 1192 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 1193 l->in.op == COMPL ) { 1194 p->in.left = p->in.right; 1195 p->in.right = l; 1196 } 1197 case ASG AND: 1198 /* change meaning of AND to ~R&L - bic on pdp11 */ 1199 r = p->in.right; 1200 if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 1201 r->tn.lval = ~r->tn.lval; 1202 } 1203 else if( r->in.op==COMPL ) { /* ~~A => A */ 1204 r->in.op = FREE; 1205 p->in.right = r->in.left; 1206 } 1207 else { /* insert complement node */ 1208 p->in.right = l = talloc(); 1209 l->in.op = COMPL; 1210 l->in.rall = NOPREF; 1211 l->in.type = r->in.type; 1212 l->in.left = r; 1213 l->in.right = NULL; 1214 } 1215 break; 1216 1217 case SCONV: 1218 l = p->in.left; 1219 #if defined(FORT) || defined(SPRECC) 1220 if( p->in.type == FLOAT || p->in.type == DOUBLE || 1221 l->in.type == FLOAT || l->in.type == DOUBLE ) 1222 return; 1223 #else 1224 if( mixtypes(p, l) ) return; 1225 #endif 1226 if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL ) 1227 return; 1228 1229 /* Only trust it to get it right if the size is the same */ 1230 if( tlen(p) != tlen(l) ) 1231 return; 1232 1233 /* clobber conversion */ 1234 if( l->in.op != FLD ) 1235 l->in.type = p->in.type; 1236 ncopy( p, l ); 1237 l->in.op = FREE; 1238 1239 break; 1240 1241 case ASSIGN: 1242 /* 1243 * Conversions are equivalent to assignments; 1244 * when the two operations are combined, 1245 * we can sometimes zap the conversion. 1246 */ 1247 r = p->in.right; 1248 l = p->in.left; 1249 if ( r->in.op == SCONV && 1250 !mixtypes(l, r) && 1251 l->in.op != FLD && 1252 tlen(l) == tlen(r) ) { 1253 p->in.right = r->in.left; 1254 r->in.op = FREE; 1255 } 1256 break; 1257 1258 case ULE: 1259 case ULT: 1260 case UGE: 1261 case UGT: 1262 o -= (UGE-GE); 1263 case EQ: 1264 case NE: 1265 case LE: 1266 case LT: 1267 case GE: 1268 case GT: 1269 r = p->in.right; 1270 l = p->in.left; 1271 if( r->in.op != ICON || 1272 r->tn.name[0] != '\0' || 1273 tlen(l) >= tlen(r) ) 1274 break; 1275 switch( l->in.type ) { 1276 case CHAR: 1277 lower = -(1 << SZCHAR - 1); 1278 upper = (1 << SZCHAR - 1) - 1; 1279 break; 1280 case UCHAR: 1281 lower = 0; 1282 upper = (1 << SZCHAR) - 1; 1283 break; 1284 case SHORT: 1285 lower = -(1 << SZSHORT - 1); 1286 upper = (1 << SZSHORT - 1) - 1; 1287 break; 1288 case USHORT: 1289 lower = 0; 1290 upper = (1 << SZSHORT) - 1; 1291 break; 1292 default: 1293 cerror("unsupported OPLOG in optim2"); 1294 } 1295 result = -1; 1296 i = r->tn.lval; 1297 switch( o ) { 1298 case EQ: 1299 case NE: 1300 if( lower == 0 && (unsigned) i > upper ) 1301 result = o == NE; 1302 else if( i < lower || i > upper ) 1303 result = o == NE; 1304 break; 1305 case LT: 1306 case GE: 1307 if( lower == 0 && (unsigned) i > upper ) 1308 result = o == LT; 1309 else if( i <= lower ) 1310 result = o != LT; 1311 else if( i > upper ) 1312 result = o == LT; 1313 break; 1314 case LE: 1315 case GT: 1316 if( lower == 0 && (unsigned) i >= upper ) 1317 result = o == LE; 1318 else if( i < lower ) 1319 result = o != LE; 1320 else if( i >= upper ) 1321 result = o == LE; 1322 break; 1323 } 1324 if( result == -1 ) 1325 break; 1326 1327 if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1328 l->in.op = FREE; 1329 ncopy(p, r); 1330 r->in.op = FREE; 1331 p->tn.type = INT; 1332 p->tn.lval = result; 1333 } 1334 else { 1335 p->in.op = COMOP; 1336 p->in.type = INT; 1337 r->tn.type = INT; 1338 r->tn.lval = result; 1339 } 1340 break; 1341 } 1342 } 1343 1344 /*ARGSUSED*/ 1345 NODE * addroreg(l) NODE *l; 1346 /* OREG was built in clocal() 1347 * for an auto or formal parameter 1348 * now its address is being taken 1349 * local code must unwind it 1350 * back to PLUS/MINUS REG ICON 1351 * according to local conventions 1352 */ 1353 { 1354 cerror("address of OREG taken"); 1355 /*NOTREACHED*/ 1356 } 1357 1358 1359 1360 # ifndef ONEPASS 1361 main( argc, argv ) char *argv[]; { 1362 return( mainp2( argc, argv ) ); 1363 } 1364 # endif 1365 1366 1367 /* added by jwf */ 1368 struct functbl { 1369 int fop; 1370 TWORD ftype; 1371 char *func; 1372 } opfunc[] = { 1373 DIV, TANY, "udiv", 1374 MOD, TANY, "urem", 1375 ASG DIV, TANY, "audiv", 1376 ASG MOD, TANY, "aurem", 1377 0, 0, 0 }; 1378 1379 hardops(p) register NODE *p; { 1380 /* change hard to do operators into function calls. */ 1381 register NODE *q; 1382 register struct functbl *f; 1383 register o; 1384 NODE *old,*temp; 1385 1386 o = p->in.op; 1387 if( ! (optype(o)==BITYPE && 1388 (ISUNSIGNED(p->in.left->in.type) || 1389 ISUNSIGNED(p->in.right->in.type))) ) 1390 return; 1391 1392 for( f=opfunc; f->fop; f++ ) { 1393 if( o==f->fop ) goto convert; 1394 } 1395 return; 1396 1397 convert: 1398 if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' ) { 1399 /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */ 1400 /* save a subroutine call -- use at most 5 instructions */ 1401 if( p->in.op == DIV && 1402 (unsigned) p->in.right->tn.lval >= 0x80000000 ) 1403 /* easy to do here, harder to do in zzzcode() */ 1404 p->in.op = UGE; 1405 return; 1406 } 1407 if( asgop( o ) ) { 1408 old = NIL; 1409 switch( p->in.left->in.op ){ 1410 case FLD: 1411 q = p->in.left->in.left; 1412 /* 1413 * rewrite (lval.fld /= rval); as 1414 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 1415 * else the compiler will evaluate lval twice. 1416 */ 1417 if( q->in.op == UNARY MUL ){ 1418 /* first allocate a temp storage */ 1419 temp = talloc(); 1420 temp->in.op = OREG; 1421 temp->tn.rval = TMPREG; 1422 temp->tn.lval = BITOOR(freetemp(1)); 1423 temp->in.type = INCREF(p->in.type); 1424 #ifdef FLEXNAMES 1425 temp->in.name = ""; 1426 #else 1427 temp->in.name[0] = '\0'; 1428 #endif 1429 old = q->in.left; 1430 q->in.left = temp; 1431 } 1432 /* fall thru ... */ 1433 1434 case REG: 1435 case NAME: 1436 case OREG: 1437 /* change ASG OP to a simple OP */ 1438 q = talloc(); 1439 q->in.op = NOASG p->in.op; 1440 q->in.rall = NOPREF; 1441 q->in.type = p->in.type; 1442 q->in.left = tcopy(p->in.left); 1443 q->in.right = p->in.right; 1444 p->in.op = ASSIGN; 1445 p->in.right = q; 1446 p = q; 1447 f -= 2; /* Note: this depends on the table order */ 1448 /* on the right side only - replace *temp with 1449 *(temp = &lval), build the assignment node */ 1450 if( old ){ 1451 temp = q->in.left->in.left; /* the "*" node */ 1452 q = talloc(); 1453 q->in.op = ASSIGN; 1454 q->in.left = temp->in.left; 1455 q->in.right = old; 1456 q->in.type = old->in.type; 1457 #ifdef FLEXNAMES 1458 q->in.name = ""; 1459 #else 1460 q->in.name[0] = '\0'; 1461 #endif 1462 temp->in.left = q; 1463 } 1464 break; 1465 1466 case UNARY MUL: 1467 /* avoid doing side effects twice */ 1468 q = p->in.left; 1469 p->in.left = q->in.left; 1470 q->in.op = FREE; 1471 break; 1472 1473 default: 1474 cerror( "hardops: can't compute & LHS" ); 1475 } 1476 } 1477 1478 /* build comma op for args to function */ 1479 q = talloc(); 1480 q->in.op = CM; 1481 q->in.rall = NOPREF; 1482 q->in.type = INT; 1483 q->in.left = p->in.left; 1484 q->in.right = p->in.right; 1485 p->in.op = CALL; 1486 p->in.right = q; 1487 1488 /* put function name in left node of call */ 1489 p->in.left = q = talloc(); 1490 q->in.op = ICON; 1491 q->in.rall = NOPREF; 1492 q->in.type = INCREF( FTN + p->in.type ); 1493 #ifndef FLEXNAMES 1494 strcpy( q->in.name, f->func ); 1495 #else 1496 q->in.name = f->func; 1497 #endif 1498 q->tn.lval = 0; 1499 q->tn.rval = 0; 1500 1501 } 1502 1503 zappost(p) NODE *p; { 1504 /* look for ++ and -- operators and remove them */ 1505 1506 register o, ty; 1507 register NODE *q; 1508 o = p->in.op; 1509 ty = optype( o ); 1510 1511 switch( o ){ 1512 1513 case INCR: 1514 case DECR: 1515 q = p->in.left; 1516 p->in.right->in.op = FREE; /* zap constant */ 1517 ncopy( p, q ); 1518 q->in.op = FREE; 1519 return; 1520 1521 } 1522 1523 if( ty == BITYPE ) zappost( p->in.right ); 1524 if( ty != LTYPE ) zappost( p->in.left ); 1525 } 1526 1527 fixpre(p) NODE *p; { 1528 1529 register o, ty; 1530 o = p->in.op; 1531 ty = optype( o ); 1532 1533 switch( o ){ 1534 1535 case ASG PLUS: 1536 p->in.op = PLUS; 1537 break; 1538 case ASG MINUS: 1539 p->in.op = MINUS; 1540 break; 1541 } 1542 1543 if( ty == BITYPE ) fixpre( p->in.right ); 1544 if( ty != LTYPE ) fixpre( p->in.left ); 1545 } 1546 1547 strip(p) register NODE *p; { 1548 NODE *q; 1549 1550 /* strip nodes off the top when no side effects occur */ 1551 for( ; ; ) { 1552 switch( p->in.op ) { 1553 case SCONV: /* remove lint tidbits */ 1554 q = p->in.left; 1555 ncopy( p, q ); 1556 q->in.op = FREE; 1557 break; 1558 /* could probably add a few more here */ 1559 default: 1560 return; 1561 } 1562 } 1563 } 1564 1565 myreader(p) register NODE *p; { 1566 strip( p ); /* strip off operations with no side effects */ 1567 canon( p ); /* expands r-vals for fields */ 1568 walkf( p, hardops ); /* convert ops to function calls */ 1569 walkf( p, optim2 ); 1570 /* jwf toff = 0; /* stack offset swindle */ 1571 } 1572