|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)su.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: # include "cpass2.h" ! 10: ! 11: /* ! 12: * from order.c ! 13: */ ! 14: ! 15: ! 16: extern int mina, maxa, minb, maxb; /* imported from allo.c */ ! 17: int failsafe; ! 18: extern toff, maxtoff; ! 19: ! 20: # define iscnode(p) (p->in.op==REG && iscreg(p->tn.rval)) ! 21: ! 22: # define max(x,y) ((x)<(y)?(y):(x)) ! 23: # define min(x,y) ((x)<(y)?(x):(y)) ! 24: ! 25: ! 26: sucomp( p ) register NODE *p; ! 27: { ! 28: ! 29: /* set the su field in the node to the sethi-ullman ! 30: number, or local equivalent */ ! 31: ! 32: register o, t; ! 33: register nr; ! 34: register u, tt; ! 35: register NODE *r, *l; ! 36: SUTYPE sul, sur; ! 37: SUTYPE tempsu; ! 38: static SUTYPE zed = { 0,0,0,0 }; ! 39: ! 40: p->in.su = zed; ! 41: switch(t = optype( o=p->in.op)) { ! 42: case LTYPE: ! 43: return; ! 44: case UTYPE: ! 45: sucomp(p->in.left); ! 46: break; ! 47: case BITYPE: ! 48: sucomp(p->in.left); ! 49: sucomp(p->in.right); ! 50: r = p->in.right; ! 51: sur = r->in.su ; ! 52: break; ! 53: } ! 54: l = p->in.left; ! 55: sul = l->in.su; ! 56: nr = szty( tt = p->in.type ); ! 57: ! 58: switch ( o ){ ! 59: case ASG ER: ! 60: /* exclusive-or -- not generally computable to-memory */ ! 61: if ( r->tn.op != ICON ) goto reg_reg_asg; ! 62: /* fall through */ ! 63: ! 64: case ASG PLUS: ! 65: case ASG MINUS: ! 66: case ASG AND: ! 67: case ASG OR: ! 68: /* these may be done directly at memory -- looks like = */ ! 69: if ( tt == FLOAT || tt == DOUBLE ) { ! 70: goto float_asop; ! 71: } ! 72: /* fall through */ ! 73: ! 74: case ASSIGN: ! 75: /* usually, compute rhs into a register, compute lhs, store */ ! 76: /* could do it backwards if lhs is hairier */ ! 77: if (SUSUM( sur ) > SUSUM( sul )){ ! 78: /* p->in.su = max( sur, sul+nr); */ ! 79: sur.d = max( sur.d, sul.d+nr ); ! 80: sur.a = max( sur.a, sul.a ); ! 81: }else{ ! 82: /* p->in.su = max( sur+1, sul); */ ! 83: if(l->in.op == FLD) { ! 84: sur.d = max(max(sur.d, sul.d),2); ! 85: } else { ! 86: sur.d = max(sur.d, sul.d); ! 87: } ! 88: sur.a = max( sur.a+1, sul.a); ! 89: } ! 90: sur.f = max( sur.f, sul.f); ! 91: p->in.su = sur; ! 92: return; ! 93: ! 94: case STASG: ! 95: /* compute two addresses, then use up to three more registrers */ ! 96: /* p->in.su = max( 3, 1+max(sul,sur)); */ ! 97: sur.d = 1+max( sur.d, sul.d ); ! 98: t = max( sur.a, sul.a ); ! 99: sur.a = max( 2, t ); ! 100: p->in.su = sur; ! 101: return; ! 102: ! 103: case UNARY MUL: ! 104: if (shumul(p->in.left)) ! 105: return; ! 106: /* most other unary ops handled in default case */ ! 107: sul.a = max( sul.a, 1); /* 1 address register to * through */ ! 108: p->in.su = sul; ! 109: return; ! 110: ! 111: case CALL: ! 112: case UNARY CALL: ! 113: case STCALL: ! 114: case UNARY STCALL: ! 115: p->in.su = fregs; ! 116: return; ! 117: ! 118: case ASG RS: ! 119: case ASG LS: ! 120: /* if the rhs is not a small contant, this is a reg-reg op */ ! 121: if ( r->tn.op == ICON && r->tn.lval >0 && r->tn.lval <= 8 ){ ! 122: /* looks like a unary op */ ! 123: sul.d += nr; ! 124: p->in.su = sul; ! 125: return; ! 126: } ! 127: /* fall through */ ! 128: case ASG MUL: ! 129: case ASG DIV: ! 130: case ASG MOD: ! 131: /* compute rhs, compute lhs (or vice versa), get lhs value, op */ ! 132: if ( tt == FLOAT || tt == DOUBLE ) { ! 133: goto float_asop; ! 134: } ! 135: reg_reg_asg: ! 136: t = SUSUM(sul)?1:0; /* number regs needed to store lhs address */ ! 137: /* want at least 2 regs + lhs address */ ! 138: /* if lhs is complicated, will always compute it into a reg FIRST */ ! 139: /* p->in.su = max( t+2*nr, min(t+sur, nr+sul)); */ ! 140: /* if (sul) ! 141: /* u = max( sul, t+sur ); ! 142: /* else ! 143: /* u = sur; ! 144: /* p->in.su = max( u, t+2*nr); ! 145: */ ! 146: if (SUSUM(sul)){ ! 147: sur.d = max( sur.d, sul.d ); ! 148: sur.a = max( sur.a+t, sul.a ); ! 149: } ! 150: sur.d = max( sur.d , 2*nr ); ! 151: sur.a = max( sur.a , t ); ! 152: sur.f = 0; ! 153: p->in.su = sur; ! 154: return; ! 155: ! 156: case PLUS: ! 157: case AND: ! 158: case OR: ! 159: case ER: ! 160: /* commutable memory-register ops */ ! 161: if ( tt == FLOAT || tt == DOUBLE ) { ! 162: goto float_asop; ! 163: } ! 164: if (l->in.op != REG && SUSUM(sul) < SUSUM(sur)){ ! 165: p->in.right = l; ! 166: p->in.left = r; ! 167: l = r; ! 168: r = p->in.right; ! 169: sul = sur; ! 170: sur = r->in.su ; ! 171: } ! 172: goto reg_mem_op; ! 173: ! 174: case EQ: ! 175: case NE: ! 176: case LE: ! 177: case GE: ! 178: case GT: ! 179: case LT: ! 180: case UGT: ! 181: case UGE: ! 182: case ULT: ! 183: case ULE: ! 184: tt = l->in.type; ! 185: nr = szty( tt ); ! 186: /* fall through */ ! 187: case MINUS: ! 188: case INCR: ! 189: case DECR: ! 190: if ( tt == FLOAT || tt == DOUBLE ) { ! 191: float_asop: ! 192: if (use68881) { ! 193: nr = 1; ! 194: if (!SUTEST(sur) ! 195: && (r->in.op != REG || !isbreg(r->tn.rval))){ ! 196: /* rhs is cheap */ ! 197: sul.f = max( sul.f, nr ); ! 198: p->in.su = sul; ! 199: return; ! 200: } ! 201: /* compute rhs, lhs (or vice versa) do op */ ! 202: if (SUGT(sur, sul)){ ! 203: /* ! 204: * value of rhs, value of lhs, ! 205: * reg-reg op ! 206: */ ! 207: /* p->in.su = max( sur, sul+nr ); */ ! 208: if (commuteop(o) && !SUTEST(sul) ! 209: && (l->in.op != REG || !isbreg(l->tn.rval))){ ! 210: u = max( sul.f, nr ); ! 211: } else { ! 212: u = nr + max( sul.f, nr ); ! 213: } ! 214: sur.d = max( sur.d, sul.d ); ! 215: sur.a = max( sur.a, sul.a ); ! 216: sur.f = max( sur.f, u ); ! 217: } else { ! 218: /* p->in.su = max( sul, sur+1 ); */ ! 219: if (r->in.op == UNARY MUL){ ! 220: /* ! 221: * address of rhs, value of lhs, ! 222: * op from memory ! 223: */ ! 224: sur.d = max( sur.d, sul.d ); ! 225: sur.a = max( sur.a, sul.a+1 ); ! 226: sur.f = max( sul.f, sur.f+1 ); ! 227: } else { ! 228: /* ! 229: * value of lhs, value of rhs, ! 230: * reg-reg-op ! 231: */ ! 232: sur.d = max( sul.d, sur.d ); ! 233: sur.a = max( sul.a, sur.a ); ! 234: sur.f = max( sul.f+1, sur.f+1 ); ! 235: } ! 236: } ! 237: p->in.su = sur; ! 238: return; ! 239: } ! 240: /* ! 241: * floating operations are calls. ! 242: * They always take ALL the registers. ! 243: * SIMPLE FIRST APPROXIMATION HERE. ! 244: * evaluate rhs first: if lhs ! 245: * costs, then may need an extra temp. ! 246: */ ! 247: if (SUTEST(sur) && SUTEST(sul) ) ! 248: u = max( sur.d, sul.d+nr); ! 249: else ! 250: u = max( sur.d, sul.d ); ! 251: tempsu.d = max( u, fregs.d ); ! 252: ! 253: u = max( sur.a, sul.a ); ! 254: tempsu.a = max( u, fregs.a ); ! 255: tempsu.f = 0; ! 256: p->in.su = tempsu; ! 257: return; ! 258: } ! 259: reg_mem_op: ! 260: /* memory-register ops */ ! 261: ! 262: /* ! 263: * if rhs is direct, then the op is very cheap. ! 264: * But if rhs is an address register, only integer ! 265: * addition and subtraction are cheap. ! 266: */ ! 267: if (SUSUM(sur) == 0) { ! 268: int cheap = 1; ! 269: if (r->in.op == REG && isbreg(r->tn.rval)) { ! 270: switch(o) { ! 271: case PLUS: ! 272: case MINUS: ! 273: case ASG PLUS: ! 274: case ASG MINUS: ! 275: if (tt == CHAR || tt == UCHAR) { ! 276: /* can't use addr regs in byte adds and subs */ ! 277: cheap = 0; ! 278: } ! 279: break; ! 280: default: ! 281: /* can't use addr regs for other ops, period */ ! 282: cheap = 0; ! 283: break; ! 284: } ! 285: } ! 286: if (cheap) { ! 287: sul.d = max(sul.d, nr); ! 288: p->in.su = sul; ! 289: return; ! 290: } ! 291: } ! 292: /* else must compute rhs, lhs (or vice versa) do op */ ! 293: if (SUGT(sul, sur)) { ! 294: /* lhs, rhs, reg-reg op */ ! 295: /* p->in.su = max( sul, sur+nr ); */ ! 296: u = nr + max( sur.d , nr ); ! 297: sur.d = max( sul.d, u ); ! 298: sur.a = max( sur.a, sul.a ); ! 299: } else { ! 300: /* p->in.su = max( sul, sur+1 ); */ ! 301: if (r->in.op == UNARY MUL){ ! 302: /* address of rhs, value of lhs, op from memory */ ! 303: sur.d = max( sur.d, sul.d ); ! 304: sur.a = max( sur.a, sul.a+1 ); ! 305: } else if (SUGT(sur,sul)) { ! 306: /* value of rhs, value of lhs, reg-reg-op */ ! 307: sur.d = max( sur.d, sul.d+nr ); ! 308: sur.a = max( sur.a, sul.a ); ! 309: } else { ! 310: /* value of lhs, value of rhs, reg-reg-op */ ! 311: sur.d = max( sul.d, sur.d+nr ); ! 312: sur.a = max( sul.a, sur.a ); ! 313: } ! 314: } ! 315: sur.f = 0; ! 316: p->in.su = sur; ! 317: /* is there an easier way to do this? */ ! 318: return; ! 319: ! 320: case RS: ! 321: case LS: ! 322: /* looks like a unary op if rhs is small */ ! 323: if ( r->tn.op == ICON && r->tn.lval >0 && r->tn.lval <= 8 ){ ! 324: /* looks like a unary op */ ! 325: sul.d = max( sul.d, nr); ! 326: p->in.su = sul; ! 327: return; ! 328: } ! 329: /* fall through */ ! 330: case MUL: ! 331: case DIV: ! 332: case MOD: ! 333: if ( tt == FLOAT || tt == DOUBLE ) { ! 334: goto float_asop; ! 335: } ! 336: reg_reg_op: ! 337: /* register-register ops */ ! 338: /* must do one and then the other */ ! 339: /* commutability not an issue here */ ! 340: /* need at least two register sets */ ! 341: if ( SUGT( sul, sur ) ){ ! 342: t = max( sul.d, sur.d+nr ); ! 343: } else { ! 344: t = max( sul.d+nr, sur.d ); ! 345: } ! 346: sul.d = max( 2*nr, t); ! 347: sul.a = max( sul.a, sur.a ); ! 348: sul.f = max( sul.f, sur.f ); ! 349: p->in.su = sul; ! 350: return; ! 351: ! 352: case NAME: ! 353: case REG: ! 354: case OREG: ! 355: case ICON: ! 356: case FCON: ! 357: return; /* su is zero */ ! 358: ! 359: case SCONV: ! 360: if (!ezsconv(p)){ ! 361: sul.d = max( sul.d, fregs.d); ! 362: sul.a = max( sul.a, fregs.a); ! 363: } else if (use68881 ! 364: && (ISFLOATING(tt) || ISFLOATING(l->in.type))) { ! 365: sul.f = max( sul.f, 1 ); ! 366: sul.d = max( sul.d, 1 ); ! 367: } else { ! 368: sul.d = max( sul.d, nr); /* normal unary */ ! 369: } ! 370: p->in.su = sul; ! 371: break; ! 372: ! 373: case FAINT: ! 374: case FANINT: ! 375: case FNINT: ! 376: /* float=>integer conversion */ ! 377: if (use68881) { ! 378: sul.d = max(sul.d, 1); ! 379: sul.f = max(sul.f, 1); ! 380: } else { ! 381: /* must do subroutine call */ ! 382: sul.d = max(sul.d, fregs.d); ! 383: sul.a = max(sul.a, fregs.a); ! 384: } ! 385: p->in.su = sul; ! 386: break; ! 387: ! 388: case CHK: ! 389: /* ! 390: * this is actually a ternary operation: ! 391: * the expression to be checked, ! 392: * the lower bound, ! 393: * the upper bound. ! 394: * if the upper and lower bounds are constant, then ! 395: * cost is the cost of the expression, which must ! 396: * always be evaluated into a data register. We ! 397: * may have to evaluate the bounds, too, and this ! 398: * costs more. ! 399: * we will try to use the 68010's chk instruction. ! 400: * failing that, we will use the 68020's chk2 instruction. ! 401: * lacking that, use compare-and-branch code. ! 402: */ ! 403: if (chk_ovfl){ ! 404: /* ! 405: * assume we have to evaluate each of the bounds & ! 406: * at the same time hold the expression. ! 407: */ ! 408: sur.d = max( r->in.left->in.su.d, r->in.right->in.su.d); ! 409: sur.a = max( r->in.left->in.su.a, r->in.right->in.su.a); ! 410: sur.f = max( r->in.left->in.su.f, r->in.right->in.su.f); ! 411: p->in.su.d = max( sul.d, nr+sur.d ); ! 412: p->in.su.a = max( sul.a, sur.a ); ! 413: p->in.su.f = max( sul.f, sur.f ); ! 414: } else { ! 415: p->in.su = sul; ! 416: } ! 417: break; ! 418: ! 419: default: ! 420: if ( t == BITYPE ){ ! 421: /* random binary operators */ ! 422: /* choose largest */ ! 423: t = max( sur.d, sul.d ); ! 424: sur.d = max( t, nr ); ! 425: sur.a = max( sur.a, sul.a ); ! 426: sur.f = max( sur.f, sul.f ); ! 427: p->in.su = sur; ! 428: return; ! 429: } ! 430: /* must be unary */ ! 431: if (dope[o]&INTRFLG) { ! 432: /* fortran intrinsics */ ! 433: if (use68881) { ! 434: sul.f = max(sul.f, 1); ! 435: } else { ! 436: /* must do subroutine call */ ! 437: sul.d = max(sul.d, fregs.d); ! 438: sul.a = max(sul.a, fregs.a); ! 439: } ! 440: } else { ! 441: /* random unary op */ ! 442: sul.d = max( sul.d, nr); ! 443: if (use68881 && ISFLOATING(tt)) { ! 444: sul.f = max( sul.f, 1 ); ! 445: } ! 446: } ! 447: p->in.su = sul; ! 448: } ! 449: } ! 450: ! 451: int radebug = 0; ! 452: ! 453: mkrall( p, r ) register NODE *p; ! 454: { ! 455: /* insure that the use of p gets done with register r; in effect, */ ! 456: /* simulate offstar */ ! 457: ! 458: if( p->in.op == FLD ){ ! 459: p->in.left->in.rall = p->in.rall; ! 460: p = p->in.left; ! 461: } ! 462: ! 463: if( p->in.op != UNARY MUL ) return; /* no more to do */ ! 464: p = p->in.left; ! 465: if( p->in.op == UNARY MUL ){ ! 466: p->in.rall = r; ! 467: p = p->in.left; ! 468: } ! 469: if( p->in.op == PLUS && p->in.right->in.op == ICON ){ ! 470: p->in.rall = r; ! 471: p = p->in.left; ! 472: } ! 473: rallo( p, r ); ! 474: } ! 475: ! 476: rallo( p, down ) NODE *p; ! 477: { ! 478: /* do register allocation */ ! 479: register o, type, down1, down2, ty; ! 480: NODE *p2; ! 481: ! 482: again: ! 483: if( radebug ) printf( "rallo( %o, %d )\n", p, down ); ! 484: ! 485: down2 = NOPREF; ! 486: p->in.rall = down; ! 487: down1 = ( down &= ~MUSTDO ); ! 488: ! 489: ty = optype( o = p->in.op ); ! 490: type = p->in.type; ! 491: ! 492: ! 493: switch( o ) { ! 494: case UNARY MUL: ! 495: down1 = NOPREF; ! 496: break; ! 497: ! 498: case ASSIGN: ! 499: down1 = NOPREF; ! 500: down2 = down; ! 501: break; ! 502: ! 503: case ASG MUL: ! 504: case ASG DIV: ! 505: case ASG MOD: ! 506: ! 507: case MUL: ! 508: case DIV: ! 509: case MOD: ! 510: switch(type){ ! 511: case FLOAT: ! 512: if (use68881 || usesky) break; ! 513: down1 = D0|MUSTDO; ! 514: down2 = D1|MUSTDO; ! 515: break; ! 516: case INT: ! 517: case UNSIGNED: ! 518: if (use68020) break; ! 519: down1 = D0|MUSTDO; ! 520: down2 = D1|MUSTDO; ! 521: break; ! 522: case DOUBLE: ! 523: if (use68881 || usesky) break; ! 524: down1 = D0|MUSTDO; ! 525: break; ! 526: default: ! 527: if (ISPTR(type)){ ! 528: /* this is the result of (char *)(a*b) */ ! 529: /* treat as an unsigned or int */ ! 530: if (use68020) break; ! 531: down1 = D0|MUSTDO; ! 532: down2 = D1|MUSTDO; ! 533: } ! 534: break; ! 535: } ! 536: break; ! 537: ! 538: case EQ: ! 539: case NE: ! 540: case GT: ! 541: case GE: ! 542: case LT: ! 543: case LE: ! 544: type = p->in.left->in.type; ! 545: /* fall through */ ! 546: case PLUS: ! 547: case MINUS: ! 548: case ASG PLUS: ! 549: case ASG MINUS: ! 550: if (use68881 || usesky) break; ! 551: switch (type){ ! 552: case FLOAT: ! 553: down1 = D0|MUSTDO; ! 554: down2 = D1|MUSTDO; ! 555: break; ! 556: case DOUBLE: ! 557: down1 = D0|MUSTDO; ! 558: break; ! 559: } ! 560: break; ! 561: ! 562: case NOT: ! 563: case ANDAND: ! 564: case OROR: ! 565: down1 = NOPREF; ! 566: break; ! 567: ! 568: case SCONV: /* float, fix, single, or double */ ! 569: if (use68881 || usesky) break; ! 570: if (ezsconv(p)) break; ! 571: down1 = D0|MUSTDO; ! 572: break; ! 573: ! 574: case FORCE: ! 575: down1 = D0|MUSTDO; ! 576: break; ! 577: ! 578: case FNINT: /* float=>int conversion, use biased rounding */ ! 579: if (use68881) break; ! 580: down1 = D0|MUSTDO; ! 581: break; ! 582: ! 583: default: ! 584: if ((dope[o]&INTRFLG) && !use68881) { ! 585: /* fortran intrinsics */ ! 586: down1 = D0|MUSTDO; ! 587: } ! 588: } ! 589: ! 590: recur: ! 591: if( ty == BITYPE ) rallo( p->in.right, down2 ); ! 592: else if( ty == LTYPE ) return; ! 593: /* else do tail-recursion */ ! 594: p = p->in.left; ! 595: down = down1; ! 596: goto again; ! 597: ! 598: } ! 599: ! 600: stoasg( p, o ) register NODE *p; ! 601: { ! 602: /* should the assignment op p be stored, ! 603: given that it lies as the right operand of o ! 604: (or the left, if o==UNARY MUL) */ ! 605: /* ! 606: if( p->in.op == INCR || p->in.op == DECR ) return; ! 607: if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG); ! 608: */ ! 609: return( shltype(p->in.left->in.op, p->in.left ) ); ! 610: } ! 611: ! 612: deltest( p ) register NODE *p; ! 613: { ! 614: /* should we delay the INCR or DECR operation p */ ! 615: # ifndef MULTILEVEL ! 616: if( p->in.op == INCR && p->in.left->in.op == REG && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){ ! 617: /* STARREG */ ! 618: return( 0 ); ! 619: } ! 620: # else ! 621: if( mlmatch(p,DEFINCDEC,INCR) && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){ ! 622: /* STARREG */ ! 623: return( 0 ); ! 624: } ! 625: #endif ! 626: p = p->in.left; ! 627: return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG ); ! 628: } ! 629: mkadrs(p) register NODE *p; ! 630: { ! 631: register o; ! 632: ! 633: o = p->in.op; ! 634: ! 635: if( asgop(o) ){ ! 636: if( !SUGT( p->in.right->in.su , p->in.left->in.su )){ ! 637: if( p->in.left->in.op == UNARY MUL ){ ! 638: if( SUTEST( p->in.left->in.su ) ) ! 639: SETSTO( p->in.left->in.left, INTEMP ); ! 640: else { ! 641: if (SUTEST( p->in.right->in.su ) ) ! 642: SETSTO( p->in.right, INTEMP ); ! 643: else ! 644: cerror( "store finds both sides trivial" ); ! 645: } ! 646: } ! 647: else if( p->in.left->in.op == FLD ! 648: && p->in.left->in.left->in.op == UNARY MUL ){ ! 649: SETSTO( p->in.left->in.left->in.left, INTEMP ); ! 650: } else { ! 651: /* should be only structure assignment */ ! 652: SETSTO( p->in.left, INTEMP ); ! 653: } ! 654: } ! 655: else SETSTO( p->in.right, INTEMP ); ! 656: } else { ! 657: if( SUGT( p->in.left->in.su , p->in.right->in.su )){ ! 658: SETSTO( p->in.left, INTEMP ); ! 659: } else { ! 660: SETSTO( p->in.right, INTEMP ); ! 661: } ! 662: } ! 663: } ! 664: ! 665: ! 666: notoff( t, r, off, cp) CONSZ off; char *cp; ! 667: { ! 668: /* is it legal to make an OREG or NAME entry which has an ! 669: /* offset of off, (from a register of r), if the ! 670: /* resulting thing had type t */ ! 671: ! 672: /* yes */ ! 673: if (use68020 && isbreg(r)) ! 674: return(0); ! 675: if ( off>=-32768 && off<=32767 ! 676: && (cp == NULL || *cp=='\0') && r>=A0 && r<=SP ) ! 677: return(0); ! 678: return(1); /* NO */ ! 679: } ! 680: ! 681: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ! 682: ! 683: #define nncon(p)\ ! 684: ((p)->in.op == ICON && ((p)->tn.name == NULL || (p)->tn.name[0] == '\0')) ! 685: ! 686: /* ! 687: * Compile an array index expression, exploiting ! 688: * scaled indexing if possible. Assume an index ! 689: * register is known to be available. ! 690: */ ! 691: do_index(p) ! 692: register NODE *p; ! 693: { ! 694: register NODE *rp,*lp; ! 695: int count; ! 696: ! 697: switch(p->in.op) { ! 698: case REG: ! 699: return; ! 700: case MUL: ! 701: /* ! 702: * at least one front-end doesn't do this... ! 703: */ ! 704: rp = p->in.right; ! 705: if (nncon(rp)) { ! 706: count = -1; ! 707: switch(rp->tn.lval) { ! 708: case 1: ! 709: count = 0; ! 710: break; ! 711: case 2: ! 712: count = 1; ! 713: break; ! 714: case 4: ! 715: count = 2; ! 716: break; ! 717: case 8: ! 718: count = 3; ! 719: break; ! 720: } ! 721: if (count >= 0) { ! 722: p->in.op = LS; ! 723: rp->tn.lval = count; ! 724: /* ! 725: * reset type, because MULS ! 726: * changes shorts to longs, but ! 727: * ASL doesn't! ! 728: */ ! 729: p->in.type = p->in.left->in.type; ! 730: goto leftshift; ! 731: } ! 732: } ! 733: break; ! 734: case LS: ! 735: leftshift: ! 736: rp = p->in.right; ! 737: lp = p->in.left; ! 738: if ( lp->in.op == SCONV && lp->in.type == INT ) { ! 739: if ( lp->in.left->in.type == CHAR ) { ! 740: /* ! 741: * we only need convert bytes to shorts. ! 742: */ ! 743: lp->in.type = SHORT; ! 744: p->in.type = SHORT; ! 745: } ! 746: else if ( use68020 && lp->in.left->in.type == SHORT ! 747: && lp->in.rall == NOPREF ) { ! 748: /* ! 749: * on the 68020, a conversion from short ! 750: * to int below a scale by 2,4, or 8 is ! 751: * subsumed into the addressing modes ! 752: */ ! 753: p->in.left = lp->in.left; ! 754: lp->in.op = FREE; ! 755: lp = p->in.left; ! 756: p->in.type = lp->in.type; ! 757: } ! 758: } /* lp->in.op == SCONV */ ! 759: if (use68020 && nncon(rp) && rp->tn.lval >= 0 ! 760: && rp->tn.lval <= 3){ ! 761: /* ! 762: * on the 68020, scaling by 2, 4, or 8 is also free ! 763: */ ! 764: if (lp->in.op != REG || p->in.rall != NOPREF) { ! 765: lp->in.rall = p->in.rall; ! 766: order(lp,INTAREG|INAREG|INTBREG|INBREG); ! 767: } ! 768: return; ! 769: } ! 770: break; ! 771: case SCONV: ! 772: if (p->in.type == INT) { ! 773: lp = p->in.left; ! 774: if (lp->in.type == CHAR) { ! 775: /* ! 776: * we only need convert bytes to shorts. ! 777: */ ! 778: p->in.type = SHORT; ! 779: } /* char */ ! 780: else if (lp->in.type == SHORT && p->in.rall == NOPREF) { ! 781: /* ! 782: * conversions from short to int ! 783: * are done by the addressing modes ! 784: */ ! 785: *p = *lp; ! 786: lp->in.op = FREE; ! 787: } /* short */ ! 788: } /* type == INT */ ! 789: break; ! 790: } /* switch */ ! 791: order(p, INTAREG|INAREG|INTBREG|INBREG); ! 792: } /* do_index */ ! 793: ! 794: /* ! 795: * is this expression a register or a ! 796: * sign-extending conversion of one? ! 797: */ ! 798: static int ! 799: regsconv(p) ! 800: NODE *p; ! 801: { ! 802: NODE *lp; ! 803: ! 804: if (p->in.op == REG) ! 805: return(1); ! 806: if (p->in.op == SCONV && p->in.type == INT) { ! 807: lp = p->in.left; ! 808: if ( (lp->in.type == SHORT || lp->in.type == CHAR) ! 809: && lp->in.op == REG ) ! 810: return(1); ! 811: } ! 812: return(0); ! 813: } ! 814: ! 815: /* ! 816: * is this already a legal index? ! 817: */ ! 818: int ! 819: isindex(p) ! 820: register NODE *p; ! 821: { ! 822: register rval; ! 823: NODE *rp; ! 824: ! 825: if (use68020) { ! 826: if (p->in.op == MUL) { ! 827: rp = p->in.right; ! 828: if (nncon(rp)) { ! 829: switch(rp->tn.lval) { ! 830: case 1: ! 831: case 2: ! 832: case 4: ! 833: case 8: ! 834: return(regsconv(p->in.left)); ! 835: } /* switch */ ! 836: } /* nncon */ ! 837: return(0); ! 838: } /* MUL */ ! 839: if (p->in.op == LS) { ! 840: rp = p->in.right; ! 841: if (nncon(rp) ! 842: && (rp->tn.lval >= 0 && rp->tn.lval <= 3)) ! 843: return(regsconv(p->in.left)); ! 844: return(0); ! 845: } /* LS */ ! 846: } /* use68020 */ ! 847: return(regsconv(p)); ! 848: } ! 849: ! 850: /* ! 851: * is p a signed byte constant ? This really asks whether p is ! 852: * permissible in a (base+disp+index) expression. On the 68020, ! 853: * anything is permissible, including relocatables. ! 854: */ ! 855: ! 856: static int ! 857: isbcon(p, t) ! 858: register NODE *p; ! 859: TWORD t; ! 860: { ! 861: int maxoff; ! 862: if (p == NIL) ! 863: return 0; ! 864: if (p->in.op == ICON) { ! 865: if (use68020) ! 866: return(1); ! 867: maxoff = ((BTYPE(t) == DOUBLE) ? 123 : 127); ! 868: if (nncon(p) && p->tn.lval <= maxoff && p->tn.lval >= -maxoff) ! 869: return(1); ! 870: } ! 871: return(0); ! 872: } ! 873: ! 874: /* ! 875: * Is p a signed short constant ? This really asks whether p ! 876: * is permissible in a (base+disp) expression. On the 68020, ! 877: * anything is permissible, including relocatables. ! 878: */ ! 879: ! 880: static int ! 881: isscon(p, t) ! 882: register NODE *p; ! 883: TWORD t; ! 884: { ! 885: int maxoff; ! 886: if (p == NIL) ! 887: return 0; ! 888: if (p->in.op == ICON) { ! 889: if (use68020) ! 890: return(1); ! 891: maxoff = ((BTYPE(t) == DOUBLE) ? 32763 : 32767); ! 892: if (nncon(p) && p->tn.lval <= maxoff && p->tn.lval >= -maxoff) ! 893: return(1); ! 894: } ! 895: return(0); ! 896: } ! 897: ! 898: #define isbregnode(p) ((p)->in.op == REG && isbreg((p)->tn.rval)) ! 899: ! 900: /* ! 901: * Is a register available for indexing? This depends ! 902: * on context larger than the immediate expression, ! 903: * represented by the 'failsafe' flag. (cf., order.c) ! 904: * Note that we should not ask this unless it we are ! 905: * fairly sure we WANT to use double indexing. ! 906: */ ! 907: static int ! 908: can_index(p, base, index) ! 909: NODE *p, *base, *index; ! 910: { ! 911: if (isindex(index)) /* already got one */ ! 912: return(1); ! 913: failsafe |= ((p->in.rall == D0) || (p->in.rall == D1)); ! 914: if (failsafe) { ! 915: /* ! 916: * We need d0, d1, or both for something; don't tie ! 917: * either one up. ! 918: */ ! 919: if (!isbregnode(base) || istreg(base->tn.rval)) { ! 920: /* ! 921: * need a scratch register for the base, too. ! 922: */ ! 923: return(0); /* forget it! */ ! 924: } ! 925: if(!rewrite_rall(index,1)) { ! 926: return(0); ! 927: } ! 928: } ! 929: return(1); ! 930: } ! 931: ! 932: /* ! 933: * Compile memory reference expressions, attempting to make the best ! 934: * use of the target machine's addressing modes. The overall plan ! 935: * is to put the expression into a canonical form, then select and ! 936: * compile a suitable subtree based on availability of registers, ! 937: * offset limitations, and support from the architecture. A goal ! 938: * is not to evaluate any more of the tree than is necessary. ! 939: * ! 940: * On entry, we assume we have been given the left branch of a UNARY MUL, ! 941: * not the UNARY MUL itself. ! 942: * ! 943: * When done, we must guarantee that the resulting tree can be turned ! 944: * into an OREG. ! 945: */ ! 946: ! 947: offstar( p ) ! 948: register NODE *p; ! 949: { ! 950: register NODE *lp, *rp; ! 951: ! 952: if ( (p->in.rall&MUSTDO) ! 953: || (p->in.op != PLUS && p->in.op != MINUS ) ) { ! 954: /* No chance to index */ ! 955: if ( p->in.op != REG || !isbreg(p->tn.rval) ) { ! 956: failsafe = 0; ! 957: order(p, INTBREG|INBREG); ! 958: } ! 959: return; ! 960: } ! 961: /* ! 962: * exp is (<exp> [+-] <exp>) ! 963: */ ! 964: lp = p->in.left; ! 965: rp = p->in.right; ! 966: if (!ISPTR(lp->in.type)) { ! 967: /* ! 968: * put the pointer on the left ! 969: */ ! 970: p->in.right = lp; ! 971: p->in.left = rp; ! 972: lp = p->in.left; ! 973: rp = p->in.right; ! 974: } ! 975: /* ! 976: * u-page hack, for the kernel boys: for example, ! 977: * (*((struct u *) 0x4000)).u_dent.d_name[i++] = *cp; ! 978: */ ! 979: if (nncon(lp) && isscon(lp) && tlen(rp) == (SZINT/SZCHAR)) { ! 980: /* ! 981: * swap base part and index part, ! 982: * then diddle the types ! 983: */ ! 984: TWORD temp; ! 985: p->in.right = lp; ! 986: p->in.left = rp; ! 987: lp = p->in.left; ! 988: rp = p->in.right; ! 989: temp = lp->in.type; ! 990: lp->in.type = rp->in.type; ! 991: rp->in.type = temp; ! 992: } ! 993: /* ! 994: * map (<exp> - <icon>) to (<exp> + <-icon>) ! 995: */ ! 996: if (p->in.op == MINUS && nncon(rp)) { ! 997: p->in.op = PLUS; ! 998: rp->tn.lval = -(rp->tn.lval); ! 999: } ! 1000: /* ! 1001: * map ( (<exp> - <icon> ) [+-] <exp> ) ! 1002: * to ( (<exp> + <-icon>) [+-] <exp> ) ! 1003: */ ! 1004: if (lp->in.op == MINUS && nncon(lp->in.right)) { ! 1005: lp->in.op = PLUS; ! 1006: lp->in.right->tn.lval = -(lp->in.right->tn.lval); ! 1007: } ! 1008: /* ! 1009: * At this point, any subtractions must be done explicitly. ! 1010: */ ! 1011: if ( p->in.op == MINUS ) { ! 1012: failsafe = 0; ! 1013: order(p, INTBREG|INBREG); ! 1014: return; ! 1015: } ! 1016: if ( lp->in.op == PLUS ) { ! 1017: ! 1018: /* ! 1019: * map (<index> + <base>) + <exp> ! 1020: * to (<base> + <index>) + <exp> ! 1021: */ ! 1022: if ( !ISPTR(lp->in.left->in.type) ) { ! 1023: NODE *q = lp->in.left; ! 1024: lp->in.left = lp->in.right; ! 1025: lp->in.right = q; ! 1026: } ! 1027: ! 1028: /* ! 1029: * map (<base> + <index>) + <bcon> ! 1030: * to (<base> + <bcon>) + <index> ! 1031: */ ! 1032: if ( isbcon(rp) && !isbcon(lp->in.right) ) { ! 1033: NODE *q = lp->in.right; ! 1034: lp->in.right = rp; ! 1035: rp = p->in.right = q; ! 1036: } ! 1037: ! 1038: /* ! 1039: * Now we evaluate the expression, or enough of it so ! 1040: * that the remainder can be handled by an addressing mode. ! 1041: */ ! 1042: if (isbcon(lp->in.right, p->in.type)) { ! 1043: /* ! 1044: * pattern is ( <base exp> + <bcon> ) + <index> ! 1045: * where <bcon> is in [-127..127] for the 68010, ! 1046: * or any integral constant on the 68020. ! 1047: */ ! 1048: NODE *llp = lp->in.left; ! 1049: if (SUTEST(llp->in.su) && SUTEST(rp->in.su)) { ! 1050: /* ! 1051: * don't bother; ! 1052: * both <base> and <index> are messy. ! 1053: */ ! 1054: goto punt; ! 1055: } ! 1056: if (SUGT(rp->in.su, llp->in.su)){ ! 1057: /* ! 1058: * Index is more expensive than base. ! 1059: * Do it first, unless you have to bend ! 1060: * over backwards to do it. ! 1061: */ ! 1062: if (can_index(p,llp,rp)) { ! 1063: do_index(rp); /* breg@(disp,index) */ ! 1064: if (!isbregnode(llp)) { ! 1065: order(llp, INTBREG|INBREG); ! 1066: } ! 1067: return; ! 1068: } ! 1069: goto punt; ! 1070: } ! 1071: /* ! 1072: * try for index ! 1073: */ ! 1074: if (can_index(p,llp,rp)) { ! 1075: /* ! 1076: * evaluate base into a <breg> ! 1077: */ ! 1078: if (!isbregnode(llp)) { ! 1079: order(llp, INTBREG|INBREG); ! 1080: } ! 1081: /* ! 1082: * evaluate <index> into a register ! 1083: */ ! 1084: do_index(rp); /* breg@(disp, index) */ ! 1085: return; ! 1086: } ! 1087: /* ! 1088: * can't index; instead, ! 1089: * rewrite as ( <base>+<index> ) + <bcon> ! 1090: */ ! 1091: punt: llp = lp->in.right; ! 1092: lp->in.right = rp; ! 1093: p->in.right = llp; ! 1094: failsafe = 0; ! 1095: order(lp, INTBREG|INBREG); /* breg@(disp) */ ! 1096: return; ! 1097: } /* (<base> + <bcon>) + <index> */ ! 1098: } /* lp == PLUS */ ! 1099: ! 1100: /* ! 1101: * At this point, the expression is of the form ! 1102: * <base part> + <index part> ! 1103: */ ! 1104: if (SUTEST(lp->in.su) && SUTEST(rp->in.su)) { ! 1105: /* ! 1106: * both <base> and <index> are messy. ! 1107: */ ! 1108: failsafe = 0; ! 1109: order(p, INTBREG|INBREG); /* breg@ */ ! 1110: return; ! 1111: } ! 1112: if ( SUGT(rp->in.su, lp->in.su) ) { ! 1113: /* ! 1114: * index is more expensive than base. ! 1115: * Do it first, unless you have to bend ! 1116: * over backwards to do it. ! 1117: */ ! 1118: if (can_index(p,lp,rp)) { ! 1119: do_index(rp); ! 1120: if (!isbregnode(lp)){ ! 1121: order(lp, INTBREG|INBREG); ! 1122: } ! 1123: return; /* base@(index)*/ ! 1124: } ! 1125: failsafe = 0; ! 1126: order(p, INTBREG|INBREG); /* base@ */ ! 1127: return; ! 1128: } ! 1129: /* ! 1130: * try to make a breg@(disp) operand ! 1131: */ ! 1132: if ( isscon(rp) ) { ! 1133: failsafe = 0; ! 1134: if (!isbregnode(lp)) { ! 1135: order(lp, INTBREG|INBREG); ! 1136: } ! 1137: return; /* breg@(disp) */ ! 1138: } ! 1139: /* ! 1140: * Do base first. ! 1141: */ ! 1142: if ( !isbregnode(lp) ) { ! 1143: order(lp, INTBREG|INBREG); ! 1144: } ! 1145: if ( istnode(lp) && tshape(rp, SCON|SNAME|SOREG|STARNM) ) { ! 1146: /* ! 1147: * pattern is <temp reg> + <mem operand> ! 1148: * indexing doesn't buy us anything. ! 1149: */ ! 1150: failsafe = 0; ! 1151: order(p, INTBREG|INBREG); /* base@ */ ! 1152: return; ! 1153: } ! 1154: if ( can_index(p,lp,rp) ) { ! 1155: do_index(rp); /* base@(index) */ ! 1156: return; ! 1157: } ! 1158: /* ! 1159: * "Either this man is dead, or my watch has stopped." ! 1160: */ ! 1161: failsafe = 0; ! 1162: order(p, INTBREG|INBREG); /* base@ */ ! 1163: } ! 1164: ! 1165: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ! 1166: ! 1167: int crslab = 2000000; /* 68k */ ! 1168: ! 1169: getlab() ! 1170: { ! 1171: return( crslab++ ); ! 1172: } ! 1173: ! 1174: deflab( l ) ! 1175: { ! 1176: print_label(l); ! 1177: } ! 1178: ! 1179: #define mkmask(reg,mask) (busy[reg] ? ((mask) | (1<<(reg))) : (mask)) ! 1180: ! 1181: genargs( p ) register NODE *p; ! 1182: { ! 1183: register NODE *pasg; ! 1184: register inc; ! 1185: register align; ! 1186: register size; ! 1187: register TWORD type; ! 1188: int padflag; ! 1189: ! 1190: /* generate code for the arguments */ ! 1191: ! 1192: /* first, do the arguments on the right */ ! 1193: while( p->in.op == CM ){ ! 1194: genargs( p->in.right ); ! 1195: p->in.op = FREE; ! 1196: p = p->in.left; ! 1197: } ! 1198: ! 1199: if( p->in.op == STARG ){ /* structure valued argument */ ! 1200: /* ! 1201: * We are stacking arguments in anticipation of a ! 1202: * call. ! 1203: * The strategy will be to push words on the ! 1204: * stack (being careful of alignment problems) ! 1205: * in open code. A dbra loop is too hard here. ! 1206: */ ! 1207: size = p->stn.stsize; ! 1208: if( p->in.left->in.op == ICON ){ ! 1209: p->in.op = FREE; ! 1210: p= p->in.left; ! 1211: p->in.op = NAME; ! 1212: } ! 1213: else { ! 1214: /* make it look beautiful... */ ! 1215: p->in.op = UNARY MUL; ! 1216: canon( p ); /* turn it into an oreg */ ! 1217: if( p->in.op != OREG ){ ! 1218: offstar( p->in.left ); ! 1219: canon( p ); ! 1220: if( p->in.op != OREG ){ ! 1221: offstar( p->in.left ); ! 1222: canon( p ); ! 1223: if( p->in.op != OREG ) cerror( "stuck starg" ); ! 1224: } ! 1225: } ! 1226: } ! 1227: ! 1228: if (size > 16) { ! 1229: /* ! 1230: * big structure argument. In its infinite wisdom, ! 1231: * Pascal passes array value parameters like this. ! 1232: * Twenty-two on the vomit meter. ! 1233: */ ! 1234: int count; ! 1235: int residue; ! 1236: short regmask; ! 1237: int savetemp; ! 1238: ! 1239: if (size&1) size++; /* assumes ALSTACK = 16 */ ! 1240: toff += size; ! 1241: if (toff > maxtoff) maxtoff = toff; ! 1242: count = size / sizeof(long); ! 1243: residue = size % sizeof(long); ! 1244: /* ! 1245: * a0 = &(actual argument); ! 1246: */ ! 1247: if (p->in.op == OREG && !R2TEST(p->tn.rval) ! 1248: && (p->tn.name == NULL || p->tn.name[0] == '\0') ! 1249: && p->tn.lval == 0) { ! 1250: p->in.op = REG; ! 1251: } ! 1252: if (p->in.op == REG) { ! 1253: if (p->tn.rval != A0) ! 1254: expand(p, RNOP, " movl AR,a0\n"); ! 1255: } else { ! 1256: expand(p, RNOP, " lea AR,a0\n"); ! 1257: } ! 1258: /* ! 1259: * allocate and copy to top of stack ! 1260: */ ! 1261: if (size > 0x7fff) { ! 1262: printf(" subl #%d,sp\n", size); ! 1263: } else { ! 1264: printf(" lea sp@(-%d),sp\n", size); ! 1265: } ! 1266: print_str(" movl sp,a1\n"); ! 1267: if (count > 0x7fff) { ! 1268: printf(" movl #%d,d0\n", count-1); ! 1269: print_str("1: movl a0@+,a1@+\n"); ! 1270: print_str(" dbra d0,1b\n"); ! 1271: print_str(" clrw d0\n"); ! 1272: print_str(" subql #1,d0\n"); ! 1273: print_str(" jcc 1b\n"); ! 1274: } else { ! 1275: printf(" movw #%d,d0\n", count-1); ! 1276: print_str("1: movl a0@+,a1@+\n"); ! 1277: print_str(" dbra d0,1b\n"); ! 1278: } ! 1279: switch(residue) { ! 1280: case 1: ! 1281: print_str(" movb a0@+,a1@+\n"); ! 1282: break; ! 1283: case 2: ! 1284: print_str(" movw a0@+,a1@+\n"); ! 1285: break; ! 1286: case 3: ! 1287: print_str(" movw a0@+,a1@+\n"); ! 1288: print_str(" movb a0@+,a1@+\n"); ! 1289: break; ! 1290: default: ! 1291: break; ! 1292: } ! 1293: reclaim(p,RNULL,0); ! 1294: return; ! 1295: } /* big structure */ ! 1296: ! 1297: p->tn.lval += size; ! 1298: /* ! 1299: * arguments must be at least sizeof(int) big around here. ! 1300: * force size up to it. ! 1301: */ ! 1302: padflag = (size <= 2 ) ; ! 1303: #ifdef FORT ! 1304: /* PASCAL ONLY */ ! 1305: if (size & 1){ ! 1306: /* ! 1307: * size is odd: last byte is peculiar. ! 1308: * movb to stack is magic. ! 1309: */ ! 1310: size -= 1; ! 1311: p->tn.lval -=1; ! 1312: expand( p, RNOP,"\tmovb\tAR,sp@-\n" ); ! 1313: toff += 2; ! 1314: if (toff > maxtoff) maxtoff = toff; ! 1315: } ! 1316: #endif FORT ! 1317: toff += size; ! 1318: if (toff > maxtoff) maxtoff = toff; ! 1319: for( ; size>0; size -= inc ){ ! 1320: inc = (size>2) ? 4 : 2; ! 1321: p->tn.lval -= inc; ! 1322: expand( p, RNOP,(inc==4)?"\tmovl\tAR,sp@-\n":"\tmovw\tAR,sp@-\n" ); ! 1323: } ! 1324: if (padflag){ ! 1325: print_str(" subql #2,sp\n"); ! 1326: toff += 2; ! 1327: if (toff > maxtoff) maxtoff = toff; ! 1328: } ! 1329: reclaim(p,RNULL,0); ! 1330: return; ! 1331: } ! 1332: ! 1333: /* ordinary case */ ! 1334: order( p, FORARG ); ! 1335: } ! 1336: ! 1337: argsize( p ) register NODE *p; ! 1338: { ! 1339: register t, s; ! 1340: t = 0; ! 1341: if( p->in.op == CM ){ ! 1342: t = argsize( p->in.left ); ! 1343: p = p->in.right; ! 1344: } ! 1345: switch (p->in.type){ ! 1346: case FLOAT: ! 1347: #ifdef FLOATMATH ! 1348: if (FLOATMATH>1){ ! 1349: SETOFF( t, ALFLOAT/SZCHAR ); ! 1350: return( t+(SZFLOAT/SZCHAR) ); ! 1351: } ! 1352: #endif FLOATMATH ! 1353: /* else fall through */ ! 1354: case DOUBLE: ! 1355: SETOFF( t, ALDOUBLE/SZCHAR ); ! 1356: return( t+(SZDOUBLE/SZCHAR) ); ! 1357: } ! 1358: if( p->in.op == STARG ){ ! 1359: SETOFF( t, ALSTRUCT/SZCHAR ); /* alignment */ ! 1360: s = p->stn.stsize; /* size */ ! 1361: s += (s & 1); /* PASCAL ONLY */ ! 1362: if (s < SZINT/SZCHAR) ! 1363: s = SZINT/SZCHAR; ! 1364: return( s+t ); ! 1365: } else { ! 1366: SETOFF( t, ALSTACK/SZCHAR ); ! 1367: return( t+(SZINT/SZCHAR) ); ! 1368: } ! 1369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.