1: # include "mfile2" 2: 3: int fltused = 0; 4: 5: stoasg( p, o ) register NODE *p; { 6: /* should the assignment op p be stored, 7: given that it lies as the right operand of o 8: (or the left, if o==UNARY MUL) */ 9: return( shltype(p->left->op, p->left ) ); 10: 11: } 12: 13: deltest( p ) register NODE *p; { 14: /* should we delay the INCR or DECR operation p */ 15: if( p->op == INCR && p->left->op == REG && spsz( p->left->type, p->right->lval ) ){ 16: /* STARREG */ 17: return( 0 ); 18: } 19: 20: p = p->left; 21: if( p->op == UNARY MUL ) p = p->left; 22: return( p->op == NAME || p->op == OREG || p->op == REG ); 23: } 24: 25: mkadrs(p) register NODE *p; { 26: register o; 27: 28: o = p->op; 29: 30: if( asgop(o) ){ 31: if( p->left->su >= p->right->su ){ 32: if( p->left->op == UNARY MUL ){ 33: if( p->left->su > 0 ) 34: SETSTO( p->left->left, INTEMP ); 35: else { 36: if( p->right->su > 0 ) SETSTO( p->right, INTEMP ); 37: else cerror( "store finds both sides trivial" ); 38: } 39: } 40: else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ 41: SETSTO( p->left->left->left, INTEMP ); 42: } 43: else { /* should be only structure assignment */ 44: SETSTO( p->left, INTEMP ); 45: } 46: } 47: else SETSTO( p->right, INTEMP ); 48: } 49: else { 50: if( p->left->su > p->right->su ){ 51: SETSTO( p->left, INTEMP ); 52: } 53: else { 54: SETSTO( p->right, INTEMP ); 55: } 56: } 57: } 58: 59: notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; { 60: /* is it legal to make an OREG or NAME entry which has an 61: /* offset of off, (from a register of r), if the 62: /* resulting thing had type t */ 63: 64: /* return( 1 ); /* NO */ 65: return(0); /* YES */ 66: } 67: 68: # define max(x,y) ((x)<(y)?(y):(x)) 69: # define min(x,y) ((x)<(y)?(x):(y)) 70: 71: 72: # define ZCHAR 01 73: # define ZLONG 02 74: # define ZFLOAT 04 75: 76: zum( p, zap ) register NODE *p; { 77: /* zap Sethi-Ullman number for chars, longs, floats */ 78: /* in the case of longs, only STARNM's are zapped */ 79: /* ZCHAR, ZLONG, ZFLOAT are used to select the zapping */ 80: 81: register su; 82: 83: su = p->su; 84: 85: switch( p->type ){ 86: 87: case CHAR: 88: case UCHAR: 89: if( !(zap&ZCHAR) ) break; 90: if( su == 0 ) p->su = su = 1; 91: break; 92: 93: case LONG: 94: case ULONG: 95: if( !(zap&ZLONG) ) break; 96: if( p->op == UNARY MUL && su == 0 ) p->su = su = 2; 97: break; 98: 99: case FLOAT: 100: if( !(zap&ZFLOAT) ) break; 101: if( su == 0 ) p->su = su = 1; 102: 103: } 104: 105: return( su ); 106: } 107: 108: sucomp( p ) register NODE *p; { 109: 110: /* set the su field in the node to the sethi-ullman 111: number, or local equivalent */ 112: 113: register o, ty, sul, sur; 114: register nr; 115: 116: ty = optype( o=p->op); 117: nr = szty( p->type ); 118: p->su = 0; 119: 120: if( ty == LTYPE ) { 121: if( p->type==FLOAT ) p->su = 1; 122: return; 123: } 124: else if( ty == UTYPE ){ 125: switch( o ) { 126: case UNARY CALL: 127: case UNARY STCALL: 128: p->su = fregs; /* all regs needed */ 129: return; 130: 131: case UNARY MUL: 132: if( shumul( p->left ) ) return; 133: 134: default: 135: p->su = max( p->left->su, nr); 136: return; 137: } 138: } 139: 140: 141: /* If rhs needs n, lhs needs m, regular su computation */ 142: 143: sul = p->left->su; 144: sur = p->right->su; 145: 146: if( o == ASSIGN ){ 147: asop: /* also used for +=, etc., to memory */ 148: if( sul==0 ){ 149: /* don't need to worry about the left side */ 150: p->su = max( sur, nr ); 151: } 152: else { 153: /* right, left address, op */ 154: if( sur == 0 ){ 155: /* just get the lhs address into a register, and mov */ 156: /* the `nr' covers the case where value is in reg afterwards */ 157: p->su = max( sul, nr ); 158: } 159: else { 160: /* right, left address, op */ 161: p->su = max( sur, nr+sul ); 162: } 163: } 164: return; 165: } 166: 167: if( o == CALL || o == STCALL ){ 168: /* in effect, takes all free registers */ 169: p->su = fregs; 170: return; 171: } 172: 173: if( o == STASG ){ 174: /* right, then left */ 175: p->su = max( max( sul+nr, sur), fregs ); 176: return; 177: } 178: 179: if( logop(o) ){ 180: /* do the harder side, then the easier side, into registers */ 181: /* left then right, max(sul,sur+nr) */ 182: /* right then left, max(sur,sul+nr) */ 183: /* to hold both sides in regs: nr+nr */ 184: nr = szty( p->left->type ); 185: sul = zum( p->left, ZLONG|ZCHAR|ZFLOAT ); 186: sur = zum( p->right, ZLONG|ZCHAR|ZFLOAT ); 187: p->su = min( max(sul,sur+nr), max(sur,sul+nr) ); 188: return; 189: } 190: 191: if( asgop(o) ){ 192: /* computed by doing right, doing left address, doing left, op, and store */ 193: switch( o ) { 194: case INCR: 195: case DECR: 196: /* do as binary op */ 197: break; 198: 199: case ASG DIV: 200: case ASG MOD: 201: case ASG MUL: 202: if( p->type!=FLOAT && p->type!=DOUBLE ) nr = fregs; 203: goto gencase; 204: 205: case ASG PLUS: 206: case ASG MINUS: 207: case ASG AND: /* really bic */ 208: case ASG OR: 209: if( p->type == INT || p->type == UNSIGNED || ISPTR(p->type) ) goto asop; 210: 211: gencase: 212: default: 213: sur = zum( p->right, ZCHAR|ZLONG|ZFLOAT ); 214: if( sur == 0 ){ /* easy case: if addressable, 215: do left value, op, store */ 216: if( sul == 0 ) p->su = nr; 217: /* harder: left adr, val, op, store */ 218: else p->su = max( sul, nr+1 ); 219: } 220: else { /* do right, left adr, left value, op, store */ 221: if( sul == 0 ){ /* right, left value, op, store */ 222: p->su = max( sur, nr+nr ); 223: } 224: else { 225: p->su = max( sur, max( sul+nr, 1+nr+nr ) ); 226: } 227: } 228: return; 229: } 230: } 231: 232: switch( o ){ 233: case ANDAND: 234: case OROR: 235: case QUEST: 236: case COLON: 237: case COMOP: 238: p->su = max( max(sul,sur), nr); 239: return; 240: } 241: 242: if( ( o==DIV || o==MOD || o==MUL ) 243: && p->type!=FLOAT && p->type!=DOUBLE ) nr = fregs; 244: if( o==PLUS || o==MUL || o==OR || o==ER ){ 245: /* AND is ruined by the hardware */ 246: /* permute: get the harder on the left */ 247: 248: register rt, lt; 249: 250: if( istnode( p->left ) || sul > sur ) goto noswap; /* don't do it! */ 251: 252: /* look for a funny type on the left, one on the right */ 253: 254: 255: lt = p->left->type; 256: rt = p->right->type; 257: 258: if( rt == FLOAT && lt == DOUBLE ) goto swap; 259: 260: if( (rt==CHAR||rt==UCHAR) && (lt==INT||lt==UNSIGNED||ISPTR(lt)) ) goto swap; 261: 262: if( lt==LONG || lt==ULONG ){ 263: if( rt==LONG || rt==ULONG ){ 264: /* if one is a STARNM, swap */ 265: if( p->left->op == UNARY MUL && sul==0 ) goto noswap; 266: if( p->right->op == UNARY MUL && p->left->op != UNARY MUL ) goto swap; 267: goto noswap; 268: } 269: else if( p->left->op == UNARY MUL && sul == 0 ) goto noswap; 270: else goto swap; /* put long on right, unless STARNM */ 271: } 272: 273: /* we are finished with the type stuff now; if one is addressable, 274: put it on the right */ 275: if( sul == 0 && sur != 0 ){ 276: 277: NODE *s; 278: int ssu; 279: 280: swap: 281: ssu = sul; sul = sur; sur = ssu; 282: s = p->left; p->left = p->right; p->right = s; 283: } 284: } 285: noswap: 286: 287: sur = zum( p->right, ZCHAR|ZLONG|ZFLOAT ); 288: if( sur == 0 ){ 289: /* get left value into a register, do op */ 290: p->su = max( nr, sul ); 291: } 292: else { 293: /* do harder into a register, then easier */ 294: p->su = max( nr+nr, min( max( sul, nr+sur ), max( sur, nr+sul ) ) ); 295: } 296: } 297: 298: int radebug = 0; 299: 300: mkrall( p, r ) register NODE *p; { 301: /* insure that the use of p gets done with register r; in effect, */ 302: /* simulate offstar */ 303: 304: if( p->op == FLD ){ 305: p->left->rall = p->rall; 306: p = p->left; 307: } 308: 309: if( p->op != UNARY MUL ) return; /* no more to do */ 310: p = p->left; 311: if( p->op == UNARY MUL ){ 312: p->rall = r; 313: p = p->left; 314: } 315: if( p->op == PLUS && p->right->op == ICON ){ 316: p->rall = r; 317: p = p->left; 318: } 319: rallo( p, r ); 320: } 321: 322: rallo( p, down ) register NODE *p; { 323: /* do register allocation */ 324: register o, type, down1, down2, ty; 325: 326: if( radebug ) printf( "rallo( %o, %o )\n", p, down ); 327: 328: down2 = NOPREF; 329: p->rall = down; 330: down1 = ( down &= ~MUSTDO ); 331: 332: ty = optype( o = p->op ); 333: type = p->type; 334: 335: 336: if( type == DOUBLE || type == FLOAT ){ 337: if( o == FORCE ) down1 = FR0|MUSTDO; 338: ++fltused; 339: } 340: else switch( o ) { 341: case ASSIGN: 342: down1 = NOPREF; 343: down2 = down; 344: break; 345: 346: case ASG MUL: 347: case ASG DIV: 348: case ASG MOD: 349: /* keep the addresses out of the hair of (r0,r1) */ 350: if(fregs == 2 ){ 351: /* lhs in (r0,r1), nothing else matters */ 352: down1 = R1|MUSTDO; 353: down2 = NOPREF; 354: break; 355: } 356: /* at least 3 regs free */ 357: /* compute lhs in (r0,r1), address of left in r2 */ 358: p->left->rall = R1|MUSTDO; 359: mkrall( p->left, R2|MUSTDO ); 360: /* now, deal with right */ 361: if( fregs == 3 ) rallo( p->right, NOPREF ); 362: else { 363: /* put address of long or value here */ 364: p->right->rall = R3|MUSTDO; 365: mkrall( p->right, R3|MUSTDO ); 366: } 367: return; 368: 369: case MUL: 370: case DIV: 371: case MOD: 372: rallo( p->left, R1|MUSTDO ); 373: 374: if( fregs == 2 ){ 375: rallo( p->right, NOPREF ); 376: return; 377: } 378: /* compute addresses, stay away from (r0,r1) */ 379: 380: p->right->rall = (fregs==3) ? R2|MUSTDO : R3|MUSTDO ; 381: mkrall( p->right, R2|MUSTDO ); 382: return; 383: 384: case CALL: 385: case STASG: 386: case EQ: 387: case NE: 388: case GT: 389: case GE: 390: case LT: 391: case LE: 392: case NOT: 393: case ANDAND: 394: case OROR: 395: down1 = NOPREF; 396: break; 397: 398: case FORCE: 399: down1 = R0|MUSTDO; 400: break; 401: 402: } 403: 404: if( ty != LTYPE ) rallo( p->left, down1 ); 405: if( ty == BITYPE ) rallo( p->right, down2 ); 406: 407: } 408: 409: offstar( p ) register NODE *p; { 410: /* handle indirections */ 411: 412: if( p->op == UNARY MUL ) p = p->left; 413: 414: if( p->op == PLUS || p->op == MINUS ){ 415: if( p->right->op == ICON ){ 416: order( p->left , INTAREG|INAREG ); 417: return; 418: } 419: } 420: order( p, INTAREG|INAREG ); 421: } 422: 423: setincr( p ) NODE *p; { 424: return( 0 ); /* for the moment, don't bother */ 425: } 426: 427: niceuty( p ) register NODE *p; { 428: register TWORD t; 429: 430: return( p->op == UNARY MUL && (t=p->type)!=CHAR && 431: t!= UCHAR && t!= FLOAT && 432: shumul( p->left) != STARREG ); 433: } 434: setbin( p ) register NODE *p; { 435: register NODE *r, *l; 436: 437: r = p->right; 438: l = p->left; 439: 440: if( p->right->su == 0 ){ /* rhs is addressable */ 441: if( logop( p->op ) ){ 442: if( l->op == UNARY MUL && l->type != FLOAT && shumul( l->left ) != STARREG ) offstar( l->left ); 443: else order( l, INAREG|INTAREG|INBREG|INTBREG|INTEMP ); 444: return( 1 ); 445: } 446: if( !istnode( l ) ){ 447: order( l, INTAREG|INTBREG ); 448: return( 1 ); 449: } 450: /* rewrite */ 451: return( 0 ); 452: } 453: /* now, rhs is complicated: must do both sides into registers */ 454: /* do the harder side first */ 455: 456: if( logop( p->op ) ){ 457: /* relational: do both sides into regs if need be */ 458: 459: if( r->su > l->su ){ 460: if( niceuty(r) ){ 461: offstar( r->left ); 462: return( 1 ); 463: } 464: else if( !istnode( r ) ){ 465: order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); 466: return( 1 ); 467: } 468: } 469: if( niceuty(l) ){ 470: offstar( l->left ); 471: return( 1 ); 472: } 473: else if( niceuty(r) ){ 474: offstar( r->left ); 475: return( 1 ); 476: } 477: else if( !istnode( l ) ){ 478: order( l, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); 479: return( 1 ); 480: } 481: if( !istnode( r ) ){ 482: order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); 483: return( 1 ); 484: } 485: cerror( "setbin can't deal with %s", opst[p->op] ); 486: } 487: 488: /* ordinary operator */ 489: 490: if( !istnode(r) && r->su > l->su ){ 491: /* if there is a chance of making it addressable, try it... */ 492: if( niceuty(r) ){ 493: offstar( r->left ); 494: return( 1 ); /* hopefully, it is addressable by now */ 495: } 496: order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); /* anything goes on rhs */ 497: return( 1 ); 498: } 499: else { 500: if( !istnode( l ) ){ 501: order( l, INTAREG|INTBREG ); 502: return( 1 ); 503: } 504: /* rewrite */ 505: return( 0 ); 506: } 507: } 508: 509: setstr( p ) register NODE *p; { /* structure assignment */ 510: if( p->right->op != REG ){ 511: order( p->right, INTAREG ); 512: return(1); 513: } 514: p = p->left; 515: if( p->op != NAME && p->op != OREG ){ 516: if( p->op != UNARY MUL ) cerror( "bad setstr" ); 517: order( p->left, INTAREG ); 518: return( 1 ); 519: } 520: return( 0 ); 521: } 522: 523: setasg( p ) register NODE *p; { 524: /* setup for assignment operator */ 525: 526: if( p->right->su != 0 && p->right->op != REG ) { 527: if( p->right->op == UNARY MUL ) 528: offstar( p->right->left ); 529: else 530: order( p->right, INAREG|INBREG|SOREG|SNAME|SCON ); 531: return(1); 532: } 533: if( p->right->op != REG && ( p->type == FLOAT || p->type == DOUBLE ) ) { 534: order( p->right, INBREG ); 535: return(1); 536: } 537: if( p->left->op == UNARY MUL && !tshape( p->left, STARREG|STARNM ) ){ 538: offstar( p->left->left ); 539: return(1); 540: } 541: if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ 542: offstar( p->left->left->left ); 543: return(1); 544: } 545: /* if things are really strange, get rhs into a register */ 546: if( p->right->op != REG ){ 547: order( p->right, INAREG|INBREG ); 548: return( 1 ); 549: } 550: return(0); 551: } 552: 553: setasop( p ) register NODE *p; { 554: /* setup for =ops */ 555: register sul, sur; 556: register NODE *q, *p2; 557: 558: sul = p->left->su; 559: sur = p->right->su; 560: 561: switch( p->op ){ 562: 563: case ASG PLUS: 564: case ASG OR: 565: case ASG MINUS: 566: if( p->type != INT && p->type != UNSIGNED && !ISPTR(p->type) ) break; 567: if( p->right->type == CHAR || p->right->type == UCHAR ){ 568: order( p->right, INAREG ); 569: return( 1 ); 570: } 571: break; 572: 573: case ASG ER: 574: if( sul == 0 || p->left->op == REG ){ 575: if( p->left->type == CHAR || p->left->type == UCHAR ) goto rew; /* rewrite */ 576: order( p->right, INAREG|INBREG ); 577: return( 1 ); 578: } 579: goto leftadr; 580: } 581: 582: if( sur == 0 ){ 583: 584: leftadr: 585: /* easy case: if addressable, do left value, op, store */ 586: if( sul == 0 ) goto rew; /* rewrite */ 587: 588: /* harder; make aleft address, val, op, and store */ 589: 590: if( p->left->op == UNARY MUL ){ 591: offstar( p->left->left ); 592: return( 1 ); 593: } 594: if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ 595: offstar( p->left->left->left ); 596: return( 1 ); 597: } 598: rew: /* rewrite, accounting for autoincrement and autodecrement */ 599: 600: q = p->left; 601: if( q->op == FLD ) q = q->left; 602: if( q->op != UNARY MUL || shumul(q->left) != STARREG ) return(0); /* let reader.c do it */ 603: 604: /* mimic code from reader.c */ 605: 606: p2 = tcopy( p ); 607: p->op = ASSIGN; 608: reclaim( p->right, RNULL, 0 ); 609: p->right = p2; 610: 611: /* now, zap INCR on right, ASG MINUS on left */ 612: 613: if( q->left->op == INCR ){ 614: q = p2->left; 615: if( q->op == FLD ) q = q->left; 616: if( q->left->op != INCR ) cerror( "bad incr rewrite" ); 617: } 618: else if( q->left->op != ASG MINUS ) cerror( " bad -= rewrite" ); 619: 620: q->left->right->op = FREE; 621: q->left->op = FREE; 622: q->left = q->left->left; 623: 624: /* now, resume reader.c rewriting code */ 625: 626: canon(p); 627: rallo( p, p->rall ); 628: order( p2->left, INTBREG|INTAREG ); 629: order( p2, INTBREG|INTAREG ); 630: return( 1 ); 631: } 632: 633: /* harder case: do right, left address, left value, op, store */ 634: 635: if( p->right->op == UNARY MUL ){ 636: offstar( p->right->left ); 637: return( 1 ); 638: } 639: /* sur> 0, since otherwise, done above */ 640: if( p->right->op == REG ) goto leftadr; /* make lhs addressable */ 641: order( p->right, INAREG|INBREG ); 642: return( 1 ); 643: } 644: 645: int crslab = 10000; 646: 647: getlab(){ 648: return( crslab++ ); 649: } 650: 651: deflab( l ){ 652: printf( "L%d:\n", l ); 653: } 654: 655: genargs( p) register NODE *p; { 656: register size; 657: 658: /* generate code for the arguments */ 659: 660: /* first, do the arguments on the right (last->first) */ 661: while( p->op == CM ){ 662: genargs( p->right ); 663: p->op = FREE; 664: p = p->left; 665: } 666: 667: if( p->op == STARG ){ /* structure valued argument */ 668: 669: size = p->stsize; 670: if( p->left->op == ICON ){ 671: /* make into a name node */ 672: p->op = FREE; 673: p= p->left; 674: p->op = NAME; 675: } 676: else { 677: /* make it look beautiful... */ 678: p->op = UNARY MUL; 679: canon( p ); /* turn it into an oreg */ 680: if( p->op != OREG ){ 681: offstar( p->left ); 682: canon( p ); 683: if( p->op != OREG ) cerror( "stuck starg" ); 684: } 685: } 686: 687: p->lval += size; /* end of structure */ 688: /* put on stack backwards */ 689: for( ; size>0; size -= 2 ){ 690: p->lval -= 2; 691: expand( p, RNOP, " mov AR,Z-\n" ); 692: } 693: reclaim( p, RNULL, 0 ); 694: return; 695: } 696: 697: /* ordinary case */ 698: 699: order( p, FORARG ); 700: } 701: 702: argsize( p ) register NODE *p; { 703: register t; 704: t = 0; 705: if( p->op == CM ){ 706: t = argsize( p->left ); 707: p = p->right; 708: } 709: if( p->type == DOUBLE || p->type == FLOAT ){ 710: SETOFF( t, 2 ); 711: return( t+8 ); 712: } 713: else if( p->type == LONG || p->type == ULONG ) { 714: SETOFF( t, 2); 715: return( t+4 ); 716: } 717: else if( p->op == STARG ){ 718: SETOFF( t, p->stalign ); /* alignment */ 719: return( t + p->stsize ); /* size */ 720: } 721: else { 722: SETOFF( t, 2 ); 723: return( t+2 ); 724: } 725: }