|
|
1.1 ! root 1: # include "cpass2.h" ! 2: #ifndef lint ! 3: static char sccsid[] = "@(#)order.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 4: #endif ! 5: ! 6: /* ! 7: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 8: */ ! 9: ! 10: /* ! 11: * order.c -- conditionally included 680X0 version ! 12: */ ! 13: ! 14: ! 15: int fltused = 0; ! 16: int floatmath = 0; ! 17: ! 18: SUTYPE fregs; ! 19: ! 20: extern int mina, maxa, minb, maxb; /* imported from allo.c */ ! 21: extern int toff, maxtoff; ! 22: ! 23: int maxargs = { -1 }; ! 24: ! 25: static SUTYPE zed = { 0,0,0,0 }; ! 26: ! 27: int failsafe; /* very disgusting: see offstar() for use */ ! 28: ! 29: # define SAFETY( a, reg, b ) \ ! 30: {if ((reg & MUSTDO) && find_mustdo( a , reg )) {rewrite_rall( b, 1 );} } ! 31: # define iscnode(p) ((p)->in.op==REG && iscreg((p)->tn.rval)) ! 32: ! 33: # define max(x,y) ((x)<(y)?(y):(x)) ! 34: # define min(x,y) ((x)<(y)?(x):(y)) ! 35: ! 36: # define divmulop(o) (dope[o]&(DIVFLG|MULFLG)) ! 37: ! 38: ! 39: NODE * ! 40: double_conv( p ) register NODE *p; ! 41: { ! 42: NODE *q = talloc(); ! 43: q->in.op = SCONV; ! 44: q->in.type = DOUBLE; ! 45: q->in.left = p; ! 46: q->in.rall = p->in.rall; ! 47: if (use68881) { ! 48: q->in.su.d = max( p->in.su.d, 1 ); ! 49: q->in.su.a = 0; ! 50: q->in.su.f = max( p->in.su.f, 1 ); ! 51: } else { ! 52: p->in.rall = MUSTDO|D0; ! 53: q->in.su.d = max( p->in.su.d, fregs.d ); ! 54: q->in.su.a = max( p->in.su.a, fregs.a ); ! 55: q->in.su.f = max( p->in.su.f, fregs.f ); ! 56: } ! 57: return q; ! 58: } ! 59: ! 60: setincr( p ) register NODE *p; ! 61: { ! 62: return( 0 ); ! 63: } ! 64: ! 65: niceuty( p ) register NODE *p; ! 66: { ! 67: return( p->in.op == UNARY MUL && p->in.type != FLOAT && ! 68: shumul( p->in.left) == STARNM ); ! 69: } ! 70: ! 71: setconv( p, cookie ) ! 72: NODE *p; ! 73: { ! 74: register NODE *lp; ! 75: TWORD t; ! 76: ! 77: lp = p->in.left; ! 78: switch(p->in.type) { ! 79: case FLOAT: ! 80: case DOUBLE: ! 81: /* convert from something nice to something icky */ ! 82: if ( use68881 ) { ! 83: if (p->in.type == DOUBLE && iscnode(lp)) { ! 84: /* ! 85: * no code necessary -- floating point ! 86: * regs are always in extended format ! 87: */ ! 88: TWORD t = p->in.type; ! 89: *p = *lp; ! 90: p->in.type = t; ! 91: lp->in.op = FREE; ! 92: return(1); ! 93: } ! 94: if (ISFLOATING(lp->in.type)) { ! 95: /* ! 96: * float => double, or vice versa ! 97: */ ! 98: order(lp, INCREG|INTCREG|INTEMP); ! 99: return(1); ! 100: } ! 101: if (ISUNSIGNED(lp->in.type)) { ! 102: /* ! 103: * the 68881 doesn't deal with unsigned types; ! 104: * convert the unsigned operand to INT. ! 105: */ ! 106: register NODE *q; ! 107: q = talloc(); ! 108: q->in.op = SCONV; ! 109: q->in.type = INT; ! 110: q->in.left = lp; ! 111: q->in.rall = lp->in.rall; ! 112: q->in.su.d = 1; ! 113: q->in.su.a = 0; ! 114: q->in.su.f = 0; ! 115: p->in.left = lp = q; ! 116: } ! 117: break; ! 118: } ! 119: failsafe = 1; ! 120: break; ! 121: default: ! 122: /* check for inverse (floating type => fixed type) */ ! 123: if (lp->in.type == FLOAT || lp->in.type == DOUBLE) { ! 124: if (use68881) { ! 125: order(lp, INCREG|INTCREG|INTEMP); ! 126: return(1); ! 127: } ! 128: failsafe = 1; ! 129: } ! 130: break; ! 131: } ! 132: if (cookie!=(INBREG|INTBREG)) ! 133: cookie = (INAREG|INTAREG|INBREG|INTBREG); ! 134: cookie |= INTEMP; ! 135: order( p->in.left, cookie ); ! 136: return 1; ! 137: } ! 138: ! 139: /* ! 140: * deal properly with the operand of a unary operator. ! 141: */ ! 142: int ! 143: setunary(p, cookie) ! 144: NODE *p; ! 145: { ! 146: NODE *lp; ! 147: ! 148: lp = p->in.left; ! 149: if (use68881 && ISFLOATING(lp->in.type)) { ! 150: switch(p->in.op) { ! 151: case FCOS: ! 152: case FSIN: ! 153: case FTAN: ! 154: case FACOS: ! 155: case FASIN: ! 156: case FATAN: ! 157: case FCOSH: ! 158: case FSINH: ! 159: case FTANH: ! 160: case FEXP: ! 161: case F10TOX: ! 162: case F2TOX: ! 163: case FLOGN: ! 164: case FLOG10: ! 165: case FLOG2: ! 166: case FSQR: ! 167: case FSQRT: ! 168: case FAINT: ! 169: case FANINT: ! 170: floatsrce(lp); ! 171: return(1); ! 172: case FNINT: ! 173: order(lp, INCREG|INTCREG); ! 174: return(1); ! 175: case UNARY MINUS: ! 176: case FABS: ! 177: /* don't use the 81 unless we have to */ ! 178: order(lp, INAREG|INCREG); ! 179: return(1); ! 180: default: ! 181: break; ! 182: } ! 183: } ! 184: order(lp, INAREG|INBREG|INCREG); ! 185: return(1); ! 186: } ! 187: ! 188: /* ! 189: * put p into a form acceptable as a 68881 source operand. ! 190: */ ! 191: static ! 192: floatsrce(p) ! 193: register NODE *p; ! 194: { ! 195: if (p->in.op == SCONV) { ! 196: /* ! 197: * the 68881 converts signed ints, float, and double ! 198: * to internal (extended) format automatically. ! 199: */ ! 200: switch(p->in.left->in.type) { ! 201: case CHAR: ! 202: case SHORT: ! 203: case INT: ! 204: case LONG: ! 205: case FLOAT: ! 206: case DOUBLE: ! 207: p = p->in.left; ! 208: break; ! 209: default: ! 210: /* must do the conversion explicitly */ ! 211: order(p->in.left, INAREG|INTAREG|INTEMP); ! 212: break; ! 213: } ! 214: } ! 215: switch(p->in.op) { ! 216: case UNARY MUL: ! 217: /* just make it addressable */ ! 218: offstar(p->in.left); ! 219: break; ! 220: case REG: ! 221: /* coprocessor cannot access address registers */ ! 222: if (isbreg(p->tn.rval)) { ! 223: order(p, INTAREG|INAREG); ! 224: } ! 225: break; ! 226: default: ! 227: /* lacking any better ideas, put it in a register */ ! 228: if (SUTEST(p->in.su)) { ! 229: if (ISFLOATING(p->in.type)) { ! 230: order(p, INCREG|INTCREG|INTEMP); ! 231: } else { ! 232: order(p, INAREG|INTAREG|INTEMP); ! 233: } ! 234: } ! 235: break; ! 236: } ! 237: } ! 238: ! 239: setbin( p, cook ) register NODE *p; ! 240: { ! 241: register NODE *r, *l; ! 242: NODE *p2, *q, *t; ! 243: SUTYPE sur, sul; ! 244: SUTYPE qcost, pcost; ! 245: extern short revrel[]; /* for logic ops */ ! 246: int cookie, i; ! 247: ! 248: r = p->in.right; ! 249: l = p->in.left; ! 250: sur = r->in.su; ! 251: sul = l->in.su; ! 252: ! 253: cookie = cook; ! 254: if (cookie!=(INBREG|INTBREG)) ! 255: cookie = (INAREG|INTAREG|INBREG|INTBREG); ! 256: cookie |= INTEMP; ! 257: /* if this is one of the constrained operators, rewrite as op= */ ! 258: switch( p->in.op ){ ! 259: case GT: ! 260: case GE: ! 261: case LT: ! 262: case LE: ! 263: case EQ: ! 264: case NE: ! 265: if (l->in.type != FLOAT && l->in.type != DOUBLE) ! 266: break; ! 267: if (use68881) { ! 268: /* ! 269: * figure out what, if anything, is ! 270: * already in a coprocessor reg ! 271: */ ! 272: int lhs,rhs; ! 273: lhs = iscnode(l); ! 274: rhs = iscnode(r); ! 275: /* ! 276: * logical ops require one operand to ! 277: * be in a coprocessor register. table.c ! 278: * expects the register on the left. ! 279: */ ! 280: if ( !lhs ) { ! 281: /* lhs is not in a coprocessor reg */ ! 282: if ( !rhs ) { ! 283: /* rhs isn't either; do harder one */ ! 284: if (SUGT(sur, sul) ! 285: && !tshape(r, SFLOAT_SRCE)) { ! 286: order(r, INCREG|INTCREG); ! 287: rhs = 1; ! 288: } else { ! 289: order(l, INCREG|INTCREG); ! 290: lhs = 1; ! 291: } ! 292: } ! 293: if (rhs) { ! 294: /* rhs is, lhs isn't */ ! 295: int temp; ! 296: p->in.op = revrel[p->in.op - EQ]; ! 297: p->in.left = r; ! 298: p->in.right = l; ! 299: r = l; ! 300: l = p->in.left; ! 301: temp = rhs; ! 302: rhs = lhs; ! 303: lhs = temp; ! 304: } ! 305: } ! 306: /* ! 307: * lhs is in a coprocessor reg ! 308: */ ! 309: if ( !rhs ) { ! 310: /* ! 311: * rhs isn't, and doesn't need to be ! 312: */ ! 313: floatsrce(r); ! 314: } /* !rhs */ ! 315: return(1); ! 316: } /* use68881 */ ! 317: ! 318: /* ! 319: * evaluate most expensive side first. If ! 320: * cheaper size has non-zero cost, may have ! 321: * to put first intermediate result in a temp. ! 322: * Actually, this should not be a problem, if ! 323: * the su-stuff worked. ! 324: */ ! 325: /* set variable "i" if we do anything here */ ! 326: i = 0; ! 327: if( SUGT( sul, sur ) && !(istnode(l)&&l->tn.rval==D0) ){ ! 328: /* do lhs first if it is the more expensive */ ! 329: l->in.rall = MUSTDO|D0; ! 330: SAFETY( r , MUSTDO|D0, l); ! 331: order( l, INTAREG); ! 332: i++; ! 333: } ! 334: if ( r->in.type == DOUBLE ){ ! 335: /* must be addressable */ ! 336: if ( !tshape( r, SNAME|SOREG|STARNM)){ ! 337: r->in.rall = NOPREF; ! 338: order( r, INTEMP ); ! 339: i++; ! 340: } ! 341: } else { ! 342: if( !(istnode(r) && r->tn.rval == D1) ){ ! 343: r->in.rall = MUSTDO|D1; ! 344: SAFETY( l , MUSTDO|D1, r); ! 345: order( r, INTAREG); ! 346: i++; ! 347: } ! 348: } ! 349: if( !(istnode(l) && l->tn.rval == D0) ){ ! 350: /* do lhs after if it is the less expensive */ ! 351: l->in.rall = MUSTDO|D0; ! 352: order( l, INTAREG); ! 353: i++; ! 354: } ! 355: if (i) ! 356: return 1; ! 357: break ; /* didn't accomplish anything -- fall into general case */ ! 358: case PLUS: ! 359: case MINUS: ! 360: if( p->in.type == FLOAT || p->in.type == DOUBLE ){ ! 361: float_ops: ! 362: /* ! 363: * evaluate most expensive side first. If ! 364: * cheaper size has non-zero cost, may have ! 365: * to put first intermediate result in a temp. ! 366: * Actually, this should not be a problem, if ! 367: * the su-stuff worked. ! 368: */ ! 369: if (r->in.type==FLOAT && (!FLOATMATH || p->in.type==DOUBLE)){ ! 370: r = p->in.right = double_conv(r); ! 371: } ! 372: if (l->in.type==FLOAT && (!FLOATMATH || p->in.type==DOUBLE)){ ! 373: l = p->in.left = double_conv(l); ! 374: } ! 375: /*----------------------------*/ ! 376: if (use68881) { ! 377: /* ! 378: * figure out what, if anything, is ! 379: * already in a coprocessor reg. The ! 380: * lhs must be a temporary. ! 381: */ ! 382: int lhs,rhs; ! 383: lhs = (istnode(l) && iscreg(l->tn.rval)); ! 384: rhs = (iscnode(r)); ! 385: /* ! 386: * dyadic ops require one operand to ! 387: * be in a coprocessor register. table.c ! 388: * expects the register on the left. ! 389: */ ! 390: if ( !lhs ) { ! 391: /* lhs is not in a temp coprocessor reg */ ! 392: if ( !rhs ) { ! 393: /* rhs isn't either; do harder one */ ! 394: if (SUGT(sur, sul) ! 395: && !tshape(r, SFLOAT_SRCE)) { ! 396: floatsrce(r); ! 397: rhs = iscnode(r); ! 398: } else { ! 399: order(l, INTCREG); ! 400: lhs = 1; ! 401: } ! 402: } ! 403: if ( rhs && !lhs && istnode(r) ! 404: && (p->in.op == PLUS || p->in.op == MUL) ) { ! 405: /* ! 406: * rhs is in a writable coprocessor ! 407: * reg, lhs isn't, and op is commutable ! 408: */ ! 409: int temp; ! 410: p->in.left = r; ! 411: p->in.right = l; ! 412: r = l; ! 413: l = p->in.left; ! 414: temp = rhs; ! 415: rhs = lhs; ! 416: lhs = temp; ! 417: } ! 418: if (!lhs) { ! 419: order(l, INTCREG); ! 420: lhs = 1; ! 421: } ! 422: } ! 423: /* ! 424: * lhs is in a writable coprocessor reg ! 425: */ ! 426: if ( !rhs ) { ! 427: /* ! 428: * rhs isn't, and doesn't need to be ! 429: */ ! 430: floatsrce(r); ! 431: } ! 432: p->in.op = ASG p->in.op; ! 433: return(1); ! 434: } /* use68881 */ ! 435: ! 436: if (usesky) { ! 437: if ( p->in.op == PLUS ) { ! 438: /* ! 439: * look for expressions of ! 440: * the form (x + y*z), which the ! 441: * sky board does in a single ! 442: * operation. ! 443: */ ! 444: if ( l->in.op == MUL && r->in.op != MUL ) { ! 445: l = r; ! 446: r = p->in.left; ! 447: p->in.left = l; ! 448: p->in.right = r; ! 449: } ! 450: if (r->in.op == MUL) { ! 451: /* ! 452: * Don't even go near it ! 453: * unless x,y, or z comes for free. ! 454: */ ! 455: if (!SUTEST(l->in.su)) { ! 456: l = r->in.left; ! 457: r = r->in.right; ! 458: } else if (!SUTEST(r->in.left->in.su)) { ! 459: r = r->in.right; ! 460: } else if (!SUTEST(r->in.right->in.su)) { ! 461: r = r->in.left; ! 462: } ! 463: } ! 464: } ! 465: for( i=0; i<2; i++ ){ ! 466: if (SUGT( l->in.su, r->in.su )){ ! 467: p2 = l; q = r; ! 468: }else if (SUTEST( r->in.su )){ ! 469: p2 = r; q = l; ! 470: }else break; ! 471: if (p2->in.op==UNARY MUL ! 472: && rewrite_b_rall(p2->in.left, 1)){ ! 473: /* try to offstar, but not into a1 */ ! 474: failsafe = find_mustdo( q, MUSTDO|D0 ); ! 475: offstar(p2->in.left); ! 476: } else { ! 477: if ( !find_mustdo( q, MUSTDO|D0) || ! 478: rewrite_rall(p2, i) ) ! 479: order( p2, INTAREG| INTBREG| INTEMP ); ! 480: else ! 481: order( p2, INTEMP ); ! 482: } ! 483: /* set su to zero here */ ! 484: p2->in.su = zed; ! 485: } /* for */ ! 486: } else { ! 487: /* ! 488: * do it in software ! 489: */ ! 490: if (p->in.type == FLOAT){ ! 491: /* assume rall's set up already */ ! 492: for( i=0; i<2; i++ ){ ! 493: if (SUGT( l->in.su, r->in.su )){ ! 494: p2 = l; q = r; ! 495: }else if (SUTEST( r->in.su )){ ! 496: p2 = r; q = l; ! 497: }else break; ! 498: SAFETY( q, D0|MUSTDO, p2 ); ! 499: failsafe = 1; ! 500: order( p2, INTAREG|INTBREG ); ! 501: p2->in.su = zed; ! 502: } ! 503: /* are no-cost, but may be wrong */ ! 504: if (!istnode(l) || l->tn.rval != D0) ! 505: order( l, INTAREG ); ! 506: } else { ! 507: /* this case is the least symmetric */ ! 508: /* basically, must rewrite lhs as d0/d1 */ ! 509: /* but if rhs is hard, do it first */ ! 510: if (!istnode(l) || l->tn.rval != D0){ ! 511: if (SUTEST( sur )){ ! 512: if (r->in.op == UNARY MUL ! 513: && ( !SUTEST(sul) || rewrite_b_rall( r->in.left, 0)) ){ ! 514: failsafe = 1; ! 515: offstar( r->in.left ); ! 516: } else { ! 517: order( r, INTEMP ); ! 518: } ! 519: } ! 520: failsafe = 1; ! 521: order( l, INTAREG ); ! 522: } ! 523: } ! 524: p->in.op = ASG p->in.op ; /* gag */ ! 525: } ! 526: /*----------------------------*/ ! 527: #ifdef FLOATMATH ! 528: if (!FLOATMATH) ! 529: #endif ! 530: p->in.type = DOUBLE; ! 531: return 1; /* order(): try again */ ! 532: } else if (ISPTR(p->in.type)){ ! 533: /* ! 534: * cute hack: we can add a short into an address register ! 535: * without extending it first. ! 536: */ ! 537: if ( isconv( l, SHORT, -1) && p->in.op==PLUS ){ ! 538: /* un-canonical form -- flip it */ ! 539: p->in.left = r; ! 540: p->in.right = r =l; ! 541: l = p->in.left; ! 542: } ! 543: if ( isconv( r, SHORT, -1 ) ){ ! 544: /* ! 545: * if this is being evaluated into an address ! 546: * register or for argument, delete the conversion ! 547: */ ! 548: if ( (cook==FORARG || (cook&(INBREG|INTBREG) ! 549: && !(cook&~(INBREG|INTBREG)))) ! 550: && l->tn.op==REG ! 551: && tshape( r->in.left, SAREG|STAREG|SBREG|STBREG|SNAME|SOREG|STARREG) ){ ! 552: if (cook==FORARG && r->in.left->tn.op != REG){ ! 553: order( r->in.left, INAREG|INTAREG|INBREG|INTBREG ); ! 554: } ! 555: /* lhs should be in an address register, ! 556: and should be writeable if SCONV operand ! 557: is not a register */ ! 558: if (!isbreg(l->tn.rval) ! 559: || !istreg(l->tn.rval) && r->in.left->in.op != REG) { ! 560: order( l, INBREG|INTBREG ); ! 561: } ! 562: p->in.right = r->in.left; ! 563: r->in.op = FREE; ! 564: return 1; ! 565: } else if (p->in.op == PLUS) { ! 566: /* otherwise, we were better off the other way */ ! 567: /* flip back */ ! 568: p->in.left = r; ! 569: p->in.right = r =l; ! 570: l = p->in.left; ! 571: } ! 572: } ! 573: } ! 574: break; ! 575: case MUL: ! 576: case DIV: ! 577: case MOD: ! 578: if( p->in.type == FLOAT || p->in.type == DOUBLE ){ ! 579: goto float_ops; ! 580: } ! 581: if( p->in.type != INT && p->in.type != UNSIGNED && !ISPTR(p->in.type)) ! 582: ! 583: break; ! 584: if(use68020) ! 585: break; ! 586: d0_d1: ! 587: /* copied from Setasop */ ! 588: sul = l->in.su; ! 589: sur = r->in.su; ! 590: /* use q to designate the more expensive side, p2 the cheaper */ ! 591: if (!SUGT(sur, sul)){ ! 592: q = l; p2 = r; pcost = sur; ! 593: } else { ! 594: q = r; p2 = l; pcost = sul; ! 595: } ! 596: if( SUTEST(sul) && SUTEST(sur) ){ ! 597: SAFETY( p2, q->in.rall, q ); ! 598: } ! 599: ! 600: /* do code emission, most expensive side first */ ! 601: if (!istnode( q ) ){ ! 602: order( q, INAREG|INTAREG); ! 603: } ! 604: if ( SUTEST( pcost ) && !istnode( p2 )){ ! 605: order( p2 ,INAREG|INTAREG); ! 606: } ! 607: if ( !istnode( l ) || l->tn.rval != D0 ){ ! 608: l->tn.rall = MUSTDO | D0; ! 609: order( l, INTAREG); ! 610: } ! 611: if (logop(p->in.op)){ ! 612: if ( !istnode( r )||r->tn.rval != D1 ){ ! 613: r->tn.rall = MUSTDO | D1; ! 614: order( r, INTAREG); ! 615: } ! 616: } else { ! 617: if ( SUTEST( sur ) && (!istnode( r )||r->tn.rval != D1)){ ! 618: r->tn.rall = MUSTDO | D1; ! 619: order( r, INTAREG); ! 620: } ! 621: p->in.op = ASG p->in.op; ! 622: } ! 623: return 1; /* go try 'gain */ ! 624: case CHK: ! 625: /* ! 626: * the rhs of a CHK operator is an ordered pair ! 627: * of integers. We load the lhs first, regardless ! 628: * of what the bounds cost, since both the bounds ! 629: * and the lhs must be in hand simultaneously. ! 630: */ ! 631: if (!istnode(l) || !isareg(l->tn.lval)) { ! 632: SAFETY(r, MUSTDO|D0, l); ! 633: order(l, INTAREG|INAREG); ! 634: return(1); ! 635: } ! 636: return(0); ! 637: } /* switch */ ! 638: ! 639: if( !SUTEST( r->in.su ) ){ ! 640: /* rhs is addressable */ ! 641: if( logop( p->in.op ) ){ ! 642: if ( l->in.op==UNARY MUL ! 643: && l->in.type!=FLOAT && shumul(l->in.left)!=STARREG ) { ! 644: offstar( l->in.left ); ! 645: } else if ( !(l->in.op==REG && isareg(l->tn.rval))) { ! 646: /* lhs is not in a data register */ ! 647: switch (l->in.type) { ! 648: case FLOAT: ! 649: case DOUBLE: ! 650: /* lhs must be in d0/d1 */ ! 651: if (r->in.op == REG && r->tn.rval == D0) { ! 652: goto reverse; ! 653: } ! 654: break; ! 655: case CHAR: ! 656: case UCHAR: ! 657: /* bytes cannot be in address registers */ ! 658: if (l->in.op == REG && isbreg(l->tn.rval)) { ! 659: break; ! 660: } ! 661: /* fall through */ ! 662: default: ! 663: reverse: ! 664: if ( r->in.op == REG && isareg(r->tn.rval) ! 665: && !SUTEST(l->in.su) ) { ! 666: /* ! 667: * rhs is in a data register, lhs ! 668: * isn't, and doesn't have to be ! 669: */ ! 670: p->in.left = r; ! 671: p->in.right = l; ! 672: p->in.op = revrel[p->in.op - EQ]; ! 673: return(1); ! 674: } ! 675: } ! 676: order( l, cookie ); ! 677: } else { ! 678: /* ! 679: * if here, must be a logical operator for 0-1 value ! 680: * and we don't have 2 registers, as we would prefer ! 681: */ ! 682: int m; ! 683: cbranch( p, -1, m=getlab() ); ! 684: p->in.op = CCODES; ! 685: p->bn.label = m; ! 686: order( p, INTAREG ); ! 687: } ! 688: return( 1 ); ! 689: } ! 690: if ( !istnode( l ) ){ ! 691: if (commuteop(p->in.op) && istnode(r)) { ! 692: /* commutative op - put temp node on the left */ ! 693: p->in.right = l; ! 694: p->in.left = r; ! 695: } else { ! 696: order( l, cookie&(INTAREG|INTBREG) ); ! 697: return( 1 ); ! 698: } ! 699: } ! 700: if ( divmulop(p->in.op) && r->in.op == REG ! 701: && isbreg(r->tn.rval)) { ! 702: order( r, INAREG|INTAREG ); ! 703: return( 1 ); ! 704: } ! 705: /* rewrite */ ! 706: return( 0 ); ! 707: } ! 708: /* now, rhs is complicated */ ! 709: /* do the harder side first */ ! 710: /* be careful of D0, D1 usage */ ! 711: ! 712: if (SUGT(l->in.su, r->in.su)) { ! 713: /* lhs first; put into register */ ! 714: SAFETY(r, MUSTDO|D0, l); ! 715: order(l, cookie&(INTAREG|INTBREG)); ! 716: return( 1 ); ! 717: } ! 718: /* try to make rhs addressable */ ! 719: if(r->in.op == UNARY MUL) { ! 720: failsafe = find_mustdo( l, D0|MUSTDO) ; ! 721: if (l->in.su.d >= nfree(STAREG)) { ! 722: /* lhs needs all available d-registers; ! 723: do not use double indexing */ ! 724: failsafe |= 1; ! 725: } ! 726: offstar( r->in.left ); ! 727: return(1); ! 728: } ! 729: if (SUGT(r->in.su , l->in.su)){ ! 730: /* rhs first; put into register */ ! 731: SAFETY( l, MUSTDO|D0, r); ! 732: /* anything goes on rhs */ ! 733: order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); ! 734: return( 1 ); ! 735: } ! 736: if (!istnode(l)) { ! 737: SAFETY(r, MUSTDO|D0, l); ! 738: order(l, cookie&(INTAREG|INTBREG)); ! 739: return( 1 ); ! 740: } ! 741: if (!istnode(r)) { ! 742: SAFETY(l, MUSTDO|D0, r); ! 743: order(r, INTAREG|INAREG|INTBREG|INBREG|INTEMP); ! 744: return( 1 ); ! 745: } ! 746: /* rewrite */ ! 747: return( 0 ); ! 748: } ! 749: ! 750: setstr( p, cook ) register NODE *p; ! 751: { ! 752: /* structure assignment */ ! 753: if (p->in.right->in.op != REG){ ! 754: order( p->in.right, INTBREG ); ! 755: return(1); ! 756: } ! 757: p = p->in.left; ! 758: if ( p->in.op != NAME && p->in.op != OREG ){ ! 759: if ( p->in.op != UNARY MUL ) cerror( "bad setstr"); ! 760: order( p->in.left, INTBREG ); ! 761: return( 1 ); ! 762: } ! 763: if( p->in.op == OREG && !R2TEST(p->tn.rval) && istreg(p->tn.rval) ! 764: && p->tn.lval == 0){ ! 765: /* cheat -- rewrite this as a REG */ ! 766: p->in.op = REG; ! 767: return (1); ! 768: } ! 769: #ifdef FORT ! 770: /* Pascal does struct assignment of things that ain't structs!! */ ! 771: if (ISARY(p->in.type)){ ! 772: p->in.type = STRTY; ! 773: return(1); ! 774: } ! 775: #endif ! 776: return( 0 ); ! 777: } ! 778: ! 779: setasg( p , cookie ) ! 780: register NODE *p; ! 781: { ! 782: /* setup for assignment operator */ ! 783: register NODE *r, *l; ! 784: int failsave = failsafe; ! 785: ! 786: r = p->in.right; ! 787: l = p->in.left; ! 788: ! 789: if ( !SUGT( r->in.su , l->in.su )) goto do_lhs; ! 790: /* if ((p->in.type == DOUBLE || p->in.type == FLOAT) ! 791: /* && iscnode(p->in.right)){ ! 792: /* order( p->in.right, INAREG|SOREG|SNAME|SCON ); ! 793: /* return 1; ! 794: /* } ! 795: */ ! 796: if( SUTEST( r->in.su ) && r->in.op != REG ){ ! 797: failsafe |= SUTEST( l->in.su ); /* conservative guess */ ! 798: if( r->in.op == UNARY MUL ){ ! 799: offstar( r->in.left ); ! 800: }else{ ! 801: if (p->in.type == DOUBLE && r->in.type == FLOAT) ! 802: p->in.right = r = double_conv( r ); ! 803: if (!use68020 || !use68881) { ! 804: /* ! 805: * more goddamn complications from register parameters: ! 806: * if the lhs needs D0 for a multiply, for instance, ! 807: * then we must be careful not to ! 808: * evaluate the rhs into D0. ! 809: */ ! 810: SAFETY( l, MUSTDO|D0, r ); ! 811: } ! 812: order( r, INAREG|INBREG|INCREG|SOREG|SNAME|SCON ); ! 813: } ! 814: failsafe = failsave; ! 815: return(1); ! 816: } ! 817: do_lhs: ! 818: if( l->in.op == UNARY MUL ) ! 819: if (!tshape( l, STARREG|STARNM ) ! 820: || p->in.type == DOUBLE){ ! 821: /* sorry, we're too feeble to *P++ with double pointers */ ! 822: failsafe |= SUTEST( r->in.su ); /* conservative guess */ ! 823: failsafe |= r->tn.su.d >= fregs.d; ! 824: offstar( l->in.left ); ! 825: failsafe = failsave; ! 826: return(1); ! 827: } ! 828: if (l->in.op==FLD && l->in.left->in.op==UNARY MUL ){ ! 829: failsafe |= SUTEST( r->in.su ); /* conservative guess */ ! 830: offstar( l->in.left->in.left ); ! 831: failsafe = failsave; ! 832: return(1); ! 833: } ! 834: /* if things are really strange, get rhs into a register */ ! 835: if( r->in.op != REG ) { ! 836: order( r, INAREG|INBREG|INCREG ); ! 837: failsafe = failsave; ! 838: return( 1 ); ! 839: } ! 840: /* for fields, rhs must be in a data register */ ! 841: if( l->in.op == FLD && r->in.op == REG && isbreg(r->tn.rval) ) { ! 842: order( r, INAREG|INTAREG ); ! 843: failsafe = failsave; ! 844: return( 1 ); ! 845: } ! 846: return(0); ! 847: } ! 848: ! 849: find_mustdo( p, regname ) register NODE *p; ! 850: { ! 851: /* if there are any ops here that require use of reg regname, return ! 852: * 1 else return 0; ! 853: */ ! 854: redo: ! 855: if (p->in.rall == regname) return 1; ! 856: if (p->in.type == DOUBLE && p->in.rall == regname-1) return 1; ! 857: switch( optype(p->in.op) ){ ! 858: case LTYPE: return 0; ! 859: case BITYPE: ! 860: if (find_mustdo(p->in.right, regname)) return 1; ! 861: /* else fall through */ ! 862: } ! 863: p = p->in.left; ! 864: goto redo; /* go 'round again */ ! 865: } ! 866: ! 867: int ! 868: rewrite_rall( n, trybreg ) NODE *n; ! 869: { ! 870: register int i, reg; ! 871: register TWORD t = n->in.type; ! 872: ! 873: /* find a temporary home for n */ ! 874: reg = -1; ! 875: for( i = D2; i <= maxa; i++){ ! 876: if( istreg(i) && busy[i] == 0){ ! 877: if (t==DOUBLE && ((i&1) || !( istreg(i+1) && busy[i+1] == 0))) ! 878: continue; /* too bad */ ! 879: reg = i; break; ! 880: } ! 881: } ! 882: if (reg < 0 && trybreg && t!=CHAR && t!= UCHAR) { ! 883: /* we are DESPARATE! */ ! 884: for( i = minb; i <= maxb; i++){ ! 885: if( istreg(i) && busy[i] == 0){ ! 886: if (t==DOUBLE && ((i&1) || !( istreg(i+1) && busy[i+1] == 0))) ! 887: continue; /* too bad */ ! 888: reg = i; break; ! 889: } ! 890: } ! 891: } ! 892: if ( reg < 0 ) return 0; ! 893: n->in.rall = (MUSTDO | reg); ! 894: return 1; ! 895: } ! 896: ! 897: int ! 898: rewrite_b_rall( n, a0ok ) ! 899: NODE *n; ! 900: { ! 901: register int i, reg; ! 902: ! 903: /* find a temporary home for n in the b-registers */ ! 904: /* get out of the hair of a0/a1 */ ! 905: reg = -1; ! 906: for( i = minb+2; i <= maxb; i++){ ! 907: if( istreg(i) && busy[i] == 0){ ! 908: reg = i; break; ! 909: } ! 910: } ! 911: if (reg<0 && a0ok && busy[minb]==0) ! 912: reg = minb; ! 913: if ( reg < 0) return 0; /*failure*/ ! 914: n->in.rall = MUSTDO | reg; ! 915: /* if this is a prospective oreg -- keep going */ ! 916: if (n->in.op == PLUS || n->in.op == MINUS){ ! 917: n = n->in.left; ! 918: if (n->in.op != REG || !isareg( n->tn.rval ) ) ! 919: n->in.rall = MUSTDO | reg; ! 920: } ! 921: return 1; ! 922: } ! 923: ! 924: NODE * ! 925: hard_rew( p ) register NODE *p; ! 926: { ! 927: register NODE *lp, *p2; ! 928: register int i, reg; ! 929: /* do rewriting for non-reg lhs of hard op='s */ ! 930: ! 931: lp = p->in.left; ! 932: switch(lp->in.op){ ! 933: default: ! 934: return p; ! 935: case REG: ! 936: if(istreg(lp->tn.rval)) return p; ! 937: case NAME: ! 938: case OREG: ! 939: case UNARY MUL: ! 940: case FLD: ! 941: break; ! 942: } ! 943: ! 944: if (odebug){ ! 945: printf("hard_rew( %o ):\n", p); ! 946: fwalk( p, eprint, 0); ! 947: } ! 948: ! 949: if( lp->in.op == UNARY MUL ){ ! 950: NODE *llp = lp->in.left; ! 951: offstar( llp ); ! 952: if ( llp->in.op == PLUS && llp->in.right->in.op != ICON ) { ! 953: /* de-index */ ! 954: order(llp, INTBREG|INBREG); ! 955: } ! 956: } ! 957: if( lp->in.op == FLD && lp->in.left->in.op == UNARY MUL ){ ! 958: NODE *lllp = lp->in.left->in.left; ! 959: offstar( lllp ); ! 960: if ( lllp->in.op == PLUS && lllp->in.right->in.op != ICON ) { ! 961: /* de-index */ ! 962: order(lllp, INTBREG|INBREG); ! 963: } ! 964: } ! 965: if( lp->in.op == FLD ) lp = lp->in.left; ! 966: ! 967: /* mimic code from reader.c */ ! 968: p2 = tcopy( p ); ! 969: p->in.op = ASSIGN; ! 970: reclaim( p->in.right, RNULL, 0 ); ! 971: p->in.right = p2; ! 972: canon(p); ! 973: rallo( p, p->in.rall ); ! 974: lp = p2->in.left; ! 975: /* if we are doing a floating op, we'll let the caller finish it off */ ! 976: if(p->in.type == DOUBLE || p->in.type == FLOAT) ! 977: return p2; ! 978: /* if we must, rewrite rhs, too */ ! 979: if (SUGT( p2->in.right->in.su , lp->in.su )){ ! 980: SAFETY( lp, p2->in.right->in.rall, p2->in.right ); ! 981: order( p2->in.right, INTAREG|INTBREG ); ! 982: } ! 983: SAFETY( p2->in.right, lp->in.rall, lp ); ! 984: order( lp, INTBREG|INTAREG ); ! 985: ! 986: return p->in.right; ! 987: } ! 988: ! 989: setasop( p, cookie ) register NODE *p; ! 990: { ! 991: /* setup for =ops */ ! 992: register SUTYPE sul, sur; ! 993: register NODE *r, *l; ! 994: register NODE *q, *p2; ! 995: SUTYPE pcost; ! 996: ! 997: r = p->in.right; ! 998: l = p->in.left; ! 999: sul = l->in.su; ! 1000: sur = r->in.su; ! 1001: ! 1002: switch( p->in.op ){ ! 1003: case ASG PLUS: ! 1004: case ASG MINUS: ! 1005: case ASG OR: ! 1006: case ASG ER: ! 1007: case ASG AND: ! 1008: if (p->in.type == FLOAT || p->in.type == DOUBLE ) { ! 1009: floatops: ! 1010: /* ! 1011: * lhs in dreg or AWD, rhs in dreg or AWD. ! 1012: */ ! 1013: ! 1014: /* ! 1015: * if the lhs is not a temp node, then we need to let ! 1016: * a op= b ; be rewritten as... ! 1017: * a = (a) op= b; ! 1018: */ ! 1019: /* HOWEVER!: ! 1020: * if rhs is expensive, we gotta do it first! ! 1021: */ ! 1022: if (r->in.type==FLOAT && p->in.type==DOUBLE){ ! 1023: r = p->in.right = double_conv(r); ! 1024: } ! 1025: ! 1026: if (use68881) { ! 1027: /* ! 1028: * if lhs is already a coprocessor reg, all ! 1029: * we have to do is clean up the rhs a little. ! 1030: */ ! 1031: int rhs = 0; ! 1032: if (iscnode(l)) { ! 1033: floatsrce(r); ! 1034: return(1); ! 1035: } ! 1036: if ( SUGT(sur, sul) ) { ! 1037: /* rhs is hard -- do it first */ ! 1038: floatsrce(r); ! 1039: rhs = 1; ! 1040: } ! 1041: p = hard_rew(p); ! 1042: l = p->in.left; ! 1043: r = p->in.right; ! 1044: if ( istnode(r) && iscreg(r->tn.rval) ! 1045: && (p->in.op == ASG PLUS || p->in.op == ASG MUL) ) { ! 1046: /* ! 1047: * commute -- we can do this because hard_rew ! 1048: * assigns the result of p to the lhs ! 1049: */ ! 1050: p->in.left = r; ! 1051: p->in.right = l; ! 1052: l = r; ! 1053: r = p->in.right; ! 1054: rhs = 0; ! 1055: } else { ! 1056: /* ! 1057: * put lhs in a coprocessor reg ! 1058: */ ! 1059: order(l, INCREG|INTCREG); ! 1060: } ! 1061: /* ! 1062: * if rhs hasn't been dealt with yet, do it ! 1063: */ ! 1064: if (!rhs) { ! 1065: floatsrce(r); ! 1066: } ! 1067: return(1); ! 1068: } /* use68881 */ ! 1069: ! 1070: if (usesky){ ! 1071: /* ! 1072: * check for pivot operation ( x += y * z ) ! 1073: * only do if one of x,y,z is free ! 1074: */ ! 1075: int pivoting = 0; ! 1076: if (p->in.op == ASG PLUS && r->in.op == MUL) { ! 1077: if (!SUTEST(sul)) { ! 1078: setbin(r, INTAREG|INAREG|INTEMP); ! 1079: return(1); ! 1080: } ! 1081: if (!SUTEST(r->in.left->in.su) ! 1082: || !SUTEST(r->in.right->in.su)) { ! 1083: pivoting = 1; ! 1084: } ! 1085: } ! 1086: /* ! 1087: * on the sky board, "op=" ops can be done ! 1088: * with lhs in memory. However, we must stay ! 1089: * away from a0/a1. ! 1090: */ ! 1091: if (SUGT(sur,sul)){ ! 1092: /* must do rhs first */ ! 1093: if (pivoting) { ! 1094: if (SUTEST(r->in.left->in.su)) { ! 1095: r = r->in.left; ! 1096: } else { ! 1097: r = r->in.right; ! 1098: } ! 1099: pivoting = 0; ! 1100: } ! 1101: if (r->in.op == UNARY MUL ! 1102: && rewrite_b_rall(r->in.left, 0)) { ! 1103: /* make addressable, avoiding a1 */ ! 1104: offstar(r->in.left); ! 1105: } else if (!find_mustdo(l, MUSTDO|D0) ! 1106: || rewrite_rall(r, 0)) { ! 1107: order(r, INAREG|INTAREG|INTEMP); ! 1108: } else { ! 1109: order(r, INTEMP); ! 1110: } ! 1111: r->in.su = zed; ! 1112: } ! 1113: /* ! 1114: * deal with lhs ! 1115: */ ! 1116: if (SUTEST(sul)) { ! 1117: if (l->in.op == UNARY MUL ! 1118: && rewrite_b_rall( l->in.left, 0 )) { ! 1119: /* make addressable, avoiding a1 */ ! 1120: offstar( l->in.left ); ! 1121: } else { ! 1122: /* failing that, try rewriting */ ! 1123: p = hard_rew(p); ! 1124: l = p->in.left; ! 1125: r = p->in.right; ! 1126: if (pivoting) { ! 1127: if (SUTEST(r->in.left->in.su)) { ! 1128: r = r->in.left; ! 1129: } else { ! 1130: r = r->in.right; ! 1131: } ! 1132: pivoting = 0; ! 1133: } ! 1134: if (!find_mustdo(r, MUSTDO|D0) ! 1135: || rewrite_rall(l, 0)) { ! 1136: order(l, INAREG|INTAREG|INTEMP); ! 1137: } else { ! 1138: order(l, INTEMP); ! 1139: } ! 1140: } ! 1141: } ! 1142: /* ! 1143: * deal with rhs, if necessary ! 1144: */ ! 1145: if (pivoting) { ! 1146: if (SUTEST(r->in.left->in.su)) { ! 1147: r = r->in.left; ! 1148: } else { ! 1149: r = r->in.right; ! 1150: } ! 1151: } ! 1152: if (SUTEST(r->in.su)){ ! 1153: if (r->in.op == UNARY MUL ! 1154: && rewrite_b_rall(r->in.left, 0)) { ! 1155: /* make addressable, avoiding a1 */ ! 1156: offstar(r->in.left); ! 1157: } else { ! 1158: order(r, INAREG|INTAREG|INTEMP); ! 1159: } ! 1160: } ! 1161: return 1; ! 1162: } else if ( !istnode(l) ){ ! 1163: if (SUTEST( sur )){ ! 1164: if (!SUTEST(sul) && r->in.type == FLOAT){ ! 1165: r->in.rall = MUSTDO|D1; ! 1166: order( r, INAREG ); ! 1167: } else { ! 1168: /* may not want it in a register, ! 1169: in case lhs needs the register */ ! 1170: if (rewrite_rall(r, 0)){ ! 1171: order( r, INAREG|INTAREG|INBREG|INTBREG|INCREG|INTCREG ); ! 1172: } else { ! 1173: r->in.rall = NOPREF; ! 1174: order( r, INTEMP ); ! 1175: } ! 1176: } ! 1177: } ! 1178: /* lhs is either easy or is an address */ ! 1179: /* ! 1180: * if its an address, we must, unhappily, ! 1181: * evaluate it AWAY from a0/a1, which will ! 1182: * be clobbered by the operation. ! 1183: */ ! 1184: if (l->in.op == UNARY MUL && l->in.left->in.op != REG){ ! 1185: failsafe = 1; /* keep away from d0/d1!! */ ! 1186: if ( rewrite_b_rall( l->in.left, 0 ) ) ! 1187: offstar( l->in.left ); ! 1188: else ! 1189: order( l->in.left, INTEMP ); ! 1190: } else ! 1191: l->in.rall = MUSTDO|D0; ! 1192: /* p->in.op = NOASG p->in.op; */ ! 1193: goto rew_lhs; ! 1194: } ! 1195: ! 1196: if (r->in.type == DOUBLE ){ ! 1197: if ( !tshape( r, SNAME|SOREG|STARNM)){ ! 1198: r->in.rall = NOPREF; ! 1199: order( r, INTEMP ); ! 1200: } ! 1201: } else { ! 1202: if( !(istnode(r) && r->tn.rval == D1) ){ ! 1203: r->in.rall = MUSTDO|D1; ! 1204: order( r, INTAREG); ! 1205: } ! 1206: } ! 1207: if ( !(istnode(l) && l->tn.rval == D0) ){ ! 1208: l->in.rall = MUSTDO|D0; ! 1209: order( l, INTAREG); ! 1210: } ! 1211: ! 1212: return 1; ! 1213: } else if (ISPTR(p->in.type) ! 1214: && (p->in.op==ASG PLUS || p->in.op==ASG MINUS) ! 1215: && isconv(r, SHORT, -1) ! 1216: && l->in.op== REG && isbreg(l->tn.rval)) { ! 1217: p->in.right = r->in.left; ! 1218: r->in.op = FREE; ! 1219: return 1; ! 1220: } else { ! 1221: if ((p->in.right->in.op != REG || ! 1222: isbreg(p->in.right->tn.rval)) && !SUTEST( sul )) { ! 1223: order(p->in.right,INAREG|INTAREG); ! 1224: return(1); ! 1225: } else break; ! 1226: } ! 1227: ! 1228: case ASG MUL: ! 1229: case ASG DIV: ! 1230: case ASG MOD: ! 1231: /* ! 1232: * This is difficult: These ops require the lhs in d0 and the ! 1233: * rhs in d1. This means that whichever side gets evaluated ! 1234: * first will monopolize one of these strategic registers for ! 1235: * the whole time the other side is being evaluated. This is ! 1236: * not acceptable if the less-expensive side ALSO requires ! 1237: * evaluation of one of these constrained ops. So we must be ! 1238: * very careful here. First, we assume that there are, indeed, ! 1239: * enough registers for us to play with, otherwise off-storing ! 1240: * should already have been taken care of by the wonders of ! 1241: * portable code generation. So what we'll do is find a free ! 1242: * register NOT in the set {d0,d1}, and force evaluation of the ! 1243: * more expensive side into that register, then rewrite the ! 1244: * requirements for that side. Hold on. ! 1245: */ ! 1246: ! 1247: if (p->in.type == FLOAT || p->in.type == DOUBLE) ! 1248: goto floatops; ! 1249: if( p->in.type != INT && p->in.type != UNSIGNED && !ISPTR(p->in.type)) ! 1250: break; ! 1251: if(use68020) ! 1252: break; ! 1253: ! 1254: /* we can only do these into d0 */ ! 1255: d0_d1: ! 1256: /* if things already look optimum, we must already have been this way once */ ! 1257: if (istnode(p->in.left) && !SUTEST( p->in.right->tn.su )){ ! 1258: order( p->in.right, INTAREG ); ! 1259: return 1; ! 1260: } ! 1261: p = hard_rew( p ); ! 1262: sul = p->in.left->in.su; ! 1263: /* use q to designate the more expensive side, p2 the cheaper */ ! 1264: if ( !SUGT( sur, sul )){ q = p->in.left; p2 = p->in.right; pcost = sur; } ! 1265: else { q = p->in.right; p2 = p->in.left; pcost = sul; } ! 1266: if( SUTEST( sul ) && SUTEST( sur )){ ! 1267: SAFETY( p2, q->in.rall, q ); ! 1268: } ! 1269: ! 1270: /* do code emission, most expensive side first */ ! 1271: if (!istnode( q ) ){ ! 1272: order( q, INAREG|INTAREG); ! 1273: } ! 1274: if ( SUTEST( pcost ) && !istnode( p2 )){ ! 1275: order( p2 ,INAREG|INTAREG); ! 1276: } ! 1277: if ( !istnode( p->in.left ) || p->in.left->tn.rval != D0 ){ ! 1278: p->in.left->tn.rall = MUSTDO | D0; ! 1279: order( p->in.left, INTAREG ); ! 1280: } ! 1281: if ( SUTEST(sur) &&(!istnode(p->in.right)||p->in.right->tn.rval!=D1)){ ! 1282: p->in.right->tn.rall = MUSTDO | D0; ! 1283: order( p->in.right, INTAREG ); ! 1284: } ! 1285: ! 1286: return(1); ! 1287: ! 1288: case ASG LS: ! 1289: case ASG RS: ! 1290: if (l->in.op != REG){ ! 1291: /* must rewrite as lhs = ((lhs) op= rhs) */ ! 1292: /* if we must, rewrite rhs, too */ ! 1293: if (SUGT( sur , sul)){ ! 1294: SAFETY( l, MUSTDO|D0, r ); ! 1295: order( r, INAREG|INBREG ); ! 1296: } ! 1297: /* lhs is either easy or is an address */ ! 1298: if (SUTEST( sul )){ ! 1299: if (l->in.op == UNARY MUL) ! 1300: offstar( l->in.left ); ! 1301: else if (l->in.op == FLD && ! 1302: l->in.left->in.op == UNARY MUL) ! 1303: offstar( l->in.left->in.left); ! 1304: } ! 1305: goto rew_lhs; ! 1306: } ! 1307: if (r->in.op == REG && isareg(r->tn.rval) ! 1308: || (r->in.op==ICON && r->tn.lval>=1 && r->tn.lval<=8)) ! 1309: break; ! 1310: order(r,INAREG|INTAREG); ! 1311: return(1); ! 1312: ! 1313: } ! 1314: ! 1315: /* ! 1316: * What we have here is an asop which could POSSIBLY be done to memory ! 1317: * if we desire it. Luckily we have the cookie as a parameter to make ! 1318: * this decision. If we do it to memory, then we just want to evaluate ! 1319: * the lhs to an address. If we do it for a value, we have to evaluate ! 1320: * the lhs for a value, then store afterwards. ! 1321: */ ! 1322: if (SUTEST( sul ) && !SUGT( sur,sul )){ ! 1323: /* since an lhs can only be an address ... */ ! 1324: if (l->in.op == UNARY MUL){ ! 1325: failsafe |= SUTEST( sur ); /* conservative guess */ ! 1326: offstar( l->in.left ); ! 1327: } else if (l->in.op == FLD){ ! 1328: if (l->in.left->in.op == UNARY MUL) ! 1329: offstar( l->in.left->in.left); ! 1330: return 0; /* rewrite as something sane */ ! 1331: } ! 1332: if (cookie&FOREFF){ ! 1333: /* for effect only! */ ! 1334: return 1; ! 1335: } ! 1336: /* otherwise, rewrite as (lhs1) = ((lhs2) op= rhs) */ ! 1337: rew_lhs: ! 1338: ncopy( p2=talloc(), p); ! 1339: p->in.op = ASSIGN; ! 1340: p->in.right = p2; ! 1341: l = p->in.left = tcopy( p2->in.left ); ! 1342: SAFETY( p2->in.right, MUSTDO|D0, p2->in.left ); ! 1343: if (l->in.op == UNARY MUL && shumul(l->in.left) == STARREG) { ! 1344: /* ! 1345: * Beware side effects lurking in lhs. We now ! 1346: * have two copies -- side effects of one copy must ! 1347: * be eliminated. Note that (lhs2) will be evaluated first. ! 1348: */ ! 1349: if (l->in.left->in.op == ASG MINUS) { ! 1350: /* predecrement -- keep side effect in (lhs2), ! 1351: delete side effect in (lhs1) */ ! 1352: q = l->in.left; ! 1353: } else { ! 1354: /* postincrement -- keep side effect in (lhs1), ! 1355: delete side effect in (lhs2) */ ! 1356: q = p2->in.left->in.left; ! 1357: } ! 1358: l = q->in.left; /* = REG */ ! 1359: r = q->in.right; /* = ICON */ ! 1360: *q = *l; ! 1361: l->in.op = FREE; ! 1362: r->in.op = FREE; ! 1363: } ! 1364: order( p2->in.left, INAREG|INBREG ); ! 1365: return 1; ! 1366: } ! 1367: if( SUTEST( sur )){ ! 1368: /* evaluate rhs into a register, then go try again */ ! 1369: SAFETY( l, MUSTDO|D0, r ); ! 1370: order( r, INAREG|INBREG ); ! 1371: return 1; ! 1372: } ! 1373: if (divmulop(p->in.op) && r->in.op == REG && isbreg(r->tn.rval)) { ! 1374: order(r, INAREG|INTAREG); ! 1375: return(1); ! 1376: } ! 1377: if (l->in.op == UNARY MUL && shumul(l->in.left) == STARREG) { ! 1378: goto rew_lhs; ! 1379: } ! 1380: return 0; ! 1381: } ! 1382: ! 1383: /* ! 1384: * returns number of free registers of a given type. This wouldn't ! 1385: * be necessary if the SU-numbers were strictly followed; however, ! 1386: * double indexing ties up more registers than sucomp assumes, and ! 1387: * should not be attempted unless a spare register exists. ! 1388: */ ! 1389: int ! 1390: nfree(cookie) ! 1391: { ! 1392: register r; ! 1393: register n; ! 1394: n = 0; ! 1395: for (r = 0; r < REGSZ; r++) { ! 1396: if ((rstatus[r]&cookie) && !busy[r]) ! 1397: n++; ! 1398: } ! 1399: return n; ! 1400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.