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