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